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하고 or 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:

관련 정보