私はカスタム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.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-cat
してorRUN+=".."
またはecho
logger "..."
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: