예제 #1
0
파일: snctl.c 프로젝트: apanda/bess
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;
}
예제 #2
0
파일: snctl.c 프로젝트: Grace-Liu/bess
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;
}
예제 #3
0
파일: snctl.c 프로젝트: Grace-Liu/bess
static struct snobj *handle_enable_tcpdump(struct snobj *q)
{
	const char *m_name;
	const char *fifo;
	gate_t gate;

	struct module *m;

	int ret;

	m_name = snobj_eval_str(q, "name");
	gate = snobj_eval_uint(q, "gate");
	fifo = snobj_eval_str(q, "fifo");

	if (!m_name)
		return snobj_err(EINVAL, "Missing 'name' field");

	if ((m = find_module(m_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m_name);

	if (gate >= m->allocated_gates)
		return snobj_err(EINVAL, "Gate '%hu' does not exist", gate);

	ret = enable_tcpdump(fifo, m, gate);

	if (ret < 0) {
		return snobj_err(-ret, "Enabling tcpdump %s[%d] failed",
				m_name, gate);
	}
	return NULL;
}
예제 #4
0
파일: snctl.c 프로젝트: apanda/bess
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;
}
예제 #5
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_connect_modules(struct snobj *arg)
{
	const char *m1_name;
	const char *m2_name;
	uint16_t gate;

	struct module *m1;
	struct module *m2;

	int ret;

	m1_name = snobj_eval_str(arg, "m1");
	m2_name = snobj_eval_str(arg, "m2");
	gate = snobj_eval_uint(arg, "gate");

	if (!m1_name || !m2_name)
		return snobj_err(EINVAL, "Missing 'm1' or 'm2' field in arg");

	if ((m1 = find_module(m1_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m1_name);

	if ((m2 = find_module(m2_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m2_name);

	ret = connect_modules(m1, gate, m2);
	if (ret < 0)
		return snobj_err(-ret, "Connection '%s'[%d]->'%s' failed", 
			m1_name, gate, m2_name);

	printf("%s[%d] -> %s\n", m1_name, gate, m2_name);

	return NULL;
}
예제 #6
0
파일: snctl.c 프로젝트: Grace-Liu/bess
static struct snobj *handle_get_tc_stats(struct snobj *q)
{
	const char *tc_name;

	struct tc *c;
	
	struct snobj *r;

	tc_name = snobj_str_get(q);
	if (!tc_name)
		return snobj_err(EINVAL, "Argument must be a name in str");

	c = ns_lookup(NS_TYPE_TC, tc_name);
	if (!c)
		return snobj_err(ENOENT, "No TC '%s' found", tc_name);

	r = snobj_map();

	snobj_map_set(r, "timestamp", snobj_double(get_epoch_time()));
	snobj_map_set(r, "count", 
			snobj_uint(c->stats.usage[RESOURCE_CNT]));
	snobj_map_set(r, "cycles", 
			snobj_uint(c->stats.usage[RESOURCE_CYCLE]));
	snobj_map_set(r, "packets", 
			snobj_uint(c->stats.usage[RESOURCE_PACKET]));
	snobj_map_set(r, "bits", 
			snobj_uint(c->stats.usage[RESOURCE_BIT]));

	return r;
}
예제 #7
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_disable_tcpdump(struct snobj *arg)
{
	const char *m_name;
	uint16_t gate;

	struct module *m;

	int ret;

	m_name = snobj_eval_str(arg, "name");
	gate = snobj_eval_uint(arg, "gate");

	if (!m_name)
		return snobj_err(EINVAL, "Missing 'name' field in arg");

	if ((m = find_module(m_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m_name);

	if (gate >= m->allocated_gates)
		return snobj_err(EINVAL, "Gate '%hu' does not exist", gate);

	ret = disable_tcpdump(m, gate);

	if (ret < 0) {
		return snobj_err(-ret, "Disabling tcpdump %s[%d] failed",
				m_name, gate);
	}
	return NULL;
}
예제 #8
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_disconnect_modules(struct snobj *arg)
{
	const char *m_name;
	uint16_t gate;

	struct module *m;

	int ret;

	m_name = snobj_eval_str(arg, "name");
	gate = snobj_eval_uint(arg, "gate");

	if (!m_name)
		return snobj_err(EINVAL, "Missing 'name' field in arg");

	if ((m = find_module(m_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m_name);

	ret = disconnect_modules(m, gate);
	if (ret < 0)
		return snobj_err(-ret, "Disconnection '%s'[%d] failed", 
			m_name, gate);

	printf("%s[%d] -> <dead end>\n", m_name, gate);

	return NULL;
}
예제 #9
0
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;
}
예제 #10
0
파일: vport.c 프로젝트: apanda/bess
static struct snobj *docker_container_pid(char *cid, int *container_pid)
{
	char buf[1024];

	FILE *fp;
		
	int ret;
	int exit_code;

	if (!cid)
		return snobj_err(EINVAL, "field 'docker' should be " \
				"a containder ID or name in string");

	ret = snprintf(buf, sizeof(buf), 
			"docker inspect --format '{{.State.Pid}}' " \
			"%s 2>&1", cid);
	if (ret >= sizeof(buf))
		return snobj_err(EINVAL, "The specified Docker " \
				"container ID or name is too long");

	fp = popen(buf, "r");
	if (!fp) 
		return snobj_err_details(ESRCH, 
				snobj_str_fmt("popen() errno=%d (%s)",
					errno, strerror(errno)),
				"Command 'docker' is not available. " \
				"(not installed?)");

	ret = fread(buf, 1, sizeof(buf) - 1, fp);
	if (ret == 0)
		return snobj_err(ENOENT, "Cannot find the PID of " \
				"container %s", cid);

	buf[ret] = '\0';
	
	ret = pclose(fp);
	exit_code = WEXITSTATUS(ret);

	if (exit_code != 0 || sscanf(buf, "%d", container_pid) == 0) {
		struct snobj *details = snobj_map();

		snobj_map_set(details, "exit_code", snobj_int(exit_code));
		snobj_map_set(details, "docker_err", snobj_str(buf));
	
		return snobj_err_details(ESRCH, details,
				"Cannot find the PID of container %s", cid);
	}

	return NULL;
}
예제 #11
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_get_module_info(struct snobj *arg)
{
	const char *m_name;
	struct module *m;

	struct snobj *r;
	struct snobj *gates;

	m_name = snobj_str_get(arg);

	if (!m_name)
		return snobj_err(EINVAL, "Argument must be a name in str");

	if ((m = find_module(m_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m_name);

	r = snobj_map();
	gates = snobj_list();

	snobj_map_set(r, "name", snobj_str(m->name));
	snobj_map_set(r, "mclass", snobj_str(m->mclass->name));

	if (m->mclass->get_desc)
		snobj_map_set(r, "desc", m->mclass->get_desc(m));

	if (m->mclass->get_dump)
		snobj_map_set(r, "dump", m->mclass->get_dump(m));

	for (int i = 0; i < m->allocated_gates; i++) {
		if (m->gates[i].m) {
			struct snobj *gate = snobj_map();
			snobj_map_set(gate, "gate", snobj_uint(i));
#if TRACK_GATES
			snobj_map_set(gate, "cnt", 
					snobj_uint(m->gates[i].cnt));
			snobj_map_set(gate, "pkts", 
					snobj_uint(m->gates[i].pkts));
			snobj_map_set(gate, "timestamp", 
					snobj_double(get_epoch_time()));
#endif
			snobj_map_set(gate, "name", snobj_str(m->gates[i].m->name));
			snobj_list_add(gates, gate);
		}
	}

	snobj_map_set(r, "gates", gates);

	return r;
}
예제 #12
0
파일: snctl.c 프로젝트: Grace-Liu/bess
static struct snobj *handle_attach_task(struct snobj *q)
{
	const char *m_name;
	const char *tc_name;

	task_id_t tid;

	struct module *m;
	struct task *t;

	m_name = snobj_eval_str(q, "name");

	if (!m_name)
		return snobj_err(EINVAL, "Missing 'name' field");

	if ((m = find_module(m_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m_name);

	tid = snobj_eval_uint(q, "taskid");
	if (tid >= MAX_TASKS_PER_MODULE)
		return snobj_err(EINVAL, "'taskid' must be between 0 and %d",
				MAX_TASKS_PER_MODULE - 1);

	if ((t = m->tasks[tid]) == NULL)
		return snobj_err(ENOENT, "Task %s:%hu does not exist", 
				m_name, tid);

	tc_name = snobj_eval_str(q, "tc");

	if (tc_name) {
		struct tc *c;

		c = ns_lookup(NS_TYPE_TC, tc_name);
		if (!c)
			return snobj_err(ENOENT, "No TC '%s' found", tc_name);

		task_attach(t, c);
	} else {
		int wid;		/* TODO: worker_id_t */

		if (task_is_attached(t))
			return snobj_err(EBUSY, "Task %s:%hu is already "
					"attached to a TC", m_name, tid);

		wid = snobj_eval_uint(q, "wid");
		if (wid >= MAX_WORKERS)
			return snobj_err(EINVAL, "'wid' must be between 0 and %d",
					MAX_WORKERS - 1);

		if (!is_worker_active(wid))
			return snobj_err(EINVAL, "Worker %d does not exist", wid);

		assign_default_tc(wid, t);
	}

	return NULL;
}
예제 #13
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_destroy_module(struct snobj *arg)
{
	const char *m_name;
	struct module *m;

	m_name = snobj_str_get(arg);

	if (!m_name)
		return snobj_err(EINVAL, "Argument must be a name in str");

	if ((m = find_module(m_name)) == NULL)
		return snobj_err(ENOENT, "No module '%s' found", m_name);

	destroy_module(m);

	return NULL;
}
예제 #14
0
파일: port_out.c 프로젝트: apanda/bess
static struct snobj *port_out_init(struct module *m, struct snobj *arg)
{
	struct port_out_priv *priv = get_priv(m);

	const char *port_name;

	port_name = snobj_str_get(arg);
	if (!port_name)
		return snobj_err(EINVAL, "Argument must be a string");

	priv->port = find_port(port_name);
	if (!priv->port)
		return snobj_err(ENODEV, "Port %s not found", port_name);

	acquire_queue(priv->port, PACKET_DIR_OUT, 0 /* XXX */, m);

	return NULL;
}
예제 #15
0
파일: snctl.c 프로젝트: apanda/bess
struct snobj *handle_request(struct client *c, struct snobj *q)
{
	struct snobj *r = NULL;
	const char *s;

#if 0
	printf("Request:\n");
	snobj_dump(q);
#endif

	if (q->type != TYPE_MAP) {
		r = snobj_err(EINVAL, "The message must be a map");
		goto reply;
	}

	s = snobj_eval_str(q, "to");
	if (!s) {
		r = snobj_str("There is no 'to' field");
		goto reply;
	}

	if (strcmp(s, "softnic") == 0) {
		r = handle_snobj_softnic(q);
	} else if (strcmp(s, "module") == 0) {
		r = handle_snobj_module(q);
	} else
		r = snobj_err(EINVAL, "Unknown destination in 'to': %s", s);

reply:
	/* No response was made? (normally means "success") */
	if (!r)
		r = snobj_nil();

#if 0
	printf("Response:\n");
	snobj_dump(r);
#endif

	return r;
}
예제 #16
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_get_port_stats(struct snobj *arg)
{
	const char *port_name;

	struct port *port;

	port_stats_t stats;

	struct snobj *r;
	struct snobj *inc;
	struct snobj *out;

	port_name = snobj_str_get(arg);
	if (!port_name)
		return snobj_err(EINVAL, "Argument must be a name in str");
	
	port = find_port(port_name);
	if (!port)
		return snobj_err(ENOENT, "No port `%s' found", port_name);

	get_port_stats(port, &stats);

	inc = snobj_map();
	snobj_map_set(inc, "packets", snobj_uint(stats[PACKET_DIR_INC].packets));
	snobj_map_set(inc, "dropped", snobj_uint(stats[PACKET_DIR_INC].dropped));
	snobj_map_set(inc, "bytes",   snobj_uint(stats[PACKET_DIR_INC].bytes));

	out = snobj_map();
	snobj_map_set(out, "packets", snobj_uint(stats[PACKET_DIR_OUT].packets));
	snobj_map_set(out, "dropped", snobj_uint(stats[PACKET_DIR_OUT].dropped));
	snobj_map_set(out, "bytes",   snobj_uint(stats[PACKET_DIR_OUT].bytes));

	r = snobj_map();
	snobj_map_set(r, "inc", inc);
	snobj_map_set(r, "out", out);
	snobj_map_set(r, "timestamp", snobj_double(get_epoch_time()));

	return r;
}
예제 #17
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_destroy_port(struct snobj *arg)
{
	const char *port_name;

	struct port *port;

	int ret;

	port_name = snobj_str_get(arg);
	if (!port_name)
		return snobj_err(EINVAL, "Argument must be a name in str");
	
	port = find_port(port_name);
	if (!port)
		return snobj_err(ENOENT, "No port `%s' found", port_name);

	ret = destroy_port(port);
	if (ret)
		return snobj_errno(-ret);

	return NULL;
}
예제 #18
0
파일: snctl.c 프로젝트: apanda/bess
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);
}
예제 #19
0
파일: port_inc.c 프로젝트: keonjang/bess
static struct snobj *port_inc_init(struct module *m, struct snobj *arg)
{
	struct port_inc_priv *priv = get_priv(m);

	const char *port_name;
	task_id_t ret;

	if (!arg || !(port_name = snobj_str_get(arg)))
		return snobj_err(EINVAL, "Argument must be a port name " \
				"(string)");

	priv->port = find_port(port_name);
	if (!priv->port)
		return snobj_err(ENODEV, "Port %s not found", port_name);

	ret = register_task(m, NULL);
	if (ret == INVALID_TASK_ID)
		return snobj_err(ENOMEM, "Task creation failed");

	acquire_queue(priv->port, PACKET_DIR_INC, 0 /* XXX */, m);

	return NULL;
}
예제 #20
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_snobj_softnic(struct snobj *q)
{
	struct snobj *arg;
	const char *s;

	s = snobj_eval_str(q, "cmd");
	if (!s)
		return snobj_err(EINVAL, "Missing 'cmd' field");

	arg = snobj_map_get(q, "arg");

	for (int i = 0; sn_handlers[i].cmd != NULL; i++) {
		if (strcmp(s, sn_handlers[i].cmd) != 0)
			continue;

		if (sn_handlers[i].pause_needed && is_any_worker_running())
			return snobj_err(EBUSY, "There is a running worker");

		return sn_handlers[i].func(arg);
	}

	return snobj_err(ENOTSUP, "Unknown command in 'cmd': '%s'", s);
}
예제 #21
0
파일: snctl.c 프로젝트: Grace-Liu/bess
static struct snobj *handle_add_tc(struct snobj *q)
{
	const char *tc_name;
	int wid;

	struct tc_params params;
	struct tc *c;

	tc_name = snobj_eval_str(q, "name");
	if (!tc_name)
		return snobj_err(EINVAL, "Missing 'name' field");

	if (!ns_is_valid_name(tc_name))
		return snobj_err(EINVAL, "'%s' is an invalid name", tc_name);

	if (ns_name_exists(tc_name))
		return snobj_err(EINVAL, "Name '%s' already exists", tc_name);

	wid = snobj_eval_uint(q, "wid");
	if (wid >= MAX_WORKERS)
		return snobj_err(EINVAL, 
				"'wid' must be between 0 and %d",
				MAX_WORKERS - 1);

	if (!is_worker_active(wid))
		return snobj_err(EINVAL, "worker:%d does not exist", wid);

	memset(&params, 0, sizeof(params));

	strcpy(params.name, tc_name);

	params.priority = snobj_eval_int(q, "priority");
	if (params.priority == DEFAULT_PRIORITY)
		return snobj_err(EINVAL, "Priority %d is reserved",
				DEFAULT_PRIORITY);

	/* TODO */
	params.share = 1;
	params.share_resource = RESOURCE_CNT;

	c = tc_init(workers[wid]->s, &params);
	if (is_err(c))
		return snobj_err(-ptr_to_err(c), "tc_init() failed");

	tc_join(c);

	return NULL;
}
예제 #22
0
파일: snctl.c 프로젝트: Grace-Liu/bess
static struct snobj *handle_reset_tcs(struct snobj *q)
{
	struct ns_iter iter;
	struct tc *c;

	struct tc **c_arr;
	size_t arr_slots = 1024;
	int n = 0;

	c_arr = malloc(arr_slots * sizeof(struct tc *));

	ns_init_iterator(&iter, NS_TYPE_TC);

	while ((c = (struct tc *)ns_next(&iter)) != NULL) {
		if (n >= arr_slots) {
			arr_slots *= 2;
			c_arr = realloc(c_arr, arr_slots * sizeof(struct tc *));
		}

		c_arr[n] = c;
		n++;
	}

	ns_release_iterator(&iter);	

	for (int i = 0; i < n; i++) {
		c = c_arr[i];

		if (c->num_tasks) {
			free(c_arr);
			return snobj_err(EBUSY, "TC %s still has %d tasks",
					c->name, c->num_tasks);
		}

		if (c->auto_free)
			continue;

		tc_leave(c);
		tc_dec_refcnt(c);
	}

	free(c_arr);
	return NULL;
}
예제 #23
0
파일: snctl.c 프로젝트: apanda/bess
static struct snobj *handle_not_implemented(struct snobj *q)
{
	return snobj_err(ENOTSUP, "Not implemented yet");
}
예제 #24
0
파일: snctl.c 프로젝트: Grace-Liu/bess
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;
}
예제 #25
0
파일: vport.c 프로젝트: apanda/bess
static struct snobj *set_ip_addr(struct port *p, int container_pid,
		struct snobj *arg)
{
	int child_pid;

	int ret = 0;

	if (snobj_type(arg) == TYPE_STR || snobj_type(arg) == TYPE_LIST) {
		if (snobj_type(arg) == TYPE_LIST) {
			if (arg->size == 0)
				goto invalid_type;

			for (int i = 0; i < arg->size; i++) {
				struct snobj *addr = snobj_list_get(arg, i);
				if (snobj_type(addr) != TYPE_STR)
					goto invalid_type;
			}
		}
	} else
		goto invalid_type;

	/* change network namespace if necessary */
	if (container_pid) {
		child_pid = fork();

		if (child_pid < 0)
			return snobj_errno(-child_pid);

		if (child_pid == 0) {
			char buf[1024];
			int fd;

			sprintf(buf, "/proc/%d/ns/net", container_pid);
			fd = open(buf, O_RDONLY);
			if (fd < 0) {
				perror("open(/proc/pid/ns/net)");
				exit(errno <= 255 ? errno: ENOMSG);
			}

			ret = setns(fd, 0);
			if (ret < 0) {
				perror("setns()");
				exit(errno <= 255 ? errno: ENOMSG);
			}
		} else
			goto wait_child;
	}

	switch (snobj_type(arg)) {
	case TYPE_STR: 
		ret = set_ip_addr_single(p, snobj_str_get(arg));
		if (ret < 0) {
			if (container_pid) {
				/* it must be the child */
				assert(child_pid == 0);	
				exit(errno <= 255 ? errno: ENOMSG);
			}
		}
		break;

	case TYPE_LIST: 
		if (!arg->size)
			goto invalid_type;

		for (int i = 0; i < arg->size; i++) {
			struct snobj *addr = snobj_list_get(arg, i);

			ret = set_ip_addr_single(p, snobj_str_get(addr));
			if (ret < 0) {
				if (container_pid) {
					/* it must be the child */
					assert(child_pid == 0);	
					exit(errno <= 255 ? errno: ENOMSG);
				} else
					break;
			}
		}

		break;

	default:
		assert(0);
	}

	if (container_pid) {
		if (child_pid == 0) {
			if (ret < 0) {
				ret = -ret;
				exit(ret <= 255 ? ret: ENOMSG);
			} else
				exit(0);
		} else {
			int exit_status;

wait_child:
			ret = waitpid(child_pid, &exit_status, 0);

			if (ret >= 0) {
				assert(ret == child_pid);
				ret = -WEXITSTATUS(exit_status);
			} else
				perror("waitpid()");
		}
	}

	if (ret < 0)
		return snobj_err_details(-ret, arg, 
				"Failed to set IP addresses " \
				"(incorrect IP address format?)");

	return NULL;

invalid_type:
	return snobj_err(EINVAL, "'ip_addr' must be a string or list " \
			"of IPv4/v6 addresses (e.g., '10.0.20.1/24')");
}
예제 #26
0
파일: vport.c 프로젝트: apanda/bess
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;
}