diff mbox series

[net-next,3/5] sfc: add functions to insert encap matches into the MAE

Message ID cae6e259972a00e4785a6d92f71d43bece0858a8.1678815095.git.ecree.xilinx@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series sfc: support TC decap rules | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 19 this patch: 19
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/build_clang success Errors and warnings before: 18 this patch: 18
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 19 this patch: 19
netdev/checkpatch warning WARNING: line length of 84 exceeds 80 columns WARNING: line length of 85 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns WARNING: line length of 88 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns WARNING: line length of 92 exceeds 80 columns WARNING: line length of 93 exceeds 80 columns WARNING: line length of 94 exceeds 80 columns WARNING: line length of 97 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

edward.cree@amd.com March 14, 2023, 5:35 p.m. UTC
From: Edward Cree <ecree.xilinx@gmail.com>

An encap match corresponds to an entry in the exact-match Outer Rule
 table; the lookup response includes the encap type (protocol) allowing
 the hardware to continue parsing into the inner headers.

Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
---
 drivers/net/ethernet/sfc/mae.c | 105 +++++++++++++++++++++++++++++++++
 drivers/net/ethernet/sfc/mae.h |   5 ++
 drivers/net/ethernet/sfc/tc.h  |   1 +
 3 files changed, 111 insertions(+)

Comments

Michal Swiatkowski March 15, 2023, 9:23 a.m. UTC | #1
On Tue, Mar 14, 2023 at 05:35:23PM +0000, edward.cree@amd.com wrote:
> From: Edward Cree <ecree.xilinx@gmail.com>
> 
> An encap match corresponds to an entry in the exact-match Outer Rule
>  table; the lookup response includes the encap type (protocol) allowing
>  the hardware to continue parsing into the inner headers.
> 
> Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
> ---
>  drivers/net/ethernet/sfc/mae.c | 105 +++++++++++++++++++++++++++++++++
>  drivers/net/ethernet/sfc/mae.h |   5 ++
>  drivers/net/ethernet/sfc/tc.h  |   1 +
>  3 files changed, 111 insertions(+)
> 
> diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
> index 1a285facda34..754391eb575f 100644
> --- a/drivers/net/ethernet/sfc/mae.c
> +++ b/drivers/net/ethernet/sfc/mae.c
> @@ -564,6 +564,20 @@ int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt)
>  	return 0;
>  }
>  
> +static int efx_mae_encap_type_to_mae_type(enum efx_encap_type type)
> +{
> +	switch (type & EFX_ENCAP_TYPES_MASK) {
> +	case EFX_ENCAP_TYPE_NONE:
> +		return MAE_MCDI_ENCAP_TYPE_NONE;
> +	case EFX_ENCAP_TYPE_VXLAN:
> +		return MAE_MCDI_ENCAP_TYPE_VXLAN;
> +	case EFX_ENCAP_TYPE_GENEVE:
> +		return MAE_MCDI_ENCAP_TYPE_GENEVE;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
>  int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id)
>  {
>  	struct ef100_nic_data *nic_data = efx->nic_data;
> @@ -921,6 +935,97 @@ int efx_mae_free_action_set_list(struct efx_nic *efx,
>  	return 0;
>  }
>  
> +int efx_mae_register_encap_match(struct efx_nic *efx,
> +				 struct efx_tc_encap_match *encap)
> +{
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_INSERT_IN_LEN(MAE_ENC_FIELD_PAIRS_LEN));
> +	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN);
> +	MCDI_DECLARE_STRUCT_PTR(match_crit);
> +	size_t outlen;
> +	int rc;
> +
> +	rc = efx_mae_encap_type_to_mae_type(encap->tun_type);
> +	if (rc < 0)
> +		return rc;
> +	match_crit = _MCDI_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA);
> +	/* The struct contains IP src and dst, and udp dport.
> +	 * So we actually need to filter on IP src and dst, L4 dport, and
> +	 * ipproto == udp.
> +	 */
> +	MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, rc);
> +#ifdef CONFIG_IPV6
> +	if (encap->src_ip | encap->dst_ip) {
> +#endif
Looks strange, in case CONFIG_IPV6 isn't defined You can also check if
theres is no zero ip.

> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE,
> +					 encap->src_ip);
> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK,
> +					 ~(__be32)0);
> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE,
> +					 encap->dst_ip);
> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK,
> +					 ~(__be32)0);
> +		MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE,
> +					htons(ETH_P_IP));
> +#ifdef CONFIG_IPV6
> +	} else {
> +		memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE),
> +		       &encap->src_ip6, sizeof(encap->src_ip6));
> +		memset(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK),
> +		       0xff, sizeof(encap->src_ip6));
> +		memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE),
> +		       &encap->dst_ip6, sizeof(encap->dst_ip6));
> +		memset(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK),
> +		       0xff, sizeof(encap->dst_ip6));
> +		MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE,
> +					htons(ETH_P_IPV6));
> +	}
> +#endif
> +	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK,
> +				~(__be16)0);
> +	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE,
> +				encap->udp_dport);
> +	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK,
> +				~(__be16)0);
Question, from tc we can set masks for matching fields. You are setting
default one, because hardware doesn't support different masks?

