diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-07-18 10:08:27 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-07-18 10:08:27 -0400 |
commit | 84a797dd0b9f7130357b70577fcbda8e638c71a7 (patch) | |
tree | 6d093dba184228f689873b7171d63933f0676e0d /net | |
parent | 6b75e3e8d664a9a1b99d31a7f4976ae70d1d090a (diff) |
netfilter: nfnetlink_queue: provide rcu enabled callbacks
nenetlink_queue operations on SMP are not efficent if several queues are
used, because of nfnl_mutex contention when applications give packet
verdict.
Use new call_rcu field in struct nfnl_callback to advertize a callback
that is called under rcu_read_lock instead of nfnl_mutex.
On my 2x4x2 machine, I was able to reach 2.000.000 pps going through
user land returning NF_ACCEPT verdicts without losses, instead of less
than 500.000 pps before patch.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Florian Westphal <fw@strlen.de>
CC: Eric Leblond <eric@regit.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 41 |
1 files changed, 12 insertions, 29 deletions
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index b83123f12b42..c645b87915b8 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -619,39 +619,26 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
619 | struct nfqnl_instance *queue; | 619 | struct nfqnl_instance *queue; |
620 | unsigned int verdict; | 620 | unsigned int verdict; |
621 | struct nf_queue_entry *entry; | 621 | struct nf_queue_entry *entry; |
622 | int err; | ||
623 | 622 | ||
624 | rcu_read_lock(); | ||
625 | queue = instance_lookup(queue_num); | 623 | queue = instance_lookup(queue_num); |
626 | if (!queue) { | 624 | if (!queue) |
627 | err = -ENODEV; | 625 | return -ENODEV; |
628 | goto err_out_unlock; | ||
629 | } | ||
630 | 626 | ||
631 | if (queue->peer_pid != NETLINK_CB(skb).pid) { | 627 | if (queue->peer_pid != NETLINK_CB(skb).pid) |
632 | err = -EPERM; | 628 | return -EPERM; |
633 | goto err_out_unlock; | ||
634 | } | ||
635 | 629 | ||
636 | if (!nfqa[NFQA_VERDICT_HDR]) { | 630 | if (!nfqa[NFQA_VERDICT_HDR]) |
637 | err = -EINVAL; | 631 | return -EINVAL; |
638 | goto err_out_unlock; | ||
639 | } | ||
640 | 632 | ||
641 | vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]); | 633 | vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]); |
642 | verdict = ntohl(vhdr->verdict); | 634 | verdict = ntohl(vhdr->verdict); |
643 | 635 | ||
644 | if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) { | 636 | if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) |
645 | err = -EINVAL; | 637 | return -EINVAL; |
646 | goto err_out_unlock; | ||
647 | } | ||
648 | 638 | ||
649 | entry = find_dequeue_entry(queue, ntohl(vhdr->id)); | 639 | entry = find_dequeue_entry(queue, ntohl(vhdr->id)); |
650 | if (entry == NULL) { | 640 | if (entry == NULL) |
651 | err = -ENOENT; | 641 | return -ENOENT; |
652 | goto err_out_unlock; | ||
653 | } | ||
654 | rcu_read_unlock(); | ||
655 | 642 | ||
656 | if (nfqa[NFQA_PAYLOAD]) { | 643 | if (nfqa[NFQA_PAYLOAD]) { |
657 | if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]), | 644 | if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]), |
@@ -664,10 +651,6 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
664 | 651 | ||
665 | nf_reinject(entry, verdict); | 652 | nf_reinject(entry, verdict); |
666 | return 0; | 653 | return 0; |
667 | |||
668 | err_out_unlock: | ||
669 | rcu_read_unlock(); | ||
670 | return err; | ||
671 | } | 654 | } |
672 | 655 | ||
673 | static int | 656 | static int |
@@ -780,9 +763,9 @@ err_out_unlock: | |||
780 | } | 763 | } |
781 | 764 | ||
782 | static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { | 765 | static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { |
783 | [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp, | 766 | [NFQNL_MSG_PACKET] = { .call_rcu = nfqnl_recv_unsupp, |
784 | .attr_count = NFQA_MAX, }, | 767 | .attr_count = NFQA_MAX, }, |
785 | [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict, | 768 | [NFQNL_MSG_VERDICT] = { .call_rcu = nfqnl_recv_verdict, |
786 | .attr_count = NFQA_MAX, | 769 | .attr_count = NFQA_MAX, |
787 | .policy = nfqa_verdict_policy }, | 770 | .policy = nfqa_verdict_policy }, |
788 | [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config, | 771 | [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config, |