Я использую следующую функцию 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
), я фактически увижу этот интерфейс во всех пространствах имен (предположительно, это фактически единое пространство имен, которое используется под разными именами).
Но если я создам несколько пространств имен, используя несколько процессов, все будет работать нормально.
Что здесь может быть не так? Должен ли я передавать какие-либо дополнительные флаги unshare()
, чтобы это работало из одного экземпляра процесса? Есть ли ограничение, согласно которому один экземпляр процесса не может создавать несколько сетевых пространств имен? Или есть проблема с вызовом mount()
, потому что /proc/self/ns/net
на самом деле монтируется несколько раз?
Обновление: кажется, что функция unshare()
правильно создает несколько сетевых пространств имен, но все точки монтирования в /var/run/netns/
на самом деле ссылаются на первое сетевое пространство имен, которое было смонтировано в этом каталоге.
Update2: кажется, что лучший подход — разветвить() другой процесс и выполнить оттуда функцию create_namespace(). В любом случае, я был бы рад услышать лучшее решение, не связанное с вызовом fork(), или, по крайней мере, получить подтверждение, доказывающее невозможность создания и управления несколькими сетевыми пространствами имен из одного процесса.
Update3: я могу создать несколько пространств имен с помощью 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(). Но я не уверен, возможно ли это).