On Sun, 30 Jul 2023 15:30:14 -0500 (CDT) Tim Mooney <Tim.Mooney@xxxxxxxx> wrote: > > All- > > I haven't been able to find anywhere in the nftables wiki that talks > about "Dos and Don'ts" from an efficiency perspective, especially for > people that may be coming from iptables/ip6tables to nftables. If it's > there and I've missed it, please point me at it. > > I have a mix of 32 iptables and ip6tables rules on a RHEL 7 box that I > want to convert to nftables for RHEL 9 (kernel 5.14.0 + Red Hat vendor > sauce, nftables 1.0.4). > > The obvious thing to do would be to just directly translate each rule to > nftables, and have 32 nftables rules. > > However, the iptables rules are all pairs of > > -A ports_allow -p tcp -m tcp -s X.Y.0.0/16 --dport 80 -j ACCEPT > -A ports_allow -p tcp -m tcp -s X.Y.0.0/16 --dport 443 -j ACCEPT > > -A ports_allow -p tcp -m tcp -s A.B.C.D/32 --dport 80 -j ACCEPT > -A ports_allow -p tcp -m tcp -s A.B.C.D/32 --dport 443 -j ACCEPT > > So I could cut the number of ntables rules in half just by using > > dport { 80, 443 } > > in the translated rule. > > The question is, *is it more efficient*, from a packet processing > perspective, to do that? My guess is that it is, but can anyone with > expertise confirm? If it is more efficient, what type of efficiency > improvement are we talking about, roughly? # nft -d netlink -c -f - <<<'table ip t { chain c { ip saddr 10.0.0.0/16 tcp dport { 80, 443 } accept; }; }' ip (null) (null) use 0 __set%d t 3 size 2 __set%d t 0 element 00005000 : 0 [end] element 0000bb01 : 0 [end] ip t c [ payload load 2b @ network header + 12 => reg 1 ] [ cmp eq reg 1 0x0000000a ] [ meta load l4proto => reg 1 ] [ cmp eq reg 1 0x00000006 ] [ payload load 2b @ transport header + 2 => reg 1 ] [ lookup reg 1 set __set%d ] [ immediate reg 0 accept ] Unsurprisingly, repeating the rule can be shown to demonstrate twice the number of instructions. You may find it difficult to measure the difference, however. > > Similarly, all of the rules list CIDR ranges or individual IPs, though > there are a mix of IPv4 and IPv6 ranges. I therefore could greatly reduce > the number of rules by creating a couple of named sets, one for IPv4 and > one for IPv6, and match the 'ip saddr' against the sets. You are definitely on the right track. Maps and/or verdict maps incorporating concatenations of the form "ipv4_addr . inet_service" and "ipv6_addr . inet_service" might also prove useful, depending on your exact requirements. -- Kerin Millar