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) | development | |
mickledore (4.2) | current stable | |
langdale (4.1) | stable | |
kirkstone (4.0) | LTS | |
honister (3.4) | EOL | |
hardknott (3.3) | 1 | EOL |
gatesgarth (3.2) | 2 | EOL |
dunfell (3.1) | 3 | LTS |
zeus (3.0) | 4 | EOL |
warrior (2.7) | 4 | EOL |
thud (2.6) | 4 | EOL |
sumo (2.5) | 4 | EOL |
rocko (2.4) | 4 | 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:
- A Raspberry Pi 3 device
- A supported SD Card
- A configured Yocto environment . Please take a look at one of the following if you do not have this prepared:
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!