Определить, является ли сетевой интерфейс `veth` с помощью` / sys / class / net`?

Быть задающим много вопросов - это возможный путь в создании ядра. Мои знания немного устарели, но я склонен начинать с "make xconfig", а затем вы можете просматривать конфигурацию. Это те же самые вопросы, но они кажутся менее настойчивыми.

Использование всех настроек по умолчанию разумно.

2
05.05.2018, 17:25
1 ответ

Проведя дополнительные исследования, я пришел к выводу, что моя цель недостижима с использованием /sys/class/net/.... К счастью, это достижимо.

Монтирование правильно настроенного пространства имен/sys/class/net

Благодаря ответу Данилы Кивера на вопрос «Переключение в сетевое пространство имен не меняет /sys/class/net?» все, что мне нужно сделать, это смонтировать sysfsв каком-то месте, чтобы получить правильное (сетевое пространство имен )для sysfsи его class/net/ветви.

В следующем примере Python сканирует сетевые пространства имен, а затем перечисляет все сетевые интерфейсы в определенном сетевом пространстве имен, помечая каждый физический сетевой интерфейс с помощью [PHY]. Обратите внимание, что этот скрипт нуждается в руте/админке, особенно из-за монтирования.

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

Однако интерфейс NETLINK для ядра Linux предоставляет необходимую информацию, иначе команда ip linkне смогла бы определить тип интерфейса.

Ключевым здесь является атрибут IFLA_LINKINFO, который возвращается при запросе у ядра списка сетевых ссылок (, то есть сетевых интерфейсов ). Внутри него находится еще один атрибут с именем IFLA_INFO_KIND, это vethв случае сетевого интерфейса vethили bridgeв случае моста ядра Linux.

Обратите внимание, что атрибут IFLA_LINKINFOявляется необязательным; например, сетевые интерфейсы loopback, ethernet и wifi не предлагают IFLA_LINKINFO.

Эту информацию можно легко получить в Python, используя известную pyroute2 библиотеку netlink. pyroute2имеет дело со всеми неприятными вещами NETLINK, его легко установить через pip3. Этот пример просто перебирает все сетевые интерфейсы, видимые в текущем сетевом пространстве имен, задавая их имена, индекс интерфейса и значение IFLA_LINKINFO, если оно присутствует.

from pyroute2 import IPRoute

netw = IPRoute()
for link in netw.get_links():
    ifindex = link['index']
    ifname = link.get_attr('IFLA_IFNAME')
    linkinfo = link.get_attr('IFLA_LINKINFO')
    if linkinfo is not None:
        linktype = linkinfo.get_attr('IFLA_INFO_KIND')
    else:
        linktype = 'None'

    print('{0}: #{1} {2}'.format(ifname, ifindex, linktype))
2
27.01.2020, 22:18

Теги

Похожие вопросы