我正在使用下面的C函数,从一个单一的进程实例中创建多个网络命名空间:
void create_namespace(const char *ns_name)
{
char ns_path[100];
snprintf(ns_path, 100, "%s/%s", "/var/run/netns", ns_name);
close(open(ns_path, O_RDONLY|O_CREAT|O_EXCL, 0));
unshare(CLONE_NEWNET);
mount("/proc/self/ns/net", ns_path, "none", MS_BIND , NULL);
}
在我的进程创建了所有的命名空间并将一个tap接口添加到任何一个网络命名空间(使用ip link set tap1 netns ns1
命令)之后,我实际上会在所有的命名空间中看到这个接口(这可能实际上是一个单一的命名空间,在不同的名称下运行)。
但是,如果我使用多个进程创建多个命名空间,那么一切都正常工作。
这里可能出了什么问题?我是否需要在单个进程实例中传递任何其他标志以使其工作?单个进程实例无法创建多个网络命名空间吗?还是mount()
调用存在问题,因为/proc/self/ns/net
实际上被多次挂载?
更新:
似乎unshare()
函数正确地创建了多个网络命名空间,但在/var/run/netns/
中的所有挂载点实际上都引用了在该目录中挂载的第一个网络命名空间。
更新2: 似乎最好的方法是fork()另一个进程并从那里执行create_namespace()函数。无论如何,我很乐意听到一个更好的解决方案,不涉及fork()调用,或者至少得到一个证实,证明无法从单个进程创建和管理多个网络命名空间。
更新3: 我能够使用以下代码使用unshare()创建多个命名空间:
int main() {
create_namespace("a");
system("ip tuntap add mode tap tapa");
system("ifconfig -a");//shows lo and tapA interface
create_namespace("b");
system("ip tuntap add mode tap tapb");
system("ifconfig -a");//show lo and tapB interface, but does not show tapA. So this is second namespace created.
}
但是在进程终止后,当我执行ip netns exec a ifconfig -a
和ip netns exec b ifconfig -a
时,似乎两个命令突然都在a命名空间中执行。因此,实际的问题是存储对命名空间的引用(或以正确的方式调用mount()函数)。但我不确定这是否可行。
/* Bind the netns last so I can watch for it */ if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0)
- Coren