1

I'm running a buildroot custom linux (kernel 4.9.87) on a custom board based on an Atmel Sama5d2.

I'm trying to configure the network on the eth0 interface using dhcp only at hotplug.

Originally, the interface was configured at boot using auto eth0 into /etc/network/interfaces

I changed it to allow-hotplug eth0 to have the following file

# cat /etc/network/interfaces 

auto lo
iface lo inet loopback

allow-hotplug eth0
iface eth0 inet dhcp

After this change, udhcpc is not run at boot and is not blocking linux boot for 30 seconds anymore if the cable is not plugged.

However, nothing happens when I plug or unplug the cable.

If I mannually run ifup -a I obtain an IP address on eth0 interface.

From this results, I don't think the problem comes from network configuration but more from handling low level events.

I've tried to monitor the plug/unplug of the cable using udevadm but I can't see any kernel event when I'm pluging and unpluging the cable (but I can see events from usb subsystem for example).

I have also written a udev rule to log events in case udevadm was not relaying this subsystem events.

# cat /etc/udev/rules.d/20-network.rules 
SUBSYSTEM=="net", ACTION=="add", RUN+="/test.sh add"
SUBSYSTEM=="net", ACTION=="remove" , RUN+="/test.sh remove" 

However, nothing is trigerred by this rule neither.


So right now I think I have an issue detecting network cable hotplug.

I could be a kernel configuration mistake as well as a hardware wiring mistake.

I don't really know how the plug/unplug event is detected at hardware level however I think that the event is sent to udev either directly by the driver itself or by one of the numerous kernel frameworks in which it's deployed.

Do you think I may be missing some kernel configuration ?

Do you think it's possible to trace the state cable at a lower level than using udev ? Maybe by directly interfacing with sysfs ?

  • Does ifconfig show your cable connect/disconnect status? What about ethtool? – Stephen Kitt Feb 27 at 13:21
0

This udev rule and script catches network interface changes:

/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 script which logs to systemd journal:

#!/bin/bash -e

action=$1
ifname=$2
id=$3
syspath=$4

echo "Network interface $ifname ($id) $action"
printenv

It can be tested without reboot with:

udevadm control --reload-rules && udevadm -d trigger -v --type devices --subsystem-match net

and then seeing the log with journalctl -xe.

If you're not running with systemd:

Remove /usr/bin/systemd-cat in RUN+=".." Replace echo with logger "..." or echo "stuff" > /dev/kmsg or other method used by your distro

Additionally you can see log events with adding dummy interface:

# ip link add dummy0 type dummy
# ip link set dummy0 up
# ip link set dummy0 down
# ip link delete dummy0

Also you can find lots of information about interface with udevadm for example:

# 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==""

These link to sys files:

# cat /sys/class/net/eno1/operstate 
up

udevadm monitor can also be used:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.