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 ?