e1000收发包分析

发布时间:2026/10/10 23:53:02

e1000收发包分析 前言上次看了 lan9118 收发包过程PIO 模式现代网卡基本千兆cpu直接搬运性能不太行了所以需要DMA开始看带dma的pci千兆网卡了能用qemu跑起来的重点看dma搬运用e1000经过查询发现有个 MIT 的著名操作系统课程 6.828 / 6.S081 的 Lab 就是让学生为 E1000 编写驱动网上有大量可以参考的学习资源就用这个吧vx6 网络实验目标DMA (Direct Memory Access)和描述符环 (Descriptor Ring)vx6 网络实验概念6.828 操作系统课xv6 操作系统做什么在 xv6 教学操作系统上亲手为一个E1000 网卡实现设备驱动。需要完成的核心任务有两个实现发送 (e1000_transmit)实现接收 (e1000_recv) 函数过程https://pdos.csail.mit.edu/6.828/2020/labs/net.html网页是英文但已有不少优秀的前辈做过这个实验还翻译成了中文可以直接搜索参考按照这个网页的步骤里面提供了一些参考资料如vx6的手册e1000的手册可以参考其中的哪些章节我看了然后发现自己还是不会写接收和发送函数于是决定给自己降低难度查找做过这个实验的前辈的代码我的任务是理解代码环境VMwareUbuntu 20.04_64尽量用较新的版本不然risv gcc工具链不太好搞安装库sudo apt install git sudo apt install make sudo apt install gcc sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu sudo apt install vim下载 riscv64-elf-ubuntu-20.04-gcc-nightly-2023.09.27-nightly.tar.gz 这是编译好的二进制解压可以了。太早的版本只能下载源码编译编译尚未成功已放弃解压bin路径加入PATHtar -zxvf riscv64-elf-ubuntu-20.04-gcc-nightly-2023.09.27-nightly.tar.gz export PATH/....../riscv/bin:$PATH下载 vx6源码切到 net 分支git clone git://g.csail.mit.edu/xv6-labs-2020 git checkout net开始编译make clean make qemu然后就报错了user/sh.c:58:1: error: infinite recursion detected [-Werrorinfinite-recursion] 58 | runcmd(struct cmd *cmd) | ^~~~~~修改vim Makefile CFLAGS ... -Wno-infinite-recursion再次 make qumu可以啦xv6 kernel is booting hart 2 starting hart 1 starting init: starting sh $已进入 qemu退出 qemuctrla 松开再按x发包测试在一个终端cd xv6-labs-2020目录运行make server命令这启动了一个服务器程序监听来自 xv6 的 UDP 数据包另一个终端运行make qemu命令来启动 xv6 操作系统进到$后执行nettests命令这会向 IP 地址为10.0.2.2的“主机”发送一个 UDP 数据包。在 QEMU 的虚拟网络里10.0.2.2这个 IP 地址被映射到了真实主机Host。因此xv6 协议栈会调用e1000_transmit()函数来发送这个数据包直接执行是不可能收到回复的因为现在还没有实现发送函数 e1000_transmit()也没有实现 接收函数过程分析相关概念在实际看代码之前先来看些基本概念DMADMA直接内存访问的核心原理CPU 不搬运数据而是将“内存缓冲区地址”和“描述符环”的物理地址告诉网卡网卡内置的 DMA 控制器会通过 PCIe 总线自行读写这些物理内存。mbuf 数据包仓库tx/rx ring 地址簿 描述符发送描述符e1000 手册 3.3.3 表 3.9vx6里的简化相比 linux 内核定义【kernel/e1000_dev.h】 struct tx_desc { uint64 addr; uint16 length; uint8 cso; uint8 cmd; uint8 status; uint8 css; uint16 special; } // [E1000 3.2.3] struct rx_desc { uint64 addr; /* Address of the descriptors data buffer */ uint16 length; /* Length of data DMAed into data buffer */ uint16 csum; /* Packet checksum */ uint8 status; /* Descriptor status */ uint8 errors; /* Descriptor Errors */ uint16 special; };mbuf【kernel/net.h】 struct mbuf { struct mbuf *next; // the next mbuf in the chain char *head; // the current start position of the buffer unsigned int len; // the length of the buffer char buf[MBUF_SIZE]; // the backing store };初始化vx6的代码里提供了初始化函数e1000_init()e1000_init 把tx_ring数组首元素的地址写入 TDBAL ​ 数组长度写入 TDLEN ​ TDH写0 ​ TDT写0这里我就不贴代码了网上能直接搜索到只记录过程。发包过程网卡硬件提供e1000手册3.4​ 发送描述符基地址寄存器 TDBAL​ 发送描述符长度寄存器 TDLEN​ 发送描述符头存器 TDH​ 发送描述符尾存器 TDT软件​ 定义 tx_ring[]​ e1000_init​ 把tx_ring数组首元素的地址写入 TDBAL​ 数组长度写入 TDLEN​ TDH写0​ TDT写0​ 发送函数​ 接收协议栈组装好的 mbuf​ 读TDT知道可用的描述位置即tx_ring数组下标发第1个包是0一次加1​ 用下标在tx_ring数组里取到 描述符 desc​ 检查 desc 里 DD位1表示desc对应的上一个数据包已处理完成完成​ 释放旧的 mbuf​ 用mbuf里的信息填充 desc 数据包的内存地址长度​ mbufer地址保存到 tx_mbufs数组用于下次使用前释放内存​ 更新 TDT硬件​ **网卡硬件内部的状态机FSM**轮询发现 TDT ! TDH​ 从当前TDH指向的位置读取描述符Descriptor的内容地址、长度、CMD 位。​ 解析出addr和length。​ 发起PCIe 读事务DMA 读去内存中读取实际的mbuf数据。​ 数据读回来放入网卡内部的 FIFO再通过网线发出去​回写描述符的status字段: 置位E1000_TXD_STAT_DDDescriptor Done位。收包过程网卡硬件提供​ RDH 硬件下一个要写的位置​接收尾指针寄存器RDT指向的是“驱动已经处理并回填好的最后一个描述符的索引”软件​ 定义 rx_ring[]​ 定义 rx_mbufs[]​ e1000_init​ 把rx_ring数组首元素的地址写入 RDBAL​ 数组长度写入 RDLEN​ RDH写0​ RDT写 RX_RING_SIZE - 1​ 接收函数e1000_intr e1000_recv e1000_recv while(1) 根据 RDT 得到 rx_index 用 rx_index 得到 rx_ring[rx_index] 描述符 判断描述符的 DD //网卡硬件在将数据包 DMA 搬运到内存完成后由网卡硬件自动置 1 的标志位 0 break 1 继续向下执行 用描述符-length 更新 rx_mbufs[rx_index]-len net_rx 把数据 rx_mbufs[rx_index] 给到协议栈 分配新 mbuf 更新 desc-addr 清除 desc-status 0 更新 RDT总结接收包完整过程e1000驱动初始化基址预填所有空仓库​ rx_ring数组首元素的地址写入 RDBAL​ 用mbufalloc()分配好所有空mbuf把它们的物理地址head一个一个填进rx_ring里每个描述符的addr字段。当数据包从网线进入网卡​ 网卡硬件DMA根据RDH找到用rx_ring[]里哪个描述符​ 从描述符里读出物理地址把数据搬运到对应物理地址​ 描述符DD写1中断通知cpucpu用注册好的中断函数处理e1000_intr调用接收函数接收函数​ 传递 **mbuf结构体的指针虚拟地址**给到了协议栈net.c而不是物理地址​ 分配新的mbuf​ 把新mbuf的物理地址填回同一个描述符。​ 清空status去掉DD​更新RDT协议栈​ 通过**mbuf结构体的指针虚拟地址**去读取mbuf-head里面存的才是物理地址但协议栈不需要知道因为 xv6 做了直接映射虚拟地址可以直接加减偏移得到物理地址参考vx6 网络实验 https://pdos.csail.mit.edu/6.828/2020/labs/net.html
延伸阅读

