As more police parameters are passed to flow_offload, driver can check them to make sure hardware handles packets in the way indicated by tc. The conform-exceed control should be drop/pipe or drop/ok. Besides, for drop/ok, the police should be the last action. As hardware can't configure peakrate/avrate/overhead, offload should not be supported if any of them is configured. Signed-off-by: Jianbo Liu <jianbol@xxxxxxxxxx> Reviewed-by: Roi Dayan <roid@xxxxxxxxxx> Reviewed-by: Ido Schimmel <idosch@xxxxxxxxxx> --- drivers/net/dsa/sja1105/sja1105_flower.c | 27 +++++++++ .../chelsio/cxgb4/cxgb4_tc_matchall.c | 55 +++++++++++++++++++ .../net/ethernet/freescale/enetc/enetc_qos.c | 31 +++++++++++ .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 54 ++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/en_tc.c | 27 +++++++++ .../ethernet/mellanox/mlxsw/spectrum_flower.c | 27 +++++++++ drivers/net/ethernet/mscc/ocelot_flower.c | 28 ++++++++++ drivers/net/ethernet/mscc/ocelot_net.c | 27 +++++++++ .../ethernet/netronome/nfp/flower/qos_conf.c | 28 ++++++++++ include/net/flow_offload.h | 6 ++ 10 files changed, 310 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105_flower.c b/drivers/net/dsa/sja1105/sja1105_flower.c index 7dcdd784aea4..8a14df8cf91e 100644 --- a/drivers/net/dsa/sja1105/sja1105_flower.c +++ b/drivers/net/dsa/sja1105/sja1105_flower.c @@ -321,6 +321,33 @@ int sja1105_cls_flower_add(struct dsa_switch *ds, int port, flow_action_for_each(i, act, &rule->action) { switch (act->id) { case FLOW_ACTION_POLICE: + if (act->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id != FLOW_ACTION_PIPE && + act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(&rule->action, act)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (act->police.peakrate_bytes_ps || + act->police.avrate || act->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (act->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c index 28fd2de9e4cf..124e65116b2d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c @@ -48,6 +48,33 @@ static int cxgb4_matchall_egress_validate(struct net_device *dev, flow_action_for_each(i, entry, actions) { switch (entry->id) { case FLOW_ACTION_POLICE: + if (entry->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (entry->police.notexceed.act_id != FLOW_ACTION_PIPE && + entry->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (entry->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(actions, entry)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (entry->police.peakrate_bytes_ps || + entry->police.avrate || entry->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (entry->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); @@ -150,6 +177,34 @@ static int cxgb4_matchall_alloc_tc(struct net_device *dev, flow_action_for_each(i, entry, &cls->rule->action) if (entry->id == FLOW_ACTION_POLICE) break; + + if (entry->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (entry->police.notexceed.act_id != FLOW_ACTION_PIPE && + entry->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (entry->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(&cls->rule->action, entry)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (entry->police.peakrate_bytes_ps || + entry->police.avrate || entry->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (entry->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c index 3555c12edb45..c992d9e86467 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c @@ -1230,6 +1230,37 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv, /* Flow meter and max frame size */ if (entryp) { + if (entryp->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + err = -EOPNOTSUPP; + goto free_sfi; + } + + if (entryp->police.notexceed.act_id != FLOW_ACTION_PIPE && + entryp->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + err = -EOPNOTSUPP; + goto free_sfi; + } + + if (entryp->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(&rule->action, entryp)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + err = -EOPNOTSUPP; + goto free_sfi; + } + + if (entryp->police.peakrate_bytes_ps || + entryp->police.avrate || entryp->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + err = -EOPNOTSUPP; + goto free_sfi; + } + if (entryp->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); err = -EOPNOTSUPP; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 626961a41089..4b6e17765b2f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -212,6 +212,33 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic, entry = &cls->rule->action.entries[0]; switch (entry->id) { case FLOW_ACTION_POLICE: + if (entry->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (entry->police.notexceed.act_id != FLOW_ACTION_PIPE && + entry->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (entry->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(&cls->rule->action, entry)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (entry->police.peakrate_bytes_ps || + entry->police.avrate || entry->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (entry->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); return -EOPNOTSUPP; @@ -355,6 +382,33 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, return -EOPNOTSUPP; } + if (act->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id != FLOW_ACTION_PIPE && + act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(flow_action, act)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (act->police.peakrate_bytes_ps || + act->police.avrate || act->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (act->police.rate_bytes_ps > 0) { rate = act->police.rate_bytes_ps * 8; burst = act->police.burst; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 1287193a019b..7c160961c92e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -4197,6 +4197,33 @@ static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv, flow_action_for_each(i, act, flow_action) { switch (act->id) { case FLOW_ACTION_POLICE: + if (act->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id != FLOW_ACTION_PIPE && + act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(flow_action, act)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (act->police.peakrate_bytes_ps || + act->police.avrate || act->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (act->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index bb417db773b9..b33c3da4daf8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -191,6 +191,33 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, return -EOPNOTSUPP; } + if (act->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id != FLOW_ACTION_PIPE && + act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(flow_action, act)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (act->police.peakrate_bytes_ps || + act->police.avrate || act->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (act->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index 949858891973..eb478ddb0f90 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -296,6 +296,34 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, "Last action must be GOTO"); return -EOPNOTSUPP; } + + if (a->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (a->police.notexceed.act_id != FLOW_ACTION_PIPE && + a->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (a->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(&f->rule->action, a)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (a->police.peakrate_bytes_ps || + a->police.avrate || a->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (a->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index e271b6225b72..69afb560ab98 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -258,6 +258,33 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port_private *priv, return -EEXIST; } + if (action->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (action->police.notexceed.act_id != FLOW_ACTION_PIPE && + action->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (action->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(&f->rule->action, action)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (action->police.peakrate_bytes_ps || + action->police.avrate || action->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (action->police.rate_pkt_ps) { NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); diff --git a/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c b/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c index 784c6dbf8bc4..247984d50b49 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/qos_conf.c @@ -132,6 +132,34 @@ nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev, "unsupported offload: qos rate limit offload requires police action"); return -EOPNOTSUPP; } + + if (action->police.exceed.act_id != FLOW_ACTION_DROP) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the exceed action is not drop"); + return -EOPNOTSUPP; + } + + if (action->police.notexceed.act_id != FLOW_ACTION_PIPE && + action->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is not pipe or ok"); + return -EOPNOTSUPP; + } + + if (action->police.notexceed.act_id == FLOW_ACTION_ACCEPT && + !flow_action_is_last_entry(&flow->rule->action, action)) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when the conform action is ok, but police action is not last"); + return -EOPNOTSUPP; + } + + if (action->police.peakrate_bytes_ps || + action->police.avrate || action->police.overhead) { + NL_SET_ERR_MSG_MOD(extack, + "Police offload is not supported when peakrate/avrate/overhead is configured"); + return -EOPNOTSUPP; + } + if (action->police.rate_bytes_ps > 0) { if (bps_num++) { NL_SET_ERR_MSG_MOD(extack, diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 94cde6bbc8a5..2b9890177aa1 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -315,6 +315,12 @@ static inline bool flow_offload_has_one_action(const struct flow_action *action) return action->num_entries == 1; } +static inline bool flow_action_is_last_entry(const struct flow_action *action, + const struct flow_action_entry *entry) +{ + return entry == &action->entries[action->num_entries - 1]; +} + #define flow_action_for_each(__i, __act, __actions) \ for (__i = 0, __act = &(__actions)->entries[0]; \ __i < (__actions)->num_entries; \ -- 2.26.2