Udev - ネットワークケーブルホットプラグイベントがキャプチャされない

Udev - ネットワークケーブルホットプラグイベントがキャプチャされない

私はカスタムAtmel Sama5d2ベースのボードでbuildrootカスタムLinux(カーネル4.9.87)を実行しています。

ホットプラグ時にのみdhcpを使用してeth0インターフェイスでネットワークを設定しようとしています。

最初に、インターフェイスはintoを使用して起動時に設定auto eth0されます。/etc/network/interfaces

allow-hotplug eth0次のファイルを持つように変更しました。

# cat /etc/network/interfaces 

auto lo
iface lo inet loopback

allow-hotplug eth0
iface eth0 inet dhcp

このように変更すると、udhcpcは起動時に実行されなくなり、ケーブルが接続されていないと30秒間Linuxブートが妨げられなくなります。

ただし、ケーブルを接続または切断しても何も起こりません。

手動で実行すると、ifup -aインターフェイスにIPアドレスが表示されます。eth0

この結果、問題はネットワーク構成ではなく、より低いレベルのイベント処理でより多く発生すると考えられます。

ケーブルの接続/分離を監視するためにudevadmを試しましたが、ケーブルを接続または切断するとカーネルイベントは表示されません(ただし、USBサブシステムのイベントは表示されます)。

また、このサブシステムイベントがudevadmによって送出されない場合にイベントを記録するudevルールを作成しました。

# cat /etc/udev/rules.d/20-network.rules 
SUBSYSTEM=="net", ACTION=="add", RUN+="/test.sh add"
SUBSYSTEM=="net", ACTION=="remove" , RUN+="/test.sh remove" 

ただし、この規則も何もトリガーしません。


これで、ネットワークケーブルのホットプラグを検出するのに問題があるようです。

カーネル構成エラーまたはハードウェア配線エラーの可能性があります。

ハードウェアレベルでプラグ/プラグ解除イベントを検出する方法はわかりませんが、ドライバ自体またはドライバを配布する多くのカーネルフレームワークのいずれかによってイベントがudevに直接送信されるとします。

一部のカーネル構成が欠落している可能性があると思いますか?

udevを使用するよりも低いレベルでステータスケーブルを追跡することは可能だと思いますか?たぶんsysfsと直接対話することによって?

答え1

この udev ルールとスクリプトは、ネットワークインターフェイスの変更をキャプチャします。

/etc/udev/rules.d/90-netifchanges.rules:

# Call custom script when ethernet device(s) are changed/added/removed/etc in system
SUBSYSTEM=="net" \
, RUN+="/usr/bin/systemd-cat /usr/local/bin/netifchanges.sh '$env{ACTION}' '$name' '$id' '$sys$devpath'"

/usr/local/bin/netifchanges.shsystemdログに書き込むスクリプト:

#!/bin/bash -e
    
action=$1
ifname=$2
id=$3
syspath=$4
    
echo "Network interface $ifname ($id) $action"
printenv

再起動しなくてもテストできます。

udevadm control --reload-rules && udevadm -d trigger -v --type devices --subsystem-match net

その後、ログを確認してくださいjournalctl -xe

systemd を使用しない場合は、次を実行します。

削除/usr/bin/systemd-catしてorRUN+=".." またはechologger "..."echo "stuff" > /dev/kmsgディストリビューションで使用される他の方法

また、仮想インターフェイスを追加してログイベントを表示できます。

# ip link add dummy0 type dummy
# ip link set dummy0 up
# ip link set dummy0 down
# ip link delete dummy0

udevadm次のように、インターフェースに関する多くの情報を見つけることもできます。

