mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
flow_offload: reject offload for all drivers with invalid police parameters
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@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b8cd5831c6
commit
d97b4b105c
@ -300,6 +300,46 @@ static int sja1105_flower_parse_key(struct sja1105_private *priv,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int sja1105_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is ok, but action is not last");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sja1105_cls_flower_add(struct dsa_switch *ds, int port,
|
||||
struct flow_cls_offload *cls, bool ingress)
|
||||
{
|
||||
@ -321,12 +361,9 @@ 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.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"QoS offload not support packets per second");
|
||||
rc = -EOPNOTSUPP;
|
||||
rc = sja1105_policer_validate(&rule->action, act, extack);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = sja1105_flower_policer(priv, port, extack, cookie,
|
||||
&key,
|
||||
|
@ -8,6 +8,46 @@
|
||||
#include "cxgb4_filter.h"
|
||||
#include "cxgb4_tc_flower.h"
|
||||
|
||||
static int cxgb4_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is ok, but action is not last");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxgb4_matchall_egress_validate(struct net_device *dev,
|
||||
struct tc_cls_matchall_offload *cls)
|
||||
{
|
||||
@ -48,11 +88,10 @@ 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.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
ret = cxgb4_policer_validate(actions, entry, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Convert bytes per second to bits per second */
|
||||
if (entry->police.rate_bytes_ps * 8 > max_link_rate) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
@ -150,11 +189,11 @@ 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.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = cxgb4_policer_validate(&cls->rule->action, entry, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Convert from bytes per second to Kbps */
|
||||
p.u.params.maxrate = div_u64(entry->police.rate_bytes_ps * 8, 1000);
|
||||
p.u.params.channel = pi->tx_chan;
|
||||
|
@ -1021,6 +1021,46 @@ static struct actions_fwd *enetc_check_flow_actions(u64 acts,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int enetc_psfp_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is ok, but action is not last");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,
|
||||
struct flow_cls_offload *f)
|
||||
{
|
||||
@ -1177,11 +1217,10 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,
|
||||
|
||||
/* Flow meter and max frame size */
|
||||
if (entryp) {
|
||||
if (entryp->police.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
|
||||
err = -EOPNOTSUPP;
|
||||
err = enetc_psfp_policer_validate(&rule->action, entryp, extack);
|
||||
if (err)
|
||||
goto free_sfi;
|
||||
}
|
||||
|
||||
if (entryp->police.burst) {
|
||||
fmi = kzalloc(sizeof(*fmi), GFP_KERNEL);
|
||||
if (!fmi) {
|
||||
|
@ -190,6 +190,40 @@ static int otx2_tc_validate_flow(struct otx2_nic *nic,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is ok, but action is not last");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when peakrate/avrate/overhead is configured");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_tc_egress_matchall_install(struct otx2_nic *nic,
|
||||
struct tc_cls_matchall_offload *cls)
|
||||
{
|
||||
@ -212,6 +246,10 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic,
|
||||
entry = &cls->rule->action.entries[0];
|
||||
switch (entry->id) {
|
||||
case FLOW_ACTION_POLICE:
|
||||
err = otx2_policer_validate(&cls->rule->action, entry, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (entry->police.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
@ -315,6 +353,7 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
|
||||
u8 nr_police = 0;
|
||||
bool pps = false;
|
||||
u64 rate;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
if (!flow_action_has_entries(flow_action)) {
|
||||
@ -355,6 +394,10 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = otx2_policer_validate(flow_action, act, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (act->police.rate_bytes_ps > 0) {
|
||||
rate = act->police.rate_bytes_ps * 8;
|
||||
burst = act->police.burst;
|
||||
|
@ -4482,6 +4482,46 @@ static int apply_police_params(struct mlx5e_priv *priv, u64 rate,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is ok, but action is not last");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
|
||||
struct flow_action *flow_action,
|
||||
struct netlink_ext_ack *extack)
|
||||
@ -4509,10 +4549,10 @@ 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.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
err = mlx5e_policer_validate(flow_action, act, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = apply_police_params(priv, act->police.rate_bytes_ps, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -15,6 +15,46 @@
|
||||
#include "spectrum.h"
|
||||
#include "core_acl_flex_keys.h"
|
||||
|
||||
static int mlxsw_sp_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is ok, but action is not last");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_flow_block *block,
|
||||
struct mlxsw_sp_acl_rule_info *rulei,
|
||||
@ -191,10 +231,9 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
err = mlxsw_sp_policer_validate(flow_action, act, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The kernel might adjust the requested burst size so
|
||||
* that it is not exactly a power of two. Re-adjust it
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/tc_act/tc_gact.h>
|
||||
#include <soc/mscc/ocelot_vcap.h>
|
||||
#include "ocelot_police.h"
|
||||
#include "ocelot_vcap.h"
|
||||
|
||||
/* Arbitrarily chosen constants for encoding the VCAP block and lookup number
|
||||
@ -217,6 +218,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
|
||||
bool ingress, struct flow_cls_offload *f,
|
||||
struct ocelot_vcap_filter *filter)
|
||||
{
|
||||
const struct flow_action *action = &f->rule->action;
|
||||
struct netlink_ext_ack *extack = f->common.extack;
|
||||
bool allow_missing_goto_target = false;
|
||||
const struct flow_action_entry *a;
|
||||
@ -244,7 +246,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
|
||||
filter->goto_target = -1;
|
||||
filter->type = OCELOT_VCAP_FILTER_DUMMY;
|
||||
|
||||
flow_action_for_each(i, a, &f->rule->action) {
|
||||
flow_action_for_each(i, a, action) {
|
||||
switch (a->id) {
|
||||
case FLOW_ACTION_DROP:
|
||||
if (filter->block_id != VCAP_IS2) {
|
||||
@ -297,11 +299,11 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
|
||||
"Last action must be GOTO");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (a->police.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = ocelot_policer_validate(action, a, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
filter->action.police_ena = true;
|
||||
|
||||
pol_ix = a->hw_index + ocelot->vcap_pol.base;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/phy/phy.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include "ocelot.h"
|
||||
#include "ocelot_police.h"
|
||||
#include "ocelot_vcap.h"
|
||||
#include "ocelot_fdma.h"
|
||||
|
||||
@ -258,11 +259,10 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port_private *priv,
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (action->police.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"QoS offload not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
err = ocelot_policer_validate(&f->rule->action, action,
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pol.rate = (u32)div_u64(action->police.rate_bytes_ps, 1000) * 8;
|
||||
pol.burst = action->police.burst;
|
||||
|
@ -154,6 +154,47 @@ int qos_policer_conf_set(struct ocelot *ocelot, int port, u32 pol_ix,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ocelot_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *a,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (a->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (a->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, a)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when peakrate/avrate/overhead is configured");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (a->police.rate_pkt_ps) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload does not support packets per second");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ocelot_policer_validate);
|
||||
|
||||
int ocelot_port_policer_add(struct ocelot *ocelot, int port,
|
||||
struct ocelot_policer *pol)
|
||||
{
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define _MSCC_OCELOT_POLICE_H_
|
||||
|
||||
#include "ocelot.h"
|
||||
#include <net/flow_offload.h>
|
||||
|
||||
enum mscc_qos_rate_mode {
|
||||
MSCC_QOS_RATE_MODE_DISABLED, /* Policer/shaper disabled */
|
||||
@ -33,4 +34,8 @@ struct qos_policer_conf {
|
||||
int qos_policer_conf_set(struct ocelot *ocelot, int port, u32 pol_ix,
|
||||
struct qos_policer_conf *conf);
|
||||
|
||||
int ocelot_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *a,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
#endif /* _MSCC_OCELOT_POLICE_H_ */
|
||||
|
@ -117,6 +117,40 @@ int nfp_flower_offload_one_police(struct nfp_app *app, bool ingress,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfp_policer_validate(const struct flow_action *action,
|
||||
const struct flow_action_entry *act,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when 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,
|
||||
"Offload not supported when conform action is not pipe or ok");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
|
||||
!flow_action_is_last_entry(action, act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when conform action is ok, but action is not last");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (act->police.peakrate_bytes_ps ||
|
||||
act->police.avrate || act->police.overhead) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Offload not supported when peakrate/avrate/overhead is configured");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
|
||||
struct tc_cls_matchall_offload *flow,
|
||||
@ -135,6 +169,7 @@ nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
|
||||
u32 burst;
|
||||
bool pps;
|
||||
u64 rate;
|
||||
int err;
|
||||
|
||||
if (!nfp_netdev_is_nfp_repr(netdev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "unsupported offload: qos rate limit offload not supported on higher level port");
|
||||
@ -181,6 +216,11 @@ nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
|
||||
"unsupported offload: qos rate limit offload requires police action");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = nfp_policer_validate(&flow->rule->action, action, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (action->police.rate_bytes_ps > 0) {
|
||||
if (bps_num++) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
|
@ -311,6 +311,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; \
|
||||
|
Loading…
Reference in New Issue
Block a user