.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * net/sched/ife.c Inter-FE action based on ForCES WG InterFE LFB |
---|
3 | 4 | * |
---|
.. | .. |
---|
9 | 10 | * Subsystem" |
---|
10 | 11 | * Authors: Jamal Hadi Salim and Damascene M. Joachimpillai |
---|
11 | 12 | * |
---|
12 | | - * This program is free software; you can redistribute it and/or |
---|
13 | | - * modify it under the terms of the GNU General Public License |
---|
14 | | - * as published by the Free Software Foundation; either version |
---|
15 | | - * 2 of the License, or (at your option) any later version. |
---|
16 | | - * |
---|
17 | 13 | * copyright Jamal Hadi Salim (2015) |
---|
18 | | - * |
---|
19 | 14 | */ |
---|
20 | 15 | |
---|
21 | 16 | #include <linux/types.h> |
---|
.. | .. |
---|
29 | 24 | #include <net/net_namespace.h> |
---|
30 | 25 | #include <net/netlink.h> |
---|
31 | 26 | #include <net/pkt_sched.h> |
---|
| 27 | +#include <net/pkt_cls.h> |
---|
32 | 28 | #include <uapi/linux/tc_act/tc_ife.h> |
---|
33 | 29 | #include <net/tc_act/tc_ife.h> |
---|
34 | 30 | #include <linux/etherdevice.h> |
---|
.. | .. |
---|
386 | 382 | if (list_empty(&ife->metalist)) |
---|
387 | 383 | return 0; |
---|
388 | 384 | |
---|
389 | | - nest = nla_nest_start(skb, TCA_IFE_METALST); |
---|
| 385 | + nest = nla_nest_start_noflag(skb, TCA_IFE_METALST); |
---|
390 | 386 | if (!nest) |
---|
391 | 387 | goto out_nlmsg_trim; |
---|
392 | 388 | |
---|
.. | .. |
---|
440 | 436 | kfree_rcu(p, rcu); |
---|
441 | 437 | } |
---|
442 | 438 | |
---|
| 439 | +static int load_metalist(struct nlattr **tb, bool rtnl_held) |
---|
| 440 | +{ |
---|
| 441 | + int i; |
---|
| 442 | + |
---|
| 443 | + for (i = 1; i < max_metacnt; i++) { |
---|
| 444 | + if (tb[i]) { |
---|
| 445 | + void *val = nla_data(tb[i]); |
---|
| 446 | + int len = nla_len(tb[i]); |
---|
| 447 | + int rc; |
---|
| 448 | + |
---|
| 449 | + rc = load_metaops_and_vet(i, val, len, rtnl_held); |
---|
| 450 | + if (rc != 0) |
---|
| 451 | + return rc; |
---|
| 452 | + } |
---|
| 453 | + } |
---|
| 454 | + |
---|
| 455 | + return 0; |
---|
| 456 | +} |
---|
| 457 | + |
---|
443 | 458 | static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, |
---|
444 | 459 | bool exists, bool rtnl_held) |
---|
445 | 460 | { |
---|
.. | .. |
---|
453 | 468 | val = nla_data(tb[i]); |
---|
454 | 469 | len = nla_len(tb[i]); |
---|
455 | 470 | |
---|
456 | | - rc = load_metaops_and_vet(i, val, len, rtnl_held); |
---|
457 | | - if (rc != 0) |
---|
458 | | - return rc; |
---|
459 | | - |
---|
460 | 471 | rc = add_metainfo(ife, i, val, len, exists); |
---|
461 | 472 | if (rc) |
---|
462 | 473 | return rc; |
---|
.. | .. |
---|
469 | 480 | static int tcf_ife_init(struct net *net, struct nlattr *nla, |
---|
470 | 481 | struct nlattr *est, struct tc_action **a, |
---|
471 | 482 | int ovr, int bind, bool rtnl_held, |
---|
| 483 | + struct tcf_proto *tp, u32 flags, |
---|
472 | 484 | struct netlink_ext_ack *extack) |
---|
473 | 485 | { |
---|
474 | 486 | struct tc_action_net *tn = net_generic(net, ife_net_id); |
---|
475 | 487 | struct nlattr *tb[TCA_IFE_MAX + 1]; |
---|
476 | 488 | struct nlattr *tb2[IFE_META_MAX + 1]; |
---|
| 489 | + struct tcf_chain *goto_ch = NULL; |
---|
477 | 490 | struct tcf_ife_params *p; |
---|
478 | 491 | struct tcf_ife_info *ife; |
---|
479 | 492 | u16 ife_type = ETH_P_IFE; |
---|
.. | .. |
---|
490 | 503 | return -EINVAL; |
---|
491 | 504 | } |
---|
492 | 505 | |
---|
493 | | - err = nla_parse_nested(tb, TCA_IFE_MAX, nla, ife_policy, NULL); |
---|
| 506 | + err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy, |
---|
| 507 | + NULL); |
---|
494 | 508 | if (err < 0) |
---|
495 | 509 | return err; |
---|
496 | 510 | |
---|
.. | .. |
---|
510 | 524 | if (!p) |
---|
511 | 525 | return -ENOMEM; |
---|
512 | 526 | |
---|
| 527 | + if (tb[TCA_IFE_METALST]) { |
---|
| 528 | + err = nla_parse_nested_deprecated(tb2, IFE_META_MAX, |
---|
| 529 | + tb[TCA_IFE_METALST], NULL, |
---|
| 530 | + NULL); |
---|
| 531 | + if (err) { |
---|
| 532 | + kfree(p); |
---|
| 533 | + return err; |
---|
| 534 | + } |
---|
| 535 | + err = load_metalist(tb2, rtnl_held); |
---|
| 536 | + if (err) { |
---|
| 537 | + kfree(p); |
---|
| 538 | + return err; |
---|
| 539 | + } |
---|
| 540 | + } |
---|
| 541 | + |
---|
513 | 542 | index = parm->index; |
---|
514 | 543 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
---|
515 | 544 | if (err < 0) { |
---|
.. | .. |
---|
524 | 553 | |
---|
525 | 554 | if (!exists) { |
---|
526 | 555 | ret = tcf_idr_create(tn, index, est, a, &act_ife_ops, |
---|
527 | | - bind, true); |
---|
| 556 | + bind, true, flags); |
---|
528 | 557 | if (ret) { |
---|
529 | 558 | tcf_idr_cleanup(tn, index); |
---|
530 | 559 | kfree(p); |
---|
.. | .. |
---|
538 | 567 | } |
---|
539 | 568 | |
---|
540 | 569 | ife = to_ife(*a); |
---|
| 570 | + if (ret == ACT_P_CREATED) |
---|
| 571 | + INIT_LIST_HEAD(&ife->metalist); |
---|
| 572 | + |
---|
| 573 | + err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); |
---|
| 574 | + if (err < 0) |
---|
| 575 | + goto release_idr; |
---|
| 576 | + |
---|
541 | 577 | p->flags = parm->flags; |
---|
542 | 578 | |
---|
543 | 579 | if (parm->flags & IFE_ENCODE) { |
---|
.. | .. |
---|
563 | 599 | p->eth_type = ife_type; |
---|
564 | 600 | } |
---|
565 | 601 | |
---|
566 | | - |
---|
567 | | - if (ret == ACT_P_CREATED) |
---|
568 | | - INIT_LIST_HEAD(&ife->metalist); |
---|
569 | | - |
---|
570 | 602 | if (tb[TCA_IFE_METALST]) { |
---|
571 | | - err = nla_parse_nested(tb2, IFE_META_MAX, tb[TCA_IFE_METALST], |
---|
572 | | - NULL, NULL); |
---|
573 | | - if (err) { |
---|
574 | | -metadata_parse_err: |
---|
575 | | - tcf_idr_release(*a, bind); |
---|
576 | | - kfree(p); |
---|
577 | | - return err; |
---|
578 | | - } |
---|
579 | | - |
---|
580 | 603 | err = populate_metalist(ife, tb2, exists, rtnl_held); |
---|
581 | 604 | if (err) |
---|
582 | 605 | goto metadata_parse_err; |
---|
583 | | - |
---|
584 | 606 | } else { |
---|
585 | 607 | /* if no passed metadata allow list or passed allow-all |
---|
586 | 608 | * then here we process by adding as many supported metadatum |
---|
.. | .. |
---|
588 | 610 | * going to bail out |
---|
589 | 611 | */ |
---|
590 | 612 | err = use_all_metadata(ife, exists); |
---|
591 | | - if (err) { |
---|
592 | | - tcf_idr_release(*a, bind); |
---|
593 | | - kfree(p); |
---|
594 | | - return err; |
---|
595 | | - } |
---|
| 613 | + if (err) |
---|
| 614 | + goto metadata_parse_err; |
---|
596 | 615 | } |
---|
597 | 616 | |
---|
598 | 617 | if (exists) |
---|
599 | 618 | spin_lock_bh(&ife->tcf_lock); |
---|
600 | | - ife->tcf_action = parm->action; |
---|
601 | 619 | /* protected by tcf_lock when modifying existing action */ |
---|
602 | | - rcu_swap_protected(ife->params, p, 1); |
---|
| 620 | + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
---|
| 621 | + p = rcu_replace_pointer(ife->params, p, 1); |
---|
603 | 622 | |
---|
604 | 623 | if (exists) |
---|
605 | 624 | spin_unlock_bh(&ife->tcf_lock); |
---|
| 625 | + if (goto_ch) |
---|
| 626 | + tcf_chain_put_by_act(goto_ch); |
---|
606 | 627 | if (p) |
---|
607 | 628 | kfree_rcu(p, rcu); |
---|
608 | 629 | |
---|
609 | | - if (ret == ACT_P_CREATED) |
---|
610 | | - tcf_idr_insert(tn, *a); |
---|
611 | | - |
---|
612 | 630 | return ret; |
---|
| 631 | +metadata_parse_err: |
---|
| 632 | + if (goto_ch) |
---|
| 633 | + tcf_chain_put_by_act(goto_ch); |
---|
| 634 | +release_idr: |
---|
| 635 | + kfree(p); |
---|
| 636 | + tcf_idr_release(*a, bind); |
---|
| 637 | + return err; |
---|
613 | 638 | } |
---|
614 | 639 | |
---|
615 | 640 | static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, |
---|
.. | .. |
---|
862 | 887 | return tcf_generic_walker(tn, skb, cb, type, ops, extack); |
---|
863 | 888 | } |
---|
864 | 889 | |
---|
865 | | -static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index, |
---|
866 | | - struct netlink_ext_ack *extack) |
---|
| 890 | +static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index) |
---|
867 | 891 | { |
---|
868 | 892 | struct tc_action_net *tn = net_generic(net, ife_net_id); |
---|
869 | 893 | |
---|
.. | .. |
---|
872 | 896 | |
---|
873 | 897 | static struct tc_action_ops act_ife_ops = { |
---|
874 | 898 | .kind = "ife", |
---|
875 | | - .type = TCA_ACT_IFE, |
---|
| 899 | + .id = TCA_ID_IFE, |
---|
876 | 900 | .owner = THIS_MODULE, |
---|
877 | 901 | .act = tcf_ife_act, |
---|
878 | 902 | .dump = tcf_ife_dump, |
---|