How to configure networking using systemd in Yocto Project

Introduction

This tutorial will guide you through configuring networking in Yocto using systemd-networkd. This is one of the possible network management utilities available in Yocto. Other utilities may be documented in other tutorials.

This will use a Raspberry Pi 3 platform so that we can demonstrate both wired and wireless networking.

Version notes

This tutorial targets the following Yocto Project versions:

Yocto Project Tutorial applies Maintenance
nanbield (4.3) :test_works: :test_works: development
mickledore (4.2) :test_works: :test_works: current stable
langdale (4.1) :test_works: :test_works: stable
kirkstone (4.0) :test_works: :test_works: LTS
honister (3.4) :test_works: :test_fails: EOL
hardknott (3.3) :test_workaround: 1 :test_fails: EOL
gatesgarth (3.2) :test_workaround: 2 :test_fails: EOL
dunfell (3.1) :test_workaround: 3 :test_works: LTS
zeus (3.0) :test_fails: 4 :test_fails: EOL
warrior (2.7) :test_fails: 4 :test_fails: EOL
thud (2.6) :test_fails: 4 :test_fails: EOL
sumo (2.5) :test_fails: 4 :test_fails: EOL
rocko (2.4) :test_fails: 4 :test_fails: EOL

1. Support for the :-override syntax was added to hardknott in the 3.3.3 patch release.
2. Support for the :-override syntax was added to gatesgarth master only, no patch release.
3. Support for the :-override syntax was added to dunfell in the 3.1.11 patch release.
4. See the EOL versions appendix.

Prerequisites

To follow this tutorial, you will need:

We also recommend:

  • UART Console Cable: This allows you to view the console logs of the device using a USB-UART connection to your PC. See this link for more details. To enable the UART in your build, add the following to your local.conf file:
ENABLE_UART = "1"

Step 1 - Enable systemd

Enable systemd in your Yocto configuration by adding the following to your local.conf file:

INIT_MANAGER = "systemd"

Step 2 - Create custom layer

To be able to proceed with this tutorial we first must create a custom layer that will contain any custom modifications or additions. Please note that the tutorials on this site will re-use this layer and if you have already created this structure by following another tutorial you can skip this step.

Create a new layer called meta-stargazer using the bitbake-layers helper application:

bitbake-layers create-layer ../sources/meta-stargazer

This will create a basic structure in meta-stargazer directory:

../sources/meta-stargazer/
├── COPYING.MIT
├── README
├── conf
│   └── layer.conf
└── recipes-example
    └── example
        └── example_0.1.bb

3 directories, 4 files

Include the layer in our Yocto Project environment:

bitbake-layers add-layer ../sources/meta-stargazer

Step 3 (optional) - Explicitly enable networkd and resolved.

This will enable the appropriate configuration options of systemd. These are enabled by default on all Yocto releases covered in this tutorial. However explicitly setting them here ensures a known state, and can be necessary if you are applying this tutorial to a DISTRO or MACHINE that changes the defaults.

Create a custom bbappend file for the systemd recipe.

mkdir -p ../sources/meta-stargazer/recipes-core/systemd
cat > ../sources/meta-stargazer/recipes-core/systemd/systemd_%.bbappend <<EOF
PACKAGECONFIG:append = " networkd resolved"
EOF

Step 4 - Modify systemd-conf recipe in custom layer

Create a recipe append for the systemd-conf recipe that contains networking configuration files.

mkdir -p ../sources/meta-stargazer/recipes-core/systemd-conf/files
cat > ../sources/meta-stargazer/recipes-core/systemd-conf/systemd-conf_%.bbappend <<EOF
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += " \
    file://eth.network \
    file://en.network \
    file://wlan.network \
"

FILES:${PN} += " \
    ${sysconfdir}/systemd/network/eth.network \
    ${sysconfdir}/systemd/network/en.network \
    ${sysconfdir}/systemd/network/wlan.network \
"

do_install:append() {
    install -d ${D}${sysconfdir}/systemd/network
    install -m 0644 ${WORKDIR}/eth.network ${D}${sysconfdir}/systemd/network
    install -m 0644 ${WORKDIR}/en.network ${D}${sysconfdir}/systemd/network
    install -m 0644 ${WORKDIR}/wlan.network ${D}${sysconfdir}/systemd/network
}
EOF

This sets up configurations for any device named by the Linux kernel starting with en, eth, wlan, which should cover most situations. The default setting here is to use DHCP.

Create the eth.network, en.network, and wlan.network files as follows:

eth.network

cat >../sources/meta-stargazer/recipes-core/systemd-conf/files/eth.network <<EOF
[Match]
Name=eth*
KernelCommandLine=!nfsroot

