static struct snobj *handle_add_worker(struct snobj *q) { unsigned int wid; unsigned int core; struct snobj *t; t = snobj_eval(q, "wid"); if (!t) return snobj_err(EINVAL, "Missing 'wid' field"); wid = snobj_uint_get(t); if (wid >= MAX_WORKERS) return snobj_err(EINVAL, "'wid' must be between 0 and %d", MAX_WORKERS - 1); t = snobj_eval(q, "core"); if (!t) return snobj_err(EINVAL, "Missing 'core' field"); core = snobj_uint_get(t); if (!is_cpu_present(core)) return snobj_err(EINVAL, "Invalid core %d", core); if (is_worker_active(wid)) return snobj_err(EEXIST, "worker:%d is already active", wid); launch_worker(wid, core); return NULL; }
static struct snobj *queue_out_init(struct module *m, struct snobj *arg) { struct queue_out_priv *priv = get_priv(m); struct snobj *t; const char *port_name; int ret; if (!arg || snobj_type(arg) != TYPE_MAP) return snobj_err(EINVAL, "Argument must be a map"); t = snobj_eval(arg, "port"); if (!t || !(port_name = snobj_str_get(t))) return snobj_err(EINVAL, "Field 'port' must be specified"); t = snobj_eval(arg, "qid"); if (!t || snobj_type(t) != TYPE_INT) return snobj_err(EINVAL, "Field 'qid' must be specified"); priv->qid = snobj_uint_get(t); priv->port = find_port(port_name); if (!priv->port) return snobj_err(ENODEV, "Port %s not found", port_name); ret = acquire_queues(priv->port, m, PACKET_DIR_OUT, &priv->qid, 1); if (ret < 0) return snobj_errno(-ret); priv->send_pkts = priv->port->driver->send_pkts; return NULL; }
static struct snobj *handle_create_module(struct snobj *arg) { const char *mclass_name; const struct mclass *mclass; struct module *module; struct snobj *r; mclass_name = snobj_eval_str(arg, "mclass"); if (!mclass_name) return snobj_err(EINVAL, "Missing 'mclass' field in arg"); mclass = find_mclass(mclass_name); if (!mclass) return snobj_err(ENOENT, "No mclass '%s' found", mclass_name); module = create_module(snobj_eval_str(arg, "name"), mclass, snobj_eval(arg, "arg"), &r); if (!module) return r; printf("Module %s created at %p\n", module->name, module); r = snobj_map(); snobj_map_set(r, "name", snobj_str(module->name)); return r; }
static struct snobj *handle_create_port(struct snobj *arg) { const char *driver_name; const struct driver *driver; struct port *port; struct snobj *r; struct snobj *err; driver_name = snobj_eval_str(arg, "driver"); if (!driver_name) return snobj_err(EINVAL, "Missing 'driver' field in arg"); driver = find_driver(driver_name); if (!driver) return snobj_err(ENOENT, "No port driver '%s' found", driver_name); port = create_port(snobj_eval_str(arg, "name"), driver, snobj_eval(arg, "arg"), &err); if (!port) return err; printf("Port %s created at %p\n", port->name, port); r = snobj_map(); snobj_map_set(r, "name", snobj_str(port->name)); return r; }
static struct snobj *handle_snobj_module(struct snobj *q) { const char *m_name; const char *cmd; struct module *m; m_name = snobj_eval_str(q, "name"); if (!m_name) return snobj_err(EINVAL, "Missing module name field 'name'"); if ((m = find_module(m_name)) == NULL) return snobj_err(ENOENT, "No module '%s' found", m_name); cmd = snobj_eval_str(q, "cmd"); if (strcmp(cmd, "query") == 0) { struct snobj *arg; if (!m->mclass->query) return snobj_err(ENOTSUP, "Module '%s' does not support queries", m_name); arg = snobj_eval(q, "arg"); if (!arg) { struct snobj *ret; arg = snobj_nil(); ret = m->mclass->query(m, arg); snobj_free(arg); return ret; } return m->mclass->query(m, arg); } else return snobj_err(ENOTSUP, "Not supported command '%s'", cmd); }
static struct snobj *init_port(struct port *p, struct snobj *conf) { struct vport_priv *priv = get_port_priv(p); int container_pid = 0; int cpu; int rxq; int ret; if (strlen(p->name) >= IFNAMSIZ) return snobj_err(EINVAL, "Linux interface name should be " \ "shorter than %d characters", IFNAMSIZ); if (snobj_eval_exists(conf, "docker")) { struct snobj *err = docker_container_pid( snobj_eval_str(conf, "docker"), &container_pid); if (err) return err; } priv->fd = open("/dev/softnic", O_RDONLY); if (priv->fd == -1) return snobj_err(ENODEV, "the kernel module is not loaded"); priv->bar = alloc_bar(p, container_pid); ret = ioctl(priv->fd, SN_IOC_CREATE_HOSTNIC, rte_malloc_virt2phy(priv->bar)); if (ret < 0) { close(priv->fd); return snobj_errno_details(-ret, snobj_str("SN_IOC_CREATE_HOSTNIC failure")); } if (snobj_eval_exists(conf, "ip_addr")) { struct snobj *err = set_ip_addr(p, container_pid, snobj_eval(conf, "ip_addr")); if (err) { deinit_port(p); return err; } } for (cpu = 0; cpu < SN_MAX_CPU; cpu++) priv->map.cpu_to_txq[cpu] = cpu % p->num_queues[PACKET_DIR_INC]; cpu = 0; for (rxq = 0; rxq < p->num_queues[PACKET_DIR_OUT]; rxq++) { while (is_worker_core(cpu)) cpu = (cpu + 1) % sysconf(_SC_NPROCESSORS_ONLN); priv->map.rxq_to_cpu[rxq] = cpu; cpu = (cpu + 1) % sysconf(_SC_NPROCESSORS_ONLN); } ret = ioctl(priv->fd, SN_IOC_SET_QUEUE_MAPPING, &priv->map); if (ret < 0) perror("SN_IOC_SET_QUEUE_MAPPING"); return NULL; }
static struct snobj *handle_list_tcs(struct snobj *q) { struct snobj *r; struct snobj *t; unsigned int wid_filter = MAX_WORKERS; struct ns_iter iter; struct tc *c; t = snobj_eval(q, "wid"); if (t) { wid_filter = snobj_uint_get(t); if (wid_filter >= MAX_WORKERS) return snobj_err(EINVAL, "'wid' must be between 0 and %d", MAX_WORKERS - 1); if (!is_worker_active(wid_filter)) return snobj_err(EINVAL, "worker:%d does not exist", wid_filter); } r = snobj_list(); ns_init_iterator(&iter, NS_TYPE_TC); while ((c = (struct tc *)ns_next(&iter)) != NULL) { int wid; if (wid_filter < MAX_WORKERS) { if (workers[wid_filter]->s != c->s) continue; wid = wid_filter; } else { for (wid = 0; wid < MAX_WORKERS; wid++) if (is_worker_active(wid) && workers[wid]->s == c->s) break; } struct snobj *elem = snobj_map(); snobj_map_set(elem, "name", snobj_str(c->name)); snobj_map_set(elem, "tasks", snobj_int(c->num_tasks)); snobj_map_set(elem, "parent", snobj_str(c->parent->name)); snobj_map_set(elem, "priority", snobj_int(c->priority)); if (wid < MAX_WORKERS) snobj_map_set(elem, "wid", snobj_uint(wid)); else snobj_map_set(elem, "wid", snobj_int(-1)); snobj_list_add(r, elem); } ns_release_iterator(&iter); return r; }