Using namespacesΒΆ

The code to init a netlink socket in a network namespace was moved to the library core. To run a socket within a netns, simply pass netns argument to the socket init:

import asyncio

from pyroute2 import AsyncIPRoute


async def main():
    async with AsyncIPRoute(netns="test") as ipr:
        print(f"current netns: {ipr.status['netns']}")

asyncio.run(main())
current netns: test

It is possible to use the old NetNS class, it is now just a compatibility wrapper for the new API:

from pyroute2 import NetNS

with NetNS("test") as ns:
    print(f"current netns: {ns.status['netns']}")
current netns: test

Flags also might be used with any constructor. The default flags are os.O_CREAT, which means that the network namespace will be created if doesn't exist. Using 0 as flags value means that the constructor will fail, if the network namespace doesn't exist already:

from pyroute2 import IPRoute

try:
    ipr = IPRoute(netns="foo", flags=0)
except FileNotFoundError:
    print("netns doesn't exist, refuse to start")
netns doesn't exist, refuse to start

The init routine works now as follows:

  • fork a child using pyroute2.config.child_process_mode, which can be either "fork" (default) for os.fork() or "mp" for multiprocessing.Process() (safer and slower).

  • start a socket in the child

  • send the socket FD back to the parent

  • init a socket in the parent using the FD from the child

  • exit the child

An important note about pyroute2.config.child_process_mode: while the "fork" mode might be significantly faster than "mp" on some setups and versions, it is not threadsafe, and you will get warnings from Python when using it in multithreaded applications. The socket init routine is written to be safe even under these circumstances, but ye warned.