FortiGate Debug Flow Functions Explained: Complete Guide 2026
Published: June 18, 2026 | Category: FortiGate | Author: Bhardwaj Vishnu
Applies to: FortiGate (all CLI/GUI-capable models) · FortiOS 6.x / 7.x / 8.0.0
If you’ve spent any real time in FortiGate troubleshooting, you already know diagnose debug flow is the single most useful diagnostic tool on the platform — and also one of the most intimidating the first few times you read its raw output. A live capture throws dozens of lines at you per packet, each tagged with a func= value that tells you exactly which internal processing stage that line belongs to.
The problem is that nobody hands you a map of what these function names actually mean. You either learn them the hard way over years of TAC tickets, or you guess. This guide is the map — every function commonly seen in diagnose debug flow output, organized by the stage of packet processing it represents, with the message pattern you’ll actually see next to it. If you want the broader troubleshooting context this sits inside — HA, SD-WAN, ADVPN, security profiles — see our FortiGate debug commands guide covering packet flow and IPsec, which this article complements rather than replaces.
- Enabling Function Names in Debug Flow
- A Note Before the Reference Tables
- 1. Packet Reception
- 2. Session Lookup and Tuple Resolution
- 3. Routing
- 4. Policy Matching (iprope)
- 5. Policy Decision and Forward Handling
- 6. Common Deny-Reason Messages (No Dedicated Function, Seen Under Policy Evaluation)
- 7. NAT Application
- 8. NPU / Hardware Offload
- 9. IPsec / Tunnel Handling
- 10. IPS / Security Inspection Handoff
- How to Use This Reference During a Live Capture
- Frequently Asked Questions
Enabling Function Names in Debug Flow
Before any of this is useful, you need function names switched on in your capture:
diagnose debug flow filter addr <ip-address>
diagnose debug flow show function-name enable
diagnose debug flow show iprope enable
diagnose debug console timestamp enable
diagnose debug enable
diagnose debug flow trace start 100
A quick clarification worth knowing: function names appear to be produced in the output regardless of whether show function-name enable is set, but Fortinet still recommends explicitly enabling it. The show iprope enable line is separate and important on its own — it reveals the hidden iprope rule checks, which is the internal table of policies and rules that traffic gets matched against, including forward traffic rules like Firewall Policies and local-in policies.
For the full official syntax reference and version-specific notes (including the NP7 packet-flow exceptions), see Fortinet’s own Debugging the packet flow documentation.
To stop the capture once you’ve got what you need:
diagnose debug flow trace stop
diagnose debug disable
diagnose debug reset
A Note Before the Reference Tables
Line numbers next to each func= entry in real debug output (e.g. line=5824) are not stable across FortiOS versions — the same function appears at different line numbers depending on build, since they’re just pointers into that version’s compiled binary. This guide deliberately omits line numbers as a memorized reference for that reason. What’s stable, and worth learning, is the function name itself and the message pattern that accompanies it. Always read the line number live off your own capture, never from a guide.
1. Packet Reception
| Function | What It Means | Example Message |
print_pkt_detail |
The first line for almost every packet — confirms FortiGate received it, on which VDOM, with which protocol, ports, and ingress interface | “vd-root:0 received a packet(proto=6, 213.13.146.142:443->85.xyz.xyz.xyz:63853) tun_id=0.0.0.0 from wan1. flag [S.], seq…” |
2. Session Lookup and Tuple Resolution
| Function | What It Means | Example Message |
resolve_ip_tuple_fast |
Fast-path lookup checking whether the packet matches an existing session | “Find an existing session, id-00000e90, reply direction” |
resolve_ip_tuple |
Slow-path resolution used when a brand-new session needs to be allocated | “allocate a new session-013004ac” |
init_ip_session_common |
Session allocation, including tunnel-bound traffic | “allocate a new session-762651ef, tun_id=10.165.1.249” |
3. Routing
| Function | What It Means | Example Message |
vf_ip4_route_input |
Route lookup showing the selected gateway and outgoing interface | “find a route: gw-192.168.11.254 via port6” |
vf_ip_route_input_common |
Route lookup variant seen on some traffic types/builds | “find a route: flag=00000000 gw-10.89.2.146 via port5” |
4. Policy Matching (iprope)
iprope is the internal table of policies and rules that traffic is matched against, including forward traffic rules such as Firewall Policies and local-in policies.
| Function | What It Means | Example Message |
iprope_dnat_check |
Checks for a matching DNAT/VIP rule ahead of forward policy lookup | “in-[IPSec36], out-[]” → “result: skb_flags-02000008, vid-20, ret-no-match, act-accept, flag-00000000” |
iprope_dnat_tree_check |
Sub-check within the DNAT matching tree | “len=0” |
iprope_fwd_check |
Forward policy check, showing ingress/egress interface plus app/URL category if already known | “in-[IPSec36], out-[port5], skb_flags-02000008, vid-20, app_id: 0, url_cat_id: 0” |
__iprope_tree_check |
Internal tree-matching step during forward policy evaluation | “gnum-100004, use addr/intf hash, len=4” |
__iprope_check |
Generic policy-group check result — used for session-helper groups (SIP/SCCP) as well as forward policy groups | “gnum-4e20 check result: ret-no-match, act-accept, flag-00000000, flag2-00000000” |
__iprope_check_one_policy |
Confirms exactly which numbered firewall policy matched | “policy-2 is matched, act-accept” |
iprope_policy_group_check |
Policy-group level check — commonly seen failing in captive portal and SSL VPN source-address denial scenarios | “after check: ret-matched, act-drop, flag-00000020, flag2-00000000” |
iprope_fwd_auth_check |
Authentication portal check on the forward path | “iprope_auth_portal_check() result: ret-matched, act-drop” |
iprope_reverse_dnat_tree_check |
Reverse-direction DNAT tree check on reply-direction packets | “len=0” |
If you’re seeing denies specifically tied to web category matching rather than a plain firewall policy mismatch, that usually means the inspection layer is involved rather than iprope itself — worth cross-checking against our FortiGate web filtering guide before assuming it’s a routing or policy-table problem.
5. Policy Decision and Forward Handling
| Function | What It Means | Example Message |
fw_forward_handler |
States the final allow/deny decision against the matched policy | Deny: “Denied by forward policy check” · Deny with policy ID: “Denied by forward policy check (policy 0)” · Allow: “Allowed by Policy-2: SNAT” |
fw_forward_dirty_handler |
Variant handler seen when session/NPU state flags are involved | “state=00010200, state2=00000000, npu_state=00000101” |
6. Common Deny-Reason Messages (No Dedicated Function, Seen Under Policy Evaluation)
These don’t always carry their own unique func= tag in older captures, but they’re the messages every engineer needs to recognize instantly:
| Message | Root Cause |
iprope_in_check() check failed, drop |
Appears when the FortiGate can’t match an incoming local-in service against a policy. Common cause: trying to ping, telnet, or SSH to an interface where that service isn’t enabled in the interface’s administrative access settings. Also seen with SSL VPN connections from a source IP not in the configured source-address list, or geo-location restrictions blocking the connecting country. |
iprope_in_check() check failed on policy 0, drop |
Same root mechanism, explicitly showing policy 0 — meaning no real policy was matched at all, often pointing at captive portal interaction or dial-up IPsec user-group authentication issues. |
reverse path check fail, drop |
FortiGate’s RPF (Reverse Path Forwarding / anti-spoofing) has no active route back to the source IP of the connection, so the packet is assumed spoofed and dropped. RPF requires an active route — usually a default route — on every interface where sessions can be initiated. |
Denied by forward policy check |
Generic catch-all for traffic that simply has no matching firewall policy at all. |
If you’re hitting iprope_in_check denials specifically on a dial-up IPsec or remote-access tunnel, it’s worth comparing your config against our FortiGate IPsec remote access VPN guide for FortiOS 7 — user-group authentication mismatches there are a frequent root cause. Similarly, if the denied session is one that should be carrying DHCP-assigned addressing over a tunnel, see our FortiGate DHCP over IPsec VPN configuration guide, since a misconfigured DHCP relay over IPsec produces a very similar-looking deny pattern to a plain policy mismatch.
7. NAT Application
| Function | What It Means | Example Message |
__ip_session_run_tuple |
Applies the actual SNAT or DNAT translation to the session tuple | SNAT: “SNAT 192.168.1.204->85.xyz.xyz.xyz:63853” · DNAT: “DNAT 192.168.11.59:31925->192.168.3.221:1487” |
get_new_addr |
Allocates the translated source IP/port for SNAT from the configured pool | “find SNAT: IP-192.168.11.59, port-31925” |
8. NPU / Hardware Offload
| Function | What It Means | Example Message |
npu_handle_session44 |
FortiGate attempting to offload the session to NPU hardware | “Trying to offloading session from IPSec36 to port5, skb.npu_flag=00000400 ses.state=00010200 ses.npu_state=0x00000101” |
np6xlite_fos_set_nturbo_ips_fwd_session |
NTurbo/NP6Lite offload step for IPS-bound forwarding sessions | “push nturbo session oid 12” |
ip_session_install_npu_session |
Confirms whether NPU offload installation succeeded | “npu session installation succeeded” |
ip_session_confirm_final |
Final session state confirmation, including NPU state and hook number | “npu_state=0x1100, hook=4” |
NPU offload behavior differs meaningfully depending on which ASIC generation is handling the traffic. If you’re trying to map an npu_handle_session44 line back to actual silicon-level packet flow, our FortiASIC NP7/CP9/SP5 architecture deep dive covers the pipeline stages this debug output is abstracting over. This section also matters if you’re troubleshooting offloaded traffic across an LACP-bonded interface, since link aggregation adds another layer between the NPU decision and the physical egress port.
9. IPsec / Tunnel Handling
| Stage | What It Means | Example Message |
| Tunnel entry | Marks entry into a policy-based IPsec tunnel | “enter IPsec tunnel-RemotePhase1” |
| Encryption | Confirms the packet was encrypted and sent to the remote peer | “encrypted, and send to 15.215.225.22 with source 66.236.56.226” |
10. IPS / Security Inspection Handoff
| Function | What It Means | Example Message |
ids_receive |
Marks the packet being handed to the IPS engine for inspection | “send to ips” |
How to Use This Reference During a Live Capture
A practical workflow rather than reading raw output top to bottom:
- Filter narrowly first.
diagnose debug flow filter addr <ip>before you ever start the trace — capturing without a filter on a busy firewall buries you in unrelated sessions. - Grep for the deny line first. If traffic isn’t passing, search the output for
Denied,check failed, orreverse pathbefore reading anything else — that single line tells you which table above to consult. - Walk the stages in order. Reception → session lookup → routing → iprope/policy match → NAT → offload. If a session dies between two stages, that gap is where your problem lives.
- Cross-reference with the session table. Once you’ve got a session ID from
resolve_ip_tuple_fast, pull it withdiagnose sys session listto see the full session state, not just the flow trace snapshot. - Check HA sync if the behavior differs between nodes. If a tunnel or session behaves correctly on one HA member but not the other, the debug flow output itself won’t tell you why — that’s a sync issue, covered in our FortiGate HA commands and debug guide.
One last practical note that ties back to where this whole reference series started: if you’re working through this on a fresh or RMA’d unit and the debug flow output looks fine but the unit itself won’t pass any traffic at all, double check it’s actually licensed before chasing a packet-flow problem that isn’t really there — see how to upload a FortiGate license via TFTP when there’s no internet access if that’s the case.
Frequently Asked Questions
Does diagnose debug flow show every packet, or just the first few?
It shows whatever you set with trace start <n> — that number is a packet count, not a time limit. On a busy interface, even a narrow filter can produce a large capture quickly, so start with a low number like 20–50 and increase only if needed.
Why don’t I see any func= tags in my output at all?
Function names should appear regardless of whether show function-name enable is set, but explicitly enabling it is still recommended — if you’re still not seeing them, double-check you ran the command before debug enable, since order matters in the debug flow command sequence.
What’s the difference between iprope_in_check and iprope_fwd_check?
iprope_in_check relates to local-in traffic — connections destined for the FortiGate itself (management access, dial-up IPsec, SSL VPN). iprope_fwd_check relates to forward traffic passing through the firewall to another destination. A failure in the former points at interface administrative access or local-in policies; a failure in the latter points at your standard firewall policy table.
My traffic shows reverse path check fail, drop but the route is clearly in my routing table — why?
This happens when the route exists but not via the same interface the packet actually arrived on. RPF checks that an active route back to the source exists via the interface where the packet was received — a route that’s correct in general but points out a different interface will still trigger the drop. Asymmetric routing environments hit this constantly; check whether asymmetric routing needs to be explicitly enabled for your topology.
Can I run diagnose debug flow without affecting production traffic?
Yes, the debug flow tool only observes and logs — it doesn’t alter packet handling. The real risk is generating excessive log volume on a high-throughput interface with no filter applied, which can affect CPU briefly during the capture. Always filter by address or port first.
Does this work the same way for NP6/NP7 offloaded traffic?
Not fully. Offloaded sessions bypass most of this software-path processing once installed in hardware, so you’ll only see the initial setup stages in debug flow. To trace ongoing behavior on offloaded traffic, either test with ICMP (which isn’t offloaded) or temporarily disable offloading on the relevant interface/policy.
Hit a function or message pattern not covered here? Use the contact page and include your full diagnose debug flow output with function names enabled — I’ll get it added to this reference.
Bhardwaj Vishnu is a Network Security Engineer with hands-on expertise in enterprise firewall management, network automation, and multi-vendor infrastructure. He holds Fortinet NSE 4/NSE 5, a Cisco CCNA, and the full Cisco Meraki certification track. He architects FortiGate security policies, manages Cisco Meraki MX/MS/MR deployments, and handles enterprise routing and switching. Every guide on netconfig.io comes from direct production experience — real CLI commands, verified configs.