Skip to content

Commit

Permalink
Merge branch 'net-tc-indirect-block-relay'
Browse files Browse the repository at this point in the history
John Hurley says:

====================
Ensure egress un/bind are relayed with indirect blocks

On register and unregister for indirect blocks, a command is called that
sends a bind/unbind event to the registering driver. This command assumes
that the bind to indirect block will be on ingress. However, drivers such
as NFP have allowed binding to clsact qdiscs as well as ingress qdiscs
from mainline Linux 5.2. A clsact qdisc binds to an ingress and an egress
block.

Rather than assuming that an indirect bind is always ingress, modify the
function names to remove the ingress tag (patch 1). In cls_api, which is
used by NFP to offload TC flower, generate bind/unbind message for both
ingress and egress blocks on the event of indirectly
registering/unregistering from that block. Doing so mimics the behaviour
of both ingress and clsact qdiscs on initialise and destroy.

This now ensures that drivers such as NFP receive the correct binder type
for the indirect block registration.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Dec 7, 2019
2 parents e0b6090 + 25a443f commit 9a74542
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 53 deletions.
15 changes: 7 additions & 8 deletions include/net/flow_offload.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,19 +380,18 @@ static inline void flow_block_init(struct flow_block *flow_block)
typedef int flow_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv,
enum tc_setup_type type, void *type_data);

typedef void flow_indr_block_ing_cmd_t(struct net_device *dev,
flow_indr_block_bind_cb_t *cb,
void *cb_priv,
enum flow_block_command command);
typedef void flow_indr_block_cmd_t(struct net_device *dev,
flow_indr_block_bind_cb_t *cb, void *cb_priv,
enum flow_block_command command);

struct flow_indr_block_ing_entry {
flow_indr_block_ing_cmd_t *cb;
struct flow_indr_block_entry {
flow_indr_block_cmd_t *cb;
struct list_head list;
};

void flow_indr_add_block_ing_cb(struct flow_indr_block_ing_entry *entry);
void flow_indr_add_block_cb(struct flow_indr_block_entry *entry);

void flow_indr_del_block_ing_cb(struct flow_indr_block_ing_entry *entry);
void flow_indr_del_block_cb(struct flow_indr_block_entry *entry);

int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv,
flow_indr_block_bind_cb_t *cb,
Expand Down
45 changes: 22 additions & 23 deletions net/core/flow_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
}
EXPORT_SYMBOL(flow_block_cb_setup_simple);

static LIST_HEAD(block_ing_cb_list);
static LIST_HEAD(block_cb_list);

static struct rhashtable indr_setup_block_ht;

Expand Down Expand Up @@ -391,20 +391,19 @@ static void flow_indr_block_cb_del(struct flow_indr_block_cb *indr_block_cb)
kfree(indr_block_cb);
}

static DEFINE_MUTEX(flow_indr_block_ing_cb_lock);
static DEFINE_MUTEX(flow_indr_block_cb_lock);

