当前位置: 首页 > news >正文

以太网扫盲(二)网卡的环形缓冲区:RX Ring和TX Ring

1 简介

环形缓冲(ring buffer)是NIC处理数据包的一种通用数据结构,出现的原因是现代NIC基本使用DMA进行数据传输,作为一种高效简单的数据结构,环形缓冲很适合这种大吞吐的场景。在NIC中分成了RX Ring和TX Ring两种缓冲,分别负责接收和传输数据包。环形缓冲的使用维护涉及到NIC硬件、驱动、DMA控制器三方。接下来的内容将以环形缓冲的组成和代码示例去讲解RX Ring和TX Ring。

2 Ring Buffer的组成

从整体上讲,Ring Buffer由NIC上的一组寄存器(基地址寄存器、长度寄存器、Head寄存器和Tail寄存器)来描述,同时Buffer的空间则是通过在驱动初始化的时候通过DMA接口分配,而具体的操作是通过一个叫做包描述符的数据结构完成。
image

2.1 包描述符

描述符(Packet Descriptor)用来表达一个数据包在缓冲区内的地址以及数据包在NIC中的状态(是否有异常发生)。这是一个硬件相关的数据结构,由NIC去规定该结构的内容。描述符分成了接收描述符 (rx descriptor)传输描述符 (tx descriptor) 接收描述符是一个用来描述网卡接收的数据缓冲区首地址和硬件用于存储包信息的数据结构。如下图所示是Intel 8254x系统NIC的接收描述符的结构,共64位。Buffer Address是NIC DMA 数据包的地址,灰色的部分是一些状态字段,这些字段在NIC接收到数据包之后通过DMA直接进行修改。

描述符实际存放的位置在驱动分配的DMA内存中,在驱动的Open接口(即启用该设备的时候)进行分配。在i40e中通过调用dma_alloc_coherent完成。

rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL);

i40e 使用共用体 i40e_rx_desc 表示一个接收描述符, 在open阶段驱动会给每个描述符分配一个pkt_addr,NIC用该地址作为DMA数据包的起始地址。当包完整的接收到DMA内存中后,NIC又会通过该描述符设置状态。值得注意的是这些操作都是通过NIC固件完成的。在i40e_rx_desc 中,pkt_addr表示缓冲区DMA的首地址;

wb结构是NIC完成和DMA的包传输之后,向内存中写入的状态,rss_hash是NIC计算的哈希。

union i40e_32byte_rx_desc {struct {__le64  pkt_addr; /* Packet buffer address */__le64  hdr_addr; /* Header buffer address *//* bit 0 of hdr_buffer_addr is DD bit */__le64  rsvd1;__le64  rsvd2;} read;struct {struct {struct {union {__le16 mirroring_status;__le16 fcoe_ctx_id;} mirr_fcoe;__le16 l2tag1;} lo_dword;union {__le32 rss; /* RSS Hash */__le32 fcoe_param; /* FCoE DDP Context id *//* Flow director filter id in case of* Programming status desc WB*/__le32 fd_id;} hi_dword;} qword0;struct {/* status/error/pktype/length */__le64 status_error_len;} qword1;struct {__le16 ext_status; /* extended status */__le16 rsvd;__le16 l2tag2_1;__le16 l2tag2_2;} qword2;struct {union {__le32 flex_bytes_lo;__le32 pe_status;} lo_dword;union {__le32 flex_bytes_hi;__le32 fd_id;} hi_dword;} qword3;} wb;  /* writeback */
};

2.2 寄存器

上一节讲过环形缓冲通过NIC中一组寄存器去表示,本节我们就这些寄存器进行更详细的讨论。就rx而言,一共有四个寄存器:

描述符缓冲的基地址通过两个寄存器表示,分别是 RDBAL(Receive Descriptor Base Address Low) 用来表示 64bit 描述符基地址的低32位,类似的,RDBAH(Receive Descriptor Base Address High) 表示 64bit 描述符基地址的高32位。 注意这里需要区分下,NIC在内存分配了两种缓冲区,一个是用于存储数据包,一个用于存储描述符,这里的寄存器表示的都是描述符缓冲区的地址。


接受描述符长度寄存器,该值需要128字节(最大的cache line大小)对齐

接收描述符头指针寄存器,该寄存器是通过硬件控制。

接收描述符尾指针寄存器

2.3 数据包缓冲区

至此环形缓冲的内容就结束了,实际上环形缓冲指的是描述符的缓冲,真正存储数据包的起始地址存在描述符中。一个缓冲有一个对skb的引用,dma内存的地

址,和对物理页的引用构成。

struct i40e_rx_buffer {dma_addr_t dma;
#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT struct sk_buff *skb;
#elsestruct page *page;
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)__u32 page_offset;
#else__u16 page_offset;
#endif__u16 pagecnt_bias;
#endif /* CONFIG_I40E_DISABLE_PACKET_SPLIT */
};
http://www.jsqmd.com/news/580911/

相关文章:

  • 终端智能编程助手Claude Code:让自然语言驱动你的开发工作流
  • LuckyLilliaBot 多账号运行完整指南:深度解析与实战配置
  • 如何高效清理微信单向好友?WechatRealFriends让社交管理更简单
  • Phi-3-mini-4k-instruct-gguf详细步骤:健康检查、日志排查与服务管理命令
  • 笔记本电脑上如何语音输入?
  • 从零开始构建实用AI智能体:小白程序员专属教程(收藏版)
  • 第23课:从 Qt 串口通信到滑动式 APP 主界面,搭起板级交互入口
  • 讯飞输入法的语音输入,跨屏图标太大了。
  • seo关键字优化费用一般多少_seo关键字优化费用是一次性的吗
  • 如何通过GitHub加速计划/pa/patents-public-data实现专利数据挖掘与技术情报分析
  • LFM2.5-1.2B-Thinking-GGUF压力测试与性能调优:寻找最佳并发参数
  • 2026年毕业论文写作避坑:学术AI工具怎么选才靠谱?
  • 构建企业级devops流水线:基于快马平台实战集成gitlab ci与cd
  • 用C语言从零写一个Shell,吃透底层逻辑
  • Qwen3-14B知识问答效果展示:专业领域(法律/医疗/金融)回答质量评估
  • 革新游戏体验:League-Toolkit智能助手全方位提升你的英雄联盟之旅
  • GLM-4.1V-9B-Base效果展示:书法作品字体+内容+文化内涵中文解析
  • 轻量级API测试工具Postman便携版:解决开发痛点的创新方案
  • Tomato-Novel-Downloader:高性能小说下载工具的技术实践与应用指南
  • 快马平台一键生成ER图与SQL:三步完成数据库设计原型
  • Cogito 3B场景应用:如何用它做旅行规划与方案分析
  • 深度实战指南:Source Han Serif CN 开源字体完整配置与优化方案
  • 从“聊天工具“到“数字徒弟“:一文看懂什么是 AI Agent
  • 零基础极速上手教程:用AI建站工具10分钟搭出专业网站
  • 一对一语言私人老师平台怎么选?五大维度深度对比与推荐 - GrowthUME
  • 5分钟快速上手:如何将STL文件转换为STEP格式实现跨平台设计协作?
  • Kafka Connect管理指南:使用可视化工具简化数据同步与集群监控
  • 有声书实证研究的现状与展望
  • 第24课:让 Qt 接上字符驱动、XADC 波形与 LED 控制,正式迈进 Qt 驱动实战
  • MPC-BE:3个核心功能打造Windows平台终极开源播放器解决方案