diff options
author | Denis V. Lunev <den@openvz.org> | 2008-02-29 14:21:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-29 14:21:22 -0500 |
commit | 98c6d1b261e74750e6c56ede26dc295201c4a8b2 (patch) | |
tree | e37818f4023b542a3c702d3fca11fc73f994737a /net/ipv6/icmp.c | |
parent | 4a6ad7a141cbee2cf074e6cf8dc527b231b69ece (diff) |
[NETNS]: Make icmpv6_sk per namespace.
All preparations are done. Now just add a hook to perform an
initialization on namespace startup and replace icmpv6_sk macro with
proper inline call. Actual namespace the packet belongs too will be
passed later along with the one for the routing.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Acked-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r-- | net/ipv6/icmp.c | 68 |
1 files changed, 47 insertions, 21 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 3eb594d54172..9f55a965c884 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -80,8 +80,10 @@ EXPORT_SYMBOL(icmpv6msg_statistics); | |||
80 | * | 80 | * |
81 | * On SMP we have one ICMP socket per-cpu. | 81 | * On SMP we have one ICMP socket per-cpu. |
82 | */ | 82 | */ |
83 | static struct sock **__icmpv6_sk = NULL; | 83 | static inline struct sock *icmpv6_sk(struct net *net) |
84 | #define icmpv6_sk (__icmpv6_sk[smp_processor_id()]) | 84 | { |
85 | return net->ipv6.icmp_sk[smp_processor_id()]; | ||
86 | } | ||
85 | 87 | ||
86 | static int icmpv6_rcv(struct sk_buff *skb); | 88 | static int icmpv6_rcv(struct sk_buff *skb); |
87 | 89 | ||
@@ -389,7 +391,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
389 | fl.fl_icmp_code = code; | 391 | fl.fl_icmp_code = code; |
390 | security_skb_classify_flow(skb, &fl); | 392 | security_skb_classify_flow(skb, &fl); |
391 | 393 | ||
392 | sk = icmpv6_sk; | 394 | sk = icmpv6_sk(&init_net); |
393 | np = inet6_sk(sk); | 395 | np = inet6_sk(sk); |
394 | 396 | ||
395 | if (icmpv6_xmit_lock(sk)) | 397 | if (icmpv6_xmit_lock(sk)) |
@@ -535,7 +537,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
535 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; | 537 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; |
536 | security_skb_classify_flow(skb, &fl); | 538 | security_skb_classify_flow(skb, &fl); |
537 | 539 | ||
538 | sk = icmpv6_sk; | 540 | sk = icmpv6_sk(&init_net); |
539 | np = inet6_sk(sk); | 541 | np = inet6_sk(sk); |
540 | 542 | ||
541 | if (icmpv6_xmit_lock(sk)) | 543 | if (icmpv6_xmit_lock(sk)) |
@@ -780,13 +782,14 @@ drop_no_count: | |||
780 | */ | 782 | */ |
781 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; | 783 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; |
782 | 784 | ||
783 | int __init icmpv6_init(void) | 785 | static int __net_init icmpv6_sk_init(struct net *net) |
784 | { | 786 | { |
785 | struct sock *sk; | 787 | struct sock *sk; |
786 | int err, i, j; | 788 | int err, i, j; |
787 | 789 | ||
788 | __icmpv6_sk = kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); | 790 | net->ipv6.icmp_sk = |
789 | if (__icmpv6_sk == NULL) | 791 | kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); |
792 | if (net->ipv6.icmp_sk == NULL) | ||
790 | return -ENOMEM; | 793 | return -ENOMEM; |
791 | 794 | ||
792 | for_each_possible_cpu(i) { | 795 | for_each_possible_cpu(i) { |
@@ -801,8 +804,8 @@ int __init icmpv6_init(void) | |||
801 | goto fail; | 804 | goto fail; |
802 | } | 805 | } |
803 | 806 | ||
804 | __icmpv6_sk[i] = sk = sock->sk; | 807 | net->ipv6.icmp_sk[i] = sk = sock->sk; |
805 | sk_change_net(sk, &init_net); | 808 | sk_change_net(sk, net); |
806 | 809 | ||
807 | sk->sk_allocation = GFP_ATOMIC; | 810 | sk->sk_allocation = GFP_ATOMIC; |
808 | /* | 811 | /* |
@@ -822,33 +825,56 @@ int __init icmpv6_init(void) | |||
822 | 825 | ||
823 | sk->sk_prot->unhash(sk); | 826 | sk->sk_prot->unhash(sk); |
824 | } | 827 | } |
825 | |||
826 | |||
827 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) { | ||
828 | printk(KERN_ERR "Failed to register ICMP6 protocol\n"); | ||
829 | err = -EAGAIN; | ||
830 | goto fail; | ||
831 | } | ||
832 | |||
833 | return 0; | 828 | return 0; |
834 | 829 | ||
835 | fail: | 830 | fail: |
836 | for (j = 0; j < i; j++) | 831 | for (j = 0; j < i; j++) |
837 | sk_release_kernel(__icmpv6_sk[j]); | 832 | sk_release_kernel(net->ipv6.icmp_sk[j]); |
838 | 833 | kfree(net->ipv6.icmp_sk); | |
839 | return err; | 834 | return err; |
840 | } | 835 | } |
841 | 836 | ||
842 | void icmpv6_cleanup(void) | 837 | static void __net_exit icmpv6_sk_exit(struct net *net) |
843 | { | 838 | { |
844 | int i; | 839 | int i; |
845 | 840 | ||
846 | for_each_possible_cpu(i) { | 841 | for_each_possible_cpu(i) { |
847 | sk_release_kernel(__icmpv6_sk[i]); | 842 | sk_release_kernel(net->ipv6.icmp_sk[i]); |
848 | } | 843 | } |
844 | kfree(net->ipv6.icmp_sk); | ||
845 | } | ||
846 | |||
847 | static struct pernet_operations __net_initdata icmpv6_sk_ops = { | ||
848 | .init = icmpv6_sk_init, | ||
849 | .exit = icmpv6_sk_exit, | ||
850 | }; | ||
851 | |||
852 | int __init icmpv6_init(void) | ||
853 | { | ||
854 | int err; | ||
855 | |||
856 | err = register_pernet_subsys(&icmpv6_sk_ops); | ||
857 | if (err < 0) | ||
858 | return err; | ||
859 | |||
860 | err = -EAGAIN; | ||
861 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) | ||
862 | goto fail; | ||
863 | return 0; | ||
864 | |||
865 | fail: | ||
866 | printk(KERN_ERR "Failed to register ICMP6 protocol\n"); | ||
867 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
868 | return err; | ||
869 | } | ||
870 | |||
871 | void __exit icmpv6_cleanup(void) | ||
872 | { | ||
873 | unregister_pernet_subsys(&icmpv6_sk_ops); | ||
849 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); | 874 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); |
850 | } | 875 | } |
851 | 876 | ||
877 | |||
852 | static const struct icmp6_err { | 878 | static const struct icmp6_err { |
853 | int err; | 879 | int err; |
854 | int fatal; | 880 | int fatal; |