Skip to main content
The nft section captures nftables rule matching events, including table, chain, rule handles, and verdicts.

Fields

table_name
string
required
Name of the nftables table that was traversed.Examples: "firewalld", "nat", "filter"
chain_name
string
required
Name of the chain within the table.Examples: "filter_INPUT", "postrouting", "prerouting"
verdict
string
required
Verdict/action taken by the rule or chain policy.Common values: "accept", "drop", "reject", "jump", "goto", "return"
verdict_chain_name
string
Target chain name when verdict is "jump" or "goto".
table_handle
i64
required
Numeric handle of the table. Used to match against nftables configuration.
chain_handle
i64
required
Numeric handle of the chain. Used to match against nftables configuration.
rule_handle
i64
Numeric handle of the specific rule that matched.When null, this indicates the chain’s default policy was applied (no explicit rule match).
policy
bool
required
Whether this verdict came from the chain’s default policy (true) or an explicit rule (false).

Display Format

table {table_name} ({table_handle}) chain {chain_name} ({chain_handle}) 
[handle {rule_handle}] {verdict} [(policy)] [chain {verdict_chain_name}]

Examples

Explicit rule match:
table firewalld (2) chain filter_INPUT (165) handle 169 accept
Chain policy:
table firewalld (2) chain filter_PREROUTING (164) accept (policy)
Jump to another chain:
table firewalld (2) chain filter_INPUT (165) handle 176 jump chain filter_INPUT_ZONES

Example JSON

Explicit Rule Match

{
  "nft": {
    "table_name": "firewalld",
    "chain_name": "filter_INPUT",
    "verdict": "accept",
    "verdict_chain_name": null,
    "table_handle": 2,
    "chain_handle": 165,
    "rule_handle": 169,
    "policy": false
  }
}

Chain Policy

{
  "nft": {
    "table_name": "firewalld",
    "chain_name": "filter_PREROUTING",
    "verdict": "accept",
    "verdict_chain_name": null,
    "table_handle": 2,
    "chain_handle": 164,
    "rule_handle": null,
    "policy": true
  }
}

Drop Rule

{
  "nft": {
    "table_name": "firewalld",
    "chain_name": "filter_INPUT",
    "verdict": "drop",
    "verdict_chain_name": null,
    "table_handle": 2,
    "chain_handle": 165,
    "rule_handle": 172,
    "policy": false
  }
}

Jump to Chain

{
  "nft": {
    "table_name": "firewalld",
    "chain_name": "filter_INPUT",
    "verdict": "jump",
    "verdict_chain_name": "filter_INPUT_ZONES",
    "table_handle": 2,
    "chain_handle": 165,
    "rule_handle": 176,
    "policy": false
  }
}

Mapping to nftables Configuration

Use the handle values to map events back to your nftables ruleset:
# Dump ruleset with handles
sudo nft -a list ruleset

Example Configuration

table inet firewalld { # handle 2
    chain filter_PREROUTING { # handle 164
        type filter hook prerouting priority filter + 10; policy accept;
        icmpv6 type { nd-router-advert, nd-neighbor-solicit } accept # handle 197
        meta nfproto ipv6 fib saddr . mark . iif oif missing drop # handle 195
    }

    chain filter_INPUT { # handle 165
        type filter hook input priority filter + 10; policy accept;
        ct state { established, related } accept # handle 169
        ct status dnat accept # handle 170
        iifname "lo" accept # handle 171
        ct state invalid drop # handle 172
        jump filter_INPUT_ZONES # handle 176
        reject with icmpx admin-prohibited # handle 177
    }
}

Mapping Events

Event 1:
{"table_handle": 2, "chain_handle": 164, "rule_handle": null, "policy": true}
Matches: Chain filter_PREROUTING default policy (accept) Event 2:
{"table_handle": 2, "chain_handle": 165, "rule_handle": 169, "policy": false}
Matches: Rule ct state { established, related } accept # handle 169 Event 3:
{"table_handle": 2, "chain_handle": 165, "rule_handle": 176, "verdict": "jump", "verdict_chain_name": "filter_INPUT_ZONES"}
Matches: Rule jump filter_INPUT_ZONES # handle 176

Complete Event Example

{
  "common": {
    "timestamp": 53529978697438,
    "smp_id": 0,
    "task": {
      "pid": 0,
      "tgid": 0,
      "comm": "swapper/0"
    }
  },
  "kernel": {
    "symbol": "__nft_trace_packet",
    "probe_type": "kprobe"
  },
  "nft": {
    "table_name": "firewalld",
    "chain_name": "filter_INPUT",
    "verdict": "accept",
    "verdict_chain_name": null,
    "table_handle": 2,
    "chain_handle": 165,
    "rule_handle": 169,
    "policy": false
  },
  "packet": {
    "len": 66,
    "capture_len": 66,
    "data": "...(base64)..."
  }
}

When This Section Appears

The nft section is populated when:
  • The nft collector is enabled (-c nft)
  • Packets traverse nftables chains with tracing enabled
  • The __nft_trace_packet kernel function is called

Analyzing Firewall Behavior

Use nft events to:
  1. Debug firewall rules: See which rules match which packets
  2. Verify policies: Confirm default policies are applied correctly
  3. Trace packet paths: Follow packets through chain jumps
  4. Identify drops: Find which rules drop traffic
  5. Performance analysis: Count rule matches to optimize rule order

Example Queries

# Find all drops
retis print events.json --format json | \
  jq '.events[] | select(.nft.verdict == "drop")'

# Count matches by rule handle
retis print events.json --format json | \
  jq -r '.events[].nft.rule_handle' | sort | uniq -c

# Find policy hits
retis print events.json --format json | \
  jq '.events[] | select(.nft.policy == true)'
Combine the nft collector with skb to see both the firewall decision and the packet contents that triggered it.

Build docs developers (and LLMs) love