• dpdk 程序如何配置网卡收发包队列描述符配置?


    问题描述

    dpdk 程序在配置网卡队列时会涉及收发包队列描述符数量配置问题,收发包描述符的数量看似是一个简单的配置,却对转发性能有着一定的影响。实际业务程序中,收发包描述符大小配置一般参考 dpdk 内部示例程序配置进行,经验之谈是不同的网卡配置不同的描述符大小,如何确定不同网卡最优的值是一个实际的问题。

    dpdk 示例程序中的缺省配置

    dpdk-19.11 testpmd 示例程序源码中,使用如下变量配置收发包描述符:

    #define RTE_TEST_RX_DESC_DEFAULT 0
    #define RTE_TEST_TX_DESC_DEFAULT 0
    uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */
    uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */
    
    • 1
    • 2
    • 3
    • 4

    这里的 nb_rxd 与 nb_txd 分别表示收包描述符个数与发包描述符个数,可以看到这里缺省的配置都为 0。
    第一次读到这块代码感觉有些奇怪,在 testpmd 的所有源码中搜索了下,确认收发包描述符的缺省配置确实是这里实现的。
    0 显然是个非法的数据,但是这里的代码又是这样写的,不由让人猜测是不是哪里有针对性地处理,于是分析了下代码,在本文中记录一下。

    testpmd 中 nb_rxd 与 nb_txd 真正配置到 dpdk 中的代码

    rte_eth_rx_queue_setup
    rte_eth_tx_queue_setup
    
    • 1
    • 2

    如上两个函数分别配置收包队列与发包队列,这两个函数的第三个参数就是描述符数量的配置项目。

    nb_rxd 与 nb_txd 最终通过间接传入到这两个函数中实现描述符配置,说明业务层没有做额外的处理,于是进入到 ethdev 实现中寻找线索。

    rte_eth_rx_queue_setup 中相关代码

    	        /* Use default specified by driver, if nb_rx_desc is zero */
            if (nb_rx_desc == 0) {
                    nb_rx_desc = dev_info.default_rxportconf.ring_size;
                    /* If driver default is also zero, fall back on EAL default */
                    if (nb_rx_desc == 0)
                            nb_rx_desc = RTE_ETH_DEV_FALLBACK_RX_RINGSIZE;
            }
    	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    可以看到当描述符配置为 0 时,使用 rte_eth_dev_info_get 获取到的驱动提供的 dev_info.default_rxportconf.ring_size配置的值,如果此配置为 0 则使用宏RTE_ETH_DEV_FALLBACK_RX_RINGSIZE定义的值,其值为 512。

    rte_eth_tx_queue_setup 处理逻辑类似,不再赘述。

    驱动中设置 default_rxportconf.ring_size 的代码

    dpdk pmd 驱动种类繁多,这里以 i40e 驱动为例,分析这部分配置的逻辑。
    搜索到 i40e_dev_info_get 函数中有如下代码:

            if (I40E_PHY_TYPE_SUPPORT_40G(hw->phy.phy_types)) {
                    /* For XL710 */
                    dev_info->speed_capa = ETH_LINK_SPEED_40G;
                    dev_info->default_rxportconf.nb_queues = 2;
                    dev_info->default_txportconf.nb_queues = 2;
                    if (dev->data->nb_rx_queues == 1)
                            dev_info->default_rxportconf.ring_size = 2048;
                    else
                            dev_info->default_rxportconf.ring_size = 1024;
                    if (dev->data->nb_tx_queues == 1)
                            dev_info->default_txportconf.ring_size = 1024;
                    else
                            dev_info->default_txportconf.ring_size = 512;
    
            } else if (I40E_PHY_TYPE_SUPPORT_25G(hw->phy.phy_types)) {
                    /* For XXV710 */
                    dev_info->speed_capa = ETH_LINK_SPEED_25G;
                    dev_info->default_rxportconf.nb_queues = 1;
                    dev_info->default_txportconf.nb_queues = 1;
                    dev_info->default_rxportconf.ring_size = 256;
                    dev_info->default_txportconf.ring_size = 256;
            } else {
                    /* For X710 */
                    dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G;
                    dev_info->default_rxportconf.nb_queues = 1;
                    dev_info->default_txportconf.nb_queues = 1;
                    if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_10G) {
                            dev_info->default_rxportconf.ring_size = 512;
                            dev_info->default_txportconf.ring_size = 256;
                    } else {
                            dev_info->default_rxportconf.ring_size = 256;
                            dev_info->default_txportconf.ring_size = 256;
                    }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    将上述逻辑进行整理,得到如下表格:

    ⽹卡类型收发包队列数⽬收包描述符个数发包描述符个数
    40G XL710120481024
    40G XL710大于 11024512
    25G XXV710*256256
    X710 10G*512256
    X710 1G*256256

    观察到上面的表格有如下特征:

    1. 收包描述符一般为发包描述符数量的 2 倍
    2. 带宽更高的网卡一般需要配置更大数量的收发包描述符数目

    dpdk 网卡收发包队列缺省描述符配置如何确定?

    使用驱动内部默认值,默认值不符合要求则单独调优

    代码配置方式如下:

    1. 应用程序调用 rte_eth_rx_queue_setup 时设置 nb_rx_desc 参数为 0
    2. 应用程序调用 rte_eth_tx_queue_setup 时设置 nb_tx_desc 参数为 0
    3. 重新编译应用部署运行,测试性能是否达标

    此时 dpdk 内部会根据不同网卡类型获取驱动缺省配置进行设置,如果驱动未提供缺省值,则使用全局默认值,这些配置值都是最优配置。

    收发包描述符影响什么?

    发包流程

    网卡手册阅读:ixgbe 发包流程研究 这篇文章中我描述过 intel 82599 网卡的发包流程,其中一个关键的结构是环形描述符队列。

    dpdk 驱动发包时,首先会申请【空闲】的发包描述符,然后使用 mbuf 中的字段填充描述符,填充完成后再更新 TDT 寄存器(设置了一个门限降低频繁访问寄存器 I/O 的性能影响)。

    网卡硬件读取 TDH 与 TDT之间的发包描述符发起 PCIE 传输 copy 报文到内部的 fifo 中然后更新 TDH 并回写描述符(也存在一个门限)。

    上图实际运作过程中,TDH 在不断的追 TDT,到达环的底部后再回到起始位置。

    cpu 填充发包描述符的速度很快,这个环形队列的长度在某种程度上代表了cpu 缓冲给 PCIE 传输与网卡更新描述符的时间,理想的情况是 cpu 一直能够获取到空闲的描述符,这样 cpu 等待的时间就非常少了,cpu 与 PCIE、网卡的并行性更好,性能表现也就更好了。

    如果将描述符的数量设置为 1,在这种极端的情况下,cpu 就要不断地等待,接近于上文描述的在 rte_eth_tx_burst 中等待发包完成的情况。

    dpdk 问题分析:dpdk-19.11 性能优于 dpdk-16.04 问题分析 这篇文章中,我就曾经描述过通过调大 dpdk-16.04 的默认描述符个数来达到性能优化的目标,背后的原理就是增加留给 PCIE 传输报文与网卡处理的缓冲时间。

    收包流程

    收包流程也存在一个环形描述符队列,其中的并行性问题与发包大致相同,不过发包描述符的数量配置在一定情况下对收包也有影响,增加发包描述符为网卡硬件传输缓冲了更多时间,但是也意味着对报文 buf 占用了更多的时间,当收包已经接近负载的时候,可能会因为发包描述符的调整导致 buf 不足,出现 imissed,一般需要对收发包描述符整体调优,单点调优的意义不大。

    总结

    网卡收发包队列描述符配置看似是一个小的配置,其背后也有诸多细节。如何确定一个最优的配置常常不是一个容易的问题,需要对现有的实现跟底层原理有相对清晰的了解,既知道哪种配置是最优的,也知道为啥它是最优的,这点就相对有些难度了。

  • 相关阅读:
    C/C++班主任管家系统
    2、使用阿里云镜像加速器提升Docker的资源下载速度
    配置.ssh功能
    Mybatis的mapper使用springbootTest报错Find why ‘xxxMapper‘ could be null
    关于CSS 优先级布局应用的教程
    如何写代码实现VRP问题中车辆容量限制及时间窗要求(python)
    Web前端:跨浏览器测试和响应式测试之间的主要区别
    RK3399 Android7.1修改adb shell下$前的提示名称
    数商云:日化用品行业采购智能管理平台整合供应闭环,实现企业端到端寻源采购
    路由套接字
  • 原文地址:https://blog.csdn.net/Longyu_wlz/article/details/134232714