Commit 4a3de3fb authored by Ahmed Zaki's avatar Ahmed Zaki Committed by Jakub Kicinski
Browse files

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: default avatarMadhu Chittim <madhu.chittim@intel.com>
Signed-off-by: default avatarAhmed Zaki <ahmed.zaki@intel.com>
Link: https://lore.kernel.org/r/20231213003321.605376-9-ahmed.zaki@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 352e9bf2
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -312,7 +312,8 @@ struct iavf_adapter {
#define IAVF_FLAG_AQ_SET_HENA			BIT_ULL(12)
#define IAVF_FLAG_AQ_SET_RSS_KEY		BIT_ULL(13)
#define IAVF_FLAG_AQ_SET_RSS_LUT		BIT_ULL(14)
#define IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE	BIT_ULL(15)
#define IAVF_FLAG_AQ_SET_RSS_HFUNC		BIT_ULL(15)
#define IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE	BIT_ULL(16)
#define IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING	BIT_ULL(19)
#define IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING	BIT_ULL(20)
#define IAVF_FLAG_AQ_ENABLE_CHANNELS		BIT_ULL(21)
@@ -414,6 +415,7 @@ struct iavf_adapter {
	struct iavf_vsi vsi;
	u32 aq_wait_count;
	/* RSS stuff */
	enum virtchnl_rss_algorithm hfunc;
	u64 hena;
	u16 rss_key_size;
	u16 rss_lut_size;
@@ -539,6 +541,7 @@ void iavf_get_hena(struct iavf_adapter *adapter);
void iavf_set_hena(struct iavf_adapter *adapter);
void iavf_set_rss_key(struct iavf_adapter *adapter);
void iavf_set_rss_lut(struct iavf_adapter *adapter);
void iavf_set_rss_hfunc(struct iavf_adapter *adapter);
void iavf_enable_vlan_stripping(struct iavf_adapter *adapter);
void iavf_disable_vlan_stripping(struct iavf_adapter *adapter);
void iavf_virtchnl_completion(struct iavf_adapter *adapter,
+6 −2
Original line number Diff line number Diff line
@@ -95,16 +95,20 @@ iavf_fill_adv_rss_sctp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
 * @rss_cfg: the virtchnl message to be filled with RSS configuration setting
 * @packet_hdrs: the RSS configuration protocol header types
 * @hash_flds: the RSS configuration protocol hash fields
 * @symm: if true, symmetric hash is required
 *
 * Returns 0 if the RSS configuration virtchnl message is filled successfully
 */
int
iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
			  u32 packet_hdrs, u64 hash_flds)
			  u32 packet_hdrs, u64 hash_flds, bool symm)
{
	struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs;
	struct virtchnl_proto_hdr *hdr;

	if (symm)
		rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
	else
		rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;

	proto_hdrs->tunnel_level = 0;	/* always outer layer */
+2 −1
Original line number Diff line number Diff line
@@ -80,13 +80,14 @@ struct iavf_adv_rss {

	u32 packet_hdrs;
	u64 hash_flds;
	bool symm;

	struct virtchnl_rss_cfg cfg_msg;
};

int
iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
			  u32 packet_hdrs, u64 hash_flds);
			  u32 packet_hdrs, u64 hash_flds, bool symm);
struct iavf_adv_rss *
iavf_find_adv_rss_cfg_by_hdrs(struct iavf_adapter *adapter, u32 packet_hdrs);
void
+28 −4
Original line number Diff line number Diff line
@@ -1529,11 +1529,12 @@ static u32 iavf_adv_rss_parse_hdrs(struct ethtool_rxnfc *cmd)
/**
 * iavf_adv_rss_parse_hash_flds - parses hash fields from RSS hash input
 * @cmd: ethtool rxnfc command
 * @symm: true if Symmetric Topelitz is set
 *
 * This function parses the rxnfc command and returns intended hash fields for
 * RSS configuration
 */
