Skip to content

Commit

Permalink
Merge branch 'net-act_police-offload-support'
Browse files Browse the repository at this point in the history
Jakub Kicinski says:

===================
net: act_police offload support

this set starts by converting cls_matchall to the new flow offload
infrastructure. It so happens that all drivers implementing cls_matchall
offload today also offload cls_flower, so its a little easier for
them to handle the actions in unified flow_rule format, even though
in cls_matchall there is no flow to speak of. If a driver ever appears
which would prefer the old, direct access to TC exts, we can add the
pointer in the offload structure back and support both.

Next the act_police is added to actions supported by flow offload API.

NFP support for act_police offload is added as the final step.  The flower
firmware is configured to perform TX rate limiting in a way which matches
act_police's behaviour.  It does not use DMA.IN back pressure, and
instead	drops packets after they had been already DMAed into the NIC.
IOW it uses our standard traffic policing implementation, future patches
will extend it to other ports and traffic directions.
===================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 6, 2019
2 parents c8f8207 + 5fb5c39 commit 7e6a95d
Show file tree
Hide file tree
Showing 18 changed files with 654 additions and 108 deletions.
38 changes: 19 additions & 19 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -1269,21 +1269,19 @@ mlxsw_sp_port_mall_tc_entry_find(struct mlxsw_sp_port *port,
static int
mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_port_mall_mirror_tc_entry *mirror,
const struct tc_action *a,
const struct flow_action_entry *act,
bool ingress)
{
enum mlxsw_sp_span_type span_type;
struct net_device *to_dev;

to_dev = tcf_mirred_dev(a);
if (!to_dev) {
if (!act->dev) {
netdev_err(mlxsw_sp_port->dev, "Could not find requested device\n");
return -EINVAL;
}

mirror->ingress = ingress;
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_dev, span_type,
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, act->dev, span_type,
true, &mirror->span_id);
}

Expand All @@ -1302,7 +1300,7 @@ mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
static int
mlxsw_sp_port_add_cls_matchall_sample(struct mlxsw_sp_port *mlxsw_sp_port,
struct tc_cls_matchall_offload *cls,
const struct tc_action *a,
const struct flow_action_entry *act,
bool ingress)
{
int err;
Expand All @@ -1313,18 +1311,18 @@ mlxsw_sp_port_add_cls_matchall_sample(struct mlxsw_sp_port *mlxsw_sp_port,
netdev_err(mlxsw_sp_port->dev, "sample already active\n");
return -EEXIST;
}
if (tcf_sample_rate(a) > MLXSW_REG_MPSC_RATE_MAX) {
if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) {
netdev_err(mlxsw_sp_port->dev, "sample rate not supported\n");
return -EOPNOTSUPP;
}

rcu_assign_pointer(mlxsw_sp_port->sample->psample_group,
tcf_sample_psample_group(a));
mlxsw_sp_port->sample->truncate = tcf_sample_truncate(a);
mlxsw_sp_port->sample->trunc_size = tcf_sample_trunc_size(a);
mlxsw_sp_port->sample->rate = tcf_sample_rate(a);
act->sample.psample_group);
mlxsw_sp_port->sample->truncate = act->sample.truncate;
mlxsw_sp_port->sample->trunc_size = act->sample.trunc_size;
mlxsw_sp_port->sample->rate = act->sample.rate;

err = mlxsw_sp_port_sample_set(mlxsw_sp_port, true, tcf_sample_rate(a));
err = mlxsw_sp_port_sample_set(mlxsw_sp_port, true, act->sample.rate);
if (err)
goto err_port_sample_set;
return 0;
Expand All @@ -1350,10 +1348,10 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
{
struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
__be16 protocol = f->common.protocol;
const struct tc_action *a;
struct flow_action_entry *act;
int err;

if (!tcf_exts_has_one_action(f->exts)) {
if (!flow_offload_has_one_action(&f->rule->action)) {
netdev_err(mlxsw_sp_port->dev, "only singular actions are supported\n");
return -EOPNOTSUPP;
}
Expand All @@ -1363,19 +1361,21 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
return -ENOMEM;
mall_tc_entry->cookie = f->cookie;

a = tcf_exts_first_action(f->exts);
act = &f->rule->action.entries[0];

if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) {
if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) {
struct mlxsw_sp_port_mall_mirror_tc_entry *mirror;

mall_tc_entry->type = MLXSW_SP_PORT_MALL_MIRROR;
mirror = &mall_tc_entry->mirror;
err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port,
mirror, a, ingress);
} else if (is_tcf_sample(a) && protocol == htons(ETH_P_ALL)) {
mirror, act,
ingress);
} else if (act->id == FLOW_ACTION_SAMPLE &&
protocol == htons(ETH_P_ALL)) {
mall_tc_entry->type = MLXSW_SP_PORT_MALL_SAMPLE;
err = mlxsw_sp_port_add_cls_matchall_sample(mlxsw_sp_port, f,
a, ingress);
act, ingress);
} else {
err = -EOPNOTSUPP;
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/netronome/nfp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ nfp-objs += \
flower/match.o \
flower/metadata.o \
flower/offload.o \
flower/tunnel_conf.o
flower/tunnel_conf.o \
flower/qos_conf.o
endif

ifeq ($(CONFIG_BPF_SYSCALL),y)
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/cmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
case NFP_FLOWER_CMSG_TYPE_ACTIVE_TUNS:
nfp_tunnel_keep_alive(app, skb);
break;
case NFP_FLOWER_CMSG_TYPE_QOS_STATS:
nfp_flower_stats_rlim_reply(app, skb);
break;
case NFP_FLOWER_CMSG_TYPE_LAG_CONFIG:
if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
skb_stored = nfp_flower_lag_unprocessed_msg(app, skb);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/cmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,9 @@ enum nfp_flower_cmsg_type_port {
NFP_FLOWER_CMSG_TYPE_TUN_IPS = 14,
NFP_FLOWER_CMSG_TYPE_FLOW_STATS = 15,
NFP_FLOWER_CMSG_TYPE_PORT_ECHO = 16,
NFP_FLOWER_CMSG_TYPE_QOS_MOD = 18,
NFP_FLOWER_CMSG_TYPE_QOS_DEL = 19,
NFP_FLOWER_CMSG_TYPE_QOS_STATS = 20,
NFP_FLOWER_CMSG_TYPE_MAX = 32,
};

Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,9 @@ static int nfp_flower_init(struct nfp_app *app)
nfp_warn(app->cpp, "Flow mod/merge not supported by FW.\n");
}

