DPDK-22.11.2 [六] RSS receive side scaling 网卡分流机制
这个的作用就是为了提高性能。
当分析网络数据时,可以为网口提供多个接收队列,每个cpu处理一个队列。
如果每条队列是独立的,那么就可以很好的并发。
这里有两个问题,一个是数据需要平均的分配到每个队列;二是同一组数据需要分配到同一个队列。
rss就是这个作用,可以设定以ip进行区分,或者以端口进行区分。
比如以ip进行区分,那么dpdk会根据网络包的ip创建一个哈希值,相同ip的网络包,哈希值一致,也会进入同一个接收队列。
可以从获取到的dpdk的rte_mbuf结构体的hash.rss
查看生成的哈希值。如果哈希值都是0,则表示配置失败。
如何开启rss,需要通过api rte_eth_dev_configure
设置,其配置如下
static const struct rte_eth_conf port_conf = {
.rxmode = {
.mq_mode = RTE_ETH_MQ_RX_RSS,//表示打开rss
},
.rx_adv_conf = {
.rss_conf = {
.rss_key = NULL,//自定义rsskey,如果不设置,则使用默认的
.rss_key_len = 0,//如果设定了自定义key,需要指定自定义rsskey的大小
.rss_hf = RTE_ETH_RSS_IPV4,//rss类型,这里就是根据ipv4区分
},
},
};
上面有几点需要注意:
- 之所以需要自定义rsskey,是因为默认rsskey会把ip往返的数据所做两种哈希值,也就是a->b的网络包与b->a的网络包认为是不同的。实际上确实是不同的,但是往往我们开发是需要放到一个队列计算,所以有专门的rsskey,可以屏蔽方向,把a->b和b->a的包都算作相同的。
- rss_hf指定的rss类型并不是所有网卡都通用的,这个需要根据对应的设备来确定,如果设置错误,会导致dpdk无法运行,并且报错
Ethdev port_id=0 invalid rss_hf: 0xa38c, valid value: 0x38d34
我们可以通过dpdk的rte_eth_dev_info_get
获取网卡的设备信息,在其获得的rte_eth_dev_info
结构体中,有一个字段flow_type_rss_offloads
给定了网卡支持的rss类型,可以通过位预算与上进行判断是否支持。这是一个bit mask
dpdk设定的常见的几种rss规则如下
#define RTE_ETH_RSS_IP ( \
RTE_ETH_RSS_IPV4 | \
RTE_ETH_RSS_FRAG_IPV4 | \
RTE_ETH_RSS_NONFRAG_IPV4_OTHER | \
RTE_ETH_RSS_IPV6 | \
RTE_ETH_RSS_FRAG_IPV6 | \
RTE_ETH_RSS_NONFRAG_IPV6_OTHER | \
RTE_ETH_RSS_IPV6_EX)
#define RTE_ETH_RSS_UDP ( \
RTE_ETH_RSS_NONFRAG_IPV4_UDP | \
RTE_ETH_RSS_NONFRAG_IPV6_UDP | \
RTE_ETH_RSS_IPV6_UDP_EX)
#define RTE_ETH_RSS_TCP ( \
RTE_ETH_RSS_NONFRAG_IPV4_TCP | \
RTE_ETH_RSS_NONFRAG_IPV6_TCP | \
RTE_ETH_RSS_IPV6_TCP_EX)
实际上我们可以设定多重rss规则,当其中一种不符合条件时,会用另一种进行匹配。
上面的意思都比较明确,FRAG表示分片包如何处理