网卡RSS功能

功能概述

        该功能主要是让网络报文,散列的交给多个CPU处理,从而避免单个CPU的负载过大,造成性能瓶颈。其主要流程如下:

  • 网卡收到一个网络报文后,根据不同的报文类型,选择不同的报文字段,进行hash计算,算出一个hash值。

    • 哪些报文类型要做RSS是可以配置的。(例如只指定ipv4 tcp报文做RSS,其他类型的报文都不做RSS)

    • 每一种配置的报文类型,可以指定选择哪些字段做hash计算。(例如,可以指定对于ipv4 tcp报文,只使用tcp的目的端口号做hash)

    • 对于没有配置的报文类型,可以不做hash计算,直接按照hash值为0来处理,然后固定选择一个队列上送。

    • hash计算函数是可以配置的。(linux内核可以配置,目前有3种:toeplitz、xor和crc32。DPDK驱动目前没看到配置hash函数的接口)

  • 计算出来一个hash值后,使用hash值的最低N个bit,作为index,在RSS indirection table中选取一个条目。使用该条目中存储的值,作为上送队列的ID,并选择该队列上送报文给CPU。

    • RSS indirection table是可以配置的,每一个条目存储的是一个上送队列的ID。通常情况下,不管是linux内核,还是DPDK应用,会让不同接收队列的报文,分布在不同的CPU core来处理。

    • RSS indirection table的大小,要跟选取的hash值的最低N个bit相匹配。通常情况下,这个表的大小,要比上送队列的个数要多。

    • 如果用户期望增加或者减小某个CPU的负载,可以修改RSS indirection table配置表,让该CPU对应的队列的ID,在RSS indirection table中的排布增加或者减小。

        网卡通常有一套默认的RSS配置,包括默认哪些报文类型做RSS,以及该报文类型选取哪些字段做RSS,以及使用哪个hash函数,以及哪个indirection table。

indirection table表的大小和hash key的大小。hash函数的支持情况。

  • indirection table表的大小要跟rx队列个数匹配

  • cx6 PF的indirection table表大小为256。hash key大小为40字节。hash函数只支持toeplitz和xor。

  • 82599 PF的indirection table表大小为128,如果PF使能了SRIOV,则为64。hash key大小为40字节。hash函数只支持toeplitz

  • 华为hinic的indirection table表大小为256。hash key大小为40字节。PF和VF参数一样。hash函数只支持toeplitz和xor。

内核rss功能

配置报文类型
ethtool -N|-U|--config-nfc|--config-ntuple DEVNAME 
    rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6 
            m|v|t|s|d|f|n|r... [context %d]

命令说明:     
rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r...
                  Configures the hash options for the specified flow type.

                  m   Hash on the Layer 2 destination address of the rx packet.
                  v   Hash on the VLAN tag of the rx packet.
                  t   Hash on the Layer 3 protocol field of the rx packet.
                  s   Hash on the IP source address of the rx packet.
                  d   Hash on the IP destination address of the rx packet.
                  f   Hash on bytes 0 and 1 of the Layer 4 header of the rx packet.
                  n   Hash on bytes 2 and 3 of the Layer 4 header of the rx packet.
                  r   Discard  all  packets  of this flow type. When this option is
                      set, all other options are ignored.
                      
配置RSS hash函数和队列在indirection table中的分布
ethtool [ FLAGS ] -X|--set-rxfh-indir|--rxfh DEVNAME    Set Rx flow hash indirection table and/or RSS hash key
                [ context %d|new ]
                [start N]
                [ equal N | weight W0 W1 ... | default ]
                [ hkey %x:%x:%x:%x:%x:.... ]
                [ hfunc FUNC ]
                [ delete ]


       -X --set-rxfh-indir --rxfh
              Configures the receive flow hash indirection table and/or RSS hash key.

           hkey   Sets  RSS hash key of the specified network device. RSS hash key should be of device supported length.
                  Hash key format must be in xx:yy:zz:aa:bb:cc format meaning both the nibbles of a byte should be  men‐
                  tioned even if a nibble is zero.

           hfunc  Sets  RSS hash function of the specified network device.  List of RSS hash functions which kernel sup‐
                  ports is shown as a part of the --show-rxfh command output.

           start N
                  For the equal and weight options, sets the starting receive queue for spreading flows to N.

           equal N
                  Sets the receive flow hash indirection table to spread  flows  evenly  between  the  first  N  receive
                  queues.

           weight W0 W1 ...
                  Sets  the  receive flow hash indirection table to spread flows between receive queues according to the
                  given weights.  The sum of the weights must be non-zero and must not exceed the size of  the  indirec‐
                  tion table.

           default
                  Sets the receive flow hash indirection table to its default value.

           context CTX | new
                  Specifies an RSS context to act on; either new to allocate a new RSS context, or CTX, a value returned
                  by a previous ... context new.

           delete Delete the specified RSS context.  May only be used in conjunction with context  and  a  non-zero  CTX
                  value.

        内核rss功能的配置,分两步:

