CS551: Fall 2010: Redesigning the Internet
Introduction
The transport of bits is a fundamental function in today's Internet. The main transport protocol in the Internet, TCP, is widely used in many applications and is largely considered to be the main contributor to the success of the Internet.
The design of TCP evolved over nearly 2 decades with additions being made to it at various points in time. When any artifact that is also concurrently being used is designed over a long period of time, the design becomes "cluttered" because of the requirement of incremental deployability or backwards compatibility: any newly introduced feature or function cannot invalidate an existing feature.
In this project, we ask you to design a new transport protocol for the Internet with the benefit of a "clean slate". Specifically, we ask you to design and implement a transport protocol called ZTP, which has (mostly) the same functionality as TCP, but, you are free to make completely different implementation choices for ZTP.
You will implement the project in two parts, with the following due dates. These parts are described in a later section.
| Part | Due Date |
|---|---|
| Part 1 | Oct 8th, 5pm |
| Part 2 | Nov 24th, 5pm |
How You Will do the Project: Simulation
Many networking designs are often studied in a simulator because it can be logistically difficult and time-consuming to implement a design in a real system of routers and hosts. The most common kind of simulation is discrete-event simulation.
In this project, you are given an implementation of a discrete-event simulator written in C++. Such a simulator, which is usually implemented as a single UNIX process, mimics the behavior of a network using a discrete-event engine which manages the communication between routers. The crucial aspect of this engine is that it simulates time and will give you a realistic sense of the sequence of events in a real-world implementation.
To understand more about discrete-event simulation, you can search the Web and read the many sites devoted to explaining the concept. In this class, you are given access to the netsim simulator, a discrete-event network simulator given below.
The Netsim Simulator
Netsim takes a topology description (and other information described below) as input. You can specify nodes and links in the topology, and the link bandwidths and propagation latencies. Netsim also implements code that lets you send a packet from any node in the network, to any other node using shortest-path routing. Each node has a limited size packet queue (whose size you can configure), and if a packet arrives at a node when this queue is full, that packet is dropped.
Thus, netsim provides the abstraction of a datagram network, on top of which you can implement several networking protocols and subsystems. In a previous edition of this class, students implemented an almost complete version of TCP on top of this simulator! In general, to implement a specific network functionality, you would use C++ inheritance and define one or more C++ classes that are derived from a base class defined in netsim.
To give you a feel for how to implement a protocol on top of netsim,
we have implemented a simple constant bit-rate transmission protocol:
this protocol sends packets periodically from a specified sender to a
specified receiver. See the cbr_app directory for how this protocol
is implemented using Netsim.
Before getting started on the project, we recommend that you follow these steps:
- Download the netsim code. To do this, use the following command:
% git clone git://sruti.usc.edu/netsim.git
-
Print out the code and read it carefully to understand what
each C++ class does. Start from
Scheduler, and readPacketSchedulerandTimer: these three files implement the heart of the discrete-event engine.Topologyimplements the routing algorithms, whileFIFONodeimplements a router with a bounded packet queue. This code is not particularly well documented, but the level of documentation is fairly typical of what you will find when you are working on collaborative projects in industry or academia. - You may also need to familiarize yourself with the C++ Standard Template Library.
-
Look at the
cbr_appdirectory and familiarize yourself with our implementation of the constant bit rate (CBR) transmission protocol. As part of this, you should also understand the configuration language in Netsim. See theexamplessub-directory for examples of how to configure a network using Netsim, and how to start the CBR sender and receiver. -
A good way to get familiar with the code and how the simulator works
is to compile (using
make) and run thecbr_appcode, examine the trace output (you need to figure out how this works), and single step through the code using the Gnu debuggergdb.
Ground rules
You are given considerable freedom in how to implement the project, but there are several constraints which are discussed in the following paragraphs.
ZTP must provide the following functionality:
- end-to-end reliable transport: packet losses within the network must be recovered using some loss recovery mechanism of your choice. Note that Netsim does not implement bit errors, so packet losses can only happen when queues fill up at a router within the router. Your implementation may assume that such congestion losses are the only source of packet loss.
- in-order delivery: ZTP must deliver data in sequence number order to the application. Netsim does not yet implement re-routing due to link failures or multipath routing, so packets cannot be reordered within the network. However, packets can be received out of order if one or more packets are lost within the network.
- congestion control: ZTP must implement an efficient and fair congestion control protocol of your choice. Specifically, ZTP must be able to efficiently utilize available bandwidth, and at the same time avoid congestion collapse.
- concurrent flows: ZTP must support multiple concurrent flows between any pair of hosts in the network.
The following functionality is optional:
- byte-sequenced delivery: you can choose to have sequence numbers represent individual bytes (like TCP), or choose a different design.
- flow control: you can assume that receivers have infinite buffers, so that flow control is unnecessary, if you believe that would simplify your implementation.
Of course, there are several other components of a modern transport protocol that you may have to implement in order to satisfy the above constraints: for example, round trip time estimation, connection establishment and teardown, and so forth. You are expected to determine which components are needed and implement them in as much detail as is required to satisfy the above constraints.
Other than these constraints, you have significant freedom that is not available to Internet designers today:
- you can add fields to the packet header to implement your functionality
- you can extend router behavior in support of the functionality that you are required to provide
- you can also optionally implement other functionality that you think should be in a transport protocol, but is not in TCP today.
In implementing ZTP, you cannot modify a single line of code inside
the netsim subdirectory. However, you must use the packet
(datagram) delivery abstractions provided by netsim in order to
build your project. You may, of course, use C++ inheritance to derive
classes from any of the base classes provided by netsim. For
example, you may need to extend the packet header to add new fields;
you can do this by inheriting the Packet class. You may also decide
to extend the functionality of a router by defining a new class
which inherits FIFONode.
Finally, on top of ZTP, you will implement a simple file transfer application, FZTP, which simply reads a specified file from the UNIX file system, and transfers its contents from a specified source to a specified destination, using ZTP.
Input
Netsim supports one configuration command that is relevant to your
project. The Link(x,y) command specifies that a topology should be
created from node x to y in the simulator. (In general, nodes
nodes are sequentially numbered using positive integers starting from
1). The Link() command has additional parameters that specify the
propagation and transmission latency on the link.
Remember that links in Netsim are /unidirectional/, so you need to
specify two =Link= commands for bi-directional traffic.
In addition, your program will need to support three additional configuration commands:
-
Router(u_int x, int q)declares a router whose identifier isx. This command should instantiate a router in the simulator. Links between routers are specified using theLink()command discussed above. The maximum queue size on each outgoing link from the router isqpackets. -
Host(u_int y)declares a host whose identifier isy. This command should instantiate a host (a ZTP endpoint) in the simulator. Links between a host and one or more routers are specified using theLink()command discussed above. -
FZTPFlow(Address s, Address d, Time t, char* f)specifies that an FZTP flow should be initiated from source nodesto destination nodedat timet. The flow should transfer the contents of a file whose pathname isf(the pathname can be relative or absolute).
Output
You should use Netsim's TRACE facility to print program output. The
TRACE facility is defined in netsim/common.h.
Specifically:
-
When a router with address
xis created, you should print a line of the following form in your program:
TRACE(TRL3, "Initialized router with address %d\n", x);
-
When a host with address
yis created, you should print a line of the following form in your program:
TRACE(TRL3, "Initialized host with address %d\n", y);
-
When connection establishment completes on an FZTP flow from
stod, your program should print a line using this statement:
TRACE(TRL3, "Established FZTP flow from %d to %d (%d)\n", s, d, t);
where t is the start time of the flow *as specified in the
configuration file* time at which connection establishment completes.
-
When connection teardown completes on an FZTP flow from
stod, your program should print a line using this statement:
TRACE(TRL3, "Tore down FZTP flow from %d to %d (%d)\n", s, d, t);
where t is the start time of the flow *as specified in the
configuration file*. time at which connection teardown completes.
-
When a packet is transmitted (or re-transmitted) at the source
s, you should print the Packet header, the sequence number field from the ZTP header, and the contents of the packet in ASCII at TRL3. See thecbr_appfor an example of how to print the header and the content. You should use the printing routines in the Packet class, but you may need to augment those printing routines to print the fields of the transport protocol header. -
Just before a packet is passed up to the "application" at
destination
d, you should print the Packet header, the sequence number field from the ZTP header, and the contents of the packet in ASCII at TRL3. See thecbr_appfor an example of how to print the header and the content. You should use the printing routines in the Packet class, but you may need to augment those printing routines to print the fields of the transport protocol header.
Implementing the Project
You should implement your project in a directory called ztp, which
should be at the same level as cbr_app. Within the ztp directory,
you should create a Makefile, and one or more header and source
files. Try to make your implementation as modular as possible,
following the structure of Netsim itself, and of the implementation in
cbr_app.
We may modify the Netsim software during the course of the semester. Moreover, this specification itself may be updated occasionally. We will announce all such changes either on the news forum or on the discussion list (sometimes, changes are triggered by questions posed by students on the discussion list). It is your responsibility to track these changes, and keep up with the changes to the specification and to the software.
Finally, although you may develop the project on your own laptop or desktop, before you submit the project must compile and test your project on aludra.usc.edu. Please be aware that subtle differences in compiler versions or other parts of the compile tool-chain can change the correctness of your implementation.
You will submit your project in two parts, as described below.
Part 1
In part 1 of the project, you should have implemented the following pieces of functionality:
- Configuration file parsing. Your part 1 submission should be able to correctly parse all the input commands specified above.
- Connection establishment and teardown. Your part 1 submission should also be able to establish (analogous to TCP's three-way handshake) one or more FZTP flows, and then immediately tear-down the flow.
Your part 1 submission should also implement the relevant outputs (trace messages for initializing hosts and routers, and for connection establishment and teardown). In this part of the project, you don't have to implement actual data transfer.
Part 2
In this part, you will need to implement all the remaining functionality: reliable end-to-end sequenced data transfer and congestion control.
Submitting The Project
You will upload your project to the class Moodle.
Follow these steps to prepare your submission. First, remove all
.o and backup files from your ztp directory. You
should only be left with the Makefile, source and header files.
Then, inside the ztp directory, execute the following
command:
% tar cvf ../project.tar . % gzip project.tar
Then, rename the project.tar.gz file as FirstnameLastname.tgz (e.g.,
RameshGovindan.tgz) where Firstname is your first name and
Lastname is your last name. Then, upload this file to the moodle.
Use the following links to upload your project:
How to Do Well in the Project
- Follow the instructions exactly.
- Do not deviate from the specified output format; do not change capitalization, do not add or remove extra characters, etc. Basically, you should make sure that we can write a script to check your output.
- Follow the submission instructions exactly.
- Create a few test cases of your own, designed to test different aspects of the program.
- Work through those test cases by hand, to make sure the program's outputs are correct.
- Whenever you change the code (and especially for last minute changes), re-test your code against the test cases. Most bugs are introduced by incremental changes to the code.
Clarifications Based on In-Class Discussion
- You can assume at most one ZTP sender or receiver per host at any given instant. This is a minimum requirement, and you're free to implement something more complicated.
-
The
Routerconfiguration commands have now been changed (see above) to include a maximum queue size parameter. Hosts will use the default queue size. - Hosts will not be multi-homed, i.e., a host will only have a link to a single router.
- You may conservatively assume an initial RTO value of 540,000 ticks of the simulator clock. You do not need to have a minimum RTO, but simply use the RTO value suggested by whatever RTT estimation algorithm you decide to use. The choice of a maximum RTO value is left up to you.
-
I have removed the
RouterandHosttypedefs. I have also added a member function to schedulerget_node(Address a)(seePacketScheduler.h): this function returns a pointer to aNodeobject given the corresponding address. To get these changes, do the following:
% git pull
- For the final project, there is no specific performance requirement. However, your implementation must be congestion-adaptive, and must be fair and efficient.