.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * net/sched/act_skbmod.c skb data modifier |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2016 Jamal Hadi Salim <jhs@mojatatu.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
10 | 6 | */ |
---|
11 | 7 | |
---|
12 | 8 | #include <linux/module.h> |
---|
.. | .. |
---|
17 | 13 | #include <linux/rtnetlink.h> |
---|
18 | 14 | #include <net/netlink.h> |
---|
19 | 15 | #include <net/pkt_sched.h> |
---|
| 16 | +#include <net/pkt_cls.h> |
---|
20 | 17 | |
---|
21 | 18 | #include <linux/tc_act/tc_skbmod.h> |
---|
22 | 19 | #include <net/tc_act/tc_skbmod.h> |
---|
.. | .. |
---|
86 | 83 | static int tcf_skbmod_init(struct net *net, struct nlattr *nla, |
---|
87 | 84 | struct nlattr *est, struct tc_action **a, |
---|
88 | 85 | int ovr, int bind, bool rtnl_held, |
---|
| 86 | + struct tcf_proto *tp, u32 flags, |
---|
89 | 87 | struct netlink_ext_ack *extack) |
---|
90 | 88 | { |
---|
91 | 89 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); |
---|
92 | 90 | struct nlattr *tb[TCA_SKBMOD_MAX + 1]; |
---|
93 | 91 | struct tcf_skbmod_params *p, *p_old; |
---|
| 92 | + struct tcf_chain *goto_ch = NULL; |
---|
94 | 93 | struct tc_skbmod *parm; |
---|
95 | 94 | u32 lflags = 0, index; |
---|
96 | 95 | struct tcf_skbmod *d; |
---|
.. | .. |
---|
103 | 102 | if (!nla) |
---|
104 | 103 | return -EINVAL; |
---|
105 | 104 | |
---|
106 | | - err = nla_parse_nested(tb, TCA_SKBMOD_MAX, nla, skbmod_policy, NULL); |
---|
| 105 | + err = nla_parse_nested_deprecated(tb, TCA_SKBMOD_MAX, nla, |
---|
| 106 | + skbmod_policy, NULL); |
---|
107 | 107 | if (err < 0) |
---|
108 | 108 | return err; |
---|
109 | 109 | |
---|
.. | .. |
---|
147 | 147 | |
---|
148 | 148 | if (!exists) { |
---|
149 | 149 | ret = tcf_idr_create(tn, index, est, a, |
---|
150 | | - &act_skbmod_ops, bind, true); |
---|
| 150 | + &act_skbmod_ops, bind, true, flags); |
---|
151 | 151 | if (ret) { |
---|
152 | 152 | tcf_idr_cleanup(tn, index); |
---|
153 | 153 | return ret; |
---|
.. | .. |
---|
158 | 158 | tcf_idr_release(*a, bind); |
---|
159 | 159 | return -EEXIST; |
---|
160 | 160 | } |
---|
| 161 | + err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); |
---|
| 162 | + if (err < 0) |
---|
| 163 | + goto release_idr; |
---|
161 | 164 | |
---|
162 | 165 | d = to_skbmod(*a); |
---|
163 | 166 | |
---|
164 | 167 | p = kzalloc(sizeof(struct tcf_skbmod_params), GFP_KERNEL); |
---|
165 | 168 | if (unlikely(!p)) { |
---|
166 | | - tcf_idr_release(*a, bind); |
---|
167 | | - return -ENOMEM; |
---|
| 169 | + err = -ENOMEM; |
---|
| 170 | + goto put_chain; |
---|
168 | 171 | } |
---|
169 | 172 | |
---|
170 | 173 | p->flags = lflags; |
---|
171 | | - d->tcf_action = parm->action; |
---|
172 | 174 | |
---|
173 | 175 | if (ovr) |
---|
174 | 176 | spin_lock_bh(&d->tcf_lock); |
---|
175 | 177 | /* Protected by tcf_lock if overwriting existing action. */ |
---|
| 178 | + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
---|
176 | 179 | p_old = rcu_dereference_protected(d->skbmod_p, 1); |
---|
177 | 180 | |
---|
178 | 181 | if (lflags & SKBMOD_F_DMAC) |
---|
.. | .. |
---|
188 | 191 | |
---|
189 | 192 | if (p_old) |
---|
190 | 193 | kfree_rcu(p_old, rcu); |
---|
| 194 | + if (goto_ch) |
---|
| 195 | + tcf_chain_put_by_act(goto_ch); |
---|
191 | 196 | |
---|
192 | | - if (ret == ACT_P_CREATED) |
---|
193 | | - tcf_idr_insert(tn, *a); |
---|
194 | 197 | return ret; |
---|
| 198 | +put_chain: |
---|
| 199 | + if (goto_ch) |
---|
| 200 | + tcf_chain_put_by_act(goto_ch); |
---|
| 201 | +release_idr: |
---|
| 202 | + tcf_idr_release(*a, bind); |
---|
| 203 | + return err; |
---|
195 | 204 | } |
---|
196 | 205 | |
---|
197 | 206 | static void tcf_skbmod_cleanup(struct tc_action *a) |
---|
.. | .. |
---|
256 | 265 | return tcf_generic_walker(tn, skb, cb, type, ops, extack); |
---|
257 | 266 | } |
---|
258 | 267 | |
---|
259 | | -static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index, |
---|
260 | | - struct netlink_ext_ack *extack) |
---|
| 268 | +static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index) |
---|
261 | 269 | { |
---|
262 | 270 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); |
---|
263 | 271 | |
---|
.. | .. |
---|
266 | 274 | |
---|
267 | 275 | static struct tc_action_ops act_skbmod_ops = { |
---|
268 | 276 | .kind = "skbmod", |
---|
269 | | - .type = TCA_ACT_SKBMOD, |
---|
| 277 | + .id = TCA_ACT_SKBMOD, |
---|
270 | 278 | .owner = THIS_MODULE, |
---|
271 | 279 | .act = tcf_skbmod_act, |
---|
272 | 280 | .dump = tcf_skbmod_dump, |
---|