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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a3b6e8fd27
|
@ -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)
|
static bool ocelot_ace_is_problematic_mac_etype(struct ocelot_ace_rule *ace)
|
||||||
{
|
{
|
||||||
|
u16 proto, mask;
|
||||||
|
|
||||||
if (ace->type != OCELOT_ACE_TYPE_ETYPE)
|
if (ace->type != OCELOT_ACE_TYPE_ETYPE)
|
||||||
return false;
|
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;
|
return true;
|
||||||
if (ether_addr_to_u64(ace->frame.etype.smac.value) &
|
if (proto == ETH_P_ARP)
|
||||||
ether_addr_to_u64(ace->frame.etype.smac.mask))
|
|
||||||
return true;
|
return true;
|
||||||
|
if (proto == ETH_P_IP)
|
||||||
|
return true;
|
||||||
|
if (proto == ETH_P_IPV6)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
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_rule *rule = flow_cls_offload_flow_rule(f);
|
||||||
struct flow_dissector *dissector = rule->match.dissector;
|
struct flow_dissector *dissector = rule->match.dissector;
|
||||||
|
u16 proto = ntohs(f->common.protocol);
|
||||||
|
bool match_protocol = true;
|
||||||
|
|
||||||
if (dissector->used_keys &
|
if (dissector->used_keys &
|
||||||
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
|
~(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)) {
|
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
|
||||||
struct flow_match_eth_addrs match;
|
struct flow_match_eth_addrs match;
|
||||||
u16 proto = ntohs(f->common.protocol);
|
|
||||||
|
|
||||||
/* The hw support mac matches only for MAC_ETYPE key,
|
/* The hw support mac matches only for MAC_ETYPE key,
|
||||||
* therefore if other matches(port, tcp flags, etc) are added
|
* 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)))
|
BIT(FLOW_DISSECTOR_KEY_CONTROL)))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (proto == ETH_P_IP ||
|
|
||||||
proto == ETH_P_IPV6 ||
|
|
||||||
proto == ETH_P_ARP)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
flow_rule_match_eth_addrs(rule, &match);
|
flow_rule_match_eth_addrs(rule, &match);
|
||||||
ace->type = OCELOT_ACE_TYPE_ETYPE;
|
ace->type = OCELOT_ACE_TYPE_ETYPE;
|
||||||
ether_addr_copy(ace->frame.etype.dmac.value,
|
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;
|
match.key->ip_proto;
|
||||||
ace->frame.ipv4.proto.mask[0] =
|
ace->frame.ipv4.proto.mask[0] =
|
||||||
match.mask->ip_proto;
|
match.mask->ip_proto;
|
||||||
|
match_protocol = false;
|
||||||
}
|
}
|
||||||
if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
|
if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
|
||||||
ace->type = OCELOT_ACE_TYPE_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;
|
match.key->ip_proto;
|
||||||
ace->frame.ipv6.proto.mask[0] =
|
ace->frame.ipv6.proto.mask[0] =
|
||||||
match.mask->ip_proto;
|
match.mask->ip_proto;
|
||||||
|
match_protocol = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
|
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;
|
struct flow_match_ipv4_addrs match;
|
||||||
u8 *tmp;
|
u8 *tmp;
|
||||||
|
|
||||||
|
@ -141,10 +139,11 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
|
||||||
|
|
||||||
tmp = &ace->frame.ipv4.dip.mask.addr[0];
|
tmp = &ace->frame.ipv4.dip.mask.addr[0];
|
||||||
memcpy(tmp, &match.mask->dst, 4);
|
memcpy(tmp, &match.mask->dst, 4);
|
||||||
|
match_protocol = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
|
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
|
||||||
ntohs(f->common.protocol) == ETH_P_IPV6) {
|
proto == ETH_P_IPV6) {
|
||||||
return -EOPNOTSUPP;
|
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.sport.mask = ntohs(match.mask->src);
|
||||||
ace->frame.ipv4.dport.value = ntohs(match.key->dst);
|
ace->frame.ipv4.dport.value = ntohs(match.key->dst);
|
||||||
ace->frame.ipv4.dport.mask = ntohs(match.mask->dst);
|
ace->frame.ipv4.dport.mask = ntohs(match.mask->dst);
|
||||||
|
match_protocol = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
|
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.vid.mask = match.mask->vlan_id;
|
||||||
ace->vlan.pcp.value[0] = match.key->vlan_priority;
|
ace->vlan.pcp.value[0] = match.key->vlan_priority;
|
||||||
ace->vlan.pcp.mask[0] = match.mask->vlan_priority;
|
ace->vlan.pcp.mask[0] = match.mask->vlan_priority;
|
||||||
|
match_protocol = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
finished_key_parsing:
|
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->prio = f->common.prio;
|
||||||
ace->id = f->cookie;
|
ace->id = f->cookie;
|
||||||
return ocelot_flower_parse_action(f, ace);
|
return ocelot_flower_parse_action(f, ace);
|
||||||
|
|
Loading…
Reference in New Issue