estoy usando siguiente función C para crear varios espacios de nombres de red desde una única instancia de proceso :cómo crear varias espacio de nombres de red de una instancia de proceso único
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);
}
Después de mi proceso crea todos los namspaces y Agrego una interfaz tap a cualquiera de los espacios de nombre de una red (con el comando ip link set tap1 netns ns1
), entonces realmente veo esta interfaz en todos los espacios de nombres (presumiblemente, este es en realidad un solo espacio de nombres que tiene diferentes nombres).
Pero, si creo múltiples espacios de nombres mediante el uso de múltiples procesos, entonces todo está funcionando bien.
¿Qué podría estar mal aquí? ¿Debo pasar banderas adicionales al unshare()
para que funcione desde una única instancia de proceso? ¿Existe una limitación de que una única instancia de proceso no puede crear múltiples espacios de nombres de red? ¿O hay un problema con la llamada mount()
, porque /proc/self/ns/net
en realidad está montado varias veces?
Actualización: Parece que unshare()
función crea varios espacios de nombres de red correctamente, pero en realidad todos los puntos de montaje en /var/run/netns/
referencia al primer espacio de nombres de red que se montó en el que direcotry.
Update2: Parece que el mejor enfoque es fork() otro proceso y ejecutar la función create_namespace() desde allí. De todos modos, me encantaría escuchar una solución mejor que no involucre fork() llamada o al menos obtener una confirmación que demuestre que es imposible crear y administrar múltiples espacios de nombres de red desde un solo proceso.
Update3: soy capaz de crear varios espacios de nombres con dejar de compartir() usando el siguiente código:
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.
}
Pero después de que el proceso termina y yo ejecutar ip netns exec a ifconfig -a
y ip netns exec b ifconfig -a
parece que ambos comandos eran de repente se ejecuta en el espacio de nombres a. Entonces, el problema real es almacenar las referencias a los espacios de nombres (o llamar a mount() de la manera correcta. Pero no estoy seguro, si esto es posible).
+1, pero podría explicar a qué se refiere con "Tenga en cuenta que no crea un nuevo espacio de nombres de red con unshare"? Vea la actualización # 3, porque mi entendimiento es que unshare() aún puede crear espacios de nombres de red.El clon (CLONE_NEWNET) es algo así como "Voy a crear un nuevo proceso hijo con un nuevo espacio de nombres de red", mientras que no compartir (CLONE_NEWNET) es como "No quiero compartir el espacio de nombres de red con mi proceso padre. uno nuevo.". lxc usa clone(), mientras que iproute2 usa unshare(). –
Trataré de explicar. Usted crea un espacio de nombres de red para su proceso _current_ con * unshare *, pero como los espacios de nombres de red necesitan un PID para vivir, no podrá crear uno nuevo solo con * unshare * para el _same_proceso. – Coren
Veo que señala, pero dejar de compartir() aún puede crear un nuevo espacio de nombres de red (esto necesita una actualización de su respuesta). Además, supongo que el espacio de nombres no necesariamente necesita un PID real donde vivir (por ejemplo, después de ejecutar el comando "ip netns add nsX" el proceso de IP finaliza, pero el espacio de nombres nsX aún permanece). Creo que esta limitación "por qué es imposible crear múltiples espacios de nombres de red a partir de un solo proceso" tiene que ver con el funcionamiento de mount(). –