[v4,27/34] net/sfc: add support for IPv4 NAT offload to MAE backend

Message ID 20230607130245.8048-28-ivan.malov@arknetworks.am (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series net/sfc: support HW conntrack assistance |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Ivan Malov June 7, 2023, 1:02 p.m. UTC
  For this offload to work, the innermost pattern items must
provide the full set of exact match criteria, which are as
follows: EtherType, IP DST, IP SRC, TP protocol ID, TP DST
and TP SRC, where the protocol types can be autodetected.

The offload requires that the IPv4 and the TP actions be
requested simultaneously in the same flow by the caller:
SET_IPV4_DST + SET_TP_DST or SET_IPV4_SRC + SET_TP_SRC.

The offload operates on the outermost frame, which,
if action VXLAN_DECAP was requested, maps to the
inner frame of the original packet. The caller
is responsible to request this offload only
when the target header is an IPv4-based one.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/features/sfc.ini       |  4 ++
 doc/guides/nics/sfc_efx.rst            |  8 +++
 doc/guides/rel_notes/release_23_07.rst | 15 +++++
 drivers/net/sfc/sfc_mae.c              | 77 +++++++++++++++++++++++---
 4 files changed, 96 insertions(+), 8 deletions(-)
  

Comments

Ferruh Yigit June 21, 2023, 4:50 p.m. UTC | #1
On 6/7/2023 2:02 PM, Ivan Malov wrote:
> For this offload to work, the innermost pattern items must
> provide the full set of exact match criteria, which are as
> follows: EtherType, IP DST, IP SRC, TP protocol ID, TP DST
> and TP SRC, where the protocol types can be autodetected.
> 
> The offload requires that the IPv4 and the TP actions be
> requested simultaneously in the same flow by the caller:
> SET_IPV4_DST + SET_TP_DST or SET_IPV4_SRC + SET_TP_SRC.
> 
> The offload operates on the outermost frame, which,
> if action VXLAN_DECAP was requested, maps to the
> inner frame of the original packet. The caller
> is responsible to request this offload only
> when the target header is an IPv4-based one.
> 
> Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

<...>

> --- a/doc/guides/rel_notes/release_23_07.rst
> +++ b/doc/guides/rel_notes/release_23_07.rst
> @@ -55,6 +55,21 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>  
> +* **Updated Solarflare network PMD.**
> +
> +  Updated the Solarflare ``sfc_efx`` driver with changes including:
> +
> +  * Added partial support for transfer flow actions SET_IPV4_DST,
> +    SET_TP_DST, SET_IPV4_SRC and SET_TP_SRC on SN1000 SmartNICs.
> +    It is required that the innermost pattern items provide the
> +    full set of exact match criteria: EtherType, IP DST, IP SRC,
> +    TP protocol ID, TP DST and TP SRC. The IPv4 and TP actions
> +    must be requested simultaneously in the same flow. These
> +    actions operate on the outermost frame, at the point
> +    where action VXLAN_DECAP (if any) has done its job.
> +    The caller is responsible to request this offload
> +    only when the target header is an IPv4-based one.
> +

Reordered update, moved it under existing Solarflare update and
simplified note as more suitable for release notes.
  

Patch

diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini
index f5ac644278..19d4935ce6 100644
--- a/doc/guides/nics/features/sfc.ini
+++ b/doc/guides/nics/features/sfc.ini
@@ -75,8 +75,12 @@  port_representor     = Y
 represented_port     = Y
 queue                = Y
 rss                  = Y
+set_ipv4_dst         = Y
+set_ipv4_src         = Y
 set_mac_dst          = Y
 set_mac_src          = Y
+set_tp_dst           = Y
+set_tp_src           = Y
 vf                   = Y
 vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index de0656876b..6e974c3720 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -270,10 +270,18 @@  Supported actions (***transfer*** rules):
 
 - OF_VLAN_SET_PCP
 
+- SET_IPV4_DST
+
+- SET_IPV4_SRC
+
 - SET_MAC_DST
 
 - SET_MAC_SRC
 
+- SET_TP_DST
+
+- SET_TP_SRC
+
 - OF_DEC_NW_TTL
 
 - DEC_TTL
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index a9b1293689..6fae4eb0a7 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -55,6 +55,21 @@  New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Updated Solarflare network PMD.**
+
+  Updated the Solarflare ``sfc_efx`` driver with changes including:
+
+  * Added partial support for transfer flow actions SET_IPV4_DST,
+    SET_TP_DST, SET_IPV4_SRC and SET_TP_SRC on SN1000 SmartNICs.
+    It is required that the innermost pattern items provide the
+    full set of exact match criteria: EtherType, IP DST, IP SRC,
+    TP protocol ID, TP DST and TP SRC. The IPv4 and TP actions
+    must be requested simultaneously in the same flow. These
+    actions operate on the outermost frame, at the point
+    where action VXLAN_DECAP (if any) has done its job.
+    The caller is responsible to request this offload
+    only when the target header is an IPv4-based one.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index d3b4099213..c58a2520da 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -9,6 +9,7 @@ 
 
 #include <stdbool.h>
 
+#include <rte_byteorder.h>
 #include <rte_bitops.h>
 #include <rte_common.h>
 #include <rte_vxlan.h>
@@ -3444,6 +3445,8 @@  sfc_mae_rule_parse_action_set_mac(struct sfc_adapter *sa,
 enum sfc_mae_actions_bundle_type {
 	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
 	SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_DST,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_SRC,
 };
 
 struct sfc_mae_actions_bundle {
@@ -3464,7 +3467,8 @@  struct sfc_mae_actions_bundle {
  */
 static int
 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
-			      efx_mae_actions_t *spec)
+			      struct sfc_flow_spec_mae *flow_spec,
+			      bool ct, efx_mae_actions_t *spec)
 {
 	int rc = 0;
 
@@ -3475,6 +3479,16 @@  sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 		rc = efx_mae_action_set_populate_vlan_push(
 			spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
 		break;
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_DST:
+		flow_spec->ct_resp.nat.dir_is_dst = true;
+		/* FALLTHROUGH */
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_SRC:
+		if (ct && flow_spec->ct_resp.nat.ip_le != 0 &&
+		    flow_spec->ct_resp.nat.port_le != 0)
+			rc = efx_mae_action_set_populate_nat(spec);
+		else
+			rc = EINVAL;
+		break;
 	default:
 		SFC_ASSERT(B_FALSE);
 		break;
@@ -3491,7 +3505,8 @@  sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 static int
 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			    struct sfc_mae_actions_bundle *bundle,
-			    efx_mae_actions_t *spec,
+			    struct sfc_flow_spec_mae *flow_spec,
+			    efx_mae_actions_t *spec, bool ct,
 			    struct rte_flow_error *error)
 {
 	enum sfc_mae_actions_bundle_type bundle_type_new;
@@ -3503,6 +3518,14 @@  sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
 		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_DST;
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_SRC;
+		break;
 	default:
 		/*
 		 * Self-sufficient actions, including END, are handled in this
@@ -3515,7 +3538,7 @@  sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 
 	if (bundle_type_new != bundle->type ||
 	    (bundle->actions_mask & (1ULL << action->type)) != 0) {
-		rc = sfc_mae_actions_bundle_submit(bundle, spec);
+		rc = sfc_mae_actions_bundle_submit(bundle, flow_spec, ct, spec);
 		if (rc != 0)
 			goto fail_submit;
 
@@ -3532,6 +3555,20 @@  sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			"Failed to request the (group of) action(s)");
 }
 
+static void
+sfc_mae_rule_parse_action_nat_addr(const struct rte_flow_action_set_ipv4 *conf,
+				   uint32_t *nat_addr_le)
+{
+	*nat_addr_le = rte_bswap32(conf->ipv4_addr);
+}
+
+static void
+sfc_mae_rule_parse_action_nat_port(const struct rte_flow_action_set_tp *conf,
+				   uint16_t *nat_port_le)
+{
+	*nat_port_le = rte_bswap16(conf->port);
+}
+
 static void
 sfc_mae_rule_parse_action_of_push_vlan(
 			    const struct rte_flow_action_of_push_vlan *conf,
@@ -4056,6 +4093,10 @@  static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_SET_MAC_SRC] = "SET_MAC_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL] = "OF_DEC_NW_TTL",
 	[RTE_FLOW_ACTION_TYPE_DEC_TTL] = "DEC_TTL",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_DST] = "SET_IPV4_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC] = "SET_IPV4_SRC",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_DST] = "SET_TP_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_SRC] = "SET_TP_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = "OF_SET_VLAN_VID",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
@@ -4075,12 +4116,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 rte_flow *flow,
+			  struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
-	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4127,6 +4168,24 @@  sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_decr_ip_ttl(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_addr(action->conf,
+					&spec_mae->ct_resp.nat.ip_le);
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_port(action->conf,
+						&spec_mae->ct_resp.nat.port_le);
+		break;
 	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
 				       bundle->actions_mask);
@@ -4285,6 +4344,7 @@  sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
+	bool ct = (action_rule_ctx->ct_mark != 0);
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
 	struct sfc_mae *mae = &sa->mae;
@@ -4335,8 +4395,8 @@  sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_actions_bundle_sync(action, &bundle,
-						 ctx.spec, error);
+		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+						 ctx.spec, ct, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
@@ -4346,7 +4406,8 @@  sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			goto fail_rule_parse_action;
 	}
 
-	rc = sfc_mae_actions_bundle_sync(action, &bundle, ctx.spec, error);
+	rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+					 ctx.spec, ct, error);
 	if (rc != 0)
 		goto fail_rule_parse_action;