web-dev-qa-db-ja.com

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

Atmel Sama5d2に基づくカスタムボードでbuildrootカスタムLinux(カーネル4.9.87)を実行しています。

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

元々、インターフェースは起動時に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は起動時に実行されず、Linuxの起動を30秒間ブロックしなくなります。

ただし、ケーブルを抜き差ししても何も起こりません。

手動でifup -aを実行すると、eth0インターフェイスでIPアドレスを取得します。

この結果から、問題の原因はネットワーク構成ではなく、低レベルのイベントの処理にあると思います。

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" 

ただし、このルールによってもトリガーされるものはありません。


そのため、現在、ネットワークケーブルのホットプラグの検出に問題があると思います。

カーネル構成の間違いとハードウェアの配線の間違いである可能性があります。

プラグ/アンプラグイベントがハードウェアレベルでどのように検出されるかはよくわかりませんが、イベントはドライバー自体によって直接、またはデプロイされている多数のカーネルフレームワークの1つによってudevに送信されると思います。

カーネル構成が不足していると思いますか?

devを使用するよりも低いレベルで状態ケーブルをトレースすることは可能だと思いますか?おそらくsysfsと直接インターフェースすることによって?

1
Arkaik

この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.sh systemdジャーナルにログを記録するスクリプト:

#!/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-catRUN+=".."を削除します。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:
3
raspi