Feature #915


Plugging in a wired network cable should restart networking, at least on eth0.

Added by Hammel over 1 year ago. Updated 10 months ago.

Start date:
30 Oct 2022
Due date:
% Done:


Estimated time:
01 - Critical


eth0 is configured for dhcp by default. If a cable is connected after boot then mdev should catch it and cause S40network to restart or at least ifup eth0.

Actions #1

Updated by Hammel over 1 year ago

  • Status changed from New to In Progress
  • % Done changed from 0 to 20

Apparently mdev doesn't monitor the ethernet interfaces for plug events.
There is a description of how to do this with scripts on stackexchange

That scripting option should be turned into a C program that uses inotify to watch the interface's operstate field and call ifup/ifdown on eth0. This will help reduce CPU overhead.

Note that this assumes we only have one eth port because none of the RPi's I'm using have more than one eth port. We will ignore USB eth dongles for now as those could probably be caught via mdev's usb script sometime in the future.

This tool should be added as a new package, so it won't be available in the dev platform.

Actions #2

Updated by Hammel over 1 year ago

I changed my mind - this should go in piboxd as a new thread. It's exactly what piboxd should be doing - managing the system low level features.

Actions #3

Updated by Hammel over 1 year ago

  • Project changed from PiBox to piboxd
  • Category deleted (06 - Hardware)
Actions #4

Updated by Hammel over 1 year ago

  • % Done changed from 20 to 30

inotify doesn't work on sysfs, at least as of 2014. GKH suggests using poll on those files instead.

I wrote it to use inotify and can verify that it doesn't work on sysfs. So I'll have to switch to using poll.

Actions #5

Updated by Hammel over 1 year ago

  • % Done changed from 30 to 60

poll() didn't work either. Every call to poll() immediately returned instead of waiting on the timeout or for event changes.

So I switched to a 2 second timer (like timer.c). This works, but then I found that using ifdown eth0 would make the carrier file disappear so I could no longer see plug events.

The eventual trick to this is to do the following:

  1. Test the carrier file for 0 (disconnected) or 1 (connected)
  2. On 0, kill pid found in /var/run/ (thats dhcp client for the port)
  3. On 1, kill same pid, then ifup -f eth0 to force dhcp restart.

Be certain to skip the kill if the pid is not valid. Also, this assumes that the network init script has already ifup'd all interfaces. That makes the carrier file in sysfs show up.

This works - I've tested it on hardware. And it doesn't kill ssh or X or anything else. It also doesn't use up excessive CPU (we're still sitting, on average, <1% cpu usage).

I need to test the following two scenarios to be certain.

  1. Boot without cable inserted. Then insert and check if ssh is accessible.
  2. Boot with cable inserted then pull it out. Wait more than a minute and plug it back in. Does ssh still respond?

These tests must first be run from a terminal on the device to check logs.
Then try it without the terminal (with updated piboxd installed to /usr/bin) and test from a remote host.

I don't really like this hack - it has the potential to leave multiple dhcp clients running - but it's faster to implement than trying to decipher the ifdown and ifup code in busybox.

Actions #6

Updated by Hammel over 1 year ago

This fails when you plug in a cable AFTER boot. It causes to die.

I think the way around this will be to examine the code in ifup and simply run udhcpd manually. Googling for the source (it's in Busybox's ifupdown.c) there is this structure:

static const struct dhcp_client_t ext_dhcp_clients[] = {
    { "dhcpcd",
        "dhcpcd[[ -h %hostname%]][[ -i %vendor%]][[ -I %client%]][[ -l %leasetime%]] %iface%",
        "dhcpcd -k %iface%",
    { "dhclient",
        "dhclient -pf /var/run/ %iface%",
        "kill -9 `cat /var/run/` 2>/dev/null",
    { "pump",
        "pump -i %iface%[[ -h %hostname%]][[ -l %leasehours%]]",
        "pump -i %iface% -k",
    { "udhcpc",
        "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/ -i %iface%[[ -x hostname:%hostname%]][[ -c %client%]]" 
                "[[ -s %script%]][[ %udhcpc_opts%]]",
        "kill `cat /var/run/` 2>/dev/null",

So it's easy to see what commands they use. I can simply use the same (but more limited for the more simplistic case) to start it.

However, it begs the question of whether ifup should be used in S40network then. What happens if S40network is manually restart without restarting piboxd? Will that cause any errors reading the carrier file from sysfs?

Actions #7

Updated by Hammel over 1 year ago

  • Status changed from In Progress to Closed
  • % Done changed from 60 to 100

Works correctly now after only down/up of dhcp client instead of the interface.

Code tested on hardware and passed.
Code committed and pushed.
Closing issue.

Actions #8

Updated by Hammel 11 months ago

  • Status changed from Closed to In Progress
  • % Done changed from 100 to 30
  • Severity changed from 02 - High to 01 - Critical

Re-opening this issue: Plugging in a cable to eth0 is not working on a piStore system. This may be related to the fact the piStore has been running unattended for some time (but not actually doing anything since no storage was attached to it).

Actions #9

Updated by Hammel 11 months ago

  • % Done changed from 30 to 60

This is likely due to pinet leaving the wlan configuration in place after NOT configuring wlan. In that situation eth0 is no longer in /etc/network/interfaces and so stops working.

Fix in pinet then retest with pibox cable plug/unplug events.

Actions #10

Updated by Hammel 10 months ago

  • Status changed from In Progress to Closed
  • % Done changed from 60 to 100

This just required an minor update to the interfaces.aponly template.

Fixed and tested on hardware.

Committed and pushed.

Closing issue.


Also available in: Atom PDF