[Network]
DHCP=v4

[DHCPv4]
UseHostname=false
EOF

en.network

cat >../sources/meta-stargazer/recipes-core/systemd-conf/files/en.network <<EOF
[Match]
Name=en*
KernelCommandLine=!nfsroot

[Network]
DHCP=v4

[DHCPv4]
UseHostname=false
EOF

wlan.network

cat >../sources/meta-stargazer/recipes-core/systemd-conf/files/wlan.network <<EOF
[Match]
Name=wlan*
KernelCommandLine=!nfsroot

[Network]
DHCP=v4

[DHCPv4]
UseHostname=false
EOF

Step 5 - Verify wired connectivity using DHCP

Rerun your build, provision the image onto an SDCard and verify that the eth0 interface is properly established:

raspberrypi3 login: root
Last login: Fri Oct  4 21:40:20 +0000 2019 on /dev/ttyS0.
root@raspberrypi3:~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr B8:27:EB:3B:B5:02  
          inet addr:192.168.7.213  Bcast:192.168.7.255  Mask:255.255.255.0
          inet6 addr: fe80::ba27:ebff:fe3b:b502/64 Scope:Link
          inet6 addr: fdf6:e934:7387:1:ba27:ebff:fe3b:b502/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:105 errors:0 dropped:4 overruns:0 frame:0
          TX packets:51 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:11855 (11.5 KiB)  TX bytes:7836 (7.6 KiB)

Step 6 - Verify wired connectivity using static IP assignment

Reconfigure your wired ethernet for static IP address assignment. Modify your eth.network file, adjusted for your network configuration, to look similar to the following:

[Match]
Name=eth*
KernelCommandLine=!nfsroot

[Network]
DNS=8.8.8.8
Address=192.168.7.200/24
Gateway=192.168.7.1

Note that similar setting will work in your wlan.network or en.network files if needed.

Rebuild, boot and verify:

Poky (Yocto Project Reference Distro) 2.7.1 raspberrypi3 ttyS0

raspberrypi3 login: root
root@raspberrypi3:~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr B8:27:EB:3B:B5:02  
          inet addr:192.168.7.200  Bcast:192.168.7.255  Mask:255.255.255.0
          inet6 addr: fdf6:e934:7387:1:ba27:ebff:fe3b:b502/64 Scope:Global
          inet6 addr: fe80::ba27:ebff:fe3b:b502/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:40 errors:0 dropped:1 overruns:0 frame:0
          TX packets:42 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:7756 (7.5 KiB)  TX bytes:6064 (5.9 KiB)

root@raspberrypi3:~# ping www.google.com
PING www.google.com (173.194.219.147): 56 data bytes
64 bytes from 173.194.219.147: seq=0 ttl=43 time=21.026 ms
64 bytes from 173.194.219.147: seq=1 ttl=43 time=26.633 ms
^C
--- www.google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 21.026/23.829/26.633 ms
root@raspberrypi3:~# 

Step 7 - Enable and test WiFi

Finally, we will enable WiFi access on the Raspberry Pi. We need to add one more component to the system; the supplicant. This is the component that handles the encryption needs of the WiFi. For this demo we assume you are connecting to an encrypted SSID.

First, tell bitbake that we want to enable WiFi. Also, make sure the appropriate firmware binary is present in your build. Add the following to your conf/local.conf file:

DISTRO_FEATURES:append = " wifi "
IMAGE_INSTALL:append = " linux-firmware-rpidistro-bcm43430 "

Then, make sure the wpa-supplicant package is installed by adding the following to the previously created systemd_%.bbappend file:

RDEPENDS:${PN}:append = " wpa-supplicant "

Next, create a custom wpa_supplicant recipe append:

mkdir -p ../sources/meta-stargazer/recipes-connectivity/wpa-supplicant/files
cat >../sources/meta-stargazer/recipes-connectivity/wpa-supplicant/wpa-supplicant_%.bbappend <<EOF
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += "file://wpa_supplicant-nl80211-wlan0.conf"

SYSTEMD_AUTO_ENABLE = "enable"
SYSTEMD_SERVICE:${PN}:append = " wpa_supplicant-nl80211@wlan0.service  "

do_install:append () {
   install -d ${D}${sysconfdir}/wpa_supplicant/
   install -D -m 600 ${WORKDIR}/wpa_supplicant-nl80211-wlan0.conf ${D}${sysconfdir}/wpa_supplicant/

   install -d ${D}${sysconfdir}/systemd/system/multi-user.target.wants/
   ln -s ${systemd_unitdir}/system/wpa_supplicant@.service ${D}${sysconfdir}/systemd/system/multi-user.target.wants/wpa_supplicant-nl80211@wlan0.service
}
EOF

