forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/net/sched/act_pedit.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * net/sched/act_pedit.c Generic packet editor
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License
6
- * as published by the Free Software Foundation; either version
7
- * 2 of the License, or (at your option) any later version.
84 *
95 * Authors: Jamal Hadi Salim (2002-4)
106 */
....@@ -23,6 +19,7 @@
2319 #include <linux/tc_act/tc_pedit.h>
2420 #include <net/tc_act/tc_pedit.h>
2521 #include <uapi/linux/tc_act/tc_pedit.h>
22
+#include <net/pkt_cls.h>
2623
2724 static unsigned int pedit_net_id;
2825 static struct tc_action_ops act_pedit_ops;
....@@ -69,8 +66,9 @@
6966 goto err_out;
7067 }
7168
72
- err = nla_parse_nested(tb, TCA_PEDIT_KEY_EX_MAX, ka,
73
- pedit_key_ex_policy, NULL);
69
+ err = nla_parse_nested_deprecated(tb, TCA_PEDIT_KEY_EX_MAX,
70
+ ka, pedit_key_ex_policy,
71
+ NULL);
7472 if (err)
7573 goto err_out;
7674
....@@ -107,14 +105,15 @@
107105 static int tcf_pedit_key_ex_dump(struct sk_buff *skb,
108106 struct tcf_pedit_key_ex *keys_ex, int n)
109107 {
110
- struct nlattr *keys_start = nla_nest_start(skb, TCA_PEDIT_KEYS_EX);
108
+ struct nlattr *keys_start = nla_nest_start_noflag(skb,
109
+ TCA_PEDIT_KEYS_EX);
111110
112111 if (!keys_start)
113112 goto nla_failure;
114113 for (; n > 0; n--) {
115114 struct nlattr *key_start;
116115
117
- key_start = nla_nest_start(skb, TCA_PEDIT_KEY_EX);
116
+ key_start = nla_nest_start_noflag(skb, TCA_PEDIT_KEY_EX);
118117 if (!key_start)
119118 goto nla_failure;
120119
....@@ -138,17 +137,19 @@
138137 static int tcf_pedit_init(struct net *net, struct nlattr *nla,
139138 struct nlattr *est, struct tc_action **a,
140139 int ovr, int bind, bool rtnl_held,
140
+ struct tcf_proto *tp, u32 flags,
141141 struct netlink_ext_ack *extack)
142142 {
143143 struct tc_action_net *tn = net_generic(net, pedit_net_id);
144144 struct nlattr *tb[TCA_PEDIT_MAX + 1];
145
+ struct tcf_chain *goto_ch = NULL;
145146 struct tc_pedit_key *keys = NULL;
146147 struct tcf_pedit_key_ex *keys_ex;
147148 struct tc_pedit *parm;
148149 struct nlattr *pattr;
149150 struct tcf_pedit *p;
150151 int ret = 0, err;
151
- int ksize;
152
+ int i, ksize;
152153 u32 index;
153154
154155 if (!nla) {
....@@ -156,7 +157,8 @@
156157 return -EINVAL;
157158 }
158159
159
- err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, pedit_policy, NULL);
160
+ err = nla_parse_nested_deprecated(tb, TCA_PEDIT_MAX, nla,
161
+ pedit_policy, NULL);
160162 if (err < 0)
161163 return err;
162164
....@@ -187,7 +189,7 @@
187189 err = tcf_idr_check_alloc(tn, &index, a, bind);
188190 if (!err) {
189191 ret = tcf_idr_create(tn, index, est, a,
190
- &act_pedit_ops, bind, false);
192
+ &act_pedit_ops, bind, false, 0);
191193 if (ret) {
192194 tcf_idr_cleanup(tn, index);
193195 goto out_free;
....@@ -205,6 +207,11 @@
205207 goto out_free;
206208 }
207209
210
+ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
211
+ if (err < 0) {
212
+ ret = err;
213
+ goto out_release;
214
+ }
208215 p = to_pedit(*a);
209216 spin_lock_bh(&p->tcf_lock);
210217
....@@ -214,25 +221,44 @@
214221 if (!keys) {
215222 spin_unlock_bh(&p->tcf_lock);
216223 ret = -ENOMEM;
217
- goto out_release;
224
+ goto put_chain;
218225 }
219226 kfree(p->tcfp_keys);
220227 p->tcfp_keys = keys;
221228 p->tcfp_nkeys = parm->nkeys;
222229 }
223230 memcpy(p->tcfp_keys, parm->keys, ksize);
231
+ p->tcfp_off_max_hint = 0;
232
+ for (i = 0; i < p->tcfp_nkeys; ++i) {
233
+ u32 cur = p->tcfp_keys[i].off;
234
+
235
+ /* sanitize the shift value for any later use */
236
+ p->tcfp_keys[i].shift = min_t(size_t, BITS_PER_TYPE(int) - 1,
237
+ p->tcfp_keys[i].shift);
238
+
239
+ /* The AT option can read a single byte, we can bound the actual
240
+ * value with uchar max.
241
+ */
242
+ cur += (0xff & p->tcfp_keys[i].offmask) >> p->tcfp_keys[i].shift;
243
+
244
+ /* Each key touches 4 bytes starting from the computed offset */
245
+ p->tcfp_off_max_hint = max(p->tcfp_off_max_hint, cur + 4);
246
+ }
224247
225248 p->tcfp_flags = parm->flags;
226
- p->tcf_action = parm->action;
249
+ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
227250
228251 kfree(p->tcfp_keys_ex);
229252 p->tcfp_keys_ex = keys_ex;
230253
231254 spin_unlock_bh(&p->tcf_lock);
232
- if (ret == ACT_P_CREATED)
233
- tcf_idr_insert(tn, *a);
255
+ if (goto_ch)
256
+ tcf_chain_put_by_act(goto_ch);
234257 return ret;
235258
259
+put_chain:
260
+ if (goto_ch)
261
+ tcf_chain_put_by_act(goto_ch);
236262 out_release:
237263 tcf_idr_release(*a, bind);
238264 out_free:
....@@ -298,12 +324,17 @@
298324 struct tcf_result *res)
299325 {
300326 struct tcf_pedit *p = to_pedit(a);
327
+ u32 max_offset;
301328 int i;
302329
303
- if (skb_unclone(skb, GFP_ATOMIC))
304
- return p->tcf_action;
305
-
306330 spin_lock(&p->tcf_lock);
331
+
332
+ max_offset = (skb_transport_header_was_set(skb) ?
333
+ skb_transport_offset(skb) :
334
+ skb_network_offset(skb)) +
335
+ p->tcfp_off_max_hint;
336
+ if (skb_ensure_writable(skb, min(skb->len, max_offset)))
337
+ goto unlock;
307338
308339 tcf_lastuse_update(&p->tcf_tm);
309340
....@@ -393,8 +424,19 @@
393424 p->tcf_qstats.overlimits++;
394425 done:
395426 bstats_update(&p->tcf_bstats, skb);
427
+unlock:
396428 spin_unlock(&p->tcf_lock);
397429 return p->tcf_action;
430
+}
431
+
432
+static void tcf_pedit_stats_update(struct tc_action *a, u64 bytes, u64 packets,
433
+ u64 drops, u64 lastuse, bool hw)
434
+{
435
+ struct tcf_pedit *d = to_pedit(a);
436
+ struct tcf_t *tm = &d->tcf_tm;
437
+
438
+ tcf_action_update_stats(a, bytes, packets, drops, hw);
439
+ tm->lastuse = max_t(u64, tm->lastuse, lastuse);
398440 }
399441
400442 static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
....@@ -406,7 +448,7 @@
406448 struct tcf_t t;
407449 int s;
408450
409
- s = sizeof(*opt) + p->tcfp_nkeys * sizeof(struct tc_pedit_key);
451
+ s = struct_size(opt, keys, p->tcfp_nkeys);
410452
411453 /* netlink spinlocks held above us - must use ATOMIC */
412454 opt = kzalloc(s, GFP_ATOMIC);
....@@ -414,8 +456,7 @@
414456 return -ENOBUFS;
415457
416458 spin_lock_bh(&p->tcf_lock);
417
- memcpy(opt->keys, p->tcfp_keys,
418
- p->tcfp_nkeys * sizeof(struct tc_pedit_key));
459
+ memcpy(opt->keys, p->tcfp_keys, flex_array_size(opt, keys, p->tcfp_nkeys));
419460 opt->index = p->tcf_index;
420461 opt->nkeys = p->tcfp_nkeys;
421462 opt->flags = p->tcfp_flags;
....@@ -461,8 +502,7 @@
461502 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
462503 }
463504
464
-static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index,
465
- struct netlink_ext_ack *extack)
505
+static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index)
466506 {
467507 struct tc_action_net *tn = net_generic(net, pedit_net_id);
468508
....@@ -471,9 +511,10 @@
471511
472512 static struct tc_action_ops act_pedit_ops = {
473513 .kind = "pedit",
474
- .type = TCA_ACT_PEDIT,
514
+ .id = TCA_ID_PEDIT,
475515 .owner = THIS_MODULE,
476516 .act = tcf_pedit_act,
517
+ .stats_update = tcf_pedit_stats_update,
477518 .dump = tcf_pedit_dump,
478519 .cleanup = tcf_pedit_cleanup,
479520 .init = tcf_pedit_init,