1、配置hash函数、hash key、indirect table。

  • 具体命令为:ethtool -X|--set-rxfh-indir|--rxfh
  • 一个网口支持多个配置。以支持不同的报文类型,使用不同的hash算法和indirect table。

        例如可以设置tcp4报文使用toeplitz算法,设置udp4报文,使用xor算法。

        如果要配置多个,则需要使用context new来创建一个新的。此时会返回一个context index。后续可以使用该context index来个更改当前的条目。context 0是默认存在的配置,用context new创建出来条目的context是大于0的。

    root@local-host:~# ethtool -X enp1s0f1np1 context new start 1 weight 1 2 3 hfunc xor
    New RSS context is 1
  • indirect table的配置,是按照权重和排布来配置的。实际给到驱动是一个代表indirect table的数组,ethtool已经将indirect table中队列的排布计算好了。
    • start N equal N,这个组合是配置哪些队列在indirect table表中平均分布。例如,假设有10个队列,但是,我只是从第5个队列开始,选择3个队列,平均分布,则配置命令为start 5 equal 3,最终的indirect table表的分布为:5、6、7、5、6、7、5、6、7...(队列编号从0开始)
    • start N weight W0 W1,配置从编号N开始,选取w个队列,并按照权重在indirect table中分布。weight后面W0、W1...的个数,表示选取的队列,W0、W1...的取值,代表各个队列的分布权重。
    • 例如:假设indirect table的大小为24,配置第3个队列开始的3个队列,按照2:1:3分布,则配置命令为start 3 weight 2 1 3或者为start 3 weight 20 10 30(weight的具体值没有限制,实际计算队列权重的时,是按照Wn/(W0+W1+W2)计算的)。最终的indirect table表的分布为:3、3、3、3、3、3、3、3、4、4、4、4、5、5、5、5、5、5、5、5、5、5、5、5(连续8个3+连续4个4+连续12个5)
    • hfunc只能设置为toeplitz、xor或crc32。

2、配置接收侧flow classify的hash options。即配置指定flow类型,选择用哪些字段计算RSS hash。

  • 目前只支持设置以下报文类型:tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6

    • 只支持ipv4和ipv6报文,其他非ip报文不支持做rss

    • icmp不支持做rss。从支持的报文类型来看,目前只对大流量的报文类型做rss,icmp通常不会有大流量。

  • 对于每种报文类型可以选择不同的字段来计算hash。

    • 具体可以设置的字段有:dmac、vlan tag、ip protocol、sip、dip、L4的第0和第1字节、L4的第2和第3字节

    • 对于tcp/udp/sctp,L4的第0和第1字节、L4的第2和第3字节,分别为sport和dport。

    • 对于ESP报文,L4的第0和第1字节、L4的第2和第3字节,组合起来是一个SPI,可以基于SPI做RSS

    • 对于AH报文,L4的第0和第1字节,分别为next header和payload len。L4的第2和第3字节,为保留字段。不适合用来做RSS。

  • 可以配置丢弃某种类型的报文。例如配置ethtool -N eth0 rx-flow-hash sctp6 r,即丢弃所有的ipv6 sctp报文。 (大部分网卡不支持该功能)

各个网卡支持的报文类型和hash字段:

  • 华为hinic。报文类型只支持tcp4|udp4|tcp6|udp6。hash字段只支持sip、dip、L4的第0和第1字节、L4的第2和第3字节,且必须要指定sip和dip。

  • cx6。报文类型只支持tcp4|udp4|tcp6|udp6。hash字段只支持sip、dip、L4的第0和第1字节、L4的第2和第3字节。

  • 82599。配置的报文协议类型都支持。hash字段只支持sip、dip、L4的第0和第1字节、L4的第2和第3字节。对于非tcp/udp报文,必须指定sip+dip为hash字段,不能再有额外指定其他字段。tcp报文,必须指定sip、dip、L4的第0和第1字节、L4的第2和第3字节。udp报文,只能指定sip+dip,或者支持的4个字段都指定。

        如果网卡在解析报文的时候,如果不能跳过ipv6的扩展头,那么在存在某些扩展头的情况下,可能无法识别udp6/tcp6/sctp6等报文,对于这些报文,网卡无法做RSS功能,可能从默认队列上送。

        内核ethtool_ops相关接口如下:

/ethtool -N|-U|--config-nfc|--config-ntuple DEVNAME rx-flow-hash|flow-type命令
int (*get_rxnfc)(struct net_device *,
                 struct ethtool_rxnfc *, u32 *rule_locs);
