Skip to content

Commit

Permalink
Merge branch 'net-sched-propagate-extack-to-cls-offloads-on-destroy-a…
Browse files Browse the repository at this point in the history
…nd-only-with-skip_sw'

Jakub Kicinski says:

====================
net: sched: propagate extack to cls offloads on destroy and only with skip_sw

This series some of Jiri's comments and the fact that today drivers
may produce extack even if there is no skip_sw flag (meaning the
driver failure is not really a problem), and warning messages will
only confuse the users.

First patch propagates extack to destroy as requested by Jiri, extack
is then propagated to the driver callback for each classifier.  I chose
not to provide the extack on error paths.  As a rule of thumb it seems
best to keep the extack of the condition which caused the error.  E.g.

     err = this_will_fail(arg, extack);
     if (err) {
        undo_things(arg, NULL /* don't pass extack */);
	return err;
     }

Note that NL_SET_ERR_MSG() will ignore the message if extack is NULL.
I was pondering whether we should make NL_SET_ERR_MSG() refuse to
overwrite the msg, but there seem to be cases in the tree where extack
is set like this:

     err = this_will_fail(arg, extack);
     if (err) {
        undo_things(arg, NULL /* don't pass extack */);
	NL_SET_ERR_MSG(extack, "extack is set after undo call :/");
	return err;
     }

I think not passing extack to undo calls is reasonable.

v2:
 - rename the temporary tc_cls_common_offload_init().
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 24, 2018
2 parents 46410c2 + c846adb commit 131f1ed
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 73 deletions.
24 changes: 12 additions & 12 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -605,17 +605,6 @@ struct tc_cls_common_offload {
struct netlink_ext_ack *extack;
};

static inline void
tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common,
const struct tcf_proto *tp,
struct netlink_ext_ack *extack)
{
cls_common->chain_index = tp->chain->index;
cls_common->protocol = tp->protocol;
cls_common->prio = tp->prio;
cls_common->extack = extack;
}

struct tc_cls_u32_knode {
struct tcf_exts *exts;
struct tc_u32_sel *sel;
Expand Down Expand Up @@ -694,6 +683,18 @@ static inline bool tc_in_hw(u32 flags)
return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false;
}

static inline void
tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common,
const struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack)
{
cls_common->chain_index = tp->chain->index;
cls_common->protocol = tp->protocol;
cls_common->prio = tp->prio;
if (tc_skip_sw(flags))
cls_common->extack = extack;
}

enum tc_fl_command {
TC_CLSFLOWER_REPLACE,
TC_CLSFLOWER_DESTROY,
Expand Down Expand Up @@ -736,7 +737,6 @@ struct tc_cls_bpf_offload {
struct bpf_prog *oldprog;
const char *name;
bool exts_integrated;
u32 gen_flags;
};

struct tc_mqprio_qopt_offload {
Expand Down
3 changes: 2 additions & 1 deletion include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ struct tcf_proto_ops {
const struct tcf_proto *,
struct tcf_result *);
int (*init)(struct tcf_proto*);
void (*destroy)(struct tcf_proto*);
void (*destroy)(struct tcf_proto *tp,
struct netlink_ext_ack *extack);

void* (*get)(struct tcf_proto*, u32 handle);
int (*change)(struct net *net, struct sk_buff *,
Expand Down
15 changes: 8 additions & 7 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,10 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
return ERR_PTR(err);
}

static void tcf_proto_destroy(struct tcf_proto *tp)
static void tcf_proto_destroy(struct tcf_proto *tp,
struct netlink_ext_ack *extack)
{
tp->ops->destroy(tp);
tp->ops->destroy(tp, extack);
module_put(tp->ops->owner);
kfree_rcu(tp, rcu);
}
Expand Down Expand Up @@ -223,7 +224,7 @@ static void tcf_chain_flush(struct tcf_chain *chain)
tcf_chain_head_change(chain, NULL);
while (tp) {
RCU_INIT_POINTER(chain->filter_chain, tp->next);
tcf_proto_destroy(tp);
tcf_proto_destroy(tp, NULL);
tp = rtnl_dereference(chain->filter_chain);
tcf_chain_put(chain);
}
Expand Down Expand Up @@ -1182,7 +1183,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
tcf_chain_tp_remove(chain, &chain_info, tp);
tfilter_notify(net, skb, n, tp, block, q, parent, fh,
RTM_DELTFILTER, false);
tcf_proto_destroy(tp);
tcf_proto_destroy(tp, extack);
err = 0;
goto errout;
}
Expand All @@ -1200,7 +1201,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
case RTM_NEWTFILTER:
if (n->nlmsg_flags & NLM_F_EXCL) {
if (tp_created)
tcf_proto_destroy(tp);
tcf_proto_destroy(tp, NULL);
NL_SET_ERR_MSG(extack, "Filter already exists");
err = -EEXIST;
goto errout;
Expand All @@ -1214,7 +1215,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
goto errout;
if (last) {
tcf_chain_tp_remove(chain, &chain_info, tp);
tcf_proto_destroy(tp);
tcf_proto_destroy(tp, extack);
}
goto errout;
case RTM_GETTFILTER:
Expand All @@ -1240,7 +1241,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
RTM_NEWTFILTER, false);
} else {
if (tp_created)
tcf_proto_destroy(tp);
tcf_proto_destroy(tp, NULL);
}

