예제 #1
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;
}
예제 #2
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')");
}