int    (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
struct ethtool_rxnfc {
    __u32               cmd; //命令类型,是flow-type还是rx-flow-hash
    __u32               flow_type; //报文类型,tcp4/esp6等
    __u64               data; //hash字段bit位,l2|vlan|l3pro|sip|dip|l4-B-01|l4-B-23
    struct ethtool_rx_flow_spec fs;
    union {
        __u32           rule_cnt;
        __u32           rss_context; //命令没指定,默认为0
    };
    __u32               rule_locs[0];
};


//ethtool [ FLAGS ] -X|--set-rxfh-indir|--rxfh DEVNAME命令回调
u32 (*get_rxfh_key_size)(struct net_device *);
u32 (*get_rxfh_indir_size)(struct net_device *);
int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key,
            u8 *hfunc);
int (*set_rxfh)(struct net_device *, const u32 *indir,
            const u8 *key, const u8 hfunc);
int (*get_rxfh_context)(struct net_device *, u32 *indir, u8 *key,
                u8 *hfunc, u32 rss_context);
int (*set_rxfh_context)(struct net_device *, const u32 *indir,
                const u8 *key, const u8 hfunc,
                u32 *rss_context, bool delete);

内核flow directory功能和RSS的组合

        每一个context,是一组RSS配置,具体信息包括:

  • 支持哪些报文类型,以及该报文类型选择哪些字段做hash;

  • hash函数,hash key值

  • Redirect table配置

        默认的context为0,这一组的RSS配置是RX默认的RSS行为。即rx报文,没有命中flow directory后,其默认的RSS行为。

        其他的context需要先创建,目前是给flow directory使用,即flow directory匹配某种报文后,可以进行指定的RSS行为,该行为通常是跟默认的RSS算法不一样,以满足用户在特定场景下,某类特殊报文的RSS需求。

配置示例:

//创建一个新的context,指定redirect table,hash函数和key使用默认值
root@localhost:~# ethtool -X enp1s0f0np0 context new start 2 equal 5
New RSS context is 1

//查看配置
root@localhost:~# ethtool -x enp1s0f0np0 context 1
RX flow hash indirection table for enp1s0f0np0 with 24 RX ring(s):
    0:      2     3     4     5     6     2     3     4
    8:      5     6     2     3     4     5     6     2
   16:      3     4     5     6     2     3     4     5
   24:      6     2     3     4     5     6     2     3
   32:      4     5     6     2     3     4     5     6
RSS hash key:
c9:1e:88:3f:79:16:50:40:24:13:bc:c6:5c:1d:39:a0:49:fb:21:76:ce:19:9c:43:50:ab:0e:f7:fa:25:3b:29:a4:83:d3:13:bf:72:ca:b2
RSS hash function:
    toeplitz: on
    xor: off
    crc32: off

//对于该context,会有默认的报文类型的hash字段选择的配置
root@localhost:~# ethtool -n enp1s0f0np0 rx-flow-hash tcp6 context 1
For RSS context 1:
TCP over IPV6 flows use these fields for computing Hash flow key:
IP SA
IP DA
L4 bytes 0 & 1 [TCP/UDP src port]
L4 bytes 2 & 3 [TCP/UDP dst port]

//也可以修改配置,但是目前不生效,不知道这一块的功能是否不完善
root@localhost:~# ethtool -N enp1s0f0np0 rx-flow-hash tcp6 ds context 1
root@localhost:~# ethtool -n enp1s0f0np0 rx-flow-hash tcp6 context 1  //修改后不生效
For RSS context 1:
TCP over IPV6 flows use these fields for computing Hash flow key:
IP SA
IP DA
L4 bytes 0 & 1 [TCP/UDP src port]
L4 bytes 2 & 3 [TCP/UDP dst port]

//配置flow directory指定特定的报文做RSS
root@localhost:~# ethtool -N enp1s0f0np0 flow-type udp4 dst-ip 192.168.100.0 m 0.0.0.255 context 1 loc 0
root@localhost:~# ethtool -n enp1s0f0np0
24 RX rings available
Total 1 rules

Filter: 0
        Rule Type: UDP over IPv4
        Src IP addr: 0.0.0.0 mask: 255.255.255.255
        Dest IP addr: 192.168.100.0 mask: 0.0.0.255
        TOS: 0x0 mask: 0xff
        Src port: 0 mask: 0xffff
        Dest port: 0 mask: 0xffff
        RSS Context ID: 1
        Action: Direct to queue 0

        目前cx6、Marvell的Octeon TX2、Solarflare Communications等网卡,实现了这个功能。cx6支持16组,Marvell支持8组、Solarflare Communications支持64组,包括默认的context 0。

        flow directory + rss,不支持设置rss的报文类型和报文hash字段选择(ethtool -N enp1s0f0np0 rx-flow-hash tcp6 ds context 1配置不生效,可能是ethtool工具本身的问题)。目前该RSS只会有默认的报文类型和报文hash字段选择的配置。

Dpdk rss功能

        dpdk struct eth_dev_ops相关的接口如下:

/** @internal Update RSS redirection table on an Ethernet device. */
typedef int (*reta_update_t)(struct rte_eth_dev *dev,
                 struct rte_eth_rss_reta_entry64 *reta_conf,
                 uint16_t reta_size);

/** @internal Query RSS redirection table on an Ethernet device. */
typedef int (*reta_query_t)(struct rte_eth_dev *dev,
                struct rte_eth_rss_reta_entry64 *reta_conf,
                uint16_t reta_size);

/**
 * A structure used to configure 64 entries of Redirection Table of the
 * Receive Side Scaling (RSS) feature of an Ethernet port. To configure
 * more than 64 entries supported by hardware, an array of this structure
 * is needed.
 */
struct rte_eth_rss_reta_entry64 {
    /** Mask bits indicate which entries need to be updated/queried. */
    uint64_t mask;
    /** Group of 64 redirection table entries. */
    uint16_t reta[RTE_ETH_RETA_GROUP_SIZE];
};


/** @internal Update RSS hash configuration of an Ethernet device. */
typedef int (*rss_hash_update_t)(struct rte_eth_dev *dev,
                 struct rte_eth_rss_conf *rss_conf);

/** @internal Get current RSS hash configuration of an Ethernet device. */
typedef int (*rss_hash_conf_get_t)(struct rte_eth_dev *dev,
                   struct rte_eth_rss_conf *rss_conf);
                   
struct rte_eth_rss_conf {
    /**
     * In rte_eth_dev_rss_hash_conf_get(), the *rss_key_len* should be
     * greater than or equal to the *hash_key_size* which get from
     * rte_eth_dev_info_get() API. And the *rss_key* should contain at least
     * *hash_key_size* bytes. If not meet these requirements, the query
     * result is unreliable even if the operation returns success.
     *
     * In rte_eth_dev_rss_hash_update() or rte_eth_dev_configure(), if
     * *rss_key* is not NULL, the *rss_key_len* indicates the length of the
     * *rss_key* in bytes and it should be equal to *hash_key_size*.
     * If *rss_key* is NULL, drivers are free to use a random or a default key.
     */
    uint8_t *rss_key;
    uint8_t rss_key_len; /**< hash key length in bytes. */
    /**
     * Indicates the type of packets or the specific part of packets to
     * which RSS hashing is to be applied.
     */
    uint64_t rss_hf; //指明hash报文类型,即哪些报文做RSS,具体RTE_ETH_RSS_IPV4,
                      对于每种报文类型,用于hash计算的报文字段是固定的,但是可以微调。
    enum rte_eth_hash_function algorithm;   /**< Hash algorithm. */
};

enum rte_eth_hash_function {
    /** DEFAULT means driver decides which hash algorithm to pick. */
    RTE_ETH_HASH_FUNCTION_DEFAULT = 0,
    RTE_ETH_HASH_FUNCTION_TOEPLITZ, /**< Toeplitz */
    RTE_ETH_HASH_FUNCTION_SIMPLE_XOR, /**< Simple XOR */
    /**
     * Symmetric Toeplitz: src, dst will be replaced by
     * xor(src, dst). For the case with src/dst only,
     * src or dst address will xor with zero pair.
     */
    RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ,
    /**
     * Symmetric Toeplitz: L3 and L4 fields are sorted prior to
     * the hash function.
     *  If src_ip > dst_ip, swap src_ip and dst_ip.
     *  If src_port > dst_port, swap src_port and dst_port.
     */
    RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ_SORT,
    RTE_ETH_HASH_FUNCTION_MAX,

