There's no actual name existing in the low-level handling of namespaces. It's all handled by common actions or expectations done with every command in the iproute2 suite.
Assigning a name to an existing anonymous network namespace really means: make the iproute2 tools believe they did their usual settings when creating this network namespace.
So what is ip netns add foo
really doing? It unshares to a new network namespace, and to keep this namespace existing even without process using it, mounts it. In the usual *nix philosophy, a namespace has an inode number representing a pseudo-file in the pseudo-filesystem nsfs. Almost no operation can be done on the file (not even read it), but it can be opened to use it as a token for namespace operations (eg setns(2)
) and can also be mounted as a bind mount.
Alas, the link nsid is not directly usable: that's not a global value representing an other namespace, but a local (locally unique but recyclable and not globally unique) ID representing a link to an other namespace. Multiple values means: links to multiple other namespaces, twice the same value means: two links to the same other namespace.
If you have to find the other namespaces starting only from this, I invite you to check my answer in this other Q/A where I made an answer about it. There's also a handy mapping tool available: plotnetcfg
which can map all the network namespaces. While it does know about iproute2 methods, it doesn't appear to give a process id separately, instead it names a namespace with a PID from it when it's not "named" by iproute2. Redacted example (requiring jq
), run as root:
# unshare -n -- sleep 999 &
[1] 677451
# plotnetcfg -f json | jq '.namespaces[].name'
""
[...]
"PID 268150 (systemd)"
"PID 345878 (systemd)"
[...]
"PID 677451 (sleep)"
Here ""
represents the initial namespace, the two systemd
are from two LXC instances, and the sleep
command running is also found.
To help for two common cases:
Once you have found by whatever method available a process in the intended network namespace, you can mimic what would do the iproute2 tools. What they exactly do might depend on their exact version. From strace
mine appear to do:
mkdir -p /run/netns
and then mount it over itself so it can be set as shared propagation:
mount --bind --make-shared /run/netns /run/netns
Above should only be done if not already done and only once. To have the tools do it for you (and only when needed), simply create and delete a dummy namespace:
ip netns add dummy && ip netns delete dummy
Now pick a name, for example foo
, create an empty file and change its mode to 000 (which is not needed, but mimics iproute2):
touch /run/netns/foo
chmod 0 /run/netns/foo
And finally mount the process' namespace given its PID (eg sleep
from before: 677451):
mount --bind /proc/677451/ns/net /run/netns/foo
That's it. Even if the sleep
command ends, the namespace will now survive. All iproute2 tools will now name it foo. For example if there was a veth interface connected to it, ip link
would replace the link nsid's number with foo
.
If you want to remove this network namespace, ip netns del foo
will now do it (caveat: as usual the actual network namespace really disappears once there's no resource using it anymore, like this sleep command).
Further documentation on iproute2's specific additional features along network namespaces in an other answer of mine.