A network stack for the xv6 operating system, written in Rust.
Building and running the xv6-net
the project requries the following dependencies:
- A C compiler (e.g. GCC)
- Make
- Rust (and the i586-unknown-linux-gnu toolchain)
- QEMU
On Ubuntu-like operating systems, a C compiler (GCC) and Make can be installed
as part of the build-essential
package:
sudo apt-get install build-essential
Rust can be installed by following the instructions on the Rust project's
homepage. The
i586-unknown-linux-gnu
toolchain can be installed using the rustup
tool:
rustup toolchain install i586-unknown-linux-gnu
QEMU can be installed via the qemu
package:
apt-get install qemu
In addition to the standard Make targets provided by the xv6
project, the
xv6-net
project adds a qemu-net
Make target. This target uses QEMU's -nic
flag to emulate an E1000
family network device. The -nic
flag creates a new
TAP device which may require root
privileges.
The xv6
network stack supports a single interface which is assigned a fixed
address of 10.0.0.2
.
The project can be built with make
:
$ make
Once built, the xv6
operating system can be started with the qemu-net
target:
$ make qemu-net
After assigning an address to the TAP interface:
$ ip addr add 10.0.0.2 dev tap0
The xv6
operating system should respond to ping.
$ ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.026 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.035 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.021 ms
The implementation of network stack adds 7 new system calls: socket
, bind
,
connect
, listen
, accept
, send
and recv
. As only UDP is currently
supported, the listen
and accept
system calls are currently nops.
socket
- Creates a new socket of the specified type (currently UDP only)bind
- Associates a socket with a local address and portconnect
- Associates a socket with a remote address and portlisten
- Not implementedaccept
- Not implementedsend
- Send data to a remote socketrecv
- Receive data from a remote socket
An example netcat like userspace program, nc
, is provided to exercise the
network stack.
The nc
program operates in two modes, client or server:
nc [-c|-s] [address] [port]
In client mode (-c
), the program will send data from stdin to the specified
port of the host located at address
. For example, to send data to 10.0.0.1
on port 4444
:
$ nc -c 10.0.0.1 4444
$ hello, world!
In server mode (-s
), the program will listen for data on the specified port.
To listen to data on port 5555
:
$ nc -s 10.0.0.2 5555
As the network interface has a fixed local address (10.0.0.2
), the address
argument is currently ignored in server mode.
- The network interface is assigned a fixed address of
10.0.0.2
- The connect(...) system call is blocking on establishing the ARP resolution of the hardware address of the remote host.
- The send(...) system call is blocking on the successful write of a transmit descriptor to the network device.
- The recv(...) system call is non-blocking, returning immediately if no data is available. This is until the functionality of proc.c is ported to Rust.