2

The Issue

I am reading this systemd documentation

I have the following files:

/usr/lib/systemd/network/80-wired.network

[Match]
eth0
[Network]
Address=192.168.3.40/22
Gateway=192.168.0.1

/usr/lib/systemd/network/80-wired.network.d/00-mod.conf

[Network]
Address=192.168.3.49/22
Gateway=192.168.0.1

The drop-in file is not overriding the network settings:

root# ip route show dev eth0
default via 192.168.0.1 proto static
192.168.0.0/22 proto kernel scope link src 192.168.3.40

What I tried

I am trying the following:

  1. modifying the drop-in, or the main config
  2. systemctl restart systemd-networkd
  3. ip route show dev eth0

I have tried resetting the Address/Gateway first by "assigning an empty string" as per the documentation:

/usr/lib/systemd/network/80-wired.network.d/00-mod.conf

[Network]
Address=
Gateway=
Address=192.168.3.49/22
Gateway=192.168.0.1

But this results in errors being printed in journalctl, and has no effect on the actually reported network configuration

Nov 12 16:40:12 sama5d27-som1-ek-sd systemd-networkd[818]: /usr/lib/systemd/network/80-wired.network:5: Invalid address '', ignoring assignment: Invalid argument
Nov 12 16:40:12 sama5d27-som1-ek-sd systemd-networkd[818]: /usr/lib/systemd/network/80-wired.network:6: Invalid Gateway='', ignoring assignment: Invalid argument

If I remove the address and Gateway from the main config, the values are correctly picked up from the drop-in, so I know the file is parsed and used.

I have tried all permutations of [Route] [Address] [Network], where the main config defines the vairables under route and address say, and the drop-in uses network , and vice versa.

If I specify a different Gateway in the drop-in, I see two gateways:

root# ip route show dev eth0
default via 192.168.0.1 proto static
default via 192.168.0.2 proto static
192.168.0.0/22 proto kernel scope link src 192.168.3.40

This leads me to think that the real issue is that I am unable to clear the original values before setting them anew, the docs say "empty sting", so I've tried:

# Truly empty
Address=
Address=\0
Address=""
Address=''
#This one has a space
Address= 
# this one is followed by an empty new-line
Address=

Am I missing some trick to this? Is it a bug?

Version info

root@sama5d27-som1-ek-sd:/usr/lib/systemd/network# networkctl --version
systemd 255 (255.4^)
-PAM -AUDIT -SELINUX -APPARMOR -IMA -SMACK -SECCOMP -GCRYPT -GNUTLS -OPENSSL +ACL +BLKID -CURL -ELFUTILS -FIDO2 -IDN2 -IDN -IPTC +KMOD -LIBCRYPTSETUP +LIBFDISK -PCRE2 -PWQUALITY -P11KIT -QRENCODE -TPM2 -BZIP2 -LZ4 -XZ -ZLIB +ZSTD -BPF_FRAMEWORK -XKBCOMMON -UTMP -SYSVINIT default-hierarchy=unified
root@sama5d27-som1-ek-sd:/usr/lib/systemd/network# cat /etc/os-release
ID=poky-atmel
NAME="Poky (Yocto Project Reference Distro)"
VERSION="5.0.3 (scarthgap)"
VERSION_ID=5.0.3
VERSION_CODENAME="scarthgap"
PRETTY_NAME="Poky (Yocto Project Reference Distro) 5.0.3 (scarthgap)"
CPE_NAME="cpe:/o:openembedded:poky-atmel:5.0.3"

Documentation that is pertinent

Under the Description section

  Along with the network file foo.network, a "drop-in" directory
  foo.network.d/ may exist. All files with the suffix ".conf" from
  this directory will be merged in the alphanumeric order and parsed
  after the main file itself has been parsed. This is useful to
  alter or add configuration settings, without having to modify the
  main configuration file. Each drop-in file must have appropriate
  section headers.

