DPDK

背景

最近在做将基于dpdk-16.11.1开发的程序,转移到基于dpdk-18.11版本下开发。遇到了网卡RSS配置的问题,在这里纪录一下。

问题

dpdk-16.11.1

在dpdk-16.11.1上的程序如下:

1static uint8_t rss_intel_key[40] = { 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 2 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 3 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 4 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 5 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A 6 }; 7 8 9static const struct rte_eth_conf port_conf = { 10 .rxmode = { 11 .mq_mode = ETH_MQ_RX_RSS, 12 .split_hdr_size = 0, 13 .header_split = 0, /**< Header Split disabled */ 14 .hw_ip_checksum = 0, /**< IP checksum offload disabled */ 15 .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 16 .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ 17 .hw_strip_crc = 0, /**< CRC stripped by hardware */ 18 }, 19 .rx_adv_conf = { 20 .rss_conf = { 21 .rss_key = rss_intel_key, 22 .rss_hf = ETH_RSS_PROTO_MASK, 23 }, 24 }, 25 .txmode = { 26 .mq_mode = ETH_MQ_TX_NONE, 27 }, 28};

rte_eth_dev_configure函数声明

1int rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_queue, 2 uint16_t nb_tx_queue, const struct rte_eth_conf *eth_conf);

无论是千兆网卡还是万兆网卡,在调用  rte_eth_dev_configure(port_id, nb_rx_queue, nb_tx_queue, &port_conf)  函数时都可以正常启动。

dpdk-18.11

dpdk-18.11中对 struct rte_eth_conf 结构体进行了修改,使用offloads代替了之前的几个变量标志位,不过这都影响不大。

1static uint8_t rss_intel_key[40] = { 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 2 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 3 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 4 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 5 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A 6 }; 7 8 9static const struct rte_eth_conf port_conf = { 10 .rxmode = { 11 .mq_mode = ETH_MQ_RX_RSS, 12 .max_rx_pkt_len = 0, 13 .split_hdr_size = 0, 14 .offloads = 0, 15 }, 16 .rx_adv_conf = { 17 .rss_conf = { 18 .rss_key = rss_intel_key, 19 .rss_key_len = 40, 20 .rss_hf = ETH_RSS_PROTO_MASK, 21 }, 22 }, 23 .txmode = { 24 .mq_mode = ETH_MQ_TX_NONE, 25 }, 26};

在调用  rte_eth_dev_configure(port_id, nb_rx_queue, nb_tx_queue, &port_conf)  函数是和16.11.1上是一致的。

在编译完成后,进行运行时发现,报错无法运行。报错如下:

Ethdev port_id=0 invalid rss_hf: 0x3ffffc, valid value: 0x38d34

port_id 0是一个igb驱动的网卡,型号为I350。

报错的意思是在调用 rte_eth_dev_configure 函数时,传入的最后一个函数参数(也就是网卡配置)中的 rx_adv_conf.rss_conf.rss_hf 参数值有问题,这个值是无效的。有效值是 0x38d34。

找到dpdk源码中打印错误信息的位置,前后代码如下:

1int 2rte_eth_dev_rss_hash_update(uint16_t port_id, 3 struct rte_eth_rss_conf *rss_conf) 4{ 5 struct rte_eth_dev *dev; 6 struct rte_eth_dev_info dev_info = { .flow_type_rss_offloads = 0, }; 7 8 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); 9 dev = &rte_eth_devices[port_id]; 10 rte_eth_dev_info_get(port_id, &dev_info); 11 if ((dev_info.flow_type_rss_offloads | rss_conf->rss_hf) != 12 dev_info.flow_type_rss_offloads) { 13 RTE_ETHDEV_LOG(ERR, 14 "Ethdev port_id=%u invalid rss_hf: 0x%"PRIx64", valid value: 0x%"PRIx64"\n", 15 port_id, rss_conf->rss_hf, 16 dev_info.flow_type_rss_offloads); 17 return -EINVAL; 18 } 19 RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_update, -ENOTSUP); 20 return eth_err(port_id, (*dev->dev_ops->rss_hash_update)(dev, 21 rss_conf)); 22}

 dev_info.flow_type_rss_offloads 就是网卡支持的flow类型, rss_conf->rss_hf 就是我们调用 rte_eth_dev_configure 函数的最后一个参考中的  rx_adv_conf.rss_conf.rss_hf 的值,

