.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Berkeley Packet Filter based traffic classifier |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * ematches. |
---|
7 | 8 | * |
---|
8 | 9 | * (C) 2013 Daniel Borkmann <dborkman@redhat.com> |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or modify |
---|
11 | | - * it under the terms of the GNU General Public License version 2 as |
---|
12 | | - * published by the Free Software Foundation. |
---|
13 | 10 | */ |
---|
14 | 11 | |
---|
15 | 12 | #include <linux/module.h> |
---|
.. | .. |
---|
157 | 154 | skip_sw = prog && tc_skip_sw(prog->gen_flags); |
---|
158 | 155 | obj = prog ?: oldprog; |
---|
159 | 156 | |
---|
160 | | - tc_cls_common_offload_init(&cls_bpf.common, tp, obj->gen_flags, |
---|
161 | | - extack); |
---|
| 157 | + tc_cls_common_offload_init(&cls_bpf.common, tp, obj->gen_flags, extack); |
---|
162 | 158 | cls_bpf.command = TC_CLSBPF_OFFLOAD; |
---|
163 | 159 | cls_bpf.exts = &obj->exts; |
---|
164 | 160 | cls_bpf.prog = prog ? prog->filter : NULL; |
---|
.. | .. |
---|
166 | 162 | cls_bpf.name = obj->bpf_name; |
---|
167 | 163 | cls_bpf.exts_integrated = obj->exts_integrated; |
---|
168 | 164 | |
---|
169 | | - if (oldprog) |
---|
170 | | - tcf_block_offload_dec(block, &oldprog->gen_flags); |
---|
| 165 | + if (oldprog && prog) |
---|
| 166 | + err = tc_setup_cb_replace(block, tp, TC_SETUP_CLSBPF, &cls_bpf, |
---|
| 167 | + skip_sw, &oldprog->gen_flags, |
---|
| 168 | + &oldprog->in_hw_count, |
---|
| 169 | + &prog->gen_flags, &prog->in_hw_count, |
---|
| 170 | + true); |
---|
| 171 | + else if (prog) |
---|
| 172 | + err = tc_setup_cb_add(block, tp, TC_SETUP_CLSBPF, &cls_bpf, |
---|
| 173 | + skip_sw, &prog->gen_flags, |
---|
| 174 | + &prog->in_hw_count, true); |
---|
| 175 | + else |
---|
| 176 | + err = tc_setup_cb_destroy(block, tp, TC_SETUP_CLSBPF, &cls_bpf, |
---|
| 177 | + skip_sw, &oldprog->gen_flags, |
---|
| 178 | + &oldprog->in_hw_count, true); |
---|
171 | 179 | |
---|
172 | | - err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw); |
---|
173 | | - if (prog) { |
---|
174 | | - if (err < 0) { |
---|
175 | | - cls_bpf_offload_cmd(tp, oldprog, prog, extack); |
---|
176 | | - return err; |
---|
177 | | - } else if (err > 0) { |
---|
178 | | - prog->in_hw_count = err; |
---|
179 | | - tcf_block_offload_inc(block, &prog->gen_flags); |
---|
180 | | - } |
---|
| 180 | + if (prog && err) { |
---|
| 181 | + cls_bpf_offload_cmd(tp, oldprog, prog, extack); |
---|
| 182 | + return err; |
---|
181 | 183 | } |
---|
182 | 184 | |
---|
183 | 185 | if (prog && skip_sw && !(prog->gen_flags & TCA_CLS_FLAGS_IN_HW)) |
---|
.. | .. |
---|
234 | 236 | cls_bpf.name = prog->bpf_name; |
---|
235 | 237 | cls_bpf.exts_integrated = prog->exts_integrated; |
---|
236 | 238 | |
---|
237 | | - tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, false); |
---|
| 239 | + tc_setup_cb_call(block, TC_SETUP_CLSBPF, &cls_bpf, false, true); |
---|
238 | 240 | } |
---|
239 | 241 | |
---|
240 | 242 | static int cls_bpf_init(struct tcf_proto *tp) |
---|
.. | .. |
---|
298 | 300 | } |
---|
299 | 301 | |
---|
300 | 302 | static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last, |
---|
301 | | - struct netlink_ext_ack *extack) |
---|
| 303 | + bool rtnl_held, struct netlink_ext_ack *extack) |
---|
302 | 304 | { |
---|
303 | 305 | struct cls_bpf_head *head = rtnl_dereference(tp->root); |
---|
304 | 306 | |
---|
.. | .. |
---|
307 | 309 | return 0; |
---|
308 | 310 | } |
---|
309 | 311 | |
---|
310 | | -static void cls_bpf_destroy(struct tcf_proto *tp, |
---|
| 312 | +static void cls_bpf_destroy(struct tcf_proto *tp, bool rtnl_held, |
---|
311 | 313 | struct netlink_ext_ack *extack) |
---|
312 | 314 | { |
---|
313 | 315 | struct cls_bpf_head *head = rtnl_dereference(tp->root); |
---|
.. | .. |
---|
417 | 419 | if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) |
---|
418 | 420 | return -EINVAL; |
---|
419 | 421 | |
---|
420 | | - ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, ovr, extack); |
---|
| 422 | + ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, ovr, true, |
---|
| 423 | + extack); |
---|
421 | 424 | if (ret < 0) |
---|
422 | 425 | return ret; |
---|
423 | 426 | |
---|
.. | .. |
---|
455 | 458 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, |
---|
456 | 459 | struct tcf_proto *tp, unsigned long base, |
---|
457 | 460 | u32 handle, struct nlattr **tca, |
---|
458 | | - void **arg, bool ovr, struct netlink_ext_ack *extack) |
---|
| 461 | + void **arg, bool ovr, bool rtnl_held, |
---|
| 462 | + struct netlink_ext_ack *extack) |
---|
459 | 463 | { |
---|
460 | 464 | struct cls_bpf_head *head = rtnl_dereference(tp->root); |
---|
461 | 465 | struct cls_bpf_prog *oldprog = *arg; |
---|
.. | .. |
---|
466 | 470 | if (tca[TCA_OPTIONS] == NULL) |
---|
467 | 471 | return -EINVAL; |
---|
468 | 472 | |
---|
469 | | - ret = nla_parse_nested(tb, TCA_BPF_MAX, tca[TCA_OPTIONS], bpf_policy, |
---|
470 | | - NULL); |
---|
| 473 | + ret = nla_parse_nested_deprecated(tb, TCA_BPF_MAX, tca[TCA_OPTIONS], |
---|
| 474 | + bpf_policy, NULL); |
---|
471 | 475 | if (ret < 0) |
---|
472 | 476 | return ret; |
---|
473 | 477 | |
---|
.. | .. |
---|
475 | 479 | if (!prog) |
---|
476 | 480 | return -ENOBUFS; |
---|
477 | 481 | |
---|
478 | | - ret = tcf_exts_init(&prog->exts, TCA_BPF_ACT, TCA_BPF_POLICE); |
---|
| 482 | + ret = tcf_exts_init(&prog->exts, net, TCA_BPF_ACT, TCA_BPF_POLICE); |
---|
479 | 483 | if (ret < 0) |
---|
480 | 484 | goto errout; |
---|
481 | 485 | |
---|
.. | .. |
---|
575 | 579 | } |
---|
576 | 580 | |
---|
577 | 581 | static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, void *fh, |
---|
578 | | - struct sk_buff *skb, struct tcmsg *tm) |
---|
| 582 | + struct sk_buff *skb, struct tcmsg *tm, bool rtnl_held) |
---|
579 | 583 | { |
---|
580 | 584 | struct cls_bpf_prog *prog = fh; |
---|
581 | 585 | struct nlattr *nest; |
---|
.. | .. |
---|
589 | 593 | |
---|
590 | 594 | cls_bpf_offload_update_stats(tp, prog); |
---|
591 | 595 | |
---|
592 | | - nest = nla_nest_start(skb, TCA_OPTIONS); |
---|
| 596 | + nest = nla_nest_start_noflag(skb, TCA_OPTIONS); |
---|
593 | 597 | if (nest == NULL) |
---|
594 | 598 | goto nla_put_failure; |
---|
595 | 599 | |
---|
.. | .. |
---|
640 | 644 | } |
---|
641 | 645 | } |
---|
642 | 646 | |
---|
643 | | -static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg) |
---|
| 647 | +static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg, |
---|
| 648 | + bool rtnl_held) |
---|
644 | 649 | { |
---|
645 | 650 | struct cls_bpf_head *head = rtnl_dereference(tp->root); |
---|
646 | 651 | struct cls_bpf_prog *prog; |
---|
.. | .. |
---|
657 | 662 | } |
---|
658 | 663 | } |
---|
659 | 664 | |
---|
660 | | -static int cls_bpf_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, |
---|
| 665 | +static int cls_bpf_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb, |
---|
661 | 666 | void *cb_priv, struct netlink_ext_ack *extack) |
---|
662 | 667 | { |
---|
663 | 668 | struct cls_bpf_head *head = rtnl_dereference(tp->root); |
---|
.. | .. |
---|
679 | 684 | cls_bpf.name = prog->bpf_name; |
---|
680 | 685 | cls_bpf.exts_integrated = prog->exts_integrated; |
---|
681 | 686 | |
---|
682 | | - err = cb(TC_SETUP_CLSBPF, &cls_bpf, cb_priv); |
---|
683 | | - if (err) { |
---|
684 | | - if (add && tc_skip_sw(prog->gen_flags)) |
---|
685 | | - return err; |
---|
686 | | - continue; |
---|
687 | | - } |
---|
688 | | - |
---|
689 | | - tc_cls_offload_cnt_update(block, &prog->in_hw_count, |
---|
690 | | - &prog->gen_flags, add); |
---|
| 687 | + err = tc_setup_cb_reoffload(block, tp, add, cb, TC_SETUP_CLSBPF, |
---|
| 688 | + &cls_bpf, cb_priv, &prog->gen_flags, |
---|
| 689 | + &prog->in_hw_count); |
---|
| 690 | + if (err) |
---|
| 691 | + return err; |
---|
691 | 692 | } |
---|
692 | 693 | |
---|
693 | 694 | return 0; |
---|