Offload a tc matchall filter with a police action to the port policer: tc qdisc add dev clsact tc filter add dev ingress matchall skip_sw \ action police rate burst conform-exceed drop The port policer meters all ingress frames on the port, so offload the filter only on ingress, on chain 0, with protocol all, and on a block that is not shared. Only drop is supported as the exceed action, and only one policer per port. Report the pass and drop counts through the matchall stats. Signed-off-by: Daniel Machon --- .../ethernet/microchip/sparx5/sparx5_tc_matchall.c | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c index 146d7f28e8f3..5bf17c52e564 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c @@ -43,6 +43,13 @@ sparx5_tc_matchall_parse_mirror_action(struct sparx5_mall_entry *entry, entry->mirror.port = netdev_priv(action->dev); } +static void +sparx5_tc_matchall_parse_port_policer_action(struct sparx5_mall_entry *entry, + struct flow_action_entry *action) +{ + entry->port_policer.police = action->police; +} + static int sparx5_tc_matchall_replace(struct net_device *ndev, struct tc_cls_matchall_offload *tmo, bool ingress) @@ -98,6 +105,30 @@ static int sparx5_tc_matchall_replace(struct net_device *ndev, } /* Get baseline stats for this port */ sparx5_mirror_stats(mall_entry, &tmo->stats); + break; + case FLOW_ACTION_POLICE: + if (tmo->common.protocol != htons(ETH_P_ALL)) { + NL_SET_ERR_MSG_MOD(tmo->common.extack, + "Policer is only supported with protocol all"); + kfree(mall_entry); + return -EOPNOTSUPP; + } + + if (tmo->common.chain_index) { + NL_SET_ERR_MSG_MOD(tmo->common.extack, + "Policer is only supported on chain 0"); + kfree(mall_entry); + return -EOPNOTSUPP; + } + + sparx5_tc_matchall_parse_port_policer_action(mall_entry, + action); + err = sparx5_add_port_policer(mall_entry, tmo->common.extack); + if (err) { + kfree(mall_entry); + return err; + } + break; case FLOW_ACTION_GOTO: err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev, @@ -151,6 +182,11 @@ static int sparx5_tc_matchall_destroy(struct net_device *ndev, if (entry->type == FLOW_ACTION_MIRRED) { sparx5_mirror_del(entry); + } else if (entry->type == FLOW_ACTION_POLICE) { + err = sparx5_delete_port_policer(entry); + if (err) + NL_SET_ERR_MSG_MOD(tmo->common.extack, + "Could not delete port policer"); } else if (entry->type == FLOW_ACTION_GOTO) { err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev, 0, 0, tmo->cookie, false); @@ -180,6 +216,8 @@ static int sparx5_tc_matchall_stats(struct net_device *ndev, if (entry->type == FLOW_ACTION_MIRRED) { sparx5_mirror_stats(entry, &tmo->stats); + } else if (entry->type == FLOW_ACTION_POLICE) { + sparx5_update_port_policer_stats(ndev, tmo); } else { NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action"); return -EOPNOTSUPP; -- 2.34.1