> +	MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO, IPPROTO_UDP);
> +	MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK, ~0);
> +	rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_INSERT, inbuf,
> +			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
> +	if (rc)
> +		return rc;
> +	if (outlen < sizeof(outbuf))
> +		return -EIO;
> +	encap->fw_id = MCDI_DWORD(outbuf, MAE_OUTER_RULE_INSERT_OUT_OR_ID);
> +	return 0;
> +}
> +
> +int efx_mae_unregister_encap_match(struct efx_nic *efx,
> +				   struct efx_tc_encap_match *encap)
> +{
> +	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1));
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1));
> +	size_t outlen;
> +	int rc;
> +
> +	MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_REMOVE_IN_OR_ID, encap->fw_id);
> +	rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_REMOVE, inbuf,
> +			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
> +	if (rc)
> +		return rc;
> +	if (outlen < sizeof(outbuf))
> +		return -EIO;
> +	/* FW freed a different ID than we asked for, should also never happen.
> +	 * Warn because it means we've now got a different idea to the FW of
> +	 * what encap_mds exist, which could cause mayhem later.
> +	 */
> +	if (WARN_ON(MCDI_DWORD(outbuf, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) != encap->fw_id))
> +		return -EIO;
> +	/* We're probably about to free @encap, but let's just make sure its
> +	 * fw_id is blatted so that it won't look valid if it leaks out.
> +	 */
> +	encap->fw_id = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL;
> +	return 0;
> +}
> +
>  static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit),
>  					   const struct efx_tc_match *match)
>  {
> diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
> index a45d1791517f..5b45138aaaf4 100644
> --- a/drivers/net/ethernet/sfc/mae.h
> +++ b/drivers/net/ethernet/sfc/mae.h
> @@ -94,6 +94,11 @@ int efx_mae_alloc_action_set_list(struct efx_nic *efx,
>  int efx_mae_free_action_set_list(struct efx_nic *efx,
>  				 struct efx_tc_action_set_list *acts);
>  
> +int efx_mae_register_encap_match(struct efx_nic *efx,
> +				 struct efx_tc_encap_match *encap);
> +int efx_mae_unregister_encap_match(struct efx_nic *efx,
> +				   struct efx_tc_encap_match *encap);
> +
>  int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
>  			u32 prio, u32 acts_id, u32 *id);
>  int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
> diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h
> index c1485679507c..19782c9a4354 100644
> --- a/drivers/net/ethernet/sfc/tc.h
> +++ b/drivers/net/ethernet/sfc/tc.h
> @@ -70,6 +70,7 @@ struct efx_tc_encap_match {
>  	__be32 src_ip, dst_ip;
>  	struct in6_addr src_ip6, dst_ip6;
>  	__be16 udp_dport;
> +	u16 tun_type; /* enum efx_encap_type */
>  	u32 fw_id; /* index of this entry in firmware encap match table */
>  };
>
Edward Cree March 15, 2023, 1:58 p.m. UTC | #2
On 15/03/2023 09:23, Michal Swiatkowski wrote:
> On Tue, Mar 14, 2023 at 05:35:23PM +0000, edward.cree@amd.com wrote:
>> +#ifdef CONFIG_IPV6
>> +	if (encap->src_ip | encap->dst_ip) {
>> +#endif
> Looks strange, in case CONFIG_IPV6 isn't defined You can also check if
> theres is no zero ip.

The idea is that #ifdef CONFIG_IPV6 then we use this to decide whether
 this is an IPv4 or IPv6 filter, otherwise we don't need to check
 anything because there's only IPv4.  What would the alternative be,
 put a WARN_ON_ONCE() and return -EINVAL in the else clause #ifndef
 CONFIG_IPV6?  Is that better?
I agree this does look strange.

> 
>> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE,
>> +					 encap->src_ip);
>> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK,
>> +					 ~(__be32)0);
>> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE,
>> +					 encap->dst_ip);
>> +		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK,
>> +					 ~(__be32)0);
>> +		MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE,
>> +					htons(ETH_P_IP));
>> +#ifdef CONFIG_IPV6
>> +	} else {
>> +		memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE),
>> +		       &encap->src_ip6, sizeof(encap->src_ip6));
>> +		memset(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK),
>> +		       0xff, sizeof(encap->src_ip6));
>> +		memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE),
>> +		       &encap->dst_ip6, sizeof(encap->dst_ip6));
>> +		memset(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK),
>> +		       0xff, sizeof(encap->dst_ip6));
>> +		MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE,
>> +					htons(ETH_P_IPV6));
>> +	}
>> +#endif
>> +	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK,
>> +				~(__be16)0);
>> +	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE,
>> +				encap->udp_dport);
>> +	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK,
>> +				~(__be16)0);
> Question, from tc we can set masks for matching fields. You are setting
> default one, because hardware doesn't support different masks?