errout:
Expand Down
2 changes: 1 addition & 1 deletion net/sched/cls_basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ static void basic_delete_filter(struct rcu_head *head)
tcf_queue_work(&f->work);
}

static void basic_destroy(struct tcf_proto *tp)
static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
{
struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f, *n;
Expand Down
24 changes: 13 additions & 11 deletions net/sched/cls_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,14 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
skip_sw = prog && tc_skip_sw(prog->gen_flags);
obj = prog ?: oldprog;

tc_cls_common_offload_init(&cls_bpf.common, tp, extack);
tc_cls_common_offload_init(&cls_bpf.common, tp, obj->gen_flags,
extack);
cls_bpf.command = TC_CLSBPF_OFFLOAD;
cls_bpf.exts = &obj->exts;
cls_bpf.prog = prog ? prog->filter : NULL;
cls_bpf.oldprog = oldprog ? oldprog->filter : NULL;
cls_bpf.name = obj->bpf_name;
cls_bpf.exts_integrated = obj->exts_integrated;
cls_bpf.gen_flags = obj->gen_flags;

if (oldprog)
tcf_block_offload_dec(block, &oldprog->gen_flags);
Expand Down Expand Up @@ -212,11 +212,12 @@ static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
}

static void cls_bpf_stop_offload(struct tcf_proto *tp,
struct cls_bpf_prog *prog)
struct cls_bpf_prog *prog,
struct netlink_ext_ack *extack)
{
int err;

err = cls_bpf_offload_cmd(tp, NULL, prog, NULL);
err = cls_bpf_offload_cmd(tp, NULL, prog, extack);
if (err)
pr_err("Stopping hardware offload failed: %d\n", err);
}
Expand All @@ -227,13 +228,12 @@ static void cls_bpf_offload_update_stats(struct tcf_proto *tp,
struct tcf_block *block = tp->chain->block;
struct tc_cls_bpf_offload cls_bpf = {};

tc_cls_common_offload_init(&cls_bpf.common, tp, NULL);
tc_cls_common_offload_init(&cls_bpf.common, tp, prog->gen_flags, NULL);
cls_bpf.command = TC_CLSBPF_STATS;
cls_bpf.exts = &prog->exts;
cls_bpf.prog = prog->filter;
cls_bpf.name = prog->bpf_name;
cls_bpf.exts_integrated = prog->exts_integrated;
cls_bpf.gen_flags = prog->gen_flags;

tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, false);
}
Expand Down Expand Up @@ -290,12 +290,13 @@ static void cls_bpf_delete_prog_rcu(struct rcu_head *rcu)
tcf_queue_work(&prog->work);
}

