Как создать несколько сетевых пространств имен из одного экземпляра процесса

Я использую следующую функцию 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(). Но я не уверен, возможно ли это).

17
задан chrk 18 December 2016 в 19:29
поделиться