Chappe 05 · Filtrage par type de paquet
Filtrage par type de paquet
Un type de paquet est un type comme un autre. Le firmware devrait offrir les mêmes leviers à tous, au lieu de réserver un traitement spécial à un seul. Voici le modèle homogène vers lequel nous allons, et ce qu'il faut ajouter pour y arriver.
Le principe
MeshCore transporte seize types de paquets : requêtes, réponses, accusés, annonces, chat de canal, données de canal, contrôle, et le reste. Un répéteur décide de relayer ou non sur le seul en-tête, sans jamais déchiffrer la charge utile.
Aujourd'hui, un seul type dispose d'un vrai interrupteur de blocage : les données de canal, par héritage d'une contribution ancienne. Les autres n'ont qu'un plafond de distance, qui ne coupe jamais totalement. C'est une asymétrie d'histoire, pas un choix de conception.
Le principe que nous adoptons est simple : un type est un type. Chaque type doit exposer le même jeu de leviers, et le comportement particulier d'un type ne doit être qu'une ligne dans une grille uniforme, pas une fonction à part.
Les cinq leviers par type
| Levier | Rôle | Disponible aujourd'hui |
|---|---|---|
block.type <t> <0|1> |
blocage total du type, le paquet est jeté dès le premier saut | non, sauf le type de données de canal |
allow.type <t> <id> |
exception qui réadmet un flux précis malgré le blocage | non, sauf le type de données de canal |
flood.max.type <t> <n> |
distance maximale, en nombre de sauts | oui, pour tous les types |
prio.type <t> <n> |
priorité sous charge | oui, pour tous les types |
airtime.budget.type <t> <n> |
part de temps d'antenne réservée | oui, pour tous les types |
Trois leviers sur cinq sont déjà uniformes. Ce qui manque, ce sont le blocage total et son exception, pour tous les types, au lieu d'une paire codée en dur sur un seul.
Un point à retenir sur le plafond de distance : la valeur 0 de flood.max.type ne veut pas dire « bloqué », elle veut dire « suit le plafond global ». Aucune valeur de ce levier ne coupe un type à zéro. Seul un vrai blocage le fait, et c'est justement ce qui manque.
La seule vraie nuance
L'exception, l'allowlist, a besoin d'un identifiant lisible en clair dans le paquet pour savoir quoi réadmettre. Or tous les types n'en portent pas un. Ce n'est pas un type qui serait spécial, c'est que certains types exposent un identifiant et d'autres non.
| Type | Identifiant en clair | Exception pertinente |
|---|---|---|
| chat de canal, données de canal | empreinte de canal | oui, par canal |
| annonce | clé publique de l'émetteur | oui, par nœud |
| requête, accusé, message direct, chemin, contrôle | aucun | non, blocage tout ou rien |
Le modèle reste homogène. L'exception est simplement vide là où il n'y a rien à filtrer, et le blocage oui/non, lui, s'applique à tous les types sans exception.
Le pipeline d'un répéteur
Le schéma ci-dessous montre où ces leviers interviennent. Un paquet en inondation traverse les portes de filtrage ; un paquet en chemin direct suit sa route sans filtrage ; l'administration du répéteur passe par une voie séparée, l'ACL.
Ce qui existe, ce qui manque
Ce qui est en place aujourd'hui dans le firmware :
- le plafond de distance par type, la priorité par type et le budget de temps d'antenne par type, pour les seize types
- un blocage total et une allowlist, mais pour le seul type de données de canal
- une liste de blocage par nœud, qui écarte le trafic de canal venu d'un émetteur banni
Ce qui manque pour rendre le modèle homogène :
- un blocage total pour n'importe quel type, pas seulement un
- une allowlist pour les types qui portent un identifiant en clair, pas seulement un
La proposition
Deux commandes, généralisées à tous les types :
| Commande | Rôle |
|---|---|
set block.type <0-15> <0|1> |
bloque ou débloque totalement un type |
set allow.type <0-15> <identifiant> |
réadmet un flux précis, pour les types qui exposent un identifiant |
Avec, en lecture, get block.type et get allow.type, sur le modèle des commandes existantes.
Compatibilité. Les commandes actuelles du type de données de canal deviennent des alias de la forme générale, pour ne casser aucune configuration existante. Le blocage par défaut des données de canal est conservé tel quel.
Garde-fou. Certains types sont structurants : l'annonce sert à la découverte, le chemin et l'accusé au routage, le contrôle à la coordination. Les bloquer casserait le réseau. La commande block.type refuse ou avertit sur ces types, ce que le plafond de distance ne fait pas aujourd'hui.
Valeurs par défaut. Aucun changement de comportement à l'installation : seul le type de données de canal reste bloqué par défaut, tous les autres passent, comme aujourd'hui.
Comment nous le validerons
Rien de tout cela ne se règle à l'estime. Chaque durcissement se mesure au banc d'essai, en relevant les compteurs de rejet du répéteur avant et après. Un filtrage qui n'écarte rien ne sert à rien, un filtrage qui écarte tout coupe le réseau : ce sont ces compteurs qui départagent.
L'objectif est ensuite de faire remonter ce modèle dans le firmware officiel, pas de maintenir un fork parallèle.