Lab net: Network stack

This is one of the project options.

In this lab you will add networking support to xv6. We will be using lwIP, an open-source TCP/IP stack, so you won’t have to write a network stack from scratch. Your job is to write a driver for a network interface controller (NIC) and add sockets to xv6.

Your solution is acceptable if DHCP succeeds with your NIC driver. Implementing sockets is encouraged but not required for this lab.

Driver

QEMU emulates a virtio-net NIC. The first step is to write a driver for this device. You may want to read both the virtio specification and the source code of the virtio disk driver in xv6 (kernel/virtio_disk.c). Make sure you understand the initialization process and how the driver and the device communicate through virtqueues.

Here are some hints about how you might go about this part.

/* initialize a NIC and store the MAC address; return 0 on success */
int virtio_net_init(int n, void *mac);

/* send data; return 0 on success */
int virtio_net_send(int n, const void *data, int len);

/* receive data; return the number of bytes received */
int virtio_net_recv(int n, void *data, int len);
net 0: mac 52:54:00:12:34:56
net 0: addr 10.0.2.15 netmask 255.255.255.0 gw 10.0.2.2

For debugging, you may turn on verbose output in kernel/lwip/lwipopts.h. For instance, lwIP will print details of the DHCP process if you set DHCP_DEBUG to LWIP_DBG_ON there. We also configure QEMU to dump all incoming and outgoing packets to en0.pcap in your lab directory. You may use tcpdump or Wireshark to inspect the file.

$ tcpdump -nr en0.pcap
reading from file en0.pcap, link-type EN10MB (Ethernet)
19:21:49.038877 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 52:54:00:12:34:56, length 308
19:21:49.038919 IP 10.0.2.2.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 548
19:21:49.040188 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 52:54:00:12:34:56, length 308
19:21:49.040202 IP 10.0.2.2.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 548
19:21:49.040654 ARP, Probe 10.0.2.15, length 28
19:21:49.536180 ARP, Probe 10.0.2.15, length 28
19:21:50.036122 ARP, Probe 10.0.2.15, length 28
19:21:50.036343 ARP, Announcement 10.0.2.15, length 28

Use tcpdump -XXnr en0.pcap to further print the data of each packet if needed.

Wireshark provides both graphical and terminal-based user interfaces. Here is an example of using the terminal version:

$ tshark -nr en0.pcap
    1   0.000000      0.0.0.0 → 255.255.255.255 DHCP 350 DHCP Discover - Transaction ID 0x5d39a
    2   0.000042     10.0.2.2 → 255.255.255.255 DHCP 590 DHCP Offer    - Transaction ID 0x5d39a
    3   0.001311      0.0.0.0 → 255.255.255.255 DHCP 350 DHCP Request  - Transaction ID 0x5d39a
    4   0.001325     10.0.2.2 → 255.255.255.255 DHCP 590 DHCP ACK      - Transaction ID 0x5d39a
    5   0.001777 52:54:00:12:34:56 → ff:ff:ff:ff:ff:ff ARP 42 Who has 10.0.2.15? Tell 0.0.0.0
    6   0.497303 52:54:00:12:34:56 → ff:ff:ff:ff:ff:ff ARP 42 Who has 10.0.2.15? Tell 0.0.0.0
    7   0.997245 52:54:00:12:34:56 → ff:ff:ff:ff:ff:ff ARP 42 Who has 10.0.2.15? Tell 0.0.0.0
    8   0.997466 52:54:00:12:34:56 → ff:ff:ff:ff:ff:ff ARP 42 Gratuitous ARP for 10.0.2.15 (Request)

Sockets

The next step is to implement socket system calls on top of lwIP’s “raw” API. You may design your own socket interface, though the BSD socket API is a good starting point. The socket interface should support at least TCP (with IPv4); it doesn’t have to support UDP or IPv6. You may find the documentation of lwIP’s TCP API useful.

Here are some hints about how you might go about this part.

Implement some user programs to test your interface. Feel free to borrow code from Hyperkernel, such as:

Below is an example output:

xv6 kernel is booting

bd: memory sz is 133865472 bytes; allocate an size array of length 24
bd: 3146512 meta bytes for managing 134217728 bytes of memory
bd: 0x56000 bytes unavailable
virtio disk init 0
net 0: mac 52:54:00:12:34:56
net 0: addr 10.0.2.15 netmask 255.255.255.0 gw 10.0.2.2
hart 1 starting
hart 2 starting
init: starting sh
$ daytime

58760 19-10-04 21:35:47 31 0 0 907.8 UTC(NIST) * 
$ wttr
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Fri, 04 Oct 2019 21:35:48 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 296
Connection: close

Weather report: Seattle, United States

               Overcast
      .--.     60 °F          
   .-(    ).   ↑ 14 mph       
  (___.__)__)  9 mi           
               0.0 in         
$

Optional challenges: