CS 485/585 (ECE 440) Computer Networking - Lab 4

CS 485/585 (ECE 440) Computer Networking, Fall 2018

Lab 4 - due Friday November 30 @ midnight

Please meet with your group members and get started on the lab as soon as possible. In general, in this class you will have about 2 weeks from the lab release date until the due date.

Accessing Your Group's Repository for this Lab

I have created a Git repository for each group. You should have already received an invite to access your repository on LoboGit. If you did not receive such an invite, contact me immediately.

The name of your repository will be teamXX, where XX are digits. You should be able to view the repository online at https://lobogit.unm.edu/net-f18/lab4/teamXX.

You will use the git tool on Linux to access the repository.

Cloning the Repository via HTTPS (Easy)

This is the easiest method of accessing your repository. Git will prompt you for your UNM NetID/password.

cd ~
mkdir -p net-f18
cd net-f18
git clone https://lobogit.unm.edu/net-f18/lab4/teamXX.git lab4
cd lab4

Here, you should be able to type ls (list files) and see the skeleton structure which your lab 3 submission should follow.

Cloning the Repository via SSH (More Difficult)

If you don't wish to type your NetID/password, you can instead use public-key authentication. First (if you haven't already done so), you need to create a key pair for public-key authentication (git will use this instead of username/password for authentication).

mkdir -p ~/.ssh
chmod 700 ~/.ssh
cd ~/.ssh
ssh-keygen -t rsa -b 4096 -C "YOUR_ADDRESS@unm.edu" -f id_rsa

(where YOUR_ADDRESS@unm.edu is your UNM email address). This creates a public key (id_rsa.pub) and a private key (id_rsa). KEEP YOUR PRIVATE KEY SECURE AT ALL TIMES! Open the public key (id_rsa.pub) in a text editor

pluma ~/.ssh/id_rsa.pub

and copy the contents into the "SSH Keys" section of your "Settings" on LoboGit. Once the public key is added on LoboGit, you can do

cd ~
mkdir -p net-f18
cd net-f18
git clone git@lobogit.unm.edu:net-f18/lab4/teamXX.git lab4
cd lab4

Here, you should be able to type "ls" (list files) and see the skeleton structure which your lab 2 submission should follow.

Setting up a Virtual Machine

For this lab, you will be given a virtual machine (VM) with sudo permissions, i.e., you will have administrative privileges (unlike on the CS lab machines). This will give you greater freedom in experimenting with the machine's protocol stack.

BE CAREFUL when using sudo on your machine! With great power comes great responsibility!

Your VM can only be reached via one of our classroom machines. If you are not in the classroom, you can access the machines remotely:

ssh -X username@b146-xx.cs.unm.edu

(where username is your CS username, and xx is between 01 and 76).

You will need at least two terminals open on the classroom machine, so either open a new terminal, or start a second SSH connection.

In one terminal, type the following commands

cd /b146vpn
openvpn b146fw-udp-1194.ovpn

and enter your CS username/password when prompted. This authenticates you with the virtual private network (VPN) needed to access your VM.

NOTE: if you get an error about the address already being in use, that means the VPN client is already running! In this case, just skip the VPN step and continue with the following instructions.

In the other open terminal, you should be able to log into your VM

ssh -X username@10.200.2.yyy

NOTE: Replace username with the username you've been sent via email (it should be the same as your NetID username). The 10.200.2.yyy is a unique IP address for your VM, which you will be sent via email. DO NOT try to log into a VM until you are assigned a username and IP address via email!

Your VM password is initially set PassXXXXXX!, where XXXXXX is the unique six-digit ID you were assigned via email at the beginning of the class. The first time you log in, you will be asked to change your password. When asked for "Current UNIX password", repeat the PassXXXXXX! password, and then you'll be asked to type a new password twice. The new password can be anything you want (this VM account is not connected to your UNM account, or your CS account -- the VM will only be used in this class).

Once you are logged into your VM, install some utilities:

sudo apt-get install mininet xterm pcapfix python-dpkt python-numpy python-cairo make gnuplot texlive-latex-extra mupdf xpdf evince graphviz iperf3 bridge-utils

sudo sed "s/disable_lua = false/disable_lua = true/g" -i /usr/share/wireshark/init.lua

sudo sed "s/stp_enable=true' %/stp_enable=true' #%/g" -i /usr/lib/python2.7/dist-packages/mininet/node.py

mkdir -p ~/git && cd ~/git
git clone https://github.com/hgn/captcp.git
cd captcp
sudo make install
cd ~

Part 1 - Error Detection at the Link Layer (30 points)

Error detection is an important service provided by the link layer (Layer 2 of the protocol stack), and also appears in higher layers. In this part of the lab, we will look at Ethernet frames (link-layer packets) more closely, and learn how the error detection mechanism(s) works.

In particular, we will use the Python raw sockets interface to send Ethernet frames directly to the link layer on the NIC. This will allow us to customize various parts of a frame, including the cyclic redundancy check (CRC) field at the end.

The checksum folder in your repository contains skeleton code to help you get started. This code is initally using an included library to do the error detection - you will need to write your own function(s) to do this. To run the code, do the following:

cd checksum
sudo ../mini.py -c openflow

At the Mininet prompt, type xterm h1 h1 to get two terminals. In one terminal, type

sudo wireshark -k -i h1-eth0

and in the other, type