Create the configuration file by running the following command on your desktop. This will prompt you for the passphrase for your WiFi. You may want to then edit the file to remove the clear-text passphrase:

wpa_passphrase 'YOUR_SSID' >  ../sources/meta-stargazer/recipes-connectivity/wpa-supplicant/files/wpa_supplicant-nl80211-wlan0.conf

Now, you can again, rebuild, boot and verify:

root@raspberrypi3:~# ifconfig
eth0      Link encap:Ethernet  HWaddr B8:27:EB:3B:B5:02  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

wlan0     Link encap:Ethernet  HWaddr B8:27:EB:6E:E0:57  
          inet addr:192.168.7.169  Bcast:192.168.7.255  Mask:255.255.255.0
          inet6 addr: fdf6:e934:7387:1:ba27:ebff:fe6e:e057/64 Scope:Global
          inet6 addr: fe80::ba27:ebff:fe6e:e057/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:25 errors:0 dropped:0 overruns:0 frame:0
          TX packets:46 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4125 (4.0 KiB)  TX bytes:8439 (8.2 KiB)

root@raspberrypi3:~# ping www.google.com
PING www.google.com (74.125.138.147): 56 data bytes
64 bytes from 74.125.138.147: seq=0 ttl=43 time=24.171 ms
64 bytes from 74.125.138.147: seq=1 ttl=43 time=25.410 ms
^C
--- www.google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 24.171/24.790/25.410 ms

Conclusion

In this tutorial, we discussed using systemd-networkd to manage the networking devices of your Yocto builds. Specifically, we enabled both wired and wireless interfaces, using both DHCP and Static IP addresses.

For further reading please visit

Appendix - EOL versions

override syntax

The syntax for override operations is currently using the :-character as a separator. Older versions of Yocto respectively BitBake used the _-character to separate variable name from operator. In order to apply this tutorial to older setups you generally have to replace the : separators with _, but be sure to cross check with other operations in your setup.

enabling systemd

