eth1
などの特定のネットワークインターフェイスが実際にはタイプveth
ネットワークインターフェイスであることを明確に識別することは可能ですか?コンテナでは、ネットワークインターフェイス名は通常eth*
ではなくveth*
で始まり、セットに実際のeth
がないことを確認できないことに注意してください。これは/sys/class/net
で検出できますか?
/sys/class/net/...
のiflink
要素はveth
ネットワークインターフェイスを明確に識別せず、代わりに他の状況でも使用されているという印象を受けています。 /sys/class/net/...
ファイルシステムを使用して質問を解決する方法がない場合、この情報を提供できるソケット呼び出しはありますか?Pythonで使用できますか?
さらに調査を重ねた結果、_ 幸いなことに、それは達成可能です。/sys/class/net/...
_を使用して目標を達成することはできないという結論に達しました。
/sys/class/net
_おかげで 「ネットワーク名前空間に切り替えても/ sys/class/netは変更されませんか?」に対するDanila Kiverの回答 私がする必要があるのは、sysfs
をどこかにマウントすることだけです。 sysfs
とその_class/net/
_ブランチに対する正しい(ネットワーク)名前空間のビューを取得します。
次のPythonの例では、ネットワーク名前空間をスキャンし、特定のネットワーク名前空間内のすべてのネットワークインターフェイスを一覧表示して、各物理ネットワークインターフェイスを_[PHY]
_でマークします。このスクリプトにはroot /が必要であることに注意してください。特にマウントによる管理キャップ。
_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
、Linuxカーネルブリッジの場合はbridge
です。
_IFLA_LINKINFO
_はオプションの属性であることに注意してください。たとえば、ループバック、イーサネット、およびWi-Fiネットワークインターフェイスは_IFLA_LINKINFO
_を提供しません。
この情報は、有名な pyroute2 ネットリンクライブラリを使用してPythonで簡単に取得できます。_pyroute2
_はすべての厄介なNETLINKのものを扱い、_pip3
_。この例では、現在のネットワーク名前空間に表示されているすべてのネットワークインターフェイスを単純に繰り返し、名前、インターフェイスインデックス、および_IFLA_LINKINFO
_値(存在する場合)を指定します。
frompyroute2 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') linkinfoがNoneでない場合: linktype = linkinfo .get_attr( 'IFLA_INFO_KIND') else: linktype = 'なし' print( '{0}:#{1} {2}'。 format(ifname、ifindex、linktype))