cls_api.c (edfbeecd92b0c4a648ed96a7e255bfc9a1bc4642) | cls_api.c (dac9c9790e542777079999900594fd069ba10489) |
---|---|
1/* 2 * net/sched/cls_api.c Packet classifier API. 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. 8 * --- 226 unchanged lines hidden (view full) --- 235static void tcf_chain_destroy(struct tcf_chain *chain) 236{ 237 struct tcf_block *block = chain->block; 238 239 list_del(&chain->list); 240 if (!chain->index) 241 block->chain0.chain = NULL; 242 kfree(chain); | 1/* 2 * net/sched/cls_api.c Packet classifier API. 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. 8 * --- 226 unchanged lines hidden (view full) --- 235static void tcf_chain_destroy(struct tcf_chain *chain) 236{ 237 struct tcf_block *block = chain->block; 238 239 list_del(&chain->list); 240 if (!chain->index) 241 block->chain0.chain = NULL; 242 kfree(chain); |
243 if (list_empty(&block->chain_list) && block->refcnt == 0) 244 kfree(block); | 243 if (list_empty(&block->chain_list) && !refcount_read(&block->refcnt)) 244 kfree_rcu(block, rcu); |
245} 246 247static void tcf_chain_hold(struct tcf_chain *chain) 248{ 249 ++chain->refcnt; 250} 251 252static bool tcf_chain_held_by_acts_only(struct tcf_chain *chain) --- 215 unchanged lines hidden (view full) --- 468 kfree(item); 469 return; 470 } 471 } 472 WARN_ON(1); 473} 474 475struct tcf_net { | 245} 246 247static void tcf_chain_hold(struct tcf_chain *chain) 248{ 249 ++chain->refcnt; 250} 251 252static bool tcf_chain_held_by_acts_only(struct tcf_chain *chain) --- 215 unchanged lines hidden (view full) --- 468 kfree(item); 469 return; 470 } 471 } 472 WARN_ON(1); 473} 474 475struct tcf_net { |
476 spinlock_t idr_lock; /* Protects idr */ |
|
476 struct idr idr; 477}; 478 479static unsigned int tcf_net_id; 480 481static int tcf_block_insert(struct tcf_block *block, struct net *net, 482 struct netlink_ext_ack *extack) 483{ 484 struct tcf_net *tn = net_generic(net, tcf_net_id); | 477 struct idr idr; 478}; 479 480static unsigned int tcf_net_id; 481 482static int tcf_block_insert(struct tcf_block *block, struct net *net, 483 struct netlink_ext_ack *extack) 484{ 485 struct tcf_net *tn = net_generic(net, tcf_net_id); |
486 int err; |
|
485 | 487 |
486 return idr_alloc_u32(&tn->idr, block, &block->index, block->index, 487 GFP_KERNEL); | 488 idr_preload(GFP_KERNEL); 489 spin_lock(&tn->idr_lock); 490 err = idr_alloc_u32(&tn->idr, block, &block->index, block->index, 491 GFP_NOWAIT); 492 spin_unlock(&tn->idr_lock); 493 idr_preload_end(); 494 495 return err; |
488} 489 490static void tcf_block_remove(struct tcf_block *block, struct net *net) 491{ 492 struct tcf_net *tn = net_generic(net, tcf_net_id); 493 | 496} 497 498static void tcf_block_remove(struct tcf_block *block, struct net *net) 499{ 500 struct tcf_net *tn = net_generic(net, tcf_net_id); 501 |
502 spin_lock(&tn->idr_lock); |
|
494 idr_remove(&tn->idr, block->index); | 503 idr_remove(&tn->idr, block->index); |
504 spin_unlock(&tn->idr_lock); |
|
495} 496 497static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, 498 u32 block_index, 499 struct netlink_ext_ack *extack) 500{ 501 struct tcf_block *block; 502 503 block = kzalloc(sizeof(*block), GFP_KERNEL); 504 if (!block) { 505 NL_SET_ERR_MSG(extack, "Memory allocation for block failed"); 506 return ERR_PTR(-ENOMEM); 507 } 508 INIT_LIST_HEAD(&block->chain_list); 509 INIT_LIST_HEAD(&block->cb_list); 510 INIT_LIST_HEAD(&block->owner_list); 511 INIT_LIST_HEAD(&block->chain0.filter_chain_list); 512 | 505} 506 507static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, 508 u32 block_index, 509 struct netlink_ext_ack *extack) 510{ 511 struct tcf_block *block; 512 513 block = kzalloc(sizeof(*block), GFP_KERNEL); 514 if (!block) { 515 NL_SET_ERR_MSG(extack, "Memory allocation for block failed"); 516 return ERR_PTR(-ENOMEM); 517 } 518 INIT_LIST_HEAD(&block->chain_list); 519 INIT_LIST_HEAD(&block->cb_list); 520 INIT_LIST_HEAD(&block->owner_list); 521 INIT_LIST_HEAD(&block->chain0.filter_chain_list); 522 |
513 block->refcnt = 1; | 523 refcount_set(&block->refcnt, 1); |
514 block->net = net; 515 block->index = block_index; 516 517 /* Don't store q pointer for blocks which are shared */ 518 if (!tcf_block_shared(block)) 519 block->q = q; 520 return block; 521} 522 523static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index) 524{ 525 struct tcf_net *tn = net_generic(net, tcf_net_id); 526 527 return idr_find(&tn->idr, block_index); 528} 529 | 524 block->net = net; 525 block->index = block_index; 526 527 /* Don't store q pointer for blocks which are shared */ 528 if (!tcf_block_shared(block)) 529 block->q = q; 530 return block; 531} 532 533static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index) 534{ 535 struct tcf_net *tn = net_generic(net, tcf_net_id); 536 537 return idr_find(&tn->idr, block_index); 538} 539 |
540static struct tcf_block *tcf_block_refcnt_get(struct net *net, u32 block_index) 541{ 542 struct tcf_block *block; 543 544 rcu_read_lock(); 545 block = tcf_block_lookup(net, block_index); 546 if (block && !refcount_inc_not_zero(&block->refcnt)) 547 block = NULL; 548 rcu_read_unlock(); 549 550 return block; 551} 552 553static void tcf_block_flush_all_chains(struct tcf_block *block) 554{ 555 struct tcf_chain *chain; 556 557 /* Hold a refcnt for all chains, so that they don't disappear 558 * while we are iterating. 559 */ 560 list_for_each_entry(chain, &block->chain_list, list) 561 tcf_chain_hold(chain); 562 563 list_for_each_entry(chain, &block->chain_list, list) 564 tcf_chain_flush(chain); 565} 566 567static void tcf_block_put_all_chains(struct tcf_block *block) 568{ 569 struct tcf_chain *chain, *tmp; 570 571 /* At this point, all the chains should have refcnt >= 1. */ 572 list_for_each_entry_safe(chain, tmp, &block->chain_list, list) { 573 tcf_chain_put_explicitly_created(chain); 574 tcf_chain_put(chain); 575 } 576} 577 578static void __tcf_block_put(struct tcf_block *block, struct Qdisc *q, 579 struct tcf_block_ext_info *ei) 580{ 581 if (refcount_dec_and_test(&block->refcnt)) { 582 /* Flushing/putting all chains will cause the block to be 583 * deallocated when last chain is freed. However, if chain_list 584 * is empty, block has to be manually deallocated. After block 585 * reference counter reached 0, it is no longer possible to 586 * increment it or add new chains to block. 587 */ 588 bool free_block = list_empty(&block->chain_list); 589 590 if (tcf_block_shared(block)) 591 tcf_block_remove(block, block->net); 592 if (!free_block) 593 tcf_block_flush_all_chains(block); 594 595 if (q) 596 tcf_block_offload_unbind(block, q, ei); 597 598 if (free_block) 599 kfree_rcu(block, rcu); 600 else 601 tcf_block_put_all_chains(block); 602 } else if (q) { 603 tcf_block_offload_unbind(block, q, ei); 604 } 605} 606 607static void tcf_block_refcnt_put(struct tcf_block *block) 608{ 609 __tcf_block_put(block, NULL, NULL); 610} 611 |
|
530/* Find tcf block. 531 * Set q, parent, cl when appropriate. 532 */ 533 534static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q, 535 u32 *parent, unsigned long *cl, 536 int ifindex, u32 block_index, 537 struct netlink_ext_ack *extack) 538{ 539 struct tcf_block *block; | 612/* Find tcf block. 613 * Set q, parent, cl when appropriate. 614 */ 615 616static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q, 617 u32 *parent, unsigned long *cl, 618 int ifindex, u32 block_index, 619 struct netlink_ext_ack *extack) 620{ 621 struct tcf_block *block; |
622 int err = 0; |
|
540 541 if (ifindex == TCM_IFINDEX_MAGIC_BLOCK) { | 623 624 if (ifindex == TCM_IFINDEX_MAGIC_BLOCK) { |
542 block = tcf_block_lookup(net, block_index); | 625 block = tcf_block_refcnt_get(net, block_index); |
543 if (!block) { 544 NL_SET_ERR_MSG(extack, "Block of given index was not found"); 545 return ERR_PTR(-EINVAL); 546 } 547 } else { 548 const struct Qdisc_class_ops *cops; 549 struct net_device *dev; 550 | 626 if (!block) { 627 NL_SET_ERR_MSG(extack, "Block of given index was not found"); 628 return ERR_PTR(-EINVAL); 629 } 630 } else { 631 const struct Qdisc_class_ops *cops; 632 struct net_device *dev; 633 |
634 rcu_read_lock(); 635 |
|
551 /* Find link */ | 636 /* Find link */ |
552 dev = __dev_get_by_index(net, ifindex); 553 if (!dev) | 637 dev = dev_get_by_index_rcu(net, ifindex); 638 if (!dev) { 639 rcu_read_unlock(); |
554 return ERR_PTR(-ENODEV); | 640 return ERR_PTR(-ENODEV); |
641 } |
|
555 556 /* Find qdisc */ 557 if (!*parent) { 558 *q = dev->qdisc; 559 *parent = (*q)->handle; 560 } else { | 642 643 /* Find qdisc */ 644 if (!*parent) { 645 *q = dev->qdisc; 646 *parent = (*q)->handle; 647 } else { |
561 *q = qdisc_lookup(dev, TC_H_MAJ(*parent)); | 648 *q = qdisc_lookup_rcu(dev, TC_H_MAJ(*parent)); |
562 if (!*q) { 563 NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't exists"); | 649 if (!*q) { 650 NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't exists"); |
564 return ERR_PTR(-EINVAL); | 651 err = -EINVAL; 652 goto errout_rcu; |
565 } 566 } 567 | 653 } 654 } 655 |
656 *q = qdisc_refcount_inc_nz(*q); 657 if (!*q) { 658 NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't exists"); 659 err = -EINVAL; 660 goto errout_rcu; 661 } 662 |
|
568 /* Is it classful? */ 569 cops = (*q)->ops->cl_ops; 570 if (!cops) { 571 NL_SET_ERR_MSG(extack, "Qdisc not classful"); | 663 /* Is it classful? */ 664 cops = (*q)->ops->cl_ops; 665 if (!cops) { 666 NL_SET_ERR_MSG(extack, "Qdisc not classful"); |
572 return ERR_PTR(-EINVAL); | 667 err = -EINVAL; 668 goto errout_rcu; |
573 } 574 575 if (!cops->tcf_block) { 576 NL_SET_ERR_MSG(extack, "Class doesn't support blocks"); | 669 } 670 671 if (!cops->tcf_block) { 672 NL_SET_ERR_MSG(extack, "Class doesn't support blocks"); |
577 return ERR_PTR(-EOPNOTSUPP); | 673 err = -EOPNOTSUPP; 674 goto errout_rcu; |
578 } 579 | 675 } 676 |
677 /* At this point we know that qdisc is not noop_qdisc, 678 * which means that qdisc holds a reference to net_device 679 * and we hold a reference to qdisc, so it is safe to release 680 * rcu read lock. 681 */ 682 rcu_read_unlock(); 683 |
|
580 /* Do we search for filter, attached to class? */ 581 if (TC_H_MIN(*parent)) { 582 *cl = cops->find(*q, *parent); 583 if (*cl == 0) { 584 NL_SET_ERR_MSG(extack, "Specified class doesn't exist"); | 684 /* Do we search for filter, attached to class? */ 685 if (TC_H_MIN(*parent)) { 686 *cl = cops->find(*q, *parent); 687 if (*cl == 0) { 688 NL_SET_ERR_MSG(extack, "Specified class doesn't exist"); |
585 return ERR_PTR(-ENOENT); | 689 err = -ENOENT; 690 goto errout_qdisc; |
586 } 587 } 588 589 /* And the last stroke */ 590 block = cops->tcf_block(*q, *cl, extack); | 691 } 692 } 693 694 /* And the last stroke */ 695 block = cops->tcf_block(*q, *cl, extack); |
591 if (!block) 592 return ERR_PTR(-EINVAL); | 696 if (!block) { 697 err = -EINVAL; 698 goto errout_qdisc; 699 } |
593 if (tcf_block_shared(block)) { 594 NL_SET_ERR_MSG(extack, "This filter block is shared. Please use the block index to manipulate the filters"); | 700 if (tcf_block_shared(block)) { 701 NL_SET_ERR_MSG(extack, "This filter block is shared. Please use the block index to manipulate the filters"); |
595 return ERR_PTR(-EOPNOTSUPP); | 702 err = -EOPNOTSUPP; 703 goto errout_qdisc; |
596 } | 704 } |
705 706 /* Always take reference to block in order to support execution 707 * of rules update path of cls API without rtnl lock. Caller 708 * must release block when it is finished using it. 'if' block 709 * of this conditional obtain reference to block by calling 710 * tcf_block_refcnt_get(). 711 */ 712 refcount_inc(&block->refcnt); |
|
597 } 598 599 return block; | 713 } 714 715 return block; |
716 717errout_rcu: 718 rcu_read_unlock(); 719errout_qdisc: 720 if (*q) { 721 qdisc_put(*q); 722 *q = NULL; 723 } 724 return ERR_PTR(err); |
|
600} 601 | 725} 726 |
727static void tcf_block_release(struct Qdisc *q, struct tcf_block *block) 728{ 729 if (!IS_ERR_OR_NULL(block)) 730 tcf_block_refcnt_put(block); 731 732 if (q) 733 qdisc_put(q); 734} 735 |
|
602struct tcf_block_owner_item { 603 struct list_head list; 604 struct Qdisc *q; 605 enum tcf_block_binder_type binder_type; 606}; 607 608static void 609tcf_block_owner_netif_keep_dst(struct tcf_block *block, --- 49 unchanged lines hidden (view full) --- 659} 660 661int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 662 struct tcf_block_ext_info *ei, 663 struct netlink_ext_ack *extack) 664{ 665 struct net *net = qdisc_net(q); 666 struct tcf_block *block = NULL; | 736struct tcf_block_owner_item { 737 struct list_head list; 738 struct Qdisc *q; 739 enum tcf_block_binder_type binder_type; 740}; 741 742static void 743tcf_block_owner_netif_keep_dst(struct tcf_block *block, --- 49 unchanged lines hidden (view full) --- 793} 794 795int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, 796 struct tcf_block_ext_info *ei, 797 struct netlink_ext_ack *extack) 798{ 799 struct net *net = qdisc_net(q); 800 struct tcf_block *block = NULL; |
667 bool created = false; | |
668 int err; 669 | 801 int err; 802 |
670 if (ei->block_index) { | 803 if (ei->block_index) |
671 /* block_index not 0 means the shared block is requested */ | 804 /* block_index not 0 means the shared block is requested */ |
672 block = tcf_block_lookup(net, ei->block_index); 673 if (block) 674 block->refcnt++; 675 } | 805 block = tcf_block_refcnt_get(net, ei->block_index); |
676 677 if (!block) { 678 block = tcf_block_create(net, q, ei->block_index, extack); 679 if (IS_ERR(block)) 680 return PTR_ERR(block); | 806 807 if (!block) { 808 block = tcf_block_create(net, q, ei->block_index, extack); 809 if (IS_ERR(block)) 810 return PTR_ERR(block); |
681 created = true; | |
682 if (tcf_block_shared(block)) { 683 err = tcf_block_insert(block, net, extack); 684 if (err) 685 goto err_block_insert; 686 } 687 } 688 689 err = tcf_block_owner_add(block, q, ei->binder_type); --- 13 unchanged lines hidden (view full) --- 703 *p_block = block; 704 return 0; 705 706err_block_offload_bind: 707 tcf_chain0_head_change_cb_del(block, ei); 708err_chain0_head_change_cb_add: 709 tcf_block_owner_del(block, q, ei->binder_type); 710err_block_owner_add: | 811 if (tcf_block_shared(block)) { 812 err = tcf_block_insert(block, net, extack); 813 if (err) 814 goto err_block_insert; 815 } 816 } 817 818 err = tcf_block_owner_add(block, q, ei->binder_type); --- 13 unchanged lines hidden (view full) --- 832 *p_block = block; 833 return 0; 834 835err_block_offload_bind: 836 tcf_chain0_head_change_cb_del(block, ei); 837err_chain0_head_change_cb_add: 838 tcf_block_owner_del(block, q, ei->binder_type); 839err_block_owner_add: |
711 if (created) { 712 if (tcf_block_shared(block)) 713 tcf_block_remove(block, net); | |
714err_block_insert: | 840err_block_insert: |
715 kfree(block); 716 } else { 717 block->refcnt--; 718 } | 841 tcf_block_refcnt_put(block); |
719 return err; 720} 721EXPORT_SYMBOL(tcf_block_get_ext); 722 723static void tcf_chain_head_change_dflt(struct tcf_proto *tp_head, void *priv) 724{ 725 struct tcf_proto __rcu **p_filter_chain = priv; 726 --- 15 unchanged lines hidden (view full) --- 742EXPORT_SYMBOL(tcf_block_get); 743 744/* XXX: Standalone actions are not allowed to jump to any chain, and bound 745 * actions should be all removed after flushing. 746 */ 747void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 748 struct tcf_block_ext_info *ei) 749{ | 842 return err; 843} 844EXPORT_SYMBOL(tcf_block_get_ext); 845 846static void tcf_chain_head_change_dflt(struct tcf_proto *tp_head, void *priv) 847{ 848 struct tcf_proto __rcu **p_filter_chain = priv; 849 --- 15 unchanged lines hidden (view full) --- 865EXPORT_SYMBOL(tcf_block_get); 866 867/* XXX: Standalone actions are not allowed to jump to any chain, and bound 868 * actions should be all removed after flushing. 869 */ 870void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 871 struct tcf_block_ext_info *ei) 872{ |
750 struct tcf_chain *chain, *tmp; 751 | |
752 if (!block) 753 return; 754 tcf_chain0_head_change_cb_del(block, ei); 755 tcf_block_owner_del(block, q, ei->binder_type); 756 | 873 if (!block) 874 return; 875 tcf_chain0_head_change_cb_del(block, ei); 876 tcf_block_owner_del(block, q, ei->binder_type); 877 |
757 if (block->refcnt == 1) { 758 if (tcf_block_shared(block)) 759 tcf_block_remove(block, block->net); 760 761 /* Hold a refcnt for all chains, so that they don't disappear 762 * while we are iterating. 763 */ 764 list_for_each_entry(chain, &block->chain_list, list) 765 tcf_chain_hold(chain); 766 767 list_for_each_entry(chain, &block->chain_list, list) 768 tcf_chain_flush(chain); 769 } 770 771 tcf_block_offload_unbind(block, q, ei); 772 773 if (block->refcnt == 1) { 774 /* At this point, all the chains should have refcnt >= 1. */ 775 list_for_each_entry_safe(chain, tmp, &block->chain_list, list) { 776 tcf_chain_put_explicitly_created(chain); 777 tcf_chain_put(chain); 778 } 779 780 block->refcnt--; 781 if (list_empty(&block->chain_list)) 782 kfree(block); 783 } else { 784 block->refcnt--; 785 } | 878 __tcf_block_put(block, q, ei); |
786} 787EXPORT_SYMBOL(tcf_block_put_ext); 788 789void tcf_block_put(struct tcf_block *block) 790{ 791 struct tcf_block_ext_info ei = {0, }; 792 793 if (!block) --- 533 unchanged lines hidden (view full) --- 1327 } else { 1328 if (tp_created) 1329 tcf_proto_destroy(tp, NULL); 1330 } 1331 1332errout: 1333 if (chain) 1334 tcf_chain_put(chain); | 879} 880EXPORT_SYMBOL(tcf_block_put_ext); 881 882void tcf_block_put(struct tcf_block *block) 883{ 884 struct tcf_block_ext_info ei = {0, }; 885 886 if (!block) --- 533 unchanged lines hidden (view full) --- 1420 } else { 1421 if (tp_created) 1422 tcf_proto_destroy(tp, NULL); 1423 } 1424 1425errout: 1426 if (chain) 1427 tcf_chain_put(chain); |
1428 tcf_block_release(q, block); |
|
1335 if (err == -EAGAIN) 1336 /* Replay the request. */ 1337 goto replay; 1338 return err; 1339} 1340 1341static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, 1342 struct netlink_ext_ack *extack) --- 105 unchanged lines hidden (view full) --- 1448 tcf_chain_tp_remove(chain, &chain_info, tp); 1449 tcf_proto_destroy(tp, extack); 1450 } 1451 } 1452 1453errout: 1454 if (chain) 1455 tcf_chain_put(chain); | 1429 if (err == -EAGAIN) 1430 /* Replay the request. */ 1431 goto replay; 1432 return err; 1433} 1434 1435static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, 1436 struct netlink_ext_ack *extack) --- 105 unchanged lines hidden (view full) --- 1542 tcf_chain_tp_remove(chain, &chain_info, tp); 1543 tcf_proto_destroy(tp, extack); 1544 } 1545 } 1546 1547errout: 1548 if (chain) 1549 tcf_chain_put(chain); |
1550 tcf_block_release(q, block); |
|
1456 return err; 1457} 1458 1459static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, 1460 struct netlink_ext_ack *extack) 1461{ 1462 struct net *net = sock_net(skb->sk); 1463 struct nlattr *tca[TCA_MAX + 1]; --- 69 unchanged lines hidden (view full) --- 1533 fh, RTM_NEWTFILTER, true); 1534 if (err < 0) 1535 NL_SET_ERR_MSG(extack, "Failed to send filter notify message"); 1536 } 1537 1538errout: 1539 if (chain) 1540 tcf_chain_put(chain); | 1551 return err; 1552} 1553 1554static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, 1555 struct netlink_ext_ack *extack) 1556{ 1557 struct net *net = sock_net(skb->sk); 1558 struct nlattr *tca[TCA_MAX + 1]; --- 69 unchanged lines hidden (view full) --- 1628 fh, RTM_NEWTFILTER, true); 1629 if (err < 0) 1630 NL_SET_ERR_MSG(extack, "Failed to send filter notify message"); 1631 } 1632 1633errout: 1634 if (chain) 1635 tcf_chain_put(chain); |
1636 tcf_block_release(q, block); |
|
1541 return err; 1542} 1543 1544struct tcf_dump_args { 1545 struct tcf_walker w; 1546 struct sk_buff *skb; 1547 struct netlink_callback *cb; 1548 struct tcf_block *block; --- 77 unchanged lines hidden (view full) --- 1626 long index_start; 1627 long index; 1628 u32 parent; 1629 int err; 1630 1631 if (nlmsg_len(cb->nlh) < sizeof(*tcm)) 1632 return skb->len; 1633 | 1637 return err; 1638} 1639 1640struct tcf_dump_args { 1641 struct tcf_walker w; 1642 struct sk_buff *skb; 1643 struct netlink_callback *cb; 1644 struct tcf_block *block; --- 77 unchanged lines hidden (view full) --- 1722 long index_start; 1723 long index; 1724 u32 parent; 1725 int err; 1726 1727 if (nlmsg_len(cb->nlh) < sizeof(*tcm)) 1728 return skb->len; 1729 |
1634 err = nlmsg_parse(cb->nlh, sizeof(*tcm), tca, TCA_MAX, NULL, NULL); | 1730 err = nlmsg_parse(cb->nlh, sizeof(*tcm), tca, TCA_MAX, NULL, 1731 cb->extack); |
1635 if (err) 1636 return err; 1637 1638 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) { | 1732 if (err) 1733 return err; 1734 1735 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) { |
1639 block = tcf_block_lookup(net, tcm->tcm_block_index); | 1736 block = tcf_block_refcnt_get(net, tcm->tcm_block_index); |
1640 if (!block) 1641 goto out; 1642 /* If we work with block index, q is NULL and parent value 1643 * will never be used in the following code. The check 1644 * in tcf_fill_node prevents it. However, compiler does not 1645 * see that far, so set parent to zero to silence the warning 1646 * about parent being uninitialized. 1647 */ --- 42 unchanged lines hidden (view full) --- 1690 continue; 1691 if (!tcf_chain_dump(chain, q, parent, skb, cb, 1692 index_start, &index)) { 1693 err = -EMSGSIZE; 1694 break; 1695 } 1696 } 1697 | 1737 if (!block) 1738 goto out; 1739 /* If we work with block index, q is NULL and parent value 1740 * will never be used in the following code. The check 1741 * in tcf_fill_node prevents it. However, compiler does not 1742 * see that far, so set parent to zero to silence the warning 1743 * about parent being uninitialized. 1744 */ --- 42 unchanged lines hidden (view full) --- 1787 continue; 1788 if (!tcf_chain_dump(chain, q, parent, skb, cb, 1789 index_start, &index)) { 1790 err = -EMSGSIZE; 1791 break; 1792 } 1793 } 1794 |
1795 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) 1796 tcf_block_refcnt_put(block); |
|
1698 cb->args[0] = index; 1699 1700out: 1701 /* If we did no progress, the error (EMSGSIZE) is real */ 1702 if (skb->len == 0 && err) 1703 return err; 1704 return skb->len; 1705} --- 143 unchanged lines hidden (view full) --- 1849 block = tcf_block_find(net, &q, &parent, &cl, 1850 t->tcm_ifindex, t->tcm_block_index, extack); 1851 if (IS_ERR(block)) 1852 return PTR_ERR(block); 1853 1854 chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0; 1855 if (chain_index > TC_ACT_EXT_VAL_MASK) { 1856 NL_SET_ERR_MSG(extack, "Specified chain index exceeds upper limit"); | 1797 cb->args[0] = index; 1798 1799out: 1800 /* If we did no progress, the error (EMSGSIZE) is real */ 1801 if (skb->len == 0 && err) 1802 return err; 1803 return skb->len; 1804} --- 143 unchanged lines hidden (view full) --- 1948 block = tcf_block_find(net, &q, &parent, &cl, 1949 t->tcm_ifindex, t->tcm_block_index, extack); 1950 if (IS_ERR(block)) 1951 return PTR_ERR(block); 1952 1953 chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0; 1954 if (chain_index > TC_ACT_EXT_VAL_MASK) { 1955 NL_SET_ERR_MSG(extack, "Specified chain index exceeds upper limit"); |
1857 return -EINVAL; | 1956 err = -EINVAL; 1957 goto errout_block; |
1858 } 1859 chain = tcf_chain_lookup(block, chain_index); 1860 if (n->nlmsg_type == RTM_NEWCHAIN) { 1861 if (chain) { 1862 if (tcf_chain_held_by_acts_only(chain)) { 1863 /* The chain exists only because there is 1864 * some action referencing it. 1865 */ 1866 tcf_chain_hold(chain); 1867 } else { 1868 NL_SET_ERR_MSG(extack, "Filter chain already exists"); | 1958 } 1959 chain = tcf_chain_lookup(block, chain_index); 1960 if (n->nlmsg_type == RTM_NEWCHAIN) { 1961 if (chain) { 1962 if (tcf_chain_held_by_acts_only(chain)) { 1963 /* The chain exists only because there is 1964 * some action referencing it. 1965 */ 1966 tcf_chain_hold(chain); 1967 } else { 1968 NL_SET_ERR_MSG(extack, "Filter chain already exists"); |
1869 return -EEXIST; | 1969 err = -EEXIST; 1970 goto errout_block; |
1870 } 1871 } else { 1872 if (!(n->nlmsg_flags & NLM_F_CREATE)) { 1873 NL_SET_ERR_MSG(extack, "Need both RTM_NEWCHAIN and NLM_F_CREATE to create a new chain"); | 1971 } 1972 } else { 1973 if (!(n->nlmsg_flags & NLM_F_CREATE)) { 1974 NL_SET_ERR_MSG(extack, "Need both RTM_NEWCHAIN and NLM_F_CREATE to create a new chain"); |
1874 return -ENOENT; | 1975 err = -ENOENT; 1976 goto errout_block; |
1875 } 1876 chain = tcf_chain_create(block, chain_index); 1877 if (!chain) { 1878 NL_SET_ERR_MSG(extack, "Failed to create filter chain"); | 1977 } 1978 chain = tcf_chain_create(block, chain_index); 1979 if (!chain) { 1980 NL_SET_ERR_MSG(extack, "Failed to create filter chain"); |
1879 return -ENOMEM; | 1981 err = -ENOMEM; 1982 goto errout_block; |
1880 } 1881 } 1882 } else { 1883 if (!chain || tcf_chain_held_by_acts_only(chain)) { 1884 NL_SET_ERR_MSG(extack, "Cannot find specified filter chain"); | 1983 } 1984 } 1985 } else { 1986 if (!chain || tcf_chain_held_by_acts_only(chain)) { 1987 NL_SET_ERR_MSG(extack, "Cannot find specified filter chain"); |
1885 return -EINVAL; | 1988 err = -EINVAL; 1989 goto errout_block; |
1886 } 1887 tcf_chain_hold(chain); 1888 } 1889 1890 switch (n->nlmsg_type) { 1891 case RTM_NEWCHAIN: 1892 err = tc_chain_tmplt_add(chain, net, tca, extack); 1893 if (err) --- 27 unchanged lines hidden (view full) --- 1921 default: 1922 err = -EOPNOTSUPP; 1923 NL_SET_ERR_MSG(extack, "Unsupported message type"); 1924 goto errout; 1925 } 1926 1927errout: 1928 tcf_chain_put(chain); | 1990 } 1991 tcf_chain_hold(chain); 1992 } 1993 1994 switch (n->nlmsg_type) { 1995 case RTM_NEWCHAIN: 1996 err = tc_chain_tmplt_add(chain, net, tca, extack); 1997 if (err) --- 27 unchanged lines hidden (view full) --- 2025 default: 2026 err = -EOPNOTSUPP; 2027 NL_SET_ERR_MSG(extack, "Unsupported message type"); 2028 goto errout; 2029 } 2030 2031errout: 2032 tcf_chain_put(chain); |
2033errout_block: 2034 tcf_block_release(q, block); |
|
1929 if (err == -EAGAIN) 1930 /* Replay the request. */ 1931 goto replay; 1932 return err; 1933} 1934 1935/* called with RTNL */ 1936static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb) --- 7 unchanged lines hidden (view full) --- 1944 long index_start; 1945 long index; 1946 u32 parent; 1947 int err; 1948 1949 if (nlmsg_len(cb->nlh) < sizeof(*tcm)) 1950 return skb->len; 1951 | 2035 if (err == -EAGAIN) 2036 /* Replay the request. */ 2037 goto replay; 2038 return err; 2039} 2040 2041/* called with RTNL */ 2042static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb) --- 7 unchanged lines hidden (view full) --- 2050 long index_start; 2051 long index; 2052 u32 parent; 2053 int err; 2054 2055 if (nlmsg_len(cb->nlh) < sizeof(*tcm)) 2056 return skb->len; 2057 |
1952 err = nlmsg_parse(cb->nlh, sizeof(*tcm), tca, TCA_MAX, NULL, NULL); | 2058 err = nlmsg_parse(cb->nlh, sizeof(*tcm), tca, TCA_MAX, NULL, 2059 cb->extack); |
1953 if (err) 1954 return err; 1955 1956 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) { | 2060 if (err) 2061 return err; 2062 2063 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) { |
1957 block = tcf_block_lookup(net, tcm->tcm_block_index); | 2064 block = tcf_block_refcnt_get(net, tcm->tcm_block_index); |
1958 if (!block) 1959 goto out; 1960 /* If we work with block index, q is NULL and parent value 1961 * will never be used in the following code. The check 1962 * in tcf_fill_node prevents it. However, compiler does not 1963 * see that far, so set parent to zero to silence the warning 1964 * about parent being uninitialized. 1965 */ --- 50 unchanged lines hidden (view full) --- 2016 NETLINK_CB(cb->skb).portid, 2017 cb->nlh->nlmsg_seq, NLM_F_MULTI, 2018 RTM_NEWCHAIN); 2019 if (err <= 0) 2020 break; 2021 index++; 2022 } 2023 | 2065 if (!block) 2066 goto out; 2067 /* If we work with block index, q is NULL and parent value 2068 * will never be used in the following code. The check 2069 * in tcf_fill_node prevents it. However, compiler does not 2070 * see that far, so set parent to zero to silence the warning 2071 * about parent being uninitialized. 2072 */ --- 50 unchanged lines hidden (view full) --- 2123 NETLINK_CB(cb->skb).portid, 2124 cb->nlh->nlmsg_seq, NLM_F_MULTI, 2125 RTM_NEWCHAIN); 2126 if (err <= 0) 2127 break; 2128 index++; 2129 } 2130 |
2131 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) 2132 tcf_block_refcnt_put(block); |
|
2024 cb->args[0] = index; 2025 2026out: 2027 /* If we did no progress, the error (EMSGSIZE) is real */ 2028 if (skb->len == 0 && err) 2029 return err; 2030 return skb->len; 2031} --- 176 unchanged lines hidden (view full) --- 2208 return ok_count; 2209} 2210EXPORT_SYMBOL(tc_setup_cb_call); 2211 2212static __net_init int tcf_net_init(struct net *net) 2213{ 2214 struct tcf_net *tn = net_generic(net, tcf_net_id); 2215 | 2133 cb->args[0] = index; 2134 2135out: 2136 /* If we did no progress, the error (EMSGSIZE) is real */ 2137 if (skb->len == 0 && err) 2138 return err; 2139 return skb->len; 2140} --- 176 unchanged lines hidden (view full) --- 2317 return ok_count; 2318} 2319EXPORT_SYMBOL(tc_setup_cb_call); 2320 2321static __net_init int tcf_net_init(struct net *net) 2322{ 2323 struct tcf_net *tn = net_generic(net, tcf_net_id); 2324 |
2325 spin_lock_init(&tn->idr_lock); |
|
2216 idr_init(&tn->idr); 2217 return 0; 2218} 2219 2220static void __net_exit tcf_net_exit(struct net *net) 2221{ 2222 struct tcf_net *tn = net_generic(net, tcf_net_id); 2223 --- 39 unchanged lines hidden --- | 2326 idr_init(&tn->idr); 2327 return 0; 2328} 2329 2330static void __net_exit tcf_net_exit(struct net *net) 2331{ 2332 struct tcf_net *tn = net_generic(net, tcf_net_id); 2333 --- 39 unchanged lines hidden --- |