diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 771fe5a17..8e13075b0 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4103,6 +4103,10 @@ efx_mae_match_spec_fini(
 	__in				efx_mae_match_spec_t *spec);
 
 typedef enum efx_mae_field_id_e {
+	/*
+	 * Fields which can be set by efx_mae_match_spec_field_set()
+	 * or by using dedicated field-specific helper APIs.
+	 */
 	EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR = 0,
 	EFX_MAE_FIELD_ETHER_TYPE_BE,
 	EFX_MAE_FIELD_ETH_SADDR_BE,
@@ -4140,6 +4144,12 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_ENC_VNET_ID_BE,
 	EFX_MAE_FIELD_OUTER_RULE_ID,
 
+	/* Single bits which can be set by efx_mae_match_spec_bit_set(). */
+	EFX_MAE_FIELD_HAS_OVLAN,
+	EFX_MAE_FIELD_HAS_IVLAN,
+	EFX_MAE_FIELD_ENC_HAS_OVLAN,
+	EFX_MAE_FIELD_ENC_HAS_IVLAN,
+
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
 
@@ -4198,6 +4208,14 @@ efx_mae_match_spec_field_set(
 	__in				size_t mask_size,
 	__in_bcount(mask_size)		const uint8_t *mask);
 
+/* The corresponding mask will be set to B_TRUE. */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_bit_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				boolean_t value);
+
 /* If the mask argument is NULL, the API will use full mask by default. */
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 4a513171a..8b63cfb37 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1720,7 +1720,8 @@ struct efx_mae_match_spec_s {
 	efx_mae_rule_type_t		emms_type;
 	uint32_t			emms_prio;
 	union emms_mask_value_pairs {
-		uint8_t			action[MAE_FIELD_MASK_VALUE_PAIRS_LEN];
+		uint8_t			action[
+					    MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN];
 		uint8_t			outer[MAE_ENC_FIELD_PAIRS_LEN];
 	} emms_mask_value_pairs;
 };
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index c1784211e..569748804 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -465,6 +465,10 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT,
 	EFX_MAE_FIELD_ID_ENC_VNET_ID_BE = MAE_FIELD_ENC_VNET_ID,
 	EFX_MAE_FIELD_ID_OUTER_RULE_ID = MAE_FIELD_OUTER_RULE_ID,
+	EFX_MAE_FIELD_ID_HAS_OVLAN = MAE_FIELD_HAS_OVLAN,
+	EFX_MAE_FIELD_ID_HAS_IVLAN = MAE_FIELD_HAS_IVLAN,
+	EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
+	EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -591,6 +595,65 @@ static const efx_mae_mv_desc_t __efx_mae_outer_rule_mv_desc_set[] = {
 
 #undef EFX_MAE_MV_DESC_ALT
 #undef EFX_MAE_MV_DESC
+};
+
+/*
+ * The following structure is a means to describe an MAE bit.
+ * The information in it is meant to be used internally by
+ * APIs for addressing a given flag in a mask-value pairs
+ * structure and for validation purposes.
+ */
+typedef struct efx_mae_mv_bit_desc_s {
+	/*
+	 * Arrays using this struct are indexed by field IDs.
+	 * Fields which aren't meant to be referenced by these
+	 * arrays comprise gaps (invalid entries). Below field
+	 * helps to identify such entries.
+	 */
+	boolean_t			emmbd_entry_is_valid;
+	efx_mae_field_cap_id_t		emmbd_bit_cap_id;
+	size_t				emmbd_value_ofst;
+	unsigned int			emmbd_value_lbn;
+	size_t				emmbd_mask_ofst;
+	unsigned int			emmbd_mask_lbn;
+} efx_mae_mv_bit_desc_t;
+
+static const efx_mae_mv_bit_desc_t __efx_mae_outer_rule_mv_bit_desc_set[] = {
+#define	EFX_MAE_MV_BIT_DESC(_name)					\
+	[EFX_MAE_FIELD_##_name] =					\
+	{								\
+		B_TRUE,							\
+		EFX_MAE_FIELD_ID_##_name,				\
+		MAE_ENC_FIELD_PAIRS_##_name##_OFST,			\
+		MAE_ENC_FIELD_PAIRS_##_name##_LBN,			\
+		MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST,		\
+		MAE_ENC_FIELD_PAIRS_##_name##_MASK_LBN,			\
+	}
+
+	EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
+	EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
+
+#undef EFX_MAE_MV_BIT_DESC
+};
+
+static const efx_mae_mv_bit_desc_t __efx_mae_action_rule_mv_bit_desc_set[] = {
+#define	EFX_MAE_MV_BIT_DESC(_name)					\
+	[EFX_MAE_FIELD_##_name] =					\
+	{								\
+		B_TRUE,							\
+		EFX_MAE_FIELD_ID_##_name,				\
+		MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_OFST,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_OFST,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN,		\
+	}
+
+	EFX_MAE_MV_BIT_DESC(HAS_OVLAN),
+	EFX_MAE_MV_BIT_DESC(HAS_IVLAN),
+	EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
+	EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
+
+#undef EFX_MAE_MV_BIT_DESC
 };
 
 	__checkReturn			efx_rc_t
@@ -789,6 +852,70 @@ efx_mae_match_spec_field_set(
 	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_bit_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				boolean_t value)
+{
+	const efx_mae_mv_bit_desc_t *bit_descp;
+	unsigned int bit_desc_set_nentries;
+	unsigned int byte_idx;
+	unsigned int bit_idx;
+	uint8_t *mvp;
+	efx_rc_t rc;
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		bit_desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
+		bit_descp = &__efx_mae_outer_rule_mv_bit_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.outer;
+		break;
+	case EFX_MAE_RULE_ACTION:
+		bit_desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
+		bit_descp = &__efx_mae_action_rule_mv_bit_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((unsigned int)field_id >= bit_desc_set_nentries) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (bit_descp->emmbd_entry_is_valid == B_FALSE) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	byte_idx = bit_descp->emmbd_value_ofst + bit_descp->emmbd_value_lbn / 8;
+	bit_idx = bit_descp->emmbd_value_lbn % 8;
+
+	if (value != B_FALSE)
+		mvp[byte_idx] |= (1U << bit_idx);
+	else
+		mvp[byte_idx] &= ~(1U << bit_idx);
+
+	byte_idx = bit_descp->emmbd_mask_ofst + bit_descp->emmbd_mask_lbn / 8;
+	bit_idx = bit_descp->emmbd_mask_lbn % 8;
+	mvp[byte_idx] |= (1U << bit_idx);
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
@@ -905,6 +1032,8 @@ efx_mae_match_spec_is_valid(
 	const efx_mae_field_cap_t *field_caps;
 	const efx_mae_mv_desc_t *desc_setp;
 	unsigned int desc_set_nentries;
+	const efx_mae_mv_bit_desc_t *bit_desc_setp;
+	unsigned int bit_desc_set_nentries;
 	boolean_t is_valid = B_TRUE;
 	efx_mae_field_id_t field_id;
 	const uint8_t *mvp;
@@ -915,6 +1044,9 @@ efx_mae_match_spec_is_valid(
 		desc_setp = __efx_mae_outer_rule_mv_desc_set;
 		desc_set_nentries =
 		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
+		bit_desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
 		mvp = spec->emms_mask_value_pairs.outer;
 		break;
 	case EFX_MAE_RULE_ACTION:
@@ -922,6 +1054,9 @@ efx_mae_match_spec_is_valid(
 		desc_setp = __efx_mae_action_rule_mv_desc_set;
 		desc_set_nentries =
 		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
+		bit_desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
 		mvp = spec->emms_mask_value_pairs.action;
 		break;
 	default:
@@ -989,6 +1124,48 @@ efx_mae_match_spec_is_valid(
 			break;
 		}
 
+		if (is_valid == B_FALSE)
+			return (B_FALSE);
+	}
+
+	for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
+	     ++field_id) {
+		const efx_mae_mv_bit_desc_t *bit_descp =
+		    &bit_desc_setp[field_id];
+		unsigned int byte_idx =
+		    bit_descp->emmbd_mask_ofst +
+		    bit_descp->emmbd_mask_lbn / 8;
+		unsigned int bit_idx =
+		    bit_descp->emmbd_mask_lbn % 8;
+		efx_mae_field_cap_id_t bit_cap_id =
+		    bit_descp->emmbd_bit_cap_id;
+
+		if (bit_descp->emmbd_entry_is_valid == B_FALSE)
+			continue; /* Skip array gap */
+
+		if ((unsigned int)bit_cap_id >= field_ncaps) {
+			/* No capability for this bit = unsupported. */
+			is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
+			if (is_valid == B_FALSE)
+				break;
+			else
+				continue;
+		}
+
+		switch (field_caps[bit_cap_id].emfc_support) {
+		case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
+			is_valid = B_TRUE;
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
+			is_valid = ((mvp[byte_idx] & (1U << bit_idx)) != 0);
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_NEVER:
+		case MAE_FIELD_UNSUPPORTED:
+		default:
+			is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
+			break;
+		}
+
 		if (is_valid == B_FALSE)
 			break;
 	}
@@ -1542,6 +1719,8 @@ efx_mae_match_specs_class_cmp(
 	const efx_mae_field_cap_t *field_caps;
 	const efx_mae_mv_desc_t *desc_setp;
 	unsigned int desc_set_nentries;
+	const efx_mae_mv_bit_desc_t *bit_desc_setp;
+	unsigned int bit_desc_set_nentries;
 	boolean_t have_same_class = B_TRUE;
 	efx_mae_field_id_t field_id;
 	const uint8_t *mvpl;
@@ -1554,6 +1733,9 @@ efx_mae_match_specs_class_cmp(
 		desc_setp = __efx_mae_outer_rule_mv_desc_set;
 		desc_set_nentries =
 		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
+		bit_desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
 		mvpl = left->emms_mask_value_pairs.outer;
 		mvpr = right->emms_mask_value_pairs.outer;
 		break;
@@ -1562,6 +1744,9 @@ efx_mae_match_specs_class_cmp(
 		desc_setp = __efx_mae_action_rule_mv_desc_set;
 		desc_set_nentries =
 		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
+		bit_desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
 		mvpl = left->emms_mask_value_pairs.action;
 		mvpr = right->emms_mask_value_pairs.action;
 		break;
@@ -1634,6 +1819,52 @@ efx_mae_match_specs_class_cmp(
 		}
 	}
 
+	if (have_same_class == B_FALSE)
+		goto done;
+
+	for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
+	     ++field_id) {
+		const efx_mae_mv_bit_desc_t *bit_descp =
+		    &bit_desc_setp[field_id];
+		efx_mae_field_cap_id_t bit_cap_id =
+		    bit_descp->emmbd_bit_cap_id;
+		unsigned int byte_idx;
+		unsigned int bit_idx;
+
+		if (bit_descp->emmbd_entry_is_valid == B_FALSE)
+			continue; /* Skip array gap */
+
+		if ((unsigned int)bit_cap_id >= field_ncaps)
+			break;
+
+		byte_idx =
+		    bit_descp->emmbd_mask_ofst +
+		    bit_descp->emmbd_mask_lbn / 8;
+		bit_idx =
+		    bit_descp->emmbd_mask_lbn % 8;
+
+		if (field_caps[bit_cap_id].emfc_mask_affects_class &&
+		    (mvpl[byte_idx] & (1U << bit_idx)) !=
+		    (mvpr[byte_idx] & (1U << bit_idx))) {
+			have_same_class = B_FALSE;
+			break;
+		}
+
+		byte_idx =
+		    bit_descp->emmbd_value_ofst +
+		    bit_descp->emmbd_value_lbn / 8;
+		bit_idx =
+		    bit_descp->emmbd_value_lbn % 8;
+
+		if (field_caps[bit_cap_id].emfc_match_affects_class &&
+		    (mvpl[byte_idx] & (1U << bit_idx)) !=
+		    (mvpr[byte_idx] & (1U << bit_idx))) {
+			have_same_class = B_FALSE;
+			break;
+		}
+	}
+
+done:
 	*have_same_classp = have_same_class;
 
 	return (0);
@@ -2282,10 +2513,10 @@ efx_mae_action_rule_insert(
 	 * MCDI request and are thus safe to be copied directly to the buffer.
 	 */
 	EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >=
-	    MAE_FIELD_MASK_VALUE_PAIRS_LEN);
+	    MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
 	offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST;
 	memcpy(payload + offset, spec->emms_mask_value_pairs.action,
-	    MAE_FIELD_MASK_VALUE_PAIRS_LEN);
+	    MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
 
 	efx_mcdi_execute(enp, &req);
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 5e724fd10..75da5aa5c 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -106,6 +106,7 @@ INTERNAL {
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
+	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
