<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.nftables.org/wiki-nftables/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Phil</id>
	<title>nftables wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.nftables.org/wiki-nftables/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Phil"/>
	<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php/Special:Contributions/Phil"/>
	<updated>2026-05-20T20:59:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1138</id>
		<title>Supported features compared to xtables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1138"/>
		<updated>2024-09-14T10:38:50Z</updated>

		<summary type="html">&lt;p&gt;Phil: linked to my ad-hoc script updating the xlate sample links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Last update: Mar/2022&lt;br /&gt;
&lt;br /&gt;
This page tracks the list of supported and unsupported extensions with comments and suggestions.&lt;br /&gt;
&lt;br /&gt;
== Unsupported extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches: xt ===&lt;br /&gt;
&lt;br /&gt;
==== bpf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== rateest ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== string ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== u32 ====&lt;br /&gt;
* raw expressions?&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===&lt;br /&gt;
&lt;br /&gt;
==== CHECKSUM ====&lt;br /&gt;
* add nft_payload.&lt;br /&gt;
* To the day, the only use case for this was DHCP clients not working with partial checksums. That should be fixed nowadays.&lt;br /&gt;
* See https://lwn.net/Articles/396466/ and https://www.spinics.net/lists/kvm/msg37660.html&lt;br /&gt;
* See https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/930962 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832090&lt;br /&gt;
&lt;br /&gt;
==== CT ====&lt;br /&gt;
* nft_ct_target. Refer to [[Matching_connection_tracking_stateful_metainformation]].&lt;br /&gt;
==== IDLETIMER ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== LED ====&lt;br /&gt;
* consider native (need this?)&lt;br /&gt;
==== RATEEST ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== TCPOPTSTRIP ====&lt;br /&gt;
* consider native interface, need to extend nft_exthdr.c&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== TTL ====&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
&lt;br /&gt;
==== NPT ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== arpreply ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: arp ===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
== Supported extensions ==&lt;br /&gt;
(Links updated via [http://nwl.cc/~n0-1/update_nftables_wiki_xlate_links.sh script].)&lt;br /&gt;
&lt;br /&gt;
=== matches: xt ===&lt;br /&gt;
&lt;br /&gt;
==== addrtype ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel. Refer to [[Matching routing information]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_addrtype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== cgroup ====&lt;br /&gt;
* nft_meta. Refer to [[Quick_reference-nftables_in_10_minutes#Meta]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cgroup.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Awaits support for cgroup2]&lt;br /&gt;
&lt;br /&gt;
==== cluster ====&lt;br /&gt;
* nft_hash&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cluster.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
* Built-in support via NFTA_RULE_USERDATA, since 3.15 (Pablo Neira). Refer to [[Matching_packet_headers#Matching_UDP.2FTCP_headers_in_the_same_rule|matching UDP/TCP headers in the same rule]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_comment.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== connbytes ====&lt;br /&gt;
* nft_ct, 4.5 kernel. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connbytes.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connlabel ====&lt;br /&gt;
* nft_meta, since 3.16.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connlabel.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connlimit ====&lt;br /&gt;
* consider native interface. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connlimit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connmark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connmark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== conntrack ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_conntrack.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== cpu ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cpu.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== dccp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_dccp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : dccp-option]&lt;br /&gt;
==== devgroup ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_devgroup.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== dscp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_dscp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ecn ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_ecn.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== esp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_esp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== hashlimit ====&lt;br /&gt;
* meter statement. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_hashlimit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== helper ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_helper.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ipcomp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_ipcomp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : compres]&lt;br /&gt;
==== iprange ====&lt;br /&gt;
* nft_payload, through native range support. To emulate iptables --ports you need two rules.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_iprange.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ipvs ====&lt;br /&gt;
* consider native interface. Refer to [[Load balancing]].&lt;br /&gt;
==== length ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_length.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit. Refer to [[Stateful objects]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_limit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== mac ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_mac.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_mark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== multiport ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_multiport.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== nfacct ====&lt;br /&gt;
* consider native interface. Refer to [[Stateful objects]].&lt;br /&gt;
==== osf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== owner ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_owner.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : socket-exists]&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_pkttype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== policy ====&lt;br /&gt;
* nft_xfrm, since 5.0&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_policy.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== recent ====&lt;br /&gt;
* consider native interface. Refer to [[Sets]].&lt;br /&gt;
==== sctp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* nft_exthdr for --chunk-types&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_sctp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== socket ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_socket.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== statistic ====&lt;br /&gt;
* nft_numgen. Refer to [[Load balancing]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_statistic.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== set ====&lt;br /&gt;
* Use native nf_tables set infrastructure.&lt;br /&gt;
==== state ====&lt;br /&gt;
* nft_ct&lt;br /&gt;
==== tcp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_tcp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== tcpmss ====&lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_tcpmss.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== time ====&lt;br /&gt;
* nft_meta, since 5.4&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_time.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== udp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_udp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===&lt;br /&gt;
&lt;br /&gt;
==== AUDIT ====&lt;br /&gt;
* nft_log, since 4.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_AUDIT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CLASSIFY ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_CLASSIFY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CONNMARK ====&lt;br /&gt;
* nft_ct&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_CONNMARK.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CONNSECMARK ====&lt;br /&gt;
* nft_ct, since 4.20&lt;br /&gt;
==== DSCP ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_DSCP.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== HL ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
==== HMARK ====&lt;br /&gt;
* nft_meta + nft_hash.&lt;br /&gt;
==== MARK ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_MARK.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== NETMAP ====&lt;br /&gt;
* nft_nat, upcoming 5.8&lt;br /&gt;
==== NFLOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_NFLOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== NFQUEUE ====&lt;br /&gt;
* nft_queue, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_NFQUEUE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SECMARK ====&lt;br /&gt;
* nft_meta, since 4.20&lt;br /&gt;
&lt;br /&gt;
==== SYNPROXY ====&lt;br /&gt;
* nft_synproxy, since 5.3&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_SYNPROXY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TEE ====&lt;br /&gt;
* nft_dup, since 4.3.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TEE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== TPROXY ====&lt;br /&gt;
* nft_tproxy, since 4.19&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TPROXY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TRACE ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TRACE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TCPMSS ====&lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TCPMSS.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== ah ====&lt;br /&gt;
* nft_payload + nft_cmp&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_ah.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== icmp ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_icmp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported codes: network-unreachable, host-unreachable, protocol-unreachable, port-unreachable, fragmentation-needed, source-route-failed, network-unknown, host-unknown, network-prohibited, host-prohibited, TOS-network-unreachable, TOS-host-unreachable, communication-prohibited, host-precedence-violation, precedence-cutoff, network-redirect, host-redirect, TOS-network-redirect, TOS-host-redirect, ttl-zero-during-transit, ttl-zero-during-reassembly, ip-header-bad and required-option-missing ]&lt;br /&gt;
==== realm ====&lt;br /&gt;
* nft_meta, through NFT_META_RTCLASSID.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_realm.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ttl ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_ttl.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv6 ===&lt;br /&gt;
&lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ah  ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_ah.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== eui64 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
==== frag ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_frag.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== hbh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_hbh.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
HBH options are not supported yet.&lt;br /&gt;
[Unsupported option: --hbh-opts]&lt;br /&gt;
==== hl ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_hl.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== icmp6 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_icmp6.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported icmpv6 codes: no-route, communication-prohibited, beyond-scope, address-unreachable, port-unreachable, failed-policy, reject-route, ttl-zero-during-transit, ttl-zero-during-reassembly, bad-header, unknown-header-type and unknown-option]&lt;br /&gt;
==== ipv6header ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
==== mh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_mh.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Needs bug fixation for option mh-type with range]&lt;br /&gt;
==== rt ====&lt;br /&gt;
* nft_exthdr + nft_cmp&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_rt.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options: --rt-0-res, --rt-0-addrs, --rt-0-not-strict]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
==== ECN ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_DNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_LOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_MASQUERADE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_REDIRECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====&lt;br /&gt;
* nft_reject_ipv4, since 3.13.&lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_REJECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_SNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_DNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_LOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_MASQUERADE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_REDIRECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====&lt;br /&gt;
* nft_reject_ipv6, since 3.14.&lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_REJECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_SNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== 802.3 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== among ====&lt;br /&gt;
* sets&lt;br /&gt;
&lt;br /&gt;
==== arp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== ip ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_ip.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== ip6 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_ip6.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_limit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_mark_m.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_pkttype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== stp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== vlan ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_vlan.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== dnat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_dnat.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== snat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_snat.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== redirect ====&lt;br /&gt;
* nft_payload + nft_meta (pkttype set unicast)&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_mark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== watchers: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== log ====&lt;br /&gt;
* nft_log&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_log.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== nflog ====&lt;br /&gt;
* nft_log&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_nflog.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
== Deprecated extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches ===&lt;br /&gt;
&lt;br /&gt;
==== physdev ====&lt;br /&gt;
* br_netfilter aims to be deprecated by nftables.&lt;br /&gt;
==== quota ====&lt;br /&gt;
* nfacct already provides quota support.&lt;br /&gt;
==== tos ====&lt;br /&gt;
* deprecated by dscp&lt;br /&gt;
&lt;br /&gt;
=== targets ===&lt;br /&gt;
&lt;br /&gt;
==== CLUSTERIP ====&lt;br /&gt;
* deprecated by cluster match.&lt;br /&gt;
==== TOS ====&lt;br /&gt;
* deprecated by DSCP&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== ULOG ====&lt;br /&gt;
* Removed from tree since 3.17.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1137</id>
		<title>Supported features compared to xtables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1137"/>
		<updated>2024-09-13T13:07:03Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* Supported extensions */ Updated with links to new xlate test cases&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Last update: Mar/2022&lt;br /&gt;
&lt;br /&gt;
This page tracks the list of supported and unsupported extensions with comments and suggestions.&lt;br /&gt;
&lt;br /&gt;
== Unsupported extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches: xt ===&lt;br /&gt;
&lt;br /&gt;
==== bpf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== rateest ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== string ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== u32 ====&lt;br /&gt;
* raw expressions?&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===&lt;br /&gt;
&lt;br /&gt;
==== CHECKSUM ====&lt;br /&gt;
* add nft_payload.&lt;br /&gt;
* To the day, the only use case for this was DHCP clients not working with partial checksums. That should be fixed nowadays.&lt;br /&gt;
* See https://lwn.net/Articles/396466/ and https://www.spinics.net/lists/kvm/msg37660.html&lt;br /&gt;
* See https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/930962 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832090&lt;br /&gt;
&lt;br /&gt;
==== CT ====&lt;br /&gt;
* nft_ct_target. Refer to [[Matching_connection_tracking_stateful_metainformation]].&lt;br /&gt;
==== IDLETIMER ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== LED ====&lt;br /&gt;
* consider native (need this?)&lt;br /&gt;
==== RATEEST ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== TCPOPTSTRIP ====&lt;br /&gt;
* consider native interface, need to extend nft_exthdr.c&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== TTL ====&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
&lt;br /&gt;
==== NPT ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== arpreply ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: arp ===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
== Supported extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches: xt ===&lt;br /&gt;
&lt;br /&gt;
==== addrtype ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel. Refer to [[Matching routing information]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_addrtype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== cgroup ====&lt;br /&gt;
* nft_meta. Refer to [[Quick_reference-nftables_in_10_minutes#Meta]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cgroup.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Awaits support for cgroup2]&lt;br /&gt;
&lt;br /&gt;
==== cluster ====&lt;br /&gt;
* nft_hash&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cluster.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
* Built-in support via NFTA_RULE_USERDATA, since 3.15 (Pablo Neira). Refer to [[Matching_packet_headers#Matching_UDP.2FTCP_headers_in_the_same_rule|matching UDP/TCP headers in the same rule]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_comment.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== connbytes ====&lt;br /&gt;
* nft_ct, 4.5 kernel. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connbytes.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connlabel ====&lt;br /&gt;
* nft_meta, since 3.16.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connlabel.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connlimit ====&lt;br /&gt;
* consider native interface. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connlimit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connmark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connmark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== conntrack ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_conntrack.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== cpu ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cpu.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== dccp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_dccp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : dccp-option]&lt;br /&gt;
==== devgroup ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_devgroup.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== dscp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_dscp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ecn ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_ecn.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== esp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_esp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== hashlimit ====&lt;br /&gt;
* meter statement. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_hashlimit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== helper ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_helper.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ipcomp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_ipcomp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : compres]&lt;br /&gt;
==== iprange ====&lt;br /&gt;
* nft_payload, through native range support. To emulate iptables --ports you need two rules.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_iprange.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ipvs ====&lt;br /&gt;
* consider native interface. Refer to [[Load balancing]].&lt;br /&gt;
==== length ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_length.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit. Refer to [[Stateful objects]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_limit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== mac ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_mac.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_mark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== multiport ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_multiport.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== nfacct ====&lt;br /&gt;
* consider native interface. Refer to [[Stateful objects]].&lt;br /&gt;
==== osf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== owner ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_owner.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : socket-exists]&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_pkttype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== policy ====&lt;br /&gt;
* nft_xfrm, since 5.0&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_policy.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== recent ====&lt;br /&gt;
* consider native interface. Refer to [[Sets]].&lt;br /&gt;
==== sctp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* nft_exthdr for --chunk-types&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_sctp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== socket ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_socket.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== statistic ====&lt;br /&gt;
* nft_numgen. Refer to [[Load balancing]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_statistic.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== set ====&lt;br /&gt;
* Use native nf_tables set infrastructure.&lt;br /&gt;
==== state ====&lt;br /&gt;
* nft_ct&lt;br /&gt;
==== tcp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_tcp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== tcpmss ====&lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_tcpmss.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== time ====&lt;br /&gt;
* nft_meta, since 5.4&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_time.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== udp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_udp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===&lt;br /&gt;
&lt;br /&gt;
==== AUDIT ====&lt;br /&gt;
* nft_log, since 4.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_AUDIT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CLASSIFY ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_CLASSIFY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CONNMARK ====&lt;br /&gt;
* nft_ct&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_CONNMARK.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CONNSECMARK ====&lt;br /&gt;
* nft_ct, since 4.20&lt;br /&gt;
==== DSCP ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_DSCP.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== HL ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
==== HMARK ====&lt;br /&gt;
* nft_meta + nft_hash.&lt;br /&gt;
==== MARK ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_MARK.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== NETMAP ====&lt;br /&gt;
* nft_nat, upcoming 5.8&lt;br /&gt;
==== NFLOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_NFLOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== NFQUEUE ====&lt;br /&gt;
* nft_queue, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_NFQUEUE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SECMARK ====&lt;br /&gt;
* nft_meta, since 4.20&lt;br /&gt;
&lt;br /&gt;
==== SYNPROXY ====&lt;br /&gt;
* nft_synproxy, since 5.3&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_SYNPROXY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TEE ====&lt;br /&gt;
* nft_dup, since 4.3.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TEE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== TPROXY ====&lt;br /&gt;
* nft_tproxy, since 4.19&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TPROXY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TRACE ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TRACE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TCPMSS ====&lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TCPMSS.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== ah ====&lt;br /&gt;
* nft_payload + nft_cmp&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_ah.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== icmp ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_icmp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported codes: network-unreachable, host-unreachable, protocol-unreachable, port-unreachable, fragmentation-needed, source-route-failed, network-unknown, host-unknown, network-prohibited, host-prohibited, TOS-network-unreachable, TOS-host-unreachable, communication-prohibited, host-precedence-violation, precedence-cutoff, network-redirect, host-redirect, TOS-network-redirect, TOS-host-redirect, ttl-zero-during-transit, ttl-zero-during-reassembly, ip-header-bad and required-option-missing ]&lt;br /&gt;
==== realm ====&lt;br /&gt;
* nft_meta, through NFT_META_RTCLASSID.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_realm.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ttl ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_ttl.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv6 ===&lt;br /&gt;
&lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ah  ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_ah.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== eui64 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
==== frag ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_frag.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== hbh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_hbh.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
HBH options are not supported yet.&lt;br /&gt;
[Unsupported option: --hbh-opts]&lt;br /&gt;
==== hl ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_hl.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== icmp6 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_icmp6.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported icmpv6 codes: no-route, communication-prohibited, beyond-scope, address-unreachable, port-unreachable, failed-policy, reject-route, ttl-zero-during-transit, ttl-zero-during-reassembly, bad-header, unknown-header-type and unknown-option]&lt;br /&gt;
==== ipv6header ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
==== mh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_mh.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Needs bug fixation for option mh-type with range]&lt;br /&gt;
==== rt ====&lt;br /&gt;
* nft_exthdr + nft_cmp&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_rt.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options: --rt-0-res, --rt-0-addrs, --rt-0-not-strict]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
==== ECN ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_DNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_LOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_MASQUERADE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_REDIRECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====&lt;br /&gt;
* nft_reject_ipv4, since 3.13.&lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_REJECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_SNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_DNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_LOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_MASQUERADE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_REDIRECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====&lt;br /&gt;
* nft_reject_ipv6, since 3.14.&lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_REJECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_SNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== 802.3 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== among ====&lt;br /&gt;
* sets&lt;br /&gt;
&lt;br /&gt;
==== arp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== ip ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_ip.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== ip6 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_ip6.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_limit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_mark_m.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_pkttype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== stp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== vlan ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_vlan.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== dnat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_dnat.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== snat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_snat.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== redirect ====&lt;br /&gt;
* nft_payload + nft_meta (pkttype set unicast)&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_mark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== watchers: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== log ====&lt;br /&gt;
* nft_log&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_log.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== nflog ====&lt;br /&gt;
* nft_log&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_nflog.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
== Deprecated extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches ===&lt;br /&gt;
&lt;br /&gt;
==== physdev ====&lt;br /&gt;
* br_netfilter aims to be deprecated by nftables.&lt;br /&gt;
==== quota ====&lt;br /&gt;
* nfacct already provides quota support.&lt;br /&gt;
==== tos ====&lt;br /&gt;
* deprecated by dscp&lt;br /&gt;
&lt;br /&gt;
=== targets ===&lt;br /&gt;
&lt;br /&gt;
==== CLUSTERIP ====&lt;br /&gt;
* deprecated by cluster match.&lt;br /&gt;
==== TOS ====&lt;br /&gt;
* deprecated by DSCP&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== ULOG ====&lt;br /&gt;
* Removed from tree since 3.17.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Main_Page&amp;diff=1081</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Main_Page&amp;diff=1081"/>
		<updated>2023-06-23T12:53:23Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* Basic operation */ link to VM code analysis page added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;nftables&#039;&#039; HOWTO documentation page. Here you will find documentation on how to build, install, configure and use nftables.&lt;br /&gt;
&lt;br /&gt;
If you have any suggestion to improve it, please send your comments to Netfilter users mailing list &amp;lt;netfilter@vger.kernel.org&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= [[News]] =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
* [[What is nftables?]]&lt;br /&gt;
* [[How to obtain help/support]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Reference =&lt;br /&gt;
* [https://www.netfilter.org/projects/nftables/manpage.html man nft - netfilter website]&lt;br /&gt;
* [https://www.mankier.com/8/nft man nft - mankier.com]&lt;br /&gt;
* [[Quick reference-nftables in 10 minutes|Quick reference, nftables in 10 minutes]]&lt;br /&gt;
* [[Netfilter hooks]] and nftables integration with existing Netfilter components&lt;br /&gt;
* [[nftables families|Understanding nftables families]]&lt;br /&gt;
* [[Data_types|Data types]]&lt;br /&gt;
* [[Connection_Tracking_System|Connection tracking system (conntrack)]], used for stateful firewalling and NAT&lt;br /&gt;
* [[Troubleshooting|Troubleshooting and FAQ]]&lt;br /&gt;
* [[Further_documentation|Additional documentation]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Installing nftables =&lt;br /&gt;
* [[nftables from distributions|Using nftables from distributions]]&lt;br /&gt;
* [[Building and installing nftables from sources]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Upgrading from xtables to nftables =&lt;br /&gt;
* [[Legacy xtables tools]]&lt;br /&gt;
* [[Moving from iptables to nftables]]&lt;br /&gt;
* [[Moving from ipset to nftables]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Basic operation =&lt;br /&gt;
* [[Configuring tables]]&lt;br /&gt;
* [[Configuring chains]]&lt;br /&gt;
* [[Simple rule management]]&lt;br /&gt;
* [[Atomic rule replacement]]&lt;br /&gt;
* [[Error reporting from the command line]]&lt;br /&gt;
* [[Building rules through expressions]]&lt;br /&gt;
* [[Operations at ruleset level]]&lt;br /&gt;
* [[Monitoring ruleset updates]]&lt;br /&gt;
* [[Scripting]]&lt;br /&gt;
* [[Ruleset debug/tracing]]&lt;br /&gt;
* [[Ruleset debug/VM code analysis]]&lt;br /&gt;
* [[Output text modifiers]]&lt;br /&gt;
&lt;br /&gt;
= Expressions: Matching packets =&lt;br /&gt;
* [[Matching packet metainformation]]&lt;br /&gt;
* [[Matching packet headers]]&lt;br /&gt;
* [[Matching connection tracking stateful metainformation]]&lt;br /&gt;
* [[Matching routing information]]&lt;br /&gt;
* [[Rate limiting matchings]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Statements: Acting on packet matches =&lt;br /&gt;
* [[Accepting and dropping packets]]&lt;br /&gt;
* [[Rejecting traffic]]&lt;br /&gt;
* [[Jumping to chain]]&lt;br /&gt;
* [[Counters]]&lt;br /&gt;
* [[Logging traffic]]&lt;br /&gt;
* [[Performing Network Address Translation (NAT)]]&lt;br /&gt;
* [[Setting packet metainformation]]&lt;br /&gt;
* [[Setting packet connection tracking metainformation]]&lt;br /&gt;
* [[Mangling packet headers]] (including stateless NAT)&lt;br /&gt;
* [[Duplicating packets]]&lt;br /&gt;
* [[Load balancing]]&lt;br /&gt;
* [[Queueing to userspace]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Advanced data structures for performance packet classification =&lt;br /&gt;
* [[Intervals]]&lt;br /&gt;
* [[Concatenations]]&lt;br /&gt;
* [[Math operations]]&lt;br /&gt;
* [[Stateful objects]]&lt;br /&gt;
** [[Counters]]&lt;br /&gt;
** [[Quotas]]&lt;br /&gt;
** [[Limits]]&lt;br /&gt;
** [[Connlimits]] (&#039;&#039;ct count&#039;&#039;)&lt;br /&gt;
* Other objects&lt;br /&gt;
** [[Conntrack helpers]] (&#039;&#039;ct helper&#039;&#039;, Layer 7 ALG)&lt;br /&gt;
** [[Ct_timeout|Conntrack timeout policies]] (&#039;&#039;ct timeout&#039;&#039;)&lt;br /&gt;
** [[Ct_expectation|Conntrack expectations]] (&#039;&#039;ct expectation&#039;&#039;)&lt;br /&gt;
** [[Synproxy]]&lt;br /&gt;
** [[Secmark|Secmarks]]&lt;br /&gt;
* Generic set infrastructure&lt;br /&gt;
** [[Sets]]&lt;br /&gt;
** [[Element timeouts]]&lt;br /&gt;
** [[Updating sets from the packet path]]&lt;br /&gt;
** [[Maps]]&lt;br /&gt;
** [[Verdict_Maps_(vmaps) | Verdict maps]]&lt;br /&gt;
** [[Meters|Metering]] (formerly known as flow tables before nftables 0.8.1)&lt;br /&gt;
* [[Flowtables]] (the fastpath network stack bypass)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
* [[Simple ruleset for a workstation]]&lt;br /&gt;
* [[Simple ruleset for a server]]&lt;br /&gt;
* [[Simple ruleset for a home router]]&lt;br /&gt;
* [[Bridge filtering]]&lt;br /&gt;
* [[Multiple NATs using nftables maps]]&lt;br /&gt;
* [[Classic perimetral firewall example]]&lt;br /&gt;
* [[Port knocking example]]&lt;br /&gt;
* [[Classification to tc structure example]]&lt;br /&gt;
* [[Using configuration management systems]] (like puppet, ansible, etc)&lt;br /&gt;
* [[GeoIP matching]]&lt;br /&gt;
&lt;br /&gt;
= Development =&lt;br /&gt;
&lt;br /&gt;
Check [[Portal:DeveloperDocs|Portal:DeveloperDocs - documentation for netfilter developers]].&lt;br /&gt;
&lt;br /&gt;
Some hints on the general development progress:&lt;br /&gt;
&lt;br /&gt;
* [[List of updates since Linux kernel 3.13]]&lt;br /&gt;
* [[List of updates in the nft command line tool]]&lt;br /&gt;
* [[Supported features compared to xtables|Supported features compared to {ip,ip6,eb,arp}tables]]&lt;br /&gt;
* [[List of available translations via iptables-translate tool]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= External links =&lt;br /&gt;
&lt;br /&gt;
Watch some videos:&lt;br /&gt;
&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=FXTRRwXi3b4 Getting a grasp of nftables], thanks to [https://www.nluug.nl/index-en.html NLUUG association] for recording this.&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=CaYp0d2wiuU#t=1m47s The ultimate packet classifier for GNU/Linux], thanks to the FSFE for paying my trip to Barcelona and for recommending me as speaker to the KDE Spanish branch.&lt;br /&gt;
* [https://www.youtube.com/watch?v=Sy0JDX451ns Florian Westphal - Why nftables?]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=0wQfSfDVN94 NLUUG - Goodbye iptables, Hello nftables]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=Uf5ULkEWPL0 LCA2018 - nftables from a user perspective]&lt;br /&gt;
&lt;br /&gt;
Watch videos to track updates:&lt;br /&gt;
&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=qXVOA2MKA1s Netdev 2.1 - Netfilter mini-workshop (2017)]&lt;br /&gt;
* Watch [https://youtu.be/iCj10vEKPrw Netdev 2.2 - Netf‌ilter mini-workshop (2018)]&lt;br /&gt;
* Watch [https://youtu.be/0hqfzp6tpZo Netdev 0x12 - Netf‌ilter mini-workshop (2019)]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=GqGGo4svj7s&amp;amp;feature=youtu.be Netdev 0x14 - Netfilter mini-Workshop (2020)] &lt;br /&gt;
&lt;br /&gt;
Additional documentations and articles:&lt;br /&gt;
&lt;br /&gt;
* Tutorial [https://zasdfgbnm.github.io/2017/09/07/Extending-nftables/ Extending nftables by Xiang Gao]&lt;br /&gt;
* Article [http://ral-arturo.org/2017/05/05/debian-stretch-stable-nftables.html New in Debian stable Stretch: nftables]&lt;br /&gt;
* Article [https://ral-arturo.org/2020/11/22/python-nftables-tutorial.html How to use nftables from python] and git repository [https://github.com/aborrero/python-nftables-tutorial python-nftables-tutorial.git]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Thanks =&lt;br /&gt;
&lt;br /&gt;
To the NLnet foundation for initial sponsorship of this HOWTO:&lt;br /&gt;
&lt;br /&gt;
[https://nlnet.nl https://nlnet.nl/image/logo.gif]&lt;br /&gt;
&lt;br /&gt;
To Eric Leblond, for boostrapping the [https://home.regit.org/netfilter-en/nftables-quick-howto/ Nftables quick howto] in 2013.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1080</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1080"/>
		<updated>2023-06-23T12:52:05Z</updated>

		<summary type="html">&lt;p&gt;Phil: kernel/user expression relation exported into a dedicated article, link to it from here&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== expressions ==&lt;br /&gt;
&lt;br /&gt;
There are many low expressions that allows us to operate over network packets&lt;br /&gt;
in different ways. You can think on these low level expressions as&lt;br /&gt;
assembly-like instructions.&lt;br /&gt;
&lt;br /&gt;
* nft_immediate: loads an immediate value into a register.&lt;br /&gt;
* nft_cmp: compare a given data with data from a given register.&lt;br /&gt;
* nft_payload: set/get arbitrary data from packet headers.&lt;br /&gt;
* nft_bitwise: perform bit-wise math operations over data in a given register.&lt;br /&gt;
* nft_byteorder: perform byte order operations over data in a given register.&lt;br /&gt;
* nft_counter: a basic counter for packet/bytes that gets incremented everything is evaluated for a packet.&lt;br /&gt;
* nft_meta: set/get packet meta information, such as related interfaces, timestamps, etc.&lt;br /&gt;
* nft_lookup: search for data from a given register (key) into a dataset. If the set is a map/vmap, returns the value for that key.&lt;br /&gt;
&lt;br /&gt;
See [[Ruleset_debug/VM_code_analysis]] for a description of how kernel&#039;s expressions relate to expressions and statements in user space and how to visualise this relation.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
This library provides data structures for entities existing in nf_tables&lt;br /&gt;
nomenclature, such as tables, chains and rules. It serves as an intermediate&lt;br /&gt;
layer between nftables and iptables-nft user space applications and nfnetlink&lt;br /&gt;
messages the kernel sends and receives.&lt;br /&gt;
&lt;br /&gt;
In general, each data structure comes with a set of handling routines:&lt;br /&gt;
&lt;br /&gt;
; allocators : To allocate and free an object of given type&lt;br /&gt;
; setters/getters : Data structure fields are accessed via an attribute number (via a specific enum field)&lt;br /&gt;
; serializers : Populating a netlink message or vice versa&lt;br /&gt;
; printers : Providing a textual representation, mostly for debugging purposes&lt;br /&gt;
&lt;br /&gt;
Where sensible, there is a &#039;&#039;&#039;list-variant&#039;&#039;&#039;, too. If so, it comes with&lt;br /&gt;
handling routines as well:&lt;br /&gt;
&lt;br /&gt;
; allocators : Allocating and freeing the list object (and members)&lt;br /&gt;
; populators : Add and remove from the list&lt;br /&gt;
&lt;br /&gt;
Where useful, there might be a &#039;&#039;&#039;lookup routine&#039;&#039;&#039; as well. With&lt;br /&gt;
nftnl_chain_list, e.g. the list object contains a hash table for chain names as&lt;br /&gt;
well so list lookup by chain name is faster than a linear search.&lt;br /&gt;
&lt;br /&gt;
A typical extra for list objects are &#039;&#039;&#039;iterators&#039;&#039;&#039;: A data structure&lt;br /&gt;
containing state while browsing through the list. Usually the only routines&lt;br /&gt;
used are allocators and a &#039;&#039;next&#039;&#039; routine.&lt;br /&gt;
&lt;br /&gt;
These are the &#039;&#039;&#039;entities defined by libnftnl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
; table : A rather boring &amp;quot;namespace&amp;quot; for chains&lt;br /&gt;
; chain : A container for rules, may attach to a netfilter hook in kernel&lt;br /&gt;
; rule : A container for expressions&lt;br /&gt;
; expr : An nftables VM code instruction&lt;br /&gt;
; flowtable : Similar to a chain, but holds flows between interfaces&lt;br /&gt;
; obj : A generic object, typically holding stateful information&lt;br /&gt;
; ruleset : A container for lists of tables, chains, sets and rules - not used by nftables application anymore&lt;br /&gt;
; set : A container for elements&lt;br /&gt;
; set_elem : A set element&lt;br /&gt;
; trace : A trace event sent by the kernel&lt;br /&gt;
&lt;br /&gt;
=== nftnl_expr ===&lt;br /&gt;
&lt;br /&gt;
While nftables distinguishes between expressions and statements, such&lt;br /&gt;
difference does not quite exist in libnftnl layer. For instance, a statement&lt;br /&gt;
like:&lt;br /&gt;
 ip saddr 192.168.0.1&lt;br /&gt;
is actually two expressions:&lt;br /&gt;
; payload : loading IPv4 header&#039;s source address into a register&lt;br /&gt;
; cmp : comparing data from a register against a stored value&lt;br /&gt;
&lt;br /&gt;
Since expressions have access to the packet, its meta data, all nftables&lt;br /&gt;
registers (including the verdict register) and may store multiple values&lt;br /&gt;
internally, they are mighty and versatile.&lt;br /&gt;
&lt;br /&gt;
=== nftnl_obj ===&lt;br /&gt;
&lt;br /&gt;
This is a common API for various object types. An object&#039;s type is defined post&lt;br /&gt;
allocation by setting the &#039;&#039;NFTNL_OBJ_TYPE&#039;&#039; attribute. Currently existing&lt;br /&gt;
object types are:&lt;br /&gt;
&lt;br /&gt;
* counter&lt;br /&gt;
* quota&lt;br /&gt;
* ct helper&lt;br /&gt;
* limit&lt;br /&gt;
* tunnel&lt;br /&gt;
* ct timeout&lt;br /&gt;
* secmark&lt;br /&gt;
* ct expect&lt;br /&gt;
* synproxy&lt;br /&gt;
&lt;br /&gt;
=== nftnl_batch ===&lt;br /&gt;
&lt;br /&gt;
This is a wrapper interface around the same functionality in libmnl (which is&lt;br /&gt;
used internally). In general, nftnl batches aid in collecting multiple netlink&lt;br /&gt;
messages for kernel submission.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
One goal in nftables development was to provide users with a library for easier&lt;br /&gt;
integration into applications than &amp;quot;shelling out&amp;quot; using &#039;&#039;system()&#039;&#039; and trying&lt;br /&gt;
to parse &#039;&#039;nft&#039;&#039; command output.&lt;br /&gt;
&lt;br /&gt;
At first, &#039;&#039;libnftnl&#039;&#039; was supposed to achieve this but the fact that it&lt;br /&gt;
exposes internal implementation details apart from being pretty low-level in&lt;br /&gt;
general made it rather unsuitable from a users&#039; perspective.&lt;br /&gt;
&lt;br /&gt;
To overcome this, &#039;&#039;nft&#039;&#039; backend code was separated into a library which&lt;br /&gt;
should fill the gap between &#039;&#039;libnftnl&#039;&#039; on one side and &#039;&#039;nft&#039;&#039; application&lt;br /&gt;
itself on the other.&lt;br /&gt;
&lt;br /&gt;
Usage of &#039;&#039;libnftables&#039;&#039; is supposed to be simple and straightforward, almost&lt;br /&gt;
like calling &#039;&#039;nft&#039;&#039; itself but with a bit more convenience. First step is to&lt;br /&gt;
create a new context:&lt;br /&gt;
&lt;br /&gt;
  struct nft_ctx *ctx = nft_ctx_new(0);&lt;br /&gt;
&lt;br /&gt;
The context allows to configure library behaviour on a &amp;quot;per session&amp;quot; basis.&lt;br /&gt;
With this in place, nftables commands may be executed:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_buffer(ctx, &amp;quot;add table inet t&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or whole dump files loaded:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_filename(ctx, &amp;quot;/etc/nftables/all-in-one.nft&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To control output, there are a number of functions:&lt;br /&gt;
&lt;br /&gt;
  FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);&lt;br /&gt;
  int nft_ctx_buffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  int nft_ctx_unbuffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  const char *nft_ctx_get_output_buffer(struct nft_ctx *ctx);&lt;br /&gt;
&lt;br /&gt;
Same for stderr. See libnftables(3) man page for further details.&lt;br /&gt;
&lt;br /&gt;
= nft: from user space to the kernel =&lt;br /&gt;
&lt;br /&gt;
The following describes the steps and entities involved after a call to&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039; in user space until the actual communication with the kernel.&lt;br /&gt;
&lt;br /&gt;
Since creation of &#039;&#039;&#039;libnftables&#039;&#039;&#039;, &#039;&#039;&#039;nft&#039;&#039;&#039; is merely a lightweight&lt;br /&gt;
front-end, basically just creating a &#039;&#039;&#039;libnftables&#039;&#039;&#039; handle, allowing to&lt;br /&gt;
configure it via command-line options and feeding &#039;&#039;&#039;nftables&#039;&#039;&#039; syntax into&lt;br /&gt;
it. Within the library, the actual work takes place. It may be divided into&lt;br /&gt;
several phases:&lt;br /&gt;
&lt;br /&gt;
* Input parsing into internal data structure&lt;br /&gt;
* Evaluation and expansion&lt;br /&gt;
* Serialization into netlink messages&lt;br /&gt;
* nfnetlink message session with kernel&lt;br /&gt;
* Error handling&lt;br /&gt;
&lt;br /&gt;
== Input parsing into internal data structures ==&lt;br /&gt;
&lt;br /&gt;
Depending on whether input comes from command line or a file (which may be&lt;br /&gt;
&#039;&#039;stdin&#039;&#039;), &#039;&#039;&#039;main()&#039;&#039;&#039; calls either &#039;&#039;&#039;nft_run_cmd_from_buffer()&#039;&#039;&#039; or&lt;br /&gt;
&#039;&#039;&#039;nft_run_cmd_from_filename()&#039;&#039;&#039; library functions.&lt;br /&gt;
&lt;br /&gt;
If JSON output was selected (&#039;&#039;&#039;nft -j&#039;&#039;&#039;), the JSON parser (in&lt;br /&gt;
&#039;&#039;src/parser_json.c&#039;&#039;) is tried first. If this did not succeed, the standard&lt;br /&gt;
(&amp;quot;human-readable&amp;quot;) syntax parser is called.&lt;br /&gt;
&lt;br /&gt;
Eventually both parsers populate a list of commands (&#039;&#039;&#039;struct cmd&#039;&#039;&#039;) and a&lt;br /&gt;
list of error messages (&#039;&#039;&#039;struct error_record&#039;&#039;&#039;) in case errors were&lt;br /&gt;
detected.&lt;br /&gt;
&lt;br /&gt;
=== Standard syntax ===&lt;br /&gt;
&lt;br /&gt;
The parser for standard syntax is implemented in lex and yacc, see&lt;br /&gt;
&#039;&#039;src/scanner.l&#039;&#039; and &#039;&#039;src/parser_bison.y&#039;&#039; for reference. It is entered via&lt;br /&gt;
the generated function &#039;&#039;&#039;nft_parse()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As a basic rule, in lex/yacc the scanner recognizes the words and the parser&lt;br /&gt;
interprets them in their context. There is also (limited) scanner control from&lt;br /&gt;
the parser by definition of a scope in which some words are valid or not. The&lt;br /&gt;
parser defines recursive patterns to match input against. Here is the top-most&lt;br /&gt;
one, &#039;&#039;&#039;input&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
input       :       /* empty */&lt;br /&gt;
            |       input           line&lt;br /&gt;
            {&lt;br /&gt;
                    if ($2 != NULL) {&lt;br /&gt;
                            $2-&amp;gt;location = @2;&lt;br /&gt;
                            list_add_tail(&amp;amp;$2-&amp;gt;list, state-&amp;gt;cmds);&lt;br /&gt;
                    }&lt;br /&gt;
            }&lt;br /&gt;
            ;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So it may be empty or (by recursion) consist of a number of&lt;br /&gt;
&#039;&#039;&#039;line&#039;&#039;&#039; patterns. Each of those lines parses into a command and is appended&lt;br /&gt;
to the list. The snippet above also shows how parser-provided &#039;&#039;&#039;location&#039;&#039;&#039;&lt;br /&gt;
data is stored in the command object. This is used for error reporting.&lt;br /&gt;
&lt;br /&gt;
=== JSON syntax ===&lt;br /&gt;
&lt;br /&gt;
The JSON parser lives in &#039;&#039;src/parser_json.c&#039;&#039; and is entered via&lt;br /&gt;
&#039;&#039;&#039;nft_parse_json_buffer()&#039;&#039;&#039; function or &#039;&#039;&#039;nft_parse_json_filename()&#039;&#039;&#039;,&lt;br /&gt;
respectively. It uses jansson library for (de-)serialization and value&lt;br /&gt;
(un-)packing. To learn about the code and to understand the program flow,&lt;br /&gt;
&#039;&#039;&#039;json_parse_cmd()&#039;&#039;&#039; function is a good starting point.&lt;br /&gt;
&lt;br /&gt;
== Evaluation and expansion ==&lt;br /&gt;
&lt;br /&gt;
Input evaluation is a crucial step and combines several tasks. It extends input&lt;br /&gt;
validation from mere syntax checks done by the parser to semantical ones,&lt;br /&gt;
taking context into perspective.&lt;br /&gt;
&lt;br /&gt;
Input may be changed, too. Sometimes it is necessary to insert extra statements&lt;br /&gt;
as dependency, sometimes types of right hand sides of comparisons must adjust&lt;br /&gt;
to left hand side type.&lt;br /&gt;
&lt;br /&gt;
Before all the above, the list of commands is scanned for cache requirements -&lt;br /&gt;
see &#039;&#039;&#039;nft_cache_evaluate()&#039;&#039;&#039; for details. Since caching may be an expensive&lt;br /&gt;
operation if in-kernel ruleset is huge, this step attempts to reduce the data&lt;br /&gt;
fetched from kernel to the bare minimum needed for correct operation. A final&lt;br /&gt;
call to &#039;&#039;&#039;nft_cache_update()&#039;&#039;&#039; then does the actual fetch.&lt;br /&gt;
&lt;br /&gt;
If evaluation passed, expansion takes place. This is mostly to cover for input&lt;br /&gt;
in &amp;quot;dump&amp;quot; notation, i.e. rules nested in chains nested in tables, etc. Such&lt;br /&gt;
input is converted into individual &amp;quot;add&amp;quot; commands as required by the netlink&lt;br /&gt;
message format. The code is pretty straightforward, see &#039;&#039;&#039;nft_cmd_expand()&#039;&#039;&#039;&lt;br /&gt;
for reference.&lt;br /&gt;
&lt;br /&gt;
== Serialization into netlink messages ==&lt;br /&gt;
&lt;br /&gt;
In this step, &#039;&#039;&#039;nftables&#039;&#039;&#039;-internal data types are converted into&lt;br /&gt;
&#039;&#039;&#039;libnftables&#039;&#039;&#039; ones (e.g., &#039;&#039;&#039;struct table&#039;&#039;&#039; into&lt;br /&gt;
&#039;&#039;&#039;struct nftnl_table&#039;&#039;&#039;). The latter abstract their internal layout as&lt;br /&gt;
attributes and are therefore opaque to the caller.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;libnftnl&#039;&#039;&#039; provides helpers to convert its own data structures into netlink&lt;br /&gt;
message format: A generic &#039;&#039;&#039;nftnl_nlmsg_build_hdr()&#039;&#039;&#039; for the header and&lt;br /&gt;
type-specific ones for the payload (e.g.,&lt;br /&gt;
&#039;&#039;&#039;nftnl_table_nlmsg_build_payload()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
The netlink messages are stored in a &#039;&#039;&#039;struct nftnl_batch&#039;&#039;&#039; which provides&lt;br /&gt;
the backing storage. This surrounding data structure serializes into an&lt;br /&gt;
introductory &#039;&#039;&#039;NFNL_MSG_BATCH_BEGIN&#039;&#039;&#039; message and a finalizing one with type&lt;br /&gt;
&#039;&#039;&#039;NFNL_MSG_BATCH_END&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In kernel space, the batch constitutes a transaction: If one of the messages is&lt;br /&gt;
rejected, none of them take effect. Ditto, if the final batch end message is&lt;br /&gt;
missing the whole batch will undo. This is how &#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s &#039;&#039;&#039;--check&#039;&#039;&#039; option&lt;br /&gt;
is implemented.&lt;br /&gt;
&lt;br /&gt;
== nfnetlink message session with kernel ==&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;nft&#039;&#039;&#039;, communication with the kernel takes place in the function&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_talk()&#039;&#039;&#039;: It converts the &#039;&#039;&#039;nftnl_batch&#039;&#039;&#039; into a message&lt;br /&gt;
suitable for &#039;&#039;&#039;sendmsg()&#039;&#039;&#039;, adjusts buffer sizes (if needed), transmits the&lt;br /&gt;
data and listens for a reply. Any error messages are handled by&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_extack_cb()&#039;&#039;&#039; function which records them for later reporting.&lt;br /&gt;
Other messages are relevant for &#039;&#039;&#039;--echo&#039;&#039;&#039; mode, in which the kernel &amp;quot;echoes&amp;quot;&lt;br /&gt;
the requests back after updating them (with handle values, for instance). These&lt;br /&gt;
are handled by &#039;&#039;&#039;netlink_echo_callback()&#039;&#039;&#039;, more or less a wrapper around&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s event monitoring code.&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
Each &#039;&#039;&#039;struct cmd&#039;&#039;&#039; object is identified by its own sequence number&lt;br /&gt;
(monotonic within the batch). Netlink error messages contain this number and&lt;br /&gt;
also an offset value, which allow to identify not only the problematic message&lt;br /&gt;
but also the specific attribute of that message which was rejected.&lt;br /&gt;
&lt;br /&gt;
Mapping from message attribute back to line or word(s) of input works via a&lt;br /&gt;
mapping from attribute offset to the &#039;&#039;&#039;struct location&#039;&#039;&#039; object stored while&lt;br /&gt;
parsing. That bison parser-provided data holds line and column numbers,&lt;br /&gt;
allowing &#039;&#039;&#039;nft&#039;&#039;&#039; to underline problematic parts of input when reporting back&lt;br /&gt;
to the caller.&lt;br /&gt;
&lt;br /&gt;
To follow the above in the source code, see &#039;&#039;&#039;nft_cmd_error()&#039;&#039;&#039; function&lt;br /&gt;
being called for each command and error it caused. The mapping is established&lt;br /&gt;
earlier while creating netlink messages, i.e. in code called from&lt;br /&gt;
&#039;&#039;&#039;do_command()&#039;&#039;&#039; - watch out for the various calls to &#039;&#039;&#039;cmd_add_loc()&#039;&#039;&#039;&lt;br /&gt;
populating the field &#039;&#039;&#039;attr&#039;&#039;&#039; in &#039;&#039;&#039;struct cmd&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to user space =&lt;br /&gt;
&lt;br /&gt;
Communication between &#039;&#039;&#039;nft&#039;&#039;&#039; in user space and &#039;&#039;&#039;nftables&#039;&#039;&#039; in  kernel&lt;br /&gt;
happens via netlink, a packet-based IPC mechanism for that purpose. Its kernel&lt;br /&gt;
source code lives in &#039;&#039;net/netlink&#039;&#039; directory and allows to be extended by&lt;br /&gt;
calling &#039;&#039;&#039;netlink_kernel_create()&#039;&#039;&#039;, passing a unique &#039;&#039;&#039;unit&#039;&#039;&#039; number and a&lt;br /&gt;
&#039;&#039;&#039;struct netlink_kernel_cfg&#039;&#039;&#039; object.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nfnetlink&#039;&#039;&#039; is such an extension, attempting to serve all netfilter-related&lt;br /&gt;
user space applications. It is implemented in &#039;&#039;net/netfilter/nfnetlink.c&#039;&#039; and&lt;br /&gt;
itself allows to be extended as well by means of groups (see&lt;br /&gt;
&#039;&#039;&#039;nfnetlink_groups&#039;&#039;&#039; in &#039;&#039;include/uapi/linux/netfilter/nfnetlink.h&#039;&#039;). These&lt;br /&gt;
in turn map to nfnetlink subsystems, see the constant array&lt;br /&gt;
&#039;&#039;&#039;nfnl_group2type&#039;&#039;&#039; in nfnetlink source file. &#039;&#039;&#039;NFNL_SUBSYS_NFTABLES&#039;&#039;&#039; is&lt;br /&gt;
the relevant one here, implemented in &#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039; (see&lt;br /&gt;
&#039;&#039;&#039;nf_tables_subsys&#039;&#039;&#039; and the call to &#039;&#039;&#039;nfnetlink_subsys_register()&#039;&#039;&#039; in&lt;br /&gt;
there).&lt;br /&gt;
&lt;br /&gt;
For insight, it is worthwhile to remain in generic &#039;&#039;&#039;nfnetlink&#039;&#039;&#039; code for a&lt;br /&gt;
little longer: &#039;&#039;&#039;nfnetlink_net_ops&#039;&#039;&#039; are registered as a &amp;quot;pernet&amp;quot; subsystem,&lt;br /&gt;
i.e. each network namespace gets its own instance. Upon netns creation,&lt;br /&gt;
&#039;&#039;&#039;nfnetlink_net_init()&#039;&#039;&#039; is called which actually creates the&lt;br /&gt;
&#039;&#039;&#039;NETLINK_NETFILTER&#039;&#039;&#039; subsystem. Its receive callback (&#039;&#039;&#039;nfnetlink_rcv()&#039;&#039;&#039;)&lt;br /&gt;
checks whether the first message header starts a batch and diverts the code&lt;br /&gt;
flow accordingly.&lt;br /&gt;
&lt;br /&gt;
For batch handling, subsystems need to define &#039;&#039;&#039;commit&#039;&#039;&#039; and &#039;&#039;&#039;abort&#039;&#039;&#039;&lt;br /&gt;
callbacks. Also, for each contained message, there must be a responsible&lt;br /&gt;
callback entry with type &#039;&#039;&#039;NFNL_CB_BATCH&#039;&#039;&#039;. &#039;&#039;&#039;nf_tables_subsys&#039;&#039;&#039; fulfills&lt;br /&gt;
these requirements.&lt;br /&gt;
&lt;br /&gt;
Each callback in &#039;&#039;&#039;nf_tables_cb&#039;&#039;&#039; (and therefore each supported message type)&lt;br /&gt;
decides whether it must be part of a batch or not - nfnetlink code does not&lt;br /&gt;
allow for multiple handlers of the same message. In nftables, only getters for&lt;br /&gt;
different ruleset elements are non-batch, anything mangling the ruleset is.&lt;br /&gt;
&lt;br /&gt;
== Non-batched handlers ==&lt;br /&gt;
&lt;br /&gt;
These are getters for:&lt;br /&gt;
&lt;br /&gt;
 * table&lt;br /&gt;
 * chain&lt;br /&gt;
 * rule&lt;br /&gt;
 * set&lt;br /&gt;
 * set element&lt;br /&gt;
 * generation ID&lt;br /&gt;
 * stateful objects&lt;br /&gt;
 * flowtable&lt;br /&gt;
&lt;br /&gt;
They all behave similar: Unless &#039;&#039;&#039;NLM_F_DUMP&#039;&#039;&#039; flag is set in the message,&lt;br /&gt;
they perform a lookup based on the required identifiers and return an nfnetlink&lt;br /&gt;
message to user space. There are type-specific helpers populating a netlink&lt;br /&gt;
message named &#039;&#039;&#039;nf_tables_fill_&amp;lt;SOMETHING&amp;gt;_info&#039;&#039;&#039;, packet sending is done by&lt;br /&gt;
a call to &#039;&#039;&#039;nfnetlink_unicast()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;&#039;NLM_F_DUMP&#039;&#039;&#039; was given, the getter iterates over all ruleset elements of&lt;br /&gt;
given type and fills a netlink message for each. In some cases, filtering the&lt;br /&gt;
output by identifiers given in the request is supported - useful to dump e.g.&lt;br /&gt;
all rules of a specific chain only.&lt;br /&gt;
&lt;br /&gt;
The iterator code is a bit complicated due to the fact that socket buffer size&lt;br /&gt;
may be exceeded. In that case, partial data is submitted to user space and the&lt;br /&gt;
dump continued afterwards. The iterators keep a &amp;quot;cursor&amp;quot; (actually a counter)&lt;br /&gt;
for where to pick up again.&lt;br /&gt;
&lt;br /&gt;
== Batched handlers ==&lt;br /&gt;
&lt;br /&gt;
To allow for rolling back a transaction which has failed or was aborted,&lt;br /&gt;
message handlers of type &#039;&#039;&#039;NFNL_CB_BATCH&#039;&#039;&#039; allocate a &#039;&#039;&#039;struct nft_trans&#039;&#039;&#039;&lt;br /&gt;
object and add it to the per-net commit list. This &amp;quot;log&amp;quot; of what was done is&lt;br /&gt;
also useful to defer actions till the very end of the transaction. See&lt;br /&gt;
&#039;&#039;&#039;nf_tables_commit()&#039;&#039;&#039; for reference of what it is used for in the&lt;br /&gt;
success-case. Similar code is found in &#039;&#039;&#039;nf_tables_abort()&#039;&#039;&#039;, reverting the&lt;br /&gt;
previous changes.&lt;br /&gt;
&lt;br /&gt;
To make the ruleset update atomic, nftables uses an internal generation ID. Its&lt;br /&gt;
value alternates between zero and one upon each commit. Ruleset elements have a&lt;br /&gt;
two-bit &amp;quot;generation mask&amp;quot;, indicating whether that element is active in the&lt;br /&gt;
generation at its bit index. This way, elements may die, get born or stay alive&lt;br /&gt;
when the generation ID toggles again.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Ruleset_debug/VM_code_analysis&amp;diff=1079</id>
		<title>Ruleset debug/VM code analysis</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Ruleset_debug/VM_code_analysis&amp;diff=1079"/>
		<updated>2023-06-23T12:47:03Z</updated>

		<summary type="html">&lt;p&gt;Phil: Page created&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In the kernel, nf_tables is implemented as a virtual machine with its own&lt;br /&gt;
instruction set. The kernel&#039;s &#039;&#039;&#039;expressions&#039;&#039;&#039; implement such instructions. In&lt;br /&gt;
user space, the mapping is not (necessarily) as direct as this.&lt;br /&gt;
&lt;br /&gt;
= Statements and expressions in user space =&lt;br /&gt;
&lt;br /&gt;
In user space nomenclature, a distinction is made between &#039;&#039;&#039;statements&#039;&#039;&#039; and&lt;br /&gt;
&#039;&#039;&#039;expressions&#039;&#039;&#039;; the relevant difference is that the former are valid parts&lt;br /&gt;
of a rule on their own while the latter usually appear as parameter or input to&lt;br /&gt;
a statement. For instance, take the following &#039;&#039;&#039;payload statement&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 ip dscp set 42&lt;br /&gt;
&lt;br /&gt;
Here, &#039;&#039;&#039;ip dscp&#039;&#039;&#039; is an expression identifying what part of the packet&lt;br /&gt;
payload to mangle, &#039;&#039;&#039;42&#039;&#039;&#039; is a constant expression holding the value to&lt;br /&gt;
assign. There are certain limits as to what may appear after the &#039;&#039;&#039;set&#039;&#039;&#039;&lt;br /&gt;
keyword, nft does some type checking to make sure it is compatible. But to&lt;br /&gt;
illustrate the power this concept has, take the following example:&lt;br /&gt;
&lt;br /&gt;
 tcp dport set tcp sport&lt;br /&gt;
&lt;br /&gt;
This will mangle a TCP packet&#039;s destination port to match whatever its source&lt;br /&gt;
port value may be. Albeit a bit constructed, this is an example of a statement&lt;br /&gt;
accepting data from two expressions.&lt;br /&gt;
&lt;br /&gt;
= Expressions in kernel space =&lt;br /&gt;
&lt;br /&gt;
The kernel does not have the concept of a statement. There are merely&lt;br /&gt;
expressions (instructions) loading data from or writing to registers, thereby&lt;br /&gt;
interacting with each other. Aside from twenty general purpose data registers&lt;br /&gt;
(each sized four bytes), there is a single &#039;&#039;&#039;verdict&#039;&#039;&#039; register used to&lt;br /&gt;
terminate rule or even chain traversal available to expressions.&lt;br /&gt;
&lt;br /&gt;
= VM bytecode in action =&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;nft&#039;&#039;&#039; translates user input into VM code for the kernel, it translates&lt;br /&gt;
from statements and expressions as user space knows them into VM code calling&lt;br /&gt;
kernel&#039;s expressions. Passing the &#039;&#039;&#039;--debug=netlink&#039;&#039;&#039; option makes this visual:&lt;br /&gt;
&lt;br /&gt;
 nft --debug=netlink add rule inet t c ip daddr 10.1.2.3 counter accept&lt;br /&gt;
 inet t c&lt;br /&gt;
   [ meta load nfproto =&amp;gt; reg 1 ]&lt;br /&gt;
   [ cmp eq reg 1 0x00000002 ]&lt;br /&gt;
   [ payload load 4b @ network header + 16 =&amp;gt; reg 1 ]&lt;br /&gt;
   [ cmp eq reg 1 0x0302010a ]&lt;br /&gt;
   [ counter pkts 0 bytes 0 ]&lt;br /&gt;
   [ immediate reg 0 accept ]&lt;br /&gt;
&lt;br /&gt;
The rule added by the command above matches the packet&#039;s&lt;br /&gt;
&#039;&#039;&#039;IPv4 Destination Address&#039;&#039;&#039; field against the value &#039;&#039;&#039;10.1.2.3&#039;&#039;&#039;, counts&lt;br /&gt;
matching packets and finally accepts them (thereby ending chain traversal for&lt;br /&gt;
this packet.&lt;br /&gt;
&lt;br /&gt;
The printed VM bytecode reveals a few more interesting details:&lt;br /&gt;
&lt;br /&gt;
# The rule actually starts with a match on &#039;&#039;&#039;meta nfproto&#039;&#039;&#039; value: Because the chain resides in inet family, it may see packets other than IPv4 ones as well. This filtering is necessary because:&lt;br /&gt;
# User space&#039;s &#039;&#039;&#039;ip daddr&#039;&#039;&#039; expression is actually very generic: The &#039;&#039;&#039;payload&#039;&#039;&#039; expression it translates into merely loads 4B from the network header at offset 16B into register 1. With an IPv6 packet, this would happily load parts of the Source Address field, which might even match the value 0x0302010a by accident. To avoid such unexpected (and unforseeable) behaviour, the implicit &#039;&#039;&#039;meta nfproto&#039;&#039;&#039; match is required.&lt;br /&gt;
# Packet matching is often implicit: The second expression, comparing &#039;&#039;&#039;meta nfproto&#039;&#039;&#039; value against &#039;&#039;&#039;0x02&#039;&#039;&#039; (= NFPROTO_IPV4) for equality (&#039;&#039;&#039;eq&#039;&#039;&#039;). If not successful, it will write the value &#039;&#039;&#039;NFT_BREAK&#039;&#039;&#039; into the verdict register and chain traversal continues with the next rule.&lt;br /&gt;
# Contrary to the above, the last expression is an explicit access to the verdict register (&#039;&#039;&#039;reg 0&#039;&#039;&#039;), writing NF_ACCEPT.&lt;br /&gt;
&lt;br /&gt;
= Statements in VM bytecode =&lt;br /&gt;
&lt;br /&gt;
Picking up one of the examples above:&lt;br /&gt;
&lt;br /&gt;
 nft --debug=netlink add rule t c tcp dport set tcp sport&lt;br /&gt;
 ip t c&lt;br /&gt;
   [ meta load l4proto =&amp;gt; reg 1 ]&lt;br /&gt;
   [ cmp eq reg 1 0x00000006 ]&lt;br /&gt;
   [ payload load 2b @ transport header + 0 =&amp;gt; reg 1 ]&lt;br /&gt;
   [ payload write reg 1 =&amp;gt; 2b @ transport header + 2 csum_type 1 csum_off 16 csum_flags 0x0 ]&lt;br /&gt;
&lt;br /&gt;
This reveals how &#039;&#039;&#039;payload statement&#039;&#039;&#039; is actually just a variant of the&lt;br /&gt;
kernel&#039;s &#039;&#039;&#039;payload expression&#039;&#039; which writes instead of reads. Some further&lt;br /&gt;
observations:&lt;br /&gt;
&lt;br /&gt;
# There is again an implicit match present, this time to assert &#039;&#039;&#039;meta l4proto&#039;&#039;&#039; matches the value 0x6 (= IPPROTO_TCP). Again to make sure the following payload expressions don&#039;t read garbage or write to odd parts of the packet.&lt;br /&gt;
# The second &#039;&#039;&#039;payload expression&#039;&#039; also holds extra information for a partial checksum update which is necessary after mangling an IPv4 packet.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1078</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1078"/>
		<updated>2023-06-22T16:56:33Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* expressions */ Documented relation between expressions in kernel and user space&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== expressions ==&lt;br /&gt;
&lt;br /&gt;
There are many low expressions that allows us to operate over network packets&lt;br /&gt;
in different ways. You can think on these low level expressions as&lt;br /&gt;
assembly-like instructions.&lt;br /&gt;
&lt;br /&gt;
* nft_immediate: loads an immediate value into a register.&lt;br /&gt;
* nft_cmp: compare a given data with data from a given register.&lt;br /&gt;
* nft_payload: set/get arbitrary data from packet headers.&lt;br /&gt;
* nft_bitwise: perform bit-wise math operations over data in a given register.&lt;br /&gt;
* nft_byteorder: perform byte order operations over data in a given register.&lt;br /&gt;
* nft_counter: a basic counter for packet/bytes that gets incremented everything is evaluated for a packet.&lt;br /&gt;
* nft_meta: set/get packet meta information, such as related interfaces, timestamps, etc.&lt;br /&gt;
* nft_lookup: search for data from a given register (key) into a dataset. If the set is a map/vmap, returns the value for that key.&lt;br /&gt;
&lt;br /&gt;
=== Relation to User Space ===&lt;br /&gt;
&lt;br /&gt;
In user space terminology, there&#039;s a distinction between &#039;&#039;&#039;statements&#039;&#039;&#039; like&lt;br /&gt;
&#039;&#039;counter&#039;&#039;, &#039;&#039;jump&#039;&#039; or &#039;&#039;log&#039;&#039; and &#039;&#039;&#039;expressions&#039;&#039;&#039; like &#039;&#039;ip saddr&#039;&#039;,&lt;br /&gt;
&#039;&#039;tcp dport&#039;&#039; or &#039;&#039;meta iifname&#039;&#039;. What distinguishes them is the fact that&lt;br /&gt;
&#039;&#039;&#039;statements&#039;&#039;&#039; are valid ruleset elements on their own while&lt;br /&gt;
&#039;&#039;&#039;expressions&#039;&#039;&#039; are usually arguments to a statement. For instance, take the&lt;br /&gt;
following &#039;&#039;&#039;payload statement&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
  ip dscp set 42&lt;br /&gt;
&lt;br /&gt;
Here, &#039;&#039;&#039;ip dscp&#039;&#039;&#039; is an expression identifying what part of the packet&lt;br /&gt;
payload to mangle, &#039;&#039;&#039;42&#039;&#039;&#039; is a constant expression holding the value to&lt;br /&gt;
assign. There are certain limits as to what may appear after the &#039;&#039;&#039;set&#039;&#039;&#039;&lt;br /&gt;
keyword, nft does some type checking to make sure it is compatible. But to&lt;br /&gt;
illustrate the power this concept has, take the following example:&lt;br /&gt;
&lt;br /&gt;
  tcp dport set tcp sport&lt;br /&gt;
&lt;br /&gt;
This will mangle a TCP packet&#039;s destination port to match whatever its source&lt;br /&gt;
port value may be. Albeit a bit constructed, this is an example of a statement&lt;br /&gt;
accepting data from two expressions. Because kernel space does not make the&lt;br /&gt;
distinction though, there must be some kind of translation happening. To analyse this, nft&#039;s &#039;&#039;&#039;--debug=netlink&#039;&#039;&#039; flag is handy:&lt;br /&gt;
&lt;br /&gt;
  nft --debug=netlink add rule t c tcp dport set tcp sport&lt;br /&gt;
  ip t c&lt;br /&gt;
    [ meta load l4proto =&amp;gt; reg 1 ]&lt;br /&gt;
    [ cmp eq reg 1 0x00000006 ]&lt;br /&gt;
    [ payload load 2b @ transport header + 0 =&amp;gt; reg 1 ]&lt;br /&gt;
    [ payload write reg 1 =&amp;gt; 2b @ transport header + 2 csum_type 1 csum_off 16 csum_flags 0x0 ]&lt;br /&gt;
&lt;br /&gt;
It prints the (libnftnl/kernel) expressions a rule consists of. This reveals&lt;br /&gt;
some interesting details:&lt;br /&gt;
&lt;br /&gt;
# There is an invisible match on &#039;&#039;&#039;meta l4proto&#039;&#039;&#039; at the start of the rule. This is a dependency imposed by the &#039;&#039;&#039;tcp sport/dport&#039;&#039;&#039; expressions which work right with TCP packets only. To avoid unexpected results, nft makes sure non-TCP packets won&#039;t match the rule right from the start.&lt;br /&gt;
&lt;br /&gt;
# Registers enable data to pass between expressions: The first expression loads the packet&#039;s layer4 protocol value into &#039;&#039;&#039;reg 1&#039;&#039;&#039;, the second expression compares &#039;&#039;&#039;reg 1&#039;&#039;&#039;&#039;s value against the value 0x6.&lt;br /&gt;
&lt;br /&gt;
# There are two &amp;quot;variants&amp;quot; of a payload expression: one that merely loads data from the packet and one that writes it. One could say the first one is the payload expression and the latter the payload statement in nft&#039;s nomenclature.&lt;br /&gt;
&lt;br /&gt;
# The second payload expression which writes 2B from &#039;&#039;&#039;reg 1&#039;&#039;&#039; into the packet at the offset of the transport header plus 2B (the position of the TCP header&#039;s &#039;&#039;&#039;Destination Port&#039;&#039;&#039; field), also holds extra information for a partial checksum update.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
This library provides data structures for entities existing in nf_tables&lt;br /&gt;
nomenclature, such as tables, chains and rules. It serves as an intermediate&lt;br /&gt;
layer between nftables and iptables-nft user space applications and nfnetlink&lt;br /&gt;
messages the kernel sends and receives.&lt;br /&gt;
&lt;br /&gt;
In general, each data structure comes with a set of handling routines:&lt;br /&gt;
&lt;br /&gt;
; allocators : To allocate and free an object of given type&lt;br /&gt;
; setters/getters : Data structure fields are accessed via an attribute number (via a specific enum field)&lt;br /&gt;
; serializers : Populating a netlink message or vice versa&lt;br /&gt;
; printers : Providing a textual representation, mostly for debugging purposes&lt;br /&gt;
&lt;br /&gt;
Where sensible, there is a &#039;&#039;&#039;list-variant&#039;&#039;&#039;, too. If so, it comes with&lt;br /&gt;
handling routines as well:&lt;br /&gt;
&lt;br /&gt;
; allocators : Allocating and freeing the list object (and members)&lt;br /&gt;
; populators : Add and remove from the list&lt;br /&gt;
&lt;br /&gt;
Where useful, there might be a &#039;&#039;&#039;lookup routine&#039;&#039;&#039; as well. With&lt;br /&gt;
nftnl_chain_list, e.g. the list object contains a hash table for chain names as&lt;br /&gt;
well so list lookup by chain name is faster than a linear search.&lt;br /&gt;
&lt;br /&gt;
A typical extra for list objects are &#039;&#039;&#039;iterators&#039;&#039;&#039;: A data structure&lt;br /&gt;
containing state while browsing through the list. Usually the only routines&lt;br /&gt;
used are allocators and a &#039;&#039;next&#039;&#039; routine.&lt;br /&gt;
&lt;br /&gt;
These are the &#039;&#039;&#039;entities defined by libnftnl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
; table : A rather boring &amp;quot;namespace&amp;quot; for chains&lt;br /&gt;
; chain : A container for rules, may attach to a netfilter hook in kernel&lt;br /&gt;
; rule : A container for expressions&lt;br /&gt;
; expr : An nftables VM code instruction&lt;br /&gt;
; flowtable : Similar to a chain, but holds flows between interfaces&lt;br /&gt;
; obj : A generic object, typically holding stateful information&lt;br /&gt;
; ruleset : A container for lists of tables, chains, sets and rules - not used by nftables application anymore&lt;br /&gt;
; set : A container for elements&lt;br /&gt;
; set_elem : A set element&lt;br /&gt;
; trace : A trace event sent by the kernel&lt;br /&gt;
&lt;br /&gt;
=== nftnl_expr ===&lt;br /&gt;
&lt;br /&gt;
While nftables distinguishes between expressions and statements, such&lt;br /&gt;
difference does not quite exist in libnftnl layer. For instance, a statement&lt;br /&gt;
like:&lt;br /&gt;
 ip saddr 192.168.0.1&lt;br /&gt;
is actually two expressions:&lt;br /&gt;
; payload : loading IPv4 header&#039;s source address into a register&lt;br /&gt;
; cmp : comparing data from a register against a stored value&lt;br /&gt;
&lt;br /&gt;
Since expressions have access to the packet, its meta data, all nftables&lt;br /&gt;
registers (including the verdict register) and may store multiple values&lt;br /&gt;
internally, they are mighty and versatile.&lt;br /&gt;
&lt;br /&gt;
=== nftnl_obj ===&lt;br /&gt;
&lt;br /&gt;
This is a common API for various object types. An object&#039;s type is defined post&lt;br /&gt;
allocation by setting the &#039;&#039;NFTNL_OBJ_TYPE&#039;&#039; attribute. Currently existing&lt;br /&gt;
object types are:&lt;br /&gt;
&lt;br /&gt;
* counter&lt;br /&gt;
* quota&lt;br /&gt;
* ct helper&lt;br /&gt;
* limit&lt;br /&gt;
* tunnel&lt;br /&gt;
* ct timeout&lt;br /&gt;
* secmark&lt;br /&gt;
* ct expect&lt;br /&gt;
* synproxy&lt;br /&gt;
&lt;br /&gt;
=== nftnl_batch ===&lt;br /&gt;
&lt;br /&gt;
This is a wrapper interface around the same functionality in libmnl (which is&lt;br /&gt;
used internally). In general, nftnl batches aid in collecting multiple netlink&lt;br /&gt;
messages for kernel submission.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
One goal in nftables development was to provide users with a library for easier&lt;br /&gt;
integration into applications than &amp;quot;shelling out&amp;quot; using &#039;&#039;system()&#039;&#039; and trying&lt;br /&gt;
to parse &#039;&#039;nft&#039;&#039; command output.&lt;br /&gt;
&lt;br /&gt;
At first, &#039;&#039;libnftnl&#039;&#039; was supposed to achieve this but the fact that it&lt;br /&gt;
exposes internal implementation details apart from being pretty low-level in&lt;br /&gt;
general made it rather unsuitable from a users&#039; perspective.&lt;br /&gt;
&lt;br /&gt;
To overcome this, &#039;&#039;nft&#039;&#039; backend code was separated into a library which&lt;br /&gt;
should fill the gap between &#039;&#039;libnftnl&#039;&#039; on one side and &#039;&#039;nft&#039;&#039; application&lt;br /&gt;
itself on the other.&lt;br /&gt;
&lt;br /&gt;
Usage of &#039;&#039;libnftables&#039;&#039; is supposed to be simple and straightforward, almost&lt;br /&gt;
like calling &#039;&#039;nft&#039;&#039; itself but with a bit more convenience. First step is to&lt;br /&gt;
create a new context:&lt;br /&gt;
&lt;br /&gt;
  struct nft_ctx *ctx = nft_ctx_new(0);&lt;br /&gt;
&lt;br /&gt;
The context allows to configure library behaviour on a &amp;quot;per session&amp;quot; basis.&lt;br /&gt;
With this in place, nftables commands may be executed:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_buffer(ctx, &amp;quot;add table inet t&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or whole dump files loaded:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_filename(ctx, &amp;quot;/etc/nftables/all-in-one.nft&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To control output, there are a number of functions:&lt;br /&gt;
&lt;br /&gt;
  FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);&lt;br /&gt;
  int nft_ctx_buffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  int nft_ctx_unbuffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  const char *nft_ctx_get_output_buffer(struct nft_ctx *ctx);&lt;br /&gt;
&lt;br /&gt;
Same for stderr. See libnftables(3) man page for further details.&lt;br /&gt;
&lt;br /&gt;
= nft: from user space to the kernel =&lt;br /&gt;
&lt;br /&gt;
The following describes the steps and entities involved after a call to&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039; in user space until the actual communication with the kernel.&lt;br /&gt;
&lt;br /&gt;
Since creation of &#039;&#039;&#039;libnftables&#039;&#039;&#039;, &#039;&#039;&#039;nft&#039;&#039;&#039; is merely a lightweight&lt;br /&gt;
front-end, basically just creating a &#039;&#039;&#039;libnftables&#039;&#039;&#039; handle, allowing to&lt;br /&gt;
configure it via command-line options and feeding &#039;&#039;&#039;nftables&#039;&#039;&#039; syntax into&lt;br /&gt;
it. Within the library, the actual work takes place. It may be divided into&lt;br /&gt;
several phases:&lt;br /&gt;
&lt;br /&gt;
* Input parsing into internal data structure&lt;br /&gt;
* Evaluation and expansion&lt;br /&gt;
* Serialization into netlink messages&lt;br /&gt;
* nfnetlink message session with kernel&lt;br /&gt;
* Error handling&lt;br /&gt;
&lt;br /&gt;
== Input parsing into internal data structures ==&lt;br /&gt;
&lt;br /&gt;
Depending on whether input comes from command line or a file (which may be&lt;br /&gt;
&#039;&#039;stdin&#039;&#039;), &#039;&#039;&#039;main()&#039;&#039;&#039; calls either &#039;&#039;&#039;nft_run_cmd_from_buffer()&#039;&#039;&#039; or&lt;br /&gt;
&#039;&#039;&#039;nft_run_cmd_from_filename()&#039;&#039;&#039; library functions.&lt;br /&gt;
&lt;br /&gt;
If JSON output was selected (&#039;&#039;&#039;nft -j&#039;&#039;&#039;), the JSON parser (in&lt;br /&gt;
&#039;&#039;src/parser_json.c&#039;&#039;) is tried first. If this did not succeed, the standard&lt;br /&gt;
(&amp;quot;human-readable&amp;quot;) syntax parser is called.&lt;br /&gt;
&lt;br /&gt;
Eventually both parsers populate a list of commands (&#039;&#039;&#039;struct cmd&#039;&#039;&#039;) and a&lt;br /&gt;
list of error messages (&#039;&#039;&#039;struct error_record&#039;&#039;&#039;) in case errors were&lt;br /&gt;
detected.&lt;br /&gt;
&lt;br /&gt;
=== Standard syntax ===&lt;br /&gt;
&lt;br /&gt;
The parser for standard syntax is implemented in lex and yacc, see&lt;br /&gt;
&#039;&#039;src/scanner.l&#039;&#039; and &#039;&#039;src/parser_bison.y&#039;&#039; for reference. It is entered via&lt;br /&gt;
the generated function &#039;&#039;&#039;nft_parse()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As a basic rule, in lex/yacc the scanner recognizes the words and the parser&lt;br /&gt;
interprets them in their context. There is also (limited) scanner control from&lt;br /&gt;
the parser by definition of a scope in which some words are valid or not. The&lt;br /&gt;
parser defines recursive patterns to match input against. Here is the top-most&lt;br /&gt;
one, &#039;&#039;&#039;input&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
input       :       /* empty */&lt;br /&gt;
            |       input           line&lt;br /&gt;
            {&lt;br /&gt;
                    if ($2 != NULL) {&lt;br /&gt;
                            $2-&amp;gt;location = @2;&lt;br /&gt;
                            list_add_tail(&amp;amp;$2-&amp;gt;list, state-&amp;gt;cmds);&lt;br /&gt;
                    }&lt;br /&gt;
            }&lt;br /&gt;
            ;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So it may be empty or (by recursion) consist of a number of&lt;br /&gt;
&#039;&#039;&#039;line&#039;&#039;&#039; patterns. Each of those lines parses into a command and is appended&lt;br /&gt;
to the list. The snippet above also shows how parser-provided &#039;&#039;&#039;location&#039;&#039;&#039;&lt;br /&gt;
data is stored in the command object. This is used for error reporting.&lt;br /&gt;
&lt;br /&gt;
=== JSON syntax ===&lt;br /&gt;
&lt;br /&gt;
The JSON parser lives in &#039;&#039;src/parser_json.c&#039;&#039; and is entered via&lt;br /&gt;
&#039;&#039;&#039;nft_parse_json_buffer()&#039;&#039;&#039; function or &#039;&#039;&#039;nft_parse_json_filename()&#039;&#039;&#039;,&lt;br /&gt;
respectively. It uses jansson library for (de-)serialization and value&lt;br /&gt;
(un-)packing. To learn about the code and to understand the program flow,&lt;br /&gt;
&#039;&#039;&#039;json_parse_cmd()&#039;&#039;&#039; function is a good starting point.&lt;br /&gt;
&lt;br /&gt;
== Evaluation and expansion ==&lt;br /&gt;
&lt;br /&gt;
Input evaluation is a crucial step and combines several tasks. It extends input&lt;br /&gt;
validation from mere syntax checks done by the parser to semantical ones,&lt;br /&gt;
taking context into perspective.&lt;br /&gt;
&lt;br /&gt;
Input may be changed, too. Sometimes it is necessary to insert extra statements&lt;br /&gt;
as dependency, sometimes types of right hand sides of comparisons must adjust&lt;br /&gt;
to left hand side type.&lt;br /&gt;
&lt;br /&gt;
Before all the above, the list of commands is scanned for cache requirements -&lt;br /&gt;
see &#039;&#039;&#039;nft_cache_evaluate()&#039;&#039;&#039; for details. Since caching may be an expensive&lt;br /&gt;
operation if in-kernel ruleset is huge, this step attempts to reduce the data&lt;br /&gt;
fetched from kernel to the bare minimum needed for correct operation. A final&lt;br /&gt;
call to &#039;&#039;&#039;nft_cache_update()&#039;&#039;&#039; then does the actual fetch.&lt;br /&gt;
&lt;br /&gt;
If evaluation passed, expansion takes place. This is mostly to cover for input&lt;br /&gt;
in &amp;quot;dump&amp;quot; notation, i.e. rules nested in chains nested in tables, etc. Such&lt;br /&gt;
input is converted into individual &amp;quot;add&amp;quot; commands as required by the netlink&lt;br /&gt;
message format. The code is pretty straightforward, see &#039;&#039;&#039;nft_cmd_expand()&#039;&#039;&#039;&lt;br /&gt;
for reference.&lt;br /&gt;
&lt;br /&gt;
== Serialization into netlink messages ==&lt;br /&gt;
&lt;br /&gt;
In this step, &#039;&#039;&#039;nftables&#039;&#039;&#039;-internal data types are converted into&lt;br /&gt;
&#039;&#039;&#039;libnftables&#039;&#039;&#039; ones (e.g., &#039;&#039;&#039;struct table&#039;&#039;&#039; into&lt;br /&gt;
&#039;&#039;&#039;struct nftnl_table&#039;&#039;&#039;). The latter abstract their internal layout as&lt;br /&gt;
attributes and are therefore opaque to the caller.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;libnftnl&#039;&#039;&#039; provides helpers to convert its own data structures into netlink&lt;br /&gt;
message format: A generic &#039;&#039;&#039;nftnl_nlmsg_build_hdr()&#039;&#039;&#039; for the header and&lt;br /&gt;
type-specific ones for the payload (e.g.,&lt;br /&gt;
&#039;&#039;&#039;nftnl_table_nlmsg_build_payload()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
The netlink messages are stored in a &#039;&#039;&#039;struct nftnl_batch&#039;&#039;&#039; which provides&lt;br /&gt;
the backing storage. This surrounding data structure serializes into an&lt;br /&gt;
introductory &#039;&#039;&#039;NFNL_MSG_BATCH_BEGIN&#039;&#039;&#039; message and a finalizing one with type&lt;br /&gt;
&#039;&#039;&#039;NFNL_MSG_BATCH_END&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In kernel space, the batch constitutes a transaction: If one of the messages is&lt;br /&gt;
rejected, none of them take effect. Ditto, if the final batch end message is&lt;br /&gt;
missing the whole batch will undo. This is how &#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s &#039;&#039;&#039;--check&#039;&#039;&#039; option&lt;br /&gt;
is implemented.&lt;br /&gt;
&lt;br /&gt;
== nfnetlink message session with kernel ==&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;nft&#039;&#039;&#039;, communication with the kernel takes place in the function&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_talk()&#039;&#039;&#039;: It converts the &#039;&#039;&#039;nftnl_batch&#039;&#039;&#039; into a message&lt;br /&gt;
suitable for &#039;&#039;&#039;sendmsg()&#039;&#039;&#039;, adjusts buffer sizes (if needed), transmits the&lt;br /&gt;
data and listens for a reply. Any error messages are handled by&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_extack_cb()&#039;&#039;&#039; function which records them for later reporting.&lt;br /&gt;
Other messages are relevant for &#039;&#039;&#039;--echo&#039;&#039;&#039; mode, in which the kernel &amp;quot;echoes&amp;quot;&lt;br /&gt;
the requests back after updating them (with handle values, for instance). These&lt;br /&gt;
are handled by &#039;&#039;&#039;netlink_echo_callback()&#039;&#039;&#039;, more or less a wrapper around&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s event monitoring code.&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
Each &#039;&#039;&#039;struct cmd&#039;&#039;&#039; object is identified by its own sequence number&lt;br /&gt;
(monotonic within the batch). Netlink error messages contain this number and&lt;br /&gt;
also an offset value, which allow to identify not only the problematic message&lt;br /&gt;
but also the specific attribute of that message which was rejected.&lt;br /&gt;
&lt;br /&gt;
Mapping from message attribute back to line or word(s) of input works via a&lt;br /&gt;
mapping from attribute offset to the &#039;&#039;&#039;struct location&#039;&#039;&#039; object stored while&lt;br /&gt;
parsing. That bison parser-provided data holds line and column numbers,&lt;br /&gt;
allowing &#039;&#039;&#039;nft&#039;&#039;&#039; to underline problematic parts of input when reporting back&lt;br /&gt;
to the caller.&lt;br /&gt;
&lt;br /&gt;
To follow the above in the source code, see &#039;&#039;&#039;nft_cmd_error()&#039;&#039;&#039; function&lt;br /&gt;
being called for each command and error it caused. The mapping is established&lt;br /&gt;
earlier while creating netlink messages, i.e. in code called from&lt;br /&gt;
&#039;&#039;&#039;do_command()&#039;&#039;&#039; - watch out for the various calls to &#039;&#039;&#039;cmd_add_loc()&#039;&#039;&#039;&lt;br /&gt;
populating the field &#039;&#039;&#039;attr&#039;&#039;&#039; in &#039;&#039;&#039;struct cmd&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to user space =&lt;br /&gt;
&lt;br /&gt;
Communication between &#039;&#039;&#039;nft&#039;&#039;&#039; in user space and &#039;&#039;&#039;nftables&#039;&#039;&#039; in  kernel&lt;br /&gt;
happens via netlink, a packet-based IPC mechanism for that purpose. Its kernel&lt;br /&gt;
source code lives in &#039;&#039;net/netlink&#039;&#039; directory and allows to be extended by&lt;br /&gt;
calling &#039;&#039;&#039;netlink_kernel_create()&#039;&#039;&#039;, passing a unique &#039;&#039;&#039;unit&#039;&#039;&#039; number and a&lt;br /&gt;
&#039;&#039;&#039;struct netlink_kernel_cfg&#039;&#039;&#039; object.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nfnetlink&#039;&#039;&#039; is such an extension, attempting to serve all netfilter-related&lt;br /&gt;
user space applications. It is implemented in &#039;&#039;net/netfilter/nfnetlink.c&#039;&#039; and&lt;br /&gt;
itself allows to be extended as well by means of groups (see&lt;br /&gt;
&#039;&#039;&#039;nfnetlink_groups&#039;&#039;&#039; in &#039;&#039;include/uapi/linux/netfilter/nfnetlink.h&#039;&#039;). These&lt;br /&gt;
in turn map to nfnetlink subsystems, see the constant array&lt;br /&gt;
&#039;&#039;&#039;nfnl_group2type&#039;&#039;&#039; in nfnetlink source file. &#039;&#039;&#039;NFNL_SUBSYS_NFTABLES&#039;&#039;&#039; is&lt;br /&gt;
the relevant one here, implemented in &#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039; (see&lt;br /&gt;
&#039;&#039;&#039;nf_tables_subsys&#039;&#039;&#039; and the call to &#039;&#039;&#039;nfnetlink_subsys_register()&#039;&#039;&#039; in&lt;br /&gt;
there).&lt;br /&gt;
&lt;br /&gt;
For insight, it is worthwhile to remain in generic &#039;&#039;&#039;nfnetlink&#039;&#039;&#039; code for a&lt;br /&gt;
little longer: &#039;&#039;&#039;nfnetlink_net_ops&#039;&#039;&#039; are registered as a &amp;quot;pernet&amp;quot; subsystem,&lt;br /&gt;
i.e. each network namespace gets its own instance. Upon netns creation,&lt;br /&gt;
&#039;&#039;&#039;nfnetlink_net_init()&#039;&#039;&#039; is called which actually creates the&lt;br /&gt;
&#039;&#039;&#039;NETLINK_NETFILTER&#039;&#039;&#039; subsystem. Its receive callback (&#039;&#039;&#039;nfnetlink_rcv()&#039;&#039;&#039;)&lt;br /&gt;
checks whether the first message header starts a batch and diverts the code&lt;br /&gt;
flow accordingly.&lt;br /&gt;
&lt;br /&gt;
For batch handling, subsystems need to define &#039;&#039;&#039;commit&#039;&#039;&#039; and &#039;&#039;&#039;abort&#039;&#039;&#039;&lt;br /&gt;
callbacks. Also, for each contained message, there must be a responsible&lt;br /&gt;
callback entry with type &#039;&#039;&#039;NFNL_CB_BATCH&#039;&#039;&#039;. &#039;&#039;&#039;nf_tables_subsys&#039;&#039;&#039; fulfills&lt;br /&gt;
these requirements.&lt;br /&gt;
&lt;br /&gt;
Each callback in &#039;&#039;&#039;nf_tables_cb&#039;&#039;&#039; (and therefore each supported message type)&lt;br /&gt;
decides whether it must be part of a batch or not - nfnetlink code does not&lt;br /&gt;
allow for multiple handlers of the same message. In nftables, only getters for&lt;br /&gt;
different ruleset elements are non-batch, anything mangling the ruleset is.&lt;br /&gt;
&lt;br /&gt;
== Non-batched handlers ==&lt;br /&gt;
&lt;br /&gt;
These are getters for:&lt;br /&gt;
&lt;br /&gt;
 * table&lt;br /&gt;
 * chain&lt;br /&gt;
 * rule&lt;br /&gt;
 * set&lt;br /&gt;
 * set element&lt;br /&gt;
 * generation ID&lt;br /&gt;
 * stateful objects&lt;br /&gt;
 * flowtable&lt;br /&gt;
&lt;br /&gt;
They all behave similar: Unless &#039;&#039;&#039;NLM_F_DUMP&#039;&#039;&#039; flag is set in the message,&lt;br /&gt;
they perform a lookup based on the required identifiers and return an nfnetlink&lt;br /&gt;
message to user space. There are type-specific helpers populating a netlink&lt;br /&gt;
message named &#039;&#039;&#039;nf_tables_fill_&amp;lt;SOMETHING&amp;gt;_info&#039;&#039;&#039;, packet sending is done by&lt;br /&gt;
a call to &#039;&#039;&#039;nfnetlink_unicast()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;&#039;NLM_F_DUMP&#039;&#039;&#039; was given, the getter iterates over all ruleset elements of&lt;br /&gt;
given type and fills a netlink message for each. In some cases, filtering the&lt;br /&gt;
output by identifiers given in the request is supported - useful to dump e.g.&lt;br /&gt;
all rules of a specific chain only.&lt;br /&gt;
&lt;br /&gt;
The iterator code is a bit complicated due to the fact that socket buffer size&lt;br /&gt;
may be exceeded. In that case, partial data is submitted to user space and the&lt;br /&gt;
dump continued afterwards. The iterators keep a &amp;quot;cursor&amp;quot; (actually a counter)&lt;br /&gt;
for where to pick up again.&lt;br /&gt;
&lt;br /&gt;
== Batched handlers ==&lt;br /&gt;
&lt;br /&gt;
To allow for rolling back a transaction which has failed or was aborted,&lt;br /&gt;
message handlers of type &#039;&#039;&#039;NFNL_CB_BATCH&#039;&#039;&#039; allocate a &#039;&#039;&#039;struct nft_trans&#039;&#039;&#039;&lt;br /&gt;
object and add it to the per-net commit list. This &amp;quot;log&amp;quot; of what was done is&lt;br /&gt;
also useful to defer actions till the very end of the transaction. See&lt;br /&gt;
&#039;&#039;&#039;nf_tables_commit()&#039;&#039;&#039; for reference of what it is used for in the&lt;br /&gt;
success-case. Similar code is found in &#039;&#039;&#039;nf_tables_abort()&#039;&#039;&#039;, reverting the&lt;br /&gt;
previous changes.&lt;br /&gt;
&lt;br /&gt;
To make the ruleset update atomic, nftables uses an internal generation ID. Its&lt;br /&gt;
value alternates between zero and one upon each commit. Ruleset elements have a&lt;br /&gt;
two-bit &amp;quot;generation mask&amp;quot;, indicating whether that element is active in the&lt;br /&gt;
generation at its bit index. This way, elements may die, get born or stay alive&lt;br /&gt;
when the generation ID toggles again.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=1073</id>
		<title>Simple rule management</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=1073"/>
		<updated>2022-10-18T09:43:21Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* Removing all the rules in a chain */ Fix flush command for removing all rules in a chain: s/flush rule/flush chain/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Rules take action on network packets (e.g. accepting or dropping them) based on whether they match specified criteria. &lt;br /&gt;
&lt;br /&gt;
Each rule consists of zero or more expressions followed by one or more statements. Each expression tests whether a packet matches a specific payload field or packet/flow metadata. Multiple expressions are linearly evaluated from left to right: if the first expression matches, then the next expression is evaluated and so on. If we reach the final expression, then the packet matches all of the expressions in the rule, and the rule&#039;s statements are executed. Each statement takes an action, such as setting the netfilter mark, counting the packet, logging the packet, or rendering a verdict such as accepting or dropping the packet or jumping to another chain. As with expressions, multiple statements are linearly evaluated from left to right: a single rule can take multiple actions by using multiple statements. Do note that a verdict statement by its nature ends the rule.&lt;br /&gt;
&lt;br /&gt;
Following are some basic operations and commands for configuring rules:&lt;br /&gt;
&lt;br /&gt;
= Appending new rules =&lt;br /&gt;
&lt;br /&gt;
To add new rules, you have to specify the corresponding table and the chain that you want to use, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output ip daddr 8.8.8.8 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;filter&#039;&#039; is the table and &#039;&#039;output&#039;&#039; is the chain. The example above adds a rule to match all packets seen by the output chain whose destination is 8.8.8.8, in case of matching it updates the rule counters. Note that counters are optional in &#039;&#039;nftables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
For those familiar with iptables, the rule appending is equivalent to &#039;&#039;-A&#039;&#039; command in iptables.&lt;br /&gt;
&lt;br /&gt;
= Listing rules =&lt;br /&gt;
&lt;br /&gt;
You can list the rules that are contained by a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also list rules by chain, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list chain filter ouput&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are plenty of [[Output_text_modifiers | output text modifiers]] than can be used when listing your rules, to for example, translate IP addresses to DNS names, TCP protocols, etc.&lt;br /&gt;
&lt;br /&gt;
= Testing your rule =&lt;br /&gt;
&lt;br /&gt;
Let&#039;s test this rule with a simple ping to 8.8.8.8:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% ping -c 1 8.8.8.8&lt;br /&gt;
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.&lt;br /&gt;
64 bytes from 8.8.8.8: icmp_req=1 ttl=64 time=1.31 ms&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if we list the rule-set, we obtain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -nn list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 1 bytes 84&lt;br /&gt;
                 tcp dport 22 counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the counters have been updated.&lt;br /&gt;
&lt;br /&gt;
= Adding a rule at a given position =&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule at a given position, you have to use the handle as reference:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -n -a list table filter&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 82 bytes 9680 # handle 8&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule after the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can check the effect of that command by listing the rule-set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -n -a list table filter&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 190 bytes 21908 # handle 8&lt;br /&gt;
                 ip daddr 127.0.0.8 drop # handle 10&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to insert a rule before the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Removing rules =&lt;br /&gt;
&lt;br /&gt;
You have to obtain the &#039;&#039;handle&#039;&#039; to delete a rule via the &#039;&#039;&#039;-a&#039;&#039;&#039; option. The &#039;&#039;handle&#039;&#039; is automagically assigned by the kernel and it uniquely identifies the rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -a list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 192.168.1.1 counter packets 1 bytes 84 # handle 5&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can delete the rule whose handle is &#039;&#039;5&#039;&#039; with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output handle 5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: There are plans to support rule deletion by passing:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output ip saddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
but this is &#039;&#039;&#039;not&#039;&#039;&#039; yet implemented. So you&#039;ll have to use the handle to delete rules until that feature is implemented.&lt;br /&gt;
&lt;br /&gt;
= Removing all the rules in a chain =&lt;br /&gt;
&lt;br /&gt;
You can delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a chain with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush chain filter output&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prepending new rules =&lt;br /&gt;
&lt;br /&gt;
To prepend new rules through the &#039;&#039;insert&#039;&#039; command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output ip daddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This prepends a rule that will update per-rule packet and bytes counters for traffic addressed to 192.168.1.1.&lt;br /&gt;
&lt;br /&gt;
The equivalent in iptables is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% iptables -I OUTPUT -t filter -d 192.168.1.1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that iptables always provides per-rule counters.&lt;br /&gt;
&lt;br /&gt;
= Replacing rules =&lt;br /&gt;
&lt;br /&gt;
You can replace any rule via the &#039;&#039;replace&#039;&#039; command by indicating the rule handle, which you have to find by first listing the ruleset with option &#039;&#039;-a&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft -a list ruleset&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                ip protocol tcp counter packets 0 bytes 0 # handle 2&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To replace the rule with handle 2, specify its handle number and the new rule that you want to replace it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft replace rule filter input handle 2 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Listing the ruleset after the above replacement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft list ruleset&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                counter packets 0 bytes 0 &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
you can see that the old rule that counted TCP packets has been replaced by the new rule that counts all packets.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1072</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1072"/>
		<updated>2022-09-13T15:30:13Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* nft: from the kernel to the usespace */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== expressions ==&lt;br /&gt;
&lt;br /&gt;
There are many low expressions that allows us to operate over network packets in different ways. You can think on these low level expressions as assembly-like instructions.&lt;br /&gt;
&lt;br /&gt;
* nft_immediate: loads an immediate value into a register.&lt;br /&gt;
* nft_cmp: compare a given data with data from a given register.&lt;br /&gt;
* nft_payload: set/get arbitrary data from packet headers.&lt;br /&gt;
* nft_bitwise: perform bit-wise math operations over data in a given register.&lt;br /&gt;
* nft_byteorder: perform byte order operations over data in a given register.&lt;br /&gt;
* nft_counter: a basic counter for packet/bytes that gets incremented everything is evaluated for a packet.&lt;br /&gt;
* nft_meta: set/get packet meta information, such as related interfaces, timestamps, etc.&lt;br /&gt;
* nft_lookup: search for data from a given register (key) into a dataset. If the set is a map/vmap, returns the value for that key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
This library provides data structures for entities existing in nf_tables&lt;br /&gt;
nomenclature, such as tables, chains and rules. It serves as an intermediate&lt;br /&gt;
layer between nftables and iptables-nft user space applications and nfnetlink&lt;br /&gt;
messages the kernel sends and receives.&lt;br /&gt;
&lt;br /&gt;
In general, each data structure comes with a set of handling routines:&lt;br /&gt;
&lt;br /&gt;
; allocators : To allocate and free an object of given type&lt;br /&gt;
; setters/getters : Data structure fields are accessed via an attribute number (via a specific enum field)&lt;br /&gt;
; serializers : Populating a netlink message or vice versa&lt;br /&gt;
; printers : Providing a textual representation, mostly for debugging purposes&lt;br /&gt;
&lt;br /&gt;
Where sensible, there is a &#039;&#039;&#039;list-variant&#039;&#039;&#039;, too. If so, it comes with&lt;br /&gt;
handling routines as well:&lt;br /&gt;
&lt;br /&gt;
; allocators : Allocating and freeing the list object (and members)&lt;br /&gt;
; populators : Add and remove from the list&lt;br /&gt;
&lt;br /&gt;
Where useful, there might be a &#039;&#039;&#039;lookup routine&#039;&#039;&#039; as well. With&lt;br /&gt;
nftnl_chain_list, e.g. the list object contains a hash table for chain names as&lt;br /&gt;
well so list lookup by chain name is faster than a linear search.&lt;br /&gt;
&lt;br /&gt;
A typical extra for list objects are &#039;&#039;&#039;iterators&#039;&#039;&#039;: A data structure&lt;br /&gt;
containing state while browsing through the list. Usually the only routines&lt;br /&gt;
used are allocators and a &#039;&#039;next&#039;&#039; routine.&lt;br /&gt;
&lt;br /&gt;
These are the &#039;&#039;&#039;entities defined by libnftnl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
; table : A rather boring &amp;quot;namespace&amp;quot; for chains&lt;br /&gt;
; chain : A container for rules, may attach to a netfilter hook in kernel&lt;br /&gt;
; rule : A container for expressions&lt;br /&gt;
; expr : An nftables VM code instruction&lt;br /&gt;
; flowtable : Similar to a chain, but holds flows between interfaces&lt;br /&gt;
; obj : A generic object, typically holding stateful information&lt;br /&gt;
; ruleset : A container for lists of tables, chains, sets and rules - not used by nftables application anymore&lt;br /&gt;
; set : A container for elements&lt;br /&gt;
; set_elem : A set element&lt;br /&gt;
; trace : A trace event sent by the kernel&lt;br /&gt;
&lt;br /&gt;
=== nftnl_expr ===&lt;br /&gt;
&lt;br /&gt;
While nftables distinguishes between expressions and statements, such&lt;br /&gt;
difference does not quite exist in libnftnl layer. For instance, a statement&lt;br /&gt;
like:&lt;br /&gt;
 ip saddr 192.168.0.1&lt;br /&gt;
is actually two expressions:&lt;br /&gt;
; payload : loading IPv4 header&#039;s source address into a register&lt;br /&gt;
; cmp : comparing data from a register against a stored value&lt;br /&gt;
&lt;br /&gt;
Since expressions have access to the packet, its meta data, all nftables&lt;br /&gt;
registers (including the verdict register) and may store multiple values&lt;br /&gt;
internally, they are mighty and versatile.&lt;br /&gt;
&lt;br /&gt;
=== nftnl_obj ===&lt;br /&gt;
&lt;br /&gt;
This is a common API for various object types. An object&#039;s type is defined post&lt;br /&gt;
allocation by setting the &#039;&#039;NFTNL_OBJ_TYPE&#039;&#039; attribute. Currently existing&lt;br /&gt;
object types are:&lt;br /&gt;
&lt;br /&gt;
* counter&lt;br /&gt;
* quota&lt;br /&gt;
* ct helper&lt;br /&gt;
* limit&lt;br /&gt;
* tunnel&lt;br /&gt;
* ct timeout&lt;br /&gt;
* secmark&lt;br /&gt;
* ct expect&lt;br /&gt;
* synproxy&lt;br /&gt;
&lt;br /&gt;
=== nftnl_batch ===&lt;br /&gt;
&lt;br /&gt;
This is a wrapper interface around the same functionality in libmnl (which is&lt;br /&gt;
used internally). In general, nftnl batches aid in collecting multiple netlink&lt;br /&gt;
messages for kernel submission.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
One goal in nftables development was to provide users with a library for easier&lt;br /&gt;
integration into applications than &amp;quot;shelling out&amp;quot; using &#039;&#039;system()&#039;&#039; and trying&lt;br /&gt;
to parse &#039;&#039;nft&#039;&#039; command output.&lt;br /&gt;
&lt;br /&gt;
At first, &#039;&#039;libnftnl&#039;&#039; was supposed to achieve this but the fact that it&lt;br /&gt;
exposes internal implementation details apart from being pretty low-level in&lt;br /&gt;
general made it rather unsuitable from a users&#039; perspective.&lt;br /&gt;
&lt;br /&gt;
To overcome this, &#039;&#039;nft&#039;&#039; backend code was separated into a library which&lt;br /&gt;
should fill the gap between &#039;&#039;libnftnl&#039;&#039; on one side and &#039;&#039;nft&#039;&#039; application&lt;br /&gt;
itself on the other.&lt;br /&gt;
&lt;br /&gt;
Usage of &#039;&#039;libnftables&#039;&#039; is supposed to be simple and straightforward, almost&lt;br /&gt;
like calling &#039;&#039;nft&#039;&#039; itself but with a bit more convenience. First step is to&lt;br /&gt;
create a new context:&lt;br /&gt;
&lt;br /&gt;
  struct nft_ctx *ctx = nft_ctx_new(0);&lt;br /&gt;
&lt;br /&gt;
The context allows to configure library behaviour on a &amp;quot;per session&amp;quot; basis.&lt;br /&gt;
With this in place, nftables commands may be executed:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_buffer(ctx, &amp;quot;add table inet t&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or whole dump files loaded:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_filename(ctx, &amp;quot;/etc/nftables/all-in-one.nft&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To control output, there are a number of functions:&lt;br /&gt;
&lt;br /&gt;
  FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);&lt;br /&gt;
  int nft_ctx_buffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  int nft_ctx_unbuffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  const char *nft_ctx_get_output_buffer(struct nft_ctx *ctx);&lt;br /&gt;
&lt;br /&gt;
Same for stderr. See libnftables(3) man page for further details.&lt;br /&gt;
&lt;br /&gt;
= nft: from user space to the kernel =&lt;br /&gt;
&lt;br /&gt;
The following describes the steps and entities involved after a call to&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039; in user space until the actual communication with the kernel.&lt;br /&gt;
&lt;br /&gt;
Since creation of &#039;&#039;&#039;libnftables&#039;&#039;&#039;, &#039;&#039;&#039;nft&#039;&#039;&#039; is merely a lightweight&lt;br /&gt;
front-end, basically just creating a &#039;&#039;&#039;libnftables&#039;&#039;&#039; handle, allowing to&lt;br /&gt;
configure it via command-line options and feeding &#039;&#039;&#039;nftables&#039;&#039;&#039; syntax into&lt;br /&gt;
it. Within the library, the actual work takes place. It may be divided into&lt;br /&gt;
several phases:&lt;br /&gt;
&lt;br /&gt;
* Input parsing into internal data structure&lt;br /&gt;
* Evaluation and expansion&lt;br /&gt;
* Serialization into netlink messages&lt;br /&gt;
* nfnetlink message session with kernel&lt;br /&gt;
* Error handling&lt;br /&gt;
&lt;br /&gt;
== Input parsing into internal data structures ==&lt;br /&gt;
&lt;br /&gt;
Depending on whether input comes from command line or a file (which may be&lt;br /&gt;
&#039;&#039;stdin&#039;&#039;), &#039;&#039;&#039;main()&#039;&#039;&#039; calls either &#039;&#039;&#039;nft_run_cmd_from_buffer()&#039;&#039;&#039; or&lt;br /&gt;
&#039;&#039;&#039;nft_run_cmd_from_filename()&#039;&#039;&#039; library functions.&lt;br /&gt;
&lt;br /&gt;
If JSON output was selected (&#039;&#039;&#039;nft -j&#039;&#039;&#039;), the JSON parser (in&lt;br /&gt;
&#039;&#039;src/parser_json.c&#039;&#039;) is tried first. If this did not succeed, the standard&lt;br /&gt;
(&amp;quot;human-readable&amp;quot;) syntax parser is called.&lt;br /&gt;
&lt;br /&gt;
Eventually both parsers populate a list of commands (&#039;&#039;&#039;struct cmd&#039;&#039;&#039;) and a&lt;br /&gt;
list of error messages (&#039;&#039;&#039;struct error_record&#039;&#039;&#039;) in case errors were&lt;br /&gt;
detected.&lt;br /&gt;
&lt;br /&gt;
=== Standard syntax ===&lt;br /&gt;
&lt;br /&gt;
The parser for standard syntax is implemented in lex and yacc, see&lt;br /&gt;
&#039;&#039;src/scanner.l&#039;&#039; and &#039;&#039;src/parser_bison.y&#039;&#039; for reference. It is entered via&lt;br /&gt;
the generated function &#039;&#039;&#039;nft_parse()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As a basic rule, in lex/yacc the scanner recognizes the words and the parser&lt;br /&gt;
interprets them in their context. There is also (limited) scanner control from&lt;br /&gt;
the parser by definition of a scope in which some words are valid or not. The&lt;br /&gt;
parser defines recursive patterns to match input against. Here is the top-most&lt;br /&gt;
one, &#039;&#039;&#039;input&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
input       :       /* empty */&lt;br /&gt;
            |       input           line&lt;br /&gt;
            {&lt;br /&gt;
                    if ($2 != NULL) {&lt;br /&gt;
                            $2-&amp;gt;location = @2;&lt;br /&gt;
                            list_add_tail(&amp;amp;$2-&amp;gt;list, state-&amp;gt;cmds);&lt;br /&gt;
                    }&lt;br /&gt;
            }&lt;br /&gt;
            ;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So it may be empty or (by recursion) consist of a number of&lt;br /&gt;
&#039;&#039;&#039;line&#039;&#039;&#039; patterns. Each of those lines parses into a command and is appended&lt;br /&gt;
to the list. The snippet above also shows how parser-provided &#039;&#039;&#039;location&#039;&#039;&#039;&lt;br /&gt;
data is stored in the command object. This is used for error reporting.&lt;br /&gt;
&lt;br /&gt;
=== JSON syntax ===&lt;br /&gt;
&lt;br /&gt;
The JSON parser lives in &#039;&#039;src/parser_json.c&#039;&#039; and is entered via&lt;br /&gt;
&#039;&#039;&#039;nft_parse_json_buffer()&#039;&#039;&#039; function or &#039;&#039;&#039;nft_parse_json_filename()&#039;&#039;&#039;,&lt;br /&gt;
respectively. It uses jansson library for (de-)serialization and value&lt;br /&gt;
(un-)packing. To learn about the code and to understand the program flow,&lt;br /&gt;
&#039;&#039;&#039;json_parse_cmd()&#039;&#039;&#039; function is a good starting point.&lt;br /&gt;
&lt;br /&gt;
== Evaluation and expansion ==&lt;br /&gt;
&lt;br /&gt;
Input evaluation is a crucial step and combines several tasks. It extends input&lt;br /&gt;
validation from mere syntax checks done by the parser to semantical ones,&lt;br /&gt;
taking context into perspective.&lt;br /&gt;
&lt;br /&gt;
Input may be changed, too. Sometimes it is necessary to insert extra statements&lt;br /&gt;
as dependency, sometimes types of right hand sides of comparisons must adjust&lt;br /&gt;
to left hand side type.&lt;br /&gt;
&lt;br /&gt;
Before all the above, the list of commands is scanned for cache requirements -&lt;br /&gt;
see &#039;&#039;&#039;nft_cache_evaluate()&#039;&#039;&#039; for details. Since caching may be an expensive&lt;br /&gt;
operation if in-kernel ruleset is huge, this step attempts to reduce the data&lt;br /&gt;
fetched from kernel to the bare minimum needed for correct operation. A final&lt;br /&gt;
call to &#039;&#039;&#039;nft_cache_update()&#039;&#039;&#039; then does the actual fetch.&lt;br /&gt;
&lt;br /&gt;
If evaluation passed, expansion takes place. This is mostly to cover for input&lt;br /&gt;
in &amp;quot;dump&amp;quot; notation, i.e. rules nested in chains nested in tables, etc. Such&lt;br /&gt;
input is converted into individual &amp;quot;add&amp;quot; commands as required by the netlink&lt;br /&gt;
message format. The code is pretty straightforward, see &#039;&#039;&#039;nft_cmd_expand()&#039;&#039;&#039;&lt;br /&gt;
for reference.&lt;br /&gt;
&lt;br /&gt;
== Serialization into netlink messages ==&lt;br /&gt;
&lt;br /&gt;
In this step, &#039;&#039;&#039;nftables&#039;&#039;&#039;-internal data types are converted into&lt;br /&gt;
&#039;&#039;&#039;libnftables&#039;&#039;&#039; ones (e.g., &#039;&#039;&#039;struct table&#039;&#039;&#039; into&lt;br /&gt;
&#039;&#039;&#039;struct nftnl_table&#039;&#039;&#039;). The latter abstract their internal layout as&lt;br /&gt;
attributes and are therefore opaque to the caller.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;libnftnl&#039;&#039;&#039; provides helpers to convert its own data structures into netlink&lt;br /&gt;
message format: A generic &#039;&#039;&#039;nftnl_nlmsg_build_hdr()&#039;&#039;&#039; for the header and&lt;br /&gt;
type-specific ones for the payload (e.g.,&lt;br /&gt;
&#039;&#039;&#039;nftnl_table_nlmsg_build_payload()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
The netlink messages are stored in a &#039;&#039;&#039;struct nftnl_batch&#039;&#039;&#039; which provides&lt;br /&gt;
the backing storage. This surrounding data structure serializes into an&lt;br /&gt;
introductory &#039;&#039;&#039;NFNL_MSG_BATCH_BEGIN&#039;&#039;&#039; message and a finalizing one with type&lt;br /&gt;
&#039;&#039;&#039;NFNL_MSG_BATCH_END&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In kernel space, the batch constitutes a transaction: If one of the messages is&lt;br /&gt;
rejected, none of them take effect. Ditto, if the final batch end message is&lt;br /&gt;
missing the whole batch will undo. This is how &#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s &#039;&#039;&#039;--check&#039;&#039;&#039; option&lt;br /&gt;
is implemented.&lt;br /&gt;
&lt;br /&gt;
== nfnetlink message session with kernel ==&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;nft&#039;&#039;&#039;, communication with the kernel takes place in the function&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_talk()&#039;&#039;&#039;: It converts the &#039;&#039;&#039;nftnl_batch&#039;&#039;&#039; into a message&lt;br /&gt;
suitable for &#039;&#039;&#039;sendmsg()&#039;&#039;&#039;, adjusts buffer sizes (if needed), transmits the&lt;br /&gt;
data and listens for a reply. Any error messages are handled by&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_extack_cb()&#039;&#039;&#039; function which records them for later reporting.&lt;br /&gt;
Other messages are relevant for &#039;&#039;&#039;--echo&#039;&#039;&#039; mode, in which the kernel &amp;quot;echoes&amp;quot;&lt;br /&gt;
the requests back after updating them (with handle values, for instance). These&lt;br /&gt;
are handled by &#039;&#039;&#039;netlink_echo_callback()&#039;&#039;&#039;, more or less a wrapper around&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s event monitoring code.&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
Each &#039;&#039;&#039;struct cmd&#039;&#039;&#039; object is identified by its own sequence number&lt;br /&gt;
(monotonic within the batch). Netlink error messages contain this number and&lt;br /&gt;
also an offset value, which allow to identify not only the problematic message&lt;br /&gt;
but also the specific attribute of that message which was rejected.&lt;br /&gt;
&lt;br /&gt;
Mapping from message attribute back to line or word(s) of input works via a&lt;br /&gt;
mapping from attribute offset to the &#039;&#039;&#039;struct location&#039;&#039;&#039; object stored while&lt;br /&gt;
parsing. That bison parser-provided data holds line and column numbers,&lt;br /&gt;
allowing &#039;&#039;&#039;nft&#039;&#039;&#039; to underline problematic parts of input when reporting back&lt;br /&gt;
to the caller.&lt;br /&gt;
&lt;br /&gt;
To follow the above in the source code, see &#039;&#039;&#039;nft_cmd_error()&#039;&#039;&#039; function&lt;br /&gt;
being called for each command and error it caused. The mapping is established&lt;br /&gt;
earlier while creating netlink messages, i.e. in code called from&lt;br /&gt;
&#039;&#039;&#039;do_command()&#039;&#039;&#039; - watch out for the various calls to &#039;&#039;&#039;cmd_add_loc()&#039;&#039;&#039;&lt;br /&gt;
populating the field &#039;&#039;&#039;attr&#039;&#039;&#039; in &#039;&#039;&#039;struct cmd&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to user space =&lt;br /&gt;
&lt;br /&gt;
Communication between &#039;&#039;&#039;nft&#039;&#039;&#039; in user space and &#039;&#039;&#039;nftables&#039;&#039;&#039; in  kernel&lt;br /&gt;
happens via netlink, a packet-based IPC mechanism for that purpose. Its kernel&lt;br /&gt;
source code lives in &#039;&#039;net/netlink&#039;&#039; directory and allows to be extended by&lt;br /&gt;
calling &#039;&#039;&#039;netlink_kernel_create()&#039;&#039;&#039;, passing a unique &#039;&#039;&#039;unit&#039;&#039;&#039; number and a&lt;br /&gt;
&#039;&#039;&#039;struct netlink_kernel_cfg&#039;&#039;&#039; object.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nfnetlink&#039;&#039;&#039; is such an extension, attempting to serve all netfilter-related&lt;br /&gt;
user space applications. It is implemented in &#039;&#039;net/netfilter/nfnetlink.c&#039;&#039; and&lt;br /&gt;
itself allows to be extended as well by means of groups (see&lt;br /&gt;
&#039;&#039;&#039;nfnetlink_groups&#039;&#039;&#039; in &#039;&#039;include/uapi/linux/netfilter/nfnetlink.h&#039;&#039;). These&lt;br /&gt;
in turn map to nfnetlink subsystems, see the constant array&lt;br /&gt;
&#039;&#039;&#039;nfnl_group2type&#039;&#039;&#039; in nfnetlink source file. &#039;&#039;&#039;NFNL_SUBSYS_NFTABLES&#039;&#039;&#039; is&lt;br /&gt;
the relevant one here, implemented in &#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039; (see&lt;br /&gt;
&#039;&#039;&#039;nf_tables_subsys&#039;&#039;&#039; and the call to &#039;&#039;&#039;nfnetlink_subsys_register()&#039;&#039;&#039; in&lt;br /&gt;
there).&lt;br /&gt;
&lt;br /&gt;
For insight, it is worthwhile to remain in generic &#039;&#039;&#039;nfnetlink&#039;&#039;&#039; code for a&lt;br /&gt;
little longer: &#039;&#039;&#039;nfnetlink_net_ops&#039;&#039;&#039; are registered as a &amp;quot;pernet&amp;quot; subsystem,&lt;br /&gt;
i.e. each network namespace gets its own instance. Upon netns creation,&lt;br /&gt;
&#039;&#039;&#039;nfnetlink_net_init()&#039;&#039;&#039; is called which actually creates the&lt;br /&gt;
&#039;&#039;&#039;NETLINK_NETFILTER&#039;&#039;&#039; subsystem. Its receive callback (&#039;&#039;&#039;nfnetlink_rcv()&#039;&#039;&#039;)&lt;br /&gt;
checks whether the first message header starts a batch and diverts the code&lt;br /&gt;
flow accordingly.&lt;br /&gt;
&lt;br /&gt;
For batch handling, subsystems need to define &#039;&#039;&#039;commit&#039;&#039;&#039; and &#039;&#039;&#039;abort&#039;&#039;&#039;&lt;br /&gt;
callbacks. Also, for each contained message, there must be a responsible&lt;br /&gt;
callback entry with type &#039;&#039;&#039;NFNL_CB_BATCH&#039;&#039;&#039;. &#039;&#039;&#039;nf_tables_subsys&#039;&#039;&#039; fulfills&lt;br /&gt;
these requirements.&lt;br /&gt;
&lt;br /&gt;
Each callback in &#039;&#039;&#039;nf_tables_cb&#039;&#039;&#039; (and therefore each supported message type)&lt;br /&gt;
decides whether it must be part of a batch or not - nfnetlink code does not&lt;br /&gt;
allow for multiple handlers of the same message. In nftables, only getters for&lt;br /&gt;
different ruleset elements are non-batch, anything mangling the ruleset is.&lt;br /&gt;
&lt;br /&gt;
== Non-batched handlers ==&lt;br /&gt;
&lt;br /&gt;
These are getters for:&lt;br /&gt;
&lt;br /&gt;
 * table&lt;br /&gt;
 * chain&lt;br /&gt;
 * rule&lt;br /&gt;
 * set&lt;br /&gt;
 * set element&lt;br /&gt;
 * generation ID&lt;br /&gt;
 * stateful objects&lt;br /&gt;
 * flowtable&lt;br /&gt;
&lt;br /&gt;
They all behave similar: Unless &#039;&#039;&#039;NLM_F_DUMP&#039;&#039;&#039; flag is set in the message,&lt;br /&gt;
they perform a lookup based on the required identifiers and return an nfnetlink&lt;br /&gt;
message to user space. There are type-specific helpers populating a netlink&lt;br /&gt;
message named &#039;&#039;&#039;nf_tables_fill_&amp;lt;SOMETHING&amp;gt;_info&#039;&#039;&#039;, packet sending is done by&lt;br /&gt;
a call to &#039;&#039;&#039;nfnetlink_unicast()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;&#039;NLM_F_DUMP&#039;&#039;&#039; was given, the getter iterates over all ruleset elements of&lt;br /&gt;
given type and fills a netlink message for each. In some cases, filtering the&lt;br /&gt;
output by identifiers given in the request is supported - useful to dump e.g.&lt;br /&gt;
all rules of a specific chain only.&lt;br /&gt;
&lt;br /&gt;
The iterator code is a bit complicated due to the fact that socket buffer size&lt;br /&gt;
may be exceeded. In that case, partial data is submitted to user space and the&lt;br /&gt;
dump continued afterwards. The iterators keep a &amp;quot;cursor&amp;quot; (actually a counter)&lt;br /&gt;
for where to pick up again.&lt;br /&gt;
&lt;br /&gt;
== Batched handlers ==&lt;br /&gt;
&lt;br /&gt;
To allow for rolling back a transaction which has failed or was aborted,&lt;br /&gt;
message handlers of type &#039;&#039;&#039;NFNL_CB_BATCH&#039;&#039;&#039; allocate a &#039;&#039;&#039;struct nft_trans&#039;&#039;&#039;&lt;br /&gt;
object and add it to the per-net commit list. This &amp;quot;log&amp;quot; of what was done is&lt;br /&gt;
also useful to defer actions till the very end of the transaction. See&lt;br /&gt;
&#039;&#039;&#039;nf_tables_commit()&#039;&#039;&#039; for reference of what it is used for in the&lt;br /&gt;
success-case. Similar code is found in &#039;&#039;&#039;nf_tables_abort()&#039;&#039;&#039;, reverting the&lt;br /&gt;
previous changes.&lt;br /&gt;
&lt;br /&gt;
To make the ruleset update atomic, nftables uses an internal generation ID. Its&lt;br /&gt;
value alternates between zero and one upon each commit. Ruleset elements have a&lt;br /&gt;
two-bit &amp;quot;generation mask&amp;quot;, indicating whether that element is active in the&lt;br /&gt;
generation at its bit index. This way, elements may die, get born or stay alive&lt;br /&gt;
when the generation ID toggles again.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1071</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1071"/>
		<updated>2022-09-13T12:24:08Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* nft: from userspace to the kernel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== expressions ==&lt;br /&gt;
&lt;br /&gt;
There are many low expressions that allows us to operate over network packets in different ways. You can think on these low level expressions as assembly-like instructions.&lt;br /&gt;
&lt;br /&gt;
* nft_immediate: loads an immediate value into a register.&lt;br /&gt;
* nft_cmp: compare a given data with data from a given register.&lt;br /&gt;
* nft_payload: set/get arbitrary data from packet headers.&lt;br /&gt;
* nft_bitwise: perform bit-wise math operations over data in a given register.&lt;br /&gt;
* nft_byteorder: perform byte order operations over data in a given register.&lt;br /&gt;
* nft_counter: a basic counter for packet/bytes that gets incremented everything is evaluated for a packet.&lt;br /&gt;
* nft_meta: set/get packet meta information, such as related interfaces, timestamps, etc.&lt;br /&gt;
* nft_lookup: search for data from a given register (key) into a dataset. If the set is a map/vmap, returns the value for that key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
This library provides data structures for entities existing in nf_tables&lt;br /&gt;
nomenclature, such as tables, chains and rules. It serves as an intermediate&lt;br /&gt;
layer between nftables and iptables-nft user space applications and nfnetlink&lt;br /&gt;
messages the kernel sends and receives.&lt;br /&gt;
&lt;br /&gt;
In general, each data structure comes with a set of handling routines:&lt;br /&gt;
&lt;br /&gt;
; allocators : To allocate and free an object of given type&lt;br /&gt;
; setters/getters : Data structure fields are accessed via an attribute number (via a specific enum field)&lt;br /&gt;
; serializers : Populating a netlink message or vice versa&lt;br /&gt;
; printers : Providing a textual representation, mostly for debugging purposes&lt;br /&gt;
&lt;br /&gt;
Where sensible, there is a &#039;&#039;&#039;list-variant&#039;&#039;&#039;, too. If so, it comes with&lt;br /&gt;
handling routines as well:&lt;br /&gt;
&lt;br /&gt;
; allocators : Allocating and freeing the list object (and members)&lt;br /&gt;
; populators : Add and remove from the list&lt;br /&gt;
&lt;br /&gt;
Where useful, there might be a &#039;&#039;&#039;lookup routine&#039;&#039;&#039; as well. With&lt;br /&gt;
nftnl_chain_list, e.g. the list object contains a hash table for chain names as&lt;br /&gt;
well so list lookup by chain name is faster than a linear search.&lt;br /&gt;
&lt;br /&gt;
A typical extra for list objects are &#039;&#039;&#039;iterators&#039;&#039;&#039;: A data structure&lt;br /&gt;
containing state while browsing through the list. Usually the only routines&lt;br /&gt;
used are allocators and a &#039;&#039;next&#039;&#039; routine.&lt;br /&gt;
&lt;br /&gt;
These are the &#039;&#039;&#039;entities defined by libnftnl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
; table : A rather boring &amp;quot;namespace&amp;quot; for chains&lt;br /&gt;
; chain : A container for rules, may attach to a netfilter hook in kernel&lt;br /&gt;
; rule : A container for expressions&lt;br /&gt;
; expr : An nftables VM code instruction&lt;br /&gt;
; flowtable : Similar to a chain, but holds flows between interfaces&lt;br /&gt;
; obj : A generic object, typically holding stateful information&lt;br /&gt;
; ruleset : A container for lists of tables, chains, sets and rules - not used by nftables application anymore&lt;br /&gt;
; set : A container for elements&lt;br /&gt;
; set_elem : A set element&lt;br /&gt;
; trace : A trace event sent by the kernel&lt;br /&gt;
&lt;br /&gt;
=== nftnl_expr ===&lt;br /&gt;
&lt;br /&gt;
While nftables distinguishes between expressions and statements, such&lt;br /&gt;
difference does not quite exist in libnftnl layer. For instance, a statement&lt;br /&gt;
like:&lt;br /&gt;
 ip saddr 192.168.0.1&lt;br /&gt;
is actually two expressions:&lt;br /&gt;
; payload : loading IPv4 header&#039;s source address into a register&lt;br /&gt;
; cmp : comparing data from a register against a stored value&lt;br /&gt;
&lt;br /&gt;
Since expressions have access to the packet, its meta data, all nftables&lt;br /&gt;
registers (including the verdict register) and may store multiple values&lt;br /&gt;
internally, they are mighty and versatile.&lt;br /&gt;
&lt;br /&gt;
=== nftnl_obj ===&lt;br /&gt;
&lt;br /&gt;
This is a common API for various object types. An object&#039;s type is defined post&lt;br /&gt;
allocation by setting the &#039;&#039;NFTNL_OBJ_TYPE&#039;&#039; attribute. Currently existing&lt;br /&gt;
object types are:&lt;br /&gt;
&lt;br /&gt;
* counter&lt;br /&gt;
* quota&lt;br /&gt;
* ct helper&lt;br /&gt;
* limit&lt;br /&gt;
* tunnel&lt;br /&gt;
* ct timeout&lt;br /&gt;
* secmark&lt;br /&gt;
* ct expect&lt;br /&gt;
* synproxy&lt;br /&gt;
&lt;br /&gt;
=== nftnl_batch ===&lt;br /&gt;
&lt;br /&gt;
This is a wrapper interface around the same functionality in libmnl (which is&lt;br /&gt;
used internally). In general, nftnl batches aid in collecting multiple netlink&lt;br /&gt;
messages for kernel submission.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
One goal in nftables development was to provide users with a library for easier&lt;br /&gt;
integration into applications than &amp;quot;shelling out&amp;quot; using &#039;&#039;system()&#039;&#039; and trying&lt;br /&gt;
to parse &#039;&#039;nft&#039;&#039; command output.&lt;br /&gt;
&lt;br /&gt;
At first, &#039;&#039;libnftnl&#039;&#039; was supposed to achieve this but the fact that it&lt;br /&gt;
exposes internal implementation details apart from being pretty low-level in&lt;br /&gt;
general made it rather unsuitable from a users&#039; perspective.&lt;br /&gt;
&lt;br /&gt;
To overcome this, &#039;&#039;nft&#039;&#039; backend code was separated into a library which&lt;br /&gt;
should fill the gap between &#039;&#039;libnftnl&#039;&#039; on one side and &#039;&#039;nft&#039;&#039; application&lt;br /&gt;
itself on the other.&lt;br /&gt;
&lt;br /&gt;
Usage of &#039;&#039;libnftables&#039;&#039; is supposed to be simple and straightforward, almost&lt;br /&gt;
like calling &#039;&#039;nft&#039;&#039; itself but with a bit more convenience. First step is to&lt;br /&gt;
create a new context:&lt;br /&gt;
&lt;br /&gt;
  struct nft_ctx *ctx = nft_ctx_new(0);&lt;br /&gt;
&lt;br /&gt;
The context allows to configure library behaviour on a &amp;quot;per session&amp;quot; basis.&lt;br /&gt;
With this in place, nftables commands may be executed:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_buffer(ctx, &amp;quot;add table inet t&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or whole dump files loaded:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_filename(ctx, &amp;quot;/etc/nftables/all-in-one.nft&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To control output, there are a number of functions:&lt;br /&gt;
&lt;br /&gt;
  FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);&lt;br /&gt;
  int nft_ctx_buffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  int nft_ctx_unbuffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  const char *nft_ctx_get_output_buffer(struct nft_ctx *ctx);&lt;br /&gt;
&lt;br /&gt;
Same for stderr. See libnftables(3) man page for further details.&lt;br /&gt;
&lt;br /&gt;
= nft: from user space to the kernel =&lt;br /&gt;
&lt;br /&gt;
The following describes the steps and entities involved after a call to&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039; in user space until the actual communication with the kernel.&lt;br /&gt;
&lt;br /&gt;
Since creation of &#039;&#039;&#039;libnftables&#039;&#039;&#039;, &#039;&#039;&#039;nft&#039;&#039;&#039; is merely a lightweight&lt;br /&gt;
front-end, basically just creating a &#039;&#039;&#039;libnftables&#039;&#039;&#039; handle, allowing to&lt;br /&gt;
configure it via command-line options and feeding &#039;&#039;&#039;nftables&#039;&#039;&#039; syntax into&lt;br /&gt;
it. Within the library, the actual work takes place. It may be divided into&lt;br /&gt;
several phases:&lt;br /&gt;
&lt;br /&gt;
* Input parsing into internal data structure&lt;br /&gt;
* Evaluation and expansion&lt;br /&gt;
* Serialization into netlink messages&lt;br /&gt;
* nfnetlink message session with kernel&lt;br /&gt;
* Error handling&lt;br /&gt;
&lt;br /&gt;
== Input parsing into internal data structures ==&lt;br /&gt;
&lt;br /&gt;
Depending on whether input comes from command line or a file (which may be&lt;br /&gt;
&#039;&#039;stdin&#039;&#039;), &#039;&#039;&#039;main()&#039;&#039;&#039; calls either &#039;&#039;&#039;nft_run_cmd_from_buffer()&#039;&#039;&#039; or&lt;br /&gt;
&#039;&#039;&#039;nft_run_cmd_from_filename()&#039;&#039;&#039; library functions.&lt;br /&gt;
&lt;br /&gt;
If JSON output was selected (&#039;&#039;&#039;nft -j&#039;&#039;&#039;), the JSON parser (in&lt;br /&gt;
&#039;&#039;src/parser_json.c&#039;&#039;) is tried first. If this did not succeed, the standard&lt;br /&gt;
(&amp;quot;human-readable&amp;quot;) syntax parser is called.&lt;br /&gt;
&lt;br /&gt;
Eventually both parsers populate a list of commands (&#039;&#039;&#039;struct cmd&#039;&#039;&#039;) and a&lt;br /&gt;
list of error messages (&#039;&#039;&#039;struct error_record&#039;&#039;&#039;) in case errors were&lt;br /&gt;
detected.&lt;br /&gt;
&lt;br /&gt;
=== Standard syntax ===&lt;br /&gt;
&lt;br /&gt;
The parser for standard syntax is implemented in lex and yacc, see&lt;br /&gt;
&#039;&#039;src/scanner.l&#039;&#039; and &#039;&#039;src/parser_bison.y&#039;&#039; for reference. It is entered via&lt;br /&gt;
the generated function &#039;&#039;&#039;nft_parse()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As a basic rule, in lex/yacc the scanner recognizes the words and the parser&lt;br /&gt;
interprets them in their context. There is also (limited) scanner control from&lt;br /&gt;
the parser by definition of a scope in which some words are valid or not. The&lt;br /&gt;
parser defines recursive patterns to match input against. Here is the top-most&lt;br /&gt;
one, &#039;&#039;&#039;input&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
input       :       /* empty */&lt;br /&gt;
            |       input           line&lt;br /&gt;
            {&lt;br /&gt;
                    if ($2 != NULL) {&lt;br /&gt;
                            $2-&amp;gt;location = @2;&lt;br /&gt;
                            list_add_tail(&amp;amp;$2-&amp;gt;list, state-&amp;gt;cmds);&lt;br /&gt;
                    }&lt;br /&gt;
            }&lt;br /&gt;
            ;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So it may be empty or (by recursion) consist of a number of&lt;br /&gt;
&#039;&#039;&#039;line&#039;&#039;&#039; patterns. Each of those lines parses into a command and is appended&lt;br /&gt;
to the list. The snippet above also shows how parser-provided &#039;&#039;&#039;location&#039;&#039;&#039;&lt;br /&gt;
data is stored in the command object. This is used for error reporting.&lt;br /&gt;
&lt;br /&gt;
=== JSON syntax ===&lt;br /&gt;
&lt;br /&gt;
The JSON parser lives in &#039;&#039;src/parser_json.c&#039;&#039; and is entered via&lt;br /&gt;
&#039;&#039;&#039;nft_parse_json_buffer()&#039;&#039;&#039; function or &#039;&#039;&#039;nft_parse_json_filename()&#039;&#039;&#039;,&lt;br /&gt;
respectively. It uses jansson library for (de-)serialization and value&lt;br /&gt;
(un-)packing. To learn about the code and to understand the program flow,&lt;br /&gt;
&#039;&#039;&#039;json_parse_cmd()&#039;&#039;&#039; function is a good starting point.&lt;br /&gt;
&lt;br /&gt;
== Evaluation and expansion ==&lt;br /&gt;
&lt;br /&gt;
Input evaluation is a crucial step and combines several tasks. It extends input&lt;br /&gt;
validation from mere syntax checks done by the parser to semantical ones,&lt;br /&gt;
taking context into perspective.&lt;br /&gt;
&lt;br /&gt;
Input may be changed, too. Sometimes it is necessary to insert extra statements&lt;br /&gt;
as dependency, sometimes types of right hand sides of comparisons must adjust&lt;br /&gt;
to left hand side type.&lt;br /&gt;
&lt;br /&gt;
Before all the above, the list of commands is scanned for cache requirements -&lt;br /&gt;
see &#039;&#039;&#039;nft_cache_evaluate()&#039;&#039;&#039; for details. Since caching may be an expensive&lt;br /&gt;
operation if in-kernel ruleset is huge, this step attempts to reduce the data&lt;br /&gt;
fetched from kernel to the bare minimum needed for correct operation. A final&lt;br /&gt;
call to &#039;&#039;&#039;nft_cache_update()&#039;&#039;&#039; then does the actual fetch.&lt;br /&gt;
&lt;br /&gt;
If evaluation passed, expansion takes place. This is mostly to cover for input&lt;br /&gt;
in &amp;quot;dump&amp;quot; notation, i.e. rules nested in chains nested in tables, etc. Such&lt;br /&gt;
input is converted into individual &amp;quot;add&amp;quot; commands as required by the netlink&lt;br /&gt;
message format. The code is pretty straightforward, see &#039;&#039;&#039;nft_cmd_expand()&#039;&#039;&#039;&lt;br /&gt;
for reference.&lt;br /&gt;
&lt;br /&gt;
== Serialization into netlink messages ==&lt;br /&gt;
&lt;br /&gt;
In this step, &#039;&#039;&#039;nftables&#039;&#039;&#039;-internal data types are converted into&lt;br /&gt;
&#039;&#039;&#039;libnftables&#039;&#039;&#039; ones (e.g., &#039;&#039;&#039;struct table&#039;&#039;&#039; into&lt;br /&gt;
&#039;&#039;&#039;struct nftnl_table&#039;&#039;&#039;). The latter abstract their internal layout as&lt;br /&gt;
attributes and are therefore opaque to the caller.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;libnftnl&#039;&#039;&#039; provides helpers to convert its own data structures into netlink&lt;br /&gt;
message format: A generic &#039;&#039;&#039;nftnl_nlmsg_build_hdr()&#039;&#039;&#039; for the header and&lt;br /&gt;
type-specific ones for the payload (e.g.,&lt;br /&gt;
&#039;&#039;&#039;nftnl_table_nlmsg_build_payload()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
The netlink messages are stored in a &#039;&#039;&#039;struct nftnl_batch&#039;&#039;&#039; which provides&lt;br /&gt;
the backing storage. This surrounding data structure serializes into an&lt;br /&gt;
introductory &#039;&#039;&#039;NFNL_MSG_BATCH_BEGIN&#039;&#039;&#039; message and a finalizing one with type&lt;br /&gt;
&#039;&#039;&#039;NFNL_MSG_BATCH_END&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In kernel space, the batch constitutes a transaction: If one of the messages is&lt;br /&gt;
rejected, none of them take effect. Ditto, if the final batch end message is&lt;br /&gt;
missing the whole batch will undo. This is how &#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s &#039;&#039;&#039;--check&#039;&#039;&#039; option&lt;br /&gt;
is implemented.&lt;br /&gt;
&lt;br /&gt;
== nfnetlink message session with kernel ==&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;nft&#039;&#039;&#039;, communication with the kernel takes place in the function&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_talk()&#039;&#039;&#039;: It converts the &#039;&#039;&#039;nftnl_batch&#039;&#039;&#039; into a message&lt;br /&gt;
suitable for &#039;&#039;&#039;sendmsg()&#039;&#039;&#039;, adjusts buffer sizes (if needed), transmits the&lt;br /&gt;
data and listens for a reply. Any error messages are handled by&lt;br /&gt;
&#039;&#039;&#039;mnl_batch_extack_cb()&#039;&#039;&#039; function which records them for later reporting.&lt;br /&gt;
Other messages are relevant for &#039;&#039;&#039;--echo&#039;&#039;&#039; mode, in which the kernel &amp;quot;echoes&amp;quot;&lt;br /&gt;
the requests back after updating them (with handle values, for instance). These&lt;br /&gt;
are handled by &#039;&#039;&#039;netlink_echo_callback()&#039;&#039;&#039;, more or less a wrapper around&lt;br /&gt;
&#039;&#039;&#039;nft&#039;&#039;&#039;&#039;s event monitoring code.&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
Each &#039;&#039;&#039;struct cmd&#039;&#039;&#039; object is identified by its own sequence number&lt;br /&gt;
(monotonic within the batch). Netlink error messages contain this number and&lt;br /&gt;
also an offset value, which allow to identify not only the problematic message&lt;br /&gt;
but also the specific attribute of that message which was rejected.&lt;br /&gt;
&lt;br /&gt;
Mapping from message attribute back to line or word(s) of input works via a&lt;br /&gt;
mapping from attribute offset to the &#039;&#039;&#039;struct location&#039;&#039;&#039; object stored while&lt;br /&gt;
parsing. That bison parser-provided data holds line and column numbers,&lt;br /&gt;
allowing &#039;&#039;&#039;nft&#039;&#039;&#039; to underline problematic parts of input when reporting back&lt;br /&gt;
to the caller.&lt;br /&gt;
&lt;br /&gt;
To follow the above in the source code, see &#039;&#039;&#039;nft_cmd_error()&#039;&#039;&#039; function&lt;br /&gt;
being called for each command and error it caused. The mapping is established&lt;br /&gt;
earlier while creating netlink messages, i.e. in code called from&lt;br /&gt;
&#039;&#039;&#039;do_command()&#039;&#039;&#039; - watch out for the various calls to &#039;&#039;&#039;cmd_add_loc()&#039;&#039;&#039;&lt;br /&gt;
populating the field &#039;&#039;&#039;attr&#039;&#039;&#039; in &#039;&#039;&#039;struct cmd&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to the usespace =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1068</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1068"/>
		<updated>2022-05-19T16:47:17Z</updated>

		<summary type="html">&lt;p&gt;Phil: Added section about libnftables&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== expressions ==&lt;br /&gt;
&lt;br /&gt;
There are many low expressions that allows us to operate over network packets in different ways. You can think on these low level expressions as assembly-like instructions.&lt;br /&gt;
&lt;br /&gt;
* nft_immediate: loads an immediate value into a register.&lt;br /&gt;
* nft_cmp: compare a given data with data from a given register.&lt;br /&gt;
* nft_payload: set/get arbitrary data from packet headers.&lt;br /&gt;
* nft_bitwise: perform bit-wise math operations over data in a given register.&lt;br /&gt;
* nft_byteorder: perform byte order operations over data in a given register.&lt;br /&gt;
* nft_counter: a basic counter for packet/bytes that gets incremented everything is evaluated for a packet.&lt;br /&gt;
* nft_meta: set/get packet meta information, such as related interfaces, timestamps, etc.&lt;br /&gt;
* nft_lookup: search for data from a given register (key) into a dataset. If the set is a map/vmap, returns the value for that key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
This library provides data structures for entities existing in nf_tables&lt;br /&gt;
nomenclature, such as tables, chains and rules. It serves as an intermediate&lt;br /&gt;
layer between nftables and iptables-nft user space applications and nfnetlink&lt;br /&gt;
messages the kernel sends and receives.&lt;br /&gt;
&lt;br /&gt;
In general, each data structure comes with a set of handling routines:&lt;br /&gt;
&lt;br /&gt;
; allocators : To allocate and free an object of given type&lt;br /&gt;
; setters/getters : Data structure fields are accessed via an attribute number (via a specific enum field)&lt;br /&gt;
; serializers : Populating a netlink message or vice versa&lt;br /&gt;
; printers : Providing a textual representation, mostly for debugging purposes&lt;br /&gt;
&lt;br /&gt;
Where sensible, there is a &#039;&#039;&#039;list-variant&#039;&#039;&#039;, too. If so, it comes with&lt;br /&gt;
handling routines as well:&lt;br /&gt;
&lt;br /&gt;
; allocators : Allocating and freeing the list object (and members)&lt;br /&gt;
; populators : Add and remove from the list&lt;br /&gt;
&lt;br /&gt;
Where useful, there might be a &#039;&#039;&#039;lookup routine&#039;&#039;&#039; as well. With&lt;br /&gt;
nftnl_chain_list, e.g. the list object contains a hash table for chain names as&lt;br /&gt;
well so list lookup by chain name is faster than a linear search.&lt;br /&gt;
&lt;br /&gt;
A typical extra for list objects are &#039;&#039;&#039;iterators&#039;&#039;&#039;: A data structure&lt;br /&gt;
containing state while browsing through the list. Usually the only routines&lt;br /&gt;
used are allocators and a &#039;&#039;next&#039;&#039; routine.&lt;br /&gt;
&lt;br /&gt;
These are the &#039;&#039;&#039;entities defined by libnftnl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
; table : A rather boring &amp;quot;namespace&amp;quot; for chains&lt;br /&gt;
; chain : A container for rules, may attach to a netfilter hook in kernel&lt;br /&gt;
; rule : A container for expressions&lt;br /&gt;
; expr : An nftables VM code instruction&lt;br /&gt;
; flowtable : Similar to a chain, but holds flows between interfaces&lt;br /&gt;
; obj : A generic object, typically holding stateful information&lt;br /&gt;
; ruleset : A container for lists of tables, chains, sets and rules - not used by nftables application anymore&lt;br /&gt;
; set : A container for elements&lt;br /&gt;
; set_elem : A set element&lt;br /&gt;
; trace : A trace event sent by the kernel&lt;br /&gt;
&lt;br /&gt;
=== nftnl_expr ===&lt;br /&gt;
&lt;br /&gt;
While nftables distinguishes between expressions and statements, such&lt;br /&gt;
difference does not quite exist in libnftnl layer. For instance, a statement&lt;br /&gt;
like:&lt;br /&gt;
 ip saddr 192.168.0.1&lt;br /&gt;
is actually two expressions:&lt;br /&gt;
; payload : loading IPv4 header&#039;s source address into a register&lt;br /&gt;
; cmp : comparing data from a register against a stored value&lt;br /&gt;
&lt;br /&gt;
Since expressions have access to the packet, its meta data, all nftables&lt;br /&gt;
registers (including the verdict register) and may store multiple values&lt;br /&gt;
internally, they are mighty and versatile.&lt;br /&gt;
&lt;br /&gt;
=== nftnl_obj ===&lt;br /&gt;
&lt;br /&gt;
This is a common API for various object types. An object&#039;s type is defined post&lt;br /&gt;
allocation by setting the &#039;&#039;NFTNL_OBJ_TYPE&#039;&#039; attribute. Currently existing&lt;br /&gt;
object types are:&lt;br /&gt;
&lt;br /&gt;
* counter&lt;br /&gt;
* quota&lt;br /&gt;
* ct helper&lt;br /&gt;
* limit&lt;br /&gt;
* tunnel&lt;br /&gt;
* ct timeout&lt;br /&gt;
* secmark&lt;br /&gt;
* ct expect&lt;br /&gt;
* synproxy&lt;br /&gt;
&lt;br /&gt;
=== nftnl_batch ===&lt;br /&gt;
&lt;br /&gt;
This is a wrapper interface around the same functionality in libmnl (which is&lt;br /&gt;
used internally). In general, nftnl batches aid in collecting multiple netlink&lt;br /&gt;
messages for kernel submission.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
One goal in nftables development was to provide users with a library for easier&lt;br /&gt;
integration into applications than &amp;quot;shelling out&amp;quot; using &#039;&#039;system()&#039;&#039; and trying&lt;br /&gt;
to parse &#039;&#039;nft&#039;&#039; command output.&lt;br /&gt;
&lt;br /&gt;
At first, &#039;&#039;libnftnl&#039;&#039; was supposed to achieve this but the fact that it&lt;br /&gt;
exposes internal implementation details apart from being pretty low-level in&lt;br /&gt;
general made it rather unsuitable from a users&#039; perspective.&lt;br /&gt;
&lt;br /&gt;
To overcome this, &#039;&#039;nft&#039;&#039; backend code was separated into a library which&lt;br /&gt;
should fill the gap between &#039;&#039;libnftnl&#039;&#039; on one side and &#039;&#039;nft&#039;&#039; application&lt;br /&gt;
itself on the other.&lt;br /&gt;
&lt;br /&gt;
Usage of &#039;&#039;libnftables&#039;&#039; is supposed to be simple and straightforward, almost&lt;br /&gt;
like calling &#039;&#039;nft&#039;&#039; itself but with a bit more convenience. First step is to&lt;br /&gt;
create a new context:&lt;br /&gt;
&lt;br /&gt;
  struct nft_ctx *ctx = nft_ctx_new(0);&lt;br /&gt;
&lt;br /&gt;
The context allows to configure library behaviour on a &amp;quot;per session&amp;quot; basis.&lt;br /&gt;
With this in place, nftables commands may be executed:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_buffer(ctx, &amp;quot;add table inet t&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or whole dump files loaded:&lt;br /&gt;
&lt;br /&gt;
  int rc = nft_run_cmd_from_filename(ctx, &amp;quot;/etc/nftables/all-in-one.nft&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To control output, there are a number of functions:&lt;br /&gt;
&lt;br /&gt;
  FILE *nft_ctx_set_output(struct nft_ctx *ctx, FILE *fp);&lt;br /&gt;
  int nft_ctx_buffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  int nft_ctx_unbuffer_output(struct nft_ctx *ctx);&lt;br /&gt;
  const char *nft_ctx_get_output_buffer(struct nft_ctx *ctx);&lt;br /&gt;
&lt;br /&gt;
Same for stderr. See libnftables(3) man page for further details.&lt;br /&gt;
&lt;br /&gt;
= nft: from userspace to the kernel =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to the usespace =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1067</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=1067"/>
		<updated>2022-05-06T16:15:16Z</updated>

		<summary type="html">&lt;p&gt;Phil: Add a description of libnftnl&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== expressions ==&lt;br /&gt;
&lt;br /&gt;
There are many low expressions that allows us to operate over network packets in different ways. You can think on these low level expressions as assembly-like instructions.&lt;br /&gt;
&lt;br /&gt;
* nft_immediate: loads an immediate value into a register.&lt;br /&gt;
* nft_cmp: compare a given data with data from a given register.&lt;br /&gt;
* nft_payload: set/get arbitrary data from packet headers.&lt;br /&gt;
* nft_bitwise: perform bit-wise math operations over data in a given register.&lt;br /&gt;
* nft_byteorder: perform byte order operations over data in a given register.&lt;br /&gt;
* nft_counter: a basic counter for packet/bytes that gets incremented everything is evaluated for a packet.&lt;br /&gt;
* nft_meta: set/get packet meta information, such as related interfaces, timestamps, etc.&lt;br /&gt;
* nft_lookup: search for data from a given register (key) into a dataset. If the set is a map/vmap, returns the value for that key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
This library provides data structures for entities existing in nf_tables&lt;br /&gt;
nomenclature, such as tables, chains and rules. It serves as an intermediate&lt;br /&gt;
layer between nftables and iptables-nft user space applications and nfnetlink&lt;br /&gt;
messages the kernel sends and receives.&lt;br /&gt;
&lt;br /&gt;
In general, each data structure comes with a set of handling routines:&lt;br /&gt;
&lt;br /&gt;
; allocators : To allocate and free an object of given type&lt;br /&gt;
; setters/getters : Data structure fields are accessed via an attribute number (via a specific enum field)&lt;br /&gt;
; serializers : Populating a netlink message or vice versa&lt;br /&gt;
; printers : Providing a textual representation, mostly for debugging purposes&lt;br /&gt;
&lt;br /&gt;
Where sensible, there is a &#039;&#039;&#039;list-variant&#039;&#039;&#039;, too. If so, it comes with&lt;br /&gt;
handling routines as well:&lt;br /&gt;
&lt;br /&gt;
; allocators : Allocating and freeing the list object (and members)&lt;br /&gt;
; populators : Add and remove from the list&lt;br /&gt;
&lt;br /&gt;
Where useful, there might be a &#039;&#039;&#039;lookup routine&#039;&#039;&#039; as well. With&lt;br /&gt;
nftnl_chain_list, e.g. the list object contains a hash table for chain names as&lt;br /&gt;
well so list lookup by chain name is faster than a linear search.&lt;br /&gt;
&lt;br /&gt;
A typical extra for list objects are &#039;&#039;&#039;iterators&#039;&#039;&#039;: A data structure&lt;br /&gt;
containing state while browsing through the list. Usually the only routines&lt;br /&gt;
used are allocators and a &#039;&#039;next&#039;&#039; routine.&lt;br /&gt;
&lt;br /&gt;
These are the &#039;&#039;&#039;entities defined by libnftnl&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
; table : A rather boring &amp;quot;namespace&amp;quot; for chains&lt;br /&gt;
; chain : A container for rules, may attach to a netfilter hook in kernel&lt;br /&gt;
; rule : A container for expressions&lt;br /&gt;
; expr : An nftables VM code instruction&lt;br /&gt;
; flowtable : Similar to a chain, but holds flows between interfaces&lt;br /&gt;
; obj : A generic object, typically holding stateful information&lt;br /&gt;
; ruleset : A container for lists of tables, chains, sets and rules - not used by nftables application anymore&lt;br /&gt;
; set : A container for elements&lt;br /&gt;
; set_elem : A set element&lt;br /&gt;
; trace : A trace event sent by the kernel&lt;br /&gt;
&lt;br /&gt;
=== nftnl_expr ===&lt;br /&gt;
&lt;br /&gt;
While nftables distinguishes between expressions and statements, such&lt;br /&gt;
difference does not quite exist in libnftnl layer. For instance, a statement&lt;br /&gt;
like:&lt;br /&gt;
 ip saddr 192.168.0.1&lt;br /&gt;
is actually two expressions:&lt;br /&gt;
; payload : loading IPv4 header&#039;s source address into a register&lt;br /&gt;
; cmp : comparing data from a register against a stored value&lt;br /&gt;
&lt;br /&gt;
Since expressions have access to the packet, its meta data, all nftables&lt;br /&gt;
registers (including the verdict register) and may store multiple values&lt;br /&gt;
internally, they are mighty and versatile.&lt;br /&gt;
&lt;br /&gt;
=== nftnl_obj ===&lt;br /&gt;
&lt;br /&gt;
This is a common API for various object types. An object&#039;s type is defined post&lt;br /&gt;
allocation by setting the &#039;&#039;NFTNL_OBJ_TYPE&#039;&#039; attribute. Currently existing&lt;br /&gt;
object types are:&lt;br /&gt;
&lt;br /&gt;
* counter&lt;br /&gt;
* quota&lt;br /&gt;
* ct helper&lt;br /&gt;
* limit&lt;br /&gt;
* tunnel&lt;br /&gt;
* ct timeout&lt;br /&gt;
* secmark&lt;br /&gt;
* ct expect&lt;br /&gt;
* synproxy&lt;br /&gt;
&lt;br /&gt;
=== nftnl_batch ===&lt;br /&gt;
&lt;br /&gt;
This is a wrapper interface around the same functionality in libmnl (which is&lt;br /&gt;
used internally). In general, nftnl batches aid in collecting multiple netlink&lt;br /&gt;
messages for kernel submission.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= nft: from userspace to the kernel =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to the usespace =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=1065</id>
		<title>Simple rule management</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=1065"/>
		<updated>2022-04-08T09:16:46Z</updated>

		<summary type="html">&lt;p&gt;Phil: nft requires options before commands nowadays&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Rules take action on network packets (e.g. accepting or dropping them) based on whether they match specified criteria. &lt;br /&gt;
&lt;br /&gt;
Each rule consists of zero or more expressions followed by one or more statements. Each expression tests whether a packet matches a specific payload field or packet/flow metadata. Multiple expressions are linearly evaluated from left to right: if the first expression matches, then the next expression is evaluated and so on. If we reach the final expression, then the packet matches all of the expressions in the rule, and the rule&#039;s statements are executed. Each statement takes an action, such as setting the netfilter mark, counting the packet, logging the packet, or rendering a verdict such as accepting or dropping the packet or jumping to another chain. As with expressions, multiple statements are linearly evaluated from left to right: a single rule can take multiple actions by using multiple statements. Do note that a verdict statement by its nature ends the rule.&lt;br /&gt;
&lt;br /&gt;
Following are some basic operations and commands for configuring rules:&lt;br /&gt;
&lt;br /&gt;
= Appending new rules =&lt;br /&gt;
&lt;br /&gt;
To add new rules, you have to specify the corresponding table and the chain that you want to use, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output ip daddr 8.8.8.8 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;filter&#039;&#039; is the table and &#039;&#039;output&#039;&#039; is the chain. The example above adds a rule to match all packets seen by the output chain whose destination is 8.8.8.8, in case of matching it updates the rule counters. Note that counters are optional in &#039;&#039;nftables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
For those familiar with iptables, the rule appending is equivalent to &#039;&#039;-A&#039;&#039; command in iptables.&lt;br /&gt;
&lt;br /&gt;
= Listing rules =&lt;br /&gt;
&lt;br /&gt;
You can list the rules that are contained by a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also list rules by chain, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list chain filter ouput&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are plenty of [[Output_text_modifiers | output text modifiers]] than can be used when listing your rules, to for example, translate IP addresses to DNS names, TCP protocols, etc.&lt;br /&gt;
&lt;br /&gt;
= Testing your rule =&lt;br /&gt;
&lt;br /&gt;
Let&#039;s test this rule with a simple ping to 8.8.8.8:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% ping -c 1 8.8.8.8&lt;br /&gt;
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.&lt;br /&gt;
64 bytes from 8.8.8.8: icmp_req=1 ttl=64 time=1.31 ms&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if we list the rule-set, we obtain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -nn list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 1 bytes 84&lt;br /&gt;
                 tcp dport 22 counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the counters have been updated.&lt;br /&gt;
&lt;br /&gt;
= Adding a rule at a given position =&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule at a given position, you have to use the handle as reference:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -n -a list table filter&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 82 bytes 9680 # handle 8&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule after the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can check the effect of that command by listing the rule-set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -n -a list table filter&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 190 bytes 21908 # handle 8&lt;br /&gt;
                 ip daddr 127.0.0.8 drop # handle 10&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to insert a rule before the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Removing rules =&lt;br /&gt;
&lt;br /&gt;
You have to obtain the &#039;&#039;handle&#039;&#039; to delete a rule via the &#039;&#039;&#039;-a&#039;&#039;&#039; option. The &#039;&#039;handle&#039;&#039; is automagically assigned by the kernel and it uniquely identifies the rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -a list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 192.168.1.1 counter packets 1 bytes 84 # handle 5&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can delete the rule whose handle is &#039;&#039;5&#039;&#039; with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output handle 5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: There are plans to support rule deletion by passing:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output ip saddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
but this is &#039;&#039;&#039;not&#039;&#039;&#039; yet implemented. So you&#039;ll have to use the handle to delete rules until that feature is implemented.&lt;br /&gt;
&lt;br /&gt;
= Removing all the rules in a chain =&lt;br /&gt;
&lt;br /&gt;
You can delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a chain with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush rule filter output&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prepending new rules =&lt;br /&gt;
&lt;br /&gt;
To prepend new rules through the &#039;&#039;insert&#039;&#039; command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output ip daddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This prepends a rule that will update per-rule packet and bytes counters for traffic addressed to 192.168.1.1.&lt;br /&gt;
&lt;br /&gt;
The equivalent in iptables is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% iptables -I OUTPUT -t filter -d 192.168.1.1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that iptables always provides per-rule counters.&lt;br /&gt;
&lt;br /&gt;
= Replacing rules =&lt;br /&gt;
&lt;br /&gt;
You can replace any rule via the &#039;&#039;replace&#039;&#039; command by indicating the rule handle, which you have to find by first listing the ruleset with option &#039;&#039;-a&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft -a list ruleset&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                ip protocol tcp counter packets 0 bytes 0 # handle 2&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To replace the rule with handle 2, specify its handle number and the new rule that you want to replace it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft replace rule filter input handle 2 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Listing the ruleset after the above replacement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft list ruleset&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                counter packets 0 bytes 0 &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
you can see that the old rule that counted TCP packets has been replaced by the new rule that counts all packets.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1062</id>
		<title>Supported features compared to xtables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1062"/>
		<updated>2022-03-11T17:34:00Z</updated>

		<summary type="html">&lt;p&gt;Phil: Review the list, update details, add links to xlate-test cases for samples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Last update: Mar/2022&lt;br /&gt;
&lt;br /&gt;
This page tracks the list of supported and unsupported extensions with comments and suggestions.&lt;br /&gt;
&lt;br /&gt;
== Unsupported extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches: xt ===&lt;br /&gt;
&lt;br /&gt;
==== bpf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== rateest ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== string ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== u32 ====&lt;br /&gt;
* raw expressions?&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===&lt;br /&gt;
&lt;br /&gt;
==== CHECKSUM ====&lt;br /&gt;
* add nft_payload.&lt;br /&gt;
* To the day, the only use case for this was DHCP clients not working with partial checksums. That should be fixed nowadays.&lt;br /&gt;
* See https://lwn.net/Articles/396466/ and https://www.spinics.net/lists/kvm/msg37660.html&lt;br /&gt;
* See https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/930962 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832090&lt;br /&gt;
&lt;br /&gt;
==== CT ====&lt;br /&gt;
* nft_ct_target. Refer to [[Matching_connection_tracking_stateful_metainformation]].&lt;br /&gt;
==== IDLETIMER ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== LED ====&lt;br /&gt;
* consider native (need this?)&lt;br /&gt;
==== RATEEST ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== TCPOPTSTRIP ====&lt;br /&gt;
* consider native interface, need to extend nft_exthdr.c&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== TTL ====&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
&lt;br /&gt;
==== NPT ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== arpreply ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: arp ===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
== Supported extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches: xt ===&lt;br /&gt;
&lt;br /&gt;
==== addrtype ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel. Refer to [[Matching routing information]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_addrtype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== cgroup ====&lt;br /&gt;
* nft_meta. Refer to [[Quick_reference-nftables_in_10_minutes#Meta]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cgroup.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Awaits support for cgroup2]&lt;br /&gt;
&lt;br /&gt;
==== cluster ====&lt;br /&gt;
* nft_hash&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cluster.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
* Built-in support via NFTA_RULE_USERDATA, since 3.15 (Pablo Neira). Refer to [[Matching_packet_headers#Matching_UDP.2FTCP_headers_in_the_same_rule|matching UDP/TCP headers in the same rule]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_comment.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== connbytes ====&lt;br /&gt;
* nft_ct, 4.5 kernel. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connbytes.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connlabel ====&lt;br /&gt;
* nft_meta, since 3.16.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connlabel.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connlimit ====&lt;br /&gt;
* consider native interface. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connlimit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== connmark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_connmark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== conntrack ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_conntrack.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== cpu ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_cpu.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== dccp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_dccp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : dccp-option]&lt;br /&gt;
==== devgroup ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_devgroup.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== dscp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_dscp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ecn ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_ecn.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== esp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_esp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== hashlimit ====&lt;br /&gt;
* meter statement. Refer to [[Meters]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_hashlimit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== helper ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_helper.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ipcomp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_ipcomp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : compres]&lt;br /&gt;
==== iprange ====&lt;br /&gt;
* nft_payload, through native range support. To emulate iptables --ports you need two rules.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_iprange.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== ipvs ====&lt;br /&gt;
* consider native interface. Refer to [[Load balancing]].&lt;br /&gt;
==== length ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_length.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit. Refer to [[Stateful objects]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_limit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== mac ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_mac.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_mark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== multiport ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_multiport.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== nfacct ====&lt;br /&gt;
* consider native interface. Refer to [[Stateful objects]].&lt;br /&gt;
==== osf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== owner ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_owner.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported option : socket-exists]&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_pkttype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== policy ====&lt;br /&gt;
* nft_xfrm, since 5.0&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_policy.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== recent ====&lt;br /&gt;
* consider native interface. Refer to [[Sets]].&lt;br /&gt;
==== sctp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* nft_exthdr for --chunk-types&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_sctp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== socket ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== statistic ====&lt;br /&gt;
* nft_numgen. Refer to [[Load balancing]].&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_statistic.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== set ====&lt;br /&gt;
* Use native nf_tables set infrastructure.&lt;br /&gt;
==== state ====&lt;br /&gt;
* nft_ct&lt;br /&gt;
==== tcp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_tcp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== tcpmss ====&lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
&lt;br /&gt;
==== time ====&lt;br /&gt;
* nft_meta, since 5.4&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_time.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== udp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_udp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===&lt;br /&gt;
&lt;br /&gt;
==== AUDIT ====&lt;br /&gt;
* nft_log, since 4.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_AUDIT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CLASSIFY ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_CLASSIFY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CONNMARK ====&lt;br /&gt;
* nft_ct&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_CONNMARK.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== CONNSECMARK ====&lt;br /&gt;
* nft_ct, since 4.20&lt;br /&gt;
==== DSCP ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_DSCP.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== HL ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
==== HMARK ====&lt;br /&gt;
* nft_meta + nft_hash.&lt;br /&gt;
==== MARK ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_MARK.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== NETMAP ====&lt;br /&gt;
* nft_nat, upcoming 5.8&lt;br /&gt;
==== NFLOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_NFLOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== NFQUEUE ====&lt;br /&gt;
* nft_queue, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_NFQUEUE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SECMARK ====&lt;br /&gt;
* nft_meta, since 4.20&lt;br /&gt;
&lt;br /&gt;
==== SYNPROXY ====&lt;br /&gt;
* nft_synproxy, since 5.3&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_SYNPROXY.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TEE ====&lt;br /&gt;
* nft_dup, since 4.3.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TEE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== TPROXY ====&lt;br /&gt;
* nft_tproxy, since 4.19&lt;br /&gt;
&lt;br /&gt;
==== TRACE ====&lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libxt_TRACE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== TCPMSS ====&lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== ah ====&lt;br /&gt;
* nft_payload + nft_cmp&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_ah.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== icmp ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_icmp.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported codes: network-unreachable, host-unreachable, protocol-unreachable, port-unreachable, fragmentation-needed, source-route-failed, network-unknown, host-unknown, network-prohibited, host-prohibited, TOS-network-unreachable, TOS-host-unreachable, communication-prohibited, host-precedence-violation, precedence-cutoff, network-redirect, host-redirect, TOS-network-redirect, TOS-host-redirect, ttl-zero-during-transit, ttl-zero-during-reassembly, ip-header-bad and required-option-missing ]&lt;br /&gt;
==== realm ====&lt;br /&gt;
* nft_meta, through NFT_META_RTCLASSID.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_realm.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ttl ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_ttl.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv6 ===&lt;br /&gt;
&lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ah  ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_ah.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== eui64 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
==== frag ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_frag.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== hbh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_hbh.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
HBH options are not supported yet.&lt;br /&gt;
[Unsupported option: --hbh-opts]&lt;br /&gt;
==== hl ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_hl.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== icmp6 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_icmp6.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported icmpv6 codes: no-route, communication-prohibited, beyond-scope, address-unreachable, port-unreachable, failed-policy, reject-route, ttl-zero-during-transit, ttl-zero-during-reassembly, bad-header, unknown-header-type and unknown-option]&lt;br /&gt;
==== ipv6header ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
==== mh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_mh.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Needs bug fixation for option mh-type with range]&lt;br /&gt;
==== rt ====&lt;br /&gt;
* nft_exthdr + nft_cmp&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_rt.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options: --rt-0-res, --rt-0-addrs, --rt-0-not-strict]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
==== ECN ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_DNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_LOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_MASQUERADE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_REDIRECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====&lt;br /&gt;
* nft_reject_ipv4, since 3.13.&lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_REJECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libipt_SNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_DNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_LOG.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_MASQUERADE.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_REDIRECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====&lt;br /&gt;
* nft_reject_ipv6, since 3.14.&lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_REJECT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
==== SNAT ====&lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libip6t_SNAT.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
=== matches: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== 802.3 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== among ====&lt;br /&gt;
* sets&lt;br /&gt;
&lt;br /&gt;
==== arp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== ip ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_ip.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== ip6 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_ip6.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_limit.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_mark_m.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_pkttype.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== stp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== vlan ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_vlan.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== dnat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_dnat.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== snat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_snat.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== redirect ====&lt;br /&gt;
* nft_payload + nft_meta (pkttype set unicast)&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_mark.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== watchers: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== log ====&lt;br /&gt;
* nft_log&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_log.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== nflog ====&lt;br /&gt;
* nft_log&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_nflog.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
== Deprecated extensions ==&lt;br /&gt;
&lt;br /&gt;
=== matches ===&lt;br /&gt;
&lt;br /&gt;
==== physdev ====&lt;br /&gt;
* br_netfilter aims to be deprecated by nftables.&lt;br /&gt;
==== quota ====&lt;br /&gt;
* nfacct already provides quota support.&lt;br /&gt;
==== tos ====&lt;br /&gt;
* deprecated by dscp&lt;br /&gt;
&lt;br /&gt;
=== targets ===&lt;br /&gt;
&lt;br /&gt;
==== CLUSTERIP ====&lt;br /&gt;
* deprecated by cluster match.&lt;br /&gt;
==== TOS ====&lt;br /&gt;
* deprecated by DSCP&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
&lt;br /&gt;
==== ULOG ====&lt;br /&gt;
* Removed from tree since 3.17.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1061</id>
		<title>Supported features compared to xtables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=1061"/>
		<updated>2022-03-10T17:40:13Z</updated>

		<summary type="html">&lt;p&gt;Phil: Link to iptables-translate testsuite for examples, libebt_log.txlate only for now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Last update: Aug/2018&lt;br /&gt;
                                                                                 &lt;br /&gt;
This page tracks the list of supported and unsupported extensions with comments and suggestions.&lt;br /&gt;
                                                                                 &lt;br /&gt;
== Unsupported extensions ==                                                     &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== matches: xt ===                                                              &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== bpf ====                                                                    &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== cluster ====                                                                &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== rateest ====                                                                &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== string ====                                                                 &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== u32 ====                                                                    &lt;br /&gt;
* raw expressions?                                                               &lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===                                                              &lt;br /&gt;
                                                         &lt;br /&gt;
==== CHECKSUM ====                                                               &lt;br /&gt;
* add nft_payload.&lt;br /&gt;
* To the day, the only use case for this was DHCP clients not working with partial checksums. That should be fixed nowadays.&lt;br /&gt;
* See https://lwn.net/Articles/396466/ and https://www.spinics.net/lists/kvm/msg37660.html&lt;br /&gt;
* See https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/930962 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832090&lt;br /&gt;
&lt;br /&gt;
==== CT ====                                                                     &lt;br /&gt;
* nft_ct_target. Refer to [[Matching_connection_tracking_stateful_metainformation]].                                              &lt;br /&gt;
==== IDLETIMER ====                                                              &lt;br /&gt;
* consider native interface&lt;br /&gt;
==== LED ====                                                                    &lt;br /&gt;
* consider native (need this?)                                                                                                            &lt;br /&gt;
==== RATEEST ====                                                                &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== TCPOPTSTRIP ====                                                            &lt;br /&gt;
* consider native interface, need to extend nft_exthdr.c&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== TTL ====&lt;br /&gt;
                                                                                 &lt;br /&gt;
=== targets: ipv6 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== NPT ====                                                                    &lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== arpreply ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== watchers: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== log ====&lt;br /&gt;
* nft_log&lt;br /&gt;
* [https://git.netfilter.org/iptables/tree/extensions/libebt_log.txlate Examples from iptables-translate testsuite]&lt;br /&gt;
&lt;br /&gt;
==== nflog ====&lt;br /&gt;
* nft_log&lt;br /&gt;
&lt;br /&gt;
=== targets: arp ===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
== Supported extensions ==                                                       &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== matches: xt ===                                                              &lt;br /&gt;
&lt;br /&gt;
==== addrtype ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel. Refer to [[Matching routing information]].&lt;br /&gt;
&lt;br /&gt;
==== cgroup ====&lt;br /&gt;
* nft_meta. Refer to [[Quick_reference-nftables_in_10_minutes#Meta]].&lt;br /&gt;
[Awaits support for cgroup2]                                                                             &lt;br /&gt;
==== comment ====&lt;br /&gt;
* Built-in support via NFTA_RULE_USERDATA, since 3.15 (Pablo Neira). Refer to [[Matching_packet_headers#Matching_UDP.2FTCP_headers_in_the_same_rule|matching UDP/TCP headers in the same rule]].&lt;br /&gt;
&lt;br /&gt;
==== connbytes ====                                                              &lt;br /&gt;
* nft_ct, 4.5 kernel. Refer to [[Meters]].&lt;br /&gt;
==== connlabel ====                                                              &lt;br /&gt;
* nft_meta, since 3.16.&lt;br /&gt;
==== connlimit ====&lt;br /&gt;
* consider native interface. Refer to [[Meters]].&lt;br /&gt;
==== connmark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
==== conntrack ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
==== cpu ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
==== dccp ====                                                                   &lt;br /&gt;
* nft_payload.    &lt;br /&gt;
[Unsupported option : dccp-option]&lt;br /&gt;
==== devgroup ====                                                               &lt;br /&gt;
* nft_meta, since 3.18.  &lt;br /&gt;
==== dscp ====                                              &lt;br /&gt;
* nft_payload.&lt;br /&gt;
==== ecn ====                                                                    &lt;br /&gt;
* nft_payload.                                                                   &lt;br /&gt;
==== esp ====                                                                    &lt;br /&gt;
* nft_payload.                                                                   &lt;br /&gt;
==== hashlimit ====                                                              &lt;br /&gt;
* meter statement. Refer to [[Meters]].&lt;br /&gt;
==== helper ====                                                                 &lt;br /&gt;
* nft_ct.&lt;br /&gt;
==== ipcomp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
[Unsupported option : compres]&lt;br /&gt;
==== iprange ====                                                                &lt;br /&gt;
* nft_payload, through native range support. To emulate iptables --ports you need two rules.                                                   &lt;br /&gt;
==== ipvs ====&lt;br /&gt;
* consider native interface. Refer to [[Load balancing]].&lt;br /&gt;
==== length ====                                                                 &lt;br /&gt;
* nft_meta.                                                                      &lt;br /&gt;
==== limit ====                                                                  &lt;br /&gt;
* nft_limit. Refer to [[Stateful objects]].&lt;br /&gt;
==== mac ====                                                                    &lt;br /&gt;
* nft_payload.                                                                   &lt;br /&gt;
==== mark ====                                                                   &lt;br /&gt;
* nft_meta.                                                                      &lt;br /&gt;
==== multiport ====                                                              &lt;br /&gt;
* nft_payload. &lt;br /&gt;
[Unsupported option : ports]                                                                                         &lt;br /&gt;
==== nfacct ====&lt;br /&gt;
* consider native interface. Refer to [[Stateful objects]].&lt;br /&gt;
==== osf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== owner ====                                                                  &lt;br /&gt;
* nft_meta. &lt;br /&gt;
[Unsupported option : socket-exists]                                                                     &lt;br /&gt;
==== pkttype ====                                                                &lt;br /&gt;
* nft_meta&lt;br /&gt;
==== policy ====&lt;br /&gt;
* nft_xfrm, since 5.0&lt;br /&gt;
==== recent ====                                                                 &lt;br /&gt;
* consider native interface. Refer to [[Sets]].&lt;br /&gt;
==== sctp ====                                                                   &lt;br /&gt;
* nft_payload&lt;br /&gt;
* nft_exthdr for --chunk-types&lt;br /&gt;
==== socket ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== statistic ====&lt;br /&gt;
* nft_numgen. Refer to [[Load balancing]].&lt;br /&gt;
==== set ====&lt;br /&gt;
* Use native nf_tables set infrastructure.                                       &lt;br /&gt;
==== state ====                                                                  &lt;br /&gt;
* nft_ct                                                                         &lt;br /&gt;
==== tcp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
==== tcpmss ====                                                                 &lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
&lt;br /&gt;
==== time ====&lt;br /&gt;
* nft_meta, since 5.4&lt;br /&gt;
&lt;br /&gt;
==== udp ====                                                                 &lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===                                                              &lt;br /&gt;
&lt;br /&gt;
==== AUDIT ====                                                              &lt;br /&gt;
* nft_log, since 4.18.&lt;br /&gt;
==== CLASSIFY ====                                                               &lt;br /&gt;
* nft_meta, since 3.14.    &lt;br /&gt;
==== CONNMARK ====                                                                                                                    &lt;br /&gt;
* nft_ct&lt;br /&gt;
==== CONNSECMARK ====&lt;br /&gt;
* nft_ct, since 4.20&lt;br /&gt;
==== DSCP ====                                                                                                                    &lt;br /&gt;
==== HL ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
==== HMARK ====&lt;br /&gt;
* nft_meta + nft_hash.&lt;br /&gt;
==== MARK ====                                                                   &lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
==== NETMAP ====                                                                 &lt;br /&gt;
* nft_nat, upcoming 5.8              &lt;br /&gt;
==== NFLOG ====                                                                  &lt;br /&gt;
* nft_log, since 3.17.                                             &lt;br /&gt;
==== NFQUEUE ====                                                                &lt;br /&gt;
* nft_queue, since 3.14.&lt;br /&gt;
==== SECMARK ====&lt;br /&gt;
* nft_meta, since 4.20&lt;br /&gt;
&lt;br /&gt;
==== SYNPROXY ====&lt;br /&gt;
* nft_synproxy, since 5.3&lt;br /&gt;
&lt;br /&gt;
==== TEE ====&lt;br /&gt;
* nft_dup, since 4.3.&lt;br /&gt;
==== TPROXY ====&lt;br /&gt;
* nft_tproxy, since 4.19&lt;br /&gt;
&lt;br /&gt;
==== TRACE ====                                                                  &lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
&lt;br /&gt;
==== TCPMSS ====                                                                 &lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv4 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== ah ====                                                                     &lt;br /&gt;
* nft_payload + nft_cmp&lt;br /&gt;
==== icmp ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
[Unsupported codes: network-unreachable, host-unreachable, protocol-unreachable, port-unreachable, fragmentation-needed, source-route-failed, network-unknown, host-unknown, network-prohibited, host-prohibited, TOS-network-unreachable, TOS-host-unreachable, communication-prohibited, host-precedence-violation, precedence-cutoff, network-redirect, host-redirect, TOS-network-redirect, TOS-host-redirect, ttl-zero-during-transit, ttl-zero-during-reassembly, ip-header-bad and required-option-missing ]&lt;br /&gt;
==== realm ====                                                                  &lt;br /&gt;
* nft_meta, through NFT_META_RTCLASSID. &lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ttl ====&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv6 ===                                                            &lt;br /&gt;
            &lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel                                                                    &lt;br /&gt;
==== ah  ====                                                                    &lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
==== eui64 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
==== frag ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
==== hbh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
HBH options are not supported yet.&lt;br /&gt;
[Unsupported option: --hbh-opts]&lt;br /&gt;
==== hl ==== &lt;br /&gt;
* nft_payload.    &lt;br /&gt;
==== icmp6 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
[Unsupported icmpv6 codes: no-route, communication-prohibited, beyond-scope, address-unreachable, port-unreachable, failed-policy, reject-route, ttl-zero-during-transit, ttl-zero-during-reassembly, bad-header, unknown-header-type and unknown-option]&lt;br /&gt;
==== ipv6header ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
==== mh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
[Needs bug fixation for option mh-type with range]&lt;br /&gt;
==== rt ====&lt;br /&gt;
* nft_exthdr + nft_cmp&lt;br /&gt;
[Unsupported options: --rt-0-res, --rt-0-addrs, --rt-0-not-strict]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
==== ECN ====                                                                    &lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== DNAT ====    &lt;br /&gt;
* nft_nat, since 3.13.    &lt;br /&gt;
==== LOG ====                                                                    &lt;br /&gt;
* nft_log, since 3.17.  &lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====                                                                 &lt;br /&gt;
* nft_reject_ipv4, since 3.13.                                         &lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.  &lt;br /&gt;
==== SNAT ====                                                            &lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.    &lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.  &lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====                                                             &lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
==== REDIRECT ====                                                               &lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====                                                                                   &lt;br /&gt;
* nft_reject_ipv6, since 3.14.                     &lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.    &lt;br /&gt;
==== SNAT ====                                                                                                                          &lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
&lt;br /&gt;
=== matches: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== 802.3 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== among ====&lt;br /&gt;
* sets&lt;br /&gt;
&lt;br /&gt;
==== arp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== ip ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== ip6 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
&lt;br /&gt;
==== stp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== vlan ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== dnat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== snat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== redirect ====&lt;br /&gt;
* nft_payload + nft_meta (pkttype set unicast)&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
&lt;br /&gt;
== Deprecated extensions ==                                                      &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== matches ===                                                                  &lt;br /&gt;
 &lt;br /&gt;
==== physdev ====                                                                &lt;br /&gt;
* br_netfilter aims to be deprecated by nftables.                                                                                &lt;br /&gt;
==== quota ====                                                                  &lt;br /&gt;
* nfacct already provides quota support.  &lt;br /&gt;
==== tos ====&lt;br /&gt;
* deprecated by dscp                                       &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== targets ===                                                                  &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== CLUSTERIP ====                                                              &lt;br /&gt;
* deprecated by cluster match.                                                   &lt;br /&gt;
==== TOS ====                                                                 &lt;br /&gt;
* deprecated by DSCP&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== ULOG ====                                                                   &lt;br /&gt;
* Removed from tree since 3.17.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Counters&amp;diff=981</id>
		<title>Counters</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Counters&amp;diff=981"/>
		<updated>2021-06-10T13:32:13Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* Resetting named counters */ Added workaround to reset anonymous counters&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A counter counts both the total number of packets and the total bytes it has seen since it was last reset. With nftables you need to explicitly specify a counter for each rule you want to count.&lt;br /&gt;
&lt;br /&gt;
= Anonymous counters =&lt;br /&gt;
&lt;br /&gt;
An anonymous counter is local to the single rule in which it appears. The following example uses an anonymous counter to count all tcp traffic routed to the local host:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table ip counter_demo {&lt;br /&gt;
    chain IN {&lt;br /&gt;
        type filter hook input priority filter; policy drop;&lt;br /&gt;
&lt;br /&gt;
        protocol tcp counter&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; that the position of the &#039;&#039;counter&#039;&#039; statement within your rule is significant, because nftables evaluates expressions and statements linearly from left to right. If the above rule were written instead:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
        counter protocol tcp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then &#039;&#039;&#039;every packet&#039;&#039;&#039; routed to your host (not just tcp packets) will update the counter!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Named counters =&lt;br /&gt;
&lt;br /&gt;
== Declaring and using named counters ==&lt;br /&gt;
&lt;br /&gt;
You can also declare named counters, which can be used in multiple rules, e.g.:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table inet named_counter_demo {&lt;br /&gt;
&lt;br /&gt;
    counter cnt_http {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    counter cnt_smtp {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    chain IN {&lt;br /&gt;
        type filter hook input priority filter; policy drop;&lt;br /&gt;
&lt;br /&gt;
        tcp dport   25 counter name cnt_smtp&lt;br /&gt;
        tcp dport   80 counter name cnt_http&lt;br /&gt;
        tcp dport  443 counter name cnt_http&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example defines two counters named &#039;&#039;cnt_http&#039;&#039; and &#039;&#039;cnt_smtp&#039;&#039; and uses them in rules to count http(s) and smtp packets routed to the local host. (This example is contrived to show using a single named counter in multiple rules; the two rules using cnt_http can easily be combined by using an anonymous [[Sets|set]].)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listing / reading named counters ==&lt;br /&gt;
&lt;br /&gt;
=== Listing named counters from nft command line ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;nft list [counter | counters]&#039;&#039; (as per below) returns the current value(s) of the selected counter(s).&lt;br /&gt;
&lt;br /&gt;
* List a particular counter:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft list counter inet named_counter_demo cnt_http&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* List all counters in a particular table:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft list counters table inet named_counter_demo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* List all counters in ruleset:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft list counters&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reading named counters from Python ===&lt;br /&gt;
&lt;br /&gt;
The following partial ruleset (note the absence of a [[Configuring_chains#Adding_base_chains|base chain]]) defines two named counters &#039;&#039;voip1&#039;&#039; and &#039;&#039;voip2&#039;&#039; and uses them to count VoIP traffic to udp/5160 and udp/5161. The commented-out rules show how to do this in simple fashion, while the 2 final rules in the &#039;&#039;FORWARD&#039;&#039; chain do the same thing using the &#039;&#039;voipcounters&#039;&#039; [[Maps|map]]. The approach using the map becomes increasingly advantageous when more ports (map elements) are added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
define ipvoipbox=192.168.0.8&lt;br /&gt;
&lt;br /&gt;
table ip filter {&lt;br /&gt;
    counter voip1 {&lt;br /&gt;
    }&lt;br /&gt;
    counter voip2 {&lt;br /&gt;
    }&lt;br /&gt;
    map voipcounters {&lt;br /&gt;
        type inet_service : counter&lt;br /&gt;
        elements = {&lt;br /&gt;
            5160 : &amp;quot;voip1&amp;quot;, &lt;br /&gt;
            5161 : &amp;quot;voip2&amp;quot; &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    chain FORWARD {&lt;br /&gt;
        #ip saddr $ipvoipbox udp dport 5160 counter name voip1 comment &amp;quot;counting packets for SIP1&amp;quot;&lt;br /&gt;
        #ip daddr $ipvoipbox udp dport 5160 counter name voip1 comment &amp;quot;counting packets for SIP1&amp;quot;&lt;br /&gt;
        #ip saddr $ipvoipbox udp sport 5161 counter name voip2 comment &amp;quot;counting packets for SIP2&amp;quot;&lt;br /&gt;
        #ip daddr $ipvoipbox udp dport 5161 counter name voip2 comment &amp;quot;counting packets for SIP2&amp;quot;&lt;br /&gt;
        ip saddr $ipvoipbox counter name udp sport map @voipcounters&lt;br /&gt;
        ip daddr $ipvoipbox counter name udp dport map @voipcounters&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can read current counter values from [[Scripting#Using_nftables_from_Python|Python using the libnftables library]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
from nftables import Nftables&lt;br /&gt;
from nftables import json&lt;br /&gt;
&lt;br /&gt;
def getCounter(countername, family=&#039;ip&#039;):&lt;br /&gt;
    nft = Nftables()&lt;br /&gt;
    nft.set_json_output(True)&lt;br /&gt;
    _, output, _ = nft.cmd(f&amp;quot;list counter {family} filter {countername}&amp;quot;)&lt;br /&gt;
    j = json.loads(output)&lt;br /&gt;
    return j[&#039;nftables&#039;][1][&amp;quot;counter&amp;quot;][&amp;quot;bytes&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
print(getCounter(&#039;voip1&#039;), &#039;bytes&#039;)&lt;br /&gt;
print(getCounter(&#039;voip2&#039;), &#039;bytes&#039;) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Resetting named counters ==&lt;br /&gt;
&lt;br /&gt;
Resetting a counter dumps its current packet and byte counts and then resets the counts to their initial values.&lt;br /&gt;
&lt;br /&gt;
* Reset a particular counter:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft reset counter inet named_counter_demo cnt_http&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Reset all counters in a particular table:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft reset counters table inet named_counter_demo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Reset all counters in ruleset:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft reset counters&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Resetting counters does not reset anonymous counters, see [https://bugzilla.netfilter.org/show_bug.cgi?id=1401 bug #1401].&lt;br /&gt;
A workaround to achieve that is to restore the current ruleset with all stateful information dropped:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% (echo &amp;quot;flush ruleset&amp;quot;; nft --stateless list ruleset) | nft -f -&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Obviously, this drops all state so might have undesired side-effects, like, e.g. resetting quotas.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Quick_reference-nftables_in_10_minutes&amp;diff=975</id>
		<title>Quick reference-nftables in 10 minutes</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Quick_reference-nftables_in_10_minutes&amp;diff=975"/>
		<updated>2021-05-21T14:23:30Z</updated>

		<summary type="html">&lt;p&gt;Phil: /* Sctp */ added &amp;#039;sctp chunk&amp;#039; docs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Find below some basic concepts to know before using nftables.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;table&#039;&#039;&#039; refers to a container of [[Configuring chains|chains]] with no specific semantics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;chain&#039;&#039;&#039; within a [[Configuring tables|table]] refers to a container of [[Simple rule management|rules]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;rule&#039;&#039;&#039; refers to an action to be configured within a &#039;&#039;chain&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= nft command line =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;nft&#039;&#039; is the command line tool in order to interact with nftables at userspace.&lt;br /&gt;
&lt;br /&gt;
== Tables ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;family&#039;&#039;&#039; refers to a one of the following table types: &#039;&#039;ip&#039;&#039;, &#039;&#039;arp&#039;&#039;, &#039;&#039;ip6&#039;&#039;, &#039;&#039;bridge&#039;&#039;, &#039;&#039;inet&#039;&#039;, &#039;&#039;netdev&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list tables [&amp;lt;family&amp;gt;]&lt;br /&gt;
% nft list table [&amp;lt;family&amp;gt;] &amp;lt;name&amp;gt; [-n] [-a]&lt;br /&gt;
% nft (add | delete | flush) table [&amp;lt;family&amp;gt;] &amp;lt;name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The argument &#039;&#039;-n&#039;&#039; shows the addresses and other information that uses names in numeric format. The &#039;&#039;-a&#039;&#039; argument is used to display the &#039;&#039;handle&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Chains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;type&#039;&#039;&#039; refers to the kind of chain to be created. Possible types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;filter&#039;&#039;: Supported by &#039;&#039;arp&#039;&#039;, &#039;&#039;bridge&#039;&#039;, &#039;&#039;ip&#039;&#039;, &#039;&#039;ip6&#039;&#039; and &#039;&#039;inet&#039;&#039; table families.&lt;br /&gt;
* &#039;&#039;route&#039;&#039;: Mark packets (like mangle for the &#039;&#039;output&#039;&#039; hook, for other hooks use the type &#039;&#039;filter&#039;&#039; instead), supported by &#039;&#039;ip&#039;&#039; and &#039;&#039;ip6&#039;&#039;.&lt;br /&gt;
* &#039;&#039;nat&#039;&#039;: In order to perform Network Address Translation, supported by &#039;&#039;ip&#039;&#039; and &#039;&#039;ip6&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;hook&#039;&#039;&#039; refers to an specific stage of the packet while it&#039;s being processed through the kernel. More info in [[Netfilter_hooks|Netfilter hooks]].&lt;br /&gt;
&lt;br /&gt;
* The hooks for &#039;&#039;ip&#039;&#039;, &#039;&#039;ip6&#039;&#039; and &#039;&#039;inet&#039;&#039; families are: &#039;&#039;prerouting&#039;&#039;, &#039;&#039;input&#039;&#039;, &#039;&#039;forward&#039;&#039;, &#039;&#039;output&#039;&#039;, &#039;&#039;postrouting&#039;&#039;.&lt;br /&gt;
* The hooks for &#039;&#039;arp&#039;&#039; family are: &#039;&#039; input&#039;&#039;, &#039;&#039;output&#039;&#039;.&lt;br /&gt;
* The &#039;&#039;bridge&#039;&#039; family handles ethernet packets traversing bridge devices.&lt;br /&gt;
* The hook for &#039;&#039;netdev&#039;&#039; is: &#039;&#039;ingress&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;priority&#039;&#039;&#039; refers to a number used to order the chains or to set them between some Netfilter operations. Possible values are: &#039;&#039;NF_IP_PRI_CONNTRACK_DEFRAG (-400)&#039;&#039;, &#039;&#039;NF_IP_PRI_RAW (-300)&#039;&#039;, &#039;&#039;NF_IP_PRI_SELINUX_FIRST (-225)&#039;&#039;, &#039;&#039;NF_IP_PRI_CONNTRACK (-200)&#039;&#039;, &#039;&#039;NF_IP_PRI_MANGLE (-150)&#039;&#039;, &#039;&#039;NF_IP_PRI_NAT_DST (-100)&#039;&#039;, &#039;&#039;NF_IP_PRI_FILTER (0)&#039;&#039;, &#039;&#039;NF_IP_PRI_SECURITY (50)&#039;&#039;, &#039;&#039;NF_IP_PRI_NAT_SRC (100)&#039;&#039;, &#039;&#039;NF_IP_PRI_SELINUX_LAST (225)&#039;&#039;, &#039;&#039;NF_IP_PRI_CONNTRACK_HELPER (300)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;policy&#039;&#039;&#039; is the default verdict statement to control the flow in the chain. Possible values are: &#039;&#039;accept&#039;&#039;, &#039;&#039;drop&#039;&#039;, &#039;&#039;queue&#039;&#039;, &#039;&#039;continue&#039;&#039;, &#039;&#039;return&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft (add | create) chain [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;name&amp;gt; [ { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; \; [policy &amp;lt;policy&amp;gt; \;] } ]&lt;br /&gt;
% nft (delete | list | flush) chain [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;name&amp;gt;&lt;br /&gt;
% nft rename chain [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;name&amp;gt; &amp;lt;newname&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;handle&#039;&#039;&#039; is an internal number that identifies a certain &#039;&#039;rule&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;position&#039;&#039;&#039; is an internal number that is used to insert a &#039;&#039;rule&#039;&#039; before a certain &#039;&#039;handle&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; &amp;lt;matches&amp;gt; &amp;lt;statements&amp;gt;&lt;br /&gt;
% nft insert rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; [position &amp;lt;position&amp;gt;] &amp;lt;matches&amp;gt; &amp;lt;statements&amp;gt;&lt;br /&gt;
% nft replace rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; [handle &amp;lt;handle&amp;gt;] &amp;lt;matches&amp;gt; &amp;lt;statements&amp;gt;&lt;br /&gt;
% nft delete rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; [handle &amp;lt;handle&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Matches ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;matches&#039;&#039;&#039; are clues used to access to certain packet information and create filters according to them.&lt;br /&gt;
&lt;br /&gt;
==== Ip ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ip match&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;dscp &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip dscp cs1&lt;br /&gt;
ip dscp != cs1&lt;br /&gt;
ip dscp 0x38&lt;br /&gt;
ip dscp != 0x20&lt;br /&gt;
ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, &lt;br /&gt;
af22, af23, af31, af32, af33, af41, af42, af43, ef}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Total packet length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip length 232&lt;br /&gt;
ip length != 233&lt;br /&gt;
ip length 333-435&lt;br /&gt;
ip length != 333-453&lt;br /&gt;
ip length { 333, 553, 673, 838}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;id&amp;gt;&#039;&#039;&lt;br /&gt;
| IP ID&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip id 22&lt;br /&gt;
ip id != 233&lt;br /&gt;
ip id 33-45&lt;br /&gt;
ip id != 33-45&lt;br /&gt;
ip id { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;frag-off &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Fragmentation offset&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip frag-off 222&lt;br /&gt;
ip frag-off != 233&lt;br /&gt;
ip frag-off 33-45&lt;br /&gt;
ip frag-off != 33-45&lt;br /&gt;
ip frag-off { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;ttl &amp;lt;ttl&amp;gt;&#039;&#039;&lt;br /&gt;
| Time to live&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip ttl 0&lt;br /&gt;
ip ttl 233&lt;br /&gt;
ip ttl 33-55&lt;br /&gt;
ip ttl != 45-50&lt;br /&gt;
ip ttl { 43, 53, 45 }&lt;br /&gt;
ip ttl { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;protocol &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| Upper layer protocol&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip protocol tcp&lt;br /&gt;
ip protocol 6&lt;br /&gt;
ip protocol != tcp&lt;br /&gt;
ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip checksum 13172&lt;br /&gt;
ip checksum 22&lt;br /&gt;
ip checksum != 233&lt;br /&gt;
ip checksum 33-45&lt;br /&gt;
ip checksum != 33-45&lt;br /&gt;
ip checksum { 33, 55, 67, 88 }&lt;br /&gt;
ip checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;saddr &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip saddr 192.168.2.0/24&lt;br /&gt;
ip saddr != 192.168.2.0/24&lt;br /&gt;
ip saddr 192.168.3.1 ip daddr 192.168.3.100&lt;br /&gt;
ip saddr != 1.1.1.1&lt;br /&gt;
ip saddr 1.1.1.1&lt;br /&gt;
ip saddr &amp;amp; 0xff == 1&lt;br /&gt;
ip saddr &amp;amp; 0.0.0.255 &amp;lt; 0.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;daddr &amp;lt;ip destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip daddr 192.168.0.1&lt;br /&gt;
ip daddr != 192.168.0.1&lt;br /&gt;
ip daddr 192.168.0.1-192.168.0.250&lt;br /&gt;
ip daddr 10.0.0.0-10.255.255.255&lt;br /&gt;
ip daddr 172.16.0.0-172.31.255.255&lt;br /&gt;
ip daddr 192.168.3.1-192.168.4.250&lt;br /&gt;
ip daddr != 192.168.0.1-192.168.0.250&lt;br /&gt;
ip daddr { 192.168.0.1-192.168.0.250 }&lt;br /&gt;
ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;version &amp;lt;version&amp;gt;&#039;&#039;&lt;br /&gt;
| Ip Header version&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip version 4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;header length&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip hdrlength 0&lt;br /&gt;
ip hdrlength 15&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Ip6 ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ip6 match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dscp &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 dscp cs1&lt;br /&gt;
ip6 dscp != cs1&lt;br /&gt;
ip6 dscp 0x38&lt;br /&gt;
ip6 dscp != 0x20&lt;br /&gt;
ip6 dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;flowlabel &amp;lt;label&amp;gt;&#039;&#039;&lt;br /&gt;
| Flow label&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 flowlabel 22&lt;br /&gt;
ip6 flowlabel != 233&lt;br /&gt;
ip6 flowlabel { 33, 55, 67, 88 }&lt;br /&gt;
ip6 flowlabel { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Payload length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 length 232&lt;br /&gt;
ip6 length != 233&lt;br /&gt;
ip6 length 333-435&lt;br /&gt;
ip6 length != 333-453&lt;br /&gt;
ip6 length { 333, 553, 673, 838}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;header&amp;gt;&#039;&#039;&lt;br /&gt;
| Next header type (Upper layer protocol number)&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 nexthdr {esp, udp, ah, comp, udplite, tcp, dccp, sctp, icmpv6}&lt;br /&gt;
ip6 nexthdr esp&lt;br /&gt;
ip6 nexthdr != esp&lt;br /&gt;
ip6 nexthdr { 33-44 }&lt;br /&gt;
ip6 nexthdr 33-44&lt;br /&gt;
ip6 nexthdr != 33-44&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hoplimit &amp;lt;hoplimit&amp;gt;&#039;&#039;&lt;br /&gt;
| Hop limit&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 hoplimit 1&lt;br /&gt;
ip6 hoplimit != 233&lt;br /&gt;
ip6 hoplimit 33-45&lt;br /&gt;
ip6 hoplimit != 33-45&lt;br /&gt;
ip6 hoplimit {33, 55, 67, 88}&lt;br /&gt;
ip6 hoplimit {33-55}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;saddr &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source Address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 saddr 1234:1234:1234:1234:1234:1234:1234:1234&lt;br /&gt;
ip6 saddr ::1234:1234:1234:1234:1234:1234:1234&lt;br /&gt;
ip6 saddr ::/64&lt;br /&gt;
ip6 saddr ::1 ip6 daddr ::2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;daddr &amp;lt;ip destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination Address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 daddr 1234:1234:1234:1234:1234:1234:1234:1234&lt;br /&gt;
ip6 daddr != ::1234:1234:1234:1234:1234:1234:1234-1234:1234::1234:1234:1234:1234:1234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;version &amp;lt;version&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header version&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 version 6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Tcp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|tcp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp dport 22&lt;br /&gt;
tcp dport != 33-45&lt;br /&gt;
tcp dport { 33-55 }&lt;br /&gt;
tcp dport {telnet, http, https }&lt;br /&gt;
tcp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
tcp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp sport 22&lt;br /&gt;
tcp sport != 33-45&lt;br /&gt;
tcp sport { 33, 55, 67, 88}&lt;br /&gt;
tcp sport { 33-55}&lt;br /&gt;
tcp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
tcp sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Sequence number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp sequence 22&lt;br /&gt;
tcp sequence != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;ackseq &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Acknowledgement number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp ackseq 22&lt;br /&gt;
tcp ackseq != 33-45&lt;br /&gt;
tcp ackseq { 33, 55, 67, 88 }&lt;br /&gt;
tcp ackseq { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;flags &amp;lt;flags&amp;gt;&#039;&#039;&lt;br /&gt;
| TCP flags&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr}&lt;br /&gt;
tcp flags cwr&lt;br /&gt;
tcp flags != cwr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;window &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Window&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp window 22&lt;br /&gt;
tcp window != 33-45&lt;br /&gt;
tcp window { 33, 55, 67, 88 }&lt;br /&gt;
tcp window { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp checksum 22&lt;br /&gt;
tcp checksum != 33-45&lt;br /&gt;
tcp checksum { 33, 55, 67, 88 }&lt;br /&gt;
tcp checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;urgptr &amp;lt;pointer&amp;gt;&#039;&#039;&lt;br /&gt;
| Urgent pointer&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp urgptr 22&lt;br /&gt;
tcp urgptr != 33-45&lt;br /&gt;
tcp urgptr { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;doff &amp;lt;offset&amp;gt;&#039;&#039;&lt;br /&gt;
| Data offset&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp doff 8&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Udp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|udp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp dport 22&lt;br /&gt;
udp dport != 33-45&lt;br /&gt;
udp dport { 33-55 }&lt;br /&gt;
udp dport {telnet, http, https }&lt;br /&gt;
udp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
udp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp sport 22&lt;br /&gt;
udp sport != 33-45&lt;br /&gt;
udp sport { 33, 55, 67, 88}&lt;br /&gt;
udp sport { 33-55}&lt;br /&gt;
udp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
udp sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Total packet length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp length 6666&lt;br /&gt;
udp length != 50-65&lt;br /&gt;
udp length { 50, 65 }&lt;br /&gt;
udp length { 35-50 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| UDP checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp checksum 22&lt;br /&gt;
udp checksum != 33-45&lt;br /&gt;
udp checksum { 33, 55, 67, 88 }&lt;br /&gt;
udp checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Udplite ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|udplite match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udplite dport 22&lt;br /&gt;
udplite dport != 33-45&lt;br /&gt;
udplite dport { 33-55 }&lt;br /&gt;
udplite dport {telnet, http, https }&lt;br /&gt;
udplite dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
udplite dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udplite sport 22&lt;br /&gt;
udplite sport != 33-45&lt;br /&gt;
udplite sport { 33, 55, 67, 88}&lt;br /&gt;
udplite sport { 33-55}&lt;br /&gt;
udplite sport vmap { 25:accept, 28:drop }&lt;br /&gt;
udplite sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| Checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udplite checksum 22&lt;br /&gt;
udplite checksum != 33-45&lt;br /&gt;
udplite checksum { 33, 55, 67, 88 }&lt;br /&gt;
udplite checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Sctp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|sctp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp dport 22&lt;br /&gt;
sctp dport != 33-45&lt;br /&gt;
sctp dport { 33-55 }&lt;br /&gt;
sctp dport {telnet, http, https }&lt;br /&gt;
sctp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
sctp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp sport 22&lt;br /&gt;
sctp sport != 33-45&lt;br /&gt;
sctp sport { 33, 55, 67, 88}&lt;br /&gt;
sctp sport { 33-55}&lt;br /&gt;
sctp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
sctp sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| Checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp checksum 22&lt;br /&gt;
sctp checksum != 33-45&lt;br /&gt;
sctp checksum { 33, 55, 67, 88 }&lt;br /&gt;
sctp checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;vtag &amp;lt;tag&amp;gt;&#039;&#039;&lt;br /&gt;
| Verification tag&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp vtag 22&lt;br /&gt;
sctp vtag != 33-45&lt;br /&gt;
sctp vtag { 33, 55, 67, 88 }&lt;br /&gt;
sctp vtag { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;chunk &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| Existence of a chunk with given type in packet&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp chunk init exists&lt;br /&gt;
sctp chunk error missing&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;chunk &amp;lt;type&amp;gt; &amp;lt;field&amp;gt;&#039;&#039;&lt;br /&gt;
| A chunk&#039;s field value (implies chunk existence)&lt;br /&gt;
|&amp;lt;sourcex lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp chunk init flags 0x1&lt;br /&gt;
sctp chunk data tsn 0x23&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Dccp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|dccp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dccp dport 22&lt;br /&gt;
dccp dport != 33-45&lt;br /&gt;
dccp dport { 33-55 }&lt;br /&gt;
dccp dport {telnet, http, https }&lt;br /&gt;
dccp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
dccp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dccp sport 22&lt;br /&gt;
dccp sport != 33-45&lt;br /&gt;
dccp sport { 33, 55, 67, 88}&lt;br /&gt;
dccp sport { 33-55}&lt;br /&gt;
dccp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
dccp sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| Type of packet&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dccp type {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}&lt;br /&gt;
dccp type request&lt;br /&gt;
dccp type != request&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ah ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ah match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| AH header length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah hdrlength 11-23&lt;br /&gt;
ah hdrlength != 11-23&lt;br /&gt;
ah hdrlength {11, 23, 44 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;reserved &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah reserved 22&lt;br /&gt;
ah reserved != 33-45&lt;br /&gt;
ah reserved {23, 100 }&lt;br /&gt;
ah reserved { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;spi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah spi 111&lt;br /&gt;
ah spi != 111-222&lt;br /&gt;
ah spi {111, 122 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;sequence&amp;gt;&#039;&#039;&lt;br /&gt;
| Sequence Number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah sequence 123&lt;br /&gt;
ah sequence {23, 25, 33}&lt;br /&gt;
ah sequence != 23-33&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Esp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|esp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;spi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
esp spi 111&lt;br /&gt;
esp spi != 111-222&lt;br /&gt;
esp spi {111, 122 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;sequence&amp;gt;&#039;&#039;&lt;br /&gt;
| Sequence Number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
esp sequence 123&lt;br /&gt;
esp sequence {23, 25, 33}&lt;br /&gt;
esp sequence != 23-33&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Comp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|comp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| Next header protocol (Upper layer protocol)&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
comp nexthdr != esp&lt;br /&gt;
comp nexthdr {esp, ah, comp, udp, udplite, tcp, tcp, dccp, sctp}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;flags &amp;lt;flags&amp;gt;&#039;&#039;&lt;br /&gt;
| Flags&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
comp flags 0x0&lt;br /&gt;
comp flags != 0x33-0x45&lt;br /&gt;
comp flags {0x33, 0x55, 0x67, 0x88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cpi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Compression Parameter Index&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
comp cpi 22&lt;br /&gt;
comp cpi != 33-45&lt;br /&gt;
comp cpi {33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Icmp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|icmp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp type {echo-reply, destination-unreachable, source-quench, redirect, echo-request, time-exceeded, parameter-problem, timestamp-request, timestamp-reply, info-request, info-reply, address-mask-request, address-mask-reply, router-advertisement, router-solicitation}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;code &amp;lt;code&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet code&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp code 111&lt;br /&gt;
icmp code != 33-55&lt;br /&gt;
icmp code { 2, 4, 54, 33, 56}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp checksum 12343&lt;br /&gt;
icmp checksum != 11-343&lt;br /&gt;
icmp checksum { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet id&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp id 12343&lt;br /&gt;
icmp id != 11-343&lt;br /&gt;
icmp id { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet sequence&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp sequence 12343&lt;br /&gt;
icmp sequence != 11-343&lt;br /&gt;
icmp sequence { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mtu &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet mtu&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp mtu 12343&lt;br /&gt;
icmp mtu != 11-343&lt;br /&gt;
icmp mtu { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;gateway &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet gateway&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp gateway 12343&lt;br /&gt;
icmp gateway != 11-343&lt;br /&gt;
icmp gateway { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Icmpv6 ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|icmpv6 match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 type {destination-unreachable, packet-too-big, time-exceeded, echo-request, echo-reply, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, nd-redirect, parameter-problem, router-renumbering}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;code &amp;lt;code&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet code&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 code 4&lt;br /&gt;
icmpv6 code 3-66&lt;br /&gt;
icmpv6 code {5, 6, 7}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 checksum 12343&lt;br /&gt;
icmpv6 checksum != 11-343&lt;br /&gt;
icmpv6 checksum { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet id&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 id 12343&lt;br /&gt;
icmpv6 id != 11-343&lt;br /&gt;
icmpv6 id { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet sequence&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 sequence 12343&lt;br /&gt;
icmpv6 sequence != 11-343&lt;br /&gt;
icmpv6 sequence { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mtu &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet mtu&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 mtu 12343&lt;br /&gt;
icmpv6 mtu != 11-343&lt;br /&gt;
icmpv6 mtu { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;max-delay &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet max delay&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 max-delay 33-45&lt;br /&gt;
icmpv6 max-delay != 33-45&lt;br /&gt;
icmpv6 max-delay {33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ether ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ether match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;saddr &amp;lt;mac address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source mac address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ether saddr 00:0f:54:0c:11:04&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ether type vlan&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Dst ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|dst match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dst nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}&lt;br /&gt;
dst nexthdr 22&lt;br /&gt;
dst nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dst hdrlength 22&lt;br /&gt;
dst hdrlength != 33-45&lt;br /&gt;
dst hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Frag ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|frag match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag nexthdr { udplite, comp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp, icmp}&lt;br /&gt;
frag nexthdr 6&lt;br /&gt;
frag nexthdr != 50-51&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;reserved &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag reserved 22&lt;br /&gt;
frag reserved != 33-45&lt;br /&gt;
frag reserved { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;frag-off &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag frag-off 22&lt;br /&gt;
frag frag-off != 33-45&lt;br /&gt;
frag frag-off { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;more-fragments &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag more-fragments 0&lt;br /&gt;
frag more-fragments 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag id 1&lt;br /&gt;
frag id 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Hbh ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|hbh match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
hbh nexthdr { udplite, comp, udp, ah, sctp, esp, dccp, tcp, icmpv6}&lt;br /&gt;
hbh nexthdr 22&lt;br /&gt;
hbh nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
hbh hdrlength 22&lt;br /&gt;
hbh hdrlength != 33-45&lt;br /&gt;
hbh hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mh ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|mh match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }&lt;br /&gt;
mh nexthdr 22&lt;br /&gt;
mh nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh hdrlength 22&lt;br /&gt;
mh hdrlength != 33-45&lt;br /&gt;
mh hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh type {binding-refresh-request, home-test-init, careof-test-init, home-test, careof-test, binding-update, binding-acknowledgement, binding-error, fast-binding-update, fast-binding-acknowledgement, fast-binding-advertisement, experimental-mobility-header, home-agent-switch-message}&lt;br /&gt;
mh type home-agent-switch-message&lt;br /&gt;
mh type != home-agent-switch-message&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;reserved &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh reserved 22&lt;br /&gt;
mh reserved != 33-45&lt;br /&gt;
mh reserved { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh checksum 22&lt;br /&gt;
mh checksum != 33-45&lt;br /&gt;
mh checksum { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Rt ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|rt match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }&lt;br /&gt;
rt nexthdr 22&lt;br /&gt;
rt nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt hdrlength 22&lt;br /&gt;
rt hdrlength != 33-45&lt;br /&gt;
rt hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt type 22&lt;br /&gt;
rt type != 33-45&lt;br /&gt;
rt type { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;seg-left &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt seg-left 22&lt;br /&gt;
rt seg-left != 33-45&lt;br /&gt;
rt seg-left { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Vlan ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|vlan match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Vlan tag ID&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vlan id 4094&lt;br /&gt;
vlan id 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cfi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vlan cfi 0&lt;br /&gt;
vlan cfi 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;pcp &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vlan pcp 7&lt;br /&gt;
vlan pcp 3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|arp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;ptype &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Payload type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp ptype 0x0800&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;htype &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Header type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp htype 1&lt;br /&gt;
arp htype != 33-45&lt;br /&gt;
arp htype { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hlen &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp hlen 1&lt;br /&gt;
arp hlen != 33-45&lt;br /&gt;
arp hlen { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;plen &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Payload length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp plen 1&lt;br /&gt;
arp plen != 33-45&lt;br /&gt;
arp plen { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;operation &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ct ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ct match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;state &amp;lt;state&amp;gt;&#039;&#039;&lt;br /&gt;
| State of the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct state { new, established, related, untracked }&lt;br /&gt;
ct state != related&lt;br /&gt;
ct state established&lt;br /&gt;
ct state 8&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;direction &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Direction of the packet relative to the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct direction original&lt;br /&gt;
ct direction != original&lt;br /&gt;
ct direction {reply, original}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;status &amp;lt;status&amp;gt;&#039;&#039;&lt;br /&gt;
| Status of the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct status expected&lt;br /&gt;
(ct status &amp;amp; expected) != expected&lt;br /&gt;
ct status {expected,seen-reply,assured,confirmed,snat,dnat,dying}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mark [set] &amp;lt;mark&amp;gt;&#039;&#039;&lt;br /&gt;
| Mark of the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct mark 0&lt;br /&gt;
ct mark or 0x23 == 0x11&lt;br /&gt;
ct mark or 0x3 != 0x1&lt;br /&gt;
ct mark and 0x23 == 0x11&lt;br /&gt;
ct mark and 0x3 != 0x1&lt;br /&gt;
ct mark xor 0x23 == 0x11&lt;br /&gt;
ct mark xor 0x3 != 0x1&lt;br /&gt;
ct mark 0x00000032&lt;br /&gt;
ct mark != 0x00000032&lt;br /&gt;
ct mark 0x00000032-0x00000045&lt;br /&gt;
ct mark != 0x00000032-0x00000045&lt;br /&gt;
ct mark {0x32, 0x2222, 0x42de3}&lt;br /&gt;
ct mark {0x32-0x2222, 0x4444-0x42de3}&lt;br /&gt;
ct mark set 0x11 xor 0x1331&lt;br /&gt;
ct mark set 0x11333 and 0x11&lt;br /&gt;
ct mark set 0x12 or 0x11&lt;br /&gt;
ct mark set 0x11&lt;br /&gt;
ct mark set mark&lt;br /&gt;
ct mark set mark map { 1 : 10, 2 : 20, 3 : 30 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;expiration &amp;lt;time&amp;gt;&#039;&#039;&lt;br /&gt;
| Connection expiration time&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct expiration 30&lt;br /&gt;
ct expiration 30s&lt;br /&gt;
ct expiration != 233&lt;br /&gt;
ct expiration != 3m53s&lt;br /&gt;
ct expiration 33-45&lt;br /&gt;
ct expiration 33s-45s&lt;br /&gt;
ct expiration != 33-45&lt;br /&gt;
ct expiration != 33s-45s&lt;br /&gt;
ct expiration {33, 55, 67, 88}&lt;br /&gt;
ct expiration { 1m7s, 33s, 55s, 1m28s}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;helper &amp;quot;&amp;lt;helper&amp;gt;&amp;quot;&#039;&#039;&lt;br /&gt;
| Helper associated with the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct helper &amp;quot;ftp&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] bytes &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original bytes &amp;gt; 100000&lt;br /&gt;
ct bytes &amp;gt; 100000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] packets &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct reply packets &amp;lt; 100&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] ip saddr &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original ip saddr 192.168.0.1&lt;br /&gt;
ct reply ip saddr 192.168.0.1&lt;br /&gt;
ct original ip saddr 192.168.1.0/24&lt;br /&gt;
ct reply ip saddr 192.168.1.0/24&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] ip daddr &amp;lt;ip destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original ip daddr 192.168.0.1&lt;br /&gt;
ct reply ip daddr 192.168.0.1&lt;br /&gt;
ct original ip daddr 192.168.1.0/24&lt;br /&gt;
ct reply ip daddr 192.168.1.0/24&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] l3proto &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original l3proto ipv4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] protocol &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original protocol 6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] proto-dst &amp;lt;port&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original proto-dst 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] proto-src &amp;lt;port&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct reply proto-src 53&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Meta ====&lt;br /&gt;
&lt;br /&gt;
[[Matching packet metainformation|&#039;&#039;meta&#039;&#039;]] matches packet by metainformation.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|meta match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iifname &amp;lt;input interface name&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface name&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iifname &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta iifname != &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta iifname {&amp;quot;eth0&amp;quot;, &amp;quot;lo&amp;quot;}&lt;br /&gt;
meta iifname &amp;quot;eth*&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oifname &amp;lt;output interface name&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface name&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oifname &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta oifname != &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta oifname {&amp;quot;eth0&amp;quot;, &amp;quot;lo&amp;quot;}&lt;br /&gt;
meta oifname &amp;quot;eth*&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iif &amp;lt;input interface index&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface index&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iif eth0&lt;br /&gt;
meta iif != eth0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oif &amp;lt;output interface index&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface index&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oif lo&lt;br /&gt;
meta oif != lo&lt;br /&gt;
meta oif {eth0, lo}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iiftype &amp;lt;input interface type&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}&lt;br /&gt;
meta iiftype != ether&lt;br /&gt;
meta iiftype ether&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oiftype &amp;lt;output interface type&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface hardware type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}&lt;br /&gt;
meta oiftype != ether&lt;br /&gt;
meta oiftype ether&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Length of the packet in bytes&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta length 1000&lt;br /&gt;
meta length != 1000&lt;br /&gt;
meta length &amp;gt; 1000&lt;br /&gt;
meta length 33-45&lt;br /&gt;
meta length != 33-45&lt;br /&gt;
meta length { 33, 55, 67, 88 }&lt;br /&gt;
meta length { 33-55, 67-88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;protocol &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| ethertype protocol&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta protocol ip&lt;br /&gt;
meta protocol != ip&lt;br /&gt;
meta protocol { ip, arp, ip6, vlan }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nfproto &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta nfproto ipv4&lt;br /&gt;
meta nfproto != ipv6&lt;br /&gt;
meta nfproto { ipv4, ipv6 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;l4proto &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta l4proto 22&lt;br /&gt;
meta l4proto != 233&lt;br /&gt;
meta l4proto 33-45&lt;br /&gt;
meta l4proto { 33, 55, 67, 88 }&lt;br /&gt;
meta l4proto { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mark [set] &amp;lt;mark&amp;gt;&#039;&#039;&lt;br /&gt;
| Packet mark&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta mark 0x4&lt;br /&gt;
meta mark 0x00000032&lt;br /&gt;
meta mark and 0x03 == 0x01&lt;br /&gt;
meta mark and 0x03 != 0x01&lt;br /&gt;
meta mark != 0x10&lt;br /&gt;
meta mark or 0x03 == 0x01&lt;br /&gt;
meta mark or 0x03 != 0x01&lt;br /&gt;
meta mark xor 0x03 == 0x01&lt;br /&gt;
meta mark xor 0x03 != 0x01&lt;br /&gt;
meta mark set 0xffffffc8 xor 0x16&lt;br /&gt;
meta mark set 0x16 and 0x16&lt;br /&gt;
meta mark set 0xffffffe9 or 0x16&lt;br /&gt;
meta mark set 0xffffffde and 0x16&lt;br /&gt;
meta mark set 0x32 or 0xfffff&lt;br /&gt;
meta mark set 0xfffe xor 0x16&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;priority [set] &amp;lt;priority&amp;gt;&#039;&#039;&lt;br /&gt;
| tc class id&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta priority none&lt;br /&gt;
meta priority 0x1:0x1&lt;br /&gt;
meta priority 0x1:0xffff&lt;br /&gt;
meta priority 0xffff:0xffff&lt;br /&gt;
meta priority set 0x1:0x1&lt;br /&gt;
meta priority set 0x1:0xffff&lt;br /&gt;
meta priority set 0xffff:0xffff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;skuid &amp;lt;user id&amp;gt;&#039;&#039;&lt;br /&gt;
| UID associated with originating socket&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta skuid {bin, root, daemon}&lt;br /&gt;
meta skuid root&lt;br /&gt;
meta skuid != root&lt;br /&gt;
meta skuid lt 3000&lt;br /&gt;
meta skuid gt 3000&lt;br /&gt;
meta skuid eq 3000&lt;br /&gt;
meta skuid 3001-3005&lt;br /&gt;
meta skuid != 2001-2005&lt;br /&gt;
meta skuid { 2001-2005 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;skgid &amp;lt;group id&amp;gt;&#039;&#039;&lt;br /&gt;
| GID associated with originating socket&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta skgid {bin, root, daemon}&lt;br /&gt;
meta skgid root&lt;br /&gt;
meta skgid != root&lt;br /&gt;
meta skgid lt 3000&lt;br /&gt;
meta skgid gt 3000&lt;br /&gt;
meta skgid eq 3000&lt;br /&gt;
meta skgid 3001-3005&lt;br /&gt;
meta skgid != 2001-2005&lt;br /&gt;
meta skgid { 2001-2005 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;rtclassid &amp;lt;class&amp;gt;&#039;&#039;&lt;br /&gt;
| Routing realm&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta rtclassid cosmos&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;pkttype &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| Packet type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta pkttype broadcast&lt;br /&gt;
meta pkttype != broadcast&lt;br /&gt;
meta pkttype { broadcast, unicast, multicast}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cpu &amp;lt;cpu index&amp;gt;&#039;&#039;&lt;br /&gt;
| CPU ID&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta cpu 1&lt;br /&gt;
meta cpu != 1&lt;br /&gt;
meta cpu 1-3&lt;br /&gt;
meta cpu != 1-2&lt;br /&gt;
meta cpu { 2,3 }&lt;br /&gt;
meta cpu { 2-3, 5-7 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iifgroup &amp;lt;input group&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface group&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iifgroup 0&lt;br /&gt;
meta iifgroup != 0&lt;br /&gt;
meta iifgroup default&lt;br /&gt;
meta iifgroup != default&lt;br /&gt;
meta iifgroup {default}&lt;br /&gt;
meta iifgroup { 11,33 }&lt;br /&gt;
meta iifgroup {11-33}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oifgroup &amp;lt;group&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface group&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oifgroup 0&lt;br /&gt;
meta oifgroup != 0&lt;br /&gt;
meta oifgroup default&lt;br /&gt;
meta oifgroup != default&lt;br /&gt;
meta oifgroup {default}&lt;br /&gt;
meta oifgroup { 11,33 }&lt;br /&gt;
meta oifgroup {11-33}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cgroup &amp;lt;group&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta cgroup 1048577&lt;br /&gt;
meta cgroup != 1048577&lt;br /&gt;
meta cgroup { 1048577, 1048578 }&lt;br /&gt;
meta cgroup 1048577-1048578&lt;br /&gt;
meta cgroup != 1048577-1048578&lt;br /&gt;
meta cgroup {1048577-1048578}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Statements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;statement&#039;&#039;&#039; is the action performed when the packet match the rule. It could be &#039;&#039;terminal&#039;&#039; and &#039;&#039;non-terminal&#039;&#039;. In a certain rule we can consider several non-terminal statements but only a single terminal statement.&lt;br /&gt;
&lt;br /&gt;
==== Verdict statements ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;verdict statement&#039;&#039;&#039; alters control flow in the ruleset and issues policy decisions for packets. The valid verdict statements are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;accept&#039;&#039;: Accept the packet and stop the remain rules evaluation.&lt;br /&gt;
* &#039;&#039;drop&#039;&#039;: Drop the packet and stop the remain rules evaluation.&lt;br /&gt;
* &#039;&#039;queue&#039;&#039;: Queue the packet to userspace and stop the remain rules evaluation.&lt;br /&gt;
* &#039;&#039;continue&#039;&#039;: Continue the ruleset evaluation with the next rule.&lt;br /&gt;
* &#039;&#039;return&#039;&#039;: Return from the current chain and continue at the next rule of the last chain. In a base chain it is equivalent to accept&lt;br /&gt;
* &#039;&#039;jump &amp;lt;chain&amp;gt;&#039;&#039;: Continue at the first rule of &amp;lt;chain&amp;gt;. It will continue at the next rule after a return statement is issued&lt;br /&gt;
* &#039;&#039;goto &amp;lt;chain&amp;gt;&#039;&#039;: Similar to jump, but after the new chain the evaluation will continue at the last chain instead of the one containing the goto statement&lt;br /&gt;
&lt;br /&gt;
==== Log ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|log statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;level [over] &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt; [burst &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt;]&#039;&#039;&lt;br /&gt;
| Log level&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
log&lt;br /&gt;
log level emerg&lt;br /&gt;
log level alert&lt;br /&gt;
log level crit&lt;br /&gt;
log level err&lt;br /&gt;
log level warn&lt;br /&gt;
log level notice&lt;br /&gt;
log level info&lt;br /&gt;
log level debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;group &amp;lt;value&amp;gt; [queue-threshold &amp;lt;value&amp;gt;] [snaplen &amp;lt;value&amp;gt;] [prefix &amp;quot;&amp;lt;prefix&amp;gt;&amp;quot;]&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
log prefix aaaaa-aaaaaa group 2 snaplen 33&lt;br /&gt;
log group 2 queue-threshold 2&lt;br /&gt;
log group 2 snaplen 33&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Reject ====&lt;br /&gt;
&lt;br /&gt;
The default &#039;&#039;&#039;reject&#039;&#039;&#039; will be the ICMP type &#039;&#039;&#039;port-unreachable&#039;&#039;&#039;. The &#039;&#039;&#039;icmpx&#039;&#039;&#039; is only used for inet family support.&lt;br /&gt;
&lt;br /&gt;
More information on the [[Rejecting_traffic]] page.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|reject statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;with &amp;lt;protocol&amp;gt; type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
reject&lt;br /&gt;
reject with icmp type host-unreachable&lt;br /&gt;
reject with icmp type net-unreachable&lt;br /&gt;
reject with icmp type prot-unreachable&lt;br /&gt;
reject with icmp type port-unreachable&lt;br /&gt;
reject with icmp type net-prohibited&lt;br /&gt;
reject with icmp type host-prohibited&lt;br /&gt;
reject with icmp type admin-prohibited&lt;br /&gt;
reject with icmpv6 type no-route&lt;br /&gt;
reject with icmpv6 type admin-prohibited&lt;br /&gt;
reject with icmpv6 type addr-unreachable&lt;br /&gt;
reject with icmpv6 type port-unreachable&lt;br /&gt;
reject with icmpx type host-unreachable&lt;br /&gt;
reject with icmpx type no-route&lt;br /&gt;
reject with icmpx type admin-prohibited&lt;br /&gt;
reject with icmpx type port-unreachable&lt;br /&gt;
ip protocol tcp reject with tcp reset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Counter ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|counter statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;packets &amp;lt;packets&amp;gt; bytes &amp;lt;bytes&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
counter&lt;br /&gt;
counter packets 0 bytes 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Limit ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|limit statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;rate [over] &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt; [burst &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt;]&#039;&#039;&lt;br /&gt;
| Rate limit&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
limit rate 400/minute&lt;br /&gt;
limit rate 400/hour&lt;br /&gt;
limit rate over 40/day&lt;br /&gt;
limit rate over 400/week&lt;br /&gt;
limit rate over 1023/second burst 10 packets&lt;br /&gt;
limit rate 1025 kbytes/second&lt;br /&gt;
limit rate 1023000 mbytes/second&lt;br /&gt;
limit rate 1025 bytes/second burst 512 bytes&lt;br /&gt;
limit rate 1025 kbytes/second burst 1023 kbytes&lt;br /&gt;
limit rate 1025 mbytes/second burst 1025 kbytes&lt;br /&gt;
limit rate 1025000 mbytes/second burst 1023 mbytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Nat ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|nat statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dnat to &amp;lt;destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination address translation&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dnat to 192.168.3.2&lt;br /&gt;
dnat to ct mark map { 0x00000014 : 1.2.3.4}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;snat to &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source address translation&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
snat to 192.168.3.2&lt;br /&gt;
snat to 2001:838:35f:1::-2001:838:35f:2:::100&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;masquerade [&amp;lt;type&amp;gt;] [to :&amp;lt;port&amp;gt;]&#039;&#039;&lt;br /&gt;
| Masquerade&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
masquerade&lt;br /&gt;
masquerade persistent,fully-random,random&lt;br /&gt;
masquerade to :1024&lt;br /&gt;
masquerade to :1024-2048&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Queue ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|queue statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;num &amp;lt;value&amp;gt; &amp;lt;scheduler&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
queue&lt;br /&gt;
queue num 2&lt;br /&gt;
queue num 2-3&lt;br /&gt;
queue num 4-5 fanout bypass&lt;br /&gt;
queue num 4-5 fanout&lt;br /&gt;
queue num 4-5 bypass&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Extras ==&lt;br /&gt;
&lt;br /&gt;
=== Export Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft export (xml | json)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Events ===&lt;br /&gt;
&lt;br /&gt;
Monitor events from Netlink creating filters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft monitor [new | destroy] [tables | chains | sets | rules | elements] [xml | json]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Nft scripting =&lt;br /&gt;
&lt;br /&gt;
== List ruleset ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list ruleset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Flush ruleset ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush ruleset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Load ruleset ==&lt;br /&gt;
&lt;br /&gt;
Create a command batch file and load it with the nft interpreter,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% echo &amp;quot;flush ruleset&amp;quot; &amp;gt; /etc/nftables.rules&lt;br /&gt;
% echo &amp;quot;add table filter&amp;quot; &amp;gt;&amp;gt; /etc/nftables.rules&lt;br /&gt;
% echo &amp;quot;add chain filter input&amp;quot; &amp;gt;&amp;gt; /etc/nftables.rules&lt;br /&gt;
% echo &amp;quot;add rule filter input meta iifname lo accept&amp;quot; &amp;gt;&amp;gt; /etc/nftables.rules&lt;br /&gt;
% nft -f /etc/nftables.rules&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or create an executable nft script file,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% cat &amp;lt;&amp;lt; EOF &amp;gt; /etc/nftables.rules&lt;br /&gt;
&amp;gt; #!/usr/local/sbin/nft -f&lt;br /&gt;
&amp;gt; flush ruleset&lt;br /&gt;
&amp;gt; add table filter&lt;br /&gt;
&amp;gt; add chain filter input&lt;br /&gt;
&amp;gt; add rule filter input meta iifname lo accept&lt;br /&gt;
&amp;gt; EOF&lt;br /&gt;
% chmod u+x /etc/nftables.rules&lt;br /&gt;
% /etc/nftables.rules&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or create an executable nft script file from an already created ruleset,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list ruleset &amp;gt; /etc/nftables.rules&lt;br /&gt;
% nft flush ruleset&lt;br /&gt;
% nft -f /etc/nftables.rules&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
== Simple IP/IPv6 Firewall ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
flush ruleset&lt;br /&gt;
&lt;br /&gt;
table firewall {&lt;br /&gt;
  chain incoming {&lt;br /&gt;
    type filter hook input priority 0; policy drop;&lt;br /&gt;
&lt;br /&gt;
    # established/related connections&lt;br /&gt;
    ct state established,related accept&lt;br /&gt;
&lt;br /&gt;
    # loopback interface&lt;br /&gt;
    iifname lo accept&lt;br /&gt;
&lt;br /&gt;
    # icmp&lt;br /&gt;
    icmp type echo-request accept&lt;br /&gt;
&lt;br /&gt;
    # open tcp ports: sshd (22), httpd (80)&lt;br /&gt;
    tcp dport {ssh, http} accept&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
table ip6 firewall {&lt;br /&gt;
  chain incoming {&lt;br /&gt;
    type filter hook input priority 0; policy drop;&lt;br /&gt;
&lt;br /&gt;
    # established/related connections&lt;br /&gt;
    ct state established,related accept&lt;br /&gt;
&lt;br /&gt;
    # invalid connections&lt;br /&gt;
    ct state invalid drop&lt;br /&gt;
&lt;br /&gt;
    # loopback interface&lt;br /&gt;
    iifname lo accept&lt;br /&gt;
&lt;br /&gt;
    # icmp&lt;br /&gt;
    # routers may also want: mld-listener-query, nd-router-solicit&lt;br /&gt;
    icmpv6 type {echo-request,nd-neighbor-solicit} accept&lt;br /&gt;
&lt;br /&gt;
    # open tcp ports: sshd (22), httpd (80)&lt;br /&gt;
    tcp dport {ssh, http} accept&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=974</id>
		<title>Supported features compared to xtables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Supported_features_compared_to_xtables&amp;diff=974"/>
		<updated>2021-05-21T14:15:28Z</updated>

		<summary type="html">&lt;p&gt;Phil: chunk-types match is supported now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Last update: Aug/2018&lt;br /&gt;
                                                                                 &lt;br /&gt;
This page tracks the list of supported and unsupported extensions with comments and suggestions.&lt;br /&gt;
                                                                                 &lt;br /&gt;
== Unsupported extensions ==                                                     &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== matches: xt ===                                                              &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== bpf ====                                                                    &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== cluster ====                                                                &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== rateest ====                                                                &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== string ====                                                                 &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== u32 ====                                                                    &lt;br /&gt;
* raw expressions?                                                               &lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===                                                              &lt;br /&gt;
                                                         &lt;br /&gt;
==== CHECKSUM ====                                                               &lt;br /&gt;
* add nft_payload.&lt;br /&gt;
* To the day, the only use case for this was DHCP clients not working with partial checksums. That should be fixed nowadays.&lt;br /&gt;
* See https://lwn.net/Articles/396466/ and https://www.spinics.net/lists/kvm/msg37660.html&lt;br /&gt;
* See https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/930962 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832090&lt;br /&gt;
&lt;br /&gt;
==== CT ====                                                                     &lt;br /&gt;
* nft_ct_target. Refer to [[Matching_connection_tracking_stateful_metainformation]].                                              &lt;br /&gt;
==== IDLETIMER ====                                                              &lt;br /&gt;
* consider native interface&lt;br /&gt;
==== LED ====                                                                    &lt;br /&gt;
* consider native (need this?)                                                                                                            &lt;br /&gt;
==== RATEEST ====                                                                &lt;br /&gt;
* consider native interface                                                      &lt;br /&gt;
==== TCPOPTSTRIP ====                                                            &lt;br /&gt;
* consider native interface, need to extend nft_exthdr.c&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== TTL ====&lt;br /&gt;
                                                                                 &lt;br /&gt;
=== targets: ipv6 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== NPT ====                                                                    &lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== arpreply ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
&lt;br /&gt;
=== watchers: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== log ====&lt;br /&gt;
* nft_log&lt;br /&gt;
&lt;br /&gt;
==== nflog ====&lt;br /&gt;
* nft_log&lt;br /&gt;
&lt;br /&gt;
=== targets: arp ===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
== Supported extensions ==                                                       &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== matches: xt ===                                                              &lt;br /&gt;
&lt;br /&gt;
==== addrtype ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel. Refer to [[Matching routing information]].&lt;br /&gt;
&lt;br /&gt;
==== cgroup ====&lt;br /&gt;
* nft_meta. Refer to [[Quick_reference-nftables_in_10_minutes#Meta]].&lt;br /&gt;
[Awaits support for cgroup2]                                                                             &lt;br /&gt;
==== comment ====&lt;br /&gt;
* Built-in support via NFTA_RULE_USERDATA, since 3.15 (Pablo Neira). Refer to [[Matching_packet_headers#Matching_UDP.2FTCP_headers_in_the_same_rule|matching UDP/TCP headers in the same rule]].&lt;br /&gt;
&lt;br /&gt;
==== connbytes ====                                                              &lt;br /&gt;
* nft_ct, 4.5 kernel. Refer to [[Meters]].&lt;br /&gt;
==== connlabel ====                                                              &lt;br /&gt;
* nft_meta, since 3.16.&lt;br /&gt;
==== connlimit ====&lt;br /&gt;
* consider native interface. Refer to [[Meters]].&lt;br /&gt;
==== connmark ====&lt;br /&gt;
* nft_meta.&lt;br /&gt;
==== conntrack ====&lt;br /&gt;
* nft_ct.&lt;br /&gt;
==== cpu ====&lt;br /&gt;
* nft_meta, since 3.18.&lt;br /&gt;
==== dccp ====                                                                   &lt;br /&gt;
* nft_payload.    &lt;br /&gt;
[Unsupported option : dccp-option]&lt;br /&gt;
==== devgroup ====                                                               &lt;br /&gt;
* nft_meta, since 3.18.  &lt;br /&gt;
==== dscp ====                                              &lt;br /&gt;
* nft_payload.&lt;br /&gt;
==== ecn ====                                                                    &lt;br /&gt;
* nft_payload.                                                                   &lt;br /&gt;
==== esp ====                                                                    &lt;br /&gt;
* nft_payload.                                                                   &lt;br /&gt;
==== hashlimit ====                                                              &lt;br /&gt;
* meter statement. Refer to [[Meters]].&lt;br /&gt;
==== helper ====                                                                 &lt;br /&gt;
* nft_ct.&lt;br /&gt;
==== ipcomp ====&lt;br /&gt;
* nft_payload.&lt;br /&gt;
[Unsupported option : compres]&lt;br /&gt;
==== iprange ====                                                                &lt;br /&gt;
* nft_payload, through native range support. To emulate iptables --ports you need two rules.                                                   &lt;br /&gt;
==== ipvs ====&lt;br /&gt;
* consider native interface. Refer to [[Load balancing]].&lt;br /&gt;
==== length ====                                                                 &lt;br /&gt;
* nft_meta.                                                                      &lt;br /&gt;
==== limit ====                                                                  &lt;br /&gt;
* nft_limit. Refer to [[Stateful objects]].&lt;br /&gt;
==== mac ====                                                                    &lt;br /&gt;
* nft_payload.                                                                   &lt;br /&gt;
==== mark ====                                                                   &lt;br /&gt;
* nft_meta.                                                                      &lt;br /&gt;
==== multiport ====                                                              &lt;br /&gt;
* nft_payload. &lt;br /&gt;
[Unsupported option : ports]                                                                                         &lt;br /&gt;
==== nfacct ====&lt;br /&gt;
* consider native interface. Refer to [[Stateful objects]].&lt;br /&gt;
==== osf ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== owner ====                                                                  &lt;br /&gt;
* nft_meta. &lt;br /&gt;
[Unsupported option : socket-exists]                                                                     &lt;br /&gt;
==== pkttype ====                                                                &lt;br /&gt;
* nft_meta&lt;br /&gt;
==== policy ====&lt;br /&gt;
* nft_xfrm, since 5.0&lt;br /&gt;
==== recent ====                                                                 &lt;br /&gt;
* consider native interface. Refer to [[Sets]].&lt;br /&gt;
==== sctp ====                                                                   &lt;br /&gt;
* nft_payload&lt;br /&gt;
* nft_exthdr for --chunk-types&lt;br /&gt;
==== socket ====&lt;br /&gt;
* consider native interface&lt;br /&gt;
==== statistic ====&lt;br /&gt;
* nft_numgen. Refer to [[Load balancing]].&lt;br /&gt;
==== set ====&lt;br /&gt;
* Use native nf_tables set infrastructure.                                       &lt;br /&gt;
==== state ====                                                                  &lt;br /&gt;
* nft_ct                                                                         &lt;br /&gt;
==== tcp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
==== tcpmss ====                                                                 &lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
&lt;br /&gt;
==== time ====&lt;br /&gt;
* nft_meta, since 5.4&lt;br /&gt;
&lt;br /&gt;
==== udp ====                                                                 &lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
=== targets: xt ===                                                              &lt;br /&gt;
&lt;br /&gt;
==== AUDIT ====                                                              &lt;br /&gt;
* nft_log, since 4.18.&lt;br /&gt;
==== CLASSIFY ====                                                               &lt;br /&gt;
* nft_meta, since 3.14.    &lt;br /&gt;
==== CONNMARK ====                                                                                                                    &lt;br /&gt;
* nft_ct&lt;br /&gt;
==== CONNSECMARK ====&lt;br /&gt;
* nft_ct, since 4.20&lt;br /&gt;
==== DSCP ====                                                                                                                    &lt;br /&gt;
==== HL ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
==== HMARK ====&lt;br /&gt;
* nft_meta + nft_hash.&lt;br /&gt;
==== MARK ====                                                                   &lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
==== NETMAP ====                                                                 &lt;br /&gt;
* nft_nat, upcoming 5.8              &lt;br /&gt;
==== NFLOG ====                                                                  &lt;br /&gt;
* nft_log, since 3.17.                                             &lt;br /&gt;
==== NFQUEUE ====                                                                &lt;br /&gt;
* nft_queue, since 3.14.&lt;br /&gt;
==== SECMARK ====&lt;br /&gt;
* nft_meta, since 4.20&lt;br /&gt;
&lt;br /&gt;
==== SYNPROXY ====&lt;br /&gt;
* nft_synproxy, since 5.3&lt;br /&gt;
&lt;br /&gt;
==== TEE ====&lt;br /&gt;
* nft_dup, since 4.3.&lt;br /&gt;
==== TPROXY ====&lt;br /&gt;
* nft_tproxy, since 4.19&lt;br /&gt;
&lt;br /&gt;
==== TRACE ====                                                                  &lt;br /&gt;
* nft_meta, since 3.14.&lt;br /&gt;
&lt;br /&gt;
==== TCPMSS ====                                                                 &lt;br /&gt;
* nft_exthdr, since 4.14&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv4 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== ah ====                                                                     &lt;br /&gt;
* nft_payload + nft_cmp&lt;br /&gt;
==== icmp ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
[Unsupported codes: network-unreachable, host-unreachable, protocol-unreachable, port-unreachable, fragmentation-needed, source-route-failed, network-unknown, host-unknown, network-prohibited, host-prohibited, TOS-network-unreachable, TOS-host-unreachable, communication-prohibited, host-precedence-violation, precedence-cutoff, network-redirect, host-redirect, TOS-network-redirect, TOS-host-redirect, ttl-zero-during-transit, ttl-zero-during-reassembly, ip-header-bad and required-option-missing ]&lt;br /&gt;
==== realm ====                                                                  &lt;br /&gt;
* nft_meta, through NFT_META_RTCLASSID. &lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel&lt;br /&gt;
==== ttl ====&lt;br /&gt;
&lt;br /&gt;
=== matches: ipv6 ===                                                            &lt;br /&gt;
            &lt;br /&gt;
==== rp_filter ====&lt;br /&gt;
* nft_fib, starting with 4.10 kernel                                                                    &lt;br /&gt;
==== ah  ====                                                                    &lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
==== eui64 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
==== frag ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
==== hbh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
HBH options are not supported yet.&lt;br /&gt;
[Unsupported option: --hbh-opts]&lt;br /&gt;
==== hl ==== &lt;br /&gt;
* nft_payload.    &lt;br /&gt;
==== icmp6 ====&lt;br /&gt;
* nft_payload + nft_cmp.&lt;br /&gt;
[Unsupported icmpv6 codes: no-route, communication-prohibited, beyond-scope, address-unreachable, port-unreachable, failed-policy, reject-route, ttl-zero-during-transit, ttl-zero-during-reassembly, bad-header, unknown-header-type and unknown-option]&lt;br /&gt;
==== ipv6header ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
==== mh ====&lt;br /&gt;
* nft_exthdr + nft_cmp.&lt;br /&gt;
[Needs bug fixation for option mh-type with range]&lt;br /&gt;
==== rt ====&lt;br /&gt;
* nft_exthdr + nft_cmp&lt;br /&gt;
[Unsupported options: --rt-0-res, --rt-0-addrs, --rt-0-not-strict]&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===&lt;br /&gt;
==== ECN ====                                                                    &lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== DNAT ====    &lt;br /&gt;
* nft_nat, since 3.13.    &lt;br /&gt;
==== LOG ====                                                                    &lt;br /&gt;
* nft_log, since 3.17.  &lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====&lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
==== REDIRECT ====&lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====                                                                 &lt;br /&gt;
* nft_reject_ipv4, since 3.13.                                         &lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.  &lt;br /&gt;
==== SNAT ====                                                            &lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv6 ===&lt;br /&gt;
==== DNAT ====&lt;br /&gt;
* nft_nat, since 3.13.    &lt;br /&gt;
==== LOG ====&lt;br /&gt;
* nft_log, since 3.17.  &lt;br /&gt;
[Unsupported options : log-tcp-sequence, log-tcp-options, log-ip-options, log-uid, log-macdecode]&lt;br /&gt;
==== MASQUERADE ====                                                             &lt;br /&gt;
* nft_masq, since 3.18.&lt;br /&gt;
==== REDIRECT ====                                                               &lt;br /&gt;
* nft_redirect, since 3.19.&lt;br /&gt;
&lt;br /&gt;
==== REJECT ====                                                                                   &lt;br /&gt;
* nft_reject_ipv6, since 3.14.                     &lt;br /&gt;
* nft_reject_inet, since 3.14.&lt;br /&gt;
* nft_reject_bridge, since 3.18.    &lt;br /&gt;
==== SNAT ====                                                                                                                          &lt;br /&gt;
* nft_nat, since 3.13.&lt;br /&gt;
&lt;br /&gt;
=== matches: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== 802.3 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== among ====&lt;br /&gt;
* sets&lt;br /&gt;
&lt;br /&gt;
==== arp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== ip ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== ip6 ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== limit ====&lt;br /&gt;
* nft_limit&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
&lt;br /&gt;
==== pkttype ====&lt;br /&gt;
* nft_meta&lt;br /&gt;
&lt;br /&gt;
==== stp ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== vlan ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== targets: bridge ===&lt;br /&gt;
&lt;br /&gt;
==== dnat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== snat ====&lt;br /&gt;
* nft_payload&lt;br /&gt;
&lt;br /&gt;
==== redirect ====&lt;br /&gt;
* nft_payload + nft_meta (pkttype set unicast)&lt;br /&gt;
&lt;br /&gt;
==== mark ====&lt;br /&gt;
* nft_mark&lt;br /&gt;
&lt;br /&gt;
== Deprecated extensions ==                                                      &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== matches ===                                                                  &lt;br /&gt;
 &lt;br /&gt;
==== physdev ====                                                                &lt;br /&gt;
* br_netfilter aims to be deprecated by nftables.                                                                                &lt;br /&gt;
==== quota ====                                                                  &lt;br /&gt;
* nfacct already provides quota support.  &lt;br /&gt;
==== tos ====&lt;br /&gt;
* deprecated by dscp                                       &lt;br /&gt;
                                                                                 &lt;br /&gt;
=== targets ===                                                                  &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== CLUSTERIP ====                                                              &lt;br /&gt;
* deprecated by cluster match.                                                   &lt;br /&gt;
==== TOS ====                                                                 &lt;br /&gt;
* deprecated by DSCP&lt;br /&gt;
&lt;br /&gt;
=== targets: ipv4 ===                                                            &lt;br /&gt;
                                                                                 &lt;br /&gt;
==== ULOG ====                                                                   &lt;br /&gt;
* Removed from tree since 3.17.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=478</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=478"/>
		<updated>2019-11-27T12:50:41Z</updated>

		<summary type="html">&lt;p&gt;Phil: fixed prerouting priority ** added inet nat support note ** corrected warning about prerouting/postrouting base-chain need in older kernels&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform NAT. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft add chain nat postrouting { type nat hook postrouting priority 100 \; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft add chain nat prerouting { type nat hook prerouting priority \-100 \; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat 192.168.1.120&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in a prerouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking.&lt;br /&gt;
&lt;br /&gt;
This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot.&lt;br /&gt;
If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets.&lt;br /&gt;
&lt;br /&gt;
The example below sets IP/port for each packet (also valid in IPv6):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule ip raw prerouting ip protocol tcp ip daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
% nft add rule ip6 raw prerouting ip6 nexthdr tcp ip6 daddr set fe00::1 tcp dport set 10 notrack&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangle packet header fields | mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Setting_packet_connection_tracking_metainformation&amp;diff=393</id>
		<title>Setting packet connection tracking metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Setting_packet_connection_tracking_metainformation&amp;diff=393"/>
		<updated>2019-04-18T08:46:13Z</updated>

		<summary type="html">&lt;p&gt;Phil: corrected typo &amp;quot;ftp-standar&amp;quot; -&amp;gt; &amp;quot;ftp-standard&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;You can set some bits of the packet conntrack metainformation, apart of [[Matching connection tracking stateful metainformation | matching on it]].&lt;br /&gt;
&lt;br /&gt;
== notrack ==&lt;br /&gt;
&lt;br /&gt;
You can use the &#039;&#039;&#039;notrack&#039;&#039;&#039; support to explicitly skip connection tracking for matching packets.&lt;br /&gt;
&lt;br /&gt;
The example below skips traffic for 80/tcp and 443/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule ip raw prerouting tcp dport { 80, 443 } notrack&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please, note that you should use notrack before the kernel connection tracking is triggered.&lt;br /&gt;
Use a chain with priority -300. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add table raw&lt;br /&gt;
nft add chain raw prerouting { type filter hook prerouting priority -300 \; }&lt;br /&gt;
nft add rule raw prerouting tcp dport 80 notrack&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Support for this was added in linux kernel 4.9 and in nftables v0.7.&lt;br /&gt;
&lt;br /&gt;
== helpers ==&lt;br /&gt;
&lt;br /&gt;
You can assign each packet a conntrack helper.&lt;br /&gt;
&lt;br /&gt;
Instantiate a helper, using a named object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table filter {&lt;br /&gt;
      ct helper sip-5060 {&lt;br /&gt;
             type &amp;quot;sip&amp;quot; protocol udp;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      ct helper ftp-standard {&lt;br /&gt;
             type &amp;quot;ftp&amp;quot; protocol tcp;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      chain c {&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, from the rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
nft add rule filter filter c udp dport 5060 ct helper set &amp;quot;sip-5060&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can of course use a dictionary, one single rule to assign many helpers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
nft add rule x y ct helper set udp dport map { \&lt;br /&gt;
                        69 : &amp;quot;tftp-69&amp;quot;, \&lt;br /&gt;
                        5060 : &amp;quot;sip-5060&amp;quot; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need nftables &amp;gt;= 0.8 and the kernel &amp;gt;= 4.12 to use this feature.&lt;br /&gt;
&lt;br /&gt;
In case of a previous version of nftables, you can can set automatic assignement with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/netfilter/nf_conntrack_helper&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, with the sysctl parameter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
net.netfilter.nf_conntrack_helper = 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=76</id>
		<title>Sets</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=76"/>
		<updated>2016-11-24T11:27:21Z</updated>

		<summary type="html">&lt;p&gt;Phil: Fixed typo: dport 22 -&amp;gt; dport 23&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;nftables&#039;&#039; comes with a built-in generic set infrastructure that allows you to use &#039;&#039;&#039;any&#039;&#039;&#039; supported selector to build sets. This infrastructure makes possible the representation of [[dictionaries]] and [[maps]].&lt;br /&gt;
&lt;br /&gt;
The set elements are internally represented using performance data structures such as hashtables and red-black trees.&lt;br /&gt;
&lt;br /&gt;
= Anonymous sets =&lt;br /&gt;
&lt;br /&gt;
Anonymous sets are those that are:&lt;br /&gt;
&lt;br /&gt;
* Bound to a rule, if the rule is removed, that set is released too.&lt;br /&gt;
* They have no specific name, the kernel internally allocates an identifier.&lt;br /&gt;
* They cannot be updated. So you cannot add and delete elements from it once it is bound to a rule.&lt;br /&gt;
&lt;br /&gt;
The following example shows how to create a simple set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output tcp dport { 22, 23 } counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule above catches all traffic going to TCP ports 22 and 23, in case of matching the counters are updated.&lt;br /&gt;
&lt;br /&gt;
= Named sets =&lt;br /&gt;
&lt;br /&gt;
You can create the named sets with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set filter blackhole { type ipv4_addr\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;blackhole&#039;&#039; is the name of the set in this case. The &#039;&#039;type&#039;&#039; option indicates the data type that this set stores, which is an IPv4 address in the case. Current maximum name length is 16 characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element filter blackhole { 192.168.3.4 }&lt;br /&gt;
% nft add element filter blackhole { 192.168.1.4, 192.168.1.5 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can use it from the rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip input ip saddr @blackhole drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The supported data types currently are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;ipv4_addr&#039;&#039;: IPv4 address&lt;br /&gt;
* &#039;&#039;ipv6_addr&#039;&#039;: IPv6 address.&lt;br /&gt;
* &#039;&#039;ether_addr&#039;&#039;: Ethernet address.&lt;br /&gt;
* &#039;&#039;inet_proto&#039;&#039;: Inet protocol type.&lt;br /&gt;
* &#039;&#039;inet_service&#039;&#039;: Internet service (read tcp port for example)&lt;br /&gt;
* &#039;&#039;mark&#039;&#039;: Mark type.&lt;br /&gt;
&lt;br /&gt;
Named sets can be updated anytime, so you can add and delete element from them.&lt;br /&gt;
&lt;br /&gt;
Eric Leblond in his [https://home.regit.org/2014/01/why-you-will-love-nftables/ Why you will love nftables] article shows a very simple example to compare iptables with nftables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -A INPUT -p tcp -m multiport --dports 23,80,443 -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which can be expressed in &#039;&#039;nftables&#039;&#039; with a couple of rules that provide a set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip6 filter input tcp dport {telnet, http, https} accept&lt;br /&gt;
% nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Listing named sets =&lt;br /&gt;
&lt;br /&gt;
You can list the content of a named set via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list set filter myset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Phil</name></author>
	</entry>
</feed>