Я использую следующую функцию 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/
на самом деле ссылаются на первое сетевое пространство имен, которое было смонтировано в этом директория.
Обновление 2: Кажется, что лучший подход — разветвить() другой процесс и выполнить оттуда функцию 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(). Но я не уверен, возможно ли это).