# udevadm info -a /sys/class/net/eno1

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:19.0/net/eno1':
    KERNEL=="eno1"
    SUBSYSTEM=="net"
    DRIVER==""
    ATTR{gro_flush_timeout}=="0"
    ATTR{proto_down}=="0"
    ATTR{addr_assign_type}=="0"
    ATTR{flags}=="0x1103"
    ATTR{netdev_group}=="0"
    ATTR{name_assign_type}=="4"
    ATTR{broadcast}=="ff:ff:ff:ff:ff:ff"
    ATTR{operstate}=="up"
    ATTR{link_mode}=="0"
    ATTR{dev_port}=="0"
    ATTR{address}=="74:d0:2b:2c:6e:d7"
    ATTR{duplex}=="full"
    ATTR{carrier_changes}=="4"
    ATTR{type}=="1"
    ATTR{addr_len}=="6"
    ATTR{dev_id}=="0x0"
    ATTR{iflink}=="3"
    ATTR{mtu}=="1500"
    ATTR{speed}=="1000"
    ATTR{carrier_down_count}=="2"
    ATTR{ifalias}==""
    ATTR{carrier_up_count}=="2"
    ATTR{ifindex}=="3"
    ATTR{carrier}=="1"
    ATTR{tx_queue_len}=="1000"
    ATTR{dormant}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:19.0':
    KERNELS=="0000:00:19.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="e1000e"
    ATTRS{device}=="0x1503"
    ATTRS{label}==" Onboard LAN"
    ATTRS{enable}=="1"
    ATTRS{irq}=="56"
    ATTRS{subsystem_vendor}=="0x1043"
    ATTRS{devspec}==""
    ATTRS{revision}=="0x06"
    ATTRS{subsystem_device}=="0x849c"
    ATTRS{local_cpus}=="ff"
    ATTRS{local_cpulist}=="0-7"
    ATTRS{class}=="0x020000"
    ATTRS{driver_override}=="(null)"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}=="1"
    ATTRS{vendor}=="0x8086"
    ATTRS{consistent_dma_mask_bits}=="64"
    ATTRS{ari_enabled}=="0"
    ATTRS{index}=="1"
    ATTRS{numa_node}=="-1"
    ATTRS{d3cold_allowed}=="1"
    ATTRS{dma_mask_bits}=="64"

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

以下はsysファイルにリンクされています。

# cat /sys/class/net/eno1/operstate 
up

udevadm monitor可能:

# udevadm -d monitor -p -k -u --subsystem-match=net
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[99386.755966] add      /devices/virtual/net/dummy0 (net)
ACTION=add
DEVPATH=/devices/virtual/net/dummy0
SUBSYSTEM=net
INTERFACE=dummy0
IFINDEX=12
SEQNUM=6842

rx-0: sd-device-monitor: Received device does not pass filter, ignoring
tx-0: sd-device-monitor: Received device does not pass filter, ignoring
UDEV  [99386.773912] add      /devices/virtual/net/dummy0 (net)
ACTION=add
DEVPATH=/devices/virtual/net/dummy0
SUBSYSTEM=net
INTERFACE=dummy0
IFINDEX=12
SEQNUM=6842
USEC_INITIALIZED=99386759873
ID_NET_NAMING_SCHEME=v240
ID_MM_CANDIDATE=1
ID_NET_DRIVER=dummy
ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
SYSTEMD_ALIAS=/sys/subsystem/net/devices/dummy0
TAGS=:systemd:

rx-0: sd-device-monitor: Received device does not pass filter, ignoring
tx-0: sd-device-monitor: Received device does not pass filter, ignoring
KERNEL[99392.704357] remove   /devices/virtual/net/dummy0 (net)
ACTION=remove
DEVPATH=/devices/virtual/net/dummy0
SUBSYSTEM=net
INTERFACE=dummy0
IFINDEX=12
SEQNUM=6847

UDEV  [99392.715832] remove   /devices/virtual/net/dummy0 (net)
ACTION=remove
DEVPATH=/devices/virtual/net/dummy0
SUBSYSTEM=net
INTERFACE=dummy0
IFINDEX=12
SEQNUM=6847
USEC_INITIALIZED=99386759873
ID_NET_NAMING_SCHEME=v240
ID_MM_CANDIDATE=1
ID_NET_DRIVER=dummy
ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
SYSTEMD_ALIAS=/sys/subsystem/net/devices/dummy0
TAGS=:systemd:

関連情報