Sorry for the late (and long) answer...

On 23/01/2023 à 19:36, Oleg A. Arkhangelsky wrote:

I tried this *.deb (Pascal approach). It doesn't change behaviour
introduced after this patch [1]. Yes, restart for "allow-hotplug"
interfaces work but I got the same system boot lag in Jeff configuration.

In your reply to Jeff on 21/01/2023, you acknowledged it was correct behaviour. You get the same delay with an unplugged interface marked "auto". I suspect that using "allow-hotplug" instead may have been used as a workaround to hide the delay in the background. Not the best way to fix things IMO.

Cyril's latest solution seems to work. I just added "-" to /bin/sh to
deal with cases when we have a device that is really hotplug and absent:
(...)
I got fast boot (as without bad patch) and working restart. One minute
long blocking during `systemctl restart networking` when DHCP is not
respoding (as in Jeff config) is expected.

Right, but you can add --no-block to avoid the delay.

This delay is caused by dhclient which becomes a daemon only after acquiring an address or 1-minute time-out. A solution would be to run dhclient with the option -nw to become a daemon immediately. Why should ifup wait until an IP address is acquired ? dhclient and ifup return status 0 anyway.

udhcpc causes a shorter delay (10s) than dhclient, but it has no option to run in the background from the start.

I also had another idea: interfaces marked "allow-hotplug" are brought up by udev events, so why not restart them by replaying events with udevadm:

udevadm trigger --action=add --subsystem-match=net

First, a summary of relevant files in the ifupdown package:

/lib/systemd/system/networking.service:
ExecStart=/sbin/ifup -a --read-environment
ExecStop=/sbin/ifdown -a --read-environment --exclude=lo

/lib/udev/rules.d/80-ifupdown.rules:
SUBSYSTEM=="net", ACTION=="add|remove", RUN+="ifupdown-hotplug"

/lib/udev/ifupdown-hotplug:
TARGET_IFACE=$(/sbin/ifquery --allow hotplug -l "$INTERFACE")
systemctl --no-block start $(systemd-escape --template ifup@.service $TARGET_IFACE)

/lib/systemd/system/ifup@.service:
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
ExecStop=/sbin/ifdown %I

On net add events, udev runs ifupdown-hotplug which starts instantiated ifup@.service for interfaces marked "allow-hotplug".
ifup@.service configures interfaces marked "allow-hotplug".

Problem: when networking.service stops interfaces, it does not stop the instantiated ifup@*.service. The above udevadm command triggers ifupdown-hotplug as expected, but starting ifup@*service which are already started is a no-op so ifup is not run again and the interfaces stay down.

Is this on purpose ?

If no, the obvious fix is to stop all ifup@*.service when networking.service is stopped, so that they can be restarted by udev.
So I ended up adding these two lines in networking.service:

 ExecStart=udevadm trigger --action=add --subsystem-match=net
 ExecStop=systemctl --no-block stop ifup@*.service

Maybe there is a more elegant way to stop ifup@*.service, e.g. using systemd unit dependencies but I am not familiar enough with this topic.

This setup causes no delay when (re)starting networking.service by hand at boot time or by hand. However if an interface marked "allow-hotplug" was manually stopped with ifdown without stopping the associated ifup@.service, it is not restarted when restarting networking.service.

Any thoughts ?

Additional questions:

networking.service starts only interfaces marked "auto", so shouldn't it stop only those interfaces ?

Alternatively, interfaces marked "allow-hotplug" are started by udev even if networking.service is not started (not started yet, stopped, disabled). This brings a significant difference between interfaces marked "auto" and "allow-hotplug": interfaces marked "allow-hotplug" are started when booting in recovery mode while interfaces marked "auto" are started only when booting in normal mode (multi-user.target). Is it desirable ?

Reply via email to