Skip to content

Commit 04c0472

Browse files
committed
Merge branch 'support-symmetric-xor-rss-hash'
Ahmed Zaki says: ==================== Support symmetric-xor RSS hash Patches 1 and 2 modify the get/set_rxh ethtool API to take a pointer to struct of parameters instead of individual params. This will allow future changes to the uAPI-shared struct ethtool_rxfh without changing the drivers' API. Patch 3 adds the support at the Kernel level, allowing the user to set a symmetric-xor RSS hash for a netdevice via: # ethtool -X eth0 hfunc toeplitz symmetric-xor and clears the flag via: # ethtool -X eth0 hfunc toeplitz The "symmetric-xor" is set in a new "input_xfrm" field in struct ethtool_rxfh. Support for the new "symmetric-xor" flag will be later sent to the "ethtool" user-space tool. Patch 4 fixes a long standing bug with the ice hash function register values. The bug has been benign for now since only (asymmetric) Toeplitz hash (Zero) has been used. Patches 5 and 6 lay some groundwork refactoring. While the first is mainly cosmetic, the second is needed since there is no more room in the previous 64-bit RSS profile ID for the symmetric attribute introduced in the next patch. Finally, patches 7 and 8 add the symmetric-xor support for the ice (E800 PFs) and the iAVF drivers. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents c3f687d + 4a3de3f commit 04c0472

File tree

79 files changed

+1817
-1238
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1817
-1238
lines changed

Documentation/netlink/specs/ethtool.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,9 @@ attribute-sets:
908908
-
909909
name: hkey
910910
type: binary
911+
-
912+
name: input_xfrm
913+
type: u32
911914
-
912915
name: plca
913916
attributes:
@@ -1598,6 +1601,7 @@ operations:
15981601
- hfunc
15991602
- indir
16001603
- hkey
1604+
- input_xfrm
16011605
dump: *rss-get-op
16021606
-
16031607
name: plca-get-cfg

Documentation/networking/ethtool-netlink.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1774,12 +1774,16 @@ Kernel response contents:
17741774
``ETHTOOL_A_RSS_HFUNC`` u32 RSS hash func
17751775
``ETHTOOL_A_RSS_INDIR`` binary Indir table bytes
17761776
``ETHTOOL_A_RSS_HKEY`` binary Hash key bytes
1777+
``ETHTOOL_A_RSS_INPUT_XFRM`` u32 RSS input data transformation
17771778
===================================== ====== ==========================
17781779

17791780
ETHTOOL_A_RSS_HFUNC attribute is bitmap indicating the hash function
17801781
being used. Current supported options are toeplitz, xor or crc32.
1781-
ETHTOOL_A_RSS_INDIR attribute returns RSS indrection table where each byte
1782+
ETHTOOL_A_RSS_INDIR attribute returns RSS indirection table where each byte
17821783
indicates queue number.
1784+
ETHTOOL_A_RSS_INPUT_XFRM attribute is a bitmap indicating the type of
1785+
transformation applied to the input protocol fields before given to the RSS
1786+
hfunc. Current supported option is symmetric-xor.
17831787

17841788
PLCA_GET_CFG
17851789
============

Documentation/networking/scaling.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ by masking out the low order seven bits of the computed hash for the
4444
packet (usually a Toeplitz hash), taking this number as a key into the
4545
indirection table and reading the corresponding value.
4646

47+
Some NICs support symmetric RSS hashing where, if the IP (source address,
48+
destination address) and TCP/UDP (source port, destination port) tuples
49+
are swapped, the computed hash is the same. This is beneficial in some
50+
applications that monitor TCP/IP flows (IDS, firewalls, ...etc) and need
51+
both directions of the flow to land on the same Rx queue (and CPU). The
52+
"Symmetric-XOR" is a type of RSS algorithms that achieves this hash
53+
symmetry by XORing the input source and destination fields of the IP
54+
and/or L4 protocols. This, however, results in reduced input entropy and
55+
could potentially be exploited. Specifically, the algorithm XORs the input
56+
as follows::
57+
58+
# (SRC_IP ^ DST_IP, SRC_IP ^ DST_IP, SRC_PORT ^ DST_PORT, SRC_PORT ^ DST_PORT)
59+
60+
The result is then fed to the underlying RSS algorithm.
61+
4762
Some advanced NICs allow steering packets to queues based on
4863
programmable filters. For example, webserver bound TCP port 80 packets
4964
can be directed to their own receive queue. Such “n-tuple” filters can

