diff mbox series

[08/10] net/sfc: use action rules in tunnel offload JUMP rules

Message ID 20210929205730.775-9-ivan.malov@oktetlabs.ru (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers show
Series net/sfc: add support for tunnel offload | expand

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Ivan Malov Sept. 29, 2021, 8:57 p.m. UTC
By design, JUMP flows should be represented solely by the outer rules. But
the HW/FW hasn't got support for setting Rx mark from RECIRC_ID on outer
rule lookup yet. Neither does it support outer rule counters. As a
workaround, an action rule of lower priority is used to do the job.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 drivers/net/sfc/sfc_flow.c | 11 +++++---
 drivers/net/sfc/sfc_mae.c  | 55 ++++++++++++++++++++++++++++++++------
 2 files changed, 54 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index c3e75bae84..b0dd7d7b6c 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2561,17 +2561,20 @@  sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
 		/*
-		 * This flow is represented solely by the outer rule.
-		 * It is supposed to mark and count matching packets.
+		 * By design, this flow should be represented solely by the
+		 * outer rule. But the HW/FW hasn't got support for setting
+		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
+		 * does it support outer rule counters. As a workaround, an
+		 * action rule of lower priority is used to do the job.
+		 *
+		 * So don't skip sfc_mae_rule_parse_actions() below.
 		 */
-		goto skip_action_rule;
 	}
 
 	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
 	if (rc != 0)
 		goto fail;
 
-skip_action_rule:
 	if (spec_mae->ft != NULL) {
 		if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP)
 			spec_mae->ft->jump_rule_is_set = B_TRUE;
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 374ef29d71..faf3be522d 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2467,6 +2467,7 @@  sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   struct rte_flow_error *error)
 {
 	struct sfc_mae_parse_ctx ctx_mae;
+	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
 	int rc;
 
@@ -2478,13 +2479,32 @@  sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 	switch (ctx_mae.ft_rule_type) {
 	case SFC_FT_RULE_JUMP:
-		/* No action rule */
-		break;
+		/*
+		 * By design, this flow should be represented solely by the
+		 * outer rule. But the HW/FW hasn't got support for setting
+		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
+		 * does it support outer rule counters. As a workaround, an
+		 * action rule of lower priority is used to do the job.
+		 */
+		priority_shift = 1;
+
+		/* FALLTHROUGH */
 	case SFC_FT_RULE_GROUP:
+		if (ctx_mae.priority != 0) {
+			/*
+			 * Because of the above workaround, deny the
+			 * use of priorities to JUMP and GROUP rules.
+			 */
+			rc = rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
+				"tunnel offload: priorities are not supported");
+			goto fail_priority_check;
+		}
+
 		/* FALLTHROUGH */
 	case SFC_FT_RULE_NONE:
 		rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
-					     spec->priority,
+					     spec->priority + priority_shift,
 					     &ctx_mae.match_spec_action);
 		if (rc != 0) {
 			rc = rte_flow_error_set(error, rc,
@@ -2559,6 +2579,7 @@  sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
 
 fail_init_match_spec_action:
+fail_priority_check:
 	return rc;
 }
 
@@ -3008,11 +3029,14 @@  sfc_mae_rule_parse_action_vxlan_encap(
 static int
 sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 			       const struct rte_flow_action_mark *conf,
+			       const struct sfc_flow_spec_mae *spec_mae,
 			       efx_mae_actions_t *spec)
 {
 	int rc;
 
-	if (conf->id > SFC_FT_USER_MARK_MASK) {
+	if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
+		/* Workaround. See sfc_flow_parse_rte_to_mae() */
+	} else if (conf->id > SFC_FT_USER_MARK_MASK) {
 		sfc_err(sa, "the mark value is too large");
 		return EINVAL;
 	}
@@ -3182,11 +3206,12 @@  static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct sfc_mae_outer_rule *outer_rule,
+			  const struct sfc_flow_spec_mae *spec_mae,
 			  struct sfc_mae_actions_bundle *bundle,
 			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
 {
+	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_meta = sa->negotiated_rx_meta;
 	bool custom_error = B_FALSE;
 	int rc = 0;
@@ -3250,9 +3275,10 @@  sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_MARK:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
 				       bundle->actions_mask);
-		if ((rx_meta & RTE_ETH_RX_META_USER_MARK) != 0) {
+		if ((rx_meta & RTE_ETH_RX_META_USER_MARK) != 0 ||
+		    spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
 			rc = sfc_mae_rule_parse_action_mark(sa, action->conf,
-							    spec);
+							    spec_mae, spec);
 		} else {
 			rc = rte_flow_error_set(error, ENOTSUP,
 						RTE_FLOW_ERROR_TYPE_ACTION,
@@ -3286,6 +3312,12 @@  sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_drop(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_JUMP:
+		if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
+			/* Workaround. See sfc_flow_parse_rte_to_mae() */
+			break;
+		}
+		/* FALLTHROUGH */
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
 				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -3375,7 +3407,7 @@  sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, spec_mae->outer_rule,
+		rc = sfc_mae_rule_parse_action(sa, action, spec_mae,
 					       &bundle, spec, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
@@ -3399,6 +3431,12 @@  sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	switch (spec_mae->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
+	case SFC_FT_RULE_JUMP:
+		/* Workaround. See sfc_flow_parse_rte_to_mae() */
+		rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
+		if (rc != 0)
+			goto fail_workaround_jump_delivery;
+		break;
 	case SFC_FT_RULE_GROUP:
 		/*
 		 * Packets that go to the rule's AR have FT mark set (from the
@@ -3428,6 +3466,7 @@  sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	return 0;
 
 fail_action_set_add:
+fail_workaround_jump_delivery:
 fail_nb_count:
 	sfc_mae_encap_header_del(sa, encap_header);