«« sommaire »»

IV.1 – Configuration du réseau

Christophe BLAESS - juillet 2023

La configuration du système que nous avons réalisée jusqu'ici était relativement simple :

Nous pouvons néanmoins avoir besoin de réaliser une configuration plus approfondie du système, c'est ce que nous évoquerons dans cette séquence.

Configuration de référence

Pour cette séquence, et les suivantes je vais repartir d'une image personnalisée en utilisant comme cible un Raspberry Pi 4. Je souhaite éviter l'émulation par QEmu pour disposer d'une vraie connexion réseau Ethernet. En outre le Raspberry Pi ne dispose pas de RTC (Real Time Clock) ce qui nous donnera l'occasion de gérer explicitement la mise à l'heure.

[Yocto-lab]$ source layers/poky/oe-init-build-env builds/build-rpi/

[build-rpi]$ 

J'utilise donc un fichier conf/local.conf dans lequel les lignes suivantes ont été ajoutées 

# <LOGILIN>

MACHINE="raspberrypi4"
DL_DIR="${TOPDIR}/../downloads"
SSTATE_DIR="${TOPDIR}/../sstate-cache"
ENABLE_UART="1"

INHERIT += "extrausers"
EXTRA_USERS_PARAMS += "useradd  -p '\$5\$gFkqOeNU\$BOtEK2RhJIu.MxFT4jqtaYGYdw85fiRbc4hplRWI/63'  guest;"
EXTRA_USERS_PARAMS += "usermod  -p '\$5\$IlhPmUHu\$AFPAiidalJ5Llt5YSqKoKXUbiWJjbvtRYT0AvzJp6p7'  root;"
hostname:pn-base-files = "mybox"
SERIAL_CONSOLES_CHECK:forcevariable = ""


# </LOGILIN>
 [...]

J'ajoute deux layers que nous n'avions pas utilisé dans le build pour Raspberry Pi jusqu'à présent.

[build-rpi]$ bitbake-layers  add-layer  ../../layers/meta-my-layer/
NOTE: Starting bitbake server...

[build-rpi]$ bitbake-layers  add-layer  ../../layers/meta-openembedded/meta-oe/
NOTE: Starting bitbake server...

[build-rpi]$

Enfin, notre fichier ../../layers/meta-my-layer/recipes-custom/images/my-image.bb est configuré comme suit :

SUMMARY = "A customized image for development purposes."
LICENSE = "MIT"

inherit core-image

IMAGE_FEATURES += "splash"
IMAGE_FEATURES += "tools-debug"
IMAGE_FEATURES += "tools-profile"
IMAGE_FEATURES += "tools-sdk"
IMAGE_FEATURES += "ssh-server-dropbear"
IMAGE_FEATURES += "read-only-rootfs"
IMAGE_INSTALL:append = " mc"
IMAGE_INSTALL:append = " nano"
IMAGE_INSTALL:append = " my-scripts"
IMAGE_INSTALL:append = " python3-modules"
IMAGE_INSTALL:append = " python-hello"
IMAGE_INSTALL:append = " hello-autotools"
IMAGE_INSTALL:append = " hello-cmake"
IMAGE_INSTALL:append = " hello-makefile"
IMAGE_INSTALL:append = " hello-simple"

J'ai relancé un build (qui a duré un bon moment car la dernière image pour Raspberry Pi datait de la séquence I.3).

[build-rpi]$ nice  bitbake  my-image

La commande «nice» précédant l'appel à bitbake demande à ce que la priorité des tâches lancées par ce dernier soit un peu moins élevée que la normale. Ainsi la compilation est un peu moins agressive vis-à-vis de l'ordonnancement et mon poste de travail reste plus confortable à utiliser pendant ce temps.

Notre image étant compilée et installée sur une carte micro-SD, nous pouvons démarrer le Raspberry Pi.

Poky (Yocto Project Reference Distro) 4.0.11 mybox ttyS0

mybox login: root
Password: (linux)

root@mybox:~# uname  -a
Linux mybox 5.15.34-v7l #1 SMP Tue Apr 19 19:21:26 UTC 2022 armv7l armv7l armv7l GNU/Linux

