This section describes the NVIDIA DOCA P4 Developer Tools, used to inspect and debug P4 programs that have been loaded to the DPU.
Introduction
Developers that develop P4 (Programming Protocol-independent Packet Processors) applications require tools to validate and debug their work.
NVIDIA P4 contains the following developer tools:
-
p4nspect CLI
-
P4 Debugger
The developer tools interact with a P4 program running on an NVIDIA® BlueField® DPU.
This technical document outlines the usage and options available in the P4 developer tools, including commands, options, and their descriptions.
Prerequisites
-
The P4 Agent (
nvp4agent) daemon must be up and running on the DPU (which is the host machine). Thenvp4agentloads thep4nspect-serverrequired by the tools. -
Compiling the P4 program using NVIDIA's P4 Compiler (
nvp4c).
Loading the nvp4c compilation output to the nvp4agent.
Setup
The tools provided are packed in a single python wheel package (e.g., p4nspect-1.0.whl).
Installing the package requires pip and can be done easily using:
pip install p4nspect-1.0.whl
After installation the tools will be available through the p4nspect and p4debugger commands in the python environment.
p4nspect Description
The p4nspect tool provides a Command-Line Interface (CLI) for:
-
Viewing the dynamic state of a P4 program components - tables, entries, keys and actions, counters and values.
-
Start and stop the recording of a debug session.
-
Dumping the state of a P4 program to an archive for offline analysis.
p4nspect Execution
Running p4nspect with no additional arguments will show the basic usage of the CLI tool. For further details, use the help/-h/--help argument.
Running commands requires a connection to the local/remote host where p4nspect-server is running, the address host and port are configurable and are 127.0.0.1:9560 by default.
The executed command's output format varies between executed commands and can sometimes be modified by providing additional arguments.
A common use case for modifying a command output is to be able use it as part of some automatic scripting.
p4nspect Tool Commands and Flags
The p4nspect CLI offers various commands for interacting with the P4 program and the DPU:
-
system-info– Displays DPU system information, including HW Model, OS name and version, OFED version. Retrieve information regarding the system specifications such as the OS version, OFED version, etc. -
devices– Lists the virtual devices configured on the DPU
Software abstractions representing real or emulated hardware devices. They provide a standardized interface for applications to interact with the DPU's resources, regardless of underlying physical hardware.
Examples include:
-
Virtual Network Interfaces (VNIs) – Logical representations of physical NICs, allowing multiple virtual networks to share a single physical interface
-
Virtual Processing Units (VPUs) – Software-defined processing units within the DPU that can be allocated to applications for tasks like packet processing or security offloading
-
Virtual Storage Devices – Software-defined representations of physical storage, offering flexibility in managing and allocating storage resources
-
counters – Display P4 counters details and values. The details included are the table, offset and value.
-
tables – Lists tables of P4 programs loaded on the DPU. Each table will detail its keys, actions, counters and a reference to its (program's) source location.
-
query – Lists P4 table entries, keys, and actions with the priority of each set of keys
-
graph – Displays a graph of the P4 pipeline using DOT language. This graph can be graphically rendered using DOT renderers.
-
hw-steering – Displays HW Steering rules dump
-
debug – Starts a debug session
Help Flags
To display details of p4nspect options usage:
-
help,-h,--help– Displays the help message and exits.
Output Control Flags
The following flags are optional and can be used independently:
-
-ll,--low-level– Displays low-level implementation details of DOCA HAL pipeline -
-ni,--non-interactive– Disables interactive output mode. This is useful for running p4nspect commands from an automatic script. -
-nh,--no-hints– Disables hints for further information. This is useful for running p4nspect commands from an automatic script. -
--csv– Sets command output to use CSV format -
--json– Sets command output to use JSON format -
--top-packets TOP_PACKETS– ShowTOP_PACKETSentries with the highest counter packets values (default: None) -
--top-bytes TOP_BYTES– ShowTOP_PACKETSentries with the highest counter bytes values (default: None) -
--url– Encode the output as a URL that can be directly pasted in a web browser. This is useful for quick rendering using online render websites (default: False). -
--parser– Display a graph of the P4 pipeline or the Flex Parser (default: False)
Filter Control Flags
-
-d DEVICE_IDS,--device_ids DEVICE_IDS– Specifies a comma-separated list of device IDs to be used -
--table_ids TABLE_IDS– Specify which table IDs to filter by (default: []) -
--table_names TABLE_NAMES– Specify which table names to filter by (default: []) -
--counter-names COUNTER_NAMES– Specify which counter names to filter by (default: []) -
--indices INDICES– Specify which entries indices to filter by (default: []) -
--show-unused– Show unused counter indices (default: False)
Control Flags for Connecting to DPU
-
-a ADDRESS,--address ADDRESS– Specifies the p4nspect server address in the formathost:port(default value is127.0.0.1:9560). -
--timeout TIMEOUT– Specifies the gRPC channel connectivity timeout (optional)
p4nspect running on a host where a DPU is installed locally uses the default values to connect to the P4 Program running on the local DPU. Specify host and port values to connect p4nspect to a P4 program running on a remote DPU.
Misc Flags
-
--version,-V– Displays the program's version number and exits.
p4nspect Commands
System-info
p4dt-dpu$ p4nspect system-info
|
DESCRIPTION |
VALUE |
|---|---|
|
DOCA HAL version |
TODO |
|
Linux OS version |
Ubuntu 22.04 LTS |
|
OFED Version |
MLNX_OFED_LINUX-24.01-0.1.7.0: |
|
P4 Agent version |
TODO |
Devices
List the of the installed BlueField (DPU) devices which the npv4agent is running on.
p4dt-dpu$ p4nspect devices
|
ID |
NAME |
PCI ADDRESS |
PORT ID |
NAME |
NUMBER |
P4 PROGRAM |
FW VERSION |
HW MODEL |
|---|---|---|---|---|---|---|---|---|
|
1000 |
br9 |
0000:65:00.0 |
0 |
enp101s0f0np0 |
50 |
alpha2_d2 |
32.38.0588 |
BlueField-3 integrated ConnectX-7 network controller |
|
|
|
|
4 |
eth3 |
5 |
|
|
|
|
|
|
|
1 |
eth0 |
2 |
|
|
|
|
|
|
|
2 |
eth1 |
3 |
|
|
|
|
|
|
|
3 |
eth2 |
4 |
|
|
|
Counters
p4dt-dpu$ p4nspect counters
DEVICE: 1000, NV_COUNTER: alpha2_drop2.decap.decap_counter, SCOPE: alpha2_drop2, TYPE: Pkts/Bts, SIZE: 4, IN USE: 3
|
IDX |
P4 |
ENTRY OFFSET |
VALUE |
|---|---|---|---|
|
0 |
decap_table |
1 |
(2, 140) |
|
1 |
decap_table |
2 |
(0, 0) |
|
2 |
decap_table |
0 |
(0, 0) |
DEVICE: 1000, NV_COUNTER: alpha2_drop2.encap.encap_counter, SCOPE: alpha2_drop2, TYPE: Pkts/Bts, SIZE: 4, IN USE: 3
|
IDX |
P4 |
ENTRY OFFSET |
VALUE |
|---|---|---|---|
|
0 |
encap_table |
0 |
(0, 0) |
|
1 |
encap_table |
2 |
(0, 0) |
|
2 |
encap_table |
1 |
(0, 0) |
DEVICE: 1000, NV_DIRECT_COUNTER: alpha2_drop2.gtp.gtp_counter, SCOPE: alpha2_drop2, TYPE: Pkts/Bts, SIZE: 128, IN USE: 3
|
IDX |
P4 |
ENTRY OFFSET |
VALUE |
|---|---|---|---|
|
0 |
gtp_table |
2 |
(0, 0) |
|
1 |
gtp_table |
1 |
(0, 0) |
|
2 |
gtp_table |
0 |
(0, 0) |
The value is in the following format: (number of packets, number of bytes)
Tables
p4dt-dpu$ p4nspect tables
DEVICE: 1000
|
ID |
TABLE |
KEYS |
ACTIONS |
COUNTER |
ENTRIES |
SOURCE |
|---|---|---|---|---|---|---|
|
34318161 |
alpha2_drop2.gtp.gtp_table |
std_meta.ingress_port |
alpha2_drop2.gtp.send_to_port |
alpha2_drop2.gtp.gtp_counter |
3 |
alpha2_d2.p4:102 |
|
|
|
headers.gtpv1.teid |
alpha2_drop2.gtp.drop |
|
|
|
|
41521446 |
alpha2_drop2.encap.encap_table |
std_meta.ingress_port |
alpha2_drop2.encap.send_to_port |
|
4 |
alpha2_d2.p4:173 |
|
|
|
headers.ipv4.src_addr |
alpha2_drop2.encap.encap_gre |
|
|
|
|
|
|
|
alpha2_drop2.encap.encap_vxlan |
|
|
|
|
|
|
|
NoAction |
|
|
|
|
44963766 |
alpha2_drop2.decap.decap_table |
std_meta.ingress_port |
alpha2_drop2.decap.send_to_port |
|
4 |
alpha2_d2.p4:235 |
|
|
|
headers.gre.$valid$ |
alpha2_drop2.decap.decap_gre |
|
|
|
|
|
|
headers.vxlan.$valid$ |
alpha2_drop2.decap.decap_vxlan |
|
|
|
|
|
|
|
NoAction |
|
|
|
Query
p4dt-dpu$ p4nspect query
DEVICE: 1000, TABLE: alpha2_drop2.gtp.gtp_table, ID: 34318161, SOURCE: alpha2_d2.p4:102
|
PRIO |
P4 KEY |
VALUE |
MASK |
TYPE |
P4 ACTION |
|---|---|---|---|---|---|
|
0 |
std_meta.ingress_port |
0x1 |
|
exact |
alpha2_drop2.gtp.send_to_port(port=0x0) |
|
|
headers.gre.$valid$ |
0x1 |
|
exact |
|
|
0 |
std_meta.ingress_port |
0x0 |
|
exact |
alpha2_drop2.gtp.send_to_port(port=0x1) |
|
|
headers.gre.$valid$ |
0x1 |
|
exact |
|
|
0 |
ALWAYS_HIT |
|
|
|
alpha2_drop2.gtp.drop() |
DEVICE: 1000, TABLE: alpha2_drop2.encap.encap_table, ID: 41521446, SOURCE: alpha2_d2.p4:173
|
PRIO |
P4 KEY |
VALUE |
MASK |
TYPE |
P4 ACTION |
|---|---|---|---|---|---|
|
3 |
std_meta.ingress_port |
0x0 |
|
exact |
alpha2_drop2.encap.send_to_port(port=0x4) |
|
|
headers.gre.$valid$ |
0x10000000 |
0xff000000 |
ternary |
|
|
1 |
std_meta.ingress_port |
0x0 |
|
exact |
alpha2_drop2.encap.encap_vxlan(port=0x3, src_mac=0x112233445566,dst_mac=0x10203040506,sip=0x1010101,dip=0x2020202,vni=0xabcd) |
|
|
headers.gre.$valid$ |
0x20000000 |
0xff000000 |
ternary |
|
|
2 |
std_meta.ingress_port |
0x0 |
|
exact |
alpha2_drop2.encap.encap_gre(port=0x2,src_mac=0x112233445566,dst_mac=0x10203040506,sip=0x1010101,dip=0x2020202,key=0xabcd) |
|
|
headers.gre.$valid$ |
0x20000000 |
0xff000000 |
ternary |
|
|
0 |
ALWAYS_HIT |
|
|
|
NoAction() |
DEVICE: 1000, TABLE: alpha2_drop2.decap.decap_table, ID: 44963766, SOURCE: alpha2_d2.p4:235
|
PRIO |
P4 KEY |
VALUE |
MASK |
TYPE |
P4 ACTION |
|---|---|---|---|---|---|
|
0 |
std_meta.ingress_port |
0x3 |
|
exact |
alpha2_drop2.decap.decap_vxlan(port=0x0,src_mac=0xaabbccddeeff,dst_mac=0x112233445566) |
|
|
headers.gre.$valid$ |
0x0 |
|
exact |
|
|
|
headers.vxlan.$valid$ |
0x1 |
|
exact |
|
|
0 |
std_meta.ingress_port |
0x4 |
|
exact |
alpha2_drop2.decap.send_to_port(port=0x0) |
|
|
headers.gre.$valid$ |
0x0 |
|
exact |
|
|
|
headers.vxlan.$valid$ |
0x0 |
|
exact |
|
|
0 |
std_meta.ingress_port |
0x2 |
|
exact |
alpha2_drop2.decap.decap_gre(port=0x0) |
|
|
headers.gre.$valid$ |
0x1 |
|
exact |
|
|
|
headers.vxlan.$valid$ |
0x0 |
|
exact |
|
|
0 |
ALWAYS_HIT |
|
|
|
NoAction() |
Different Output Option Flags
p4dt-dpu$ p4nspect tables --csv
"DEVICE: 1000"
"ID","TABLE","KEYS","ACTIONS","COUNTER","ENTRIES","SOURCE"
"34318161","alpha2_drop2.gtp.gtp_table","std_meta.ingress_port
headers.gtpv1.teid","alpha2_drop2.gtp.send_to_port
alpha2_drop2.gtp.drop","alpha2_drop2.gtp.gtp_counter","3","alpha2_d2.p4:102"
"41521446","alpha2_drop2.encap.encap_table","std_meta.ingress_port
headers.ipv4.src_addr","alpha2_drop2.encap.send_to_port
alpha2_drop2.encap.encap_gre
alpha2_drop2.encap.encap_vxlan
NoAction","","4","alpha2_d2.p4:173"
"44963766","alpha2_drop2.decap.decap_table","std_meta.ingress_port
headers.gre.$valid$
headers.vxlan.$valid$","alpha2_drop2.decap.send_to_port
alpha2_drop2.decap.decap_gre
alpha2_drop2.decap.decap_vxlan
NoAction","","4","alpha2_d2.p4:235"
p4dt-dpu$ p4nspect tables --json
[
[
{
"DEVICE": 1000
},
{
"ID": 34318161,
"TABLE": "alpha2_drop2.gtp.gtp_table",
"KEYS": [
"std_meta.ingress_port",
"headers.gtpv1.teid"
],
"ACTIONS": [
"alpha2_drop2.gtp.send_to_port",
"alpha2_drop2.gtp.drop"
],
"COUNTER": "alpha2_drop2.gtp.gtp_counter",
"ENTRIES": 3,
"SOURCE": {
"filename": "/tmp/p4src/alpha2_d2.p4",
"line": 102,
"column": 11
}
},
{
"ID": 41521446,
"TABLE": "alpha2_drop2.encap.encap_table",
"KEYS": [
"std_meta.ingress_port",
"headers.ipv4.src_addr"
],
"ACTIONS": [
"alpha2_drop2.encap.send_to_port",
"alpha2_drop2.encap.encap_gre",
"alpha2_drop2.encap.encap_vxlan",
"NoAction"
],
"COUNTER": "",
"ENTRIES": 4,
"SOURCE": {
"filename": "/tmp/p4src/alpha2_d2.p4",
"line": 173,
"column": 11
}
},
{
"ID": 44963766,
"TABLE": "alpha2_drop2.decap.decap_table",
"KEYS": [
"std_meta.ingress_port",
"headers.gre.$valid$",
"headers.vxlan.$valid$"
],
"ACTIONS": [
"alpha2_drop2.decap.send_to_port",
"alpha2_drop2.decap.decap_gre",
"alpha2_drop2.decap.decap_vxlan",
"NoAction"
],
"COUNTER": "",
"ENTRIES": 4,
"SOURCE": {
"filename": "/tmp/p4src/alpha2_d2.p4",
"line": 235,
"column": 11
}
}
]
]
Graph
p4dt-dpu$ p4nspect graph -ll
This command generates output of the program's control flow graph in dot format.
Device 1000:
digraph hybrid_pipeline {
graph [compound=true]
// Legend
subgraph cluster_legend {
hal_table [label=<<B>HAL Table ID</B><BR/>[Implements P4 Objects]> shape=diamond]
legend_invis [label=legend_invis shape=point style=invis width=0]
p4_control [label="P4 Control" color=blue shape=rectangle]
}
alpha2_drop2_start [label=start color=green shape=none]
legend_invis -> alpha2_drop2_start [style=invis]
// Pipeline Stage: main
subgraph cluster_alpha2_drop2 {
graph [color=blue label=alpha2_drop2 shape=rectangle]
24 [label=<<B>24</B><BR/>[alpha2_drop2]> shape=diamond]
alpha2_drop2_start -> 24
48 [label=<<B>48</B><BR/>[alpha2_drop2.gtp.gtp_table]> shape=diamond]
DROP [label=DROP fontcolor=red shape=box]
48 -> DROP
alpha2_drop2_end [label=end color=red shape=none]
48 -> alpha2_drop2_end
36 [label=<<B>36</B><BR/>[alpha2_drop2]> shape=diamond]
36 -> 48
56 [label=<<B>56</B><BR/>[alpha2_drop2.decap.decap_table]> shape=diamond]
56 -> alpha2_drop2_end
44 [label=<<B>44</B><BR/>[alpha2_drop2]> shape=diamond]
44 -> 56
44 -> alpha2_drop2_end
32 [label=<<B>32</B><BR/>[alpha2_drop2]> shape=diamond]
32 -> 44
32 -> alpha2_drop2_end
52 [label=<<B>52</B><BR/>[alpha2_drop2.encap.encap_table]> shape=diamond]
52 -> 32
52 -> alpha2_drop2_end
40 [label=<<B>40</B><BR/>[alpha2_drop2]> shape=diamond]
55 [label=<<B>55</B><BR/>[alpha2_drop2.encap.encap_table]> shape=diamond]
40 -> 55
40 -> 32
40 -> alpha2_drop2_end
28 [label=<<B>28</B><BR/>[alpha2_drop2]> shape=diamond]
28 -> 40
28 -> alpha2_drop2_end
36 -> 28
36 -> alpha2_drop2_end
24 -> 36
24 -> alpha2_drop2_end
}
}
p4dt-dpu$ p4nspect graph -ll --url
Running this command generates a HTTP url link to the program's control flow graph (shown above) in dot format, rendered using https://dreampuf.github.io/GraphvizOnline/#digraph%20example%0A%7B%0A%7D%0A
p4dt-dpu$ p4nspect graph --parser
This command generates output of the program's parser graph in dot format.
Device 1000:
// Parser packet_parser
digraph packet_parser {
graph [concentrate=true splines=compound]
// Legend
subgraph cluster_legend {
fixed_state [label="Fixed State" style=filled]
legend_invis [label=legend_invis shape=point style=invis width=0]
flex_state [label="Flex State"]
default_transition_note [label="All states have an hidden transition to accept\nEdges are annotated with their match value." shape=none]
legend_invis -> default_transition_note [style=invis]
}
start [label=start color=green shape=point]
default_transition_note -> start [style=invis]
nv_parse_ethernet [label=ethernet id=nv_parse_ethernet style=filled]
start -> nv_parse_ethernet
nv_parse_vlan [label=vlan id=nv_parse_vlan style=filled]
nv_parse_ethernet -> nv_parse_vlan [label="0x8100" color=gray id="nv_parse_ethernet-nv_parse_vlan"]
nv_parse_ipv4 [label=ipv4 id=nv_parse_ipv4 style=filled]
nv_parse_ethernet -> nv_parse_ipv4 [label="0x800" color=gray id="nv_parse_ethernet-nv_parse_ipv4"]
nv_parse_ipv6 [label=ipv6 id=nv_parse_ipv6 style=filled]
nv_parse_ethernet -> nv_parse_ipv6 [label="0x86dd" color=gray id="nv_parse_ethernet-nv_parse_ipv6"]
nv_parse_mpls [label=mpls id=nv_parse_mpls style=filled]
nv_parse_ethernet -> nv_parse_mpls [label="0x8847" color=gray id="nv_parse_ethernet-nv_parse_mpls"]
nv_parse_geneve [label=geneve id=nv_parse_geneve style=filled]
nv_parse_inner_ipv4 [label=inner_ipv4 id=nv_parse_inner_ipv4 style=filled]
nv_parse_geneve -> nv_parse_inner_ipv4 [label="0x800" color=gray id="nv_parse_geneve-nv_parse_inner_ipv4"]
nv_parse_inner_ipv6 [label=inner_ipv6 id=nv_parse_inner_ipv6 style=filled]
nv_parse_geneve -> nv_parse_inner_ipv6 [label="0x86dd" color=gray id="nv_parse_geneve-nv_parse_inner_ipv6"]
nv_parse_inner_mpls [label=inner_mpls id=nv_parse_inner_mpls style=filled]
nv_parse_geneve -> nv_parse_inner_mpls [label="0x8847" color=gray id="nv_parse_geneve-nv_parse_inner_mpls"]
nv_parse_inner_ethernet [label=inner_ethernet id=nv_parse_inner_ethernet style=filled]
nv_parse_geneve -> nv_parse_inner_ethernet [label="0x6558" color=gray id="nv_parse_geneve-nv_parse_inner_ethernet"]
nv_parse_gre [label=gre id=nv_parse_gre style=filled]
nv_parse_gre -> nv_parse_inner_ipv4 [label="0x800" color=gray id="nv_parse_gre-nv_parse_inner_ipv4"]
nv_parse_gre -> nv_parse_inner_ipv6 [label="0x86dd" color=gray id="nv_parse_gre-nv_parse_inner_ipv6"]
nv_parse_gre -> nv_parse_inner_mpls [label="0x8847" color=gray id="nv_parse_gre-nv_parse_inner_mpls"]
nv_parse_nvgre_vsid [label=nvgre_vsid id=nv_parse_nvgre_vsid style=filled]
nv_parse_gre -> nv_parse_nvgre_vsid [label="0x6558" color=gray id="nv_parse_gre-nv_parse_nvgre_vsid"]
nv_parse_icmp [label=icmp id=nv_parse_icmp style=filled]
nv_parse_icmpv6 [label=icmpv6 id=nv_parse_icmpv6 style=filled]
nv_parse_inner_vlan [label=inner_vlan id=nv_parse_inner_vlan style=filled]
nv_parse_inner_ethernet -> nv_parse_inner_vlan [label="0x8100" color=gray id="nv_parse_inner_ethernet-nv_parse_inner_vlan"]
nv_parse_inner_ethernet -> nv_parse_inner_ipv4 [label="0x800" color=gray id="nv_parse_inner_ethernet-nv_parse_inner_ipv4"]
nv_parse_inner_ethernet -> nv_parse_inner_ipv6 [label="0x86dd" color=gray id="nv_parse_inner_ethernet-nv_parse_inner_ipv6"]
nv_parse_inner_ethernet -> nv_parse_inner_mpls [label="0x8847" color=gray id="nv_parse_inner_ethernet-nv_parse_inner_mpls"]
nv_parse_inner_icmp [label=inner_icmp id=nv_parse_inner_icmp style=filled]
nv_parse_inner_icmpv6 [label=inner_icmpv6 id=nv_parse_inner_icmpv6 style=filled]
nv_parse_inner_ipv4 -> nv_parse_inner_icmp [label="0x1" color=gray id="nv_parse_inner_ipv4-nv_parse_inner_icmp"]
nv_parse_inner_tcp [label=inner_tcp id=nv_parse_inner_tcp style=filled]
nv_parse_inner_ipv4 -> nv_parse_inner_tcp [label="0x6" color=gray id="nv_parse_inner_ipv4-nv_parse_inner_tcp"]
nv_parse_inner_udp [label=inner_udp id=nv_parse_inner_udp style=filled]
nv_parse_inner_ipv4 -> nv_parse_inner_udp [label="0x11" color=gray id="nv_parse_inner_ipv4-nv_parse_inner_udp"]
nv_parse_inner_ipv6 -> nv_parse_inner_icmpv6 [label="0x3a" color=gray id="nv_parse_inner_ipv6-nv_parse_inner_icmpv6"]
nv_parse_inner_ipv6 -> nv_parse_inner_tcp [label="0x6" color=gray id="nv_parse_inner_ipv6-nv_parse_inner_tcp"]
nv_parse_inner_ipv6 -> nv_parse_inner_udp [label="0x11" color=gray id="nv_parse_inner_ipv6-nv_parse_inner_udp"]
nv_parse_inner_mpls1 [label=inner_mpls1 id=nv_parse_inner_mpls1 style=filled]
nv_parse_inner_mpls -> nv_parse_inner_mpls1 [label="0x0" color=gray id="nv_parse_inner_mpls-nv_parse_inner_mpls1"]
nv_parse_inner_mpls_next_header [label=nv_parse_inner_mpls_next_header id=nv_parse_inner_mpls_next_header style=filled]
nv_parse_inner_mpls -> nv_parse_inner_mpls_next_header [label="0x1" color=gray id="nv_parse_inner_mpls-nv_parse_inner_mpls_next_header"]
nv_parse_inner_mpls2 [label=inner_mpls2 id=nv_parse_inner_mpls2 style=filled]
nv_parse_inner_mpls1 -> nv_parse_inner_mpls2 [label="0x0" color=gray id="nv_parse_inner_mpls1-nv_parse_inner_mpls2"]
nv_parse_inner_mpls1 -> nv_parse_inner_mpls_next_header [label="0x1" color=gray id="nv_parse_inner_mpls1-nv_parse_inner_mpls_next_header"]
nv_parse_inner_mpls3 [label=inner_mpls3 id=nv_parse_inner_mpls3 style=filled]
nv_parse_inner_mpls2 -> nv_parse_inner_mpls3 [label="0x0" color=gray id="nv_parse_inner_mpls2-nv_parse_inner_mpls3"]
nv_parse_inner_mpls2 -> nv_parse_inner_mpls_next_header [label="0x1" color=gray id="nv_parse_inner_mpls2-nv_parse_inner_mpls_next_header"]
nv_parse_inner_mpls4 [label=inner_mpls4 id=nv_parse_inner_mpls4 style=filled]
nv_parse_inner_mpls3 -> nv_parse_inner_mpls4 [label="0x0" color=gray id="nv_parse_inner_mpls3-nv_parse_inner_mpls4"]
nv_parse_inner_mpls3 -> nv_parse_inner_mpls_next_header [label="0x1" color=gray id="nv_parse_inner_mpls3-nv_parse_inner_mpls_next_header"]
nv_parse_inner_mpls4 -> nv_parse_inner_mpls_next_header [label="0x1" color=gray id="nv_parse_inner_mpls4-nv_parse_inner_mpls_next_header"]
nv_parse_inner_mpls_next_header -> nv_parse_inner_ipv4 [label="0x4" color=gray id="nv_parse_inner_mpls_next_header-nv_parse_inner_ipv4"]
nv_parse_inner_mpls_next_header -> nv_parse_inner_ipv6 [label="0x6" color=gray id="nv_parse_inner_mpls_next_header-nv_parse_inner_ipv6"]
nv_parse_inner_vlan -> nv_parse_inner_ipv4 [label="0x800" color=gray id="nv_parse_inner_vlan-nv_parse_inner_ipv4"]
nv_parse_inner_vlan -> nv_parse_inner_ipv6 [label="0x86dd" color=gray id="nv_parse_inner_vlan-nv_parse_inner_ipv6"]
nv_parse_inner_vlan -> nv_parse_inner_mpls [label="0x8847" color=gray id="nv_parse_inner_vlan-nv_parse_inner_mpls"]
nv_parse_ipsec_esp [label=esp id=nv_parse_ipsec_esp style=filled]
nv_parse_ipv4 -> nv_parse_inner_ipv4 [label="0x4" color=gray id="nv_parse_ipv4-nv_parse_inner_ipv4"]
nv_parse_ipv4 -> nv_parse_inner_ipv6 [label="0x29" color=gray id="nv_parse_ipv4-nv_parse_inner_ipv6"]
nv_parse_ipv4 -> nv_parse_icmp [label="0x1" color=gray id="nv_parse_ipv4-nv_parse_icmp"]
nv_parse_tcp [label=tcp id=nv_parse_tcp style=filled]
nv_parse_ipv4 -> nv_parse_tcp [label="0x6" color=gray id="nv_parse_ipv4-nv_parse_tcp"]
nv_parse_udp [label=udp id=nv_parse_udp style=filled]
nv_parse_ipv4 -> nv_parse_udp [label="0x11" color=gray id="nv_parse_ipv4-nv_parse_udp"]
nv_parse_ipv4 -> nv_parse_gre [label="0x2f" color=gray id="nv_parse_ipv4-nv_parse_gre"]
nv_parse_ipv4 -> nv_parse_ipsec_esp [label="0x32" color=gray id="nv_parse_ipv4-nv_parse_ipsec_esp"]
nv_parse_ipv6 -> nv_parse_inner_ipv4 [label="0x4" color=gray id="nv_parse_ipv6-nv_parse_inner_ipv4"]
nv_parse_ipv6 -> nv_parse_inner_ipv6 [label="0x29" color=gray id="nv_parse_ipv6-nv_parse_inner_ipv6"]
nv_parse_ipv6 -> nv_parse_icmpv6 [label="0x3a" color=gray id="nv_parse_ipv6-nv_parse_icmpv6"]
nv_parse_ipv6 -> nv_parse_tcp [label="0x6" color=gray id="nv_parse_ipv6-nv_parse_tcp"]
nv_parse_ipv6 -> nv_parse_udp [label="0x11" color=gray id="nv_parse_ipv6-nv_parse_udp"]
nv_parse_ipv6 -> nv_parse_gre [label="0x2f" color=gray id="nv_parse_ipv6-nv_parse_gre"]
nv_parse_ipv6 -> nv_parse_ipsec_esp [label="0x32" color=gray id="nv_parse_ipv6-nv_parse_ipsec_esp"]
nv_parse_mpls1 [label=mpls1 id=nv_parse_mpls1 style=filled]
nv_parse_mpls -> nv_parse_mpls1 [label="0x0" color=gray id="nv_parse_mpls-nv_parse_mpls1"]
nv_parse_mpls_next_header [label=nv_parse_mpls_next_header id=nv_parse_mpls_next_header style=filled]
nv_parse_mpls -> nv_parse_mpls_next_header [label="0x1" color=gray id="nv_parse_mpls-nv_parse_mpls_next_header"]
nv_parse_mpls2 [label=mpls2 id=nv_parse_mpls2 style=filled]
nv_parse_mpls1 -> nv_parse_mpls2 [label="0x0" color=gray id="nv_parse_mpls1-nv_parse_mpls2"]
nv_parse_mpls1 -> nv_parse_mpls_next_header [label="0x1" color=gray id="nv_parse_mpls1-nv_parse_mpls_next_header"]
nv_parse_mpls3 [label=mpls3 id=nv_parse_mpls3 style=filled]
nv_parse_mpls2 -> nv_parse_mpls3 [label="0x0" color=gray id="nv_parse_mpls2-nv_parse_mpls3"]
nv_parse_mpls2 -> nv_parse_mpls_next_header [label="0x1" color=gray id="nv_parse_mpls2-nv_parse_mpls_next_header"]
nv_parse_mpls4 [label=mpls4 id=nv_parse_mpls4 style=filled]
nv_parse_mpls3 -> nv_parse_mpls4 [label="0x0" color=gray id="nv_parse_mpls3-nv_parse_mpls4"]
nv_parse_mpls3 -> nv_parse_mpls_next_header [label="0x1" color=gray id="nv_parse_mpls3-nv_parse_mpls_next_header"]
nv_parse_mpls4 -> nv_parse_mpls_next_header [label="0x1" color=gray id="nv_parse_mpls4-nv_parse_mpls_next_header"]
nv_parse_mpls_next_header -> nv_parse_ipv4 [label="0x4" color=gray id="nv_parse_mpls_next_header-nv_parse_ipv4"]
nv_parse_mpls_next_header -> nv_parse_ipv6 [label="0x6" color=gray id="nv_parse_mpls_next_header-nv_parse_ipv6"]
nv_parse_nvgre_vsid -> nv_parse_inner_ethernet [label="0x0" color=gray id="nv_parse_nvgre_vsid-nv_parse_inner_ethernet"]
nv_parse_psp [label=psp id=nv_parse_psp style=filled]
parse_gtp [label=gtpv1 id=parse_gtp style=""]
nv_parse_udp -> parse_gtp [label="0x868" color=black id="nv_parse_udp-parse_gtp"]
nv_parse_vxlan [label=vxlan id=nv_parse_vxlan style=filled]
nv_parse_udp -> nv_parse_vxlan [label="0x12b5" color=gray id="nv_parse_udp-nv_parse_vxlan"]
nv_parse_vxlan_gpe [label=vxlan_gpe id=nv_parse_vxlan_gpe style=filled]
nv_parse_udp -> nv_parse_vxlan_gpe [label="0x12b6" color=gray id="nv_parse_udp-nv_parse_vxlan_gpe"]
nv_parse_udp -> nv_parse_geneve [label="0x17c1" color=gray id="nv_parse_udp-nv_parse_geneve"]
nv_parse_udp -> nv_parse_inner_mpls [label="0x19eb" color=gray id="nv_parse_udp-nv_parse_inner_mpls"]
nv_parse_udp -> nv_parse_ipsec_esp [label="0x1194" color=gray id="nv_parse_udp-nv_parse_ipsec_esp"]
nv_parse_udp -> nv_parse_psp [label="0x3e8" color=gray id="nv_parse_udp-nv_parse_psp"]
nv_parse_vlan -> nv_parse_ipv4 [label="0x800" color=gray id="nv_parse_vlan-nv_parse_ipv4"]
nv_parse_vlan -> nv_parse_ipv6 [label="0x86dd" color=gray id="nv_parse_vlan-nv_parse_ipv6"]
nv_parse_vlan -> nv_parse_mpls [label="0x8847" color=gray id="nv_parse_vlan-nv_parse_mpls"]
nv_parse_vxlan -> nv_parse_inner_ethernet [label="0x0" color=gray id="nv_parse_vxlan-nv_parse_inner_ethernet"]
nv_parse_vxlan_gpe -> nv_parse_inner_ipv4 [label="0x1" color=gray id="nv_parse_vxlan_gpe-nv_parse_inner_ipv4"]
nv_parse_vxlan_gpe -> nv_parse_inner_ipv6 [label="0x2" color=gray id="nv_parse_vxlan_gpe-nv_parse_inner_ipv6"]
nv_parse_vxlan_gpe -> nv_parse_inner_ethernet [label="0x3" color=gray id="nv_parse_vxlan_gpe-nv_parse_inner_ethernet"]
}
p4dt-dpu$ p4nspect graph --parser --url
Running this command generates a HTTP url link to the program's parser graph (shown above) in dot format, rendered using https://dreampuf.github.io/GraphvizOnline/#digraph%20example%0A%7B%0A%7D%0A
Illustration
It is possible to render the graph to get the following picture:
Commands and Flags Summary
Some of the flags are universally applicable to all of the commands, but some are applicable to only specific commands. The following table outlines which commands and which flags relate
|
|
system-info |
devices |
counters |
tables |
query |
graph |
hw-steering |
debug |
|---|---|---|---|---|---|---|---|---|
|
--address |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--time-out |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--non-interactive |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--no-hints |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--csv |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--json |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--device-ids |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--low-level |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
✔ |
|
--table-ids |
|
|
✔ |
✔ |
✔ |
|
|
|
|
--table_names |
|
|
✔ |
✔ |
✔ |
|
|
|
|
--counter-names |
|
|
✔ |
|
|
|
|
|
|
--show-unused |
|
|
✔ |
|
|
|
|
|
|
--indices |
|
|
✔ |
|
|
|
|
|
|
--top-packets |
|
|
✔ |
|
|
|
|
|
|
--top-bytes |
|
|
✔ |
|
|
|
|
|
|
--url |
|
|
|
|
|
✔ |
|
|
|
--parser |
|
|
|
|
|
✔ |
|
|
|
--output-file |
|
|
|
|
|
|
|
✔ |
|
--debug-device-id |
|
|
|
|
|
|
|
✔ |
P4 Debugger Description
An offline debugger, that is, it records the passage of traffic packets throughout a P4 program's pipeline and lets the developer trace the details of each packet's course using an interactive graphic UI.
P4 Debugger Execution
Running p4debugger with no additional arguments will open the GUI application.
Opening and debugging a pre-caught debug session can be done using the `File` menu of by specifying the debug session file in the program execution command as follows:
p4debugger my-debug-archive.tar.gz
P4 Debugger User Manual
File Menu
Select the File → Open Debug Session File and choose the appropriate <p4-debug-file>.tar.gz in this example hello_packet.tar.gz.
The file will load.
Packet List
On the left pane users can see the Packets list. The packet list exposes the following fields:
-
ID – this is the packet's unique identifier.
-
Date Time – the time it entered the p4 pipeline.
-
Time Since Start – time since the first packet entered the p4 pipeline.
-
Size – packet size
-
Ingress Port
Filter
To filter out packets use the fields at the bottom left of the screen.
For example: "packet ID is not 0".
Press the + button and then the Apply button
Press the "Clear All" button.
A converse filter example: "packet ID is 0" again pressing the + and then the Apply buttons
Parser Graph
The middle section of the screen there is the parser graph
It outlines the route a packet can take. The purple nodes (such as "ethernet" above) indicate the node it traversed. It consists of both flex nodes which the p4 programmer instigated and static (fixed) nodes which are inherent part of the hardware.
Pipeline Stages
Selecting a packet from the Packets list will display the selected packet's pipeline stages.
Each row in the pipeline stages correlates to a single source location point in the p4 program code.
Cells in the table are interactable, selecting a cell will mark the relevant source location when applicable.
Variables
Selecting a pipeline stage (a single cell or the whole row) will display variable information in two different tabs.
-
The "Variables" tab shows p4 variables defined in the program and their values in the current pipeline stage.
-
The "Raw" tab shows a deeper dive into the low level variables (e.g., registers, samplers, etc.)
Source Code
Selecting a cell in a pipeline stage will open the p4 program in a new tab, marking the relevant source location when applicable.
The debugger seeks the p4 source file using the search paths defined in the Settings or by browsing manually for the file.
Log
The log window pane is on the left side. It shows the internal logs of the nvp4agent.
System-info
Packet Dissector
Selecting a pipeline stage will dissect the packet.
Hex Dump
Selecting a pipeline stage will show a raw hexdump of the packet.
Options
The File->Preferences menu will open the Preferences window.
Here you can set different settings related to the debugger and the debug session.
Last updated: