@@ -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 */
@@ -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
@@ -1550,6 +1550,17 @@ static u64 iavf_adv_rss_parse_hash_flds(struct ethtool_rxnfc *cmd)
{
u64 hfld = IAVF_ADV_RSS_HASH_INVALID;
+ /* Sanity check: if a symmetric hash is requested, then:
+ * 1 - no other fields besides IP src/dst and/or L4 src/dst
+ * 2 - If src is set, dst must also be set
+ */
+ if ((cmd->data & RXH_SYMMETRIC_XOR) &&
+ ((cmd->data & ~(RXH_SYMMETRIC_XOR | RXH_IP_SRC | RXH_IP_DST |
+ RXH_L4_B_0_1 | RXH_L4_B_2_3)) ||
+ (!!(cmd->data & RXH_IP_SRC) ^ !!(cmd->data & RXH_IP_DST)) ||
+ (!!(cmd->data & RXH_L4_B_0_1) ^ !!(cmd->data & RXH_L4_B_2_3))))
+ return hfld;
+
if (cmd->data & RXH_IP_SRC || cmd->data & RXH_IP_DST) {
switch (cmd->flow_type) {
case TCP_V4_FLOW:
@@ -1618,6 +1629,7 @@ 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;
@@ -1632,11 +1644,15 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
if (hash_flds == IAVF_ADV_RSS_HASH_INVALID)
return -EINVAL;
+ if (cmd->data & RXH_SYMMETRIC_XOR)
+ symm = true;
+
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;
}
@@ -1655,9 +1671,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));
adapter->aq_required |= IAVF_FLAG_AQ_ADD_ADV_RSS_CFG;
@@ -1669,6 +1687,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);
adapter->aq_required |= IAVF_FLAG_AQ_ADD_ADV_RSS_CFG;
}
@@ -1698,6 +1717,7 @@ iavf_get_adv_rss_hash_opt(struct iavf_adapter *adapter,
{
struct iavf_adv_rss *rss;
u64 hash_flds;
+ bool symm;
u32 hdrs;
if (!ADV_RSS_SUPPORT(adapter))
@@ -1711,10 +1731,12 @@ iavf_get_adv_rss_hash_opt(struct iavf_adapter *adapter,
spin_lock_bh(&adapter->adv_rss_lock);
rss = iavf_find_adv_rss_cfg_by_hdrs(adapter, hdrs);
- if (rss)
+ if (rss) {
hash_flds = rss->hash_flds;
- else
+ symm = rss->symm;
+ } else {
hash_flds = IAVF_ADV_RSS_HASH_INVALID;
+ }
spin_unlock_bh(&adapter->adv_rss_lock);
if (hash_flds == IAVF_ADV_RSS_HASH_INVALID)
@@ -1738,6 +1760,9 @@ iavf_get_adv_rss_hash_opt(struct iavf_adapter *adapter,
IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT))
cmd->data |= (u64)RXH_L4_B_2_3;
+ if (symm)
+ cmd->data |= (u64)RXH_SYMMETRIC_XOR;
+
return 0;
}