Commit a3b6e8fd authored by David S. Miller's avatar David S. Miller

Merge branch 'Ocelot-MAC_ETYPE-tc-flower-key-improvements'

Vladimir Oltean says:

====================
Ocelot MAC_ETYPE tc-flower key improvements

As discussed in the comments surrounding this patch:
https://patchwork.ozlabs.org/project/netdev/patch/20200417190308.32598-1-olteanv@gmail.com/

the restrictions imposed on non-MAC_ETYPE rules were harsher than they
needed to be. IP, IPv6, ARP rules can still be added concurrently with
src_mac and dst_mac rules, as long as those MAC address rules do not ask
for an offending EtherType.

For that to actually be supported, we need to parse the EtherType from
the flower classification rule first.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 44dd5efc 4faa2e06
......@@ -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;
}
......
......@@ -51,6 +51,8 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
{
struct flow_rule *rule = flow_cls_offload_flow_rule(f);
struct flow_dissector *dissector = rule->match.dissector;
u16 proto = ntohs(f->common.protocol);
bool match_protocol = true;
if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
......@@ -71,7 +73,6 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
struct flow_match_eth_addrs match;
u16 proto = ntohs(f->common.protocol);
/* The hw support mac matches only for MAC_ETYPE key,
* therefore if other matches(port, tcp flags, etc) are added
......@@ -86,11 +87,6 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
BIT(FLOW_DISSECTOR_KEY_CONTROL)))
return -EOPNOTSUPP;
if (proto == ETH_P_IP ||
proto == ETH_P_IPV6 ||
proto == ETH_P_ARP)
return -EOPNOTSUPP;
flow_rule_match_eth_addrs(rule, &match);
ace->type = OCELOT_ACE_TYPE_ETYPE;
ether_addr_copy(ace->frame.etype.dmac.value,
......@@ -114,6 +110,7 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
match.key->ip_proto;
ace->frame.ipv4.proto.mask[0] =
match.mask->ip_proto;
match_protocol = false;
}
if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
ace->type = OCELOT_ACE_TYPE_IPV6;
......@@ -121,11 +118,12 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
match.key->ip_proto;
ace->frame.ipv6.proto.mask[0] =
match.mask->ip_proto;
match_protocol = false;
}
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
ntohs(f->common.protocol) == ETH_P_IP) {
proto == ETH_P_IP) {
struct flow_match_ipv4_addrs match;
u8 *tmp;
......@@ -141,10 +139,11 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
tmp = &ace->frame.ipv4.dip.mask.addr[0];
memcpy(tmp, &match.mask->dst, 4);
match_protocol = false;
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
ntohs(f->common.protocol) == ETH_P_IPV6) {
proto == ETH_P_IPV6) {
return -EOPNOTSUPP;
}
......@@ -156,6 +155,7 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
ace->frame.ipv4.sport.mask = ntohs(match.mask->src);
ace->frame.ipv4.dport.value = ntohs(match.key->dst);
ace->frame.ipv4.dport.mask = ntohs(match.mask->dst);
match_protocol = false;
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
......@@ -167,9 +167,20 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
ace->vlan.vid.mask = match.mask->vlan_id;
ace->vlan.pcp.value[0] = match.key->vlan_priority;
ace->vlan.pcp.mask[0] = match.mask->vlan_priority;
match_protocol = false;
}
finished_key_parsing:
if (match_protocol && proto != ETH_P_ALL) {
/* TODO: support SNAP, LLC etc */
if (proto < ETH_P_802_3_MIN)
return -EOPNOTSUPP;
ace->type = OCELOT_ACE_TYPE_ETYPE;
*(u16 *)ace->frame.etype.etype.value = htons(proto);
*(u16 *)ace->frame.etype.etype.mask = 0xffff;
}
/* else, a rule of type OCELOT_ACE_TYPE_ANY is implicitly added */
ace->prio = f->common.prio;
ace->id = f->cookie;
return ocelot_flower_parse_action(f, ace);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment