安装正确的命名空间/sys/class/net

安装正确的命名空间/sys/class/net

是否可以明确识别给定的网络接口(例如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网络接口或bridgeLinux 内核桥接器。

请注意,这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))

相关内容