See my reply on patch #1 about mask sets and overlap.
The hardware supports masks on some fields in the Outer Rule table,
 although not (in the current version) L4 ports.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
index 1a285facda34..754391eb575f 100644
--- a/drivers/net/ethernet/sfc/mae.c
+++ b/drivers/net/ethernet/sfc/mae.c
@@ -564,6 +564,20 @@  int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt)
 	return 0;
 }
 
+static int efx_mae_encap_type_to_mae_type(enum efx_encap_type type)
+{
+	switch (type & EFX_ENCAP_TYPES_MASK) {
+	case EFX_ENCAP_TYPE_NONE:
+		return MAE_MCDI_ENCAP_TYPE_NONE;
+	case EFX_ENCAP_TYPE_VXLAN:
+		return MAE_MCDI_ENCAP_TYPE_VXLAN;
+	case EFX_ENCAP_TYPE_GENEVE:
+		return MAE_MCDI_ENCAP_TYPE_GENEVE;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id)
 {
 	struct ef100_nic_data *nic_data = efx->nic_data;
@@ -921,6 +935,97 @@  int efx_mae_free_action_set_list(struct efx_nic *efx,
 	return 0;
 }
 
+int efx_mae_register_encap_match(struct efx_nic *efx,
+				 struct efx_tc_encap_match *encap)
+{
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_INSERT_IN_LEN(MAE_ENC_FIELD_PAIRS_LEN));
+	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN);
+	MCDI_DECLARE_STRUCT_PTR(match_crit);
+	size_t outlen;
+	int rc;
+
+	rc = efx_mae_encap_type_to_mae_type(encap->tun_type);
+	if (rc < 0)
+		return rc;
+	match_crit = _MCDI_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA);
+	/* The struct contains IP src and dst, and udp dport.
+	 * So we actually need to filter on IP src and dst, L4 dport, and
+	 * ipproto == udp.
+	 */
+	MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, rc);
+#ifdef CONFIG_IPV6
+	if (encap->src_ip | encap->dst_ip) {
+#endif
+		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE,
+					 encap->src_ip);
+		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK,
+					 ~(__be32)0);
+		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE,
+					 encap->dst_ip);
+		MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK,
+					 ~(__be32)0);
+		MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE,
+					htons(ETH_P_IP));
+#ifdef CONFIG_IPV6
+	} else {
+		memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE),
+		       &encap->src_ip6, sizeof(encap->src_ip6));
+		memset(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK),
+		       0xff, sizeof(encap->src_ip6));
+		memcpy(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE),
+		       &encap->dst_ip6, sizeof(encap->dst_ip6));
+		memset(MCDI_STRUCT_PTR(match_crit, MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK),
+		       0xff, sizeof(encap->dst_ip6));
+		MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE,
+					htons(ETH_P_IPV6));
+	}
+#endif
+	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK,
+				~(__be16)0);
+	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE,
+				encap->udp_dport);
+	MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK,
+				~(__be16)0);
+	MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO, IPPROTO_UDP);
+	MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK, ~0);
+	rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_INSERT, inbuf,
+			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		return rc;
+	if (outlen < sizeof(outbuf))
+		return -EIO;
+	encap->fw_id = MCDI_DWORD(outbuf, MAE_OUTER_RULE_INSERT_OUT_OR_ID);
+	return 0;
+}
+
+int efx_mae_unregister_encap_match(struct efx_nic *efx,
+				   struct efx_tc_encap_match *encap)
+{
+	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1));
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1));
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, MAE_OUTER_RULE_REMOVE_IN_OR_ID, encap->fw_id);
+	rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_REMOVE, inbuf,
+			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		return rc;
+	if (outlen < sizeof(outbuf))
+		return -EIO;
+	/* FW freed a different ID than we asked for, should also never happen.
+	 * Warn because it means we've now got a different idea to the FW of
+	 * what encap_mds exist, which could cause mayhem later.
+	 */
+	if (WARN_ON(MCDI_DWORD(outbuf, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) != encap->fw_id))
+		return -EIO;
+	/* We're probably about to free @encap, but let's just make sure its
+	 * fw_id is blatted so that it won't look valid if it leaks out.
+	 */
+	encap->fw_id = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL;
+	return 0;
+}
+
 static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit),
 					   const struct efx_tc_match *match)
 {
diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
index a45d1791517f..5b45138aaaf4 100644
--- a/drivers/net/ethernet/sfc/mae.h
+++ b/drivers/net/ethernet/sfc/mae.h
@@ -94,6 +94,11 @@  int efx_mae_alloc_action_set_list(struct efx_nic *efx,
 int efx_mae_free_action_set_list(struct efx_nic *efx,
 				 struct efx_tc_action_set_list *acts);
 
+int efx_mae_register_encap_match(struct efx_nic *efx,
+				 struct efx_tc_encap_match *encap);
+int efx_mae_unregister_encap_match(struct efx_nic *efx,
+				   struct efx_tc_encap_match *encap);
+
 int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
 			u32 prio, u32 acts_id, u32 *id);
 int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h
index c1485679507c..19782c9a4354 100644
--- a/drivers/net/ethernet/sfc/tc.h
+++ b/drivers/net/ethernet/sfc/tc.h
@@ -70,6 +70,7 @@  struct efx_tc_encap_match {
 	__be32 src_ip, dst_ip;
 	struct in6_addr src_ip6, dst_ip6;
 	__be16 udp_dport;
+	u16 tun_type; /* enum efx_encap_type */
 	u32 fw_id; /* index of this entry in firmware encap match table */
 };