[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <3d678d71-cc44-1824-7b9b-c12482078be6@gmail.com>
Date: Mon, 20 Dec 2021 00:48:07 -0800
From: Eric Dumazet <eric.dumazet@...il.com>
To: Simon Horman <simon.horman@...igine.com>,
David Miller <davem@...emloft.net>,
Jakub Kicinski <kuba@...nel.org>
Cc: Alexandre Belloni <alexandre.belloni@...tlin.com>,
Andrew Lunn <andrew@...n.ch>,
Claudiu Manoil <claudiu.manoil@....com>,
Cong Wang <xiyou.wangcong@...il.com>,
Florian Fainelli <f.fainelli@...il.com>,
Ido Schimmel <idosch@...dia.com>,
Jamal Hadi Salim <jhs@...atatu.com>,
Jiri Pirko <jiri@...nulli.us>,
Leon Romanovsky <leon@...nel.org>,
Michael Chan <michael.chan@...adcom.com>,
Oz Shlomo <ozsh@...dia.com>, Petr Machata <petrm@...dia.com>,
Roi Dayan <roid@...dia.com>,
Saeed Mahameed <saeedm@...dia.com>,
Vivien Didelot <vivien.didelot@...il.com>,
Vlad Buslov <vladbu@...dia.com>,
Vladimir Oltean <vladimir.oltean@....com>,
Baowen Zheng <baowen.zheng@...igine.com>,
Louis Peens <louis.peens@...igine.com>,
UNGLinuxDriver@...rochip.com, linux-kernel@...r.kernel.org,
linux-rdma@...r.kernel.org, netdev@...r.kernel.org,
oss-drivers@...igine.com
Subject: Re: [PATCH v8 net-next 06/13] flow_offload: allow user to offload tc
action to net device
On 12/17/21 10:16 AM, Simon Horman wrote:
> From: Baowen Zheng <baowen.zheng@...igine.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@...igine.com>
> Signed-off-by: Louis Peens <louis.peens@...igine.com>
> Signed-off-by: Simon Horman <simon.horman@...igine.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)
Powered by blists - more mailing lists