if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
nfp_flower_qos_init(app);

INIT_LIST_HEAD(&app_priv->indr_block_cb_priv);
INIT_LIST_HEAD(&app_priv->non_repr_priv);

Expand All @@ -799,6 +802,9 @@ static void nfp_flower_clean(struct nfp_app *app)
skb_queue_purge(&app_priv->cmsg_skbs_low);
flush_work(&app_priv->cmsg_work);

if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
nfp_flower_qos_cleanup(app);

if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG)
nfp_flower_lag_cleanup(&app_priv->nfp_lag);

Expand Down
29 changes: 29 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define __NFP_FLOWER_H__ 1

#include "cmsg.h"
#include "../nfp_net.h"

#include <linux/circ_buf.h>
#include <linux/hashtable.h>
Expand Down Expand Up @@ -39,6 +40,7 @@ struct nfp_app;
#define NFP_FL_NBI_MTU_SETTING BIT(1)
#define NFP_FL_FEATS_GENEVE_OPT BIT(2)
#define NFP_FL_FEATS_VLAN_PCP BIT(3)
#define NFP_FL_FEATS_VF_RLIM BIT(4)
#define NFP_FL_FEATS_FLOW_MOD BIT(5)
#define NFP_FL_FEATS_FLOW_MERGE BIT(30)
#define NFP_FL_FEATS_LAG BIT(31)
Expand Down Expand Up @@ -157,6 +159,9 @@ struct nfp_fl_internal_ports {
* @active_mem_unit: Current active memory unit for flower rules
* @total_mem_units: Total number of available memory units for flower rules
* @internal_ports: Internal port ids used in offloaded rules
* @qos_stats_work: Workqueue for qos stats processing
* @qos_rate_limiters: Current active qos rate limiters
* @qos_stats_lock: Lock on qos stats updates
*/
struct nfp_flower_priv {
struct nfp_app *app;
Expand Down Expand Up @@ -185,6 +190,23 @@ struct nfp_flower_priv {
unsigned int active_mem_unit;
unsigned int total_mem_units;
struct nfp_fl_internal_ports internal_ports;
struct delayed_work qos_stats_work;
unsigned int qos_rate_limiters;
spinlock_t qos_stats_lock; /* Protect the qos stats */
};

/**
* struct nfp_fl_qos - Flower APP priv data for quality of service
* @netdev_port_id: NFP port number of repr with qos info
* @curr_stats: Currently stored stats updates for qos info
* @prev_stats: Previously stored updates for qos info
* @last_update: Stored time when last stats were updated
*/
struct nfp_fl_qos {
u32 netdev_port_id;
struct nfp_stat_pair curr_stats;
struct nfp_stat_pair prev_stats;
u64 last_update;
};

/**
Expand All @@ -194,13 +216,15 @@ struct nfp_flower_priv {
* @mac_offloaded: Flag indicating a MAC address is offloaded for repr
* @offloaded_mac_addr: MAC address that has been offloaded for repr
* @mac_list: List entry of reprs that share the same offloaded MAC
* @qos_table: Stored info on filters implementing qos
*/
struct nfp_flower_repr_priv {
struct nfp_repr *nfp_repr;
unsigned long lag_port_flags;
bool mac_offloaded;
u8 offloaded_mac_addr[ETH_ALEN];
struct list_head mac_list;
struct nfp_fl_qos qos_table;
};

/**
Expand Down Expand Up @@ -366,6 +390,11 @@ int nfp_flower_lag_populate_pre_action(struct nfp_app *app,
struct nfp_fl_pre_lag *pre_act);
int nfp_flower_lag_get_output_id(struct nfp_app *app,
struct net_device *master);
void nfp_flower_qos_init(struct nfp_app *app);
void nfp_flower_qos_cleanup(struct nfp_app *app);
int nfp_flower_setup_qos_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_matchall_offload *flow);
void nfp_flower_stats_rlim_reply(struct nfp_app *app, struct sk_buff *skb);
int nfp_flower_reg_indir_block_handler(struct nfp_app *app,
struct net_device *netdev,
unsigned long event);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,9 @@ static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
case TC_SETUP_CLSFLOWER:
return nfp_flower_repr_offload(repr->app, repr->netdev,
type_data);
case TC_SETUP_CLSMATCHALL:
return nfp_flower_setup_qos_offload(repr->app, repr->netdev,
type_data);
default:
return -EOPNOTSUPP;
}
Expand Down
Loading

0 comments on commit 7e6a95d

Please sign in to comment.