        dpdk目前支持的具体报文类型有:

#define RTE_ETH_RSS_IPV4               RTE_BIT64(2)
#define RTE_ETH_RSS_FRAG_IPV4          RTE_BIT64(3)  //ipv4分片报文做rss。默认不做。
#define RTE_ETH_RSS_NONFRAG_IPV4_TCP   RTE_BIT64(4)
#define RTE_ETH_RSS_NONFRAG_IPV4_UDP   RTE_BIT64(5)
#define RTE_ETH_RSS_NONFRAG_IPV4_SCTP  RTE_BIT64(6)
#define RTE_ETH_RSS_NONFRAG_IPV4_OTHER RTE_BIT64(7)  //不知道要做什么?
#define RTE_ETH_RSS_IPV6               RTE_BIT64(8)
#define RTE_ETH_RSS_FRAG_IPV6          RTE_BIT64(9)
#define RTE_ETH_RSS_NONFRAG_IPV6_TCP   RTE_BIT64(10)
#define RTE_ETH_RSS_NONFRAG_IPV6_UDP   RTE_BIT64(11)
#define RTE_ETH_RSS_NONFRAG_IPV6_SCTP  RTE_BIT64(12)
#define RTE_ETH_RSS_NONFRAG_IPV6_OTHER RTE_BIT64(13)
#define RTE_ETH_RSS_L2_PAYLOAD         RTE_BIT64(14)
#define RTE_ETH_RSS_IPV6_EX            RTE_BIT64(15)
#define RTE_ETH_RSS_IPV6_TCP_EX        RTE_BIT64(16)
#define RTE_ETH_RSS_IPV6_UDP_EX        RTE_BIT64(17)
#define RTE_ETH_RSS_PORT               RTE_BIT64(18)
#define RTE_ETH_RSS_VXLAN              RTE_BIT64(19)
#define RTE_ETH_RSS_GENEVE             RTE_BIT64(20)
#define RTE_ETH_RSS_NVGRE              RTE_BIT64(21)
#define RTE_ETH_RSS_GTPU               RTE_BIT64(23)
#define RTE_ETH_RSS_ETH                RTE_BIT64(24)
#define RTE_ETH_RSS_S_VLAN             RTE_BIT64(25)
#define RTE_ETH_RSS_C_VLAN             RTE_BIT64(26)
#define RTE_ETH_RSS_ESP                RTE_BIT64(27)
#define RTE_ETH_RSS_AH                 RTE_BIT64(28)
#define RTE_ETH_RSS_L2TPV3             RTE_BIT64(29)
#define RTE_ETH_RSS_PFCP               RTE_BIT64(30)
#define RTE_ETH_RSS_PPPOE              RTE_BIT64(31)
#define RTE_ETH_RSS_ECPRI              RTE_BIT64(32)
#define RTE_ETH_RSS_MPLS               RTE_BIT64(33)
#define RTE_ETH_RSS_IPV4_CHKSUM        RTE_BIT64(34)

/**
 * The RTE_ETH_RSS_L4_CHKSUM works on checksum field of any L4 header.
 * It is similar to RTE_ETH_RSS_PORT that they don't specify the specific type of
 * L4 header. This macro is defined to replace some specific L4 (TCP/UDP/SCTP)
 * checksum type for constructing the use of RSS offload bits.
 *
 * Due to above reason, some old APIs (and configuration) don't support
 * RTE_ETH_RSS_L4_CHKSUM. The rte_flow RSS API supports it.
 *
 * For the case that checksum is not used in an UDP header,
 * it takes the reserved value 0 as input for the hash function.
 */
#define RTE_ETH_RSS_L4_CHKSUM          RTE_BIT64(35)

#define RTE_ETH_RSS_L2TPV2             RTE_BIT64(36)

//下面是微调的宏定义,可以和前面的宏定义组合使用
/*
 * We use the following macros to combine with above RTE_ETH_RSS_* for
 * more specific input set selection. These bits are defined starting
 * from the high end of the 64 bits.
 * Note: If we use above RTE_ETH_RSS_* without SRC/DST_ONLY, it represents
 * both SRC and DST are taken into account. If SRC_ONLY and DST_ONLY of
 * the same level are used simultaneously, it is the same case as none of
 * them are added.
 */
#define RTE_ETH_RSS_L3_SRC_ONLY        RTE_BIT64(63)
#define RTE_ETH_RSS_L3_DST_ONLY        RTE_BIT64(62)
#define RTE_ETH_RSS_L4_SRC_ONLY        RTE_BIT64(61)
#define RTE_ETH_RSS_L4_DST_ONLY        RTE_BIT64(60)
#define RTE_ETH_RSS_L2_SRC_ONLY        RTE_BIT64(59)
#define RTE_ETH_RSS_L2_DST_ONLY        RTE_BIT64(58)

/*
 * Only select IPV6 address prefix as RSS input set according to
 * https://tools.ietf.org/html/rfc6052
 * Must be combined with RTE_ETH_RSS_IPV6, RTE_ETH_RSS_NONFRAG_IPV6_UDP,
 * RTE_ETH_RSS_NONFRAG_IPV6_TCP, RTE_ETH_RSS_NONFRAG_IPV6_SCTP.
 */
#define RTE_ETH_RSS_L3_PRE32           RTE_BIT64(57)
#define RTE_ETH_RSS_L3_PRE40           RTE_BIT64(56)
#define RTE_ETH_RSS_L3_PRE48           RTE_BIT64(55)
#define RTE_ETH_RSS_L3_PRE56           RTE_BIT64(54)
#define RTE_ETH_RSS_L3_PRE64           RTE_BIT64(53)
#define RTE_ETH_RSS_L3_PRE96           RTE_BIT64(52)

/**
 * level 1, requests RSS to be performed on the outermost packet
 * encapsulation level.
 */
#define RTE_ETH_RSS_LEVEL_OUTERMOST    (UINT64_C(1) << 50)

/**
 * level 2, requests RSS to be performed on the specified inner packet
 * encapsulation level, from outermost to innermost (lower to higher values).
 */
#define RTE_ETH_RSS_LEVEL_INNERMOST    (UINT64_C(2) << 50)

