Commit 0e039f5c authored by Ong Boon Leong's avatar Ong Boon Leong Committed by David S. Miller

net: stmmac: add RX frame steering based on VLAN priority in tc flower

We extend tc flower to support configuration of VLAN priority-based RX
frame steering hardware offloading.

To map VLAN <PCP> to Traffic Class <TC>:
  $ tc filter add dev <IFNAME> parent ffff: protocol 802.1Q flower \
       vlan_prio <PCP> hw_tc <TC>

  Note: <TC> < N whereby "tc qdisc ... num_tc N ..."

To delete all tc flower configurations:
  $ tc qdisc delete dev <IFNAME> ingress
Signed-off-by: default avatarOng Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bd0f670e
...@@ -598,14 +598,73 @@ static int tc_del_flow(struct stmmac_priv *priv, ...@@ -598,14 +598,73 @@ static int tc_del_flow(struct stmmac_priv *priv,
return ret; return ret;
} }
#define VLAN_PRIO_FULL_MASK (0x07)
static int tc_add_vlan_flow(struct stmmac_priv *priv,
struct flow_cls_offload *cls)
{
struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
struct flow_dissector *dissector = rule->match.dissector;
int tc = tc_classid_to_hwtc(priv->dev, cls->classid);
struct flow_match_vlan match;
/* Nothing to do here */
if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN))
return -EINVAL;
if (tc < 0) {
netdev_err(priv->dev, "Invalid traffic class\n");
return -EINVAL;
}
flow_rule_match_vlan(rule, &match);
if (match.mask->vlan_priority) {
u32 prio;
if (match.mask->vlan_priority != VLAN_PRIO_FULL_MASK) {
netdev_err(priv->dev, "Only full mask is supported for VLAN priority");
return -EINVAL;
}
prio = BIT(match.key->vlan_priority);
stmmac_rx_queue_prio(priv, priv->hw, prio, tc);
}
return 0;
}
static int tc_del_vlan_flow(struct stmmac_priv *priv,
struct flow_cls_offload *cls)
{
struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
struct flow_dissector *dissector = rule->match.dissector;
int tc = tc_classid_to_hwtc(priv->dev, cls->classid);
/* Nothing to do here */
if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN))
return -EINVAL;
if (tc < 0) {
netdev_err(priv->dev, "Invalid traffic class\n");
return -EINVAL;
}
stmmac_rx_queue_prio(priv, priv->hw, 0, tc);
return 0;
}
static int tc_add_flow_cls(struct stmmac_priv *priv, static int tc_add_flow_cls(struct stmmac_priv *priv,
struct flow_cls_offload *cls) struct flow_cls_offload *cls)
{ {
int ret; int ret;
ret = tc_add_flow(priv, cls); ret = tc_add_flow(priv, cls);
if (!ret)
return ret; return ret;
return tc_add_vlan_flow(priv, cls);
} }
static int tc_del_flow_cls(struct stmmac_priv *priv, static int tc_del_flow_cls(struct stmmac_priv *priv,
...@@ -614,8 +673,10 @@ static int tc_del_flow_cls(struct stmmac_priv *priv, ...@@ -614,8 +673,10 @@ static int tc_del_flow_cls(struct stmmac_priv *priv,
int ret; int ret;
ret = tc_del_flow(priv, cls); ret = tc_del_flow(priv, cls);
if (!ret)
return ret; return ret;
return tc_del_vlan_flow(priv, cls);
} }
static int tc_setup_cls(struct stmmac_priv *priv, static int tc_setup_cls(struct stmmac_priv *priv,
......
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