Udev - 未捕获网络电缆热插拔事件

Udev - 未捕获网络电缆热插拔事件

我正在基于 Atmel Sama5d2 的定制板上运行 buildroot 定制 Linux(内核 4.9.87)。

我正在尝试仅在热插拔时使用 dhcp 在 eth0 接口上配置网络。

最初,该接口是在启动时使用auto eth0into配置的/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上获得一个 IP 地址。eth0

从这个结果来看,我认为问题不是来自网络配置,而是更多来自处理低级事件。

我尝试使用 udevadm 监视电缆的插入/拔出,但在插入和拔出电缆时看不到任何内核事件(但我可以看到来自 USB 子系统的事件)。

我还编写了一条 udev 规则来记录事件,以防 udevadm 未中继此子系统事件。

# 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。

您认为我可能缺少一些内核配置吗?

您认为可以在比使用 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替换为或或RUN+=".."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:

相关内容