Commit 14bfb13f authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by David S. Miller

net: flow_offload: add flow_block structure and use it

This object stores the flow block callbacks that are attached to this
block. Update flow_block_cb_lookup() to take this new object.

This patch restores the block sharing feature.

Fixes: da3eeb90 ("net: flow_offload: add list handling functions")
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a7323311
...@@ -752,7 +752,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev, ...@@ -752,7 +752,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
if (!indr_priv) if (!indr_priv)
return -ENOENT; return -ENOENT;
block_cb = flow_block_cb_lookup(f, block_cb = flow_block_cb_lookup(f->block,
mlx5e_rep_indr_setup_block_cb, mlx5e_rep_indr_setup_block_cb,
indr_priv); indr_priv);
if (!block_cb) if (!block_cb)
......
...@@ -1604,7 +1604,8 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1604,7 +1604,8 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
bool register_block = false; bool register_block = false;
int err; int err;
block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower, block_cb = flow_block_cb_lookup(f->block,
mlxsw_sp_setup_tc_block_cb_flower,
mlxsw_sp); mlxsw_sp);
if (!block_cb) { if (!block_cb) {
acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net); acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net);
...@@ -1656,7 +1657,8 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1656,7 +1657,8 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
struct flow_block_cb *block_cb; struct flow_block_cb *block_cb;
int err; int err;
block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower, block_cb = flow_block_cb_lookup(f->block,
mlxsw_sp_setup_tc_block_cb_flower,
mlxsw_sp); mlxsw_sp);
if (!block_cb) if (!block_cb)
return; return;
...@@ -1717,7 +1719,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1717,7 +1719,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
case FLOW_BLOCK_UNBIND: case FLOW_BLOCK_UNBIND:
mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port, mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
f, ingress); f, ingress);
block_cb = flow_block_cb_lookup(f, cb, mlxsw_sp_port); block_cb = flow_block_cb_lookup(f->block, cb, mlxsw_sp_port);
if (!block_cb) if (!block_cb)
return -ENOENT; return -ENOENT;
......
...@@ -316,8 +316,8 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port, ...@@ -316,8 +316,8 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
return -EOPNOTSUPP; return -EOPNOTSUPP;
block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower, block_cb = flow_block_cb_lookup(f->block,
port); ocelot_setup_tc_block_cb_flower, port);
if (!block_cb) { if (!block_cb) {
port_block = ocelot_port_block_create(port); port_block = ocelot_port_block_create(port);
if (!port_block) if (!port_block)
...@@ -350,8 +350,8 @@ void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port, ...@@ -350,8 +350,8 @@ void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
{ {
struct flow_block_cb *block_cb; struct flow_block_cb *block_cb;
block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower, block_cb = flow_block_cb_lookup(f->block,
port); ocelot_setup_tc_block_cb_flower, port);
if (!block_cb) if (!block_cb)
return; return;
......
...@@ -169,7 +169,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port, ...@@ -169,7 +169,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
list_add_tail(&block_cb->driver_list, f->driver_block_list); list_add_tail(&block_cb->driver_list, f->driver_block_list);
return 0; return 0;
case FLOW_BLOCK_UNBIND: case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f, cb, port); block_cb = flow_block_cb_lookup(f->block, cb, port);
if (!block_cb) if (!block_cb)
return -ENOENT; return -ENOENT;
......
...@@ -1327,7 +1327,8 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev, ...@@ -1327,7 +1327,8 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
list_add_tail(&block_cb->driver_list, &nfp_block_cb_list); list_add_tail(&block_cb->driver_list, &nfp_block_cb_list);
return 0; return 0;
case FLOW_BLOCK_UNBIND: case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f, nfp_flower_setup_tc_block_cb, block_cb = flow_block_cb_lookup(f->block,
nfp_flower_setup_tc_block_cb,
repr); repr);
if (!block_cb) if (!block_cb)
return -ENOENT; return -ENOENT;
...@@ -1440,7 +1441,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app, ...@@ -1440,7 +1441,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
if (!cb_priv) if (!cb_priv)
return -ENOENT; return -ENOENT;
block_cb = flow_block_cb_lookup(f, block_cb = flow_block_cb_lookup(f->block,
nfp_flower_setup_indr_block_cb, nfp_flower_setup_indr_block_cb,
cb_priv); cb_priv);
if (!block_cb) if (!block_cb)
......
...@@ -249,6 +249,10 @@ enum flow_block_binder_type { ...@@ -249,6 +249,10 @@ enum flow_block_binder_type {
FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS, FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
}; };
struct flow_block {
struct list_head cb_list;
};
struct netlink_ext_ack; struct netlink_ext_ack;
struct flow_block_offload { struct flow_block_offload {
...@@ -256,6 +260,7 @@ struct flow_block_offload { ...@@ -256,6 +260,7 @@ struct flow_block_offload {
enum flow_block_binder_type binder_type; enum flow_block_binder_type binder_type;
bool block_shared; bool block_shared;
struct net *net; struct net *net;
struct flow_block *block;
struct list_head cb_list; struct list_head cb_list;
struct list_head *driver_block_list; struct list_head *driver_block_list;
struct netlink_ext_ack *extack; struct netlink_ext_ack *extack;
...@@ -280,7 +285,7 @@ struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb, ...@@ -280,7 +285,7 @@ struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
void (*release)(void *cb_priv)); void (*release)(void *cb_priv));
void flow_block_cb_free(struct flow_block_cb *block_cb); void flow_block_cb_free(struct flow_block_cb *block_cb);
struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *offload, struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
flow_setup_cb_t *cb, void *cb_ident); flow_setup_cb_t *cb, void *cb_ident);
void *flow_block_cb_priv(struct flow_block_cb *block_cb); void *flow_block_cb_priv(struct flow_block_cb *block_cb);
...@@ -337,4 +342,9 @@ flow_cls_offload_flow_rule(struct flow_cls_offload *flow_cmd) ...@@ -337,4 +342,9 @@ flow_cls_offload_flow_rule(struct flow_cls_offload *flow_cmd)
return flow_cmd->rule; return flow_cmd->rule;
} }
static inline void flow_block_init(struct flow_block *flow_block)
{
INIT_LIST_HEAD(&flow_block->cb_list);
}
#endif /* _NET_FLOW_OFFLOAD_H */ #endif /* _NET_FLOW_OFFLOAD_H */
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
#include <net/netfilter/nf_flow_table.h> #include <net/netfilter/nf_flow_table.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/flow_offload.h>
struct module; struct module;
...@@ -951,7 +952,7 @@ struct nft_stats { ...@@ -951,7 +952,7 @@ struct nft_stats {
* @stats: per-cpu chain stats * @stats: per-cpu chain stats
* @chain: the chain * @chain: the chain
* @dev_name: device name that this base chain is attached to (if any) * @dev_name: device name that this base chain is attached to (if any)
* @cb_list: list of flow block callbacks (for hardware offload) * @flow_block: flow block (for hardware offload)
*/ */
struct nft_base_chain { struct nft_base_chain {
struct nf_hook_ops ops; struct nf_hook_ops ops;
...@@ -961,7 +962,7 @@ struct nft_base_chain { ...@@ -961,7 +962,7 @@ struct nft_base_chain {
struct nft_stats __percpu *stats; struct nft_stats __percpu *stats;
struct nft_chain chain; struct nft_chain chain;
char dev_name[IFNAMSIZ]; char dev_name[IFNAMSIZ];
struct list_head cb_list; struct flow_block flow_block;
}; };
static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain) static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
......
...@@ -399,7 +399,7 @@ struct tcf_block { ...@@ -399,7 +399,7 @@ struct tcf_block {
refcount_t refcnt; refcount_t refcnt;
struct net *net; struct net *net;
struct Qdisc *q; struct Qdisc *q;
struct list_head cb_list; struct flow_block flow_block;
struct list_head owner_list; struct list_head owner_list;
bool keep_dst; bool keep_dst;
unsigned int offloadcnt; /* Number of oddloaded filters */ unsigned int offloadcnt; /* Number of oddloaded filters */
......
...@@ -193,12 +193,12 @@ void flow_block_cb_free(struct flow_block_cb *block_cb) ...@@ -193,12 +193,12 @@ void flow_block_cb_free(struct flow_block_cb *block_cb)
} }
EXPORT_SYMBOL(flow_block_cb_free); EXPORT_SYMBOL(flow_block_cb_free);
struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *f, struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
flow_setup_cb_t *cb, void *cb_ident) flow_setup_cb_t *cb, void *cb_ident)
{ {
struct flow_block_cb *block_cb; struct flow_block_cb *block_cb;
list_for_each_entry(block_cb, f->driver_block_list, driver_list) { list_for_each_entry(block_cb, &block->cb_list, list) {
if (block_cb->cb == cb && if (block_cb->cb == cb &&
block_cb->cb_ident == cb_ident) block_cb->cb_ident == cb_ident)
return block_cb; return block_cb;
...@@ -268,7 +268,7 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f, ...@@ -268,7 +268,7 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
list_add_tail(&block_cb->driver_list, driver_block_list); list_add_tail(&block_cb->driver_list, driver_block_list);
return 0; return 0;
case FLOW_BLOCK_UNBIND: case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f, cb, cb_ident); block_cb = flow_block_cb_lookup(f->block, cb, cb_ident);
if (!block_cb) if (!block_cb)
return -ENOENT; return -ENOENT;
......
...@@ -975,7 +975,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev, ...@@ -975,7 +975,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
list_add_tail(&block_cb->driver_list, &dsa_slave_block_cb_list); list_add_tail(&block_cb->driver_list, &dsa_slave_block_cb_list);
return 0; return 0;
case FLOW_BLOCK_UNBIND: case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f, cb, dev); block_cb = flow_block_cb_lookup(f->block, cb, dev);
if (!block_cb) if (!block_cb)
return -ENOENT; return -ENOENT;
......
...@@ -1662,7 +1662,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, ...@@ -1662,7 +1662,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
chain->flags |= NFT_BASE_CHAIN | flags; chain->flags |= NFT_BASE_CHAIN | flags;
basechain->policy = NF_ACCEPT; basechain->policy = NF_ACCEPT;
INIT_LIST_HEAD(&basechain->cb_list); flow_block_init(&basechain->flow_block);
} else { } else {
chain = kzalloc(sizeof(*chain), GFP_KERNEL); chain = kzalloc(sizeof(*chain), GFP_KERNEL);
if (chain == NULL) if (chain == NULL)
......
...@@ -116,7 +116,7 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain, ...@@ -116,7 +116,7 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain,
struct flow_block_cb *block_cb; struct flow_block_cb *block_cb;
int err; int err;
list_for_each_entry(block_cb, &basechain->cb_list, list) { list_for_each_entry(block_cb, &basechain->flow_block.cb_list, list) {
err = block_cb->cb(type, type_data, block_cb->cb_priv); err = block_cb->cb(type, type_data, block_cb->cb_priv);
if (err < 0) if (err < 0)
return err; return err;
...@@ -154,7 +154,7 @@ static int nft_flow_offload_rule(struct nft_trans *trans, ...@@ -154,7 +154,7 @@ static int nft_flow_offload_rule(struct nft_trans *trans,
static int nft_flow_offload_bind(struct flow_block_offload *bo, static int nft_flow_offload_bind(struct flow_block_offload *bo,
struct nft_base_chain *basechain) struct nft_base_chain *basechain)
{ {
list_splice(&bo->cb_list, &basechain->cb_list); list_splice(&bo->cb_list, &basechain->flow_block.cb_list);
return 0; return 0;
} }
...@@ -198,6 +198,7 @@ static int nft_flow_offload_chain(struct nft_trans *trans, ...@@ -198,6 +198,7 @@ static int nft_flow_offload_chain(struct nft_trans *trans,
return -EOPNOTSUPP; return -EOPNOTSUPP;
bo.command = cmd; bo.command = cmd;
bo.block = &basechain->flow_block;
bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
bo.extack = &extack; bo.extack = &extack;
INIT_LIST_HEAD(&bo.cb_list); INIT_LIST_HEAD(&bo.cb_list);
......
...@@ -691,6 +691,8 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev, ...@@ -691,6 +691,8 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
if (!indr_dev->block) if (!indr_dev->block)
return; return;
bo.block = &indr_dev->block->flow_block;
indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK, indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
&bo); &bo);
tcf_block_setup(indr_dev->block, &bo); tcf_block_setup(indr_dev->block, &bo);
...@@ -775,6 +777,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev, ...@@ -775,6 +777,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
.command = command, .command = command,
.binder_type = ei->binder_type, .binder_type = ei->binder_type,
.net = dev_net(dev), .net = dev_net(dev),
.block = &block->flow_block,
.block_shared = tcf_block_shared(block), .block_shared = tcf_block_shared(block),
.extack = extack, .extack = extack,
}; };
...@@ -810,6 +813,7 @@ static int tcf_block_offload_cmd(struct tcf_block *block, ...@@ -810,6 +813,7 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
bo.net = dev_net(dev); bo.net = dev_net(dev);
bo.command = command; bo.command = command;
bo.binder_type = ei->binder_type; bo.binder_type = ei->binder_type;
bo.block = &block->flow_block;
bo.block_shared = tcf_block_shared(block); bo.block_shared = tcf_block_shared(block);
bo.extack = extack; bo.extack = extack;
INIT_LIST_HEAD(&bo.cb_list); INIT_LIST_HEAD(&bo.cb_list);
...@@ -987,8 +991,8 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, ...@@ -987,8 +991,8 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
mutex_init(&block->lock); mutex_init(&block->lock);
flow_block_init(&block->flow_block);
INIT_LIST_HEAD(&block->chain_list); INIT_LIST_HEAD(&block->chain_list);
INIT_LIST_HEAD(&block->cb_list);
INIT_LIST_HEAD(&block->owner_list); INIT_LIST_HEAD(&block->owner_list);
INIT_LIST_HEAD(&block->chain0.filter_chain_list); INIT_LIST_HEAD(&block->chain0.filter_chain_list);
...@@ -1570,7 +1574,7 @@ static int tcf_block_bind(struct tcf_block *block, ...@@ -1570,7 +1574,7 @@ static int tcf_block_bind(struct tcf_block *block,
i++; i++;
} }
list_splice(&bo->cb_list, &block->cb_list); list_splice(&bo->cb_list, &block->flow_block.cb_list);
return 0; return 0;
...@@ -3156,7 +3160,7 @@ int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, ...@@ -3156,7 +3160,7 @@ int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
if (block->nooffloaddevcnt && err_stop) if (block->nooffloaddevcnt && err_stop)
return -EOPNOTSUPP; return -EOPNOTSUPP;
list_for_each_entry(block_cb, &block->cb_list, list) { list_for_each_entry(block_cb, &block->flow_block.cb_list, list) {
err = block_cb->cb(type, type_data, block_cb->cb_priv); err = block_cb->cb(type, type_data, block_cb->cb_priv);
if (err) { if (err) {
if (err_stop) if (err_stop)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment