100k pps — нагрузка, а не сертификат детерминированности. Модельный постмортем: после переноса политики с FreeBSD pf на Linux nftables часть соединений перестала открываться. Мониторинг кричит «firewall не вывозит», общий CPU спокоен. Первый подозреваемый — перевод правил: у pf последнее совпавшее фильтрующее правило определяет решение, если обработку не остановил quick. В nftables accept одной base chain допускает дальнейшую обработку другими цепочками того же hook. Сначала восстанавливаем путь пакета: FreeBSD — pfctl -sr -v, pfctl -si, pfctl -ss; Linux — nft -a list ruleset, conntrack -S. Проверяем hook и priority, порядок правил, состояния и дельты счётчиков. Для узко выбранного тестового потока включаем meta nftrace set 1 и читаем nft monitor trace. Без включённого nftrace команда не покажет трассировку. Семантика описана в https://man.freebsd.org/pf.conf и https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains. Затем отделяем политику от нехватки ресурсов. На Linux сопоставляем net.netfilter.nf_conntrack_count и net.netfilter.nf_conntrack_max, дельты insert_failed, drop, early_drop в conntrack -S; на FreeBSD — текущие состояния и счётчики отказов pfctl -si с лимитами pfctl -sm. Проверяем потери NIC через ethtool -S на Linux и netstat -i -d на FreeBSD. Одинаковые 100k pps внутри установленных потоков и при постоянном создании новых соединений — разные испытания. Средний CPU не оправдывает переполненную очередь одного RX-потока. Вердикт: без размеров пакетов, скорости создания состояний, числа потоков и профиля bursts победителя нет. Отдельно испытываем новые и установленные соединения при смене политики: загрузка правил не означает удаления старых состояний. K8s поверх непонятного packet path добавляет участников расследования, а не доказательств. Эксплуатация bare-metal: https://ftops.space/?utm_source=telegram&utm_medium=smm&utm_campaign=ftops&utm_content=freebsd-pf-protiv-linux-nftables-sr.