Handy references:
Lab Audio
Lab Audio, Day 2
For this lab, you'll be designing and implementing reliable data transfer
over an unreliable (simulated) link. Your submission will be in the form of a
library that mimics the type of functionality that you would expect to get from
an OS's transport-layer implementation.
Your transport protocol should be a stop-and-wait protocol for now. We'll
introduce high-performance pipelining features in lab 6.
Requirements
- You must use C to implement your library code, and the underlying
transport that it uses to transfer messages must be UDP. TCP would give you
reliability, which would obviously defeat the purpose...
- You should build a stop-and-wait style of protocol that works even when
links have very small packet buffers (e.g., size 2 packets).
- The example code includes a test application that sits above your library
and uses it to transfer a file. You may edit the test application for your own
testing, but when grading, I will use the default version, so do not
rely on changes to these files for correct operation. Your library (lab5.h and
lab5.c) should allow any application that's built on top of it to achieve
reliable communication. When transferring files with your library, you should
get byte-for-byte identical copies. Use diff, md5sum, etc. to
veryify that everything is transferred properly.
- As a part of your implementation of reliability, you'll need to perform
RTT estimation to determine how you should set timeout values. You should use
an EWMA-based mechanism like TCP does. The library function my_rtt()
should always return your library's current estimate of the RTT. Normally you
wouldn't export such information up to the application/user, but I'll use this
to check your RTT calculation.
Like TCP, you should compute your timeout as a function of the current RTT
estimate, sampling only those segments for which no retransmission is
necessary. If a timeout occurs, you should double the timeout for each
subsequent retransmission of the same segment.
- Your implementation should cleanly shut down connections on both ends, even
if packets get lost. You do NOT need to implement the TCP behavior that
allows each side to shutdown independently. TCP is substantially more
complex than the protocol you're building because your protocol is
unidirectional. Like TCP though, in my_close(), you may want to wait for
some time, to make sure the last ACK didn't get lost (leaving one end
hanging).
You should NOT rely on ICMP error messages to help your closing procedure. To
be safe, it's best to disable ICMP from both hosts before starting the sender
and receiver with:
iptables -I OUTPUT -p icmp -j DROP
- You should provide a brief (~1/2 - 1 page) description of the testing and
debugging strategy you used to convince yourself that the protocol you've
implemented is correct. If you encountered major hurdles, what were they, and
how did you solve the problem?
Environment - Setup
For this lab, we'll be using an emulation package called mininet to create
virtual links that allow us to vary their performance characteristics (latency,
loss rate, etc.). Because it requires special permissions to execute, we'll be
running it inside of a virtual machine. The VM image will NOT fit in your home
directory, so you'll need to work in /local, which is the local hard disk of
the machine you're using.
Storing things on /local has two major implications that you need to account
for:
- The data on /local is stored on a single disk (unlike your home directory,
which is split across multiple disks for redundancy). When you're done working,
you should save your important lab files elsewhere (e.g., push them to github)
to avoid data loss in the event of a disk failure. When you're done working on
your VM, you should shut it down nicely: "sudo shutdown -h now"
- The /local partition on each machine is only available on that machine.
This means that if you want to move and work a different machine, you'll need
to set up a new VM at the new location. You could also copy your VM image from
/local on one machine to /local on another with scp.
To get started, you'll need to import a copy of the starter VM image:
- Run virtualbox in a terminal or open it from within your favorite
graphical menu.
- Go to File->Preferences, set your "Default Machine Folder" to "/local", and
then close the preferences window.
- Go to File->Import Applicance. Choose: /local/CS43-Mininet-VM.ovf and push next once.
- You should now be seeing "Appliance settings". Edit the name to include your username. For example, CS43-Mininet-VM-kwebb.
- Click import and wait a minute for it to complete.
After you've completed these steps, you should see the your VM in the
list of VMs available to start. Go ahead and turn it on.
While you could work from within the new VM window that just came up, doing
so is a huge pain if you enjoy nice things like graphical interfaces. Instead,
it's much easier to connect to the VM via ssh with X11 forwarding turned on.
The VM is already configured such that you can connect to it by sshing
to your local machine on port 22222. (Port 22222 on your machine gets
forwarded to port 22 on the VM):
ssh -Y localhost -p 22222 -l mininet
(The password is: mininet)
Before going any further, you should use the passwd command to set
a new password to protect your VM. After that, you'll need to configure an SSH
key so that you can access GitHub. You have to options:
- Create a new key for the VM and add it to your GitHub account. (Instructions)
- Copy your existing ssh key from your CS account to the VM (e.g., with scp).
Environment - Mininet
Once you've connected to the VM, you can run mininet:
- From your terminal that's ssh'ed to the VM, run mininet, and tell it to
create a minimal network topology with two hosts connected to a switch with
10ms latency on each link, 5% packet loss on each link, and a buffer of size 2.
Note that there is no space between parameters:
sudo mn --link tc,delay='10ms',loss=5,max_queue_size=2 -x
This will pop up four terminal windows: one for each of the two hosts (h1 and
h2), one for the switch (s1), and one for a controller (c0). Close the
controller and switch terminals, you won't be using those for this lab.
All the operations you perform within these windows are as if you were ssh'ed
to two lab machines. They work independently like different machines but share
the same files. If you run 'ifconfig' on each of them, you'll see that h1 has
an IP address of 10.0.0.1 and h2 has 10.0.0.2. You should be able to transmit
data between the two. Test that by running the ping command at h1:
ping 10.0.0.2
You should see a (round trip time) delay of ~40 ms with approximately a 19%
loss rate (each link has an independent 5% chance of dropping a packet).
You'll find the example code in the lab5 directory, which is shared between the
VM and each of the fake hosts.
- Edit/execute code and work on the lab. You'll want to periodically make a
backup of your changes (push to GitHub), since the VM image is stored on the
machine's local disk. If the disk fails, you don't want to lose your
changes...
- When you're done, you can tell the VM to shutdown by executing:
sudo shutdown -h now
Grading Rubric
This assignment is worth five points.
- 1 - Your protocol is a stop and wait protocol that delivers data reliably,
even when link buffers are small (i.e., two packets) when no packets are lost.
- 1 - Your protocol reliably delivers data despite packet losses.
- 1 - Your protocol correctly estimates the round trip time of the path.
- 1 - Your protocol cleanly terminates connections such that both ends agree
that the connection is closed.
- 1 - You provide a description of how you tested and debugged your
protocol.
Tips
If you have any questions about the lab requirements or specification,
please post on Piazza.
Submitting
Please remove any debugging output prior to submitting.
Please do not submit output file(s) that you used in testing.
To submit your code, simply commit your changes locally using git
add and git commit. Then run git push while in your lab
directory.