static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog)
static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog,
struct netlink_ext_ack *extack)
{
struct cls_bpf_head *head = rtnl_dereference(tp->root);

idr_remove_ext(&head->handle_idr, prog->handle);
cls_bpf_stop_offload(tp, prog);
cls_bpf_stop_offload(tp, prog, extack);
list_del_rcu(&prog->link);
tcf_unbind_filter(tp, &prog->res);
if (tcf_exts_get_net(&prog->exts))
Expand All @@ -309,18 +310,19 @@ static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
{
struct cls_bpf_head *head = rtnl_dereference(tp->root);

__cls_bpf_delete(tp, arg);
__cls_bpf_delete(tp, arg, extack);
*last = list_empty(&head->plist);
return 0;
}

static void cls_bpf_destroy(struct tcf_proto *tp)
static void cls_bpf_destroy(struct tcf_proto *tp,
struct netlink_ext_ack *extack)
{
struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *prog, *tmp;

list_for_each_entry_safe(prog, tmp, &head->plist, link)
__cls_bpf_delete(tp, prog);
__cls_bpf_delete(tp, prog, extack);

idr_destroy(&head->handle_idr);
kfree_rcu(head, rcu);
Expand Down
3 changes: 2 additions & 1 deletion net/sched/cls_cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
return err;
}

static void cls_cgroup_destroy(struct tcf_proto *tp)
static void cls_cgroup_destroy(struct tcf_proto *tp,
struct netlink_ext_ack *extack)
{
struct cls_cgroup_head *head = rtnl_dereference(tp->root);

Expand Down
2 changes: 1 addition & 1 deletion net/sched/cls_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ static int flow_init(struct tcf_proto *tp)
return 0;
}

static void flow_destroy(struct tcf_proto *tp)
static void flow_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
{
struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *f, *next;
Expand Down
24 changes: 13 additions & 11 deletions net/sched/cls_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,13 @@ static void fl_destroy_filter(struct rcu_head *head)
tcf_queue_work(&f->work);
}

static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f,
struct netlink_ext_ack *extack)
{
struct tc_cls_flower_offload cls_flower = {};
struct tcf_block *block = tp->chain->block;

tc_cls_common_offload_init(&cls_flower.common, tp, NULL);
tc_cls_common_offload_init(&cls_flower.common, tp, f->flags, extack);
cls_flower.command = TC_CLSFLOWER_DESTROY;
cls_flower.cookie = (unsigned long) f;

Expand All @@ -243,7 +244,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
bool skip_sw = tc_skip_sw(f->flags);
int err;

tc_cls_common_offload_init(&cls_flower.common, tp, extack);
tc_cls_common_offload_init(&cls_flower.common, tp, f->flags, extack);
cls_flower.command = TC_CLSFLOWER_REPLACE;
cls_flower.cookie = (unsigned long) f;
cls_flower.dissector = dissector;
Expand All @@ -255,7 +256,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
err = tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, skip_sw);
if (err < 0) {
fl_hw_destroy_filter(tp, f);
fl_hw_destroy_filter(tp, f, NULL);
return err;
} else if (err > 0) {
tcf_block_offload_inc(block, &f->flags);
Expand All @@ -272,7 +273,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
struct tc_cls_flower_offload cls_flower = {};
struct tcf_block *block = tp->chain->block;

tc_cls_common_offload_init(&cls_flower.common, tp, NULL);
tc_cls_common_offload_init(&cls_flower.common, tp, f->flags, NULL);
cls_flower.command = TC_CLSFLOWER_STATS;
cls_flower.cookie = (unsigned long) f;
cls_flower.exts = &f->exts;
Expand All @@ -282,14 +283,15 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
&cls_flower, false);
}

static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)
static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
struct netlink_ext_ack *extack)
{
struct cls_fl_head *head = rtnl_dereference(tp->root);

idr_remove_ext(&head->handle_idr, f->handle);
list_del_rcu(&f->list);
if (!tc_skip_hw(f->flags))
fl_hw_destroy_filter(tp, f);
fl_hw_destroy_filter(tp, f, extack);
tcf_unbind_filter(tp, &f->res);
if (tcf_exts_get_net(&f->exts))
call_rcu(&f->rcu, fl_destroy_filter);
Expand All @@ -315,13 +317,13 @@ static void fl_destroy_rcu(struct rcu_head *rcu)
schedule_work(&head->work);
}

