Skip to content

Commit 5339dcb

Browse files
azaki1NipaLocal
authored and
NipaLocal
committed
iavf: enable symmetric-xor RSS for Toeplitz hash function
Allow the user to set the symmetric Toeplitz hash function via: # ethtool -X eth0 hfunc toeplitz symmetric-xor The driver will reject any new RSS configuration if a field other than (IP src/dst and L4 src/dst ports) is requested for hashing. The symmetric RSS will not be supported on PFs not advertising the ADV RSS Offload flag (ADV_RSS_SUPPORT()), for example the E700 series (i40e). Reviewed-by: Madhu Chittim <[email protected]> Signed-off-by: Ahmed Zaki <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 9d2ee8d commit 5339dcb

File tree

10 files changed

+156
-8
lines changed

10 files changed

+156
-8
lines changed

drivers/net/ethernet/intel/iavf/iavf.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,8 @@ struct iavf_adapter {
312312
#define IAVF_FLAG_AQ_SET_HENA BIT_ULL(12)
313313
#define IAVF_FLAG_AQ_SET_RSS_KEY BIT_ULL(13)
314314
#define IAVF_FLAG_AQ_SET_RSS_LUT BIT_ULL(14)
315-
#define IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE BIT_ULL(15)
315+
#define IAVF_FLAG_AQ_SET_RSS_HFUNC BIT_ULL(15)
316+
#define IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE BIT_ULL(16)
316317
#define IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING BIT_ULL(19)
317318
#define IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING BIT_ULL(20)
318319
#define IAVF_FLAG_AQ_ENABLE_CHANNELS BIT_ULL(21)
@@ -414,6 +415,7 @@ struct iavf_adapter {
414415
struct iavf_vsi vsi;
415416
u32 aq_wait_count;
416417
/* RSS stuff */
418+
enum virtchnl_rss_algorithm hfunc;
417419
u64 hena;
418420
u16 rss_key_size;
419421
u16 rss_lut_size;
@@ -539,6 +541,7 @@ void iavf_get_hena(struct iavf_adapter *adapter);
539541
void iavf_set_hena(struct iavf_adapter *adapter);
540542
void iavf_set_rss_key(struct iavf_adapter *adapter);
541543
void iavf_set_rss_lut(struct iavf_adapter *adapter);
544+
void iavf_set_rss_hfunc(struct iavf_adapter *adapter);
542545
void iavf_enable_vlan_stripping(struct iavf_adapter *adapter);
543546
void iavf_disable_vlan_stripping(struct iavf_adapter *adapter);
544547
void iavf_virtchnl_completion(struct iavf_adapter *adapter,

drivers/net/ethernet/intel/iavf/iavf_adv_rss.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,21 @@ iavf_fill_adv_rss_sctp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
9595
* @rss_cfg: the virtchnl message to be filled with RSS configuration setting
9696
* @packet_hdrs: the RSS configuration protocol header types
9797
* @hash_flds: the RSS configuration protocol hash fields
98+
* @symm: if true, symmetric hash is required
9899
*
99100
* Returns 0 if the RSS configuration virtchnl message is filled successfully
100101
*/
101102
int
102103
iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
103-
u32 packet_hdrs, u64 hash_flds)
104+
u32 packet_hdrs, u64 hash_flds, bool symm)
104105
{
105106
struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs;
106107
struct virtchnl_proto_hdr *hdr;
107108

108-
rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
109+
if (symm)
110+
rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
111+
else
112+
rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
109113

110114
proto_hdrs->tunnel_level = 0; /* always outer layer */
111115

drivers/net/ethernet/intel/iavf/iavf_adv_rss.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,14 @@ struct iavf_adv_rss {
8080

8181
u32 packet_hdrs;
8282
u64 hash_flds;
83+
bool symm;
8384

8485
struct virtchnl_rss_cfg cfg_msg;
8586
};
8687

8788
int
8889
iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
89-
u32 packet_hdrs, u64 hash_flds);
90+
u32 packet_hdrs, u64 hash_flds, bool symm);
9091
struct iavf_adv_rss *
9192
iavf_find_adv_rss_cfg_by_hdrs(struct iavf_adapter *adapter, u32 packet_hdrs);
9293
void

drivers/net/ethernet/intel/iavf/iavf_ethtool.c

+28-4
Original file line numberDiff line numberDiff line change
@@ -1529,11 +1529,12 @@ static u32 iavf_adv_rss_parse_hdrs(struct ethtool_rxnfc *cmd)
15291529
/**
15301530
* iavf_adv_rss_parse_hash_flds - parses hash fields from RSS hash input
15311531
* @cmd: ethtool rxnfc command
1532+
* @symm: true if Symmetric Topelitz is set
15321533
*
15331534
* This function parses the rxnfc command and returns intended hash fields for
15341535
* RSS configuration
15351536
*/
1536-
static u64 iavf_adv_rss_parse_hash_flds(struct ethtool_rxnfc *cmd)
1537+
static u64 iavf_adv_rss_parse_hash_flds(struct ethtool_rxnfc *cmd, bool symm)
15371538
{
15381539
u64 hfld = IAVF_ADV_RSS_HASH_INVALID;
15391540

@@ -1605,25 +1606,29 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
16051606
struct iavf_adv_rss *rss_old, *rss_new;
16061607
bool rss_new_add = false;
16071608
int count = 50, err = 0;
1609+
bool symm = false;
16081610
u64 hash_flds;
16091611
u32 hdrs;
16101612

16111613
if (!ADV_RSS_SUPPORT(adapter))
16121614
return -EOPNOTSUPP;
16131615

1616+
symm = !!(adapter->hfunc == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC);
1617+
16141618
hdrs = iavf_adv_rss_parse_hdrs(cmd);
16151619
if (hdrs == IAVF_ADV_RSS_FLOW_SEG_HDR_NONE)
16161620
return -EINVAL;
16171621

1618-
hash_flds = iavf_adv_rss_parse_hash_flds(cmd);
1622+
hash_flds = iavf_adv_rss_parse_hash_flds(cmd, symm);
16191623
if (hash_flds == IAVF_ADV_RSS_HASH_INVALID)
16201624
return -EINVAL;
16211625

16221626
rss_new = kzalloc(sizeof(*rss_new), GFP_KERNEL);
16231627
if (!rss_new)
16241628
return -ENOMEM;
16251629

1626-
if (iavf_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds)) {
1630+
if (iavf_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds,
1631+
symm)) {
16271632
kfree(rss_new);
16281633
return -EINVAL;
16291634
}
@@ -1642,9 +1647,11 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
16421647
if (rss_old) {
16431648
if (rss_old->state != IAVF_ADV_RSS_ACTIVE) {
16441649
err = -EBUSY;
1645-
} else if (rss_old->hash_flds != hash_flds) {
1650+
} else if (rss_old->hash_flds != hash_flds ||
1651+
rss_old->symm != symm) {
16461652
rss_old->state = IAVF_ADV_RSS_ADD_REQUEST;
16471653
rss_old->hash_flds = hash_flds;
1654+
rss_old->symm = symm;
16481655
memcpy(&rss_old->cfg_msg, &rss_new->cfg_msg,
16491656
sizeof(rss_new->cfg_msg));
16501657
} else {
@@ -1655,6 +1662,7 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
16551662
rss_new->state = IAVF_ADV_RSS_ADD_REQUEST;
16561663
rss_new->packet_hdrs = hdrs;
16571664
rss_new->hash_flds = hash_flds;
1665+
rss_new->symm = symm;
16581666
list_add_tail(&rss_new->list, &adapter->adv_rss_list_head);
16591667
}
16601668
spin_unlock_bh(&adapter->adv_rss_lock);
@@ -1905,6 +1913,9 @@ static int iavf_get_rxfh(struct net_device *netdev,
19051913
u16 i;
19061914

19071915
rxfh->hfunc = ETH_RSS_HASH_TOP;
1916+
if (adapter->hfunc == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
1917+
rxfh->input_xfrm |= RXH_XFRM_SYM_XOR;
1918+
19081919
if (rxfh->key)
19091920
memcpy(rxfh->key, adapter->rss_key, adapter->rss_key_size);
19101921

@@ -1937,6 +1948,18 @@ static int iavf_set_rxfh(struct net_device *netdev,
19371948
rxfh->hfunc != ETH_RSS_HASH_TOP)
19381949
return -EOPNOTSUPP;
19391950

1951+
if ((rxfh->input_xfrm & RXH_XFRM_SYM_XOR) &&
1952+
adapter->hfunc != VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC) {
1953+
if (!ADV_RSS_SUPPORT(adapter))
1954+
return -EOPNOTSUPP;
1955+
adapter->hfunc = VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
1956+
adapter->aq_required |= IAVF_FLAG_AQ_SET_RSS_HFUNC;
1957+
} else if (!(rxfh->input_xfrm & RXH_XFRM_SYM_XOR) &&
1958+
adapter->hfunc != VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC) {
1959+
adapter->hfunc = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
1960+
adapter->aq_required |= IAVF_FLAG_AQ_SET_RSS_HFUNC;
1961+
}
1962+
19401963
if (!rxfh->key && !rxfh->indir)
19411964
return 0;
19421965

@@ -1955,6 +1978,7 @@ static int iavf_set_rxfh(struct net_device *netdev,
19551978
static const struct ethtool_ops iavf_ethtool_ops = {
19561979
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
19571980
ETHTOOL_COALESCE_USE_ADAPTIVE,
1981+
.cap_rss_sym_xor_supported = true,
19581982
.get_drvinfo = iavf_get_drvinfo,
19591983
.get_link = ethtool_op_get_link,
19601984
.get_ringparam = iavf_get_ringparam,

drivers/net/ethernet/intel/iavf/iavf_main.c

+4
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,10 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
21662166
iavf_set_rss_lut(adapter);
21672167
return 0;
21682168
}
2169+
if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_HFUNC) {
2170+
iavf_set_rss_hfunc(adapter);
2171+
return 0;
2172+
}
21692173

21702174
if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE) {
21712175
iavf_set_promiscuous(adapter);

drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

+41
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,34 @@ void iavf_set_rss_lut(struct iavf_adapter *adapter)
11411141
kfree(vrl);
11421142
}
11431143

1144+
/**
1145+
* iavf_set_rss_hfunc
1146+
* @adapter: adapter structure
1147+
*
1148+
* Request the PF to set our RSS Hash function
1149+
**/
1150+
void iavf_set_rss_hfunc(struct iavf_adapter *adapter)
1151+
{
1152+
struct virtchnl_rss_hfunc *vrh;
1153+
int len = sizeof(*vrh);
1154+
1155+
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
1156+
/* bail because we already have a command pending */
1157+
dev_err(&adapter->pdev->dev, "Cannot set RSS Hash function, command %d pending\n",
1158+
adapter->current_op);
1159+
return;
1160+
}
1161+
vrh = kzalloc(len, GFP_KERNEL);
1162+
if (!vrh)
1163+
return;
1164+
vrh->vsi_id = adapter->vsi.id;
1165+
vrh->rss_algorithm = adapter->hfunc;
1166+
adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_HFUNC;
1167+
adapter->aq_required &= ~IAVF_FLAG_AQ_SET_RSS_HFUNC;
1168+
iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_HFUNC, (u8 *)vrh, len);
1169+
kfree(vrh);
1170+
}
1171+
11441172
/**
11451173
* iavf_enable_vlan_stripping
11461174
* @adapter: adapter structure
@@ -2142,6 +2170,19 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
21422170
dev_warn(&adapter->pdev->dev, "Failed to add VLAN filter, error %s\n",
21432171
iavf_stat_str(&adapter->hw, v_retval));
21442172
break;
2173+
case VIRTCHNL_OP_CONFIG_RSS_HFUNC:
2174+
dev_warn(&adapter->pdev->dev, "Failed to configure hash function, error %s\n",
2175+
iavf_stat_str(&adapter->hw, v_retval));
2176+
2177+
if (adapter->hfunc ==
2178+
VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
2179+
adapter->hfunc =
2180+
VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
2181+
else
2182+
adapter->hfunc =
2183+
VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
2184+
2185+
break;
21452186
default:
21462187
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
21472188
v_retval, iavf_stat_str(&adapter->hw, v_retval),

drivers/net/ethernet/intel/ice/ice_virtchnl.c

+50
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,51 @@ static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg)
999999
NULL, 0);
10001000
}
10011001

1002+
/**
1003+
* ice_vc_config_rss_hfunc
1004+
* @vf: pointer to the VF info
1005+
* @msg: pointer to the msg buffer
1006+
*
1007+
* Configure the VF's RSS Hash function
1008+
*/
1009+
static int ice_vc_config_rss_hfunc(struct ice_vf *vf, u8 *msg)
1010+
{
1011+
struct virtchnl_rss_hfunc *vrh = (struct virtchnl_rss_hfunc *)msg;
1012+
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1013+
u8 hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
1014+
struct ice_vsi *vsi;
1015+
1016+
if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1017+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1018+
goto error_param;
1019+
}
1020+
1021+
if (!ice_vc_isvalid_vsi_id(vf, vrh->vsi_id)) {
1022+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1023+
goto error_param;
1024+
}
1025+
1026+
if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
1027+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1028+
goto error_param;
1029+
}
1030+
1031+
vsi = ice_get_vf_vsi(vf);
1032+
if (!vsi) {
1033+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1034+
goto error_param;
1035+
}
1036+
1037+
if (vrh->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
1038+
hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ;
1039+
1040+
if (ice_set_rss_hfunc(vsi, hfunc))
1041+
v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
1042+
error_param:
1043+
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_HFUNC, v_ret,
1044+
NULL, 0);
1045+
}
1046+
10021047
/**
10031048
* ice_vc_cfg_promiscuous_mode_msg
10041049
* @vf: pointer to the VF info
@@ -3766,6 +3811,7 @@ static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
37663811
.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
37673812
.config_rss_key = ice_vc_config_rss_key,
37683813
.config_rss_lut = ice_vc_config_rss_lut,
3814+
.config_rss_hfunc = ice_vc_config_rss_hfunc,
37693815
.get_stats_msg = ice_vc_get_stats_msg,
37703816
.cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg,
37713817
.add_vlan_msg = ice_vc_add_vlan_msg,
@@ -3895,6 +3941,7 @@ static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {
38953941
.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
38963942
.config_rss_key = ice_vc_config_rss_key,
38973943
.config_rss_lut = ice_vc_config_rss_lut,
3944+
.config_rss_hfunc = ice_vc_config_rss_hfunc,
38983945
.get_stats_msg = ice_vc_get_stats_msg,
38993946
.cfg_promiscuous_mode_msg = ice_vc_repr_cfg_promiscuous_mode,
39003947
.add_vlan_msg = ice_vc_add_vlan_msg,
@@ -4077,6 +4124,9 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
40774124
case VIRTCHNL_OP_CONFIG_RSS_LUT:
40784125
err = ops->config_rss_lut(vf, msg);
40794126
break;
4127+
case VIRTCHNL_OP_CONFIG_RSS_HFUNC:
4128+
err = ops->config_rss_hfunc(vf, msg);
4129+
break;
40804130
case VIRTCHNL_OP_GET_STATS:
40814131
err = ops->get_stats_msg(vf, msg);
40824132
break;

drivers/net/ethernet/intel/ice/ice_virtchnl.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct ice_virtchnl_ops {
3232
int (*cfg_irq_map_msg)(struct ice_vf *vf, u8 *msg);
3333
int (*config_rss_key)(struct ice_vf *vf, u8 *msg);
3434
int (*config_rss_lut)(struct ice_vf *vf, u8 *msg);
35+
int (*config_rss_hfunc)(struct ice_vf *vf, u8 *msg);
3536
int (*get_stats_msg)(struct ice_vf *vf, u8 *msg);
3637
int (*cfg_promiscuous_mode_msg)(struct ice_vf *vf, u8 *msg);
3738
int (*add_vlan_msg)(struct ice_vf *vf, u8 *msg);

drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static const u32 vlan_v2_allowlist_opcodes[] = {
6868
static const u32 rss_pf_allowlist_opcodes[] = {
6969
VIRTCHNL_OP_CONFIG_RSS_KEY, VIRTCHNL_OP_CONFIG_RSS_LUT,
7070
VIRTCHNL_OP_GET_RSS_HENA_CAPS, VIRTCHNL_OP_SET_RSS_HENA,
71+
VIRTCHNL_OP_CONFIG_RSS_HFUNC,
7172
};
7273

7374
/* VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC */

include/linux/avf/virtchnl.h

+19
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ enum virtchnl_ops {
118118
VIRTCHNL_OP_GET_STATS = 15,
119119
VIRTCHNL_OP_RSVD = 16,
120120
VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
121+
VIRTCHNL_OP_CONFIG_RSS_HFUNC = 18,
121122
/* opcode 19 is reserved */
122123
VIRTCHNL_OP_IWARP = 20, /* advanced opcode */
123124
VIRTCHNL_OP_RDMA = VIRTCHNL_OP_IWARP,
@@ -919,6 +920,21 @@ enum virtchnl_rss_algorithm {
919920
VIRTCHNL_RSS_ALG_XOR_SYMMETRIC = 3,
920921
};
921922

923+
/* VIRTCHNL_OP_CONFIG_RSS_HFUNC
924+
* VF sends this message to configure the RSS hash function. Only supported
925+
* if both PF and VF drivers set the VIRTCHNL_VF_OFFLOAD_RSS_PF bit during
926+
* configuration negotiation.
927+
* The hash function is initialized to VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC
928+
* by the PF.
929+
*/
930+
struct virtchnl_rss_hfunc {
931+
u16 vsi_id;
932+
u16 rss_algorithm; /* enum virtchnl_rss_algorithm */
933+
u32 reserved;
934+
};
935+
936+
VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hfunc);
937+
922938
/* VIRTCHNL_OP_ENABLE_CHANNELS
923939
* VIRTCHNL_OP_DISABLE_CHANNELS
924940
* VF sends these messages to enable or disable channels based on
@@ -1542,6 +1558,9 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
15421558
vrl->lut_entries);
15431559
}
15441560
break;
1561+
case VIRTCHNL_OP_CONFIG_RSS_HFUNC:
1562+
valid_len = sizeof(struct virtchnl_rss_hfunc);
1563+
break;
15451564
case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
15461565
break;
15471566
case VIRTCHNL_OP_SET_RSS_HENA:

0 commit comments

Comments
 (0)