root@mybox:~# cat  /sys/firmware/devicetree/base/model 
Raspberry Pi 4 Model B Rev 1.1

Configuration initiale du réseau

Au démarrage nous voyons ces traces qui ressemblent à des messages d'erreur :

udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: no lease, forking to background

Par défaut, Yocto nous propose une image dont la configuration réseau est dynamiquement obtenue à l'aide du protocole DHCP.

Plus précisément, le Raspberry Pi envoie sur le réseau Ethernet un message broadcast disant «Mon adresse matérielle est XX:XX:XX:XX:XX, je souhaite obtenir une adresse IP». Normalement un serveur DHCP présent sur le réseau (généralement un routeur pour les réseaux d'entreprise ou une box dans un cadre domestique) lui répond en lui indiquant entre autres l'adresse IP qui lui est attribuée, l'adresse de la passerelle de sortie du sous-réseau et l'adresse du serveur DNS permettant de traduire les URL en adresse IP.

Mon Raspberry Pi n'était pas relié au réseau, nous voyons donc les messages d'échec de l'initialisation. Si je branche son port Ethernet sur le réseau local et que je le redémarre, les messages sont différents :

udhcpc: sending discover
udhcpc: broadcasting discover
udhcpc: broadcasting select for 192.168.3.11, server 192.168.3.254
udhcpc: lease of 192.168.3.11 obtained from 192.168.3.254, lease time 43200

Une fois connecté, je peux vérifier la configuration réseau.

Poky (Yocto Project Reference Distro) 4.0.11 mybox ttyS0

mybox login: root
Password: (linux)
root@mybox:~# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether dc:a6:32:02:57:3d brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.11/24 brd 192.168.3.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2a01:e0a:22:ea90:dea6:32ff:fe02:573d/64 scope global dynamic flags 100 
       valid_lft 86353sec preferred_lft 86353sec
    inet6 fe80::dea6:32ff:fe02:573d/64 scope link 
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000
    link/ether dc:a6:32:02:57:3e brd ff:ff:ff:ff:ff:ff
root@mybox:~# 

Il existe toutefois de nombreuses situations où on ne dispose pas de serveur DHCP sur notre réseau, et ceci pour différentes raisons (sécurité, politique d'administration, réseau industriel dédié à certains équipements…).

Nous pouvons modifier la configuration de Yocto pour que notre système dispose d'une configuration réseau statique avec des adresses fixées dès la production de l'image.

Pour cela, il nous faut configurer le fichier /etc/network/interfaces de la cible. Par défaut son contenu est le suivant 

# The loopback interface
auto lo
iface lo inet loopback

# Wireless interfaces
iface wlan0 inet dhcp
        wireless_mode managed
        wireless_essid any
        wpa-driver wext
        wpa-conf /etc/wpa_supplicant.conf

iface atml0 inet dhcp

# Wired or wireless interfaces
auto eth0
iface eth0 inet dhcp
iface eth1 inet dhcp

# Ethernet/RNDIS gadget (g_ether)
# ... or on host side, usbnet and random hwaddr
iface usb0 inet static
        address 192.168.7.2
        netmask 255.255.255.0
        network 192.168.7.0
        gateway 192.168.7.1

# Bluetooth networking
iface bnep0 inet dhcp

Le moins que l'on puisse dire, c'est que la gamme des interfaces gérées par ce fichier est plutôt large :

Ce fichier est très riche, mais en pratique son contenu utile est beaucoup plus réduit :

Il nous reste au final deux interfaces utilisables immédiatement : «lo» et «eth0». Pour avoir une configuration statique de notre interface Ethernet, il suffirait donc que notre fichier /etc/network/interfaces ressemble à :

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address  192.168.3.101
  netmask  255.255.255.0
  gateway 192.168.3.254
  dns-nameserver 8.8.8.8

La configuration du réseau Ethernet est évidement à adapter en fonction des situations. La ligne «address» configure l'adresse IP du Raspberry Pi, la ligne «netmask» le masque binaire du sous-réseau et celle «gateway» l'adresse de la passerelle à joindre pour accéder aux autres sous-réseaux et à Internet.

Une ligne est moins habituelle : «dns-nameserver» permet d'indiquer un serveur DNS, toutefois cette option ne fonctionne pas encore sur notre Raspberry Pi, car il manque un package dans notre image.

Configuration réseau statique

Si nous modifions manuellement le fichier interfaces de la cible et redémarrons, nous pouvons observer la configuration suivante :

Poky (Yocto Project Reference Distro) 4.0.11 mybox ttyS0

mybox login: root
Password: (linux)
root@mybox:~# ip  addr  show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether dc:a6:32:02:57:3d brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.101/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2a01:e0a:22:ea90:dea6:32ff:fe02:573d/64 scope global dynamic flags 100 
       valid_lft 86082sec preferred_lft 86082sec
    inet6 fe80::dea6:32ff:fe02:573d/64 scope link 
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000
    link/ether dc:a6:32:02:57:3e brd ff:ff:ff:ff:ff:ff

root@mybox:~# ip route
default via 192.168.3.254 dev eth0 
192.168.3.0/24 dev eth0 scope link  src 192.168.3.101 

root@mybox:~# ping 192.168.3.254
PING 192.168.3.254 (192.168.3.254): 56 data bytes
64 bytes from 192.168.3.254: seq=0 ttl=64 time=0.628 ms
64 bytes from 192.168.3.254: seq=1 ttl=64 time=0.315 ms
64 bytes from 192.168.3.254: seq=2 ttl=64 time=0.309 ms
^C
--- 192.168.3.254 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.309/0.417/0.628 ms

L'adresse IP de l'interface eth0 est correcte, et on arrive à joindre une autre adresse du même sous-réseau (ici la passerelle). Essayons de joindre une adresse IP distante sur Internet :

root@mybox:~# ping  8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=119 time=3.054 ms
64 bytes from 8.8.8.8: seq=1 ttl=119 time=3.546 ms
64 bytes from 8.8.8.8: seq=2 ttl=119 time=3.551 ms
64 bytes from 8.8.8.8: seq=3 ttl=119 time=2.745 ms
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 2.745/3.224/3.551 ms

Ce serveur DNS de Google est bien accessible. Essayons de résoudre une adresse symbolique 

root@mybox:~# ping  www.kernel.org 
ping: bad address 'www.kernel.org'
root@mybox:~#

La résolution de noms échoue, car il nous manque le package «resolvconf» qui prend en compte la ligne «dns-nameservers» du fichier interfaces. Nous pouvons commencer par rajouter la ligne suivante dans notre fichier d'image :

IMAGE_INSTALL:append = " resolvconf"

Toutefois, cela n'est pas suffisant. Nous avons modifié le fichier interfaces directement sur la cible, mais nous souhaitons qu'il soit configuré comme nous le voulons dès la production de l'image. Nous devons donc rechercher quelle recette le fournit.

Recherche de la recette responsable d'un fichier

Un problème revient régulièrement lorsque l'on cherche à affiner la configuration d'une image produite par Yocto Project : «mais quelle recette a bien pu installer ce fichier ?». Profitons de l'occasion offerte par le fichier «interfaces» pour voir comment procéder.

Nous allons employer l'outil devtool fourni par Poky pour qu'il nous indique quelle recette installe le fichier indiqué. La commande est exécutée sur la machine de développement, mais le chemin passé en argument correspond à celui observé dans l'arborescence de la cible :

[build-rpi]$ devtool  search  /etc/network/interfaces
NOTE: Starting bitbake server...
NOTE: Reconnecting to bitbake server...
NOTE: Retrying server connection (#1)...
NOTE: Reconnecting to bitbake server...
NOTE: Previous bitbake instance shutting down?, waiting to retry...
NOTE: Retrying server connection (#2)...
Loading cache: 100% |############################################################################################################| Time: 0:00:00
Loaded 2832 entries from dependency cache.
init-ifupdown         Basic TCP/IP networking init scripts and configuration files

Le nom du package est indiqué sur la dernière ligne : «init-ifupdown». Nous pouvons aussi demander à devtool de rechercher l'emplacement de la recette en question (même s'il est assez évident que c'est une recette de base de Poky) :

[build-rpi]$ devtool  find-recipe  init-ifupdown
NOTE: Starting bitbake server...
INFO: Creating workspace layer in /home/cpb/Yocto-lab/build-rpi/workspace
NOTE: Reconnecting to bitbake server...
NOTE: Retrying server connection (#1)...
NOTE: Reconnecting to bitbake server...
NOTE: Previous bitbake instance shutting down?, waiting to retry...
NOTE: Retrying server connection (#2)...
Parsing recipes: 100% |##########################################################################################################| Time: 0:02:35
Parsing of 1785 .bb files complete (0 cached, 1785 parsed). 2832 targets, 122 skipped, 0 masked, 0 errors.
/home/cpb/Yocto-lab/layers/poky/meta/recipes-core/init-ifupdown/init-ifupdown_1.0.bb

Voyons le contenu du répertoire de cette recette :

[build-rpi]$ ls  ../../layers/poky/meta/recipes-core/init-ifupdown/
init-ifupdown-1.0  init-ifupdown_1.0.bb

[build-rpi]$ ls  ../../layers/poky/meta/recipes-core/init-ifupdown/init-ifupdown-1.0/
copyright  init  interfaces  nfsroot  qemuall
[build-rpi]$ 

Le fichier «interfaces» est bien là ! Il ne nous reste plus qu'à le remplacer en suivant la même méthode que celle que nous avions employée dans la séquence II.3. Commençons par créer les répertoires nécessaires dans notre layer :

[build-rpi]$ mkdir  -p  ../../layers/meta-my-layer/recipes-core/init-ifupdown/init-ifupdown/

Puis nous y copions le fichier «interfaces» présenté plus-haut :

[build-rpi]$ nano  ../../layers/meta-my-layer/recipes-core/init-ifupdown/init-ifupdown/interfaces
  auto lo
  iface lo inet loopback

  auto eth0
  iface eth0 inet static
    address  192.168.3.101
    netmask  255.255.255.0
    gateway 192.168.3.254
    dns-nameserver 8.8.8.8

Et enfin nous écrivons une petite extension .bbappend pour indiquer que les fichiers concernant cette recette doivent être recherchés en priorité dans notre sous-répertoire :

[build-rpi]$ nano  ../../layers/meta-my-layer/recipes-core/init-ifupdown/init-ifupdown_%.bbappend
  FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"

Nous pouvons relancer le build et réinstaller notre image sur la carte SD du Raspberry Pi. Une fois le boot terminé, nous observons :

root@mybox:~# ip  addr  show
1: lo:  mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc mq qlen 1000
    link/ether dc:a6:32:02:57:3d brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.101/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2a01:e0a:22:ea90:dea6:32ff:fe02:573d/64 scope global dynamic flags 100 
       valid_lft 86393sec preferred_lft 86393sec
    inet6 fe80::dea6:32ff:fe02:573d/64 scope link 
       valid_lft forever preferred_lft forever
3: wlan0:  mtu 1500 qdisc noop qlen 1000
    link/ether dc:a6:32:02:57:3e brd ff:ff:ff:ff:ff:ff

root@mybox:~# ping www.kernel.org
PING www.kernel.org (136.144.49.103): 56 data bytes
64 bytes from 136.144.49.103: seq=0 ttl=54 time=11.533 ms
64 bytes from 136.144.49.103: seq=1 ttl=54 time=11.531 ms
64 bytes from 136.144.49.103: seq=2 ttl=54 time=11.788 ms
64 bytes from 136.144.49.103: seq=3 ttl=54 time=11.481 ms
^C
--- www.kernel.org ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 11.481/11.583/11.788 ms

La configuration est bien celle que nous avons fixée statiquement, la résolution de noms fonctionne ainsi que la communication avec une machine distante sur Internet.

Conclusion

Cette séquence nous a permis de personnaliser la configuration réseau, mais au-delà de cette action, nous avons vu comment expérimenter directement sur la cible et reporter ensuite les modifications dans l'image en recherchant les recettes concernées et en les surchargeant.

Ce document est placé sous licence Creative Common CC-by-nc. Vous pouvez copier son contenu et le réemployer à votre gré pour une utilisation non-commerciale. Vous devez en outre mentionner sa provenance.

Le nom Yocto Project est une marque déposée par la Linux Foundation. Le présent document n'est en aucune façon approuvé par Yocto Project ou la Linux Foundation.

«« sommaire »»