sudo ./main.py -d 10.0.0.2 -m 10:00:00:00:00:02

This Python script creates an Ethernet frame containing an ICMP (ping) packet and sends it to the NIC on host h1, so you should see the ICMP request show up in Wireshark, followed by an ICMP response from host h2.

If you click on the ICMP request, and then open the Ethernet II field below, you can inspect the CRC by looking at the "Frame check sequence" field. Wireshark will tell you whether the CRC is valid. Additionally, you can inspect the Internet checksum, i.e., the network-layer error detection code, by opening the Internet Protocol Version 4 field, and looking at Header checksum. To make Wireshark validate the checksum, select Edit -> Preferences -> Protocols -> IPv4 -> "Validate the IPv4 checksum if possible" and click Ok.

If either of these error detection codes is invalid, the ICMP request packet will likely be dropped before it reaches the destination host, meaning you will not see an ICMP reply from host h2 in that case.

Task A - Write your own function to compute the CRC32 for the Ethernet frame. You can use the existing function in the code as a "black box" to compare your CRC32 functionality against.

Task B - Write your own function to compute the Internet checksum over the IP header within the Ethernet frame. Again, you can use the existing function to compare your functionality against.

Part 2 - Address Resolution Protocol (ARP) (30 points)

In Part 1, we used the following command to send an Ethernet frame to the NIC on host h1:

sudo ./main.py -d 10.0.0.2 -m 10:00:00:00:00:02

Notice that we are manually specifying the destination MAC address (link-layer address) of the frame. In general, we would only know the IP address 10.0.0.2 of the destination, and we would need some mechanism for determining the destination's MAC address. This is where the address resolution protocol (ARP) is used - host h1 can send out an ARP request for address 10.0.0.2, and when host h2 sees the request, it can respond with its MAC address.

In this part of the lab, instead of manually specifying the MAC address of the destination, we will use ARP to "automatically" determine it.

Task A - Complete the getMAC() function in checksum/main.py. You will need to create an ARP request packet, send it to the NIC, and then receive packets until you see the ARP reply from the destination. Once you receive this reply, extract the MAC address, and return it.

Task B - If you have completed Task A correctly, your can now run your code as follows:

sudo ./main.py -d 10.0.0.2

Notice that we do not specify the MAC address (it is determined via ARP). More specifically, do the following to make sure your code is fully working:

cd checksum
sudo ../mini.py -c openflow -r

NOTE: the -r option causes the MAC addresses of thse hosts in Mininet to be randomized, so you can check that your code is actually getting the correct MAC address. At the Mininet prompt, type xterm h1 h1 to get two terminals. In one terminal, type

sudo wireshark -k -i h1-eth0

and in the other, type

sudo ./main.py -d 10.0.0.2

You should see the ICMP request and reply show up in Wireshark, and inspecting the ICMP request packet should show the properly-computed destination MAC address.

Part 3 - Learning Switch using Software-Defined Networking (SDN) (30 points)

Recall from the previous lab how we manually installed forwarding rules on the switches in order to set up the routes between the various hosts. In this part of the lab, we will investigate how software-defined networking (SDN) allows us to do this automatically.

In particular, we will build what's called a learning switch - the forwarding rules on the switches will be added on demand, based on the traffic that's being sent to them.

The basic idea of SDN is that all of the switches connect to a special machine called a controller. In our case, the communication between the switches and the controller is out-of-band (these messages do not flow through the network like the ICMP/ARP packets we've seen so far), and uses an API known as OpenFlow (we will use OpenFlow 1.0).

You can see how this works by experimenting with the OpenFlow 1.0 reference controller. First, run the following in one terminal:

controller ptcp:localhost:6633 -v --log-file=mylog

In another terminal, start up Mininet using the custom startup script:

sudo ./mini.py -c remote

Mininet should wait a few seconds as the switches connect to the controller, and then you should see the controller begin to emit a large amount of debugging output, showing you what OpenFlow messages are being received/sent at the controller.

This OpenFlow 1.0 controller implements the learning switch, so while the controller is running, communication between hosts should be enabled in Mininet. For example, if you type h1 ping h2, the controller is able to set up the route to allow these pings to succeed.

Task A - Look through the code, starting with the run() function in SwitchHandler.java, and make sure you understand the basics of what it is doing. The OpenFlow 1.0 Specification will be very helpful in learning about the different messages, and their correct order.

Task B - Implement your own learning switch, using the SDN controller skeleton code provided for you in the controller directory of your repository. The place your code needs to be added is in the handlePacketIn() method of SwitchHandler.java. A very clear description of the learning switch algorithm implemented on a different SDN controller (known as POX) can be found here: L2 Learning Switch. Upon receiving a packet from a switch, you will need to send two types of messages back to the switch: (1) a PacketOut message, which causes the packet to be flooded on all interfaces except the one it arrived on (PacketOut functionality is already provided for you), and (2) a FlowMod message(s) which install rules based on the reverse path of the packet (you will need to build the FlowMod functionality, and you can see how this is done for PacketOut).

The graphical guide to OpenFlow 1.0 Messages should be very helpful as you think about which PacketOut and FlowMod messages you should send back to the switch.

Part 4 - Documentation (10 points)

Clearly document (using source-code comments) all of your work. Also fill in the README.md file (preferably using Markdown syntax) with a brief writeup about the design choices you made in your code.

Providing adequate documentation helps me see that you understand the code you've written.