[P4-dev] Parse/process dynamic payload

cs.lev cs.lev at gmx.com
Mon Oct 8 08:20:34 EDT 2018

Hi all,

I am (still) playing with P4's capability to modify/monitor the payload
in a packet. According to some sources I have found here and on the
github, I quickly created a simple P4 application that prints out the
processed packet's data, i.e., header information from layer 2 to layer
Source code is here:

Logging is based on debug tables and exact matches on the different
fields of the header.
(debug tables can be enabled by `#define` conditions in the beginning
of the source code - now IP/TCP is enabled for ingress processing.

I have encountered that if I further define a couple of bytes to parse
in the header, i.e., when I read the payload, for instance, 2 bytes
after the TCP options field, I became able to match on those specific
bytes as well.
However, if the payload is shorter than 2-bytes, the whole packet and
its headers are treated as a corrupted packet and monitoring (or even a
TCP header based routing) is not working.

In particular, assume I have a TCP netcat connection between two hosts,
and the client sends two characters, say, two 'a' (which is 2 bytes + 1
byte EOL character) then parsing is working well and I can see the
following in the console:
* standard_metadata.ingress_port: 0000
* meta.tcp_metadata.tcp_len     : 0029
* hdr.tcp.srcPort               : da2e
* hdr.tcp.dstPort               : 115c
* hdr.tcp.seqNo                 : 76dc4b4b
* hdr.tcp.ackNo                 : 8dcbb939
* hdr.tcp.dataOffset            : 08
* hdr.tcp.flags_1               : 00
* hdr.tcp.flags_2               : 01
* hdr.tcp.flags_3               : 08
* hdr.tcp.window                : 00e5
* hdr.tcp.checksum              : 5ffa
* hdr.tcp.urgentPtr             : 0000
* hdr.tcp.payload               : 6161

However, if I only send an empty character with the 1-byte EOL
character (0x0a) summing up only 1-byte payload, then not just the
payload parsing "crashes in some sense" but I get the following output:
* standard_metadata.ingress_port: 0000
* meta.tcp_metadata.tcp_len     : 0000
* hdr.tcp.srcPort               : 0000
* hdr.tcp.dstPort               : 0000
* hdr.tcp.seqNo                 : 00000000
* hdr.tcp.ackNo                 : 00000000
* hdr.tcp.dataOffset            : 00
* hdr.tcp.flags_1               : 00
* hdr.tcp.flags_2               : 00
* hdr.tcp.flags_3               : 00
* hdr.tcp.window                : 0000
* hdr.tcp.checksum              : 0000
* hdr.tcp.urgentPtr             : 0000
* hdr.tcp.payload               : 0000

Of course, this always happens for the ACK messages back from the
server as there is no payload at all.

Furthermore, hdr.tcp.isValid() function also fails - I guess because it
validates the header according to my specification, which should
contain the 2-byte big payload as well.
I can overcome this by having a condition on the ipv4.protocol field
instead if I want to catch TCP packets, but still the TCP header
information in the debug tables show zeros.

Is there any way to overcome this?
Maybe putting payload related part into metadata and parse that part
with lookahead() functions? Would it even work with dynamic payload


More information about the P4-dev mailing list