Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-079 — air-netlink (couche 1) : transport netlink générique, crate indépendante + descellement additif couche-0-v1.11 (AF_NETLINK + sockaddr_nl)

Statut : Accepté (décision BDFL, 2026-07-07 — option B, couche 1). RFC de structure (ADR-015). Applique le modèle de nouvelle crate couche 1 + descellement additif (ADR-062), précédents ADR-069 (crate air-handle) et ADR-051/ADR-070/ADR-071 (descellements additifs couche 0).

Catégorie : Nouvelle crate couche 1 (air-netlink) + descellement additif couche 0 (AF_NETLINK/sockaddr_nl). Aucune rupture d’ABI ni de signature ; jalons antérieurs conservés.

Contexte

La spec air-network (substrat de connexion L2) a besoin, pour sa conscience du chemin (AirNetworkPathMonitorNWPathMonitor), d’observer l’état réseau du noyau : interfaces, adresses, routes, liens up/down. C’est du plan de contrôle réseau — le domaine de rtnetlink (NETLINK_ROUTE).

La couche 0 n’expose qu’un socket NETLINK_KOBJECT_UEVENT spécifique (hotplug, consommé par air-device), pas de netlink générique ; air-socket a délibérément retiré netlink (décision 2026-06-15 : « netlink relève de la configuration kernel, concern distinct → futur crate air-netlink »).

Deux options ont été analysées :

  • (A) Étendre air-device — réutilise l’infra netlink existante, mais conflate deux protocoles très différents (uevent = broadcast texte read-only vs rtnetlink = requête/réponse + dump + attributs TLV, surface hostile), exige un descellement lourd d’une crate scellée dédiée aux devices, et disperse un transport que d’autres consommateurs veulent (WireGuard, DHCP, routes air-config, wifi nl80211).
  • (B) Crate indépendante air-netlinkresponsabilité unique, transport réutilisable par tous les consommateurs, fuzzable en isolation (le TLV kernel est la surface hostile), cohérent avec la décision air-socket déjà écrite ; coût = une crate + un petit additif couche 0.

Décision

Option B, couche 1. On crée une crate air-netlink (couche 1) : un transport netlink générique (message framing, codec d’attributs TLV, corrélation requête/réponse/dump), suivant le patron sans-IO 9-composants (note réseau §2.2). Elle est réutilisable par air-network (path monitor), les daemons WireGuard/DHCP (L5), air-config (projection de routes), et le futur wifi (nl80211) / firewall (nftables).

Placement couche 1 (pair d’air-socket), pas couche 2. Un transport kernel-facing générique est au niveau d’air-socket (L1) ; ce sont ses consommateurs qui vivent plus haut (air-network L2, daemons L5). Cela révise la mention prospective « couche 2 » de la spec air-socket (référence approximative), à réconcilier par grep.

Descellement additif couche 0 requis (couche-0-v1.11). Les syscalls génériques socket/bind/sendmsg/recvmsg existent déjà (air-sys-syscall::net). Il manque seulement :

  • SocketDomain::Netlink = 16 (AF_NETLINK) dans l’enum typé (air-sys-types::net, aujourd’hui Unix=1/Ipv4=2/Ipv6=10) ;
  • un type/codec SocketAddrNetlink (sockaddr_nl : nl_family, nl_pad, nl_pid, nl_groups — 12 octets) exposé pour bind.

Aucun nouveau syscall. Additif modéré (modèle ADR-070 sockaddr codec).

air-device inchangé. Son socket uevent NETLINK_KOBJECT_UEVENT reste tel quel (pas de descellement de air-device). Une migration future de ce socket sur air-netlink est possible mais non requise (non bloquante) — notée en suite.

Gouvernance

  • Décision structurante (nouvelle crate + touche couche 0 scellée) → ratification BDFL (présent ADR), pas la délégation additive neutre.
  • Tags posés après implémentation + barrière 2 arches (x86_64 + aarch64, ADR-072) : couche-0-v1.11 (additif AF_NETLINK) puis couche-1-v1.x (crate air-netlink).
  • Zéro-C, zéro unsafe exposé ; parsing TLV borné + fuzzé (surface hostile kernel), couverture 100 % (couche 1).

Conséquences

  • Nouvelle crate crates/air-netlink (couche 1) ; spec docs/specs/layer-1/air-netlink.md.
  • Descellement couche 0 : SocketDomain::Netlink + SocketAddrNetlinkcouche-0-v1.11.
  • air-network::AirNetworkPathMonitor débloqué (rtnetlink lien/adresse/route + abonnement multicast RTNLGRP_*).
  • Réconciliation doc : mention « couche 2 » d’air-socket corrigée en « couche 1 ».
  • Précédent : les autres familles netlink (nl80211, nftables, genetlink) se poseront au-dessus de ce transport, sans le réécrire.

Alternatives rejetées

  • (A) Étendre air-device — conflate uevent (broadcast texte) et rtnetlink (plan de contrôle TLV) ; descellement lourd d’une crate scellée hors périmètre ; disperse un transport multi-consommateurs. Rejeté.
  • air-netlink en couche 2 — un transport kernel générique appartient à L1 (pair d’air-socket) ; le placer en L2 créerait des dépendances descendantes tordues pour air-config (L1) et compliquerait la réutilisation. Rejeté.
  • Réécrire un parseur netlink par consommateur — duplication d’une surface de parsing hostile ; contraire à la règle des 80 % et au patron sans-IO. Rejeté.

Suite

  • Spec air-netlink (couche 1) — faite (docs/specs/layer-1/air-netlink.md).
  • Implémentation : additif couche 0 (AF_NETLINK/sockaddr_nl, RFC de descellement) puis crate air-netlink ; tags après barrière 2 arches.
  • Migration éventuelle du socket uevent d’air-device sur air-netlink (non bloquante).
  • Câblage : registre ADRs, SUMMARY.md, INDEX.md ; note « à résoudre » d’air-network mise à jour.