是否可以明确识别给定的网络接口(例如eth1
)实际上是一种类型veth
网络接口?请注意,在容器中,它们的网络接口名称通常eth*
以而不是开头,veth*
并且无法确定eth
集合中是否存在实数。这可以通过检测吗/sys/class/net
?
我的印象是,iflink
中的元素/sys/class/net/...
并没有明确标识veth
网络接口,而是也用于其他情况。如果无法使用/sys/class/net/...
文件系统解决我的问题,是否有套接字调用可以为我提供此信息,最好在 Python 中使用?
答案1
经过更多研究后,我得出的结论是,使用幸运的是,它是可以实现的。/sys/class/net/...
.
安装正确的命名空间/sys/class/net
谢谢Danila Kiver 对“切换到网络名称空间不会更改 /sys/class/net?”的回答我需要做的就是在某个地方安装sysfs
以便获得正确的(网络)命名空间视图sysfs
及其class/net/
分支。
以下 Python 示例扫描网络命名空间,然后列出特定网络命名空间中的所有网络接口,并用[PHY]
.请注意,此脚本需要 root/admin 权限,特别是由于挂载。
import psutil
import nsenter
from ctypes import c_char_p, c_ulong
import ctypes.util
import os
import tempfile
# https://stackoverflow.com/a/29156997
libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
libc.mount.argtypes = (c_char_p, c_char_p, c_char_p, c_ulong, c_char_p)
libc.umount.argtypes = (c_char_p, )
netns_index = dict()
for process in psutil.process_iter():
netns_ref = '/proc/%d/ns/net' % process.pid
try:
netns_id = os.stat(netns_ref).st_ino
if netns_id not in netns_index:
netns_index[netns_id] = netns_ref
except PermissionError:
pass
with tempfile.TemporaryDirectory() as temp_mnt:
for netns_id, netns_ref in netns_index.items():
with nsenter.Namespace(netns_ref, 'net'):
print('net:[%d]' % netns_id)
if libc.mount('sysfs'.encode('ascii'),
temp_mnt.encode('ascii'),
'sysfs'.encode('ascii'),
0,
''.encode('ascii')) >= 0:
for nif_name in sorted(os.listdir('%s/class/net' % temp_mnt)):
nif_path = os.readlink('%s/class/net/%s' % (temp_mnt, nif_name))
phys_nif = not nif_path.startswith('../../devices/virtual/')
print(' %s %s' % (nif_name, '[PHY]' if phys_nif else ''))
libc.umount(temp_mnt.encode('ascii'))
解决方法没有/sys/class/net
然而,Linux 内核的 NETLINK 接口提供了所需的信息,否则命令ip link
将无法判断接口的类型。
这里的关键是IFLA_LINKINFO
向内核请求网络链接(即网络接口)列表时返回的属性。它里面有另一个名为 的属性IFLA_INFO_KIND
,它veth
适用于veth
网络接口或bridge
Linux 内核桥接器。
请注意,这IFLA_LINKINFO
是一个可选属性;例如,环回、以太网和 wifi 网络接口不提供IFLA_LINKINFO
.
这些信息可以使用著名的 Python 轻松获得pyroute2网络链接库。pyroute2
处理所有讨厌的 NETLINK 东西,通过 轻松安装它pip3
。此示例只是迭代当前网络命名空间中可见的所有网络接口,给出它们的名称、接口索引和值IFLA_LINKINFO
(如果存在)。
从pyroute2导入IPRoute 网络 = IP 路由() 对于 netw.get_links() 中的链接: ifindex = 链接['索引'] ifname = link.get_attr('IFLA_IFNAME') linkinfo = link.get_attr('IFLA_LINKINFO') 如果 linkinfo 不是 None: linktype = linkinfo.get_attr('IFLA_INFO_KIND') 别的: 链接类型 = '无' print('{0}: #{1} {2}'.format(ifname, ifindex, linktype))