Skip to content

Commit 25a443f

Browse files
jahurleydavem330
authored andcommitted
net: sched: allow indirect blocks to bind to clsact in TC
When a device is bound to a clsact qdisc, bind events are triggered to registered drivers for both ingress and egress. However, if a driver registers to such a device using the indirect block routines then it is assumed that it is only interested in ingress offload and so only replays ingress bind/unbind messages. The NFP driver supports the offload of some egress filters when registering to a block with qdisc of type clsact. However, on unregister, if the block is still active, it will not receive an unbind egress notification which can prevent proper cleanup of other registered callbacks. Modify the indirect block callback command in TC to send messages of ingress and/or egress bind depending on the qdisc in use. NFP currently supports egress offload for TC flower offload so the changes are only added to TC. Fixes: 4d12ba4 ("nfp: flower: allow offloading of matches on 'internal' ports") Signed-off-by: John Hurley <[email protected]> Acked-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent dbad340 commit 25a443f

File tree

1 file changed

+33
-19
lines changed

1 file changed

+33
-19
lines changed

net/sched/cls_api.c

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -626,15 +626,15 @@ static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held)
626626
static int tcf_block_setup(struct tcf_block *block,
627627
struct flow_block_offload *bo);
628628

629-
static void tc_indr_block_ing_cmd(struct net_device *dev,
630-
struct tcf_block *block,
631-
flow_indr_block_bind_cb_t *cb,
632-
void *cb_priv,
633-
enum flow_block_command command)
629+
static void tc_indr_block_cmd(struct net_device *dev, struct tcf_block *block,
630+
flow_indr_block_bind_cb_t *cb, void *cb_priv,
631+
enum flow_block_command command, bool ingress)
634632
{
635633
struct flow_block_offload bo = {
636634
.command = command,
637-
.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
635+
.binder_type = ingress ?
636+
FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS :
637+
FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
638638
.net = dev_net(dev),
639639
.block_shared = tcf_block_non_null_shared(block),
640640
};
@@ -652,9 +652,10 @@ static void tc_indr_block_ing_cmd(struct net_device *dev,
652652
up_write(&block->cb_lock);
653653
}
654654

655-
static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
655+
static struct tcf_block *tc_dev_block(struct net_device *dev, bool ingress)
656656
{
657657
const struct Qdisc_class_ops *cops;
658+
const struct Qdisc_ops *ops;
658659
struct Qdisc *qdisc;
659660

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

667-
cops = qdisc->ops->cl_ops;
668+
ops = qdisc->ops;
669+
if (!ops)
670+
return NULL;
671+
672+
if (!ingress && !strcmp("ingress", ops->id))
673+
return NULL;
674+
675+
cops = ops->cl_ops;
668676
if (!cops)
669677
return NULL;
670678

671679
if (!cops->tcf_block)
672680
return NULL;
673681

674-
return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
682+
return cops->tcf_block(qdisc,
683+
ingress ? TC_H_MIN_INGRESS : TC_H_MIN_EGRESS,
684+
NULL);
675685
}
676686

677-
static void tc_indr_block_get_and_ing_cmd(struct net_device *dev,
678-
flow_indr_block_bind_cb_t *cb,
679-
void *cb_priv,
680-
enum flow_block_command command)
687+
static void tc_indr_block_get_and_cmd(struct net_device *dev,
688+
flow_indr_block_bind_cb_t *cb,
689+
void *cb_priv,
690+
enum flow_block_command command)
681691
{
682-
struct tcf_block *block = tc_dev_ingress_block(dev);
692+
struct tcf_block *block;
693+
694+
block = tc_dev_block(dev, true);
695+
tc_indr_block_cmd(dev, block, cb, cb_priv, command, true);
683696

684-
tc_indr_block_ing_cmd(dev, block, cb, cb_priv, command);
697+
block = tc_dev_block(dev, false);
698+
tc_indr_block_cmd(dev, block, cb, cb_priv, command, false);
685699
}
686700

687701
static void tc_indr_block_call(struct tcf_block *block,
@@ -3626,9 +3640,9 @@ static struct pernet_operations tcf_net_ops = {
36263640
.size = sizeof(struct tcf_net),
36273641
};
36283642

3629-
static struct flow_indr_block_entry block_ing_entry = {
3630-
.cb = tc_indr_block_get_and_ing_cmd,
3631-
.list = LIST_HEAD_INIT(block_ing_entry.list),
3643+
static struct flow_indr_block_entry block_entry = {
3644+
.cb = tc_indr_block_get_and_cmd,
3645+
.list = LIST_HEAD_INIT(block_entry.list),
36323646
};
36333647

36343648
static int __init tc_filter_init(void)
@@ -3643,7 +3657,7 @@ static int __init tc_filter_init(void)
36433657
if (err)
36443658
goto err_register_pernet_subsys;
36453659

3646-
flow_indr_add_block_cb(&block_ing_entry);
3660+
flow_indr_add_block_cb(&block_entry);
36473661

36483662
rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL,
36493663
RTNL_FLAG_DOIT_UNLOCKED);

0 commit comments

Comments
 (0)