        Rte flow支持action为rss,此时会指定完整的RSS信息:报文类型及hash字段选择、hash函数及hash key、redirect table。

struct rte_flow_action_rss {
    enum rte_eth_hash_function func; /**< RSS hash function to apply. */
    /**
     * Packet encapsulation level RSS hash @p types apply to.
     *
     * - @p 0 requests the default behavior. Depending on the packet
     *   type, it can mean outermost, innermost, anything in between or
     *   even no RSS.
     *
     *   It basically stands for the innermost encapsulation level RSS
     *   can be performed on according to PMD and device capabilities.
     *
     * - @p 1 requests RSS to be performed on the outermost packet
     *   encapsulation level.
     *
     * - @p 2 and subsequent values request RSS to be performed on the
     *   specified inner packet encapsulation level, from outermost to
     *   innermost (lower to higher values).
     *
     * Values other than @p 0 are not necessarily supported.
     *
     * Requesting a specific RSS level on unrecognized traffic results
     * in undefined behavior. For predictable results, it is recommended
     * to make the flow rule pattern match packet headers up to the
     * requested encapsulation level so that only matching traffic goes
     * through.
     */
    uint32_t level;
    uint64_t types; /**< Specific RSS hash types (see RTE_ETH_RSS_*). */
    uint32_t key_len; /**< Hash key length in bytes. */
    uint32_t queue_num; /**< Number of entries in @p queue. */
    const uint8_t *key; /**< Hash key. */
    const uint16_t *queue; /**< Queue indices to use. */
};

        从DPDK的配置接口来看,DPDK不支持针对不同的协议报文选择用不同的字段进行hash字段,只能指定一套统一的选择hash字段的规则。

        DPDK对RSS的支持,在hash函数,以及识别的报文类型上,相比linux内核的ethtool配置,要更丰富一些。其中dpdk支持的hash函数有:Toeplitz、Simple XOR、Symmetric Toeplitz、Symmetric Toeplitz SORT

        DPDK使用RTE_ETH_RSS_NONFRAG_IPV4_TCP等宏来定义报文类型,对于每一种报文类型,默认使用一些字段来计算hash,例如RTE_ETH_RSS_NONFRAG_IPV4_TCP默认使用sip + dip + sport + dport来计算hash。同时可以使用RTE_ETH_RSS_L3_SRC_ONLY等宏定义来去除一些字段。

        例如,如果使用RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L3_SRC_ONLY组合,那么对于ipv4 tcp报文使用sip + sport + dport来计算hash。

        另外dpdk支持选择根据报文的最外层head信息,还是某一层隧道的head信息进行hash计算。这个在默认的rss配置是不支持的,但是在rte_flow配置rss action的时候是支持的。默认的rss配置是使用外层还是隧道内存报文做RSS,取决于网卡的默认行为。

        DPDK驱动,各网卡支持的RSS配置:

  • cx6。

    • 支持报文类型为,不支持ipv6地址前缀长度选择:

          #define RTE_ETH_RSS_IPV4               RTE_BIT64(2)
          #define RTE_ETH_RSS_FRAG_IPV4          RTE_BIT64(3)
          #define RTE_ETH_RSS_NONFRAG_IPV4_TCP   RTE_BIT64(4)
          #define RTE_ETH_RSS_NONFRAG_IPV4_UDP   RTE_BIT64(5)
          #define RTE_ETH_RSS_NONFRAG_IPV4_SCTP  RTE_BIT64(6)
          #define RTE_ETH_RSS_NONFRAG_IPV4_OTHER RTE_BIT64(7)
          #define RTE_ETH_RSS_IPV6               RTE_BIT64(8)
          #define RTE_ETH_RSS_FRAG_IPV6          RTE_BIT64(9)
          #define RTE_ETH_RSS_NONFRAG_IPV6_TCP   RTE_BIT64(10)
          #define RTE_ETH_RSS_NONFRAG_IPV6_UDP   RTE_BIT64(11)
          #define RTE_ETH_RSS_NONFRAG_IPV6_SCTP  RTE_BIT64(12)
          #define RTE_ETH_RSS_NONFRAG_IPV6_OTHER RTE_BIT64(13)
          #define RTE_ETH_RSS_IPV6_EX            RTE_BIT64(15)
          #define RTE_ETH_RSS_IPV6_TCP_EX        RTE_BIT64(16)
          #define RTE_ETH_RSS_IPV6_UDP_EX        RTE_BIT64(17)
          #define RTE_ETH_RSS_ESP                RTE_BIT64(27)
    • RSS key的长度为40。不支持设置hash算法函数,应该使用的是硬件默认的hash算法,具体是什么不确定(可能是Toeplitz?)

    • Redirect table的大小,最大可能是512。(目前内核看到的大小为256)

    • Rte flow的rss action支持的配置更多,具体有:

      • 支持level。默认是用最外层做RSS,当level>=2时,使用内层做RSS。目前只支持一层隧道。

      • 普通RSS配置支持的报文类型,这里也都支持。

      • 支持ESP,且使用SPI做RSS。通常情况下,设置RTE_ETH_RSS_ESP时,也要设置RTE_ETH_RSS_IPV4等参数,否则,只会使用SPI做RSS。

  • Intel 82599

    • 支持报文类型为,不支持RTE_ETH_RSS_L3_SRC_ONLY等设置,不支持ipv6地址前缀长度选择:

          RTE_ETH_RSS_IPV4
          RTE_ETH_RSS_NONFRAG_IPV4_TCP
          RTE_ETH_RSS_NONFRAG_IPV4_UDP
          RTE_ETH_RSS_IPV6
          RTE_ETH_RSS_NONFRAG_IPV6_TCP
          RTE_ETH_RSS_NONFRAG_IPV6_UDP
          RTE_ETH_RSS_IPV6_EX
          RTE_ETH_RSS_IPV6_TCP_EX
          RTE_ETH_RSS_IPV6_UDP_EX
    • RSS key的长度为40。不支持设置hash算法函数,应该使用的是硬件默认的hash算法,具体是什么不确定(可能是Toeplitz?)

    • Redirect table的大小,128。

  • 华为hinic

    • 支持报文类型为,不支持RTE_ETH_RSS_L3_SRC_ONLY等设置,不支持ipv6地址前缀长度选择:

          #define RTE_ETH_RSS_IPV4               RTE_BIT64(2)
          #define RTE_ETH_RSS_FRAG_IPV4          RTE_BIT64(3)
          #define RTE_ETH_RSS_NONFRAG_IPV4_TCP   RTE_BIT64(4)
          #define RTE_ETH_RSS_NONFRAG_IPV4_UDP   RTE_BIT64(5)
          #define RTE_ETH_RSS_IPV6               RTE_BIT64(8)
          #define RTE_ETH_RSS_FRAG_IPV6          RTE_BIT64(9)
          #define RTE_ETH_RSS_NONFRAG_IPV6_TCP   RTE_BIT64(10)
          #define RTE_ETH_RSS_NONFRAG_IPV6_UDP   RTE_BIT64(11)
          #define RTE_ETH_RSS_IPV6_EX            RTE_BIT64(15)
          #define RTE_ETH_RSS_IPV6_TCP_EX        RTE_BIT64(16)
    • RSS key的长度为40。不支持设置hash算法函数,应该使用的是硬件默认的hash算法,具体是什么不确定(可能是Toeplitz?)

    • Redirect table的大小,256。

  • Intel E810

    • 支持报文类型为,不支持RTE_ETH_RSS_L3_SRC_ONLY等设置,不支持ipv6地址前缀长度选择:

          RTE_ETH_RSS_IPV4
          RTE_ETH_RSS_NONFRAG_IPV4_TCP
          RTE_ETH_RSS_NONFRAG_IPV4_UDP
          RTE_ETH_RSS_NONFRAG_IPV4_SCTP
          RTE_ETH_RSS_IPV6
          RTE_ETH_RSS_NONFRAG_IPV6_TCP
          RTE_ETH_RSS_NONFRAG_IPV6_UDP
          RTE_ETH_RSS_NONFRAG_IPV6_SCTP

    • RSS key的长度为40。不支持设置hash算法函数,应该使用的是硬件默认的hash算法,具体是什么不确定(可能是Toeplitz?)

    • Redirect table的大小,256。

    • Rte flow的rss action支持的配置更多。包括RTE_ETH_RSS_L3_SRC_ONLY设置、ipv6地址前缀长度设置。支持的hash函数也可配。这里不再列出,源代码有点复杂。

各个网卡的实现分析

        内核的RSS配置,支持不同的报文类型,选择不同的字段进行hash计算。但是实际上,很多网卡的实现并不支持这么灵活的配置。例如82599和华为的hinic,硬件的配置参数为报文类型的识别指示,对于指定的报文类型,按照固定的字段进行hash计算,不支持灵活配置。从CX6的内核驱动代码来看,目前对于不同的协议类型,支持灵活的配置。

1、82599

  不支持对于不同的报文类型,设置不同的hash字段选择。硬件有一套默认的hash字段选择规范。硬件目前只能识别ipv4 tcp、ipv4 udp、ipv6 tcp、ipv6 udp,ipv4, ipv6。

  ipv4 tcp和ipv6 tcp默认使用sip+dip+sport+dport计算hash,这个是默认配置,不支持更改。

  ipv4 udp和ipv6 udp支持配置,如果配置,使用sip+dip+sport+dport计算hash。如果不配置,则认为是普通的ipv4或ipv6。

  普通的ipv4或ipv6默认使用sip + dip计算hash,这个是默认配置,不支持更改。

2、cx6

