2.7 KiB
TLV parsing of IPv4 options
Description
This program illustrates how to parse IPv4 options with bmv2. There is a very easy way to parse IPv4 options in P4 using a single variable length field. However, this means that options are not parsed individually, but together, as one block. All the options are parsed to a single field, which is fine for many use cases but can be insufficient in some. In this example, we use TLV parsing to parse all options separately to their own header instance.
The program is quite straightforward. The following IPv4 options are supported:
- end of list
- no-op
- security
- timestamp
There is one important caveat: when compiling the P4 program, a strict ordering
of all packet headers has to be known. This is usually done by inspecting the
parse graph and running a topological sorting algorithm on it. However this
algorithm will not work if there exists loops in the header graph, as is the
case with TLV parsing. There is not yet an official way of enforcing your own
header ordeing in the P4 program, so we had to bypass this restriction by using
a @pragma
, as you can see in the code:
@pragma header_ordering ethernet ipv4_base ipv4_option_security ipv4_option_NOP ipv4_option_timestamp ipv4_option_EOL
This @pragma
instruction will be interpreted by the P4 -> bmv2 compiler.
This order is used by the deparser, when sending a packet out of the egress port, which means that the option layout for the outgoing packet may not be the same as for the incoming packet.
The table format_options
makes sure that the IPv4 header is formatted
correctly in the outgoing packet.
Note that the P4 program assumes the incoming packet is correctly formatted. We do not perform any sanity checking because parser execptions are not yet supported by bmv2.
So in a nutshell, all this P4 program does is:
- parse the IPv4 options for the incoming packet
- re-serialize the packet again, with a potentially different order for options
Running the demo
We provide a small demo to let you test the program. It consists of the following scripts:
- [run_switch.sh] (run_switch.sh): compile the P4 program and starts the switch, also configures the data plane by running the CLI [commands] (commands.txt).
- [send_one.py] (send_one.py): send an IPv4 packet with options
To run the demo:
- start the switch and configure the tables:
sudo ./run_switch.sh
. - run the Python script:
sudo python send_one.py
.
Then inspect the pcap
file for port 0 of the switch (veth0.pcap
) with
Wireshark. You will observe that the order of the IPv4 options has changed but
that the outgoing packet contains all the options of the incoming packet and is
perfectly valid (with a correct checksum).