From 7dec902f4fc0cf1162e18030f2598440e311a2d2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 20 Apr 2020 19:27:42 +0300 Subject: [PATCH] net: mscc: ocelot: refine the ocelot_ace_is_problematic_mac_etype function The commit mentioned below was a bit too harsh, and while it restricted the invalid key combinations which are known to not work, such as: tc filter add dev swp0 ingress proto ip \ flower src_ip 192.0.2.1 action drop tc filter add dev swp0 ingress proto all \ flower src_mac 00:11:22:33:44:55 action drop it also restricted some which still should work, such as: tc filter add dev swp0 ingress proto ip \ flower src_ip 192.0.2.1 action drop tc filter add dev swp0 ingress proto 0x22f0 \ flower src_mac 00:11:22:33:44:55 action drop What actually does not match "sanely" is a MAC_ETYPE rule on frames having an EtherType of ARP, IPv4, IPv6, in addition to SNAP and OAM frames (which the ocelot tc-flower implementation does not parse yet, so the function might need to be revisited again in the future). So just make the function recognize the problematic MAC_ETYPE rules by EtherType - thus the VCAP IS2 can be forced to match even on those packets. This patch makes it possible for IP rules to live on a port together with MAC_ETYPE rules that are non-all, non-arp, non-ip and non-ipv6. Fixes: d4d0cb741d7b ("net: mscc: ocelot: deal with problematic MAC_ETYPE VCAP IS2 rules") Reported-by: Allan W. Nielsen Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot_ace.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c index 8a2f7d13ef6d..dfd82a3baab2 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.c +++ b/drivers/net/ethernet/mscc/ocelot_ace.c @@ -739,14 +739,24 @@ static void ocelot_match_all_as_mac_etype(struct ocelot *ocelot, int port, static bool ocelot_ace_is_problematic_mac_etype(struct ocelot_ace_rule *ace) { + u16 proto, mask; + if (ace->type != OCELOT_ACE_TYPE_ETYPE) return false; - if (ether_addr_to_u64(ace->frame.etype.dmac.value) & - ether_addr_to_u64(ace->frame.etype.dmac.mask)) + + proto = ntohs(*(u16 *)ace->frame.etype.etype.value); + mask = ntohs(*(u16 *)ace->frame.etype.etype.mask); + + /* ETH_P_ALL match, so all protocols below are included */ + if (mask == 0) return true; - if (ether_addr_to_u64(ace->frame.etype.smac.value) & - ether_addr_to_u64(ace->frame.etype.smac.mask)) + if (proto == ETH_P_ARP) return true; + if (proto == ETH_P_IP) + return true; + if (proto == ETH_P_IPV6) + return true; + return false; }