forked from Minki/linux
net: dsa: sja1105: make room for virtual link parsing in flower offload
Virtual links are a sja1105 hardware concept of executing various flow actions based on a key extracted from the frame's DMAC, VID and PCP. Currently the tc-flower offload code supports only parsing the DMAC if that is the broadcast MAC address, and the VLAN PCP. Extract the key parsing logic from the L2 policers functionality and move it into its own function, after adding extra logic for matching on any DMAC and VID. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
94f94d4acf
commit
b70bb8d4ab
@ -97,6 +97,32 @@ struct sja1105_info {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
enum sja1105_key_type {
|
||||
SJA1105_KEY_BCAST,
|
||||
SJA1105_KEY_TC,
|
||||
SJA1105_KEY_VLAN_UNAWARE_VL,
|
||||
SJA1105_KEY_VLAN_AWARE_VL,
|
||||
};
|
||||
|
||||
struct sja1105_key {
|
||||
enum sja1105_key_type type;
|
||||
|
||||
union {
|
||||
/* SJA1105_KEY_TC */
|
||||
struct {
|
||||
int pcp;
|
||||
} tc;
|
||||
|
||||
/* SJA1105_KEY_VLAN_UNAWARE_VL */
|
||||
/* SJA1105_KEY_VLAN_AWARE_VL */
|
||||
struct {
|
||||
u64 dmac;
|
||||
u16 vid;
|
||||
u16 pcp;
|
||||
} vl;
|
||||
};
|
||||
};
|
||||
|
||||
enum sja1105_rule_type {
|
||||
SJA1105_RULE_BCAST_POLICER,
|
||||
SJA1105_RULE_TC_POLICER,
|
||||
@ -106,6 +132,7 @@ struct sja1105_rule {
|
||||
struct list_head list;
|
||||
unsigned long cookie;
|
||||
unsigned long port_mask;
|
||||
struct sja1105_key key;
|
||||
enum sja1105_rule_type type;
|
||||
|
||||
union {
|
||||
@ -117,7 +144,6 @@ struct sja1105_rule {
|
||||
/* SJA1105_RULE_TC_POLICER */
|
||||
struct {
|
||||
int sharindx;
|
||||
int tc;
|
||||
} tc_pol;
|
||||
};
|
||||
};
|
||||
|
@ -46,6 +46,7 @@ static int sja1105_setup_bcast_policer(struct sja1105_private *priv,
|
||||
rule->cookie = cookie;
|
||||
rule->type = SJA1105_RULE_BCAST_POLICER;
|
||||
rule->bcast_pol.sharindx = sja1105_find_free_l2_policer(priv);
|
||||
rule->key.type = SJA1105_KEY_BCAST;
|
||||
new_rule = true;
|
||||
}
|
||||
|
||||
@ -117,7 +118,8 @@ static int sja1105_setup_tc_policer(struct sja1105_private *priv,
|
||||
rule->cookie = cookie;
|
||||
rule->type = SJA1105_RULE_TC_POLICER;
|
||||
rule->tc_pol.sharindx = sja1105_find_free_l2_policer(priv);
|
||||
rule->tc_pol.tc = tc;
|
||||
rule->key.type = SJA1105_KEY_TC;
|
||||
rule->key.tc.pcp = tc;
|
||||
new_rule = true;
|
||||
}
|
||||
|
||||
@ -169,14 +171,37 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sja1105_flower_parse_policer(struct sja1105_private *priv, int port,
|
||||
struct netlink_ext_ack *extack,
|
||||
struct flow_cls_offload *cls,
|
||||
u64 rate_bytes_per_sec,
|
||||
s64 burst)
|
||||
static int sja1105_flower_policer(struct sja1105_private *priv, int port,
|
||||
struct netlink_ext_ack *extack,
|
||||
unsigned long cookie, struct sja1105_key *key,
|
||||
u64 rate_bytes_per_sec,
|
||||
s64 burst)
|
||||
{
|
||||
switch (key->type) {
|
||||
case SJA1105_KEY_BCAST:
|
||||
return sja1105_setup_bcast_policer(priv, extack, cookie, port,
|
||||
rate_bytes_per_sec, burst);
|
||||
case SJA1105_KEY_TC:
|
||||
return sja1105_setup_tc_policer(priv, extack, cookie, port,
|
||||
key->tc.pcp, rate_bytes_per_sec,
|
||||
burst);
|
||||
default:
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown keys for policing");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int sja1105_flower_parse_key(struct sja1105_private *priv,
|
||||
struct netlink_ext_ack *extack,
|
||||
struct flow_cls_offload *cls,
|
||||
struct sja1105_key *key)
|
||||
{
|
||||
struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
|
||||
struct flow_dissector *dissector = rule->match.dissector;
|
||||
bool is_bcast_dmac = false;
|
||||
u64 dmac = U64_MAX;
|
||||
u16 vid = U16_MAX;
|
||||
u16 pcp = U16_MAX;
|
||||
|
||||
if (dissector->used_keys &
|
||||
~(BIT(FLOW_DISSECTOR_KEY_BASIC) |
|
||||
@ -213,16 +238,14 @@ static int sja1105_flower_parse_policer(struct sja1105_private *priv, int port,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!ether_addr_equal_masked(match.key->dst, bcast,
|
||||
match.mask->dst)) {
|
||||
if (!ether_addr_equal(match.mask->dst, bcast)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Only matching on broadcast DMAC is supported");
|
||||
"Masked matching on MAC not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return sja1105_setup_bcast_policer(priv, extack, cls->cookie,
|
||||
port, rate_bytes_per_sec,
|
||||
burst);
|
||||
dmac = ether_addr_to_u64(match.key->dst);
|
||||
is_bcast_dmac = ether_addr_equal(match.key->dst, bcast);
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
|
||||
@ -230,22 +253,46 @@ static int sja1105_flower_parse_policer(struct sja1105_private *priv, int port,
|
||||
|
||||
flow_rule_match_vlan(rule, &match);
|
||||
|
||||
if (match.key->vlan_id & match.mask->vlan_id) {
|
||||
if (match.mask->vlan_id &&
|
||||
match.mask->vlan_id != VLAN_VID_MASK) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Matching on VID is not supported");
|
||||
"Masked matching on VID is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (match.mask->vlan_priority != 0x7) {
|
||||
if (match.mask->vlan_priority &&
|
||||
match.mask->vlan_priority != 0x7) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Masked matching on PCP is not supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return sja1105_setup_tc_policer(priv, extack, cls->cookie, port,
|
||||
match.key->vlan_priority,
|
||||
rate_bytes_per_sec,
|
||||
burst);
|
||||
if (match.mask->vlan_id)
|
||||
vid = match.key->vlan_id;
|
||||
if (match.mask->vlan_priority)
|
||||
pcp = match.key->vlan_priority;
|
||||
}
|
||||
|
||||
if (is_bcast_dmac && vid == U16_MAX && pcp == U16_MAX) {
|
||||
key->type = SJA1105_KEY_BCAST;
|
||||
return 0;
|
||||
}
|
||||
if (dmac == U64_MAX && vid == U16_MAX && pcp != U16_MAX) {
|
||||
key->type = SJA1105_KEY_TC;
|
||||
key->tc.pcp = pcp;
|
||||
return 0;
|
||||
}
|
||||
if (dmac != U64_MAX && vid != U16_MAX && pcp != U16_MAX) {
|
||||
key->type = SJA1105_KEY_VLAN_AWARE_VL;
|
||||
key->vl.dmac = dmac;
|
||||
key->vl.vid = vid;
|
||||
key->vl.pcp = pcp;
|
||||
return 0;
|
||||
}
|
||||
if (dmac != U64_MAX) {
|
||||
key->type = SJA1105_KEY_VLAN_UNAWARE_VL;
|
||||
key->vl.dmac = dmac;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NL_SET_ERR_MSG_MOD(extack, "Not matching on any known key");
|
||||
@ -259,22 +306,34 @@ int sja1105_cls_flower_add(struct dsa_switch *ds, int port,
|
||||
struct netlink_ext_ack *extack = cls->common.extack;
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
const struct flow_action_entry *act;
|
||||
int rc = -EOPNOTSUPP, i;
|
||||
unsigned long cookie = cls->cookie;
|
||||
struct sja1105_key key;
|
||||
int rc, i;
|
||||
|
||||
rc = sja1105_flower_parse_key(priv, extack, cls, &key);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = -EOPNOTSUPP;
|
||||
|
||||
flow_action_for_each(i, act, &rule->action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_POLICE:
|
||||
rc = sja1105_flower_parse_policer(priv, port, extack, cls,
|
||||
act->police.rate_bytes_ps,
|
||||
act->police.burst);
|
||||
rc = sja1105_flower_policer(priv, port,
|
||||
extack, cookie, &key,
|
||||
act->police.rate_bytes_ps,
|
||||
act->police.burst);
|
||||
if (rc)
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Action not supported");
|
||||
break;
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -297,7 +356,7 @@ int sja1105_cls_flower_del(struct dsa_switch *ds, int port,
|
||||
old_sharindx = policing[bcast].sharindx;
|
||||
policing[bcast].sharindx = port;
|
||||
} else if (rule->type == SJA1105_RULE_TC_POLICER) {
|
||||
int index = (port * SJA1105_NUM_TC) + rule->tc_pol.tc;
|
||||
int index = (port * SJA1105_NUM_TC) + rule->key.tc.pcp;
|
||||
|
||||
old_sharindx = policing[index].sharindx;
|
||||
policing[index].sharindx = port;
|
||||
|
Loading…
Reference in New Issue
Block a user