-
Notifications
You must be signed in to change notification settings - Fork 31
Tutorial Assignments
In this Lab session you will have the opportunity to complete the following three projects:
-
Switch Calculator - using the switch as a calculator and key-value store
-
TCP Monitor - using the switch to monitor the number of bytes transferred in each TCP connection
-
In-band Network Telemetry (INT) - implement basic support for INT to facilitate network measurements
The hardware testing component of these tutorial assignments require a machine equipped with both a SUME board and a dual port 10G NIC connected as shown below.
10G NIC SUME
------ ---------
| |
eth1 --<======>-- nf0
| |
eth2 --<======>-- nf1
| |
------ -- nf2
|
-- nf3
|
---------
This is a simple exercise which demonstrates many of the basic features of the P4->NetFPGA workflow. In this assignment, you will write a P4 program that configures the NetFPGA SUME switch to act as a simple calculator and key-value store.
The operations that will be supported are:
- ADD - add two operands and return the result
- SUBTRACT - subtract two operands and return the result
- ADD_REG - add an operand to the current value stored in a register on the switch and return the result
- SET_REG - set the value of a register on the switch
- LOOKUP - lookup the given key in a table on the switch and return the result
In order to ask the switch to perform one of these operations, a client will send a packet with the following header on top of the Ethernet layer:
header Calc_h {
bit<32> op1;
bit<8> opCode;
bit<32> op2;
bit<32> result;
}
Where op1
and op2
are the first and second operand respectively, opCode
indicates which of the 5 supported operations to perform, and the result
field is set by the switch after performing the required computation. The switch should also swap the source and destination MAC addresses on the received packet before sending the final packet back to the client.
In summary, the switch will perform the following tasks:
- Receive and parse packet from client
- Swap the source and destination MAC addresses
- Examine the
opCode
field to determine the appropriate operation to perform - Set the
result
field if necessary - Construct the final packet and send it back to the client
The following image shows how the operands and registers should be used to perform the various functions:
To complete this assignment you will need to do the following:
-
Modify
$SUME_FOLDER/tools/settings.sh
to ensure that theP4_PROJECT_NAME
environment variable is set toswitch_calc
. Run$ source settings.sh
-
Complete switch_calc.p4 - a skeleton P4 program has been provided for you in
$P4_PROJECT_DIR/src/switch_calc.p4
.TopParser
andTopDeparser
are already complete.TopPipe
(i.e. the match-action pipeline) has all of the necessary tables and actions defined. Your job is to fill in the control flow to implement the switch_calc program. Note that the commands.txt file in the same directory fills the entries in thelookup_table
. -
Review gen_testdata.py - this is the python script that generates the test data (i.e. applied/expected packets and metadata) to be used in the simulations that verify functionality. The file is located in
$P4_PROJECT_DIR/testdata/
. -
Run the P4-SDNet compiler to generate the resulting HDL and an initial simulation framework:
$ cd $P4_PROJECT_DIR && make
-
Run the SDNet simulation:
$ cd $P4_PROJECT_DIR/nf_sume_sdnet_ip/SimpleSumeSwitch
$ ./vivado_sim.bash
.Note: you may also run
vivado_sim_waveform.bash
if you would like to fire up the Vivado GUI and see the HDL waveforms (this is a very useful debugging tool).If this simulation passes great! If it does not you will need to modify either your P4 program or your
gen_testdata.py
script. -
Generate the scripts that can be used in the NetFPGA SUME simulations to configure the table entries.
$ cd $P4_PROJECT_DIR && make config_writes
-
Wrap SDNet output in wrapper module and install as a SUME library core:
$ cd $P4_PROJECT_DIR && make uninstall_sdnet && make install_sdnet
-
Set up the SUME simulation. The
$NF_DESIGN_DIR/test/sim_switch_default
directory contains arun.py
script which is responsible for running a SUME simulation, check it out. You will see that it reads the test packets generated by thegen_testdata.py
script and applies the packets to SUME interfaces. All we need to do here is copy theconfig_writes.py
script generated in step 6 into this directory by runningmake
.$ cd $NF_DESIGN_DIR/test/sim_switch_default && make
-
Run the SUME simulation. The following command launches the SUME simulation and calls the
run.py
script in the$NF_DESIGN_DIR/test/sim_switch_default/
directory:$ cd $SUME_FOLDER
$ ./tools/scripts/nf_test.py sim --major switch --minor default
Note: you may also run the above command with the
--gui
option to fire up the Vivado GUI and see the HDL waveforms. Again, a very useful debugging tool.Also run the
sim_switch_ctrlWrites
simulation, which demonstrates how to read/write registers in the SUME simulations. Remember to runmake
in this test directory as well.If all simulations pass and you don't plan to perform hardware testing then you are done with this assignment. Otherwise, move onto the next step.
-
Compile the bitstream.
$ cd $NF_DESIGN_DIR && make
-
Check that the design meets the timing requirements. See this FAQ for information about how to do this.
-
Copy the bitstream file and
config_writes.sh
script into the$NF_DESIGN_DIR/bitfiles
directory.$ cd $NF_DESIGN_DIR/bitfiles
$ mv simple_sume_switch.bit ${P4_PROJECT_NAME}.bit
$ cp $P4_PROJECT_DIR/testdata/config_writes.sh ./
-
Program FPGA. Make sure that the
P4_PROJECT_NAME
environment variable is set correctly in the$SUME_FOLDER/tools/settings.sh
file. Source thissettings.sh
file.$ cd $NF_DESIGN_DIR/bitfiles/
$ sudo bash
# bash program_switch.sh
Note: Make sure that all the configuration writes succeed. If this is the first time you are programming the FPGA since the machine was last powered off then you might get
ERROR
messages statingNo such device
.To resolve this, follow the below-mentioned steps:
a. Reboot the Machine
b. Execute the following commands (taken from Step 9 on Getting Started Page in this repo):
[root@nf-test109 ~]# cd $DRIVER_FOLDER
[root@nf-test109 sume_riffa_v1_0_0]# make all
[root@nf-test109 sume_riffa_v1_0_0]# make install
[root@nf-test109 sume_riffa_v1_0_0]# modprobe sume_riffa
[root@nf-test109 sume_riffa_v1_0_0]# lsmod | grep sume_riffa
c. Now, you will be able to see
nf0
,nf1
,nf2
andnf3
ports in yourifconfig
output. Re-execute the aforementioned commands in Step 13. This time the configuration writes & the loading bitstream process should succeed. -
Test the design on real hardware! Go to the
$P4_PROJECT_DIR/sw/CLI
directory and run theP4_SWITCH_CLI.py
script. This initiates an interactive command line interface that you can use to interact with your switch (i.e. read/write registers, add/remove table entries, etc.). Typehelp
to see the list of available commands.Go to the
$P4_PROJECT_DIR/sw/hw_test_tool
directory and run$ sudo bash
then run theswitch_calc_tester.py
script. This will initiate a command line tool that you can use to submit packets to the switch and view its response. Typehelp run_test
to see how to use the command.Try adding two numbers
testing> run_test 2 + 3
and seeing what you get. Also try doing things like setting one of theconst
register entries from the command line then submitting anADD_REG
packet. Or submit aSET_REG
packet and read the value from the command line. Or add a new entry into thelookup_table
and submit aLOOKUP
packet to get the result. -
If the switch appears to be working congratulations! You've finished the assignment!
-
Writing the P4 program:
- You can check if your P4 program will compile by entering into the
$P4_PROJECT_DIR/src
directory and running$ make
- You will need to use one of the register atom externs available in the P4->NetFPGA library. In this case, we have already instantiated the
const_reg_rw
atom for you, but you will need to use it in the control flow. These registers can only be accessed one time in the P4 code.
- You can check if your P4 program will compile by entering into the
-
Debugging tools:
- See here for debugging tips.
This tutorial is designed to give users experience writing stateful P4 programs by utilizing some of the register atoms available in the P4->NetFPGA extern library.
In this assignment, you will write a P4 program to configure the NetFPGA SUME to perform some basic TCP connection monitoring. Recall that a TCP connection is established with the 3-way handshake (SYN, SYN-ACK, ACK) and in general, completes after a FIN packet is sent in both directions. For the purposes of this assignment, we will define a flow as all of the packets with a particular 5-tuple ID (srcIP, dstIP, protocol, source_port, destination_port); a flow starts with a packet that has the SYN bit set and ends with a packet that has the FIN bit set. Note that using this definition, each TCP connection consists of two flows, one in each direction.
The TCP Monitor P4 program will compute the size of each flow (in bytes) and after the flow has completed, it will update a histogram indicating the distribution of flow sizes that have passed through the switch. The control-plane can read this histogram off of the switch and display the current distribution in real time.
The general idea is as follows:
-
There are two register arrays:
-
byte_cnt
- stores the current size in bytes of all "active" flows. Where an "active" flow is one in which the SYN packet has been seen, but the FIN packet has not been seen yet. -
dist
- stores the histogram of flow sizes that have been seen to pass through the switch.
-
-
The 5-tuple is extracted from each arriving packet and hashed using a simple longitudinal redundancy check (LRC) to compute the index with which to access the
byte_cnt
register. -
The initial SYN packet will reset the
byte_cnt
register entry to 0 -
Each subsequent packet of the flow will increment its corresponding entry in the
byte_cnt
register with the size of its TCP payload. -
The FIN packet will extract the final size of the flow from the
byte_cnt
register and use it to increment one of the entries of thedist
register. -
Note: It is true that the 5-tuple of different flows may hash to the same entry of the
byte_cnt
register, which will skew the resulting histogram towards larger flows. We will ignore that case for the purposes of this assignment to keep things simple.
-
Modify
$SUME_FOLDER/tools/settings.sh
to ensure that theP4_PROJECT_NAME
environment variable is set totcp_monitor
. Run$ source settings.sh
-
Complete tcp_monitor.p4 - a skeleton P4 program has been provided for you in
$P4_PROJECT_DIR/src/tcp_monitor.p4
.TopParser
andTopDeparser
are already complete.TopPipe
(i.e. the match-action pipeline) has all of the necessary tables and actions defined. Your job is to fill in the control flow to implement the tcp_monitor program. -
Review gen_testdata.py - we have completed the
gen_testdata.py
script for you, but ask that you review how it uses python's scapy module to generate the flows. -
Follow steps 4 - 13 as listed in the "Switch Calculator" tutorial above.
-
Hardware testing!
$ cd $P4_PROJECT_DIR/sw/hw_test_tool
and open up two terminal windows:-
In one terminal, run the
view_dist.py
script which will periodically read the flow size distribution from the switch and display it as a histogram. -
In the other terminal, run
$ sudo bash
then run thetcp_monitor_tester.py
script, which initiates a command line interface that allows you to send TCP flows through the switch. Typehelp
to see options.
Make sure that the histogram is being updated as you would expect. Note that if you try to send too many concurrent flows through the switch, some will hash to the same
byte_cnt
register entry which will skew the results. -
-
If the switch appears to be working properly then congratulations! You've finished the assignment!
In this assignment you will write a P4 program to implement basic INT support for the NetFPGA SUME platform. INT is quickly becoming one of the most popular applications for programmable data-planes, and it's all about gaining more visibility into your network. There are different ways of adding support for INT, but in this tutorial we will roughly base our implementation on this INT specification.
The basic idea is as follows:
-
An INT source end host will generate a packet with an INT header (over Ethernet) that contains an instruction bitmask.
-
Each bit of that instruction bitmask corresponds to a different type of metadata in the switch (e.g. switch ID, ingress port, egress port, ingress timestamp, etc.).
-
If a particular bit is set in the instruction bitmask that means the switch should insert the corresponding metadata into the packet. Each piece of metadata is represented as a header with a single bottom-of-stack (
bos
) bit followed by 31 bits of data. The last piece of INT metadata must have thebos
bit set to 1. The diagram below shows how new INT metadata is inserted into the packet.
| Ethernet | INT | INT_data | INT_data | payload |
| | | bos:0 | bos:1 | |
^
|
New data inserted here
- The format of the INT header is shown below. We will ignore the replication and copy fields to simplify the implementation.
// INT header
header int_h {
bit<2> ver; // version #
bit<2> rep; // replication requested
bit<1> c; // is copy
bit<1> e; // max hop count exceeded
bit<5> rsvd1; // reserved 1
bit<5> ins_cnt; // # of 1's in instruction bitmask
bit<8> max_hop_cnt; // max # hops allowed to add metadata
bit<8> total_hop_cnt; // # hops that have added metadata
bit<5> instruction_bitmask; // which metadata to add to packet
bit<27> rsvd2; // reserved 2
}
-
Our INT implementation will support gathering 5 types of metadata from the switch:
- SwitchID
- Ingress Port
- Egress Queue Occupancy
- Ingress Timestamp
- Egress Port
-
Upon receiving the final packet, the INT sink end host will extract the resulting metadata.
-
Modify
$SUME_FOLDER/tools/settings.sh
to ensure that theP4_PROJECT_NAME
environment variable is set toint
. Run$ source settings.sh
-
Complete int.p4 - a skeleton P4 program has been provided for you in
$P4_PROJECT_DIR/src/int.p4
. -
Review gen_testdata.py
-
Follow steps 4 - 13 as listed in the "Switch Calculator" tutorial above.
-
Hardware testing!
$ cd $P4_PROJECT_DIR/sw/hw_test_tool
and open up two terminal windows:-
In one terminal run
$ sudo bash
then run# ./rcv_int
, which receives, parses, and prints received INT packets. -
In the other terminal run
$ sudo bash
then run# ./int_tester.py
, which allows you to send INT packets with a particular instruction bitmask into the switch. For example,testing> run_test 0b11001
will submit an INT packet that requests to switch to insert the switchID, ingress port, and egress port into the packet. Typetesting> help run_test
to see documentation about the command.
-
If the switch appears to be working congratulations! You've completed the assignment.