Project 1: Create a Network Protocol
CS233/333 - Networks and Distributed Systems
Fall, 1999.
Due Date: October 29, 11:59 p.m.
Disclaimer : This is only a brief description to get you thinking about it.
More details will follow later.
Introduction
In this project, you are going to implement a new network protocol
suite based largely on IP. The starting point for your protocol will
be the reception and transmission of raw ethernet packets. From
there, you will be responsible for assembling and disassembling
packets, dispatching handlers for various system services and
higher-level protocols, error recovery, and providing data to
user-level code.
The programming language for this project is Python.
Find a group
This is a group project. Undergraduates may work in groups of up to 3 people.
Graduate students may work in groups of 2 people. You may work alone if you
wish.
The Big Picture
The end result of this project is for you to implement the following network
programming API.
- socket(family, proto)
Create a communications socket. family is the protocol
family and is AF_CS333 for this project. proto
describes the protocol and is one of SOCK_DGRAM,
SOCK_RDGRAM, or SOCK_STREAM. SOCK_DGRAM is
an unreliable datagram protocol similar to the UDP
protocol. SOCK_RDGRAM is a reliable datagram protocol that is
like SOCK_DGRAM, but with error recovery.
SOCK_STREAM is a reliable connection-oriented protocol
similar to the TCP protocol.
- bind(socket,port)
Binds a socket object to a port number. A port number of 0 indicates
that the system should pick a port number.
- accept(socket)
Wait for an incoming connection. Returns a new socket object on success
that is used for subsequent communication.
- listen(socket, queuesize)
Start listening for incoming packets on a given socket. The socket
must already be bound to a port before calling this function. queuesize
specifies the maximum number of pending connections that are allowed.
- close(socket)
Close a socket connection.
- getsockname(socket)
Returns the IP address and port number assigned to a socket.
- getsockstatus(socket)
Returns the socket status as an integer.
- recv(socket,maxbytes)
Receive up to maxbytes of data on the socket. Returns the data
read as a string. This function blocks until data is available.
It may return fewer than maxbytes of data however.
- recvfrom(socket, maxbytes)
Read a datagram of data from the socket. Returns the data sent
as a string, and the address of the sender.
- send(socket,data)
Send data across the socket object. Returns the number of bytes
sent on success.
- sendto(socket,data, dest)
Sends a datagram across a socket. data is the raw
data to send (as a string), and dest is the IP address
and port number of the target machine.
This API closely mimics the existing Unix socket API. In fact, when your
project is finished, it should be possible to run HTTP and other common
application level protocols across your network protocol.
The Low-level Interface
You will be provided with a low-level packet-based interface to the
ethernet device. The following functions are contained in
a Python module eth (to be supplied).
- eth.read_packet()
Read a raw packet of data from the ethernet device. The returned
packet contains all of its raw ethernet headers and is not decoded
or error-checked in any manner.
- eth.send_packet(data)
Send a raw packet of data to the ethernet device. data
must be a properly encoded ethernet packet. This function always
returns immediately.
- eth.eth_address([str])
Returns the ethernet address of the machine as a 6-byte binary string suitable
for use in raw ethernet packets. str is an optional string
containing an ethernet address formatted as xx:xx:xx:xx:xx:xx.
If supplied, it is converted to its 6-byte binary string representation.
- eth.eth_address_string([bstr])
Returns the ethernet address of the machine as a nicely formatted string
of the form xx:xx:xx:xx:xx:xx. bstr is an optional
6-byte binary string containing an ethernet address. If supplied, it's
address is returned instead.
- eth.ip_address([str])
Returns the current IP address of the machine as a 4-byte binary string
suitable for use in raw packets. str is an optional string
containing an IP address of the form xx.xx.xx.xx. If supplied,
it's address is returned as a 4-byte string instead.
- eth.ip_address_string([bstr])
Return the current IP address of the machine as a nicely formatted
string of the form xx.xx.xx.xx. bstr is an optional
4-byte binary string containing an IP address. If supplied, it's
address is returned instead.
Here is a simple example of using these functions:
[root@baldy vnet]# npython
Python 1.5.2 (#7, Sep 21 1999, 11:01:07) [GCC egcs-2.91.66 19990314/Linux (egcs- on linux2
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> import eth
eth: initializing ipchains
eth: Initializing the ethernet interface
eth: eth0 = 00:C0:4F:6E:2C:A0
eth: IP address = 128.135.11.12
>>> print eth.eth_address_string()
00:c0:4f:6e:2c:a0
>>> data = eth.read_packet()
>>> print len(data)
60
>>> data
'\000\300On,\240\010\000 \237\253\361\010\000E\000\000(|H@\000\377\006\347\334\200\207\013\220\200\207\013\014\235\025\000\027\271\226\020\033\375i\334\241P\020"85\010\000\000UUUUUU'
>>>
>>> while 1:
... data = eth.read_packet()
... print "\nPACKET:"
... print repr(data)
...
...
You should go up to the networks lab to try this out at your convenience. Note:
make sure you use the special version of Python 'npython' as it contains a
number of modifications that make it possible to read/write raw packets as
well as support for threads (that will be needed later).
The Real and Virtual Network
The low-level network functions contained in the eth module
support two modes of operation. If you are logged onto a machine as
"root" (as will be the case in the networks lab), the
eth module provides access to the real ethernet device on the
machine. That is, the packets you read and write will be real packets
on the network. However, for development, you may want to work in the
Linux lab or on other machines where you do not have access to the
root password. To support this, the eth module starts a
virtual network server if it determines you are running as an ordinary
unpriviledged user.
To use the virtual network feature on a normal machine, you should
first make sure you are using the proper version of Python (npython)
above. Then, in a terminal, you can create a host by setting the
following environment variables:
% setenv ETH xx:xx:xx:xx:xx:xx
% setenv IP yy.yy.yy.yy
(where you fill in the specific values). For example:
% setenv ETH 00:c0:4f:8e:91:d2
% setenv IP 192.168.69.2
% npython
Python 1.5.2 (#7, Sep 21 1999, 11:01:07) [GCC egcs-2.91.66 19990314/Linux (egcs- on linux2
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> import eth
Initializing vnet...
(111, 'Connection refused')
Starting the vnet server...
(111, 'Connection refused')
Connected with the vnet server.
eth: Initializing the ethernet interface
eth: eth0 = 00:c0:4f:8e:91:d2
eth: IP address = 192.168.69.2
>>>
If successful (as shown above), the Python interpreter in which
eth was loaded will behave as a machine with the given ethernet
and IP address. Now, in another window on your machine, you can follow
the same procedure to create another virtual machine with a different
ethernet and IP address. At this point, the two terminal windows
are connected in a "virtual" network and properly addressed packets can be
sent between the two interpreters as normally (using the same low-level
packet interface described earlier).
If you want to avoid all of the above, the spawnnet script
can be used to launch a 4-node virtual network with the same ethernet
and IP addresses as the four Dell Linux machines in the networks lab.
To use this, set your DISPLAY variable and do the following:
% setenv DISPLAY yourmachine:0
% spawnnet
This will cause 4 xterm windows to appear on your screen. Each will be
configured to operate as a different node in the network when you
run your programs. (A demo of this will be given in class).
Software
All of the relevant software for this project can be found in
/stage/classes/archive/1999/fall/CS233/project1
(which should be accessible on the Linux lab machines).
Approximate Schedule
The project will be complete in 3-stages, 1 week apart.
- Friday, October 15. Low-level packet interface and ARP protocol.
- Friday, October 22. UDP and Reliable UDP protocol. Error checking.
- Friday, October 29. Streams protocol. Final handin.
Like OS, it is unlikely that you will finish any of these stages if you wait
until the night before the due date.
More details about each part of the project will be handed out separately.
Grading
Your grade is based solely on whether or not you produce a working network
protocol. A series of tests will be provided to test your programs.
Your programs must be able to pass a minimal series of tests to
receive a passing grade. A most advanced set of tests must be passed
to receive full credit.
Grading breakdown:
- On time handin of each part (30%)
- Final handin (70%).
Note: Only the final handin will be graded for correctness(70%). The rest
of the grade is determined by whether or not you hand in each piece on time
and whether or not it appears as if you have made progress (10% reduction
for each missed due date).