diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index a56521696a..2cfff20f47 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -975,6 +975,8 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_rss_attach;
 
+	sfc_flow_init(sa);
+
 	rc = sfc_flow_rss_attach(sa);
 	if (rc != 0)
 		goto fail_flow_rss_attach;
@@ -1006,8 +1008,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "fini nic");
 	efx_nic_fini(enp);
 
-	sfc_flow_init(sa);
-
 	rc = sfc_sw_xstats_init(sa);
 	if (rc != 0)
 		goto fail_sw_xstats_init;
@@ -1030,7 +1030,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_sw_xstats_close(sa);
 
 fail_sw_xstats_init:
-	sfc_flow_fini(sa);
 	sfc_repr_proxy_detach(sa);
 
 fail_repr_proxy_attach:
@@ -1052,6 +1051,7 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_flow_rss_detach(sa);
 
 fail_flow_rss_attach:
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 
 fail_rss_attach:
@@ -1099,8 +1099,6 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_sriov_vswitch_destroy(sa);
 
-	sfc_flow_fini(sa);
-
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
 	sfc_tbls_detach(sa);
@@ -1108,6 +1106,7 @@ sfc_detach(struct sfc_adapter *sa)
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
 	sfc_flow_rss_detach(sa);
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 	sfc_port_detach(sa);
 	sfc_ev_detach(sa);
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 432295ea62..94696afac0 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -7,6 +7,8 @@
  * for Solarflare) and Solarflare Communications, Inc.
  */
 
+#include <stdbool.h>
+
 #include <rte_byteorder.h>
 #include <rte_tailq.h>
 #include <rte_common.h>
@@ -2405,7 +2407,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2421,7 +2423,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2613,14 +2615,14 @@ sfc_flow_create(struct rte_eth_dev *dev,
 	struct rte_flow *flow;
 
 	sfc_adapter_lock(sa);
-	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	flow = sfc_flow_create_locked(sa, false, attr, pattern, actions, error);
 	sfc_adapter_unlock(sa);
 
 	return flow;
 }
 
 struct rte_flow *
-sfc_flow_create_locked(struct sfc_adapter *sa,
+sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 		       const struct rte_flow_attr *attr,
 		       const struct rte_flow_item pattern[],
 		       const struct rte_flow_action actions[],
@@ -2635,6 +2637,8 @@ sfc_flow_create_locked(struct sfc_adapter *sa,
 	if (flow == NULL)
 		goto fail_no_mem;
 
+	flow->internal = internal;
+
 	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
@@ -2711,10 +2715,14 @@ sfc_flow_flush(struct rte_eth_dev *dev,
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	struct rte_flow *flow;
 	int ret = 0;
+	void *tmp;
 
 	sfc_adapter_lock(sa);
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		if (sa->state == SFC_ETHDEV_STARTED) {
 			int rc;
 
@@ -2842,10 +2850,14 @@ void
 sfc_flow_fini(struct sfc_adapter *sa)
 {
 	struct rte_flow *flow;
+	void *tmp;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		TAILQ_REMOVE(&sa->flow_list, flow, entries);
 		sfc_flow_free(sa, flow);
 	}
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index a3ca09f225..ec5e29f257 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -10,6 +10,8 @@
 #ifndef _SFC_FLOW_H
 #define _SFC_FLOW_H
 
+#include <stdbool.h>
+
 #include <rte_tailq.h>
 #include <rte_flow_driver.h>
 
@@ -101,6 +103,7 @@ struct sfc_flow_spec {
 struct rte_flow {
 	struct sfc_flow_spec spec;	/* flow specification */
 	TAILQ_ENTRY(rte_flow) entries;	/* flow list entries */
+	bool internal;			/* true for internal rules */
 };
 
 TAILQ_HEAD(sfc_flow_list, rte_flow);
@@ -195,7 +198,7 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
-struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 					const struct rte_flow_attr *attr,
 					const struct rte_flow_item pattern[],
 					const struct rte_flow_action actions[],
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index c0b97b1fe1..36eb78d425 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2539,6 +2539,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
+	if (ctx->internal) {
+		/*
+		 * A driver-internal flow may not comprise an outer rule,
+		 * but it must not match on invalid outer rule ID since
+		 * it must catch all missed packets, including those
+		 * that hit an outer rule of another flow entry but
+		 * do not hit a higher-priority action rule later.
+		 * So do not set match on outer rule ID here.
+		 */
+		SFC_ASSERT(ctx->match_spec_outer == NULL);
+		*rulep = NULL;
+		return 0;
+	}
+
 	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
 		*rulep = NULL;
 		goto no_or_id;
@@ -2825,9 +2839,10 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
-			   struct sfc_flow_spec_mae *spec,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2835,6 +2850,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
 	ctx_mae.ft_rule_type = spec->ft_rule_type;
+	ctx_mae.internal = flow->internal;
 	ctx_mae.priority = spec->priority;
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
@@ -3644,11 +3660,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_flow_spec_mae *spec_mae,
+			  const 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;
 	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;
@@ -3772,6 +3789,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 
 		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
 
+		if (flow->internal) {
+			switch_port_type_mask |=
+					1U << SFC_MAE_SWITCH_PORT_REPRESENTOR;
+		}
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
 				action->conf, switch_port_type_mask, spec);
 		break;
@@ -3842,9 +3864,10 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
-			   struct sfc_flow_spec_mae *spec_mae,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
@@ -3901,7 +3924,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,
+		rc = sfc_mae_rule_parse_action(sa, action, flow,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d2995ded88..307236ea11 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -363,6 +363,7 @@ struct sfc_mae_parse_ctx {
 	size_t				tunnel_def_mask_size;
 	const void			*tunnel_def_mask;
 	bool				match_mport_set;
+	bool				internal;
 	enum sfc_ft_rule_type		ft_rule_type;
 	struct sfc_mae_pattern_data	pattern_data;
 	efx_tunnel_protocol_t		encap_type;
@@ -376,11 +377,11 @@ void sfc_mae_detach(struct sfc_adapter *sa);
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
 int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			       const struct rte_flow_item pattern[],
-			       struct sfc_flow_spec_mae *spec,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       const struct rte_flow_action actions[],
-			       struct sfc_flow_spec_mae *spec_mae,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
