castleman.space

Thomas Castleman's website.

TCP/IP

2022

In the spring semester of 2022, for Brown's cs168: Computer Networks, I collaborated with Charlie Gagnon to implement our own TCP and IP stack.

IP Layer

The project specification effectively asks you to start by implementing a driver program that connects to other instances of itself over UDP, forming a sort of virtual network with UDP as the link layer. These processes exchange routing information with their neighbors using the RIP protocol, and use this information to forward packets across their links.

By following the RIP specification (RFC 2453), our nodes were able to automatically learn routes to every node in the network, send packets unreliably from any node to any other node, and adapt to changes in the topology as links go down and come back up.

ICMP

Using our IP functionality, we implemented a subset of the Internet Control Message Protocol (RFC 792) so that we could implement a traceroute command in our driver.

This command uses ICMP Echo and Echo Response packets to determine the IP addresses of routers on each hop along the way to a destination address.

TCP Layer

Once we had a network layer that could perform routing and unreliable delivery of packets, we were able to work on implementing our own transport layer that could provide a notion of sockets, reliable delivery of a stream of bytes, and congestion control.

With the guidance of RFC 793, we implemented connection setup and teardown, the TCP state machine, proper sequencing and acknowledgement of packets, retransmission, flow control using the sliding window protocol specified in the RFC, and out of order packet processing. In the end, our TCP was able to transfer a 5MB file fully reliably in just a few seconds.

As an extension for his capstone, Charlie also added congestion control to our TCP, using the TCP Tahoe approach (RFC 5681), which adds a separate congestion window and changes how retransmissions work.

Rust

Perhaps one of the most exciting aspects of this project was that we implemented it in Rust. This is definitely the largest Rust program I've worked on, and I have to say I am glad we made the choice to use it.

As with any complicated piece of software, we spent a lot of time debugging. We did not, however, spend time debugging things like memory corruption, memory leaks, and unpredictable crashes. Rust enabled us to focus on the challenge of implementing a complex multithreaded networking program (which is hard enough!), rather than the consequences of common C pitfalls.

Source

Unfortunately, as this project is still part of the course materials for cs168, I am unable to make our implementation public.