FortiGate Debug Flow Functions
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.
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” |
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.
