summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/sfc/tc.c
diff options
context:
space:
mode:
authorEdward Cree <ecree.xilinx@gmail.com>2023-05-11 22:47:31 +0300
committerDavid S. Miller <davem@davemloft.net>2023-05-12 12:37:02 +0300
commitb6583d5e9e94adce1be61ec59fef4e129f0bc68a (patch)
tree3490f6caebba6034332044df084c38ce3c132ea1 /drivers/net/ethernet/sfc/tc.c
parent3c9561c0a5b988be3dfd24ea1de2301b95efc640 (diff)
downloadlinux-b6583d5e9e94adce1be61ec59fef4e129f0bc68a.tar.xz
sfc: support TC decap rules matching on enc_src_port
Allow efx_tc_encap_match entries to include a udp_sport and a udp_sport_mask. As with enc_ip_tos, use pseudos to enforce that all encap matches within a given <src_ip,dst_ip,udp_dport> tuple have the same udp_sport_mask. Note that since we use a single layer of pseudos for both fields, two matches that differ in (say) udp_sport value aren't permitted to have different ip_tos_mask, even though this would technically be safe. Current userland TC does not support setting enc_src_port; this patch was tested with an iproute2 patched to support it. Signed-off-by: Edward Cree <ecree.xilinx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sfc/tc.c')
-rw-r--r--drivers/net/ethernet/sfc/tc.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c
index 8e1769d2c4ee..da684b4b7211 100644
--- a/drivers/net/ethernet/sfc/tc.c
+++ b/drivers/net/ethernet/sfc/tc.c
@@ -377,6 +377,7 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
enum efx_encap_type type,
enum efx_tc_em_pseudo_type em_type,
u8 child_ip_tos_mask,
+ __be16 child_udp_sport_mask,
struct netlink_ext_ack *extack)
{
struct efx_tc_encap_match *encap, *old, *pseudo = NULL;
@@ -425,11 +426,7 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
NL_SET_ERR_MSG_MOD(extack, "Egress encap match is not exact on dst UDP port");
return -EOPNOTSUPP;
}
- if (match->mask.enc_sport) {
- NL_SET_ERR_MSG_MOD(extack, "Egress encap match on src UDP port not supported");
- return -EOPNOTSUPP;
- }
- if (match->mask.enc_ip_tos) {
+ if (match->mask.enc_sport || match->mask.enc_ip_tos) {
struct efx_tc_match pmatch = *match;
if (em_type == EFX_TC_EM_PSEUDO_MASK) { /* can't happen */
@@ -438,9 +435,12 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
}
pmatch.value.enc_ip_tos = 0;
pmatch.mask.enc_ip_tos = 0;
+ pmatch.value.enc_sport = 0;
+ pmatch.mask.enc_sport = 0;
rc = efx_tc_flower_record_encap_match(efx, &pmatch, type,
EFX_TC_EM_PSEUDO_MASK,
match->mask.enc_ip_tos,
+ match->mask.enc_sport,
extack);
if (rc)
return rc;
@@ -452,7 +452,8 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
goto fail_pseudo;
}
- rc = efx_mae_check_encap_match_caps(efx, ipv6, match->mask.enc_ip_tos, extack);
+ rc = efx_mae_check_encap_match_caps(efx, ipv6, match->mask.enc_ip_tos,
+ match->mask.enc_sport, extack);
if (rc)
goto fail_pseudo;
@@ -472,6 +473,9 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
encap->ip_tos = match->value.enc_ip_tos;
encap->ip_tos_mask = match->mask.enc_ip_tos;
encap->child_ip_tos_mask = child_ip_tos_mask;
+ encap->udp_sport = match->value.enc_sport;
+ encap->udp_sport_mask = match->mask.enc_sport;
+ encap->child_udp_sport_mask = child_udp_sport_mask;
encap->type = em_type;
encap->pseudo = pseudo;
old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_match_ht,
@@ -493,9 +497,9 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
NL_SET_ERR_MSG_MOD(extack, "Pseudo encap match conflicts with existing direct entry");
return -EEXIST;
case EFX_TC_EM_PSEUDO_MASK:
- /* old EM is protecting a ToS-qualified filter, so may
- * only be shared with another pseudo for the same
- * ToS mask.
+ /* old EM is protecting a ToS- or src port-qualified
+ * filter, so may only be shared with another pseudo
+ * for the same ToS and src port masks.
*/
if (em_type != EFX_TC_EM_PSEUDO_MASK) {
NL_SET_ERR_MSG_FMT_MOD(extack,
@@ -510,6 +514,13 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
old->child_ip_tos_mask);
return -EEXIST;
}
+ if (child_udp_sport_mask != old->child_udp_sport_mask) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "Pseudo encap match for UDP src port mask %#x conflicts with existing pseudo(MASK) entry for mask %#x",
+ child_udp_sport_mask,
+ old->child_udp_sport_mask);
+ return -EEXIST;
+ }
break;
default: /* Unrecognised pseudo-type. Just say no */
NL_SET_ERR_MSG_FMT_MOD(extack,
@@ -704,7 +715,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
}
rc = efx_tc_flower_record_encap_match(efx, &match, type,
- EFX_TC_EM_DIRECT, 0,
+ EFX_TC_EM_DIRECT, 0, 0,
extack);
if (rc)
goto release;