# 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).