这里的if判断意思是配置的flow类型必须是网卡支持的flow类型,如果配置了网卡不支持的类型,就会报错。

经过计算器算出 0x38d34的二进制是111000110100110100,再配合在 rte_ethdev.h 中 ETH_RSS_开头的宏定义,得出111000110100110100就是下面所有宏定义的 或 值:

1ETH_RSS_IPV4 | \ 2ETH_RSS_NONFRAG_IPV4_TCP| \ 3ETH_RSS_NONFRAG_IPV4_UDP| \ 4ETH_RSS_IPV6 | \ 5ETH_RSS_NONFRAG_IPV6_TCP | \ 6ETH_RSS_NONFRAG_IPV6_UDP | \ 7ETH_RSS_IPV6_EX | \ 8ETH_RSS_IPV6_TCP_EX | \ 9ETH_RSS_IPV6_UDP_EX

而我们配置中的参数  ETH_RSS_PROTO_MASK 显然比上面的类型要多,也就是 ETH_RSS_PROTO_MASK 定义的一些类型,网卡不支持,故而报错。

我们再看16.11.1中的源码

1int 2rte_eth_dev_rss_hash_update(uint8_t port_id, struct rte_eth_rss_conf *rss_conf) 3{ 4 struct rte_eth_dev *dev; 5 uint16_t rss_hash_protos; 6 7 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); 8 rss_hash_protos = rss_conf->rss_hf; 9 if ((rss_hash_protos != 0) && 10 ((rss_hash_protos & ETH_RSS_PROTO_MASK) == 0)) { 11 RTE_PMD_DEBUG_TRACE("Invalid rss_hash_protos=0x%x\n", 12 rss_hash_protos); 13 return -EINVAL; 14 } 15 dev = &rte_eth_devices[port_id]; 16 RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_update, -ENOTSUP); 17 return (*dev->dev_ops->rss_hash_update)(dev, rss_conf); 18}

显然判断逻辑不同的。这里的判断意思是,只要有配置,并且配置中的flow类型至少有1项是在  ETH_RSS_PROTO_MASK  中的就可以,除非你配置的类型都不在  ETH_RSS_PROTO_MASK 中才会报错,这里就可以看出,即使你配置了网卡不支持的特性,也不会报错。

至此问题已解决。

总结

在dpdk-18.11中,配置网卡rss,必须网卡支持这种特性才行,否则会报错。

下面是整理的 igb , ixgbe ,  i40e 驱动网卡所支持的flow类型。

igb支持的特性

测试使用I350及I211网卡,有效值为0x38d34,二进制为111000110100110100,对应宏定义为

1#define ETH_RSS_E1000_IGB (\ 2 ETH_RSS_IPV4 | \ 3 ETH_RSS_NONFRAG_IPV4_TCP| \ 4 ETH_RSS_NONFRAG_IPV4_UDP| \ 5 ETH_RSS_IPV6 | \ 6 ETH_RSS_NONFRAG_IPV6_TCP | \ 7 ETH_RSS_NONFRAG_IPV6_UDP | \ 8 ETH_RSS_IPV6_EX | \ 9 ETH_RSS_IPV6_TCP_EX | \ 10 ETH_RSS_IPV6_UDP_EX)

ixgbe支持的特性

测试使用82599ES网卡,有效值和igb相同

#define ETH_RSS_IXGBE ETH_RSS_E1000_IGB

i40e支持的特性

测试使用X710网卡,有效值为0x7ef8,二进制为111111011111000,对应宏定义为

1#define ETH_RSS_I40E (\ 2 ETH_RSS_FRAG_IPV4 | \ 3 ETH_RSS_NONFRAG_IPV4_TCP | \ 4 ETH_RSS_NONFRAG_IPV4_UDP | \ 5 ETH_RSS_NONFRAG_IPV4_SCTP | \ 6 ETH_RSS_NONFRAG_IPV4_OTHER | \ 7 ETH_RSS_FRAG_IPV6 | \ 8 ETH_RSS_NONFRAG_IPV6_TCP | \ 9 ETH_RSS_NONFRAG_IPV6_UDP | \ 10 ETH_RSS_NONFRAG_IPV6_SCTP | \ 11 ETH_RSS_NONFRAG_IPV6_OTHER | \ 12 ETH_RSS_L2_PAYLOAD)
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

swap空间的增减方法

(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap