Messages in this thread Patch in this message | | | Subject | Re: [PATCH v8 net-next 06/13] flow_offload: allow user to offload tc action to net device | From | Eric Dumazet <> | Date | Mon, 20 Dec 2021 00:48:07 -0800 |
| |
On 12/17/21 10:16 AM, Simon Horman wrote: > From: Baowen Zheng <baowen.zheng@corigine.com> > > Use flow_indr_dev_register/flow_indr_dev_setup_offload to > offload tc action. > > We need to call tc_cleanup_flow_action to clean up tc action entry since > in tc_setup_action, some actions may hold dev refcnt, especially the mirror > action. > > Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com> > Signed-off-by: Louis Peens <louis.peens@corigine.com> > Signed-off-by: Simon Horman <simon.horman@corigine.com> > ---
Hi there.
I think this is causing the following syzbot splat, please take a look, thanks !
WARNING: suspicious RCU usage 5.16.0-rc5-syzkaller #0 Not tainted ----------------------------- include/net/tc_act/tc_tunnel_key.h:33 suspicious rcu_dereference_protected() usage!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1 1 lock held by syz-executor393/3602: #0: ffffffff8d313968 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock net/core/rtnetlink.c:72 [inline] #0: ffffffff8d313968 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock net/core/rtnetlink.c:72 [inline] net/core/rtnetlink.c:5567 #0: ffffffff8d313968 (rtnl_mutex){+.+.}-{3:3}, at: rtnetlink_rcv_msg+0x3be/0xb80 net/core/rtnetlink.c:5567 net/core/rtnetlink.c:5567
stack backtrace: CPU: 1 PID: 3602 Comm: syz-executor393 Not tainted 5.16.0-rc5-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] __dump_stack lib/dump_stack.c:88 [inline] lib/dump_stack.c:106 dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 lib/dump_stack.c:106 is_tcf_tunnel_set include/net/tc_act/tc_tunnel_key.h:33 [inline] is_tcf_tunnel_set include/net/tc_act/tc_tunnel_key.h:33 [inline] net/sched/act_tunnel_key.c:832 tcf_tunnel_key_offload_act_setup+0x4f2/0xa20 net/sched/act_tunnel_key.c:832 net/sched/act_tunnel_key.c:832 offload_action_init net/sched/act_api.c:194 [inline] offload_action_init net/sched/act_api.c:194 [inline] net/sched/act_api.c:263 tcf_action_offload_add_ex+0x279/0x550 net/sched/act_api.c:263 net/sched/act_api.c:263 tcf_action_offload_add net/sched/act_api.c:294 [inline] tcf_action_offload_add net/sched/act_api.c:294 [inline] net/sched/act_api.c:1439 tcf_action_init+0x601/0x860 net/sched/act_api.c:1439 net/sched/act_api.c:1439 tcf_action_add+0xf9/0x480 net/sched/act_api.c:1940 net/sched/act_api.c:1940 tc_ctl_action+0x346/0x470 net/sched/act_api.c:1999 net/sched/act_api.c:1999 rtnetlink_rcv_msg+0x413/0xb80 net/core/rtnetlink.c:5570 net/core/rtnetlink.c:5570 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2492 net/netlink/af_netlink.c:2492 netlink_unicast_kernel net/netlink/af_netlink.c:1315 [inline] netlink_unicast_kernel net/netlink/af_netlink.c:1315 [inline] net/netlink/af_netlink.c:1341 netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1341 net/netlink/af_netlink.c:1341 netlink_sendmsg+0x904/0xdf0 net/netlink/af_netlink.c:1917 net/netlink/af_netlink.c:1917 sock_sendmsg_nosec net/socket.c:704 [inline] sock_sendmsg_nosec net/socket.c:704 [inline] net/socket.c:724 sock_sendmsg+0xcf/0x120 net/socket.c:724 net/socket.c:724 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2409 net/socket.c:2409 ___sys_sendmsg+0xf3/0x170 net/socket.c:2463 net/socket.c:2463 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2492 net/socket.c:2492 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_x64 arch/x86/entry/common.c:50 [inline] arch/x86/entry/common.c:80 do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f896932b2a9 Code: 28 c3 e8 2a 14 00 00 66 2e 0f 1f 84 00 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffeff6cc4d8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f896932b2a9 RDX: 0000000000000000 RSI: 0000000020000300 RDI: 0000000000000003
> include/linux/netdevice.h | 1 + > include/net/flow_offload.h | 17 +++++++ > include/net/pkt_cls.h | 5 ++ > net/core/flow_offload.c | 42 +++++++++++++---- > net/sched/act_api.c | 93 ++++++++++++++++++++++++++++++++++++++ > net/sched/act_csum.c | 4 +- > net/sched/act_ct.c | 4 +- > net/sched/act_gact.c | 13 +++++- > net/sched/act_gate.c | 4 +- > net/sched/act_mirred.c | 13 +++++- > net/sched/act_mpls.c | 16 ++++++- > net/sched/act_police.c | 4 +- > net/sched/act_sample.c | 4 +- > net/sched/act_skbedit.c | 11 ++++- > net/sched/act_tunnel_key.c | 9 +++- > net/sched/act_vlan.c | 16 ++++++- > net/sched/cls_api.c | 21 +++++++-- > 17 files changed, 254 insertions(+), 23 deletions(-) > > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h > index a419718612c6..8b0bdeb4734e 100644 > --- a/include/linux/netdevice.h > +++ b/include/linux/netdevice.h > @@ -920,6 +920,7 @@ enum tc_setup_type { > TC_SETUP_QDISC_TBF, > TC_SETUP_QDISC_FIFO, > TC_SETUP_QDISC_HTB, > + TC_SETUP_ACT, > }; > > /* These structures hold the attributes of bpf state that are being passed > diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h > index 2271da5aa8ee..5b8c54eb7a6b 100644 > --- a/include/net/flow_offload.h > +++ b/include/net/flow_offload.h > @@ -551,6 +551,23 @@ struct flow_cls_offload { > u32 classid; > }; > > +enum offload_act_command { > + FLOW_ACT_REPLACE, > + FLOW_ACT_DESTROY, > + FLOW_ACT_STATS, > +}; > + > +struct flow_offload_action { > + struct netlink_ext_ack *extack; /* NULL in FLOW_ACT_STATS process*/ > + enum offload_act_command command; > + enum flow_action_id id; > + u32 index; > + struct flow_stats stats; > + struct flow_action action; > +}; > + > +struct flow_offload_action *offload_action_alloc(unsigned int num_actions); > + > static inline struct flow_rule * > flow_cls_offload_flow_rule(struct flow_cls_offload *flow_cmd) > { > diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h > index 5d4ff76d37e2..1bfb616ea759 100644 > --- a/include/net/pkt_cls.h > +++ b/include/net/pkt_cls.h > @@ -262,6 +262,9 @@ static inline void tcf_exts_put_net(struct tcf_exts *exts) > for (; 0; (void)(i), (void)(a), (void)(exts)) > #endif > > +#define tcf_act_for_each_action(i, a, actions) \ > + for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = actions[i]); i++) > + > static inline void > tcf_exts_stats_update(const struct tcf_exts *exts, > u64 bytes, u64 packets, u64 drops, u64 lastuse, > @@ -539,6 +542,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex) > int tc_setup_offload_action(struct flow_action *flow_action, > const struct tcf_exts *exts); > void tc_cleanup_offload_action(struct flow_action *flow_action); > +int tc_setup_action(struct flow_action *flow_action, > + struct tc_action *actions[]); > > int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, > void *type_data, bool err_stop, bool rtnl_held); > diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c > index 6beaea13564a..022c945817fa 100644 > --- a/net/core/flow_offload.c > +++ b/net/core/flow_offload.c > @@ -27,6 +27,26 @@ struct flow_rule *flow_rule_alloc(unsigned int num_actions) > } > EXPORT_SYMBOL(flow_rule_alloc); > > +struct flow_offload_action *offload_action_alloc(unsigned int num_actions) > +{ > + struct flow_offload_action *fl_action; > + int i; > + > + fl_action = kzalloc(struct_size(fl_action, action.entries, num_actions), > + GFP_KERNEL); > + if (!fl_action) > + return NULL; > + > + fl_action->action.num_entries = num_actions; > + /* Pre-fill each action hw_stats with DONT_CARE. > + * Caller can override this if it wants stats for a given action. > + */ > + for (i = 0; i < num_actions; i++) > + fl_action->action.entries[i].hw_stats = FLOW_ACTION_HW_STATS_DONT_CARE; > + > + return fl_action; > +} > + > #define FLOW_DISSECTOR_MATCH(__rule, __type, __out) \ > const struct flow_match *__m = &(__rule)->match; \ > struct flow_dissector *__d = (__m)->dissector; \ > @@ -549,19 +569,25 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch, > void (*cleanup)(struct flow_block_cb *block_cb)) > { > struct flow_indr_dev *this; > + u32 count = 0; > + int err; > > mutex_lock(&flow_indr_block_lock); > + if (bo) { > + if (bo->command == FLOW_BLOCK_BIND) > + indir_dev_add(data, dev, sch, type, cleanup, bo); > + else if (bo->command == FLOW_BLOCK_UNBIND) > + indir_dev_remove(data); > + } > > - if (bo->command == FLOW_BLOCK_BIND) > - indir_dev_add(data, dev, sch, type, cleanup, bo); > - else if (bo->command == FLOW_BLOCK_UNBIND) > - indir_dev_remove(data); > - > - list_for_each_entry(this, &flow_block_indr_dev_list, list) > - this->cb(dev, sch, this->cb_priv, type, bo, data, cleanup); > + list_for_each_entry(this, &flow_block_indr_dev_list, list) { > + err = this->cb(dev, sch, this->cb_priv, type, bo, data, cleanup); > + if (!err) > + count++; > + } > > mutex_unlock(&flow_indr_block_lock); > > - return list_empty(&bo->cb_list) ? -EOPNOTSUPP : 0; > + return (bo && list_empty(&bo->cb_list)) ? -EOPNOTSUPP : count; > } > EXPORT_SYMBOL(flow_indr_dev_setup_offload); > diff --git a/net/sched/act_api.c b/net/sched/act_api.c > index 3258da3d5bed..5c21401b0555 100644 > --- a/net/sched/act_api.c > +++ b/net/sched/act_api.c > @@ -19,8 +19,10 @@ > #include <net/sock.h> > #include <net/sch_generic.h> > #include <net/pkt_cls.h> > +#include <net/tc_act/tc_pedit.h> > #include <net/act_api.h> > #include <net/netlink.h> > +#include <net/flow_offload.h> > > #ifdef CONFIG_INET > DEFINE_STATIC_KEY_FALSE(tcf_frag_xmit_count); > @@ -129,8 +131,92 @@ static void free_tcf(struct tc_action *p) > kfree(p); > } > > +static unsigned int tcf_offload_act_num_actions_single(struct tc_action *act) > +{ > + if (is_tcf_pedit(act)) > + return tcf_pedit_nkeys(act); > + else > + return 1; > +} > + > +static int offload_action_init(struct flow_offload_action *fl_action, > + struct tc_action *act, > + enum offload_act_command cmd, > + struct netlink_ext_ack *extack) > +{ > + fl_action->extack = extack; > + fl_action->command = cmd; > + fl_action->index = act->tcfa_index; > + > + if (act->ops->offload_act_setup) > + return act->ops->offload_act_setup(act, fl_action, NULL, false); > + > + return -EOPNOTSUPP; > +} > + > +static int tcf_action_offload_cmd(struct flow_offload_action *fl_act, > + struct netlink_ext_ack *extack) > +{ > + int err; > + > + err = flow_indr_dev_setup_offload(NULL, NULL, TC_SETUP_ACT, > + fl_act, NULL, NULL); > + if (err < 0) > + return err; > + > + return 0; > +} > + > +/* offload the tc action after it is inserted */ > +static int tcf_action_offload_add(struct tc_action *action, > + struct netlink_ext_ack *extack) > +{ > + struct tc_action *actions[TCA_ACT_MAX_PRIO] = { > + [0] = action, > + }; > + struct flow_offload_action *fl_action; > + int num, err = 0; > + > + num = tcf_offload_act_num_actions_single(action); > + fl_action = offload_action_alloc(num); > + if (!fl_action) > + return -ENOMEM; > + > + err = offload_action_init(fl_action, action, FLOW_ACT_REPLACE, extack); > + if (err) > + goto fl_err; > + > + err = tc_setup_action(&fl_action->action, actions); > + if (err) { > + NL_SET_ERR_MSG_MOD(extack, > + "Failed to setup tc actions for offload\n"); > + goto fl_err; > + } > + > + err = tcf_action_offload_cmd(fl_action, extack); > + tc_cleanup_offload_action(&fl_action->action); > + > +fl_err: > + kfree(fl_action); > + > + return err; > +} > + > +static int tcf_action_offload_del(struct tc_action *action) > +{ > + struct flow_offload_action fl_act = {}; > + int err = 0; > + > + err = offload_action_init(&fl_act, action, FLOW_ACT_DESTROY, NULL); > + if (err) > + return err; > + > + return tcf_action_offload_cmd(&fl_act, NULL); > +} > + > static void tcf_action_cleanup(struct tc_action *p) > { > + tcf_action_offload_del(p); > if (p->ops->cleanup) > p->ops->cleanup(p); > > @@ -1061,6 +1147,11 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, > return ERR_PTR(err); > } > > +static bool tc_act_bind(u32 flags) > +{ > + return !!(flags & TCA_ACT_FLAGS_BIND); > +} > + > /* Returns numbers of initialized actions or negative error. */ > > int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, > @@ -1103,6 +1194,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, > sz += tcf_action_fill_size(act); > /* Start from index 0 */ > actions[i - 1] = act; > + if (!tc_act_bind(flags)) > + tcf_action_offload_add(act, extack); > } > > /* We have to commit them all together, because if any error happened in > diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c > index 4428852a03d7..e0f515b774ca 100644 > --- a/net/sched/act_csum.c > +++ b/net/sched/act_csum.c > @@ -705,7 +705,9 @@ static int tcf_csum_offload_act_setup(struct tc_action *act, void *entry_data, > entry->csum_flags = tcf_csum_update_flags(act); > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + fl_action->id = FLOW_ACTION_CSUM; > } > > return 0; > diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c > index dc64f31e5191..1c537913a189 100644 > --- a/net/sched/act_ct.c > +++ b/net/sched/act_ct.c > @@ -1505,7 +1505,9 @@ static int tcf_ct_offload_act_setup(struct tc_action *act, void *entry_data, > entry->ct.flow_table = tcf_ct_ft(act); > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + fl_action->id = FLOW_ACTION_CT; > } > > return 0; > diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c > index f77be22069f4..bde6a6c01e64 100644 > --- a/net/sched/act_gact.c > +++ b/net/sched/act_gact.c > @@ -272,7 +272,18 @@ static int tcf_gact_offload_act_setup(struct tc_action *act, void *entry_data, > } > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + if (is_tcf_gact_ok(act)) > + fl_action->id = FLOW_ACTION_ACCEPT; > + else if (is_tcf_gact_shot(act)) > + fl_action->id = FLOW_ACTION_DROP; > + else if (is_tcf_gact_trap(act)) > + fl_action->id = FLOW_ACTION_TRAP; > + else if (is_tcf_gact_goto_chain(act)) > + fl_action->id = FLOW_ACTION_GOTO; > + else > + return -EOPNOTSUPP; > } > > return 0; > diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c > index 1d8297497692..d56e73843a4b 100644 > --- a/net/sched/act_gate.c > +++ b/net/sched/act_gate.c > @@ -637,7 +637,9 @@ static int tcf_gate_offload_act_setup(struct tc_action *act, void *entry_data, > return err; > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + fl_action->id = FLOW_ACTION_GATE; > } > > return 0; > diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c > index 8eecf55be0a2..39acd1d18609 100644 > --- a/net/sched/act_mirred.c > +++ b/net/sched/act_mirred.c > @@ -482,7 +482,18 @@ static int tcf_mirred_offload_act_setup(struct tc_action *act, void *entry_data, > } > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + if (is_tcf_mirred_egress_redirect(act)) > + fl_action->id = FLOW_ACTION_REDIRECT; > + else if (is_tcf_mirred_egress_mirror(act)) > + fl_action->id = FLOW_ACTION_MIRRED; > + else if (is_tcf_mirred_ingress_redirect(act)) > + fl_action->id = FLOW_ACTION_REDIRECT_INGRESS; > + else if (is_tcf_mirred_ingress_mirror(act)) > + fl_action->id = FLOW_ACTION_MIRRED_INGRESS; > + else > + return -EOPNOTSUPP; > } > > return 0; > diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c > index a4615e1331e0..b9ff3459fdab 100644 > --- a/net/sched/act_mpls.c > +++ b/net/sched/act_mpls.c > @@ -415,7 +415,21 @@ static int tcf_mpls_offload_act_setup(struct tc_action *act, void *entry_data, > } > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + switch (tcf_mpls_action(act)) { > + case TCA_MPLS_ACT_PUSH: > + fl_action->id = FLOW_ACTION_MPLS_PUSH; > + break; > + case TCA_MPLS_ACT_POP: > + fl_action->id = FLOW_ACTION_MPLS_POP; > + break; > + case TCA_MPLS_ACT_MODIFY: > + fl_action->id = FLOW_ACTION_MPLS_MANGLE; > + break; > + default: > + return -EOPNOTSUPP; > + } > } > > return 0; > diff --git a/net/sched/act_police.c b/net/sched/act_police.c > index abb6d16a20b2..0923aa2b8f8a 100644 > --- a/net/sched/act_police.c > +++ b/net/sched/act_police.c > @@ -421,7 +421,9 @@ static int tcf_police_offload_act_setup(struct tc_action *act, void *entry_data, > entry->police.mtu = tcf_police_tcfp_mtu(act); > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + fl_action->id = FLOW_ACTION_POLICE; > } > > return 0; > diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c > index 07e56903211e..9a22cdda6bbd 100644 > --- a/net/sched/act_sample.c > +++ b/net/sched/act_sample.c > @@ -303,7 +303,9 @@ static int tcf_sample_offload_act_setup(struct tc_action *act, void *entry_data, > tcf_offload_sample_get_group(entry, act); > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + fl_action->id = FLOW_ACTION_SAMPLE; > } > > return 0; > diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c > index c380f9e6cc95..ceba11b198bb 100644 > --- a/net/sched/act_skbedit.c > +++ b/net/sched/act_skbedit.c > @@ -347,7 +347,16 @@ static int tcf_skbedit_offload_act_setup(struct tc_action *act, void *entry_data > } > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + if (is_tcf_skbedit_mark(act)) > + fl_action->id = FLOW_ACTION_MARK; > + else if (is_tcf_skbedit_ptype(act)) > + fl_action->id = FLOW_ACTION_PTYPE; > + else if (is_tcf_skbedit_priority(act)) > + fl_action->id = FLOW_ACTION_PRIORITY; > + else > + return -EOPNOTSUPP; > } > > return 0; > diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c > index e96a65a5323e..23aba03d26a8 100644 > --- a/net/sched/act_tunnel_key.c > +++ b/net/sched/act_tunnel_key.c > @@ -827,7 +827,14 @@ static int tcf_tunnel_key_offload_act_setup(struct tc_action *act, > } > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + if (is_tcf_tunnel_set(act)) > + fl_action->id = FLOW_ACTION_TUNNEL_ENCAP; > + else if (is_tcf_tunnel_release(act)) > + fl_action->id = FLOW_ACTION_TUNNEL_DECAP; > + else > + return -EOPNOTSUPP; > } > > return 0; > diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c > index 0300792084f0..756e2dcde1cd 100644 > --- a/net/sched/act_vlan.c > +++ b/net/sched/act_vlan.c > @@ -395,7 +395,21 @@ static int tcf_vlan_offload_act_setup(struct tc_action *act, void *entry_data, > } > *index_inc = 1; > } else { > - return -EOPNOTSUPP; > + struct flow_offload_action *fl_action = entry_data; > + > + switch (tcf_vlan_action(act)) { > + case TCA_VLAN_ACT_PUSH: > + fl_action->id = FLOW_ACTION_VLAN_PUSH; > + break; > + case TCA_VLAN_ACT_POP: > + fl_action->id = FLOW_ACTION_VLAN_POP; > + break; > + case TCA_VLAN_ACT_MODIFY: > + fl_action->id = FLOW_ACTION_VLAN_MANGLE; > + break; > + default: > + return -EOPNOTSUPP; > + } > } > > return 0; > diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c > index 53f263c9a725..353e1eed48be 100644 > --- a/net/sched/cls_api.c > +++ b/net/sched/cls_api.c > @@ -3488,8 +3488,8 @@ static int tc_setup_offload_act(struct tc_action *act, > #endif > } > > -int tc_setup_offload_action(struct flow_action *flow_action, > - const struct tcf_exts *exts) > +int tc_setup_action(struct flow_action *flow_action, > + struct tc_action *actions[]) > { > int i, j, index, err = 0; > struct tc_action *act; > @@ -3498,11 +3498,11 @@ int tc_setup_offload_action(struct flow_action *flow_action, > BUILD_BUG_ON(TCA_ACT_HW_STATS_IMMEDIATE != FLOW_ACTION_HW_STATS_IMMEDIATE); > BUILD_BUG_ON(TCA_ACT_HW_STATS_DELAYED != FLOW_ACTION_HW_STATS_DELAYED); > > - if (!exts) > + if (!actions) > return 0; > > j = 0; > - tcf_exts_for_each_action(i, act, exts) { > + tcf_act_for_each_action(i, act, actions) { > struct flow_action_entry *entry; > > entry = &flow_action->entries[j]; > @@ -3531,6 +3531,19 @@ int tc_setup_offload_action(struct flow_action *flow_action, > spin_unlock_bh(&act->tcfa_lock); > goto err_out; > } > + > +int tc_setup_offload_action(struct flow_action *flow_action, > + const struct tcf_exts *exts) > +{ > +#ifdef CONFIG_NET_CLS_ACT > + if (!exts) > + return 0; > + > + return tc_setup_action(flow_action, exts->actions); > +#else > + return 0; > +#endif > +} > EXPORT_SYMBOL(tc_setup_offload_action); > > unsigned int tcf_exts_num_actions(struct tcf_exts *exts)
| |