首页 > 其他分享 >【XV6】 networking

【XV6】 networking

时间:2024-02-14 19:11:06浏览次数:30  
标签:networking idx mbuf rx XV6 ring e1000 E1000

代码:https://github.com/JasenChao/xv6-labs.git

E1000网络设备驱动

题目已经在kernel/e1000.c中给出了E1000的初始化函数和发送接收函数,要求完善发送和接收的功能。

其他相关的代码,上层的网络协议在kernel/net.ckernel/net.h中。

PCI总线上搜索网卡的代码在kernel/pci.c中:

// tell the e1000 to reveal its registers at
// physical address 0x40000000.
base[4+0] = e1000_regs;

e1000_init((uint32*)e1000_regs);

e1000_init()函数配置了E1000为DMA模式,预备了多个缓冲区组成了两个环,用来存储需要发送和接收的消息,相当于一个队列,两个环配置为大小为 RX_RING_SIZETX_RING_SIZE

发送函数

net.c 中的网络堆栈需要发送数据包时,e1000_transmit函数使用要发送的数据包mbuf。发送完成的数据包需要确保mbuf最终被释放,同时在传输数据包完成后,mbufs的status标志位会变为E1000_TXD_STAT_DD。

int
e1000_transmit(struct mbuf *m)
{
  //
  // Your code here.
  //
  // the mbuf contains an ethernet frame; program it into
  // the TX descriptor ring so that the e1000 sends it. Stash
  // a pointer so that it can be freed after sending.
  //
  acquire(&e1000_lock);
  int idx = regs[E1000_TDT];                              // 取E1000_TDT寄存器的值作为队列尾部
  if ((tx_ring[idx].status & E1000_TXD_STAT_DD) == 0) {   // 如果发送已完成,则退出
    release(&e1000_lock);
    return -1;
  }

  if (tx_mbufs[idx]) mbuffree(tx_mbufs[idx]);             // 如果mbuf非空,则释放掉

  tx_mbufs[idx] = m;                                      // mbuf指向需要发送的m
  tx_ring[idx].length = m->len;
  tx_ring[idx].addr = (uint64)m->head;
  tx_ring[idx].css = tx_ring[idx].cso = tx_ring[idx].special = 0;
  tx_ring[idx].cmd = E1000_TXD_CMD_RS | E1000_TXD_CMD_EOP;
  regs[E1000_TDT] = (idx + 1) % TX_RING_SIZE;             // 更新寄存器

  release(&e1000_lock);
  return 0;
}

接收函数

接收函数应该扫描队列,将新收到的mbuf传送到上层的网络协议中,也就是net_rx(),然后用空的mbuf代替。

static void
e1000_recv(void)
{
  //
  // Your code here.
  //
  // Check for packets that have arrived from the e1000
  // Create and deliver an mbuf for each packet (using net_rx()).
  //
  int idx = (regs[E1000_RDT] + 1) % RX_RING_SIZE;
  while(rx_ring[idx].status & E1000_RXD_STAT_DD) {
    rx_mbufs[idx]->len = rx_ring[idx].length;
    net_rx(rx_mbufs[idx]);                            // mbuf送到上层协议

    // 清空mbuf
    rx_mbufs[idx] = mbufalloc(0);
    rx_ring[idx].status = 0;
    rx_ring[idx].addr = (uint64)rx_mbufs[idx]->head;
    regs[E1000_RDT] = idx;
    idx = (idx + 1) % RX_RING_SIZE;
  }
}

测试结果

直观的测试可以用两个xv6目录的终端,分别运行make servermake qemu,在make qemu的xv6中运行nettests,然后可以在make server的终端里看到测试结果。

也可以使用make grade测试,结果如下:

== Test running nettests == 
$ make qemu-gdb
(3.7s) 
== Test   nettest: ping == 
  nettest: ping: OK 
== Test   nettest: single process == 
  nettest: single process: OK 
== Test   nettest: multi-process == 
  nettest: multi-process: OK 
== Test   nettest: DNS == 
  nettest: DNS: OK 

