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 the acl 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