Project 3
This project includes 2 exercises: Source Routing and Key-Value Store. You will need to use the P4 language spec1 and the P4 language cheat sheet2 as references. Source Routing asks you to write a P4 program to implement a custom source routing protocol. Key-Value Store asks you to write a P4 program to implement a key-value store in the switch. We use P4_16 in this assignment. Both exercises could be completed with the VM we used in the P4 tutorial class.
Exercise 1: Source Routing
In this exercise, we will implement a very simple source routing protocol in P4. We will call this protocol EasyRoute. You will be designing the P4 program from scratch. To test your implementation, a Mininet network needs to be established to allow messages being sent between hosts, which is already implemented and provided for you by run_demo.py.
Your tasks include:
1. implementingtheTODOsintheprovidedskeletonprogram: assignment3_src/source_routing/source_routing.p4
2. fill`table_entries`ins*-runtime.jsonifyouusetablesinyourp4 program
No other files need to be changed for this exercise. After implementing your code,
1. In your shell, run:
make run
This will compile your source_routing.p4 and bring up switches in a Mininet topology
1 https://p4.org/p4-spec/docs/P4-16-v1.1.0-draft.html
2 https://drive.google.com/file/d/1Z8woKyElFAOP6bMd8tRa_Q4SA1cd_Uva/view
2. You should now see a Mininet command prompt. Open two terminals for two hosts, e.g. h1 and h2.
mininet> xterm h1 h2
3. EachhostincludesasmallPython-basedmessagingprogram.Inh2s
terminal, start the receiving process:
Then you should be able to see the following screenshot:
Then type any message (e.g. ) to send to h2. In h2s xterm, you will observe the message received by as following if the source routing protocol is implemented correctly in your program.
Description of the EasyRoute protocol
The EasyRoute packets have the following formats:
The preamble is always set to 0. You can use this to distinguish the EasyRoute packets from other packets (Ethernet frames) your switch may receive. We do not guarantee that your P4 switch will exclusively receive EasyRoute packets. Only EasyRoute packets should be forwarded.
4. In
./receive.py h2-eth0
h1
s xterm, send a message to
./send.py h1 h2
h2
:
root@p4:~/assignment3_src/source_routing# ./send.py h1 h2
WARNING: No route found for IPv6 destination :: (no default route?) path is: [h1, s1, s2, h2]
port list is: [2, 1]
What do you want to send:
p4 is cool
root@p4:~/assignment3_src/source_routing# ./receive.py h2-eth0 WARNING: No route found for IPv6 destination :: (no default route?) p4 is cool
h2
preamble
num_valid
port_1
port_2
port_n
payload
8 bytes
4 bytes
1 byte
1 byte
The num_valid field indicates the number of valid ports in the header. If your EasyRoute packet is to traverse 3 switches, num_valid will initially be set to 3, and the port list will be 3 byte long. When a switch receives an EasyRoute packet, the first port of the list is used to determine the outgoing port for the packet. num_valid is then decremented by 1 and the first port is removed from the list.
We will use the EasyRoute protocol to send text messages. The payload will therefore correspond to the text message we are sending. You do not have to worry about the encoding of the text message.
Example using EasyRoute
To send message p4 is cool from h1 to h3, the EasyRoute packet will look like this:
when it leaves h1: 00000000 00000000|00000002 | 03 | 01 | p4 is cool : 00000000 00000000|00000001 | 01 | p4 is cool
: 00000000 00000000|00000000 | p4 is cool
when it leaves
sw1
when it leaves
sw3
Note that the last switch should not remove the EasyRoute header; otherwise the application running in the end hosts wont be able to handle incoming packets properly.
Your P4 implementation needs to adhere to the following requirements:
1. all non-EasyRoute packets should be dropped
2. if a switch receives an EasyRoute packet for which num_valid is 0, the packet should be dropped
NOTE: EasyRoute protocol is different from the source_routing exercise in the P4 tutorial. In the tutorial, MAX_HOPS is used to maintain the next-hop list. You are NOT allowed to use MAX_HOPS in your implementation.
Hints
1. In the start parse state, you can use lookahead to check if the packet is an EasyRoute packet. A call to lookahead
2. A table can match on an empty key, which means the default action will always be executed if configured correctly by the runtime. Just omit the key attribute to achieve this.
3. When parsing the EasyRoute header, you do not have to parse the whole port list. Hence youll need to simply extract the first port of the list and ignore the rest (including the payload).
Also, preamble, num_valid and the port number dont have to all be placed in the same header type.
4. If you use tables in your program, you need to populate the table entries in s*- runtime.json.
Exercise 2: Key-Value Store
A key-value store is a storage service. Each item in the key-value store has a key, which is the name of the item, and a value, which is the actual content of the item. A key-value store provides two basic functions: get(key) and put(key, value). The function get(key) gets the value of the corresponding key from the key-value store.
The function put(key, value) updates the value of the corresponding in the key- value store.
Your tasks include:
1. implementingtheTODOsintheprovidedskeletonprogram: assignment3_src/kv/kv.p4
2. fill`table_entries`ins*-runtime.jsonifyouusetablesinyourp4 program
3. completekv.pytoissueputandgetqueriestosw1
You will implement a key-value store in the switch with P4. The key-value packets
are similar with the EasyRoute packets as following:
The preamble is always set to 1. You can use this to distinguish the key-value packets from other packets (EasyRoute packets and Ethernet frames) your switch may receive. We do not guarantee that your P4 switch will exclusively receive EasyRoute packets.
The type field indicates the type of the query, which can be 0 (get request), 1 (put request), 2 (get reply), and 3 (put reply). The key and value field contain the key and value of an item, respectively.
Example of Key-Value comands
For a get query, the type field should be 0 and the key field contains the key for the queried item. The value field is not meaningful. The switch should update the type field to 2 and update the value field based on the value stored in the switch. Then the switch sends the packet back to the sender as the response. (Switch needs to check whether the requested key matches the key in the key-value store)
For a put query, the type field should be 1, the key field should contain the key for the queried item, and the value field should contain the new value of the item.
preamble
num_valid
port
type
key
value
8 bytes
4 bytes
1 byte
1 byte
4 bytes
4 bytes
The switch should update its key-value store with the new value, update the type field to 3, and then send the packet back to the sender as the response. (Switch simply overwrites the (key, value) without examining key)
To make it simple, you do not need to implement sophisticated routing in this assignment. You can assume that the client is directly connect to the switch, and the switch simply sends the packet to the ingress port to reply to the client.
You can use part of the code in EasyRoute and implement the key-value store functionality. Set the size of the key-value store in the switch to be 1000.
After implementing your code, 1. In your shell, run:
make run
This will compile your kv.p4 and bring up switches in a Mininet topology
2. You should now see a Mininet command prompt. Open two terminals for
host h1.
mininet> xterm h1 h1
3. In one of the terminals, start the receiving process:
./receive.py h1-eth0
4. In the other xterm, start kv.py:
./kv.py
you should be able to issue the get and put query with commands put [key] [value] and get [key], for example put 1 11 and get 1. Refer assignment3_src/send.py to implement kv.py.
Hints
1. Essentially, key-value stores are implemented with hash tables. You will need stateful objects, i.e. register, in this exercise. Maintain both key and value in your key-value store.
2. You can assume the key and value are both integers. Calculate hash value over key as the array index to access register. Also, assume all valid values are non- zero, thus value being 0 in the get response packet could be used to indicate that the requested key does not exist.
Submission
Submit your code in a zip or tarball file to Canvas.
DUE: Dec 12th 11:59 pm ET
Reviews
There are no reviews yet.