63 lines
2.7 KiB
Markdown
63 lines
2.7 KiB
Markdown
# 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).
|