(undone) MIT6.S081 2023 学习笔记 (Day8: LAB7 networking)

网页:https://pdos.csail.mit.edu/6.S081/2023/labs/net.html


任务1:In this lab you will write an xv6 device driver for a network interface card (NIC). (doing)

你将使用一种名为E1000的网络设备来处理网络通信。对于xv6(以及你编写的驱动程序)来说,E1000看起来就像一块连接到真实以太局域网(LAN)的真实硬件。实际上,你的驱动程序将要与之通信的E1000是由qemu提供的模拟设备,连接到一个同样由qemu模拟的局域网。在这个模拟的局域网上,xv6("客户机")的IP地址是10.0.2.15。Qemu还安排了运行qemu的计算机在局域网上显示为IP地址10.0.2.2。当xv6使用E1000向10.0.2.2发送数据包时,qemu会将数据包传递到运行qemu的(真实)计算机("主机")上的相应应用程序。

你将使用QEMU的"用户模式网络栈"。QEMU的文档中有更多关于用户模式网络栈的信息,可以在这里找到。我们已经更新了Makefile,以启用QEMU的用户模式网络栈和E1000网卡。

Makefile 配置了 QEMU,将所有传入和传出的数据包记录到你的实验目录中的 packets.pcap 文件中。查看这些记录可能有助于确认 xv6 是否正在发送和接收你预期的数据包。要显示记录的数据包,可以使用以下命令:

bash 复制代码
tcpdump -XXnr packets.pcap

我们为本次实验向 xv6 仓库添加了一些文件。文件 kernel/e1000.c 包含了 E1000 的初始化代码以及用于发送和接收数据包的空函数,你需要填写这些函数。文件 kernel/e1000_dev.h 包含了 E1000 定义的寄存器和标志位的定义,这些内容在 Intel E1000 软件开发手册中有详细描述。文件 kernel/net.c 和 kernel/net.h 包含了一个简单的网络栈,实现了 IP、UDP 和 ARP 协议。这些文件还包含了一个用于存储数据包的灵活数据结构,称为 mbuf。最后,文件 kernel/pci.c 包含了在 xv6 启动时在 PCI 总线上搜索 E1000 网卡的代码。

这一次 LAB 讲义的内容太多了,我们直接看源码吧。

从讲义来看,这一次要通过的测试为 nettests,需要先在一个窗口运行 make server,再启动 xv6,运行 nettests

我们运行后陷入卡死状态,如下:

OK,那就先来看 nettests.c 源码,先从 main 看起:

c 复制代码
int
main(int argc, char *argv[])
{
  int i, ret;
  // 这个端口号使用 -DNET_TESTS_PORT 在编译阶段定义
  uint16 dport = NET_TESTS_PORT;

  printf("nettests running on port %d\n", dport);
  
  // 测试 ping 命令是否能运行正常
  printf("testing ping: ");
  ping(2000, dport, 1);
  printf("OK\n");
  
  // 测试单进程 100 次 ping 
  printf("testing single-process pings: ");
  for (i = 0; i < 100; i++)
    ping(2000, dport, 1);
  printf("OK\n");
  
  // 申请 10 个 子进程一起 ping
  printf("testing multi-process pings: ");
  for (i = 0; i < 10; i++){
    int pid = fork();
    if (pid == 0){
      ping(2000 + i + 1, dport, 1);
      exit(0);
    }
  }
  for (i = 0; i < 10; i++){
    wait(&ret);
    if (ret != 0)
      exit(1);
  }
  printf("OK\n");
  
  // 测试 DNS
  printf("testing DNS\n");
  dns();
  printf("DNS OK\n");
  
  // 上述都没问题,则所有测试通过 
  printf("all tests passed.\n");
  exit(0);
}

从 main 函数来看,我们需要关心的只有两个函数 ping() 和 dns()。

先来看 ping():

c 复制代码
static void
ping(uint16 sport, uint16 dport, int attempts)
{
  int fd;
  char *obuf = "a message from xv6!";
  uint32 dst;

  // 10.0.2.2, which qemu remaps to the external host,
  // i.e. the machine you're running qemu on.
  dst = (10 << 24) | (0 << 16) | (2 << 8) | (2 << 0);

  // you can send a UDP packet to any Internet address
  // by using a different dst.
  
  if((fd = connect(dst, sport, dport)) < 0){
    fprintf(2, "ping: connect() failed\n");
    exit(1);
  }

  for(int i = 0; i < attempts; i++) {
    if(write(fd, obuf, strlen(obuf)) < 0){
      fprintf(2, "ping: send() failed\n");
      exit(1);
    }
  }

  char ibuf[128];
  int cc = read(fd, ibuf, sizeof(ibuf)-1);
  if(cc < 0){
    fprintf(2, "ping: recv() failed\n");
    exit(1);
  }

  close(fd);
  ibuf[cc] = '\0';
  if(strcmp(ibuf, "this is the host!") != 0){
    fprintf(2, "ping didn't receive correct payload\n");
    exit(1);
  }
}

大致来看,就是使用 connect 系统调用去连接 localhost(outside of qemu) 的一个端口,然后发送一个消息 "a message from xv6!",再接受一个消息 "this is the host!"

TODO: here 我们来仔细研究一下,ping命令这个过程会有哪些包的来往

TODO: here DNS


相关推荐
xuhaoyu_cpp_java1 小时前
项目学习(三)分页查询
java·经验分享·笔记·学习
小宋加油啊3 小时前
机械臂抓取物体 PVN3D算法调研学习
学习·算法·3d
Xzh04234 小时前
AI Agent 学习路线(Java 后端方向)
java·人工智能·学习
Cloud_Shy6184 小时前
解读《Effective Python 3rd Edition》:从练气到老魔(第五章 Item 33 - 35)
开发语言·人工智能·笔记·python·学习方法
做cv的小昊4 小时前
计算机图形学:【Games101】学习笔记08——光线追踪(辐射度量学、渲染方程与全局光照、蒙特卡洛积分与路径追踪)
图像处理·笔记·学习·计算机视觉·游戏引擎·图形渲染·概率论
星恒随风4 小时前
C++ 类和对象入门(五):初始化列表、explicit 和 static 成员详解
开发语言·c++·笔记·学习·状态模式
sensen_kiss6 小时前
CPT304 SoftwareEngineeringII 软件工程 2 Pt.8 软件测试 (Software Testing)(上)
学习·软件工程
力学与人工智能6 小时前
PPT分享 | 洛桑联邦理工学院魏震:深度几何学习在工业设计优化中的应用
学习·优化·工业设计·深度几何学习·洛桑联邦理工学院
sensen_kiss8 小时前
CPT304 SoftwareEngineeringII 软件工程 2 Pt.9 软件测试 (Software Testing)(下)
学习·软件工程
wu_ye_m8 小时前
学习c语言第35天 函数声明和定义
c语言·开发语言·学习