更多相关文章

2026/10/10 23:52:36

std::variant与std::visit:从访问者模式到类型安全联合

访问者&#xff08;Visitor&#xff09;模式想解决的是&#xff1a;有一族结构相对稳定的类型&#xff0c;上面要挂多种易变的操作&#xff08;求值、打印、序列化……&#xff09;&#xff0c;又不想在每个类里无限加成员函数&#xff0c;也不想用一长串 if (dynamic_cast<…

2026/10/8 4:15:58

GLYKEN可莱康二十年产业积累,探索燕窝肽健康产业新未来

近年来&#xff0c;随着消费者对健康意识的日益提高&#xff0c;大健康产业正在迎来一次重要的转型&#xff0c;正从传统滋补迈向科学营养和日常管理的新阶段。在这样的背景下&#xff0c;GLYKEN&#xff08;可莱康&#xff09;在燕窝肽领域全力以赴&#xff0c;借助科技创新为…

2026/10/10 23:46:48

以 Gradio 破局,让 MCP 服务触达云端:TaoToken 统一 Key 通道实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 23:46:48

GitHub热点项目精选:从信息过载到高效筛选的实操方法论

1. 从一份空白输入说起&#xff1a;为什么"热点精选"类内容值得认真做拿到这个标题的时候&#xff0c;我第一反应是愣了一下——项目正文是空的&#xff0c;关键词是空的&#xff0c;摘要描述也是空的&#xff0c;只有一行"2026-10-02 GitHub 热点项目精选"…

