Search code examples
systemdudhcpc

Optimizing a systemd service taking too long


I have this udhcpc service in my system:

[Unit]
Description=uDHCP Client Service
After=network.target
Conflicts=systemd-resolved.service

[Service]
Type=forking
ExecStart=/sbin/udhcpc -p /var/run/udhcpc.brg0.pid -i brg0 -R -b
ExecStop=/bin/sh -c 'test -f /var/run/udhcpc.brg0.pid && kill $(cat /var/run/udhcpc.brg0.pid)'

[Install]
WantedBy=multi-user.target

It's been working well, except systemd-analyze is showing that it is adding about 7 seconds to the boot time:

          7.388s udhcpc.service
          4.946s dev-mmcblk1p2.device
          1.303s uim-sysfs.service
           959ms dev-mmcblk1p4.device
           752ms dev-mmcblk1p3.device
           739ms dev-mmcblk1p1.device
           718ms systemd-hwdb-update.service
           .
           .

And here is the output of systemd-analyze critical-chain:

multi-user.target @15.164s
[[0;1;31mudhcpc.service @7.773s +7.388s[[0m
  network.target @7.551s
    [[0;1;31msystemd-networkd.service @6.724s +668ms[[0m
      [[0;1;31msystemd-udevd.service @1.854s +87ms[[0m
        [[0;1;31msystemd-tmpfiles-setup-dev.service @1.662s +70ms[[0m
          [[0;1;31msystemd-sysusers.service @1.353s +229ms[[0m
            [[0;1;31msystemd-remount-fs.service @1.044s +238ms[[0m
              systemd-journald.socket @911ms
                -.slice @281ms

I suppose the right way to fix this is to avoid using udhcpc and stick to the mechanism built into systemd, but unfortunately that's not my call. I'd like to at least optimize the boot time though. What are some things I can do?


Solution

  • The "problem" is systemd-networkd, which stops the boot until the network is configured -- and this is what you want to replace, not systemd-resolved.

    Network autoconfiguration cannot be made any faster, because, when properly implemented, DHCP needs to check that the address isn't already in use, which involves sending a bunch of ARP packets and waiting for the timeout.

    Since you insert your service between "network is configured" and "multi-user boot is complete" targets, you introduce a dependency where there was none before.

    Network configuration is normally asynchronous, because any service that fails when the network is unconfigured at start would also fail when the network goes down later.