Exploiter les 4 cœurs de son OPNsense : RSS et system tunables
En activant Suricata en mode IPS, la charge CPU du pare-feu est devenue nettement plus visible — et un constat classique est ressorti : malgré 4 cœurs disponibles, top montrait un seul cœur saturé pendant qu'un trafic soutenu traversait le WAN, les trois autres restant quasiment inactifs. C'est un comportement par défaut bien connu sur FreeBSD (et donc OPNsense) : sans configuration explicite, le traitement des paquets réseau n'est pas automatiquement réparti sur plusieurs cœurs.
1. Pourquoi un seul cœur travaille par défaut
Historiquement, le traitement des interruptions réseau (une interruption matérielle par paquet reçu, avant même que le pare-feu ne l'analyse) est géré par une seule file d'attente sur l'interface, elle-même épinglée à un seul cœur CPU. Sur une petite charge, ça ne se voit pas. Dès que le débit ou le nombre de paquets par seconde augmente (typiquement avec Suricata en IPS, qui ajoute un traitement CPU par paquet), ce cœur unique devient le facteur limitant bien avant que les trois autres ne soient sollicités.
2. Constater le problème avant de le corriger
Avant de modifier quoi que ce soit, mieux vaut confirmer le diagnostic depuis le shell OPNsense :
# Répartition de charge par cœur en temps réel
$ top -P
# Nombre d'interruptions par interface/file, et sur quel cœur elles tombent
$ vmstat -i
# Le pilote de la carte réseau expose-t-il plusieurs files (queues) ?
$ sysctl dev.igb.0.queue0.name dev.igb.1.queue0.name 2>/dev/null
# (remplacer "igb" par le pilote réellement utilisé : em, ix, vmx...)
Si top -P montre un cœur systématiquement proche de 100% pendant qu'un débit soutenu traverse l'interface WAN, et les autres quasiment au repos, le diagnostic est confirmé.
3. Activer le multi-queue et RSS via les tunables
Dans OPNsense : System → Settings → Tunables. Les réglages clés (adapter le préfixe igb au pilote réellement utilisé sur votre matériel) :
net.isr.maxthreads=4— nombre de threads du "network ISR" (le sous-système qui distribue le traitement des paquets), à aligner sur le nombre de cœurs disponibles.net.isr.bindthreads=1— épingle chaque thread ISR à un cœur CPU dédié, pour éviter que l'ordonnanceur ne les fasse migrer d'un cœur à l'autre.net.inet.rss.enabled=1— active RSS au niveau de la pile réseau.net.inet.rss.bits=2— nombre de bits utilisés pour le hash RSS ; 2 bits correspond à 4 buckets, un par cœur sur une machine à 4 cœurs.hw.igb.num_queues=4— demande au pilote de la carte réseau d'exposer 4 files de réception matérielles plutôt qu'une seule (nécessite un redémarrage complet, pas juste un rechargement du service).
sysctl dev.<pilote>.0.queue1.name après redémarrage : si la deuxième file n'existe pas, le pilote ou la carte ne supporte tout simplement pas plus d'une file sur cette plateforme.4. Vérifier la répartition après application
Après redémarrage complet (pas un simple rechargement de configuration — ces réglages s'appliquent au démarrage du noyau), relancez top -P sous charge : les interruptions réseau et le traitement associé (y compris Suricata, qui bénéficie directement de la parallélisation) doivent désormais se répartir sur les 4 cœurs plutôt que de saturer le premier.
Le gain n'est pas qu'une question de confort : sur un pare-feu qui fait aussi de l'IPS, un cœur unique saturé peut devenir le facteur limitant bien avant la bande passante théorique de la liaison Internet elle-même.
Conclusion
Ce réglage ne se voit pas tant que la charge reste modeste, mais devient déterminant dès qu'on ajoute des traitements coûteux en CPU comme Suricata en IPS ou un trafic soutenu. Quelques tunables et un redémarrage suffisent à exploiter tout le potentiel d'un boîtier multi-cœur qui, par défaut, n'en utilisait qu'un seul. Si vous voulez être accompagné sur le dimensionnement ou le tuning de votre pare-feu, n'hésitez pas à me contacter.