net: flow_offload: add flow_block_cb_setup_simple()

Most drivers do the same thing to set up the flow block callbacks, this
patch adds a helper function to do this.

This preparation patch reduces the number of changes to adapt the
existing drivers to use the flow block callback API.

This new helper function takes a flow block list per-driver, which is
set to NULL until this driver list is used.

This patch also introduces the flow_block_command and
flow_block_binder_type enumerations, which are renamed to use
FLOW_BLOCK_* in follow up patches.

There are three definitions (aliases) in order to reduce the number of
updates in this patch, which go away once drivers are fully adapted to
use this flow block API.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Pablo Neira Ayuso 2019-07-09 22:55:39 +02:00 committed by David S. Miller
parent 2bb295f3a5
commit 4e95bc268b
17 changed files with 117 additions and 317 deletions

View File

@ -9907,32 +9907,16 @@ static int bnxt_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
static int bnxt_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct bnxt *bp = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, bnxt_setup_tc_block_cb,
bp, bp, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, bnxt_setup_tc_block_cb, bp);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct bnxt *bp = netdev_priv(dev);
switch (type) {
case TC_SETUP_BLOCK:
return bnxt_setup_tc_block(dev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
bnxt_setup_tc_block_cb,
bp, bp, true);
case TC_SETUP_QDISC_MQPRIO: {
struct tc_mqprio_qopt *mqprio = type_data;

View File

@ -161,34 +161,16 @@ static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
}
}
static int bnxt_vf_rep_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block,
bnxt_vf_rep_setup_tc_block_cb,
vf_rep, vf_rep, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block,
bnxt_vf_rep_setup_tc_block_cb, vf_rep);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
switch (type) {
case TC_SETUP_BLOCK:
return bnxt_vf_rep_setup_tc_block(dev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
bnxt_vf_rep_setup_tc_block_cb,
vf_rep, vf_rep, true);
default:
return -EOPNOTSUPP;
}

View File

@ -3190,32 +3190,16 @@ static int cxgb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
static int cxgb_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct port_info *pi = netdev2pinfo(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, cxgb_setup_tc_block_cb,
pi, dev, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, cxgb_setup_tc_block_cb, pi);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct port_info *pi = netdev2pinfo(dev);
switch (type) {
case TC_SETUP_BLOCK:
return cxgb_setup_tc_block(dev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
cxgb_setup_tc_block_cb,
pi, dev, true);
default:
return -EOPNOTSUPP;
}

View File

@ -8177,34 +8177,18 @@ static int i40e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
static int i40e_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, i40e_setup_tc_block_cb,
np, np, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, i40e_setup_tc_block_cb, np);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int __i40e_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
switch (type) {
case TC_SETUP_QDISC_MQPRIO:
return i40e_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
return i40e_setup_tc_block(netdev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
i40e_setup_tc_block_cb,
np, np, true);
default:
return -EOPNOTSUPP;
}

View File