static u64 iavf_adv_rss_parse_hash_flds(struct ethtool_rxnfc *cmd)
static u64 iavf_adv_rss_parse_hash_flds(struct ethtool_rxnfc *cmd, bool symm)
{
	u64 hfld = IAVF_ADV_RSS_HASH_INVALID;

@@ -1605,17 +1606,20 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
	struct iavf_adv_rss *rss_old, *rss_new;
	bool rss_new_add = false;
	int count = 50, err = 0;
	bool symm = false;
	u64 hash_flds;
	u32 hdrs;

	if (!ADV_RSS_SUPPORT(adapter))
		return -EOPNOTSUPP;

	symm = !!(adapter->hfunc == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC);

	hdrs = iavf_adv_rss_parse_hdrs(cmd);
	if (hdrs == IAVF_ADV_RSS_FLOW_SEG_HDR_NONE)
		return -EINVAL;

	hash_flds = iavf_adv_rss_parse_hash_flds(cmd);
	hash_flds = iavf_adv_rss_parse_hash_flds(cmd, symm);
	if (hash_flds == IAVF_ADV_RSS_HASH_INVALID)
		return -EINVAL;

@@ -1623,7 +1627,8 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
	if (!rss_new)
		return -ENOMEM;

	if (iavf_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds)) {
	if (iavf_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds,
				      symm)) {
		kfree(rss_new);
		return -EINVAL;
	}
@@ -1642,9 +1647,11 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
	if (rss_old) {
		if (rss_old->state != IAVF_ADV_RSS_ACTIVE) {
			err = -EBUSY;
		} else if (rss_old->hash_flds != hash_flds) {
		} else if (rss_old->hash_flds != hash_flds ||
			   rss_old->symm != symm) {
			rss_old->state = IAVF_ADV_RSS_ADD_REQUEST;
			rss_old->hash_flds = hash_flds;
			rss_old->symm = symm;
			memcpy(&rss_old->cfg_msg, &rss_new->cfg_msg,
			       sizeof(rss_new->cfg_msg));
		} else {
@@ -1655,6 +1662,7 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
		rss_new->state = IAVF_ADV_RSS_ADD_REQUEST;
		rss_new->packet_hdrs = hdrs;
		rss_new->hash_flds = hash_flds;
		rss_new->symm = symm;
		list_add_tail(&rss_new->list, &adapter->adv_rss_list_head);
	}
	spin_unlock_bh(&adapter->adv_rss_lock);
@@ -1905,6 +1913,9 @@ static int iavf_get_rxfh(struct net_device *netdev,
	u16 i;

	rxfh->hfunc = ETH_RSS_HASH_TOP;
	if (adapter->hfunc == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
		rxfh->input_xfrm |= RXH_XFRM_SYM_XOR;

	if (rxfh->key)
		memcpy(rxfh->key, adapter->rss_key, adapter->rss_key_size);

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

	if ((rxfh->input_xfrm & RXH_XFRM_SYM_XOR) &&
	    adapter->hfunc != VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC) {
		if (!ADV_RSS_SUPPORT(adapter))
			return -EOPNOTSUPP;
		adapter->hfunc = VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
		adapter->aq_required |= IAVF_FLAG_AQ_SET_RSS_HFUNC;
	} else if (!(rxfh->input_xfrm & RXH_XFRM_SYM_XOR) &&
		    adapter->hfunc != VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC) {
		adapter->hfunc = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
		adapter->aq_required |= IAVF_FLAG_AQ_SET_RSS_HFUNC;
	}

	if (!rxfh->key && !rxfh->indir)
		return 0;

@@ -1955,6 +1978,7 @@ static int iavf_set_rxfh(struct net_device *netdev,
static const struct ethtool_ops iavf_ethtool_ops = {
	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
				     ETHTOOL_COALESCE_USE_ADAPTIVE,
	.cap_rss_sym_xor_supported = true,
	.get_drvinfo		= iavf_get_drvinfo,
	.get_link		= ethtool_op_get_link,
	.get_ringparam		= iavf_get_ringparam,
+4 −0
Original line number Diff line number Diff line
@@ -2166,6 +2166,10 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
		iavf_set_rss_lut(adapter);
		return 0;
	}
	if (adapter->aq_required & IAVF_FLAG_AQ_SET_RSS_HFUNC) {
		iavf_set_rss_hfunc(adapter);
		return 0;
	}

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