Skip to content

Commit 97f3156

Browse files
robh2Nate Foster
authored andcommitted
Adding P4D2_2018_East Folder (#116)
* Copying P4D2 Fall 2017 into P4D2 2018 East. * Updated P4D2_2018_East VM. Added vagrant URL workaround, cdrom to VM. Updated to latest commits of BMV2, p4c, PI. Known issue with p4runtime exercise. * Applied patch from @antoninbas in and updated solution
1 parent 89277b5 commit 97f3156

103 files changed

Lines changed: 8930 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
4.73 MB
Binary file not shown.

P4D2_2018_East/exercises/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# P4 Tutorial
2+
3+
## Introduction
4+
5+
Welcome to the P4 Tutorial!
6+
7+
We've prepared a set of exercises to help you get started with P4
8+
programming, organized into four modules:
9+
10+
1. Introduction and Language Basics
11+
* [Basic Forwarding](./basic)
12+
* [Basic Tunneling](./basic_tunnel)
13+
14+
2. P4 Runtime and the Control Plane
15+
* [P4 Runtime](./p4runtime)
16+
17+
3. Monitoring and Debugging
18+
* [Explicit Congestion Notification](./ecn)
19+
* [Multi-Hop Route Inspection](./mri)
20+
21+
4. Advanced Data Structures
22+
* [Source Routing](./source_routing)
23+
* [Calculator](./calc)
24+
25+
5. Dynamic Behavior
26+
* [Load Balancing](./load_balance)
27+
28+
## Obtaining required software
29+
30+
If you are starting this tutorial at the Fall 2017 P4 Developer Day, then we've already
31+
provided you with a virtual machine that has all of the required
32+
software installed.
33+
34+
Otherwise, to complete the exercises, you will need to either build a
35+
virtual machine or install several dependencies.
36+
37+
To build the virtual machine:
38+
- Install [Vagrant](https://vagrantup.com) and [VirtualBox](https://virtualbox.org)
39+
- `cd vm`
40+
- `vagrant up`
41+
- Log in with username `p4` and password `p4` and issue the command `sudo shutdown -r now`
42+
- When the machine reboots, you should have a graphical desktop machine with the required
43+
software pre-installed.
44+
45+
To install dependencies by hand, please reference the [vm](../vm) installation scripts.
46+
They contain the dependencies, versions, and installation procedure.
47+
You can run them directly on an Ubuntu 16.04 machine:
48+
- `sudo ./root-bootstrap.sh`
49+
- `sudo ./user-bootstrap.sh`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include ../../utils/Makefile
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Implementing Basic Forwarding
2+
3+
## Introduction
4+
5+
The objective of this exercise is to write a P4 program that
6+
implements basic forwarding. To keep things simple, we will just
7+
implement forwarding for IPv4.
8+
9+
With IPv4 forwarding, the switch must perform the following actions
10+
for every packet: (i) update the source and destination MAC addresses,
11+
(ii) decrement the time-to-live (TTL) in the IP header, and (iii)
12+
forward the packet out the appropriate port.
13+
14+
Your switch will have a single table, which the control plane will
15+
populate with static rules. Each rule will map an IP address to the
16+
MAC address and output port for the next hop. We have already defined
17+
the control plane rules, so you only need to implement the data plane
18+
logic of your P4 program.
19+
20+
> **Spoiler alert:** There is a reference solution in the `solution`
21+
> sub-directory. Feel free to compare your implementation to the
22+
> reference.
23+
24+
## Step 1: Run the (incomplete) starter code
25+
26+
The directory with this README also contains a skeleton P4 program,
27+
`basic.p4`, which initially drops all packets. Your job will be to
28+
extend this skeleton program to properly forward IPv4 packets.
29+
30+
Before that, let's compile the incomplete `basic.p4` and bring
31+
up a switch in Mininet to test its behavior.
32+
33+
1. In your shell, run:
34+
```bash
35+
make run
36+
```
37+
This will:
38+
* compile `basic.p4`, and
39+
* start a Mininet instance with three switches (`s1`, `s2`, `s3`)
40+
configured in a triangle, each connected to one host (`h1`, `h2`,
41+
and `h3`).
42+
* The hosts are assigned IPs of `10.0.1.1`, `10.0.2.2`, and `10.0.3.3`.
43+
44+
2. You should now see a Mininet command prompt. Open two terminals
45+
for `h1` and `h2`, respectively:
46+
```bash
47+
mininet> xterm h1 h2
48+
```
49+
3. Each host includes a small Python-based messaging client and
50+
server. In `h2`'s xterm, start the server:
51+
```bash
52+
./receive.py
53+
```
54+
4. In `h1`'s xterm, send a message to `h2`:
55+
```bash
56+
./send.py 10.0.2.2 "P4 is cool"
57+
```
58+
The message will not be received.
59+
5. Type `exit` to leave each xterm and the Mininet command line.
60+
Then, to stop mininet:
61+
```bash
62+
make stop
63+
```
64+
And to delete all pcaps, build files, and logs:
65+
```bash
66+
make clean
67+
```
68+
69+
The message was not received because each switch is programmed
70+
according to `basic.p4`, which drops all packets on arrival.
71+
Your job is to extend this file so it forwards packets.
72+
73+
### A note about the control plane
74+
75+
A P4 program defines a packet-processing pipeline, but the rules
76+
within each table are inserted by the control plane. When a rule
77+
matches a packet, its action is invoked with parameters supplied by
78+
the control plane as part of the rule.
79+
80+
In this exercise, we have already implemented the the control plane
81+
logic for you. As part of bringing up the Mininet instance, the
82+
`make run` command will install packet-processing rules in the tables of
83+
each switch. These are defined in the `sX-commands.txt` files, where
84+
`X` corresponds to the switch number.
85+
86+
**Important:** A P4 program also defines the interface between the
87+
switch pipeline and control plane. The commands in the files
88+
`sX-commands.txt` refer to specific tables, keys, and actions by name,
89+
and any changes in the P4 program that add or rename tables, keys, or
90+
actions will need to be reflected in these command files.
91+
92+
## Step 2: Implement L3 forwarding
93+
94+
The `basic.p4` file contains a skeleton P4 program with key pieces of
95+
logic replaced by `TODO` comments. Your implementation should follow
96+
the structure given in this file---replace each `TODO` with logic
97+
implementing the missing piece.
98+
99+
A complete `basic.p4` will contain the following components:
100+
101+
1. Header type definitions for Ethernet (`ethernet_t`) and IPv4 (`ipv4_t`).
102+
2. **TODO:** Parsers for Ethernet and IPv4 that populate `ethernet_t` and `ipv4_t` fields.
103+
3. An action to drop a packet, using `mark_to_drop()`.
104+
4. **TODO:** An action (called `ipv4_forward`) that:
105+
1. Sets the egress port for the next hop.
106+
2. Updates the ethernet destination address with the address of the next hop.
107+
3. Updates the ethernet source address with the address of the switch.
108+
4. Decrements the TTL.
109+
5. **TODO:** A control that:
110+
1. Defines a table that will read an IPv4 destination address, and
111+
invoke either `drop` or `ipv4_forward`.
112+
2. An `apply` block that applies the table.
113+
6. **TODO:** A deparser that selects the order
114+
in which fields inserted into the outgoing packet.
115+
7. A `package` instantiation supplied with the parser, control, and deparser.
116+
> In general, a package also requires instances of checksum verification
117+
> and recomputation controls. These are not necessary for this tutorial
118+
> and are replaced with instantiations of empty controls.
119+
120+
## Step 3: Run your solution
121+
122+
Follow the instructions from Step 1. This time, your message from
123+
`h1` should be delivered to `h2`.
124+
125+
### Food for thought
126+
127+
The "test suite" for your solution---sending a message from `h1` to
128+
`h2`---is not very robust. What else should you test to be confident
129+
of your implementation?
130+
131+
> Although the Python `scapy` library is outside the scope of this tutorial,
132+
> it can be used to generate packets for testing. The `send.py` file shows how
133+
> to use it.
134+
135+
Other questions to consider:
136+
- How would you enhance your program to support next hops?
137+
- Is this program enough to replace a router? What's missing?
138+
139+
### Troubleshooting
140+
141+
There are several problems that might manifest as you develop your program:
142+
143+
1. `basic.p4` might fail to compile. In this case, `make run` will
144+
report the error emitted from the compiler and halt.
145+
146+
2. `basic.p4` might compile but fail to support the control plane
147+
rules in the `s1-commands.txt` through `s3-command.txt` files that
148+
`make run` tries to install using the Bmv2 CLI. In this case, `make run`
149+
will log the CLI tool output in the `logs` directory. Use these error
150+
messages to fix your `basic.p4` implementation.
151+
152+
3. `basic.p4` might compile, and the control plane rules might be
153+
installed, but the switch might not process packets in the desired
154+
way. The `/tmp/p4s.<switch-name>.log` files contain detailed logs
155+
that describing how each switch processes each packet. The output is
156+
detailed and can help pinpoint logic errors in your implementation.
157+
158+
#### Cleaning up Mininet
159+
160+
In the latter two cases above, `make run` may leave a Mininet instance
161+
running in the background. Use the following command to clean up
162+
these instances:
163+
164+
```bash
165+
make stop
166+
```
167+
168+
## Next Steps
169+
170+
Congratulations, your implementation works! In the next exercise we
171+
will build on top of this and add support for a basic tunneling
172+
protocol: [basic_tunnel](../basic_tunnel)!
173+
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/* -*- P4_16 -*- */
2+
#include <core.p4>
3+
#include <v1model.p4>
4+
5+
const bit<16> TYPE_IPV4 = 0x800;
6+
7+
/*************************************************************************
8+
*********************** H E A D E R S ***********************************
9+
*************************************************************************/
10+
11+
typedef bit<9> egressSpec_t;
12+
typedef bit<48> macAddr_t;
13+
typedef bit<32> ip4Addr_t;
14+
15+
header ethernet_t {
16+
macAddr_t dstAddr;
17+
macAddr_t srcAddr;
18+
bit<16> etherType;
19+
}
20+
21+
header ipv4_t {
22+
bit<4> version;
23+
bit<4> ihl;
24+
bit<8> diffserv;
25+
bit<16> totalLen;
26+
bit<16> identification;
27+
bit<3> flags;
28+
bit<13> fragOffset;
29+
bit<8> ttl;
30+
bit<8> protocol;
31+
bit<16> hdrChecksum;
32+
ip4Addr_t srcAddr;
33+
ip4Addr_t dstAddr;
34+
}
35+
36+
struct metadata {
37+
/* empty */
38+
}
39+
40+
struct headers {
41+
ethernet_t ethernet;
42+
ipv4_t ipv4;
43+
}
44+
45+
/*************************************************************************
46+
*********************** P A R S E R ***********************************
47+
*************************************************************************/
48+
49+
parser MyParser(packet_in packet,
50+
out headers hdr,
51+
inout metadata meta,
52+
inout standard_metadata_t standard_metadata) {
53+
54+
state start {
55+
/* TODO: add parser logic */
56+
transition accept;
57+
}
58+
}
59+
60+
61+
/*************************************************************************
62+
************ C H E C K S U M V E R I F I C A T I O N *************
63+
*************************************************************************/
64+
65+
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
66+
apply { }
67+
}
68+
69+
70+
/*************************************************************************
71+
************** I N G R E S S P R O C E S S I N G *******************
72+
*************************************************************************/
73+
74+
control MyIngress(inout headers hdr,
75+
inout metadata meta,
76+
inout standard_metadata_t standard_metadata) {
77+
action drop() {
78+
mark_to_drop();
79+
}
80+
81+
action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {
82+
/* TODO: fill out code in action body */
83+
}
84+
85+
table ipv4_lpm {
86+
key = {
87+
hdr.ipv4.dstAddr: lpm;
88+
}
89+
actions = {
90+
ipv4_forward;
91+
drop;
92+
NoAction;
93+
}
94+
size = 1024;
95+
default_action = NoAction();
96+
}
97+
98+
apply {
99+
/* TODO: fix ingress control logic
100+
* - ipv4_lpm should be applied only when IPv4 header is valid
101+
*/
102+
ipv4_lpm.apply();
103+
}
104+
}
105+
106+
/*************************************************************************
107+
**************** E G R E S S P R O C E S S I N G *******************
108+
*************************************************************************/
109+
110+
control MyEgress(inout headers hdr,
111+
inout metadata meta,
112+
inout standard_metadata_t standard_metadata) {
113+
apply { }
114+
}
115+
116+
/*************************************************************************
117+
************* C H E C K S U M C O M P U T A T I O N **************
118+
*************************************************************************/
119+
120+
control MyComputeChecksum(inout headers hdr, inout metadata meta) {
121+
apply {
122+
update_checksum(
123+
hdr.ipv4.isValid(),
124+
{ hdr.ipv4.version,
125+
hdr.ipv4.ihl,
126+
hdr.ipv4.diffserv,
127+
hdr.ipv4.totalLen,
128+
hdr.ipv4.identification,
129+
hdr.ipv4.flags,
130+
hdr.ipv4.fragOffset,
131+
hdr.ipv4.ttl,
132+
hdr.ipv4.protocol,
133+
hdr.ipv4.srcAddr,
134+
hdr.ipv4.dstAddr },
135+
hdr.ipv4.hdrChecksum,
136+
HashAlgorithm.csum16);
137+
}
138+
}
139+
140+
141+
/*************************************************************************
142+
*********************** D E P A R S E R *******************************
143+
*************************************************************************/
144+
145+
control MyDeparser(packet_out packet, in headers hdr) {
146+
apply {
147+
/* TODO: add deparser logic */
148+
}
149+
}
150+
151+
/*************************************************************************
152+
*********************** S W I T C H *******************************
153+
*************************************************************************/
154+
155+
V1Switch(
156+
MyParser(),
157+
MyVerifyChecksum(),
158+
MyIngress(),
159+
MyEgress(),
160+
MyComputeChecksum(),
161+
MyDeparser()
162+
) main;

0 commit comments

Comments
 (0)