Under the [Network] section:

   Address=
      A static IPv4 or IPv6 address and its prefix length, separated
      by a "/" character. Specify this key more than once to
      configure several addresses. The format of the address must be
      as described in inet_pton(3). This is a short-hand for an
      [Address] section only containing an Address key (see below).
      This option may be specified more than once.

      If the specified address is "0.0.0.0" (for IPv4) or "::" (for
      IPv6), a new address range of the requested size is
      automatically allocated from a system-wide pool of unused
      ranges. Note that the prefix length must be equal or larger
      than 8 for IPv4, and 64 for IPv6. The allocated range is
      checked against all current network interfaces and all known
      network configuration files to avoid address range conflicts.
      The default system-wide pool consists of 192.168.0.0/16,
      172.16.0.0/12 and 10.0.0.0/8 for IPv4, and fd00::/8 for IPv6.
      This functionality is useful to manage a large number of
      dynamically created network interfaces with the same network
      configuration and automatic address range assignment.

      If an IPv4 link-local address (169.254.0.0/16) is specified,
      IPv4 Address Conflict Detection (RFC 5227[8]) is enabled for
      the address. To assign an IPv4 link-local address without IPv4
      Address Conflict Detection, please use [Address] section to
      configure the address and disable DuplicateAddressDetection=.

          [Address]
          Address=169.254.10.1/24
          DuplicateAddressDetection=none

      If an empty string is specified, then the all previous
      assignments in both [Network] and [Address] sections are
      cleared.

      Added in version 211.

  Gateway=
      The gateway address, which must be in the format described in
      inet_pton(3). This is a short-hand for a [Route] section only
      containing a Gateway= key. This option may be specified more
      than once.

      Added in version 211.
2
  • I assume one of those config examples was supposed to say Gateway=192.168.0.2 instead of .1? Commented Nov 12 at 18:02
  • @grawity Yes, the idea was to replace, not append Commented Nov 13 at 9:56

1 Answer 1

2

Not all config parsers in systemd support Key= to unset old values – it is mostly handled by ad-hoc code for each value, rather than being generic at syntax level. In networkd it's generally just not implemented. (Just as e.g. in .service units it is not possible to unset After= for technical reasons.)

If you don't want to use the distribution-provided 80-wired.network, you can override it in two ways:

  • Create an 80-wired.network in /etc/systemd/network. /usr/lib is for the distribution and /etc is where admin configuration is placed; a file in the latter fully overrides an identically-named file in the former.

    This is the same as overriding .service unit files.

  • Create a different .network file that matches the same interfaces and give it a name that sorts before the original name (in ASCII order), e.g. call it 79-wired.network or 50-eth0.network instead.

    This method is specific to "match"-style configurations, such as .network or .link files, where files specify criteria inside and the first matching file wins.

Both methods are meant for the "admin" providing the configuration. If you are the "distribution" (which I suppose might be the case when building stuff with Yocto), then simply don't ship the unwanted 80-wired.network in the first place.


Other options:

  • Put the default address in the drop-in instead of the main file. Have the installer/updater generate a fresh 'generic' drop-in whenever it doesn't exist yet (e.g. you could use systemd-tmpfiles.d's /usr/share/factory/etc for this purpose), and if it already exists then don't touch it again.

  • Alternatively, store the configuration somewhere else entirely, and generate drop-ins in /run before each service startup (similar to how systemd generators work) – e.g. that's what Netplan does on Ubuntu. Then the default could be implemented as part of the generator's code.

5
  • The aim is to have a base network file that defines a good default, and other necessary networking components, and allow the user to specify custom a IP, in a way that isn't trashed if we issue an update to the main networking file. Drop-ins seemed the ideal, and intended way, to do that, but I guess I'll have to hack something custom into our updater that can preserve a custom IP, and just modify the base-file, thanks for your help. Commented Nov 13 at 10:00
  • Weird that the docs explicitly say to unset the IP, to set it to an empty string, but then not actually support it. Commented Nov 13 at 10:01
  • 1
    Might be a bug (either in docs or in code); report it on systemd's GitHub. Commented Nov 13 at 10:01
  • 1
    If your updater already has a way to ignore the drop-ins, then I'd have the installer/updater generate a fresh 'generic' drop-in if it's missing outright (e.g. you could copy it using systemd's "/usr/share/factory/etc" facility), but still not touch it on upgrades. Alternatively, store the configuration somewhere else entirely, and generate drop-ins in /run before each service startup (similar to how systemd generators work) – e.g. that's what Netplan does on Ubuntu. Commented Nov 13 at 10:02
  • 1
    great point, if the ip and gateway are in the dropin at time of distribution, the sw can replace/modify the dropin at will, and be safe during an update, which might replace the base networking file, but not the drop-in, thanks Commented Nov 13 at 10:04

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.