@ -3113,35 +3113,6 @@ static int iavf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
/**
* iavf_setup_tc_block - register callbacks for tc
* @netdev: network interface device structure
* @f: tc offload data
*
* This function registers block callbacks for tc
* offloads
**/
static int iavf_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct iavf_adapter *adapter = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, iavf_setup_tc_block_cb,
adapter, adapter, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, iavf_setup_tc_block_cb,
adapter);
return 0;
default:
return -EOPNOTSUPP;
}
}
/**
* iavf_setup_tc - configure multiple traffic classes
* @netdev: network interface device structure
@ -3156,11 +3127,15 @@ static int iavf_setup_tc_block(struct net_device *dev,
static int iavf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
struct iavf_adapter *adapter = netdev_priv(netdev);
switch (type) {
case TC_SETUP_QDISC_MQPRIO:
return __iavf_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
return iavf_setup_tc_block(netdev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
iavf_setup_tc_block_cb,
adapter, adapter, true);
default:
return -EOPNOTSUPP;
}

View File

@ -2783,25 +2783,6 @@ static int igb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
static int igb_setup_tc_block(struct igb_adapter *adapter,
struct tc_block_offload *f)
{
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, igb_setup_tc_block_cb,
adapter, adapter, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, igb_setup_tc_block_cb,
adapter);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int igb_offload_txtime(struct igb_adapter *adapter,
struct tc_etf_qopt_offload *qopt)
{
@ -2834,7 +2815,10 @@ static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
case TC_SETUP_QDISC_CBS:
return igb_offload_cbs(adapter, type_data);
case TC_SETUP_BLOCK:
return igb_setup_tc_block(adapter, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
igb_setup_tc_block_cb,
adapter, adapter, true);
case TC_SETUP_QDISC_ETF:
return igb_offload_txtime(adapter, type_data);

View File

@ -9607,27 +9607,6 @@ static int ixgbe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
static int ixgbe_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, ixgbe_setup_tc_block_cb,
adapter, adapter, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, ixgbe_setup_tc_block_cb,
adapter);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int ixgbe_setup_tc_mqprio(struct net_device *dev,
struct tc_mqprio_qopt *mqprio)
{
@ -9638,9 +9617,13 @@ static int ixgbe_setup_tc_mqprio(struct net_device *dev,
static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
switch (type) {
case TC_SETUP_BLOCK:
return ixgbe_setup_tc_block(dev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
ixgbe_setup_tc_block_cb,
adapter, adapter, true);
case TC_SETUP_QDISC_MQPRIO:
return ixgbe_setup_tc_mqprio(dev, type_data);
default:

View File

@ -3457,36 +3457,19 @@ static int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
return -EOPNOTSUPP;
}
}
static int mlx5e_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct mlx5e_priv *priv = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, mlx5e_setup_tc_block_cb,
priv, priv, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, mlx5e_setup_tc_block_cb,
priv);
return 0;
default:
return -EOPNOTSUPP;
}
}
#endif
static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct mlx5e_priv *priv = netdev_priv(dev);
switch (type) {
#ifdef CONFIG_MLX5_ESWITCH
case TC_SETUP_BLOCK:
return mlx5e_setup_tc_block(dev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
mlx5e_setup_tc_block_cb,
priv, priv, true);
#endif
case TC_SETUP_QDISC_MQPRIO:
return mlx5e_setup_tc_mqprio(dev, type_data);

View File

@ -1153,32 +1153,16 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
}
}
static int mlx5e_rep_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
struct mlx5e_priv *priv = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, mlx5e_rep_setup_tc_cb,
priv, priv, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, mlx5e_rep_setup_tc_cb, priv);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct mlx5e_priv *priv = netdev_priv(dev);
switch (type) {
case TC_SETUP_BLOCK:
return mlx5e_rep_setup_tc_block(dev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
mlx5e_rep_setup_tc_cb,
priv, priv, true);
default:
return -EOPNOTSUPP;
}

View File

@ -265,19 +265,6 @@ static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type,
int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr,
struct tc_block_offload *f)
{
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block,
nfp_abm_setup_tc_block_cb,
repr, repr, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, nfp_abm_setup_tc_block_cb,
repr);
return 0;
default:
return -EOPNOTSUPP;
}
return flow_block_cb_setup_simple(f, NULL, nfp_abm_setup_tc_block_cb,
repr, repr, true);
}

View File

@ -160,35 +160,16 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
return 0;
}
static int nfp_bpf_setup_tc_block(struct net_device *netdev,
struct tc_block_offload *f)
{
struct nfp_net *nn = netdev_priv(netdev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block,
nfp_bpf_setup_tc_block_cb,
nn, nn, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block,
nfp_bpf_setup_tc_block_cb,
nn);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
enum tc_setup_type type, void *type_data)
{
struct nfp_net *nn = netdev_priv(netdev);
switch (type) {
case TC_SETUP_BLOCK:
return nfp_bpf_setup_tc_block(netdev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
nfp_bpf_setup_tc_block_cb,
nn, nn, true);
default:
return -EOPNOTSUPP;
}

View File

@ -579,25 +579,6 @@ static int qede_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
static int qede_setup_tc_block(struct qede_dev *edev,
struct tc_block_offload *f)
{
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block,
qede_setup_tc_block_cb,
edev, edev, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, qede_setup_tc_block_cb, edev);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int
qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
void *type_data)
@ -607,7 +588,9 @@ qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
return qede_setup_tc_block(edev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
qede_setup_tc_block_cb,
edev, edev, true);
case TC_SETUP_QDISC_MQPRIO:
mqprio = type_data;

View File

@ -3769,24 +3769,6 @@ static int stmmac_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
return ret;
}
static int stmmac_setup_tc_block(struct stmmac_priv *priv,
struct tc_block_offload *f)
{
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, stmmac_setup_tc_block_cb,
priv, priv, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, stmmac_setup_tc_block_cb, priv);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void *type_data)
{
@ -3794,7 +3776,9 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
return stmmac_setup_tc_block(priv, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
stmmac_setup_tc_block_cb,
priv, priv, true);
case TC_SETUP_QDISC_CBS:
return stmmac_tc_setup_cbs(priv, priv, type_data);
default:

View File

@ -78,26 +78,6 @@ nsim_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
return nsim_bpf_setup_tc_block_cb(type, type_data, cb_priv);
}
static int
nsim_setup_tc_block(struct net_device *dev, struct tc_block_offload *f)
{
struct netdevsim *ns = netdev_priv(dev);
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, nsim_setup_tc_block_cb,
ns, ns, f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, nsim_setup_tc_block_cb, ns);
return 0;
default:
return -EOPNOTSUPP;
}
}
static int nsim_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
{
struct netdevsim *ns = netdev_priv(dev);
@ -226,9 +206,13 @@ static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state)
static int
nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
{
struct netdevsim *ns = netdev_priv(dev);
switch (type) {
case TC_SETUP_BLOCK:
return nsim_setup_tc_block(dev, type_data);
return flow_block_cb_setup_simple(type_data, NULL,
nsim_setup_tc_block_cb,
ns, ns, true);
default:
return -EOPNOTSUPP;
}

View File

@ -3,6 +3,7 @@
#include <linux/kernel.h>
#include <net/flow_dissector.h>
#include <net/sch_generic.h>
struct flow_match {
struct flow_dissector *dissector;
@ -237,4 +238,30 @@ static inline void flow_stats_update(struct flow_stats *flow_stats,
flow_stats->lastused = max_t(u64, flow_stats->lastused, lastused);
}
enum flow_block_command {
TC_BLOCK_BIND,
TC_BLOCK_UNBIND,
};
enum flow_block_binder_type {
TCF_BLOCK_BINDER_TYPE_UNSPEC,
TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
};
struct tcf_block;
struct netlink_ext_ack;
struct flow_block_offload {
enum flow_block_command command;
enum flow_block_binder_type binder_type;
struct tcf_block *block;
struct list_head *driver_block_list;
struct netlink_ext_ack *extack;
};
int flow_block_cb_setup_simple(struct flow_block_offload *f,
struct list_head *driver_list, tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv, bool ingress_only);
#endif /* _NET_FLOW_OFFLOAD_H */