drivers/net/ethernet/amazon/ena/ena_ethtool.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -802,15 +802,15 @@ static int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir)
802802
return rc;
803803
}
804804

805-
static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
806-
u8 *hfunc)
805+
static int ena_get_rxfh(struct net_device *netdev,
806+
struct ethtool_rxfh_param *rxfh)
807807
{
808808
struct ena_adapter *adapter = netdev_priv(netdev);
809809
enum ena_admin_hash_functions ena_func;
810810
u8 func;
811811
int rc;
812812

813-
rc = ena_indirection_table_get(adapter, indir);
813+
rc = ena_indirection_table_get(adapter, rxfh->indir);
814814
if (rc)
815815
return rc;
816816

@@ -825,7 +825,7 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
825825
return rc;
826826
}
827827

828-
rc = ena_com_get_hash_key(adapter->ena_dev, key);
828+
rc = ena_com_get_hash_key(adapter->ena_dev, rxfh->key);
829829
if (rc)
830830
return rc;
831831

@@ -842,27 +842,27 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
842842
return -EOPNOTSUPP;
843843
}
844844

845-
if (hfunc)
846-
*hfunc = func;
845+
rxfh->hfunc = func;
847846

848847
return 0;
849848
}
850849

851-
static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
852-
const u8 *key, const u8 hfunc)
850+
static int ena_set_rxfh(struct net_device *netdev,
851+
struct ethtool_rxfh_param *rxfh,
852+
struct netlink_ext_ack *extack)
853853
{
854854
struct ena_adapter *adapter = netdev_priv(netdev);
855855
struct ena_com_dev *ena_dev = adapter->ena_dev;
856856
enum ena_admin_hash_functions func = 0;
857857
int rc;
858858

859-
if (indir) {
860-
rc = ena_indirection_table_set(adapter, indir);
859+
if (rxfh->indir) {
860+
rc = ena_indirection_table_set(adapter, rxfh->indir);
861861
if (rc)
862862
return rc;
863863
}
864864

865-
switch (hfunc) {
865+
switch (rxfh->hfunc) {
866866
case ETH_RSS_HASH_NO_CHANGE:
867867
func = ena_com_get_current_hash_function(ena_dev);
868868
break;
@@ -874,12 +874,12 @@ static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
874874
break;
875875
default:
876876
netif_err(adapter, drv, netdev, "Unsupported hfunc %d\n",
877-
hfunc);
877+
rxfh->hfunc);
878878
return -EOPNOTSUPP;
879879
}
880880

881-
if (key || func) {
882-
rc = ena_com_fill_hash_function(ena_dev, func, key,
881+
if (rxfh->key || func) {
882+
rc = ena_com_fill_hash_function(ena_dev, func, rxfh->key,
883883
ENA_HASH_KEY_SIZE,
884884
0xFFFFFFFF);
885885
if (unlikely(rc)) {

drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -527,47 +527,48 @@ static u32 xgbe_get_rxfh_indir_size(struct net_device *netdev)
527527
return ARRAY_SIZE(pdata->rss_table);
528528
}
529529

530-
static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
531-
u8 *hfunc)
530+
static int xgbe_get_rxfh(struct net_device *netdev,
531+
struct ethtool_rxfh_param *rxfh)
532532
{
533533
struct xgbe_prv_data *pdata = netdev_priv(netdev);
534534
unsigned int i;
535535

536-
if (indir) {
536+
if (rxfh->indir) {
537537
for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++)
538-
indir[i] = XGMAC_GET_BITS(pdata->rss_table[i],
539-
MAC_RSSDR, DMCH);
538+
rxfh->indir[i] = XGMAC_GET_BITS(pdata->rss_table[i],
539+
MAC_RSSDR, DMCH);
540540
}
541541

542-
if (key)
543-
memcpy(key, pdata->rss_key, sizeof(pdata->rss_key));
542+
if (rxfh->key)
543+
memcpy(rxfh->key, pdata->rss_key, sizeof(pdata->rss_key));
544544

545-
if (hfunc)
546-
*hfunc = ETH_RSS_HASH_TOP;
545+
rxfh->hfunc = ETH_RSS_HASH_TOP;
547546

548547
return 0;
549548
}
550549

551-
static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
552-
const u8 *key, const u8 hfunc)
550+
static int xgbe_set_rxfh(struct net_device *netdev,
551+
struct ethtool_rxfh_param *rxfh,
552+
struct netlink_ext_ack *extack)
553553
{
554554
struct xgbe_prv_data *pdata = netdev_priv(netdev);
555555
struct xgbe_hw_if *hw_if = &pdata->hw_if;
556556
unsigned int ret;
557557

558-
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) {
558+
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
559+
rxfh->hfunc != ETH_RSS_HASH_TOP) {
559560
netdev_err(netdev, "unsupported hash function\n");
560561
return -EOPNOTSUPP;
561562
}
562563

563-
if (indir) {
564-
ret = hw_if->set_rss_lookup_table(pdata, indir);
564+
if (rxfh->indir) {
565+
ret = hw_if->set_rss_lookup_table(pdata, rxfh->indir);
565566
if (ret)
566567
return ret;
567568
}
568569

569-
if (key) {
570-
ret = hw_if->set_rss_hash_key(pdata, key);
570+
if (rxfh->key) {
571+
ret = hw_if->set_rss_hash_key(pdata, rxfh->key);
571572
if (ret)
572573
return ret;
573574
}

drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -447,30 +447,30 @@ static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
447447
return sizeof(cfg->aq_rss.hash_secret_key);
448448
}
449449

450-
static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
451-
u8 *hfunc)
450+
static int aq_ethtool_get_rss(struct net_device *ndev,
451+
struct ethtool_rxfh_param *rxfh)
452452
{
453453
struct aq_nic_s *aq_nic = netdev_priv(ndev);
454454
struct aq_nic_cfg_s *cfg;
455455
unsigned int i = 0U;
456456

457457
cfg = aq_nic_get_cfg(aq_nic);
458458

459-
if (hfunc)
460-
*hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
461-
if (indir) {
459+
rxfh->hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
460+
if (rxfh->indir) {
462461
for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
463-
indir[i] = cfg->aq_rss.indirection_table[i];
462+
rxfh->indir[i] = cfg->aq_rss.indirection_table[i];
464463
}
465-
if (key)
466-
memcpy(key, cfg->aq_rss.hash_secret_key,
464+
if (rxfh->key)
465+
memcpy(rxfh->key, cfg->aq_rss.hash_secret_key,
467466
sizeof(cfg->aq_rss.hash_secret_key));
468467

469468
return 0;
470469
}
471470

472-
static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
473-
const u8 *key, const u8 hfunc)
471+
static int aq_ethtool_set_rss(struct net_device *netdev,
472+
struct ethtool_rxfh_param *rxfh,
473+
struct netlink_ext_ack *extack)
474474
{
475475
struct aq_nic_s *aq_nic = netdev_priv(netdev);
476476
struct aq_nic_cfg_s *cfg;
@@ -482,16 +482,17 @@ static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
482482
rss_entries = cfg->aq_rss.indirection_table_size;
483483

484484
/* We do not allow change in unsupported parameters */
485-
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
485+
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
486+
rxfh->hfunc != ETH_RSS_HASH_TOP)
486487
return -EOPNOTSUPP;
487488
/* Fill out the redirection table */
488-
if (indir)
489+
if (rxfh->indir)
489490
for (i = 0; i < rss_entries; i++)
490-
cfg->aq_rss.indirection_table[i] = indir[i];
491+
cfg->aq_rss.indirection_table[i] = rxfh->indir[i];
491492

492493
/* Fill out the rss hash key */
493-
if (key) {
494-
memcpy(cfg->aq_rss.hash_secret_key, key,
494+
if (rxfh->key) {
495+
memcpy(cfg->aq_rss.hash_secret_key, rxfh->key,
495496
sizeof(cfg->aq_rss.hash_secret_key));
496497
err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
497498
&cfg->aq_rss);

drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3486,16 +3486,15 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
34863486
return T_ETH_INDIRECTION_TABLE_SIZE;
34873487
}
34883488

3489-
static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
3490-
u8 *hfunc)
3489+
static int bnx2x_get_rxfh(struct net_device *dev,
3490+
struct ethtool_rxfh_param *rxfh)
34913491
{
34923492
struct bnx2x *bp = netdev_priv(dev);
34933493
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
34943494
size_t i;
34953495

3496-
if (hfunc)
3497-
*hfunc = ETH_RSS_HASH_TOP;
3498-
if (!indir)
3496+
rxfh->hfunc = ETH_RSS_HASH_TOP;
3497+
if (!rxfh->indir)
34993498
return 0;
35003499

35013500
/* Get the current configuration of the RSS indirection table */
@@ -3511,25 +3510,27 @@ static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
35113510
* queue.
35123511
*/
35133512
for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++)
3514-
indir[i] = ind_table[i] - bp->fp->cl_id;
3513+
rxfh->indir[i] = ind_table[i] - bp->fp->cl_id;
35153514

35163515
return 0;
35173516
}
35183517

3519-
static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
3520-
const u8 *key, const u8 hfunc)
3518+
static int bnx2x_set_rxfh(struct net_device *dev,
3519+
struct ethtool_rxfh_param *rxfh,
3520+
struct netlink_ext_ack *extack)
35213521
{
35223522
struct bnx2x *bp = netdev_priv(dev);
35233523
size_t i;
35243524

35253525
/* We require at least one supported parameter to be changed and no
35263526
* change in any of the unsupported parameters
35273527
*/
3528-
if (key ||
3529-
(hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
3528+
if (rxfh->key ||
3529+
(rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
3530+
rxfh->hfunc != ETH_RSS_HASH_TOP))
35303531
return -EOPNOTSUPP;
35313532

3532-
if (!indir)
3533+
if (!rxfh->indir)
35333534
return 0;
35343535

35353536
for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
@@ -3542,7 +3543,7 @@ static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
35423543
* align the received table to the Client ID of the leading RSS
35433544
* queue
35443545
*/
3545-
bp->rss_conf_obj.ind_table[i] = indir[i] + bp->fp->cl_id;
3546+
bp->rss_conf_obj.ind_table[i] = rxfh->indir[i] + bp->fp->cl_id;
35463547
}
35473548

35483549
if (bp->state == BNX2X_STATE_OPEN)

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,49 +1333,49 @@ static u32 bnxt_get_rxfh_key_size(struct net_device *dev)
13331333
return HW_HASH_KEY_SIZE;
13341334
}
13351335

1336-
static int bnxt_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
1337-
u8 *hfunc)
1336+
static int bnxt_get_rxfh(struct net_device *dev,
1337+
struct ethtool_rxfh_param *rxfh)
13381338
{
13391339
struct bnxt *bp = netdev_priv(dev);
13401340
struct bnxt_vnic_info *vnic;
13411341
u32 i, tbl_size;
13421342

1343-
if (hfunc)
1344-
*hfunc = ETH_RSS_HASH_TOP;
1343+
rxfh->hfunc = ETH_RSS_HASH_TOP;
13451344

13461345
if (!bp->vnic_info)
13471346
return 0;
13481347

13491348
vnic = &bp->vnic_info[0];
1350-
if (indir && bp->rss_indir_tbl) {
1349+
if (rxfh->indir && bp->rss_indir_tbl) {
13511350
tbl_size = bnxt_get_rxfh_indir_size(dev);
13521351
for (i = 0; i < tbl_size; i++)
1353-
indir[i] = bp->rss_indir_tbl[i];
1352+
rxfh->indir[i] = bp->rss_indir_tbl[i];
13541353
}
13551354

1356-
if (key && vnic->rss_hash_key)
1357-
memcpy(key, vnic->rss_hash_key, HW_HASH_KEY_SIZE);
1355+
if (rxfh->key && vnic->rss_hash_key)
1356+
memcpy(rxfh->key, vnic->rss_hash_key, HW_HASH_KEY_SIZE);
13581357

13591358
return 0;
13601359
}
13611360

1362-
static int bnxt_set_rxfh(struct net_device *dev, const u32 *indir,
1363-
const u8 *key, const u8 hfunc)
1361+
static int bnxt_set_rxfh(struct net_device *dev,
1362+
struct ethtool_rxfh_param *rxfh,
1363+
struct netlink_ext_ack *extack)
13641364
{
13651365
struct bnxt *bp = netdev_priv(dev);
13661366
int rc = 0;
13671367

1368-
if (hfunc && hfunc != ETH_RSS_HASH_TOP)
1368+
if (rxfh->hfunc && rxfh->hfunc != ETH_RSS_HASH_TOP)
13691369
return -EOPNOTSUPP;
13701370

1371-
if (key)
1371+
if (rxfh->key)
13721372
return -EOPNOTSUPP;
13731373

1374-
if (indir) {
1374+
if (rxfh->indir) {
13751375
u32 i, pad, tbl_size = bnxt_get_rxfh_indir_size(dev);
13761376

13771377
for (i = 0; i < tbl_size; i++)
1378-
bp->rss_indir_tbl[i] = indir[i];
1378+
bp->rss_indir_tbl[i] = rxfh->indir[i];
13791379
pad = bp->rss_indir_tbl_entries - tbl_size;
13801380
if (pad)
13811381
memset(&bp->rss_indir_tbl[i], 0, pad * sizeof(u16));

0 commit comments

Comments
 (0)