static void flow_block_ing_cmd(struct net_device *dev,
flow_indr_block_bind_cb_t *cb,
void *cb_priv,
enum flow_block_command command)
static void flow_block_cmd(struct net_device *dev,
flow_indr_block_bind_cb_t *cb, void *cb_priv,
enum flow_block_command command)
{
struct flow_indr_block_ing_entry *entry;
struct flow_indr_block_entry *entry;

mutex_lock(&flow_indr_block_ing_cb_lock);
list_for_each_entry(entry, &block_ing_cb_list, list) {
mutex_lock(&flow_indr_block_cb_lock);
list_for_each_entry(entry, &block_cb_list, list) {
entry->cb(dev, cb, cb_priv, command);
}
mutex_unlock(&flow_indr_block_ing_cb_lock);
mutex_unlock(&flow_indr_block_cb_lock);
}

int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv,
Expand All @@ -424,8 +423,8 @@ int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv,
if (err)
goto err_dev_put;

flow_block_ing_cmd(dev, indr_block_cb->cb, indr_block_cb->cb_priv,
FLOW_BLOCK_BIND);
flow_block_cmd(dev, indr_block_cb->cb, indr_block_cb->cb_priv,
FLOW_BLOCK_BIND);

return 0;

Expand Down Expand Up @@ -464,8 +463,8 @@ void __flow_indr_block_cb_unregister(struct net_device *dev,
if (!indr_block_cb)
return;

flow_block_ing_cmd(dev, indr_block_cb->cb, indr_block_cb->cb_priv,
FLOW_BLOCK_UNBIND);
flow_block_cmd(dev, indr_block_cb->cb, indr_block_cb->cb_priv,
FLOW_BLOCK_UNBIND);

flow_indr_block_cb_del(indr_block_cb);
flow_indr_block_dev_put(indr_dev);
Expand Down Expand Up @@ -499,21 +498,21 @@ void flow_indr_block_call(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(flow_indr_block_call);

void flow_indr_add_block_ing_cb(struct flow_indr_block_ing_entry *entry)
void flow_indr_add_block_cb(struct flow_indr_block_entry *entry)
{
mutex_lock(&flow_indr_block_ing_cb_lock);
list_add_tail(&entry->list, &block_ing_cb_list);
mutex_unlock(&flow_indr_block_ing_cb_lock);
mutex_lock(&flow_indr_block_cb_lock);
list_add_tail(&entry->list, &block_cb_list);
mutex_unlock(&flow_indr_block_cb_lock);
}
EXPORT_SYMBOL_GPL(flow_indr_add_block_ing_cb);
EXPORT_SYMBOL_GPL(flow_indr_add_block_cb);

void flow_indr_del_block_ing_cb(struct flow_indr_block_ing_entry *entry)
void flow_indr_del_block_cb(struct flow_indr_block_entry *entry)
{
mutex_lock(&flow_indr_block_ing_cb_lock);
mutex_lock(&flow_indr_block_cb_lock);
list_del(&entry->list);
mutex_unlock(&flow_indr_block_ing_cb_lock);
mutex_unlock(&flow_indr_block_cb_lock);
}
EXPORT_SYMBOL_GPL(flow_indr_del_block_ing_cb);
EXPORT_SYMBOL_GPL(flow_indr_del_block_cb);

static int __init init_flow_indr_rhashtable(void)
{
Expand Down
6 changes: 3 additions & 3 deletions net/netfilter/nf_tables_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ static int nft_offload_netdev_event(struct notifier_block *this,
return NOTIFY_DONE;
}

static struct flow_indr_block_ing_entry block_ing_entry = {
static struct flow_indr_block_entry block_ing_entry = {
.cb = nft_indr_block_cb,
.list = LIST_HEAD_INIT(block_ing_entry.list),
};
Expand All @@ -605,13 +605,13 @@ int nft_offload_init(void)
if (err < 0)
return err;

flow_indr_add_block_ing_cb(&block_ing_entry);
flow_indr_add_block_cb(&block_ing_entry);

return 0;
}

void nft_offload_exit(void)
{
flow_indr_del_block_ing_cb(&block_ing_entry);
flow_indr_del_block_cb(&block_ing_entry);
unregister_netdevice_notifier(&nft_offload_netdev_notifier);
}
52 changes: 33 additions & 19 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,15 +626,15 @@ static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held)
static int tcf_block_setup(struct tcf_block *block,
struct flow_block_offload *bo);

static void tc_indr_block_ing_cmd(struct net_device *dev,
struct tcf_block *block,
flow_indr_block_bind_cb_t *cb,
void *cb_priv,
enum flow_block_command command)
static void tc_indr_block_cmd(struct net_device *dev, struct tcf_block *block,
flow_indr_block_bind_cb_t *cb, void *cb_priv,
enum flow_block_command command, bool ingress)
{
struct flow_block_offload bo = {
.command = command,
.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
.binder_type = ingress ?
FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS :
FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
.net = dev_net(dev),
.block_shared = tcf_block_non_null_shared(block),
};
Expand All @@ -652,9 +652,10 @@ static void tc_indr_block_ing_cmd(struct net_device *dev,
up_write(&block->cb_lock);
}

static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
static struct tcf_block *tc_dev_block(struct net_device *dev, bool ingress)
{
const struct Qdisc_class_ops *cops;
const struct Qdisc_ops *ops;
struct Qdisc *qdisc;

if (!dev_ingress_queue(dev))
Expand All @@ -664,24 +665,37 @@ static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
if (!qdisc)
return NULL;

cops = qdisc->ops->cl_ops;
ops = qdisc->ops;
if (!ops)
return NULL;

if (!ingress && !strcmp("ingress", ops->id))
return NULL;

cops = ops->cl_ops;
if (!cops)
return NULL;

if (!cops->tcf_block)
return NULL;

return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
return cops->tcf_block(qdisc,
ingress ? TC_H_MIN_INGRESS : TC_H_MIN_EGRESS,
NULL);
}

static void tc_indr_block_get_and_ing_cmd(struct net_device *dev,
flow_indr_block_bind_cb_t *cb,
void *cb_priv,
enum flow_block_command command)
static void tc_indr_block_get_and_cmd(struct net_device *dev,
flow_indr_block_bind_cb_t *cb,
void *cb_priv,
enum flow_block_command command)
{
struct tcf_block *block = tc_dev_ingress_block(dev);
struct tcf_block *block;

block = tc_dev_block(dev, true);
tc_indr_block_cmd(dev, block, cb, cb_priv, command, true);

tc_indr_block_ing_cmd(dev, block, cb, cb_priv, command);
block = tc_dev_block(dev, false);
tc_indr_block_cmd(dev, block, cb, cb_priv, command, false);
}

static void tc_indr_block_call(struct tcf_block *block,
Expand Down Expand Up @@ -3626,9 +3640,9 @@ static struct pernet_operations tcf_net_ops = {
.size = sizeof(struct tcf_net),
};

static struct flow_indr_block_ing_entry block_ing_entry = {
.cb = tc_indr_block_get_and_ing_cmd,
.list = LIST_HEAD_INIT(block_ing_entry.list),
static struct flow_indr_block_entry block_entry = {
.cb = tc_indr_block_get_and_cmd,
.list = LIST_HEAD_INIT(block_entry.list),
};

static int __init tc_filter_init(void)
Expand All @@ -3643,7 +3657,7 @@ static int __init tc_filter_init(void)
if (err)
goto err_register_pernet_subsys;

flow_indr_add_block_ing_cb(&block_ing_entry);
flow_indr_add_block_cb(&block_entry);

rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL,
RTNL_FLAG_DOIT_UNLOCKED);
Expand Down

0 comments on commit 9a74542

Please sign in to comment.