MIT 6.1810 · Lab net · 网络驱动

Lab: 网络驱动

在本实验中,你将编写一个 xv6 网络设备卡(NIC)驱动程序,然后编写以太网/IP/UDP 协议处理栈的接收半部分。

难度:中等

分支:net

实验日期:2026 秋季

$ git fetch
$ git checkout net
$ make clean

背景

在编写代码之前,你可能需要复习xv6 手册的第 6 章:"中断和设备驱动程序"。

你将使用称为 E1000 的网络设备来处理网络通信。对 xv6(和你编写的驱动程序)来说,E1000 看起来像连接到真实以太网局域网(LAN)的真实硬件。事实上,你的驱动程序将与之通信的 E1000 是由 qemu 提供的仿真。

在此仿真 LAN 上,xv6("客户")的 IP 地址为 10.0.2.15。运行 qemu 的计算机("主机")以 IP 地址 10.0.2.2 出现在 LAN 上。

我们将 QEMU 配置为将所有传入和传出数据包记录到实验目录中的文件 packets.pcap 中:

tcpdump -XXnr packets.pcap

我们为本实验向 xv6 仓库添加了一些文件:

第一部分:NIC 中等

你的工作是完成 kernel/e1000.c 中的 e1000_transmit() 和 e1000_recv(),以便驱动程序可以发送和接收数据包。

在编写代码时,你将参考官方课程提供的 E1000 软件开发人员手册,特别是:

我们提供的 e1000_init() 函数配置 E1000 从 RAM 读取要传输的数据包,并将接收到的数据包写入 RAM。这种技术称为 DMA(直接内存访问)。

E1000 需要一个"描述符"数组来描述接收缓冲区。描述符数组称为接收环(receive ring)或接收队列。struct rx_desc 描述描述符格式。还有一个传输环。

e1000_transmit 提示

e1000_recv 提示

第二部分:UDP 接收 中等

UDP(用户数据报协议)允许不同 Internet 主机上的用户进程交换单个数据包(数据报)。UDP 分层在 IP 之上。

你的工作是填写 kernel/net.c 中 ip_rx()、sys_recv() 和 sys_bind() 的实现。

系统调用 API 规范

// 发送 UDP 数据包
send(short sport, int dst, short dport, char *buf, int len)

// 接收 UDP 数据包
recv(short dport, int *src, short *sport, char *buf, int maxlen)

// 绑定端口(在 recv 之前调用)
bind(short port)

一些提示:

提交实验

时间花费

创建一个新文件 time.txt,放入一个整数,表示你花在实验上的小时数。

答案

如果本实验有问题,将答案写在 answers-net.txt 中。

提交

运行 make zipball,上传到 Gradescope。

可选挑战