static void fl_destroy(struct tcf_proto *tp)
static void fl_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
{
struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *f, *next;

list_for_each_entry_safe(f, next, &head->filters, list)
__fl_delete(tp, f);
__fl_delete(tp, f, extack);
idr_destroy(&head->handle_idr);

__module_get(THIS_MODULE);
Expand Down Expand Up @@ -958,7 +960,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
rhashtable_remove_fast(&head->ht, &fold->ht_node,
head->ht_params);
if (!tc_skip_hw(fold->flags))
fl_hw_destroy_filter(tp, fold);
fl_hw_destroy_filter(tp, fold, NULL);
}

*arg = fnew;
Expand Down Expand Up @@ -997,7 +999,7 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
if (!tc_skip_sw(f->flags))
rhashtable_remove_fast(&head->ht, &f->ht_node,
head->ht_params);
__fl_delete(tp, f);
__fl_delete(tp, f, extack);
*last = list_empty(&head->filters);
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion net/sched/cls_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ static void fw_delete_filter(struct rcu_head *head)
tcf_queue_work(&f->work);
}

static void fw_destroy(struct tcf_proto *tp)
static void fw_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
{
struct fw_head *head = rtnl_dereference(tp->root);
struct fw_filter *f;
Expand Down
13 changes: 7 additions & 6 deletions net/sched/cls_matchall.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,13 @@ static void mall_destroy_rcu(struct rcu_head *rcu)

static void mall_destroy_hw_filter(struct tcf_proto *tp,
struct cls_mall_head *head,
unsigned long cookie)
unsigned long cookie,
struct netlink_ext_ack *extack)
{
struct tc_cls_matchall_offload cls_mall = {};
struct tcf_block *block = tp->chain->block;

tc_cls_common_offload_init(&cls_mall.common, tp, NULL);
tc_cls_common_offload_init(&cls_mall.common, tp, head->flags, extack);
cls_mall.command = TC_CLSMATCHALL_DESTROY;
cls_mall.cookie = cookie;

Expand All @@ -94,15 +95,15 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
bool skip_sw = tc_skip_sw(head->flags);
int err;

tc_cls_common_offload_init(&cls_mall.common, tp, extack);
tc_cls_common_offload_init(&cls_mall.common, tp, head->flags, extack);
cls_mall.command = TC_CLSMATCHALL_REPLACE;
cls_mall.exts = &head->exts;
cls_mall.cookie = cookie;

err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSMATCHALL,
&cls_mall, skip_sw);
if (err < 0) {
mall_destroy_hw_filter(tp, head, cookie);
mall_destroy_hw_filter(tp, head, cookie, NULL);
return err;
} else if (err > 0) {
tcf_block_offload_inc(block, &head->flags);
Expand All @@ -114,15 +115,15 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
return 0;
}

static void mall_destroy(struct tcf_proto *tp)
static void mall_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
{
struct cls_mall_head *head = rtnl_dereference(tp->root);

if (!head)
return;

if (!tc_skip_hw(head->flags))
mall_destroy_hw_filter(tp, head, (unsigned long) head);
mall_destroy_hw_filter(tp, head, (unsigned long) head, extack);

if (tcf_exts_get_net(&head->exts))
call_rcu(&head->rcu, mall_destroy_rcu);
Expand Down
2 changes: 1 addition & 1 deletion net/sched/cls_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ static void route4_delete_filter(struct rcu_head *head)
tcf_queue_work(&f->work);
}

static void route4_destroy(struct tcf_proto *tp)
static void route4_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
{
struct route4_head *head = rtnl_dereference(tp->root);
int h1, h2;
Expand Down
Loading

0 comments on commit 131f1ed

Please sign in to comment.