        从CX6的内核驱动代码来看,目前对于不同的协议类型,支持灵活的配置。只支持ipv4 tcp、ipv4 udp、ipv6 tcp、ipv6 udp报文类型。不支持SCTP、AH和ESP

3、华为hinic

  实现和82599类似,设置ipv4 tcp、ipv4 udp、ipv6 tcp、ipv6 udp等标记,如果没有设置这些标记,对于tcp和udp报文,则认为是普通ipv4报文,对于普通ipv4报文使用sip + dip计算hash。

  默认的普通ipv4和ipv6配置,ethtool命令行怎么配置? ethtool命令行目前不支持单独的ipv4和ipv6报文类型的配置。(是否任意配置一个类型,例如udp4或者tcp6,都会设置ipv4或者ipv6报文类型的配置?)

4、E810

  对于不同的协议类型,支持灵活的配置。只支持ipv4 tcp、ipv4 udp、ipv4 sctp、ipv6 tcp、ipv6 udp、ipv6 sctp报文类型。不支持AH和ESP

网卡芯片RSS功能架构

支持OVS offload的网卡芯片系统架构

硬件RSS表项的内容:

  • 协议报文hash字段选择配置

    • 支持以下协议类型:ipv4 tcp、ipv4 udp、ipv4 sctp、ipv4 ah、ipv4 esp、ipv6 tcp、ipv6 udp、ipv6 sctp,ipv6 ah、ipv6 esp、ipv4、ipv6,共12种类型

    • 对于每一种协议类型,存在以下bit位:

      • Valid,1bit,当前协议是否生效。如果为无效,则认为该报文是普通的ipv4报文

      • SIP selected,1bit。表明是否使用sip计算hash。

      • DIP selected,1bit。表明是否使用dip计算hash。

      • Ip protocol selected,1bit。表明是否使用Ip protocol计算hash。

      • l4-B-01 selected,1bit。表明是否使用L4 header的前2个字节计算hash。

      • l4-B-23 selected,1bit。表明是否使用L4 header的第2和第3个字节计算hash。

      • ipv6 extend,1bit。如果存在IPv6 destination options header头,使用该header中的Home address作为源IPv6地址,参与hash计算;如果存在Routing-Header-Type-2,使用该header中的IPv6地址作为目的IPv6地址,参与hash计算。

    • 一些公共标记

      • level,1bit,0表示使用隧道外层做RSS,1表示使用隧道内层做RSS。

      • Vxlan selected,1bit,1表示,对于vxlan报文,VNI也参与计算hash,否则不参与计算

      • GENEVE selected,1bit,1表示,对于GENEVE报文,VNI也参与计算hash,否则不参与计算

      • NVGRE selected,1bit,1表示,对于NVGRE报文,VSI也参与计算hash,否则不参与计算

      • ipv4 frag hash,1bit,1表示,对于ipv4分片报文参与hash计算,当作普通的ipv4报文,默认不参与hash计算

      • ipv6 frag hash,1bit,1表示,对于ipv6分片报文参与hash计算,当作普通的ipv6报文,默认不参与hash计算

  • hash函数,3bit

    • 0:Toeplitz;1:XOR:3;CRC32;4:symmetric Toeplitz;5: symmetric Toeplitz sort

  • Hash key,40字节

  • Redirect table,MxN。 M为表的条目数,128或者256;N为队列编号的位宽,取决于硬件队列的个数。

QA

1、如果是隧道报文,使用内层还是外层的报文信息做RSS?

        对于linux的ethtool配置的RSS,目前不能指定内层还是外层。其行为由网卡自己控制。通常情况下,使用外层报文做RSS。也可以对于隧道报文,使用内层信息做RSS。

        对于DPDK的网口默认RSS配置,目前也不能指定内层还是外层。其行为由网卡自己控制。

        对于DPDK的rte flow做RSS,可以指定由内层还是外层做RSS。

2、是否存在多个RSS配置信息相同的问题?如何解决这个问题?

        不管是linux内核的rss context,还是dpdk的rte flow的rss action,都可能会存在RSS配置信息相同的问题,即linux内核的多个rss context配置信息完全相同,多个rte flow的rss action完全相同。

        对于linux内核,在实际应用中,用户不应该配置多个rss context信息一模一样,只配置一个rss context就好了,完全没有必要配置多个。多个flow directory条目可以指向同一个rss context。

        对于rte flow的rss action完全相同的问题,最新的DPDK版本已经支持indirector action的配置接口。用户可以先通过DPDK的action_handle_create接口,配置一个共享的RSS action,该接口返回一个action handle,然后多个rte flow的配置条目,可以包含相同的rss indirector action handle。

        如果DPDK接口不支持action_handle_create接口,那么可以在flow create的时候,可以自己将RSS action进行统一管理,查询重复的RSS action配置,并进行引用计数管理。

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值