Skip to content

Commit 3599b65

Browse files
authored
Flowcahe exercise (#675)
Signed-off-by: Dscano <[email protected]>
1 parent 6dab99c commit 3599b65

File tree

8 files changed

+1302
-1
lines changed

8 files changed

+1302
-1
lines changed

exercises/flowcache/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
BMV2_SWITCH_EXE = simple_switch_grpc
3+
4+
include ../../utils/Makefile

exercises/flowcache/README.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
2+
[comment]: # (SPDX-License-Identifier: Apache-2.0)
3+
4+
# Implementing a Control Plane using P4Runtime
5+
6+
## Introduction
7+
8+
In this exercise, we will be using P4Runtime to send flow entries to the
9+
switch instead of using the switch's CLI. We will be building on the same P4
10+
program that you used in the [basic_tunnel](../basic_tunnel) exercise. The
11+
P4 program has been renamed to `advanced_tunnel.p4` and has been augmented
12+
with two counters (`ingressTunnelCounter`, `egressTunnelCounter`) and
13+
two new actions (`myTunnel_ingress`, `myTunnel_egress`).
14+
15+
You will use the starter program, `mycontroller.py`, and a few helper
16+
libraries in the `p4runtime_lib` directory to create the table entries
17+
necessary to tunnel traffic between host 1 and 2.
18+
19+
> **Spoiler alert:** There is a reference solution in the `solution`
20+
> sub-directory. Feel free to compare your implementation to the
21+
> reference.
22+
23+
## Step 1: Run the (incomplete) starter code
24+
25+
The starter code for this assignment is in a file called `mycontroller.py`,
26+
and it will install only some of the rules that you need to tunnel traffic between
27+
two hosts.
28+
29+
Let's first compile the new P4 program, start the network, use `mycontroller.py`
30+
to install a few rules, and look at the `ingressTunnelCounter` to see that things
31+
are working as expected.
32+
33+
1. In your shell, run:
34+
```bash
35+
make
36+
```
37+
This will:
38+
* compile `advanced_tunnel.p4`,
39+
* start a Mininet instance with three switches (`s1`, `s2`, `s3`)
40+
configured in a triangle, each connected to one host (`h1`, `h2`, `h3`), and
41+
* assign IPs of `10.0.1.1`, `10.0.2.2`, `10.0.3.3` to the respective hosts.
42+
43+
2. You should now see a Mininet command prompt. Start a ping between h1 and h2:
44+
```bash
45+
mininet> h1 ping h2
46+
```
47+
Because there are no rules on the switches, you should **not** receive any
48+
replies yet. You should leave the ping running in this shell.
49+
50+
3. Open another shell and run the starter code:
51+
```bash
52+
cd ~/tutorials/exercises/p4runtime
53+
./mycontroller.py
54+
```
55+
This will install the `advanced_tunnel.p4` program on the switches and push the
56+
tunnel ingress rules.
57+
The program prints the tunnel ingress and egress counters every 2 seconds.
58+
You should see the ingress tunnel counter for s1 increasing:
59+
```
60+
s1 ingressTunnelCounter 100: 2 packets
61+
```
62+
The other counters should remain at zero.
63+
64+
4. Press `Ctrl-C` to the second shell to stop `mycontroller.py`
65+
66+
Each switch is currently mapping traffic into tunnels based on the destination IP
67+
address. Your job is to write the rules that forward the traffic between the switches
68+
based on the tunnel ID.
69+
70+
### Potential Issues
71+
72+
If you see the following error message when running `mycontroller.py`, then
73+
the gRPC server is not running on one or more switches.
74+
75+
```
76+
p4@p4:~/tutorials/exercises/p4runtime$ ./mycontroller.py
77+
...
78+
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with (StatusCode.UNAVAILABLE, Connect Failed)>
79+
```
80+
81+
You can check to see which of gRPC ports are listening on the machine by running:
82+
```bash
83+
sudo netstat -lpnt
84+
```
85+
86+
The easiest solution is to enter `Ctrl-D` or `exit` in the `mininet>` prompt,
87+
and re-run `make`.
88+
89+
### A note about the control plane
90+
91+
A P4 program defines a packet-processing pipeline, but the rules
92+
within each table are inserted by the control plane. In this case,
93+
`mycontroller.py` implements our control plane, instead of installing static
94+
table entries like we have in the previous exercises.
95+
96+
**Important:** A P4 program also defines the interface between the
97+
switch pipeline and control plane. This interface is defined in the
98+
`advanced_tunnel.p4info` file. The table entries that you build in `mycontroller.py`
99+
refer to specific tables, keys, and actions by name, and we use a P4Info helper
100+
to convert the names into the IDs that are required for P4Runtime. Any changes
101+
in the P4 program that add or rename tables, keys, or actions will need to be
102+
reflected in your table entries.
103+
104+
## Step 2: Implement Tunnel Forwarding
105+
106+
The `mycontroller.py` file is a basic controller plane that does the following:
107+
1. Establishes a gRPC connection to the switches for the P4Runtime service.
108+
2. Pushes the P4 program to each switch.
109+
3. Writes tunnel ingress and tunnel egress rules for two tunnels between h1 and h2.
110+
4. Reads tunnel ingress and egress counters every 2 seconds.
111+
112+
It also contains comments marked with `TODO` which indicate the functionality
113+
that you need to implement.
114+
115+
Your job will be to write the tunnel transit rule in the `writeTunnelRules` function
116+
that will match on tunnel ID and forward packets to the next hop.
117+
118+
![topology](../basic_tunnel/topo.png)
119+
120+
In this exercise, you will be interacting with some of the classes and methods in
121+
the `p4runtime_lib` directory. Here is a summary of each of the files in the directory:
122+
- `helper.py`
123+
- Contains the `P4InfoHelper` class which is used to parse the `p4info` files.
124+
- Provides translation methods from entity name to and from ID number.
125+
- Builds P4 program-dependent sections of P4Runtime table entries.
126+
- `switch.py`
127+
- Contains the `SwitchConnection` class which grabs the gRPC client stub, and
128+
establishes connections to the switches.
129+
- Provides helper methods that construct the P4Runtime protocol buffer messages
130+
and makes the P4Runtime gRPC service calls.
131+
- `bmv2.py`
132+
- Contains `Bmv2SwitchConnection` which extends `SwitchConnections` and provides
133+
the BMv2-specific device payload to load the P4 program.
134+
- `convert.py`
135+
- Provides convenience methods to encode and decode from friendly strings and
136+
numbers to the byte strings required for the protocol buffer messages.
137+
- Used by `helper.py`
138+
139+
140+
## Step 3: Run your solution
141+
142+
Follow the instructions from Step 1. If your Mininet network is still running,
143+
you will just need to run the following in your second shell:
144+
```bash
145+
./mycontroller.py
146+
```
147+
148+
You should start to see ICMP replies in your Mininet prompt, and you should start to
149+
see the values for all counters start to increment.
150+
151+
### Extra Credit and Food for Thought
152+
153+
You might notice that the rules that are printed by `mycontroller.py` contain the entity
154+
IDs rather than the table names. You can use the P4Info helper to translate these IDs
155+
into entry names.
156+
157+
Also, you may want to think about the following:
158+
- What assumptions about the topology are baked into your implementation? How would you
159+
need to change it for a more realistic network?
160+
161+
- Why are the byte counters different between the ingress and egress counters?
162+
163+
- What is the TTL in the ICMP replies? Why is it the value that it is?
164+
Hint: The default TTL is 64 for packets sent by the hosts.
165+
166+
If you are interested, you can find the protocol buffer and gRPC definitions here:
167+
- [P4Runtime](https://github.com/p4lang/p4runtime/blob/main/proto/p4/v1/p4runtime.proto)
168+
- [P4Info](https://github.com/p4lang/p4runtime/blob/main/proto/p4/config/v1/p4info.proto)
169+
170+
#### Cleaning up Mininet
171+
172+
If the Mininet shell crashes, it may leave a Mininet instance
173+
running in the background. Use the following command to clean up:
174+
```bash
175+
make clean
176+
```
177+
178+
#### Running the reference solution
179+
180+
To run the reference solution, you should run the following command from the
181+
`~/tutorials/exercises/p4runtime` directory:
182+
```bash
183+
solution/mycontroller.py
184+
```
185+
186+
187+
## Next Steps
188+
189+
Congratulations, your implementation works! Move onto the next assignment
190+
[Explicit Congestion Notification](../ecn)
191+
192+
193+
## Relevant Documentation
194+
195+
Documentation on the Usage of Gateway (gw) and ARP Commands in topology.json is [here](https://github.com/p4lang/tutorials/tree/master/exercises/basic#the-use-of-gateway-gw-and-arp-commands-in-topologyjson)
196+
197+
The documentation for P4_16 and P4Runtime is available [here](https://p4.org/specs/)
198+
199+
All excercises in this repository use the v1model architecture, the documentation for which is available at:
200+
1. The BMv2 Simple Switch target document accessible [here](https://github.com/p4lang/behavioral-model/blob/master/docs/simple_switch.md) talks mainly about the v1model architecture.
201+
2. The include file `v1model.p4` has extensive comments and can be accessed [here](https://github.com/p4lang/p4c/blob/master/p4include/v1model.p4).

0 commit comments

Comments
 (0)