In this lesson, you will learn how to structure your nftables rule sets to minimize CPU overhead by reducing the number of times the kernel must evaluate each packet.
The Cost of Sequential Evaluation
When a packet enters the network stack, the kernel traverses your rule sets in order. If you have hundreds of rules, checking every single one for every packet is computationally expensive. The "efficiency" of a rule set is determined by how quickly the kernel can reach a decision—either accept or drop—and exit the evaluation loop.
Use Sets and Maps for O(1) Lookups
The most effective way to optimize performance is to move away from linear lists of rules toward Sets and Maps.
Instead of writing individual rules for each IP address or port:
# Inefficient: Linear traversal
nft add rule ip filter input tcp dport 80 accept
nft add rule ip filter input tcp dport 443 accept
You should use a set to perform a single lookup:
# Efficient: O(1) complexity lookup
nft add set ip filter allowed_ports { type inet_service\; }
nft add element ip filter allowed_ports { 80, 443 }
nft add rule ip filter input tcp dport @allowed_ports accept
By using a set, the kernel uses optimized data structures (like hashes or trees) to find a match, regardless of how many items are in the set.
Prioritize "Early Exit" Rules
Always place your most frequently triggered rules at the top of your chain. If 90% of your traffic is from a trusted internal subnet, add an accept rule for that range immediately. This allows the vast majority of traffic to bypass the rest of the rule set entirely. Conversely, place high-volume drop rules (like those blocking known malicious IP ranges) early as well to avoid processing "garbage" traffic deeper in the stack.
Leverage Chain Organization
Rather than one giant input chain, break logic into smaller, dedicated chains. By jumping to specific chains based on packet type (e.g., prerouting_lan vs prerouting_wan), you ensure the kernel only evaluates the rules relevant to that specific traffic flow, further reducing the instruction count per packet.
Key Takeaway: Optimize your rule sets by replacing linear chains with hash-based lookups and placing your most common traffic patterns at the top of your policy.