Lab6_Network Driver

简介

在本实验中,我们将为 NIC(Network Interface Card, 网络接口卡)编写驱动程序。这个网卡基于Intel 82540EM芯片,也称为E1000。

除了编写驱动程序之外,我们还需要创建一个system call 来访问我们的驱动程序。我们将实现缺失的网络服务器代码,以在网络堆栈和驱动程序之间传输数据包。我们还可以通过完成Web服务器将所有内容绑定在一起。使用新的Web服务器,我们将能够从文件系统中提供文件。

这个 lab 比之前的都要难,因为 there are no skeleton files, no system call interfaces written in stone, and many design decisions are left up to you.

QEMU’s virtual network

QEMU’s documentation has more about user-net here

QEMU 默认提供一个运行在 IP 10.0.2.2上的虚拟路由,并且为 JOS 分配IP 10.0.2.15。To keep things simple, we hard-code these defaults into the network server in net/ns.h. 为了解决连接内网问题(host 无法连接运行在QEMU上的Web server),我们配置QEMU在主机某个端口上运行服务。该端口只需连接到JOS中的某个端口,并在真实主机和虚拟网络之间来回传送数据。

To find out what ports QEMU is forwarding to on your development host, run make which-ports. For convenience, the makefile also provides make nc-7 and make nc-80, which allow you to interact directly with servers running on these ports in your terminal.

~/workspaces/MIT6.828/lab$ make which-ports
Local port 26001 forwards to JOS port 7 (echo server)
Local port 26002 forwards to JOS port 80 (web server)

Packet Inspection

Makefile 配置了QEMU的网络栈,将进出的网络包记录到 qemu.pcap中。我们可以使用图形化的 wireshark,或是使用命令行获得网络包的hex/ASCII信息。

tcpdump -XXnr qemu.pcap

Debugging the E1000

The E1000 can produce a lot of debug output, so you have to enable specific logging channels. Some channels you might find useful are:

Flag Meaning
tx Log packet transmit operations
txerr Log transmit ring errors
rx Log changes to RCTL
rxfilter Log filtering of incoming packets
rxerr Log receive ring errors
unknown Log reads and writes of unknown registers
eeprom Log reads from the EEPROM
interrupt Log interrupts and changes to interrupt registers.

2.2. The Network Server

从零开始写一个网络栈是十分困难的,因此我们使用lwIP, 其是一个开源的轻量级TCP/IP协议套件,其中包含网络栈。You can find more information on lwIP here

The network server is actually a combination of four environments:

  • core network server environment (includes socket call dispatcher and lwIP)
  • input environment
  • output environment
  • timer environment

我们将实现图中标记为绿色的部分。
network Server

2.3. The Core Network Server Environment

For each user environment IPC, the dispatcher in the network server calls the appropriate BSD socket interface function provided by lwIP on behalf of the user.

Regular user environments do not use the nsipc_* calls directly. Instead, they use the functions in lib/sockets.c, which provides a file descriptor-based sockets API.

there is a key difference between file server and network server. BSD socket calls like accept and recv can block indefinitely. Since this is unacceptable, the network server uses user-level threading to avoid blocking the entire server environment.

In addition to the core network environment there are three helper environments. Besides accepting messages from user applications, the core network environment’s dispatcher also accepts messages from the input and timer environments.

Part A: Initialization and transmitting packets

我们需要为我们的内核添加时间概念。使用时钟中断,并用一个变量进行计数。

Exercise 1

Add a call to time_tick for every clock interrupt in kern/trap.c(in kern/time.c). Implement sys_time_msec and add it to syscall in kern/syscall.c so that user space has access to the time.

只是添加一个系统调用,很简单。

// 1
// LAB 4: Your code here.
	case (IRQ_OFFSET + IRQ_TIMER):
		// 回应8259A 接收中断。
		lapic_eoi();
		time_tick();
		sched_yield();
		break;
// 2
static int
sys_time_msec(void)
{
   
	// LAB 6: Your code here.
	return time_msec();
	// panic("sys_time_msec not implemented");
}
// 3
case SYS_time_msec:
		return sys_time_msec();

The Network Interface Card

Exercise 2

Browse Intel’s Software Developer’s Manual for the E1000. This manual covers several closely related Ethernet controllers. QEMU emulates the 82540EM.

我们应该浏览第2章以了解设备。 要编写驱动程序,还需要熟悉第3章和第14章以及4.1(尽管不是4.1的小节)。还要参考第13章。

82540em接口图

Receive and Transmit Description

  • Packet Reception
    • recognizing the presence of a packet on the wire,
    • performing address filtering,
    • storing the packet in the receive data FIFO,
    • transferring the data to a receive buffer in host memory,
      • buffer size RCTL.BSIZE & RCTL.BSEX
    • updating the state of a receive descriptor.
      • Status
      • Errors
      • Special

PCI Interface

PCI是外围设备互连(Peripheral Component Interconnect)的简称,是在目前计算机系统中得到广泛应用的通用总线接口标准:

  • 在一个PCI系统中,最多可以有256根PCI总线,一般主机上只会用到其中很少的几条。
  • 在一根PCI总线上可以连接多个物理设备,可以是一个网卡、显卡或者声卡等,最多不超过32个。
  • 一个PCI物理设备可以有多个功能,比如同时提供视频解析和声音解析,最多可提供8个功能。
  • 每个功能对应1个256字节的PCI配置空间

为了在引导期间执行PCI初始化,PCI代码遍历PCI总线以寻找设备。 当它找到设备时,它会读取其供应商ID和设备ID,并使用这两个值作为搜索pci_attach_vendor数组的键。 该数组由struct pci_driver条目组成,如下所示:

struct pci_driver {
   
    uint32_t key1, key2;
    int (*attachfn) (struct pci_func *pcif);
};

如果发现的设备的供应商ID和设备ID与数组中的条目匹配,则PCI代码会调用该条目的attachfn来执行设备初始化。

struct pci_func {
   
    struct pci_bus *bus;

    uint32_t dev;
    uint32_t func;

    uint32_t dev_id;
    uint32_t dev_class;

    uint32_t reg_base[6];
    uint32_t reg_size[6];
    uint8_t irq_line;
};

我们重点关注struct pci_func的最后三个成员,因为它们记录了设备的negotiated memory,I/O 和中断资源。 reg_basereg_size数组包含最多六个基址寄存器或BAR的信息。reg_base存储内存映射 I/O 区域的基地址(或 I/O 端口资源的基本 I/O 端口),reg_size包含reg_base中相应基值的大小(以字节为单位)或 I/O 端口数, 和irq_line包含分配给设备的 IRQ line 以进行中断。

pci_func_enable将会使能设备,协调资源,并将其填入struct pci_func

Exercise 3

Implement an attach function to initialize the E1000.

查看手册以及根据内核启动时的打印信息,我们可以知道 E1000 的 Vender ID = 0x8086, Device ID = 0x100E。

PCI: 00:00.0: 8086:1237: class: 6.0 (Bridge device) irq: 0
PCI: 00:01.0: 8086:7000: class: 6.1 (Bridge device) irq: 0
PCI: 00:01.1: 8086:7010: class: 1.1 (Storage controller) irq: 0
PCI: 00:01.3: 8086:7113: class: 6.80 (Bridge device) irq: 9
PCI: 00:02.0: 1234:1111: class: 3.0 (Display controller) irq
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值