网卡的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)

大家都在看

  • 从台积电增产28纳米产线看袁项之争

    由台积电增建南京28纳米产线引发的袁项之争,他们的观点和论据,我总结一下,大致如下: 袁:引进外资,鼓励竞争,产生鲶鱼效应,让芯片代工产业快速活跃起来,百花齐放,消费者受益。并举了…

    Linux 2023年6月6日
    093
  • kubenetes无法创建pod/创建RC时无法自动创建pod的问题

    一、问题概述 问题1:虽然每次通过yaml创建rc都显示成功了,但是kubectl get pod却没显示任何的pod. 问题2:直接通过yaml创建pod提示apixxx 问题3…

    Linux 2023年6月14日
    0108
  • 保姆教程系列一、Linux搭建Nacos

    前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 简介: Nacos是阿里巴巴开源的一款支持服务注册与发现,配置管理以及微服务管理的组件。用来取代以前常用的注册中心…

    Linux 2023年6月14日
    095
  • ret2syscall

    博客网址:www.shicoder.top微信:18223081347欢迎加群聊天 :452380935 这一次我们来深入分析下更难的栈溢出题目 ret2syscall 首先还是先…

    Linux 2023年6月13日
    0126
  • 4-初识Django Admin

    初识Django Admin Django Admin是Django为我们提供的网站后台管理应用,通常网站,个人博客,CMS等都会有个后台管理界面,这个界面只有管理员权限的用户才能…

    Linux 2023年6月7日
    092
  • bash 教程-2 shell 字符串 转义 模式扩展 特殊符号 [MD]

    我的GitHub 我的博客 我的微信 我的邮箱 bqt20094 baiqiantao@sina.com 字符串的表示 shell 中的字符串可以用 单&am…

    Linux 2023年5月28日
    067
  • php+nginx环境搭建

    1、安装基础环境: yum -y install gcc bison bison-devel zlib-devel libmcrypt-devel mhash-devel open…

    Linux 2023年6月6日
    087
  • 部署前后端为独立的 Docker 节点

    在『服务器部署 Vue 和 Django 项目的全记录』一文中,介绍了在服务器中使用 Nginx 部署前后端项目的过程。然而,当 Web 应用流量增多时,需要考虑负载均衡、流量分发…

    Linux 2023年6月7日
    0116
  • etcd 与 redis使用场景

    etcd etcd主要讲究服务发现, 有监听机制, 并能保持数据的一直性, 高可用 etcd的红火来源于kurbernetes用etcd做服务发现 etcd是一种分布式存储,更强调…

    Linux 2023年5月28日
    0101
  • podman对容器映像签名和分发

    熟悉podman 如何使用 Podman 对容器映像进行签名和分发 熟悉podman 此示例容器将运行一个非常基本的 httpd 服务器,该服务器仅为其索引页提供服务 [root@…

    Linux 2023年6月7日
    096
  • EKS助力小白实践云原生——通过k8s部署wordpress应用

    目前云原生在大厂已经有了充分的实践,也逐渐向小厂以及非互联网公司推广。适逢12月20日,腾讯云原生【燎原社】精心打造了云原生在线技术工坊,让零基础的同学也能快速入门和实践 Dock…

    Linux 2023年6月13日
    085
  • 【填空题】考研数据结构填空题整理

    数据结构填空题 题源来自《算法与数据结构考研试题精析》、《王道数据结构》在Liang’s Blog所著的文章上补充考点,仅供参考学习 一、概论 数据元素 是数据的基本单…

    Linux 2023年6月13日
    0119
  • python学习

    目录: 1、课程推荐以及书籍推荐 2、学习记录 2.1:无 1. 实践过程 廖雪峰的官方网站 2. 学习记录 2.1 无: posted @2022-02-12 19:44 风御之…

    Linux 2023年6月13日
    0104
  • 安装Redis6.x

    gcc安装完毕以后,接下来可以按照redis了,解压redis6安装包 tar -zxvf redis-6.0.9.tar.gz * 查看日志,表示运行成功 vim /usr/lo…

    Linux 2023年5月28日
    077
  • CSRankings: Computer Science Rankings

    CSRankings is a metrics-based ranking of top computer science institutions around the worl…

    Linux 2023年6月13日
    0121
  • Windows server 2008 域控制器

    Windows的网络架构 Windows的网络架构大致分为: 工作组架构 域架构 工作组架构:工作组是由一组通过网络连接在一起的计算机组成,组内的计算机可以共享本机的文件,打印机等…

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