检索 Python 中网络命名空间的 netnsid
Retrieving the netnsid of a network namespace in Python
当试图找到位于不同命名空间的 veth
对的正确对等网络接口时,该端不仅由其 iflink
属性 指示,而且通过 link-netnsid
。此 link-netnsid
是一个网络命名空间 ID,仅在当前网络命名空间内有意义。
Linux 内核不提供将 netnsid 映射到网络名称空间 inode 编号,这是唯一的唯一标识。但是,Linux 提供 RTM_GETNSID
请求,将由 fd (NETNSA_FD
) 或 PID (NETNSA_PID
) 标识的网络命名空间映射到本地 netnsid。
如何在 Python 中发出这样的 RTM_GETNSID
请求,最好使用 pyroute2
库?到目前为止,我无法成功请求 PID 标识的命名空间的 netnsid,但只能返回无效参数错误 22,使用以下脚本:
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345)]
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)
事实证明我的代码实际上是正确的,但是 pyroute2
中存在一个错误导致 RTNETLINK 消息太短了几个八位字节(在 strace
中可见)。作为解决这个库错误的临时 hack,设置两个属性就足够了,这样内核就可以接受 RTNETLINK 数据包并对其进行处理,即使它不完全正确。
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345), ('NETNSA_PID', 0] # hack around pyroute 0.5.0 bug
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)
当试图找到位于不同命名空间的 veth
对的正确对等网络接口时,该端不仅由其 iflink
属性 指示,而且通过 link-netnsid
。此 link-netnsid
是一个网络命名空间 ID,仅在当前网络命名空间内有意义。
Linux 内核不提供将 netnsid 映射到网络名称空间 inode 编号,这是唯一的唯一标识。但是,Linux 提供 RTM_GETNSID
请求,将由 fd (NETNSA_FD
) 或 PID (NETNSA_PID
) 标识的网络命名空间映射到本地 netnsid。
如何在 Python 中发出这样的 RTM_GETNSID
请求,最好使用 pyroute2
库?到目前为止,我无法成功请求 PID 标识的命名空间的 netnsid,但只能返回无效参数错误 22,使用以下脚本:
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345)]
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)
事实证明我的代码实际上是正确的,但是 pyroute2
中存在一个错误导致 RTNETLINK 消息太短了几个八位字节(在 strace
中可见)。作为解决这个库错误的临时 hack,设置两个属性就足够了,这样内核就可以接受 RTNETLINK 数据包并对其进行处理,即使它不完全正确。
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345), ('NETNSA_PID', 0] # hack around pyroute 0.5.0 bug
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)