Skip to content

Commit

Permalink
net: stmmac: add RX frame steering based on VLAN priority in tc flower
Browse files Browse the repository at this point in the history
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: Ong Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ong Boon Leong authored and David S. Miller committed Mar 18, 2021
1 parent bd0f670 commit 0e039f5
Showing 1 changed file with 63 additions and 2 deletions.
65 changes: 63 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,14 +598,73 @@ static int tc_del_flow(struct stmmac_priv *priv,
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,
struct flow_cls_offload *cls)
{
int ret;

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,
Expand All @@ -614,8 +673,10 @@ static int tc_del_flow_cls(struct stmmac_priv *priv,
int ret;

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,
Expand Down

0 comments on commit 0e039f5

Please sign in to comment.