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と直接インターフェースすることによって?
この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
のRUN+=".."
を削除します。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: