网卡的RX Ring和TX Ring

1 简介

环形缓冲(ring buffer)是NIC处理数据包的一种通用数据结构,出现的原因是现代NIC基本使用DMA进行数据传输,作为一种高效简单[1]的数据结构,环形缓冲很

适合这种大吞吐的场景。在NIC中分成了RX Ring和TX Ring两种缓冲,分别负责接收和传输数据包。环形缓冲的使用维护涉及到NIC硬件、驱动、DMA控制器三

方。接下来的内容将以环形缓冲的组成和代码示例去讲解RX Ring和TX Ring。

2 Ring Buffer的组成

从整体上讲,Ring Buffer由NIC上的一组寄存器(基地址寄存器、长度寄存器、Head寄存器和Tail寄存器)来描述,同时Buffer的空间则是通过在驱动初始化的时

候通过DMA接口分配,而具体的操作是通过一个叫做包描述符的数据结构完成。

网卡的RX Ring和TX Ring

图2-1 Ring Buffer结构图

2.1 包描述符

描述符(Packet Descriptor)用来表达一个数据包在缓冲区内的地址以及数据包在NIC中的状态(是否有异常发生)。这是一个硬件相关的数据结构,由NIC去规定该

结构的内容。描述符分成了接收描述符 (rx descriptor) 和传输描述符 (tx descriptor) 接收描述符是一个用来描述网卡接收的数据缓冲区首地址和硬件用于存储包信

息的数据结构。如下图所示是Intel 8254x系统NIC的接收描述符的结构,共64位。Buffer Address是NIC DMA 数据包的地址,灰色的部门是一些状态字段,这些

字段在NIC接收到数据包之后通过DMA直接进行修改。

网卡的RX Ring和TX Ring

描述符实际存放的位置在驱动分配的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而言,一共有四个寄存器,

网卡的RX Ring和TX Ring

图2-1 NIC RX Ring结构图(来自Intel文档)

描述符缓冲的基地址通过两个寄存器表示,分别是 RDBAL(Receive Descriptor Base Address Low) 用来表示 64bit 描述符基地址的低32位,类似的,

RDBAH(Receive Descriptor Base Address High) 表示 64bit 描述符基地址的高32位。 注意这里需要区分下,NIC在内存分配了两种缓冲区,一个是用于存储数据

包,一个用于存储描述符,这里的寄存器表示的都是描述符缓冲区的地址。

网卡的RX Ring和TX Ring

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

网卡的RX Ring和TX Ring

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

网卡的RX Ring和TX Ring

接收描述符尾指针寄存器

网卡的RX Ring和TX Ring

2.3 数据包缓冲区

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

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

struct i40e_rx_buffer {
    dma_addr_t dma;
#ifdef CONFIG_I40E_DISABLE_PACKET_SPLIT
    struct sk_buff *skb;
#else
    struct 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 */
};

参考

https://stackoverflow.com/questions/36625892/descriptor-concept-in-nic

https://en.wikipedia.org/wiki/Circular_buffer

https://wenfh2020.com/2021/12/29/kernel-tcp-receive/

网卡的RX Ring和TX Ring

本作品采用
知识共享署名 4.0 国际许可协议

进行许可。

Original: https://www.cnblogs.com/dennis-wong/p/16326890.html
Author: 成蹊0xc000
Title: 网卡的RX Ring和TX Ring

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/582762/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux显示IP和主机名

    (1) ifconfig:Linux ifconfig命令用于显示或设置网络设备。 语法: ifconfig [网络设备][down up -allmulti -arp -prom…

    Linux 2023年6月8日
    096
  • 句柄过多导致SSH失败

    现象描述 scp文件的时候,突然有一个节点拷贝失败了。以为免密被修改了,结果一问说原因是:句柄过多。 以前这种情况接触较少,就顺带查了一下资料。 句柄的定义 这个标题隐含的一个前提…

    Linux 2023年6月8日
    091
  • 【设计模式】Java设计模式-装饰者模式

    Java设计模式 – 装饰者模式 😄 不断学习才是王道🔥 继续踏上学习之路,学之分享笔记👊 总有一天我也能像各位大佬一样🏆原创作品,更多关注我CSDN: 一个有梦有戏的…

    Linux 2023年6月6日
    0134
  • Arrays.binarySearch方法

    Arrays .binarySearch(int[] arr,int b) 1,数组arr必须排序后调用查找b在arr数组中的下标是多少。 2,存在:返回在数组中的下标 不存在:返…

    Linux 2023年6月8日
    057
  • MySQL-连接数据库

    连接数据库在操作数据库之前,需要连接它,输入命令:mysql -u用户名 -p密码。 在你自己本机上连接数据库用上述方式是可以的,不过在平台上连接数据库还需要加上一句-h127.0…

    Linux 2023年6月8日
    082
  • 手把手教你在Linux系统下安装MongoDB

    1. 下载最新的stable版MongoDB [root@spirit-of-fire ~]# wget http://downloads.mongodb.org/linux/mo…

    Linux 2023年6月14日
    0104
  • 【socket】基于socket通信-线程上报温度

    线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变…

    Linux 2023年6月13日
    095
  • python入门基础知识五(for循环、公共操作与推导式)

    for循环 break终止循环 a = ‘abcd’ for i in a: … if i == ‘c’: … print("’c’ stands for ‘ce…

    Linux 2023年6月7日
    0114
  • NoteOfMySQL-07-索引

    1. 索引概述 创建索引的目的是为了优化数据库的查询速度,不添加索引的情况下需要遍历所有数据才能进行删、查、改等操作。 2. 索引存储类型 存储类型 支持的存储引擎 B型树(BTR…

    Linux 2023年6月14日
    080
  • 操作系统实现-boot.asm实现

    博客网址:www.shicoder.top微信:18223081347欢迎加群聊天 :452380935 这一次我们进入操作系统实现的真实编码, 这一次主要是完善对boot.asm…

    Linux 2023年6月13日
    0121
  • MySQL优化

    1.建立索引 (1)合理的索引能够加速数据读取效率,不合理的索引反而会拖慢响应速度; (2)索引越多,更新数据的速度越慢 (3)尽量在MyIsam作为引擎的时候使用索引 (4)可在…

    Linux 2023年6月7日
    055
  • Shell添加任务计划

    添加任务计划,每30分钟自动执行 /data1/scripts/chk_sds.sh mkdir /data1/scripts echo -e "if [ \ps -C …

    Linux 2023年5月28日
    068
  • 【证券从业】金融基础知识-第四章 股票03

    注1:后续学习并整理到第八章,全书完结后再合并成一个笔记进行源文件分享 注2:本章内容巨多,大约分为三篇文章记录消化 posted @2022-06-08 01:28 陈景中 阅读…

    Linux 2023年6月13日
    088
  • ABCD四个顺序执行方法,拓展性延申

    今天在群里,有人问 有几个void返回值&amp…

    Linux 2023年6月7日
    0113
  • Docker镜像安全的一些(初级)检测方法

    一些使用过的工具记录。 docker scan工具 这个是docker官方工具,参考文档:https://docs.docker.com/engine/scan/ 使用方法: 命令…

    Linux 2023年6月6日
    077
  • redis主从复制

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 特性: 运行在内存中的数据集工作方式 支持多种数据结构 提供不同级别的磁盘持…

    Linux 2023年5月28日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球