Skip to content

Commit 1e153d1

Browse files
azaki1NipaLocal
authored andcommitted
net: ethtool: add support for symmetric-xor RSS hash
Symmetric RSS hash functions are beneficial in applications that monitor both Tx and Rx packets of the same flow (IDS, software firewalls, ..etc). Getting all traffic of the same flow on the same RX queue results in higher CPU cache efficiency. A NIC that supports "symmetric-xor" can achieve this RSS hash symmetry by XORing the source and destination fields and pass the values to the RSS hash algorithm. The user may request RSS hash symmetry for a specific algorithm, via: # ethtool -X eth0 hfunc <hash_alg> symmetric-xor or turn symmetry off (asymmetric) by: # ethtool -X eth0 hfunc <hash_alg> The specific fields for each flow type should then be specified as usual via: # ethtool -N|-U eth0 rx-flow-hash <flow_type> s|d|f|n Reviewed-by: Wojciech Drewek <[email protected]> CC: [email protected] Signed-off-by: Ahmed Zaki <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent ff9bab1 commit 1e153d1

File tree

8 files changed

+74
-6
lines changed

8 files changed

+74
-6
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

include/linux/ethtool.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,8 @@ struct ethtool_mm_stats {
615615
* to allocate a new RSS context; on return this field will
616616
* contain the ID of the newly allocated context.
617617
* @rss_delete: Set to non-ZERO to remove the @rss_context context.
618+
* @input_xfrm: Defines how the input data is transformed. Valid values are one
619+
* of %RXH_XFRM_*.
618620
*/
619621
struct ethtool_rxfh_param {
620622
u8 hfunc;
@@ -624,6 +626,7 @@ struct ethtool_rxfh_param {
624626
u8 *key;
625627
u32 rss_context;
626628
u8 rss_delete;
629+
u8 input_xfrm;
627630
};
628631

629632
/**
@@ -632,6 +635,8 @@ struct ethtool_rxfh_param {
632635
* parameter.
633636
* @cap_rss_ctx_supported: indicates if the driver supports RSS
634637
* contexts.
638+
* @cap_rss_sym_xor_supported: indicates if the driver supports symmetric-xor
639+
* RSS.
635640
* @supported_coalesce_params: supported types of interrupt coalescing.
636641
* @supported_ring_params: supported ring params.
637642
* @get_drvinfo: Report driver/device information. Modern drivers no
@@ -811,6 +816,7 @@ struct ethtool_rxfh_param {
811816
struct ethtool_ops {
812817
u32 cap_link_lanes_supported:1;
813818
u32 cap_rss_ctx_supported:1;
819+
u32 cap_rss_sym_xor_supported:1;
814820
u32 supported_coalesce_params;
815821
u32 supported_ring_params;
816822
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);

include/uapi/linux/ethtool.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,8 @@ struct ethtool_rxfh_indir {
12661266
* hardware hash key.
12671267
* @hfunc: Defines the current RSS hash function used by HW (or to be set to).
12681268
* Valid values are one of the %ETH_RSS_HASH_*.
1269+
* @input_xfrm: Defines how the input data is transformed. Valid values are one
1270+
* of %RXH_XFRM_*.
12691271
* @rsvd8: Reserved for future use; see the note on reserved space.
12701272
* @rsvd32: Reserved for future use; see the note on reserved space.
12711273
* @rss_config: RX ring/queue index for each hash value i.e., indirection table
@@ -1285,7 +1287,8 @@ struct ethtool_rxfh {
12851287
__u32 indir_size;
12861288
__u32 key_size;
12871289
__u8 hfunc;
1288-
__u8 rsvd8[3];
1290+
__u8 input_xfrm;
1291+
__u8 rsvd8[2];
12891292
__u32 rsvd32;
12901293
__u32 rss_config[];
12911294
};
@@ -1992,6 +1995,14 @@ static inline int ethtool_validate_duplex(__u8 duplex)
19921995

19931996
#define WOL_MODE_COUNT 8
19941997

1998+
/* RSS hash function data
1999+
* XOR the corresponding source and destination fields of each specified
2000+
* protocol. Both copies of the XOR'ed fields are fed into the RSS and RXHASH
2001+
* calculation. Note that this XORing reduces the input set entropy and could
2002+
* be exploited to reduce the RSS queue spread.
2003+
*/
2004+
#define RXH_XFRM_SYM_XOR (1 << 0)
2005+
19952006
/* L2-L4 network traffic flow types */
19962007
#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */
19972008
#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */

include/uapi/linux/ethtool_netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,7 @@ enum {
908908
ETHTOOL_A_RSS_HFUNC, /* u32 */
909909
ETHTOOL_A_RSS_INDIR, /* binary */
910910
ETHTOOL_A_RSS_HKEY, /* binary */
911+
ETHTOOL_A_RSS_INPUT_XFRM, /* u32 */
911912

912913
__ETHTOOL_A_RSS_CNT,
913914
ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1),

net/ethtool/ioctl.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -972,18 +972,35 @@ static int ethtool_rxnfc_copy_to_user(void __user *useraddr,
972972
static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
973973
u32 cmd, void __user *useraddr)
974974
{
975+
const struct ethtool_ops *ops = dev->ethtool_ops;
976+
struct ethtool_rxfh_param rxfh = {};
975977
struct ethtool_rxnfc info;
976978
size_t info_size = sizeof(info);
977979
int rc;
978980

979-
if (!dev->ethtool_ops->set_rxnfc)
981+
if (!ops->set_rxnfc || !ops->get_rxfh)
980982
return -EOPNOTSUPP;
981983

982984
rc = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr);
983985
if (rc)
984986
return rc;
985987

986-
rc = dev->ethtool_ops->set_rxnfc(dev, &info);
988+
rc = ops->get_rxfh(dev, &rxfh);
989+
if (rc)
990+
return rc;
991+
992+
/* Sanity check: if symmetric-xor is set, then:
993+
* 1 - no other fields besides IP src/dst and/or L4 src/dst
994+
* 2 - If src is set, dst must also be set
995+
*/
996+
if ((rxfh.input_xfrm & RXH_XFRM_SYM_XOR) &&
997+
((info.data & ~(RXH_IP_SRC | RXH_IP_DST |
998+
RXH_L4_B_0_1 | RXH_L4_B_2_3)) ||
999+
(!!(info.data & RXH_IP_SRC) ^ !!(info.data & RXH_IP_DST)) ||
1000+
(!!(info.data & RXH_L4_B_0_1) ^ !!(info.data & RXH_L4_B_2_3))))
1001+
return -EINVAL;
1002+
1003+
rc = ops->set_rxnfc(dev, &info);
9871004
if (rc)
9881005
return rc;
9891006

@@ -1198,7 +1215,7 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
11981215
user_key_size = rxfh.key_size;
11991216

12001217
/* Check that reserved fields are 0 for now */
1201-
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd8[2] || rxfh.rsvd32)
1218+
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd32)
12021219
return -EINVAL;
12031220
/* Most drivers don't handle rss_context, check it's 0 as well */
12041221
if (rxfh.rss_context && !ops->cap_rss_ctx_supported)
@@ -1271,11 +1288,15 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
12711288
return -EFAULT;
12721289

12731290
/* Check that reserved fields are 0 for now */
1274-
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd8[2] || rxfh.rsvd32)
1291+
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd32)
12751292
return -EINVAL;
12761293
/* Most drivers don't handle rss_context, check it's 0 as well */
12771294
if (rxfh.rss_context && !ops->cap_rss_ctx_supported)
12781295
return -EOPNOTSUPP;
1296+
/* Check input data transformation capabilities */
1297+
if ((rxfh.input_xfrm & RXH_XFRM_SYM_XOR) &&
1298+
!ops->cap_rss_sym_xor_supported)
1299+
return -EOPNOTSUPP;
12791300

12801301
/* If either indir, hash key or function is valid, proceed further.
12811302
* Must request at least one change: indir size, hash key or function.
@@ -1341,6 +1362,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
13411362

13421363
rxfh_dev.hfunc = rxfh.hfunc;
13431364
rxfh_dev.rss_context = rxfh.rss_context;
1365+
rxfh_dev.input_xfrm = rxfh.input_xfrm;
13441366

13451367
ret = ops->set_rxfh(dev, &rxfh_dev, extack);
13461368
if (ret)

net/ethtool/rss.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct rss_reply_data {
1313
u32 indir_size;
1414
u32 hkey_size;
1515
u32 hfunc;
16+
u32 input_xfrm;
1617
u32 *indir_table;
1718
u8 *hkey;
1819
};
@@ -97,6 +98,7 @@ rss_prepare_data(const struct ethnl_req_info *req_base,
9798
goto out_ops;
9899

99100
data->hfunc = rxfh.hfunc;
101+
data->input_xfrm = rxfh.input_xfrm;
100102
out_ops:
101103
ethnl_ops_complete(dev);
102104
return ret;
@@ -110,6 +112,7 @@ rss_reply_size(const struct ethnl_req_info *req_base,
110112
int len;
111113

112114
len = nla_total_size(sizeof(u32)) + /* _RSS_HFUNC */
115+
nla_total_size(sizeof(u32)) + /* _RSS_INPUT_XFRM */
113116
nla_total_size(sizeof(u32) * data->indir_size) + /* _RSS_INDIR */
114117
nla_total_size(data->hkey_size); /* _RSS_HKEY */
115118

@@ -124,6 +127,8 @@ rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base,
124127

125128
if ((data->hfunc &&
126129
nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) ||
130+
(data->input_xfrm &&
131+
nla_put_u32(skb, ETHTOOL_A_RSS_INPUT_XFRM, data->input_xfrm)) ||
127132
(data->indir_size &&
128133
nla_put(skb, ETHTOOL_A_RSS_INDIR,
129134
sizeof(u32) * data->indir_size, data->indir_table)) ||

0 commit comments

Comments
 (0)