toozyfuzzy
toozyfuzzy

Reputation: 1236

RSS (Receive Side Scaling) on Intel XL710 Per port

I struggle with Intel XL710 card using DPDK to make it compute RSS hash using only SRC IPV4 or DST IPV4 on per port basis. The card has 4 10GE ports and RSS config is global for them whatever i do. I tried to set SRC/DST IPV4 fields in PCTYPE and the configuration applied last only takes action.

So the behavior i want to achieve.

Let's say i have upstream packet arrived on port 0:

SRC: 10.10.10.1 and DST:10.10.10.2

And reply downstream packet arrived on port 1:

SRC: 10.10.10.2 and DST:10.10.10.1

I want port 0 (which in our case is upstream) on the card to compute RSS hash based on SRC address 10.10.10.1 and for, port 1 (which is downstream) to compute the hash using DST address which in our case also will be 10.10.10.1. So the idea is to distribute packets between RX queues in a way that only SRC/DST address respectively affects this distribution.

I'm not bound specifically to RSS. Whatever tech will do if it allows to achieve this.

The configuration i used:

void setFilter(uint16_t portId, uint32_t value){

//Value = RTE_ETH_FLOW_NONFRAG_IPV4_TCP in that case

struct rte_eth_hash_filter_info info;
uint32_t ftype, idx, offset;
int ret;

if (rte_eth_dev_filter_supported(portId,
            RTE_ETH_FILTER_HASH) < 0) {
    printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
                        portId);
    return;
}

memset(&info, 0, sizeof(info));
info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
info.info.global_conf.hash_func =
  RTE_ETH_HASH_FUNCTION_DEFAULT;

ftype = value;
idx = ftype / UINT64_BIT;
offset = ftype % UINT64_BIT;
info.info.global_conf.valid_bit_mask[idx] |= (1ULL << offset);
info.info.global_conf.sym_hash_enable_mask[idx] |=
  (1ULL << offset);
ret = rte_eth_dev_filter_ctrl(portId, RTE_ETH_FILTER_HASH,
                RTE_ETH_FILTER_SET, &info);
if (ret < 0)
    printf("Cannot set global hash configurations by port %d\n",
                        portId);
else
    printf("Global hash configurations have been set "
           "succcessfully by port %d\n", portId);
}

void setPctypeRss(uint16_t portId, uint16_t fieldIdx) {

/* Note that AVF_FILTER_PCTYPE_NONF_IPV4_TCP is define for
 * Virtual Function. Defines are the same for Physical Functions
 */
int ret = -ENOTSUP;

enum rte_pmd_i40e_inset_type inset_type = INSET_HASH;
struct rte_pmd_i40e_inset inset;

ret = rte_pmd_i40e_inset_get(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
                             &inset, inset_type);

if (ret) {
    printf("Failed to get input set.\n");
    return;
}

memset(&inset, 0, sizeof(inset));

ret = rte_pmd_i40e_inset_set(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
                 &inset, inset_type);

if (ret) {
    printf("Failed to CLEAR input set.\n");
    return;
}
else
{
    printf("Successfull cleared input set\n");
}

ret = rte_pmd_i40e_inset_get(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
                 &inset, inset_type);
if (ret) {
    printf("Failed to get input set.\n");
    return;
}

ret = rte_pmd_i40e_inset_field_set(&inset.inset, fieldIdx);

if (ret) {
    printf("Failed to configure input set field.\n");
    return;
}

ret = rte_pmd_i40e_inset_set(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
                 &inset, inset_type);
if (ret) {
    printf("Failed to set input set.\n");
    return;
}

if (ret == -ENOTSUP)
    printf("Function not supported\n");
}

Upvotes: 1

Views: 1250

Answers (1)

Andriy Berestovskyy
Andriy Berestovskyy

Reputation: 8544

IMO it is worth trying a bit simpler solution. We can simply use rte_eth_dev_configure():

https://doc.dpdk.org/api/rte__ethdev_8h.html#a1a7d3a20b102fee222541fda50fd87bd

And just set eth_conf.rss_conf.rss_hf to ETH_RSS_IP as described here:

https://doc.dpdk.org/api/structrte__eth__rss__conf.html#ad70f17882a835e5d4e38c64a9f872fdc

There are few examples in DPDK using this functionality. and most of them work fine ;)

Upvotes: 1

Related Questions