diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index ff0d094068..b0f19d51b4 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -192,6 +192,10 @@ Supported pattern items (***transfer*** rules):
 
 - PHY_PORT (cannot repeat; conflicts with other traffic source items)
 
+- PF (cannot repeat; conflicts with other traffic source items)
+
+- VF (cannot repeat; conflicts with other traffic source items)
+
 - ETH
 
 Supported actions (***transfer*** rules):
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 1e7a368303..7d1a3b5999 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -276,6 +276,109 @@ sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
 	return 0;
 }
 
+static int
+sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item,
+			   struct sfc_flow_parse_ctx *ctx,
+			   struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
+	efx_mport_sel_t mport_v;
+	int rc;
+
+	if (ctx_mae->match_mport_set) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't handle multiple traffic source items");
+	}
+
+	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
+					    &mport_v);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to convert the PF ID");
+	}
+
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+					  &mport_v, NULL);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to set MPORT for the PF");
+	}
+
+	ctx_mae->match_mport_set = B_TRUE;
+
+	return 0;
+}
+
+static int
+sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item,
+			   struct sfc_flow_parse_ctx *ctx,
+			   struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
+	const struct rte_flow_item_vf supp_mask = {
+		.id = 0xffffffff,
+	};
+	const void *def_mask = &rte_flow_item_vf_mask;
+	const struct rte_flow_item_vf *spec = NULL;
+	const struct rte_flow_item_vf *mask = NULL;
+	efx_mport_sel_t mport_v;
+	int rc;
+
+	if (ctx_mae->match_mport_set) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't handle multiple traffic source items");
+	}
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask, def_mask,
+				 sizeof(struct rte_flow_item_vf), error);
+	if (rc != 0)
+		return rc;
+
+	if (mask->id != supp_mask.id) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Bad mask in the VF pattern item");
+	}
+
+	/*
+	 * If "spec" is not set, the item requests any VF related to the
+	 * PF of the current DPDK port (but not the PF itself).
+	 * Reject this match criterion as unsupported.
+	 */
+	if (spec == NULL) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Bad spec in the VF pattern item");
+	}
+
+	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, spec->id, &mport_v);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to convert the PF + VF IDs");
+	}
+
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+					  &mport_v, NULL);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to set MPORT for the PF + VF");
+	}
+
+	ctx_mae->match_mport_set = B_TRUE;
+
+	return 0;
+}
+
 struct sfc_mae_field_locator {
 	efx_mae_field_id_t		field_id;
 	size_t				size;
@@ -387,6 +490,28 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_phy_port,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_PF,
+		/*
+		 * In terms of RTE flow, this item is a META one,
+		 * and its position in the pattern is don't care.
+		 */
+		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_pf,
+	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_VF,
+		/*
+		 * In terms of RTE flow, this item is a META one,
+		 * and its position in the pattern is don't care.
+		 */
+		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_vf,
+	},
 	{
 		.type = RTE_FLOW_ITEM_TYPE_ETH,
 		.prev_layer = SFC_FLOW_ITEM_START_LAYER,
@@ -407,6 +532,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	int rc;
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
+	ctx_mae.sa = sa;
 
 	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
 				     spec->priority,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d9f0ee3cbc..3c34d08f88 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -57,6 +57,7 @@ struct sfc_adapter;
 struct sfc_flow_spec;
 
 struct sfc_mae_parse_ctx {
+	struct sfc_adapter		*sa;
 	efx_mae_match_spec_t		*match_spec_action;
 	bool				match_mport_set;
 };