All currently maintained releases support the `INIT_MANAGER´ variable. For older Yocto releases, systemd can be selected with the following snippet to be placed in a distro configuration or local.conf.

# Enable systemd
DISTRO_FEATURES_append = " systemd "
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_init_manager = "systemd"
VIRTUAL-RUNTIME_initscripts = ""

If this tutorial was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!

4 Likes

@drewmoseley nice!
Cosmetic suggestion: Instead of headers Step 1 - 7, perhaps use more descriptive headers to highlight what each section is about?

Awesome guide! I followed the first parts your guide with great success, and managed to get my raspberry configured with a fixed ip with no problems.

I did however run into issues when trying to go through with the wlan section. I think I discovered a type on wlan.network that specifies “Name=en*” (I tried “Name=wlan*” but that did not help). I keep getting the following error messages when booting up:

[    2.854532] systemd[1]: multi-user.target: Wants dependency dropin /etc/systemd/system/multi-user.target.wants/wpa_supplicant-nl80211@%i.service is not a valid unit name, ignoring.
[    2.871027] systemd[1]: multi-user.target: Wants dependency dropin /etc/systemd/system/multi-user.target.wants/wpa_supplicant-nl80211@wlan0.service target /lib/systemd/system/wpa_supplicant@.service has different name
[    2.890835] systemd[1]: multi-user.target: Wants dependency dropin /etc/systemd/system/multi-user.target.wants/wpa_supplicant-wired@%i.service is not a valid unit name, ignoring.
[    2.975344] systemd[1]: multi-user.target: Wants dependency dropin /etc/systemd/system/multi-user.target.wants/wpa_supplicant-nl80211@%i.service is not a valid unit name, ignoring.
[    2.991803] systemd[1]: multi-user.target: Wants dependency dropin /etc/systemd/system/multi-user.target.wants/wpa_supplicant-nl80211@wlan0.service target /lib/systemd/system/wpa_supplicant@.service has different name

This doesn’t tell me anything but I am hopeing it makes more sense to you…

@elchtzeasar welcome to Mender hub. I’m glad you found this useful. Well-spotted on the copy/paste error in wlan.network. I’ve fixed that in the post.

As for your other error, I’ve never seen that. It feels to me like something is mistyped somewhere in your recipe files. It seems to be complaining about the naming, thus my hunch. Although it’s not completely clear that is an error.

Do you see the wlan device when running “ifconfig -a”?

Drew

Thanks for a quick response. ifconfig -a did not list wlan0, but I found some other guides, and someone had listed dmesg for brcmfmac. I tried it and realized it was trying to load 43455 instead of 43430. I updated my local.conf and have now come alot further.

Before the update I had:
root@raspberrypi3:~# dmesg | grep brcmfmac
[ 4.588919] brcmfmac: F1 signature read @0x18000000=0x15264345
[ 4.597649] brcmfmac: brcmf_fw_map_chip_to_name: using brcm/brcmfmac43455-sdio.bin for chip 0x004345(17221) rev 0x000006
[ 4.610487] usbcore: registered new interface driver brcmfmac
[ 4.617209] brcmfmac mmc1:0001:1: Direct firmware load for brcm/brcmfmac43455-sdio.bin failed with error -2
[ 5.681293] brcmfmac: brcmf_sdio_htclk: HT Avail timeout (1000000): clkctl 0x50
[ 6.693172] brcmfmac: brcmf_sdio_htclk: HT Avail timeout (1000000): clkctl 0x50

I changed to "IMAGE_INSTALL_append = " linux-firmware-rpidistro-bcm43455 " in local.conf and I can now see a wlan0 when running “ifconfig -a”, but still get the same error messages from wpa_supplicant and wlan0 is not setup.

I can however run the following command which gets my wlan0 up and running:
/usr/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-nl80211-wlan0.conf -iwlan0 &

I will try to troubleshoot my last issues and post the solution here in case it helps anyone else…

I have now realized that my /etc/systemd/system/multi-user.target.wants/wpa_supplicant-nl80211@wlan0.service file contains the rule: ExecStart=/usr/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I. Changing the recipe to create /etc/wpa_supplicant/wpa_supplicant-wlan0.conf instead of wpa_supplicant-nl80211-wlan0.conf makes things work from startup.

1 Like

Interesting. I wonder if the bcm43455 driver has been updated and no longer supports the nl80211 mode?

Hi, thank you for your detailed guide.
I have installed nodejs and systemd using “local.conf” file modification. but it seems that network manager has some issue. I used your tutorial. but I can’t see eth0, en and wlan.network files in /etc/systemd/network directory. I want to modify an old yocto project which uses earlier version of poky and oe. I got below error while building which convert it to warning by local.conf file as below!


Hi @king, welcome to Mender hub.

In the older versions of poky, you are correct that systemd-conf does not exist. It looks like that was introduced in the thud release. It is possible to make similar files in sumo and earlier in a variety of recipes. I have them added in using a bbappend for systemd. The bbappend file should be largely similar to what is used for systemd-conf here. The downside of appending systemd directly is that it causes many packages to need to be rebuilt. I have heard of people making such changes in the base-files recipe to avoid this but I have not tried it myself.

Drew

OK
but I added “BB_DANGLINGAPPENDS_WARNONLY ?= “true”” line to “conf/local.conf” file and change it to warning and do the bitbake building. I can’t see *.network files in the systemd/network directory, so I added manually in the OS and rebooted. all things are OK and working fine.

Good to hear. Changing it to a warning is fine to get a successful build but as you discovered that will result in the config files not being available on the target.

Hi,

I have tried above steps but i m getting error while testing the ethernet connection.

$root > ifconfig eth0
ifconfig: eth0: error fetching interface information: Device not found

can some one help on this?

Hi @Amrun-Nisha-R, welcome to Mender hub.
What board are you using for this? What does “ifconfig -a” show?

Drew

Hi Drew,

I m using DART-MX8M board (imx8mq-var-dart). When I gave command ifconfig -a , I got below error.

It looks like your filesystem is corrupt. The original invocation of ifconfig worked above but now it is giving filesystem errors.

Note that it doesn’t look like that board has an ethernet interface so the original report of “Device not found” is likely correct.

Drew

Sorry Drew,

I have uploaded the wrong image. This is the error message that i got from the board.

image

OK. That means there is no network interface with a proper driver and firmware. Did you follow the instructions from here for the build? I think if you make sure the DISTRO is set to fslc-xwayland then all the appropriate bits will be installed.

Drew

Actually I m using DISTRO as fsl_wayland to build the core-image-minimal and I have followed the instructions from the variscite http://variwiki.com/index.php?title=Yocto_Build_Release&release=RELEASE_SUMO_V2.1_DART-MX8M . And also I didn’t need X11 configurations.

I don’t think core-image-minimal includes extra drivers and firmware blobs by default. You may have better luck using core-image-base.

Drew

Hi Drew,
What are all the drivers need to be added in the core-image-minimal?
And how can i add those things based on the configuration files?
How can i enable the connman service in core-image minimal?