View File

@ -26,11 +26,9 @@ struct tcf_walker {
int register_tcf_proto_ops(struct tcf_proto_ops *ops);
int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
enum tcf_block_binder_type {
TCF_BLOCK_BINDER_TYPE_UNSPEC,
TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
};
#define tc_block_offload flow_block_offload
#define tc_block_command flow_block_command
#define tcf_block_binder_type flow_block_binder_type
struct tcf_block_ext_info {
enum tcf_block_binder_type binder_type;
@ -610,18 +608,6 @@ int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
void *type_data, bool err_stop);
unsigned int tcf_exts_num_actions(struct tcf_exts *exts);
enum tc_block_command {
TC_BLOCK_BIND,
TC_BLOCK_UNBIND,
};
struct tc_block_offload {
enum tc_block_command command;
enum tcf_block_binder_type binder_type;
struct tcf_block *block;
struct netlink_ext_ack *extack;
};
struct tc_cls_common_offload {
u32 chain_index;
__be16 protocol;

View File

@ -2,6 +2,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <net/flow_offload.h>
#include <net/pkt_cls.h>
struct flow_rule *flow_rule_alloc(unsigned int num_actions)
{
@ -164,3 +165,27 @@ void flow_rule_match_enc_opts(const struct flow_rule *rule,
FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_OPTS, out);
}
EXPORT_SYMBOL(flow_rule_match_enc_opts);
int flow_block_cb_setup_simple(struct flow_block_offload *f,
struct list_head *driver_block_list,
tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
bool ingress_only)
{
if (ingress_only &&
f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
f->driver_block_list = driver_block_list;
switch (f->command) {
case TC_BLOCK_BIND:
return tcf_block_cb_register(f->block, cb, cb_ident, cb_priv,
f->extack);
case TC_BLOCK_UNBIND:
tcf_block_cb_unregister(f->block, cb, cb_ident);
return 0;
default:
return -EOPNOTSUPP;
}
}
EXPORT_SYMBOL(flow_block_cb_setup_simple);