Fall Semester 2006
Due: November 1, 2006 (midnight) for both
sessions
In this project, you will be implementing a reliable simplex data link layer protocol for noisy channel described in section 3.3.3 of our textbook (Computer Networks, Tanenbaum, 2002). In this project description, we refer this protocol as PAR (Positive Acknowledgement with Retransmission) protocol. Since it is not convenient to program against the real APIs in this level (you need to write kernel code and access layer 1 and layer 3 APIs residing in the kernel), your code will have to execute in a simulated environment. In fact, the layer 1 will be simulated using UDP, and layer 3 is simulated by application layer input and output.

The execution of network protocols is typically event-driven. Such events include the arrival of a message from the lower or higher level, and the expiration of a timer. The event is often called an interrupt.
Consider a layer n and its adjacent layers n+1 and n-1, as shown in the figure above. When layer n+1 has a message to send, it invokes the send interface provided by the layer n and passes the message to layer n. Layer n maintains a send buffer to store message to be sent (and to be retransmitted). If the buffer is already full when layer n+1 tries to send a message, an error will be returned. The send call will trigger an event so that the thread that is executing the layer n protocol can fetch the message in the send buffer and passes it to the lower layer (n-1) afternoon adding a layer n header.
Similarly, when a message arrives at layer n-1, an event is generated and the layer n protocol thread is woken up to handle the message. In general, the message is initially stored in a receive buffer of layer n before it is delivered to layer n+1, for a number of reasons (e.g., to ensure source ordering in TCP). In our PAR protocol, this buffer is not used because the message is delivered right away.
If layer n-1 might be lossy (i.e., it does not offer a reliable service), layer n must implements a retransmission mechanism to retransmit the messages to be sent, if the acknowledgement does not arrive in time. To do this, the protocol starts a timer each time it transmits (or retransmits) a message. If the timer expires, an event is generated and the protocol thread is woken up to perform the retransmission operation.
Event-driven programming is not trivial. Therefore, you are provided with Java skeleton code and the binary (Java byte code) files for a reference implementation for this project. In the reference implementation, the main thread executes the PAR protocol, and a separate thread is used to pick up messages arrived from UDP in the simulated physical layer. The timer is implemented using the facility provided by Java (java.util.Timer and java.util.TimerTask). You are strongly encouraged to build your project based on the skeleton Java code. However, you are free to choose a different programming language if you wish, in which case, you will have to implement the simulation environment as well as the PAR protocol from scratch.
As you may have noticed, the PAR protocol described in section 3.3.3 of our textbook proactively fetches a message from the network layer whenever it has finished sending a message. The reference implementation follows it closely. We should note that it does not match the practical use cases.
The reference implementation consists of the following files:
Considering that many students do not have strong programming background, most of the files above will be provided with full implementation. Your tasks include:
The reference implementation has only a simple verification test on the correctness of the frames received. It includes a preamble with each frame sent and check the validity of the preamble. This check does not work if the transmission error occurs after the preamble part in a frame. To improve the current implementation, you need to compute a checksum for each frame and include the checksum as a trailer in each frame sent, and verify the checksum of each frame received.
Because UDP ensures no corruption for packets delivered, you need to instrument the PhysicalLayer send() code to inject corruption into frames to be sent. Again, the corruption fault should happen randomly with controllable probabilities, just like the frame loss rate.