2026/10/10 23:46:48

药丸缺陷检测数据集:VOC与YOLO格式转换及YOLOv8训练实战指南

简介&#xff1a;这份药丸表面缺陷检测数据集以Pascal VOC和YOLO两种主流格式整理&#xff0c;覆盖污染、裂纹、合格品三个类别&#xff0c;共2759张真实图片与2798个标注框&#xff0c;类别分布均衡&#xff0c;适合入门目标检测或构建药品质检视觉模型时直接训练、验证与迁移…

2026/10/10 23:46:48

Transformer时间序列预测实战:数据预处理与模型改造指南

简介&#xff1a;本资源是一份面向深度学习初学者与时间序列建模实践者的Transformer实战项目&#xff0c;聚焦将NLP领域里程碑模型迁移应用于天气预报、电力负荷预测、金融时序分析等典型场景。项目完整复现了Transformer编码器-解码器架构&#xff0c;涵盖位置编码、多头自注…

2026/10/10 23:46:48

涉密内网办公系统CKEditor格式保留插件选型与落地配置

接手过这类涉密内网办公系统改造的人&#xff0c;大概率都经历过相似的"至暗时刻"&#xff1a;文印室老师傅把Word红头文件直接CtrlC进浏览器&#xff0c;排版全散&#xff1b;科研人员从内部资料站复制一段带公式的内容&#xff0c;粘进去全是乱码&#xff1b;最麻烦…

2026/10/10 23:41:47

Python+OpenCV车道线检测实战:环境搭建、参数调优与GUI避坑指南

简介&#xff1a;这份资源面向正在做毕设、课程设计或期末大作业的学生&#xff0c;以及希望入门计算机视觉与图像处理方向的Python学习者&#xff0c;提供一套可直接运行的车道线检测完整项目。源码基于Python与OpenCV实现&#xff0c;覆盖图像加载、灰度化与高斯滤波预处理、…

2026/10/10 7:31:36

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起&#xff1a;为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高&#xff0c;很多人第一次听到会以为是某个新模型的名字&#xff0c;其实它更像是一种思路——把Jev模型的能力当作底座&#xff0c;通过Agent的方式去接管浏览器&#xf…

2026/10/9 20:15:56

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同"&#xff1a;多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西&#xff0c;大概率会有一种感觉&#xff1a;单个 Agent 能做的事情&#xff0c;其实很快就摸到天花板了。你给它一个提示词&#xff0c;挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 0:04:53

从逻辑门到计算机:数字电路核心原理与全加器搭建实战

如果你拆过一台旧电脑的主板&#xff0c;盯着那些黑乎乎的小芯片看上一会儿&#xff0c;可能会冒出同一个疑问&#xff1a;这堆引脚密集的元件&#xff0c;到底是怎么“变”出那么复杂的应用的&#xff1f;答案并不在某个神秘的部件里&#xff0c;而是在所有芯片内部都在反复使…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