Adding in a P4 example that implements the Axon source-routed Ethernet protocol.
This commit is contained in:
102
examples/axon/README.md
Normal file
102
examples/axon/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Axon source routing protocol
|
||||
|
||||
## Description
|
||||
|
||||
This program implements the Axon protocol for source-routed Ethernet
|
||||
described in the ANCS '10 paper "Axon: A Flexible Substrate for
|
||||
Source-routed Ethernet". The most notable aspect of the Axon protocol
|
||||
is that, in addition to maintaining a list of forward hops, it also
|
||||
builds a list of the input ports the packet was received on. Together,
|
||||
these hops define a reverse path to the source that uses the same links
|
||||
as the forward path.
|
||||
|
||||
More specifically, the Axon header format is as follows:
|
||||
|
||||
| | | | | | |
|
||||
|---|---|---|---|---|---|
|
||||
| AxonType : 8 | AxonHdrLength : 16 | FwdHopCount : 8 | RevHopCount : 8 | [FwdHops : 8] | [RevHops : 8] |
|
||||
| | | | | | |
|
||||
|
||||
Note that the number of bits per field both shown above and used in this
|
||||
program are different from those described in the Axon ANCS '10 paper.
|
||||
Specifically, the width of the AxonType, FwdHopCount, and RevHopCount
|
||||
fields have been rounded up to the nearest multiple of 8.
|
||||
|
||||
Upon receiving an Axon packet, an Axon switch performs three operations:
|
||||
|
||||
1. It validates the header length matches the described number of
|
||||
forward hops and reverse hops (and is less than a maximum length).
|
||||
2. It pushes the input port of the packet onto the list of reverse hops
|
||||
and increments the reverse hop count.
|
||||
3. It pops the head off of the list of forward hops, decrements the
|
||||
forward hop count, and then uses this port as an output port for the
|
||||
packet.
|
||||
|
||||
This program implements a switch that only performs these three operations.
|
||||
|
||||
As an example, this program builds upon the P4 concepts introduced by
|
||||
the EasyRoute protocol, adding in simple TLV processing. Similar to
|
||||
EasyRoute, the Axon protocol pops the next hop it should follow off of a
|
||||
list and decrements a header field. However, the EasyRoute program can
|
||||
avoid TLV parsing by only parsing up to the first hop of the source
|
||||
route and then removing it. On the other hand, the Axon protocol also
|
||||
requires that the input port of a packet is pushed onto a list. This
|
||||
means that at the list of forward hops must be parsed. Because this list
|
||||
may be variable in length, this program must perform simple TLV parsing.
|
||||
However, unlike parsing an IP header, this TLV example is not
|
||||
complicated by issues related to ordering packet headers. Additionally,
|
||||
this program parses the reverse hops of the Axon header, even though
|
||||
they do not strictly need to be if only Axon forwarding is performed,
|
||||
i.e., subsequent packet headers do not need to be parsed.
|
||||
|
||||
Note that the header stacks parsed in this program (`axon_fwdHop` and
|
||||
`axon_revHop`) can only hold 64 entries, even though the parser could
|
||||
try to parse up to 256 entries (8 bits). This is because of a
|
||||
limitation in `p4c-bmv2/p4c_bm/gen_json.py`. If stack sizes of 256 are
|
||||
used, the script stalls for an extended period of time then generates
|
||||
the following error: `RuntimeError: maximum recursion depth exceeded`.
|
||||
|
||||
Because of this error and because *parser exceptions* are not yet
|
||||
supported by bmv2, improperly formatted packets can cause simple\_switch
|
||||
to crash. In practice, this occurs when IPv6 discovery packets are
|
||||
received. In order to avoid this problem, like EasyRoute, this program
|
||||
also adds a 64bit preamble to the start of packets and requires that
|
||||
this preamble equals 0. However, this only mitigates the problem. A
|
||||
carefully crafted packet could still exceed the header stack of 64
|
||||
entries.
|
||||
|
||||
### Running the demo
|
||||
|
||||
We provide a small demo to let you test the program. It consists of the
|
||||
following scripts:
|
||||
- [run_demo.sh] (run_demo.sh): compiles the P4 program, starts the switch,
|
||||
configures the data plane by running the CLI [commands]
|
||||
(commands.txt), and starts the mininet console.
|
||||
- [receive.py] (receive.py): listens for Axon formatted packets. This
|
||||
command is intended to be run by a mininet host.
|
||||
- [send.py] (send.py): sends Axon formatted packets from one host to
|
||||
another. This command is intended to be run by a mininet host.
|
||||
|
||||
To run the demo:
|
||||
./run_demo.sh will compile your code and create the Mininet network described
|
||||
above. It will also use commands.txt to configure each one of the switches.
|
||||
Once the network is up and running, you should type the following in the Mininet
|
||||
CLI:
|
||||
|
||||
- `xterm h1`
|
||||
- `xterm h3`
|
||||
|
||||
This will open a terminal for you on h1 and h3.
|
||||
|
||||
On h3 run: `./receive.py`.
|
||||
|
||||
On h1 run: `./send.py h1 h3`.
|
||||
|
||||
You should then be able to type messages on h1 and receive them on h3. The
|
||||
`send.py` program finds the shortest path between h1 and h3 using Dijkstra, then
|
||||
send correctly-formatted packets to h3 through s1 and s3. Once you are
|
||||
done testing, quit mininet. .pcap files will be generated for every
|
||||
interface (9 files: 3 for each of the 3 switches). You can look at the
|
||||
appropriate files and check that packets are being processed correctly,
|
||||
e.g., the forward hops and reverse hops are updated appropriately and
|
||||
the correct output and input ports are used.
|
||||
Reference in New Issue
Block a user