2015-10-23 12:20:29 -07:00

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:

  1. parse the IPv4 options for the incoming packet
  2. 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).