Homework 3
Changelog
- v1: October 16, 2019
Overview
In this homework assignment, you will explore the features of P4 and start using the language to build a simple router. We will extend your router with additional functionality in later assignments.
Due Date
- 11:59pm, October 29, 2019
Academic Integrity
This assignment must be completed individually. All work you submit
must be your own and sharing or receiving code is forbidden, with the
exception of your partner. Do not look for or submit code you find on
the Internet, and do not post solutions or partial solutions on the
discussion site. If you make use of any outside materials, you must
give attribution. You may ask general questions about the development
environment, p4c
, bmv2
, Mininet, etc., and you may discuss
high-level details of the exercises with your classmates. If you have
any questions about what is allowed and what is not allowed, please
ask the instructor first!
Exercise 1: Checksums
In this exercise you will extend the simple switch we saw in class
(named switch.p4
in the starter code) with support for verifying
IPv4 checksums. According to the specification of IPv4 in IETF RFC
791,
The checksum field is the 16 bit one's complement of the one's
complement sum of all 16 bit words in the header. For purposes of
computing the checksum, the value of the checksum field is zero.
Your job is to add code to MyVerifyChecksum
and MyIngress
so that
incoming packets with an invalid IPv4 checksum are dropped.
Implementation Notes
The V1Model
architecture definition provides the HashAlgorithm.csum16
hash
function, as well as a checksum verification extern function with the
following signature:
extern void verify_checksum<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo);
This function sets the checksum_error
bit in standard_metadata
when verification fails, which can be used to drop the packet in the
ingress
control.
Testing
To test your program, we have provided a pair of Python scripts that allow you to send and receive traffic from the command-line. You can run these scripts as follows:
First, as in the first assignment, start Mininet by typing make
and
start the controller by typing ./mycontroller.py
. Next, from the
Mininet console type the following command:
> xterm h1 h2 h3
Then execute ./receive.py
on one of the hosts, say h1
.
Finally execute ./send.py 10.0.1.11 "Hello World"
on another host, say h2
.
To make it easier for you to test that your code is working correctly,
we have deliberately introduced a bug into the send.py
script – it
always generates IPv4 packets with the checksum 0xffff
. Hence,
after you implement checksum verification, the packets generated by
this script should be dropped. To remove the bug, delete
chksum=0xffff
from send.py
.
To submit: Rename your solution checksum.p4
and submit on CMS.
Exercise 2: Access Control
In this exercise, you will extend your code from Exercise 1 with
support for specifying access policies. More specifically, your
program will provide an additional match-action table named acl
that
the control plane can populate with rules to drop specified packets.
This table should support matching on any subset of the following header
fields:
- Ethernet source addresses
- Ethernet destination address
- IPv4 source addresses (if it exists)
- IPv4 destination addresses (if it exists)
- TCP/UDP source port (if it exists)
- TCP/UDP source port (if it exists)
It makes sense to use the
ternary
match kind so that some fields may be omitted in match. As an extension, you may also allow other fields (e.g., ingress/egress ports) to be matched in the ACL table.
Implementation Steps
To complete this exericse, you should extend the simple router as follows:
- Declare header types for the TCP and UDP headers.
- Extend the parser to populate the new headers.
- Create a match-action table
acl
- Apply
acl
at a suitable location in the ingress pipeline. - Edit the
mycontroller.py
files to populate theacl
tables with entries.
For full credit, be sure that your program has well-defined behavior on all packets – i.e., does not read or write invalid headers.
Testing
To test that your access control rules are working correctly, insert a
rule to the acl
table that filters going to the IP addresses of one
of the hosts, and verify that packets sent to that host are indeed
dropped. The mycontroller.py
file has a helper function that can add
ACL rules that match on the destination address. Of course, you may
want to add additional matches to the table entry, or add additional
helper functions. Note that to match on a ternary
key, you should
supply the value and a mask. However, if the mask is 0
, you should
simply omit that key.
To submit: Rename your solution acl.p4
and submit on CMS.
Exercise 3: Load Balancer
In this exercise, you will extend your solution to Exercise 2 with
support for load balancing. More specifically, your switch will take
incoming traffic from host h1
going to the “fictious” IP address
10.0.0.99
and map it to one of hosts h2
or h3
, rewriting the IP
and MAC addresses to match the addresses of the selected host. Other
traffic should be forwarded using the same strategy as in switch.p4
.
You should ensure that your code preserves “flow affinity” – i.e., packets in the same connection should be sent to the same server. You can consider packets to be members of the same flow if they have the same the source and destination IPv4 address, the same IPv4 protocol field, and the same source and destination TCP/UDP ports.
Implementation Steps
To complete this exericse, you should extend the access control router
with support for load balancing as specified above. There are several
ways to achieve this, and you are free to use any algorithm you like.
However, using a hash function to select one of h2
or h3
is the
most common approach. The v1model.p4
architecture contains the
definitions of several extern functions that may be useful. In
particular, the signature of the hash
extern is as follows:
extern void hash<O, T, D, M>(out O result, in HashAlgorithm algo, in T base, in D data, in M max);
Hence, the statement
hash(result, algo, base, data, max);
computes the hash of data
using algo
modulo max
, adds base
,
and stores the resulting value in result
. For example,
hash(x, HashAlgorithm.crc16, 0, { hdr.ipv4.dstAddr }, 2);
hashes the IPv4 destination address to a single bit and stores the result in x
.
Testing
To test your solution, you should verify that packets sent by h1
to
the fictitious address above are indeed delivered to h2
and h3
using the send.py
and receive.py
scripts.
To submit: Rename your solution load_balance.p4
and submit on CMS.
Exercise 4: Debriefing
-
How many hours did you spend on this assignment?
-
Would you rate it as easy, moderate, or difficult?
-
If you worked with a partner, please briefly describe both of your contributions to the solution you submitted.
-
How deeply do you feel you understand the material it covers (0%-100%)?
-
If you have any other comments, I would like to hear them! Please write them down or send email to
jnfoster@cs.cornell.edu
To submit: debriefing.txt