COSC 4377 - Introduction to Computer Networks

Spring 2012

MW 1:00-2:30pm at PGH347

InstructorOmprakash Gnawali

Homework 7 : Packet Forwarding

Due: midnight March 21, 2012

In this assignment, we will create a network and write forwarding logic to forward packets between arbitrary pair of nodes in the network (as long as there is a valid route between them).

Part 1 - Setting up the network

In this part, we setup the network of processes. In a real network, these proceses are run on different machines but in this assignment, we run all the processes in a single machine to simplify the homework and standardize the testing environment.

We provide the code for most of this part. Each node is represented by a process. The sample code reads the file that lists all the neighbors of each node. It also sets up the basic flow for a pthreads-based driver, receiver, and sender implementation. The comments in the code tell you about the major missing pieces. You will need to setup the server socket on the nodes to read packets sent by neighboring nodes.

We will launch the "node" executable for each node in the network. If we have a network consisting of 5 nodes, we will launch "node" five times with arguments identifying the node. Each node reads a "links" file, which has a list of its neighbors -- their id and port.

./node nodeid port

Node's address or id is given by nodeid. The node listens for incoming
packets on the port.

Lets learn how to setup a topology that looks like:

|         |

We need to specify the links for each node on the links file. We will have five links file with names link1, link2, link3, link4, and link5. These files list all the neighbors for the respective nodes. The first column is nodeid and the second column is the port on which that neighbor is listening for packets. Then, we lanuch the nodes like this:
./node 1 101 &
./node 2 102 &
./node 3 103 &
./node 4 104 &
./node 5 105 &

Make sure the ports used to launch the nodes is the same as the ones listed on the links file.

Each node process, when launched, should setup a UDP (not TCP) socket to read packets sent by its neighbors. You might find it more convenient to use connectionless UDP socket setup so that you can use a single function or thread to read packets sent by all the neighbors.

Part 2 - Routing

In this homework, we will use static routing to determine the paths between the nodes in the network. We will learn how to do dynamic routing in next homework.

When the "node" executable is launched, it expects a route file that lists all the destination (first column) and next hop (second column). It is not necessary for all the nodes to have routes to all the nodes in the network. Some nodes might not have any route. We are providing route1, route2, route3, route4, route5 as examples for the topology described above. In these examples, you all notice that not all the nodes have routes to all the nodes. With the route file, you should be able to create loops, shortest paths, sub-optimal paths, etc.

Although the provided code has skeleton for reading the route file, you need to define data structure to store, update, and lookup the tables.

Part 3 - Forwarding

Now that the topology and the routes are setup, we are ready to forward some packets. We have already defined the structure for packet. When we discuss forwarding, we need to describe the tasks performed by three types of nodes:

  1. Origin node: The origin node wants to send a packet to node "d". It allocates a packet structure, sets the destination to d. It sets the source as itself. It sets hops to 0. It sets type to 2 because we are creating a data packet. It sets the sequence number to 0 for the first packet. It increments the sequence number each time a new packet is sent to allow us to uniquely identify the packets. And finally, it puts the payload that we need to send to the node d. It then looks up the next hop for that destination in this routing table and sends the packet to the next hop.
  2. Forwarder node: The forwarder node is always ready to receive packets from its neighbors. When it receives a packet from its neighbor, it immediately increments the hops field in the packet. If the destination is the current node, the forwarding is complete. We dispatch the packet to the application running in the current node. If the destination is not the current node, the node looks up the next for that destination in its routing table. If there is no route, it should log appropriate error message and drop the packet. If there is a route to that destination, it sends the packet to the next hop. If the hops field reaches infinity (10), it should drop the packet.
  3. Destination node: When the packet arrives at the destination node, the forwarder dispatches the packet to the application. The application then processes the packet. In this assignment, the processing is simply logging the fact that the packet arrived at the destination.

Node Control Terminal

The skeleton code provides a way for you to interact with the node but you should fill in some missing pieces. When you launch "node", it waits for these commands from the user:
  1. interfaces : List all the interfaces (links to neighbors).
  2. routes : List all the routes -- destination and next hop, one entry per line. You should complete this part.
  3. down nodeid : Break the link to nodeid. Once a link is broken, the forwarder should not attempt to forward the packet on this link, even though the link might still be in the routing table. You should complete this part.
  4. up nodeid : Bring a link to nodeid up. If the link to the nodeid is broken, restore the link, which makes the link available for forwarding. You should complete this part.
  5. send nodeid string : Send a message in string to nodeid. Send is called at the origin node. You should complete this part.
When you create a large topology, you might want to put the commands to run most of your nodes in a script and run that script. You can launch just one or two nodes in a terminal so that you can generate packets using send, etc. In the given topology above, if you want to test your setup to send packets from 1 to 5, you can launch nodes 2-5 using a script. Then, lanuch node 1 and use the send command on node 1's control terminal.


You can use printfs and other standard debugging techniques to debug your code. For example, if you want to understand if forwarding is working correctly, you can printf the key details about the packets being received and trasnmitted by each node. These printf outputs can get confusing if you have a number of node processes writing to stdout. It might be easier to track the packets if you open multiple terminals and launch one node process per terminal. This setup will allow you to "see" the packets traversing the terminals as it traverses the network.

We also require that each node also creates a file logx.txt where x is the node id. For example, node 25 would create log25.txt. Each line in the log file should be one of:

  1. SEND origin:xx dst:xx seq:xx nexthop:xx. The origin just sent a packet with sequence number seq to nexthop with the final destination dst.
  2. RCV origin:xx dst:xx seq:xx prevhop:xx. A node received a packet from prevhop. The packet originated at origin and is destined to dst.
  3. FWD origin:xx dst:xx seq:xx nexthop:xx. A node just forwarded a packet to nexthop.
  4. NOROUTE origin:xx dst:xx seq:xx. The forwarding node could not find a route to dst in its routing table.
  5. FAIL origin:xx dst:xx seq:xx nexthop:xx. There was an error while forwarding the packet to nexthop.
  6. DST origin:xx seq:xx prevhop:xx. The packet was received at the final destination.
In the above examples, all xx are integers. Here is what an excerpt of log25.txt might look like:

SEND origin:25 dst:5 seq:12 nexthop:5
RCV origin:8 dst:5 seq:4 prevhop:3
FWD origin:8 dst:5 seq:4 nexthop:5
RCV origin:8 dst:5 seq:5 prevhop:3
FWD origin:8 dst:5 seq:5 nexthop:5
RCV origin:8 dst:5 seq:6 prevhop:3
FWD origin:8 dst:5 seq:6 nexthop:5

The log file above shows that node 25 originated a packet to the destination 5. Then it received three packets, also to destination 5, from node 3. It forwarded these packets to node 5 immediately after receiving them. The sequence in which these messages should indicate the sequence of packet events that occurr at node 25.

Each time you need to log a packet event, please open the log file, append to it, and close the file. Thus, we will have the log file with all the contents intact even if the nodes crash or forget to close the file before terminating.


Put your source code (node.c) into a folder with the name: uhid_hw7, where uhid is the prefix of your email address. There should be a single Makefile in that directory. When we run make on that directory, it should produce one executable called node. Put a README.txt in the directory describing anything unusual (e.g., limitations) of your implementation. Then, zip the directory and upload the zip file using Blackboard.