systemd-networkd
systemd-networkd is a system daemon that manages network configurations. It detects and configures network devices as they appear; it can also create virtual network devices. This service can be especially useful to set up complex network configurations for a container managed by systemd-nspawn or for virtual machines. It also works fine on simple connections.
Basic usage
The systemd package is part of the default Arch installation and contains all needed files to operate a wired network. Wireless adapters, covered later in this article, can be set up by services, such as wpa_supplicant or iwd.
Required services and setup
To use systemd-networkd, start/enable systemd-networkd.service
.
systemctl --type=service
and then stop them.It is optional to also configure systemd-resolved, which is a network name resolution service to local applications, considering the following points:
- It is important to understand how resolv.conf and systemd-resolved interact to properly configure the DNS that will be used, some explanations are provided in systemd-resolved.
- systemd-resolved is required if DNS entries are specified in .network files.
-
systemd-resolved is also required to obtain DNS addresses from DHCP servers or IPv6 router advertisements.
(by setting (DHCP=
and/orIPv6AcceptRA=
in the[Network]
section, andUseDNS=yes
(the default) in the corresponding section(s)[DHCPv4]
,[DHCPv6]
,[IPv6AcceptRA]
, see systemd.network(5)). - Note that systemd-resolved can also be used without systemd-networkd.
systemd-networkd-wait-online
Enabling systemd-networkd.service
also enables systemd-networkd-wait-online.service
, which is a oneshot system service that waits for the network to be configured. The latter has WantedBy=network-online.target
, so it will be started only when network-online.target
itself is enabled or pulled in by some other unit. See also systemd#Running services after the network is up.
By default, systemd-networkd-wait-online.service
waits for all links managed by systemd-networkd to be fully configured or failed, and for at least one link to be online.
For system with multiple network interfaces that are not expected to be connected all the time (e.g. if a dual-port Ethernet card, but only one cable plugged in), starting systemd-networkd-wait-online.service
will fail after the default timeout of 2 minutes. This may cause an unwanted delay in the startup process. To change the behaviour to wait for any interface rather than all interfaces to become online, edit the service and add the --any
parameter to the ExecStart
line:
/etc/systemd/system/systemd-networkd-wait-online.service.d/wait-for-only-one-interface.conf
[Service] ExecStart= ExecStart=/usr/lib/systemd/systemd-networkd-wait-online --any
Alternatively, use systemd-networkd-wait-online@.service
to wait for a specific interface. For example, to wait for enp1s0
, disable systemd-networkd-wait-online.service
and enable systemd-networkd-wait-online@enp1s0.service
.
See systemd-networkd-wait-online(8) for details.
Configuration examples
All configurations in this section are stored as foo.network
in /etc/systemd/network/
. For a full listing of options and processing order, see #Configuration files and systemd.network(5).
systemd/udev automatically assigns predictable, stable network interface names for all local Ethernet, WLAN, and WWAN interfaces. Use networkctl list
to list the devices on the system. If it is desired to divert from the automatic interface naming, see Network configuration#Change interface name for examples.
After making changes to a configuration file, restart systemd-networkd.service
.
- The options specified in the configuration files are case sensitive.
- In the examples below,
enp1s0
is the wired adapter andwlp2s0
is the wireless adapter. These names can be different on different systems. See Network configuration#Network interfaces for checking your adapter names. - It is also possible to use a wildcard, e.g.
Name=en*
orName=wl*
. - Devices can also be matched by their type. E.g.
Type=ether
for Ethernet,Type=wlan
for Wi-Fi andType=wwan
for WWAN. - Note that
Type=ether
will also match virtual Ethernet interfaces. To exclude them, useType=ether
in combination withKind=!*
. - To disable IPv6, see IPv6#systemd-networkd.
Wired adapter using DHCP
/etc/systemd/network/20-wired.network
[Match] Name=enp1s0 [Network] DHCP=yes
Wired adapter using a static IP
/etc/systemd/network/20-wired.network
[Match] Name=enp1s0 [Network] Address=10.1.10.9/24 Gateway=10.1.10.1 DNS=10.1.10.1
Address=
can be used more than once to configure multiple IPv4 or IPv6 addresses. See #network files or systemd.network(5) for more options.
Wireless adapter
In order to connect to a wireless network with systemd-networkd, a wireless adapter configured with another application such as wpa_supplicant or iwd is required.
/etc/systemd/network/25-wireless.network
[Match] Name=wlp2s0 [Network] DHCP=yes IgnoreCarrierLoss=3s
If the wireless adapter has a static IP address, the configuration is the same (except for the interface name) as in a wired adapter.
IgnoreCarrierLoss=3s
ensures that systemd-networkd will not re-configure the interface (e.g., release and re-acquire a DHCP lease) for a short period (3 seconds in this example) while the wireless interface roams to another access point within the same wireless network (SSID), which translates to shorter downtime when roaming.To authenticate to the wireless network, use e.g. wpa_supplicant or iwd.
Wired and wireless adapters on the same machine
This setup will enable a DHCP IP for both a wired and wireless connection making use of the metric directive to allow the kernel to decide on-the-fly which one to use. This way, no connection downtime is observed when the wired connection is unplugged.
The kernel's route metric (same as configured with ip) decides which route to use for outgoing packets, in cases when several match. This will be the case when both wireless and wired devices on the system have active connections. To break the tie, the kernel uses the metric. If one of the connections is terminated, the other automatically wins without there being a gap with nothing configured (ongoing transfers may still not deal with this nicely but that is at a different OSI layer).
systemd-networkd does not set per-interface-type default route metrics, so it needs to be configured manually:
Metric
option is for static routes while the RouteMetric
option is for setups not using static routes. See systemd.network(5) for more details./etc/systemd/network/20-wired.network
[Match] Name=enp1s0 [Network] DHCP=yes [DHCPv4] RouteMetric=100 [IPv6AcceptRA] RouteMetric=100
/etc/systemd/network/25-wireless.network
[Match] Name=wlp2s0 [Network] DHCP=yes [DHCPv4] RouteMetric=600 [IPv6AcceptRA] RouteMetric=600
Configuration files
The global configuration file in /etc/systemd/networkd.conf
may be used to override some defaults only. The main configuration is performed per network device. Configuration files are located in /usr/lib/systemd/network/
, the volatile runtime network directory /run/systemd/network/
and the local administration network directory /etc/systemd/network/
. Files in /etc/systemd/network/
have the highest priority.
There are three types of configuration files. They all use a format similar to systemd unit files.
- .network files. They will apply a network configuration for a matching device
- .netdev files. They will create a virtual network device for a matching environment
- .link files. When a network device appears, udev will look for the first matching .link file
They all follow the same rules:
- If all conditions in the
[Match]
section are matched, the profile will be activated - an empty
[Match]
section means the profile will apply in any case (can be compared to the*
wildcard) - all configuration files are collectively sorted and processed in lexical order, regardless of the directory in which they live
- files with identical name replace each other
- Files in
/etc/systemd/network/
override the corresponding system-supplied file in/usr/lib/systemd/network/
. Optionally use a symlink to/dev/null
to "mask" a system file. - systemd accepts the values
1
,true
,yes
,on
for a true boolean, and the values0
,false
,no
,off
for a false boolean. See systemd.syntax(7). - systemd-networkd will alter routing tables also for other network software. If this is undesired, configure
ManageForeignRoutingPolicyRules=
in networkd.conf(5) accordingly. For example, see WireGuard#Connection lost after sleep using systemd-networkd.
network files
These files are aimed at setting network configuration variables, especially for servers and containers.
.network files have the following sections: [Match]
, [Link]
, [Network]
, [Address]
, [Route]
, and [DHCPv4]
. Below are commonly configured keys for each section. See systemd.network(5) for more information and examples.
[Match]
Parameter | Description | Accepted Values | Default Value |
---|---|---|---|
Name= |
Match device names, e.g. en* . By prefixing with ! , the list can be inverted. |
white-space separated device names with globs, logical negation (! ) |
|
MACAddress= |
Match MAC addresses, e.g. MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF
|
whitespace-separated MAC addresses in full colon-, hyphen- or dot-delimited hexadecimal | |
Host= |
Match the hostname or machine ID of the host. | hostname string with globs, machine-id(5) | |
Virtualization= |
Check whether the system is executed in a virtualized environment. Virtualization=false will only match your host machine, while Virtualization=true matches any container or VM. It is possible to check for a specific virtualization type or implementation, or for a user namespace (with private-users ). |
boolean, logical negation (! ), type (vm , container ), implementation (see systemd-detect-virt(1)), private-users
|
[Link]
Parameter | Description | Accepted Values | Default Value |
---|---|---|---|
MACAddress= |
Assign a hardware address to the device. Useful for MAC address spoofing. | full colon-, hyphen- or dot-delimited hexadecimal MAC addresses | |
MTUBytes= |
Maximum transmission unit in bytes to set for the device. Note that if IPv6 is enabled on the interface, and the MTU is chosen below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value. Setting a larger MTU value (e.g. when using jumbo frames) can significantly speed up your network transfers | integer (usual suffixes K, M, G, are supported and are understood to the base of 1024) | |
Multicast= |
allows the usage of multicast | boolean | ? not documented ? |
[Network]
Parameter | Description | Accepted Values | Default Value |
---|---|---|---|
DHCP= |
Controls DHCPv4 and/or DHCPv6 client support. | boolean, ipv4 , ipv6
|
no
|
DHCPServer= |
If enabled, a DHCPv4 server will be started. | boolean |
no
|
MulticastDNS= |
Enables multicast DNS support. When set to resolve , only resolution is enabled, but not host or service registration and announcement. |
boolean, resolve
|
false
|
DNSSEC= |
Controls DNSSEC DNS validation support on the link. When set to allow-downgrade , compatibility with non-DNSSEC capable networks is increased, by automatically turning off DNSSEC in this case. |
boolean, allow-downgrade
|
false
|
DNS= |
Configure static DNS addresses. May be specified more than once. | inet_pton(3) | |
Domains= |
A list of domains which should be resolved using the DNS servers on this link. systemd.network(5) § [NETWORK] SECTION OPTIONS | domain name, optionally prefixed with a tilde (~ ) |
|
IPv4Forwarding= and IPv6Forwarding=
|
If enabled, incoming (IPv4 / IPv6) packets on this network interface will be forwarded to any other interfaces according to the routing table. This controls the net.ipv4/6.conf.INTERFACE.forwarding sysctl option of the network interface. See Internet sharing#Enable packet forwarding for details. |
boolean |
no
|
IPMasquerade= |
If enabled, packets forwarded from the network interface will appear as coming from the local host. Depending on the value, implies IPv6Forwarding=yes or IPv4Forwarding=yes . |
ipv4 , ipv6 , both , no
|
no
|
IPv6PrivacyExtensions= |
Configures use of stateless temporary addresses that change over time (see RFC 4941). When prefer-public , enables the privacy extensions, but prefers public addresses over temporary addresses. When kernel , the kernel's default setting will be left in place. |
boolean, prefer-public , kernel
|
no
|
[Address]
Parameter | Description | Accepted Values | Default Value |
---|---|---|---|
Address= |
Specify this key more than once to configure several addresses. Mandatory unless DHCP is used. 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. |
static IPv4 or IPv6 address and its prefix length (see inet_pton(3)) |
[Route]
-
Gateway=
this option is mandatory unless direct routing or DHCP is used -
Destination=
the destination prefix of the route, possibly followed by a slash and the prefix length -
Metrics=
the priority of this route -
Type=
the type for the route -
Table=
the table identifier for the route -
GatewayOnLink=
if set toyes
, the kernel does not have to check if the gateway is reachable directly by the current machine (i.e., attached to the local network). Can be used to solve some routing issues.
If Destination
is not present in [Route]
section, this section is treated as a default route.
Address=
and Gateway=
keys in the [Network]
section as a short-hand if [Address]
section contains only an Address
key and [Route]
section contains only a Gateway
key.[RoutingPolicyRule]
Standard routing algorithms usually take in account only the destination address when they have to choose to which gateway send a packet. But for more complex networks this is not enough.
The [RoutingPolicyRule]
section allows you to specify additional rules that are applied only to those packages that match the specified conditions.
Here a non-exhaustive list of these matches:
-
TypeOfService=
(matches) the Type of Service of the packet as an integer in the range0..255
; -
From=
the source address prefix; -
To=
the destination address prefix; -
FirewallMark=
the iptables firewall mark value; -
IncomingInterface=
the incoming device; -
OutgoingInterface=
the outgoing device;
Other options:
-
Type=
the Routing Policy Database rule type; -
Table=
the routing table to use if the packet matches the rule; -
Priority=
the priority of this rule. Rules are evaluated in increasing order of priority, therefore lower priority rules are applied before others; -
InvertRule=
if set totrue
then the rule is inverted, that is it is applied to every package that doesn't satisfy at least one of the matches; -
SuppressPrefixLength=
the rule is suppressed if the prefix length is equal or less than the specified value;
[DHCPv4]
Parameter | Description | Accepted Values | Default Value |
---|---|---|---|
UseDNS= |
controls whether the DNS servers advertised by the DHCP server are used | boolean |
true
|
Anonymize= |
when true, the options sent to the DHCP server will follow the RFC:7844 (Anonymity Profiles for DHCP Clients) to minimize disclosure of identifying information | boolean |
false
|
UseDomains= |
controls whether the domain name received from the DHCP server will be used as DNS search domain. If set to route , the domain name received from the DHCP server will be used for routing DNS queries only, but not for searching. This option can sometimes fix local name resolving when using systemd-resolved
|
boolean, route
|
false
|
IPv6OnlyMode= |
when true, the DHCP client will signal to the DHCP server that it supports IPv6-only operation (RFC:8925, IPv6-Only Preferred Option for DHCPv4). If the DHCPv4 server returns that option in its DHCP response, the client will abort the DHCP request, will not acquire an IPv4 address and will configure an IPv6-only network | boolean |
true if IPv6 is enabled
|
[DHCPServer]
This is an example of a DHCP server configuration which works well with hostapd to create a wireless hotspot. IPMasquerade
adds the firewall rules for NAT and implies IPv4Forwarding=yes
to enable packet forwarding.
/etc/systemd/network/wlan0.network
[Match] Name=wlan0 [Network] Address=10.1.1.1/24 DHCPServer=true IPMasquerade=ipv4 [DHCPServer] PoolOffset=100 PoolSize=20 EmitDNS=yes DNS=9.9.9.9
netdev files
These files will create virtual network devices. They have two sections: [Match]
and [NetDev]
. Below are commonly configured keys for each section. See systemd.netdev(5) for more information and examples.
[Match] section
-
Host=
the hostname -
Virtualization=
check if the system is running in a virtualized environment
[NetDev] section
Most common keys are:
-
Name=
the interface name. mandatory -
Kind=
e.g. bridge, bond, vlan, veth, sit, etc. mandatory
Usage with containers
systemd-networkd can provide fully automatic configuration of networking for systemd-nspawn containers when it is used on the host system as well as inside the container. See systemd-nspawn#Networking for a comprehensive overview.
For the examples below,
- we will limit the output of the
ip a
command to the concerned interfaces, - we assume the host is the main operating system running on real hardware and the container is the guest system,
- all interface names and IP addresses are only examples.
Network bridge with DHCP
Bridge interface
First, create a virtual bridge interface with a .netdev unit file which tells systemd-networkd to create a device named br0
that functions as an Ethernet bridge.
/etc/systemd/network/25-br0.netdev
[NetDev] Name=br0 Kind=bridge
Optionally add MACAddress=none
to the NetDev
section for the bridge to inherit MAC address from one of the bridged interfaces. This also requires a creation of 25-br0.link file.
MACAddress=xx:xx:xx:xx:xx:xx
in the NetDev
section above.Restart systemd-networkd.service
to have systemd-networkd create the bridge.
To see the newly created bridge on the host and on the container, type:
$ ip a
3: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default link/ether ae:bd:35:ea:0c:c9 brd ff:ff:ff:ff:ff:ff
Note that the interface br0
is listed but is still DOWN at this stage.
Bind Ethernet to bridge
The next step is to add a network interface to the newly created bridge. The configuration file of the bridge must be loaded before those of the bridged interfaces, so its configuration file should be alphanumerically prior to those. In the example below, we add any interface that matches the name en*
into the bridge br0
.
/etc/systemd/network/25-br0-en.network
[Match] Name=en* [Network] Bridge=br0
The Ethernet interface must not have DHCP or an IP address associated, as the bridge requires an interface to bind to with no IP address.
Name=en*
. Only the first file that matches an interface is applied.Bridge network
Now that the bridge has been created and has been bound to an existing network interface, the IP configuration of the bridge interface must be specified. This is defined in a third .network file, the example below uses DHCP.
/etc/systemd/network/25-br0.network
[Match] Name=br0 [Network] DHCP=yes
Inherit MAC address (optional)
For the bridge to inhering MAC address from one of the bridged interfaces, set MACAddress=none
and MACAddressPolicy=none
.
/etc/systemd/network/25-br0.netdev
[NetDev] Name=br0 Kind=bridge MACAddress=none
/etc/systemd/network/25-br0.link
[Match] OriginalName=br0 [Link] MACAddressPolicy=none
Configure the container
Use the --network-bridge=br0
option when starting the container. See systemd-nspawn#Use a network bridge for details.
Result
- on host
$ ip a
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 14:da:e9:b5:7a:88 brd ff:ff:ff:ff:ff:ff inet 192.168.1.87/24 brd 192.168.1.255 scope global br0 valid_lft forever preferred_lft forever inet6 fe80::16da:e9ff:feb5:7a88/64 scope link valid_lft forever preferred_lft forever 6: vb-MyContainer: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000 link/ether d2:7c:97:97:37:25 brd ff:ff:ff:ff:ff:ff inet6 fe80::d07c:97ff:fe97:3725/64 scope link valid_lft forever preferred_lft forever
- on container
$ ip a
2: host0: <BROADCAST,MULTICAST,ALLMULTI,AUTOMEDIA,NOTRAILERS,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 5e:96:85:83:a8:5d brd ff:ff:ff:ff:ff:ff inet 192.168.1.73/24 brd 192.168.1.255 scope global host0 valid_lft forever preferred_lft forever inet6 fe80::5c96:85ff:fe83:a85d/64 scope link valid_lft forever preferred_lft forever
Notice
- we have now one IP address for
br0
on the host, and one forhost0
in the container - two new interfaces have appeared:
vb-MyContainer
in the host andhost0
in the container. This comes as a result of the--network-bridge=br0
option as explained in systemd-nspawn#Use a network bridge for details. - the DHCP address on
host0
comes from the system/usr/lib/systemd/network/80-container-host0.network
file. - on host
$ brctl show
bridge name bridge id STP enabled interfaces br0 8000.14dae9b57a88 no enp7s0 vb-MyContainer
the above command output confirms we have a bridge with two interfaces binded to.
- on host
$ ip route
default via 192.168.1.254 dev br0 192.168.1.0/24 dev br0 proto kernel scope link src 192.168.1.87
- on container
$ ip route
default via 192.168.1.254 dev host0 192.168.1.0/24 dev host0 proto kernel scope link src 192.168.1.73
the above command outputs confirm we have activated br0
and host0
interfaces with an IP address and Gateway 192.168.1.254. The gateway address has been automatically grabbed by systemd-networkd.
Network bridge with static IP addresses
Setting a static IP address for each device can be helpful in case of deployed web services (e.g FTP, http, SSH). Each device will keep the same MAC address across reboots if your system /usr/lib/systemd/network/99-default.link
file has the MACAddressPolicy=persistent
option (it has by default). This setup routes any service on the gateway to the desired device.
The following configuration needs to be done for this setup:
- on host
The configuration is very similar to the #Network bridge with DHCP section. First, a virtual bridge interface needs to be created and the main physical interface needs to be bound to it. This task can be accomplished with the following two files, with contents equal to those available in the DHCP section.
/etc/systemd/network/MyBridge.netdev /etc/systemd/network/MyEth.network
Next, you need to configure the IP and DNS of the newly created virtual bridge interface. For example:
/etc/systemd/network/MyBridge.network
[Match] Name=br0 [Network] DNS=192.168.1.254 Address=192.168.1.87/24 Gateway=192.168.1.254
- on container
To get configure a static IP address on the container, we need to override the system /usr/lib/systemd/network/80-container-host0.network
file, which provides a DHCP configuration for the host0
network interface of the container. This can be done by placing the configuration into /etc/systemd/network/80-container-host0.network
. For example:
/etc/systemd/network/80-container-host0.network
[Match] Name=host0 [Network] DNS=192.168.1.254 Address=192.168.1.94/24 Gateway=192.168.1.254
Make sure that systemd-networkd.service
is enabled in the container.
MACVLAN bridge
For the host to be able to reach containers connected via MACVLAN, the host itself also needs to connect via MACVLAN and not directly to the underlying Ethernet network interface.
On the host, attach the underlying Ethernet network interface to MACVLAN and make sure it does not get assigned IP addresses. For example, using mv-0
as the MACVLAN interface name and with enp1s0
as the host's Ethernet interface:
/etc/systemd/network/30-enp1s0.network
[Match] Name=enp1s0 [Link] RequiredForOnline=carrier [Network] MACVLAN=mv-0 DHCP=no IPv6AcceptRA=false LinkLocalAddressing=no MulticastDNS=false LLMNR=false
-
RequiredForOnline=carrier
prevents systemd-networkd-wait-online.service from waiting (and eventually failing) for the connection to acquire an IP address, which will never happen. - The underlying network interface does not necessarily need to be a physical Ethernet interface. For example, a MACVLAN bridge can be attached to a bond.
Create the MACVLAN bridge mv-0
:
/etc/systemd/network/25-mv-0.netdev
[NetDev] Name=mv-0 Kind=macvlan [MACVLAN] Mode=bridge
Configure the host's network connection on the MACVLAN bridge (mv-0
). The following example uses DHCP, replace the options as necessary.
/etc/systemd/network/35-mv-0.network
[Match] Name=mv-0 [Link] RequiredForOnline=routable [Network] BindCarrier=enp1s0 DHCP=yes
For the container, attach a MACVLAN to the underlying Ethernet network interface (enp1s0
in the examples above). For example, in /etc/systemd/nspawn/container_name.nspawn
specify:
[Network] MACVLAN=enp1s0
For containers started from the command line, pass them the --network-macvlan=enp1s0
option.
In the container, the MACVLAN interface will have the name mv-underlying_interface_name
(e.g. mv-enp1s0
). Configure the network connection as necessary (just like in the host) by matching the interface name. For example, using DHCP:
/etc/systemd/network/30-mv-enp1s0.network
[Match] Name=mv-enp1s0 [Link] RequiredForOnline=routable [Network] DHCP=yes
Tips and tricks
Interface and desktop integration
systemd-networkd does not have a proper interactive graphical management interface. Still, some tools are available to either display or modify the current state of the network, receive notifications or interact with the wireless configuration:
-
networkctl provides a command-line shell interface to query or modify the network interface states. It is worth noting that in order to change only some aspects of an interface behavior, one is required to first edit one or more configuration files in
/etc/systemd/network/
. - When networkd is configured with wpa_supplicant, both wpa_cli and wpa_gui offer the ability to associate and configure WLAN interfaces dynamically.
- The networkd-dispatcherAUR daemon allows executing scripts in response to network interface state changes, similar to NetworkManager-dispatcher.
- As for the DNS resolver systemd-resolved, information about current DNS servers can be visualized with
resolvectl status
.
Configuring static IP or DHCP based on SSID (location)
Often there is a situation where your home wireless network uses DHCP and office wireless network uses static IP. This mixed setup can be configured as follows:
/etc/systemd/network/24-wireless-office.network
# special configuration for office WiFi network [Match] Name=wlp2s0 SSID=office_ap_name #BSSID=aa:bb:cc:dd:ee:ff [Network] Address=10.1.10.9/24 Gateway=10.1.10.1 DNS=10.1.10.1 #DNS=8.8.8.8
/etc/systemd/network/25-wireless-dhcp.network
# use DHCP for any other WiFi network [Match] Name=wlp2s0 [Network] DHCP=yes
Bonding a wired and wireless interface
See also Wireless bonding.
Bonding allows connection sharing through multiple interfaces, so if e.g. the wired interface is unplugged, the wireless is still connected and the network connectivity remains up seamlessly.
Create a bond interface. In this case the mode is active-backup, which means packets are routed through a secondary interface if the primary interface goes down.
/etc/systemd/network/30-bond0.netdev
[NetDev] Name=bond0 Kind=bond [Bond] Mode=active-backup PrimaryReselectPolicy=always MIIMonitorSec=1s
Set the wired interface as the primary:
/etc/systemd/network/30-ethernet-bond0.network
[Match] Name=enp0s25 [Network] Bond=bond0 PrimarySlave=true
Set the wireless as the secondary:
/etc/systemd/network/30-wifi-bond0.network
[Match] Name=wlan0 [Network] Bond=bond0
[Match]
section, use of PermanentMACAddress
is recommended over MACAddress
, see this upstream discussion.Configure the bond interface just like a normal interface:
/etc/systemd/network/30-bond0.network
[Match] Name=bond0 [Network] BindCarrier=enp0s25 wlan0 DHCP=yes
Now if the wired network is unplugged, the connection should remain through the wireless:
$ networkctl
IDX LINK TYPE OPERATIONAL SETUP 1 lo loopback carrier unmanaged 2 enp0s25 ether no-carrier configured 3 bond0 bond degraded-carrier configured 5 wlan0 wlan enslaved configured 4 links listed.
Speeding up TCP slow-start
On a higher bandwidth link with moderate latency (typically a home Internet connection that is above 10 Mbit/s) the default settings for the TCP Slow Start algorithm are somewhat conservative. This issue exhibits as downloads starting slowly and taking a number of seconds to speed up before they reach the connection's full bandwidth. It is particularly noticeable with a pacman upgrade, where each package downloaded starts off slowly and often finishes before it has reached the connection's full speed.
These settings can be adjusted to make TCP connections start with larger window sizes than the defaults, avoiding the time it takes for them to automatically increase on each new TCP connection[1]. While this will usually decrease performance on slow connections (or if the values are increased too far) due to having to retransmit a larger number of lost packets, they can substantially increase performance on connections with sufficient bandwidth.
It is important to benchmark before and after changing these values to ensure it is improving network speed and not reducing it. If you are not seeing downloads begin slowly and gradually speed up, then there is no need to change these values as they are already optimal for your connection speed. When benchmarking, be sure to test against both a high speed and low speed remote server to ensure you are not speeding up access to fast machines at the expense of making access to slow servers even slower.
To adjust these values, edit the .network file for the connection:
/etc/systemd/network/eth0.network
[Match] Name=eth0 #[Network] #Gateway=... <-- Remove this if you have it, and put it in the Gateway= line below [Route] # This will apply to the gateway supplied via DHCP. If you manually specify # your gateway, put it here instead. Gateway=_dhcp4 # The defaults for these values is 10. They are a multiple of the MSS (1460 bytes). InitialCongestionWindow=10 InitialAdvertisedReceiveWindow=10
The defaults of 10
work well for connections slower than 10 Mbit/s. For a 100 Mbit/s connection, a value of 30
works well. The manual page systemd.network(5) § [ROUTE] SECTION OPTIONS says a value of 100
is considered excessive.
If the sysctl setting net.ipv4.tcp_slow_start_after_idle
is enabled then the connection will return to these initial settings after it has been idle for some time (and often a very small amount of time). If this setting is disabled then the connection will maintain a higher window if a larger one was negotiated during packet transfer. Regardless of the setting, each new TCP connection will begin with the Initial*
settings set above.
The sysctl setting net.ipv4.tcp_congestion_control
is not directly related to these values, as it controls how the congestion and receive windows are adjusted while a TCP link is active, and particularly when the path between the two hosts is congested and throughput must be reduced. The above Initial*
values simply set the default window values selected for each new connection, before any congestion algorithm takes over and adjusts them as needed. Setting higher initial values simply shortcuts some negotiation while the congestion algorithm tries to find the optimum values (or, conversely, setting the wrong initial values adds additional negotiation time while the congestion algorithm works towards correcting them, slowing down each newly established TCP connection for a few seconds extra).
Prevent multiple default routes
When using multiple network devices, ip route
may show multiple default routes. Not all of them may be desired, e.g.
ip route
default via 10.30.1.1 dev eno2 proto dhcp src 10.30.1.15 metric 1024 default via 192.168.1.254 dev eno1 proto dhcp src 172.18.105.104 metric 1024
In the above example, eno1 provides internet while eno2 provides restricted access. There is a race condition for which of both is chosen as default route. Since eno2 came up first, it is preferred and thus, there is no internet access. To prevent that, make systemd-networkd not accept the device for routing at all. In the associated .network file - in the above example: eno2 - put
/etc/systemd/network/eno2.network
[DHCP] UseRoutes=false
See also
- systemd-networkd(8)
- Tom Gundersen posts on Core OS blog
- How to set up systemd-networkd with wpa_supplicant (WonderWoofy's walkthrough on Arch forums)