Simple debugging procedures for P4 programming exercises - grupogita/ONOSP4-tutorial GitHub Wiki
Debugging is a vital task for any programming exercise in any language. Having mechanisms to check the values of variables either directly assigned or obtained during the program execution is quite important in order to validate the correct processing flow of the program logic.
Due to its nature, P4 lacks of expressive mechanisms to perform execution debugging. The language does not have things such as print/printf functions or logging factories that enable to print variables in arbitrary formats. Nevertheless, it is possible to have an approximation to check the values of the variables in order to verify that program executions is working as desired.
According to P4 documentation there are two options that can be followed. These options output information to the switch log file and help to determine specially how match/action artifacts are operating.
Dummy debug tables
The first debugging mechanism consists in creating dummy debug tables. These tables have two main properties:
- As keys, the developer may use any field: Protocol header fields, metadata fields, variables.
- As action, no action is to be defined. That is, the action block of the table remains empty.
Next, there is an example of a dummy debug table to show the values of the standard 5-tuple defining an IP flow, assuming that the corresponding fields have been previously defined
table debug_flow {
key = {
hdr.ipv4.src_ip: exact;
hdr.ipv4.dst_ip: exact;
hdr.ipv4.protocol: exact;
hdr.tcp.src_port: exact;
hdr.tcp.dst_port: exact;
local_metadata.flow_id: exact
}
actions = {
}
After the definiton of this table, the way to generate the log is simply applying this table at the desired point of the program (e.g. Ingress or Egress Pipelines).
apply {
....
if(hdr.ipv4.isValid()) {
...
debug_flow.apply();
This will cause that the corresponding values defined in the key will be printed as debug messages in the switch logfile, provided that the switch has been started with debug level. This can be done by changing the loglevel parameter in the stratum2.py file which defines the StratumBmv2Switch wrapper class used for the mininet integration. This log file, by default, is located at /tmp/XX/stratum_bmv2.log where XX corresponds to the name of the switch as passed through the mininet topology file.
At the log file, there should be some lines similar to the following ones:
[17:05:26.580] [bmv2] [D] [thread 6453] [79.0] [cxt 0] Looking up key:
* hdr.ipv4.src_addr : 0a000103
* hdr.ipv4.dst_addr : 0a000102
* hdr.ipv4.protocol : 6
* hdr.tcp.src_port : 8000
* hdr.tcp.dst_port : 50
* local_metadata.flow_id: 0000
[17:05:26.580] [bmv2] [D] [thread 6453] [79.0] [cxt 0] Table 'IngressPipeImpl.debug_flow': miss
Log messages
Another simple mechanism that can be used to generate logs helping to debug P4 programs is introducing log messages. These messages are simple strings containing the values of the variables that need to be printed. For the insertion of these messages, the programmer can use the log_msg function. Below, it is shown an example of such log message for some of the variables used in the previous example:
if(hdr.ethernet.isValid() && hdr.ipv4.isValid()){
...
l2_exact_table.apply();
log_msg("After L2_EXACT_TABLE: SRCIP {}, DSTIP {}, OUTPORT {}", {hdr.ipv4.src_addr, hdr.ipv4.dst_addr, standard_metadata.egress_spec});
...
}
The log message will appear within the switch log file, which by default, is located at /tmp/XX/stratum_bmv2.log where XX corresponds to the name of the switch as passed through the mininet topology file.
[17:09:59.179] [bmv2] [I] [thread 6453] After L2_EXACT_TABLE: SRCIP 0a000001, DSTIP 0a00000a, OUTPORT 1
Notes
- Log level of the switch, which by default is INFO would only display the messages generated with the log_msg function. For messages generated with dummy tables, log level needs to be increased to at least DEBUG in the mininet topology file, when instantiating the switch.
- Generation of log files should be used only during development, and it should be disabled when executing experiments or simulations.
- If switch is left running during a long time, specially with log level set to DEBUG or TRACE, you must be aware of avoding a disk filling.
- Numerical values are presented as HEX values.
Across the exercises of this tutorial, you might find some useful examples of debugging. You can take these examples as starting point in order to create your own configurations.