Assignment title: Information
MP: Transport Protocol
Your goal in this MP is to implement a reliable transport protocol that supports congestion and flow control. You will build your protocol on
top of UDP. Your protocol should have the following features:
Handshake
Your client and server should perform a handshake to establish a connection. If there is no response from the server, you should return an
error. Unlike TCP, you don't have to support multiple simultaneous connections to the same port.
Reliable Data Transfer
You should ensure data is delivered reliably and in order even if the network drops, delays, or reorders packets. You can assume that the
network never corrupts the packets.
Flow Control
When sending data, you should use flow control to ensure that data does not get sent faster than it is processed at the receiver. You may
allow a little buffering in your system but no more than 100 KB or so.
Congestion Control
You should implement congestion control to avoid congesting the network. Your system should dynamically adjust its sending rate to avoid
congestion and maintain high overall throughput.
Fairness
Two connections using your transport protocol should converge to fairly sharing the link; i.e., have roughly the same throughput (+/-
10%). This should happen within about 100 RTTs, even if the two connections were not started at the same time.
TCP Friendliness
Your protocol must be somewhat TCP friendly: if you share a connection with a TCP flow, your flow should have between 60% and 70% of
the aggregate throughput.
Utilization
In the absence of packet loss (other than due to congestion) or reordering, and when there are no competing flows, your protocol should
utilize at least 70% of the bandwidth in the steady state.
Implementation
You may implement this project in C/C++ or Python. Unlike MP1, C/C++ is a reasonable implementation choice for this project and you
may see somewhat higher performance. In Python, you should implement a socket-like object, described in the file transport.py. In
C/C++, you should implement the functions described in the file transport.h. The functions implement a slightly simplified version of the
standard socket interface.
Python function C function Description
MP2Socket.__init__() mp2_socket_init() Initialize the socket
MP2Socket.connect() mp2_socket_connect() Connect to a remote socket. The remote endpoint is specified by a hostname (string) and a
UDP port number (integer, host byte order)
MP2Socket.accept() mp2_socket_accept() Wait for a connection on the specified UDP port. This essentially combines
TCP's bind, listen, and accept calls. Unlike TCP, accept will be called on a socket only
once, since you don't need to handle multiple connections to the same socket.
MP2Socket.send() mp2_socket_send() Send data to the remote endpoint. Data may be of arbitrary size and you may need to break it
up into packets. This call may block due to flow control. send should always sendall the data,
partial sends are unacceptable.
MP2Socket.recv() mp2_socket_recv() Receive some data from the socket. Wait until data is available and deliver however much is
available to the reader. A single send() may be received through multiple recv()calls, and
vice versa, but data must be delivered in the same order that it is sent (as in TCP).
MP2Socket.close() mp2_socket_close() Close the socket and let the remote end know that the connection is closed.
Working in Python, you should modify transport.py to implement the MP2Socket class. (You may use other .py files and import them
in transport.py.) Working in C/C++, you should not modify transport.h and instead implement the needed functions in one or
more .c or .ccfiles.
Network EnvironmentThe test network environment will have a bandwidth of at most 10 Mbps and round-trip delay of at most 50 ms. If you want to replicate it,
we suggest setting up a Linux virtual machine in VirtualBox or VMWare and using the tc (traffic control) command together with the
network emulation module:
Delete any old tc rules
% sudo tc qdisc del dev eth0 root
(eth0 here is your network interface; you can find its name by running ifconfig)
Add a 40 ms delay and 5% packet loss:
% sudo tc qdisc add dev eth0 root handle 1:0 netem delay 40ms loss 5%
(You can omit loss 5% if you don't want any loss)
Set a bandwidth limit of 10 Mbps:
% sudo tc qdisc add dev eth0 parent 1:1 handle 10:0 tbf rate 10Mbit burst 1mb latency 1ms
If you are running on two VMs, you want to do this on the VM that is sending data, as tc only affects outgoing traffic on the interface. If
you are running the server and client on the same machine, you should be able to use dev lo instead to apply the limits to the loopback
device, but note that you'll want to cut the delay in half because it will be applied in both directions.
Note that if you want to have two VirtualBox VMs that talk to each other, you should create a "NAT Network" in VirtualBox network
preference and configure both of them to use that network; otherwise they will not be able to forward traffic to each other.