Skip to content

Commit

Permalink
iavf: enable symmetric-xor RSS for Toeplitz hash function
Browse files Browse the repository at this point in the history
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 <madhu.chittim@intel.com>
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: NipaLocal <nipa@local>
  • Loading branch information
azaki1 authored and NipaLocal committed Dec 13, 2023
1 parent d524bed commit 9784e07
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 8 deletions.
5 changes: 4 additions & 1 deletion drivers/net/ethernet/intel/iavf/iavf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions drivers/net/ethernet/intel/iavf/iavf_adv_rss.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,21 @@ 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;

rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
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 */

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/intel/iavf/iavf_adv_rss.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 28 additions & 4 deletions drivers/net/ethernet/intel/iavf/iavf_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -1605,25 +1606,29 @@ 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;

rss_new = kzalloc(sizeof(*rss_new), GFP_KERNEL);
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;
}
Expand All @@ -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 {
Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand All @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/iavf/iavf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
41 changes: 41 additions & 0 deletions drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,34 @@ void iavf_set_rss_lut(struct iavf_adapter *adapter)
kfree(vrl);
}

/**
* iavf_set_rss_hfunc
* @adapter: adapter structure
*
* Request the PF to set our RSS Hash function
**/
void iavf_set_rss_hfunc(struct iavf_adapter *adapter)
{
struct virtchnl_rss_hfunc *vrh;
int len = sizeof(*vrh);

if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot set RSS Hash function, command %d pending\n",
adapter->current_op);
return;
}
vrh = kzalloc(len, GFP_KERNEL);
if (!vrh)
return;
vrh->vsi_id = adapter->vsi.id;
vrh->rss_algorithm = adapter->hfunc;
adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_HFUNC;
adapter->aq_required &= ~IAVF_FLAG_AQ_SET_RSS_HFUNC;
iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_HFUNC, (u8 *)vrh, len);
kfree(vrh);
}

/**
* iavf_enable_vlan_stripping
* @adapter: adapter structure
Expand Down Expand Up @@ -2142,6 +2170,19 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
dev_warn(&adapter->pdev->dev, "Failed to add VLAN filter, error %s\n",
iavf_stat_str(&adapter->hw, v_retval));
break;
case VIRTCHNL_OP_CONFIG_RSS_HFUNC:
dev_warn(&adapter->pdev->dev, "Failed to configure hash function, error %s\n",
iavf_stat_str(&adapter->hw, v_retval));

if (adapter->hfunc ==
VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
adapter->hfunc =
VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
else
adapter->hfunc =
VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;

break;
default:
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
v_retval, iavf_stat_str(&adapter->hw, v_retval),
Expand Down
50 changes: 50 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_virtchnl.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,51 @@ static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg)
NULL, 0);
}

/**
* ice_vc_config_rss_hfunc
* @vf: pointer to the VF info
* @msg: pointer to the msg buffer
*
* Configure the VF's RSS Hash function
*/
static int ice_vc_config_rss_hfunc(struct ice_vf *vf, u8 *msg)
{
struct virtchnl_rss_hfunc *vrh = (struct virtchnl_rss_hfunc *)msg;
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
u8 hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
struct ice_vsi *vsi;

if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
goto error_param;
}

if (!ice_vc_isvalid_vsi_id(vf, vrh->vsi_id)) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
goto error_param;
}

if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
goto error_param;
}

vsi = ice_get_vf_vsi(vf);
if (!vsi) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
goto error_param;
}

if (vrh->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ;

if (ice_set_rss_hfunc(vsi, hfunc))
v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
error_param:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_HFUNC, v_ret,
NULL, 0);
}

/**
* ice_vc_cfg_promiscuous_mode_msg
* @vf: pointer to the VF info
Expand Down Expand Up @@ -3766,6 +3811,7 @@ static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
.config_rss_key = ice_vc_config_rss_key,
.config_rss_lut = ice_vc_config_rss_lut,
.config_rss_hfunc = ice_vc_config_rss_hfunc,
.get_stats_msg = ice_vc_get_stats_msg,
.cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg,
.add_vlan_msg = ice_vc_add_vlan_msg,
Expand Down Expand Up @@ -3895,6 +3941,7 @@ static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {
.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
.config_rss_key = ice_vc_config_rss_key,
.config_rss_lut = ice_vc_config_rss_lut,
.config_rss_hfunc = ice_vc_config_rss_hfunc,
.get_stats_msg = ice_vc_get_stats_msg,
.cfg_promiscuous_mode_msg = ice_vc_repr_cfg_promiscuous_mode,
.add_vlan_msg = ice_vc_add_vlan_msg,
Expand Down Expand Up @@ -4077,6 +4124,9 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
case VIRTCHNL_OP_CONFIG_RSS_LUT:
err = ops->config_rss_lut(vf, msg);
break;
case VIRTCHNL_OP_CONFIG_RSS_HFUNC:
err = ops->config_rss_hfunc(vf, msg);
break;
case VIRTCHNL_OP_GET_STATS:
err = ops->get_stats_msg(vf, msg);
break;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice_virtchnl.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct ice_virtchnl_ops {
int (*cfg_irq_map_msg)(struct ice_vf *vf, u8 *msg);
int (*config_rss_key)(struct ice_vf *vf, u8 *msg);
int (*config_rss_lut)(struct ice_vf *vf, u8 *msg);
int (*config_rss_hfunc)(struct ice_vf *vf, u8 *msg);
int (*get_stats_msg)(struct ice_vf *vf, u8 *msg);
int (*cfg_promiscuous_mode_msg)(struct ice_vf *vf, u8 *msg);
int (*add_vlan_msg)(struct ice_vf *vf, u8 *msg);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ static const u32 vlan_v2_allowlist_opcodes[] = {
static const u32 rss_pf_allowlist_opcodes[] = {
VIRTCHNL_OP_CONFIG_RSS_KEY, VIRTCHNL_OP_CONFIG_RSS_LUT,
VIRTCHNL_OP_GET_RSS_HENA_CAPS, VIRTCHNL_OP_SET_RSS_HENA,
VIRTCHNL_OP_CONFIG_RSS_HFUNC,
};

/* VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC */
Expand Down
19 changes: 19 additions & 0 deletions include/linux/avf/virtchnl.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ enum virtchnl_ops {
VIRTCHNL_OP_GET_STATS = 15,
VIRTCHNL_OP_RSVD = 16,
VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
VIRTCHNL_OP_CONFIG_RSS_HFUNC = 18,
/* opcode 19 is reserved */
VIRTCHNL_OP_IWARP = 20, /* advanced opcode */
VIRTCHNL_OP_RDMA = VIRTCHNL_OP_IWARP,
Expand Down Expand Up @@ -919,6 +920,21 @@ enum virtchnl_rss_algorithm {
VIRTCHNL_RSS_ALG_XOR_SYMMETRIC = 3,
};

/* VIRTCHNL_OP_CONFIG_RSS_HFUNC
* VF sends this message to configure the RSS hash function. Only supported
* if both PF and VF drivers set the VIRTCHNL_VF_OFFLOAD_RSS_PF bit during
* configuration negotiation.
* The hash function is initialized to VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC
* by the PF.
*/
struct virtchnl_rss_hfunc {
u16 vsi_id;
u16 rss_algorithm; /* enum virtchnl_rss_algorithm */
u32 reserved;
};

VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hfunc);

/* VIRTCHNL_OP_ENABLE_CHANNELS
* VIRTCHNL_OP_DISABLE_CHANNELS
* VF sends these messages to enable or disable channels based on
Expand Down Expand Up @@ -1542,6 +1558,9 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
vrl->lut_entries);
}
break;
case VIRTCHNL_OP_CONFIG_RSS_HFUNC:
valid_len = sizeof(struct virtchnl_rss_hfunc);
break;
case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
break;
case VIRTCHNL_OP_SET_RSS_HENA:
Expand Down

0 comments on commit 9784e07

Please sign in to comment.