标签:networking,idx,mbuf,rx,XV6,ring,e1000,E1000
From: https://www.cnblogs.com/JasenChao/p/18015452

相关文章

  • [MIT 6.S081] Lab: Copy-on-Write Fork for xv6
    Lab:Copy-on-WriteForkforxv6在这个实验中,我们要为xv6实现cowfork。Implementcopy-onwrite根据写时复制的方式,我们在复制页面的时候应该采用的是将父级的物理页面映射到子级的页面,因此我们需要修改kernel/vm.c中的uvmcopy,将页面复制修改为映射的方式,同时应当将......
  • MIT 6.1810 Lab: Copy-on-Write Fork for xv6
    lab网址:https://pdos.csail.mit.edu/6.828/2022/labs/cow.htmlxv6Book:https://pdos.csail.mit.edu/6.828/2022/xv6/book-riscv-rev3.pdfImplementcopy-on-writefork这部分需要我们实现写时拷贝,题目给出解决方案为,当fork时,将父子进程的页表项都设置为只度,当发生写错误时,在处......
  • [MIT 6.S081] Lab: xv6 lazy page allocation
    Lab:xv6lazypageallocationEliminateallocationfromsbrk()这一步比较简单,直接在sys_sbrk中将分配内存改为对内存大小进行修改而不分配内存即可。uint64sys_sbrk(void){intaddr;intn;if(argint(0,&n)<0)return-1;addf=myproc()->sz;my......
  • xv6book阅读 chapter3
    页表是硬件提供进程间隔离的方法之一,并通过它来实现虚拟地址和物理地址之间的转换,通过页表可以决定进程能够访问物理内存的哪些部分,xv6提供了一些小技巧,比如在不同的地址空间中可以映射相同的trampolinepage,trampoline是用来辅助用户模式进入内核模式的,所以它可被共用。1分页硬......
  • [MIT 6.S081] Lab: Xv6 and Unix utilities
    Lab:Xv6andUnixutilitiesGradesleepsleep格式如下sleep5这边需要使用kernal/stat.h中的sleep系统调用,并将参数转化为传入。#include"kernel/types.h"#include"kernel/stat.h"#include"user/user.h"intmain(intargc,char*argv[]){if(......
  • xv6book阅读 chapter2
    一个操作系统至少应该满足三个需求:多路复用、隔离、交互。本章主要介绍如何组织操作系统来实现以上的三个需求,本文关注的是一种围绕单核进行设计的方法,这种设计是被许多uinx操作系统所使用的。Xv6运行在多核RISC-V微处理器上时,它的许多低级功能(例如,它的进程实现)是特定于RISC-V的......
  • xv6 磁盘中断流程和启动时调度流程
    本文讲述xv6中的一些细节流程,还有对之前文中遗留的问题做一些补充说明,主要有以下几个问题:一次完整的磁盘中断流程进入调度器后的详细流程sched函数中的条件判断scheduler函数中为什么要周期性关中断一次完整的磁盘流程此节讲述完整的磁盘读写流程,读写的流程总体差不多,这里以读......
  • xv6 想到什么记什么
    xv6不同视频里安装了不同版本两个我都装了一个是xv6-public点进去是深大视频里配套的i386arch另一个是xv6risc-V就是另一个我参考的视频里 运行xv6用的QEMU是个linux上的模拟器xv6又是个unix变体简易版系统所以最终说起来这个系统是一个程序,跑在一个模拟器程序里,模......
  • xv6 start
    操作系统必须满足三个要求:多路,隔离,交流。用户模式和管理模式强隔离要求应用程序和操作系统之间有一个硬边界。如果应用程序出错,我们不希望操作系统失败或其他应用程序出错,相反操作系统应该能够清理失败的应用程序并继续运行其他应用程序。为了实现强隔离,操作系统必须安排应用程......
  • xv6 mmap
    inlinux调用mmap,会申请一段内存空间(文件的内存映射部分),并且自动映射到指定的文件内存映射部分。mmapvoid*mmap(void*addr,size_tlength,intprot,intflags,intfd,off_toffset);addr为用户指定的内存起始地址,为0时由系统分配。length制定映射的长度,单位是字节。......