| .. | .. |
|---|
| 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; |
|---|