diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2008-04-16 04:05:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-16 04:05:32 -0400 |
commit | 44d3c299dcfee094f10e0c686ad6588fd36d4f8f (patch) | |
tree | 437aa81b715eee3805ca016df77923c3cb770892 /net/ipv4/ipip.c | |
parent | cec3ffae1a019f02cd6b5fa291f279c8e9f86157 (diff) |
[IPIP]: Make tunnels hashes per net.
Either net or ipip_net already exists in all the required
places, so just use one.
Besides, tune net_init and net_exit calls to respectively
initialize the hashes and destroy devices.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r-- | net/ipv4/ipip.c | 68 |
1 files changed, 36 insertions, 32 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index da7147090a19..9c2939ba7b94 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -123,6 +123,12 @@ | |||
123 | 123 | ||
124 | static int ipip_net_id; | 124 | static int ipip_net_id; |
125 | struct ipip_net { | 125 | struct ipip_net { |
126 | struct ip_tunnel *tunnels_r_l[HASH_SIZE]; | ||
127 | struct ip_tunnel *tunnels_r[HASH_SIZE]; | ||
128 | struct ip_tunnel *tunnels_l[HASH_SIZE]; | ||
129 | struct ip_tunnel *tunnels_wc[1]; | ||
130 | struct ip_tunnel **tunnels[4]; | ||
131 | |||
126 | struct net_device *fb_tunnel_dev; | 132 | struct net_device *fb_tunnel_dev; |
127 | }; | 133 | }; |
128 | 134 | ||
@@ -130,12 +136,6 @@ static int ipip_fb_tunnel_init(struct net_device *dev); | |||
130 | static int ipip_tunnel_init(struct net_device *dev); | 136 | static int ipip_tunnel_init(struct net_device *dev); |
131 | static void ipip_tunnel_setup(struct net_device *dev); | 137 | static void ipip_tunnel_setup(struct net_device *dev); |
132 | 138 | ||
133 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; | ||
134 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; | ||
135 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; | ||
136 | static struct ip_tunnel *tunnels_wc[1]; | ||
137 | static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; | ||
138 | |||
139 | static DEFINE_RWLOCK(ipip_lock); | 139 | static DEFINE_RWLOCK(ipip_lock); |
140 | 140 | ||
141 | static struct ip_tunnel * ipip_tunnel_lookup(struct net *net, | 141 | static struct ip_tunnel * ipip_tunnel_lookup(struct net *net, |
@@ -144,21 +144,22 @@ static struct ip_tunnel * ipip_tunnel_lookup(struct net *net, | |||
144 | unsigned h0 = HASH(remote); | 144 | unsigned h0 = HASH(remote); |
145 | unsigned h1 = HASH(local); | 145 | unsigned h1 = HASH(local); |
146 | struct ip_tunnel *t; | 146 | struct ip_tunnel *t; |
147 | struct ipip_net *ipn = net_generic(net, ipip_net_id); | ||
147 | 148 | ||
148 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { | 149 | for (t = ipn->tunnels_r_l[h0^h1]; t; t = t->next) { |
149 | if (local == t->parms.iph.saddr && | 150 | if (local == t->parms.iph.saddr && |
150 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 151 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
151 | return t; | 152 | return t; |
152 | } | 153 | } |
153 | for (t = tunnels_r[h0]; t; t = t->next) { | 154 | for (t = ipn->tunnels_r[h0]; t; t = t->next) { |
154 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 155 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
155 | return t; | 156 | return t; |
156 | } | 157 | } |
157 | for (t = tunnels_l[h1]; t; t = t->next) { | 158 | for (t = ipn->tunnels_l[h1]; t; t = t->next) { |
158 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) | 159 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) |
159 | return t; | 160 | return t; |
160 | } | 161 | } |
161 | if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) | 162 | if ((t = ipn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) |
162 | return t; | 163 | return t; |
163 | return NULL; | 164 | return NULL; |
164 | } | 165 | } |
@@ -179,7 +180,7 @@ static struct ip_tunnel **__ipip_bucket(struct ipip_net *ipn, | |||
179 | prio |= 1; | 180 | prio |= 1; |
180 | h ^= HASH(local); | 181 | h ^= HASH(local); |
181 | } | 182 | } |
182 | return &tunnels[prio][h]; | 183 | return &ipn->tunnels[prio][h]; |
183 | } | 184 | } |
184 | 185 | ||
185 | static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn, | 186 | static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn, |
@@ -266,7 +267,7 @@ static void ipip_tunnel_uninit(struct net_device *dev) | |||
266 | 267 | ||
267 | if (dev == ipn->fb_tunnel_dev) { | 268 | if (dev == ipn->fb_tunnel_dev) { |
268 | write_lock_bh(&ipip_lock); | 269 | write_lock_bh(&ipip_lock); |
269 | tunnels_wc[0] = NULL; | 270 | ipn->tunnels_wc[0] = NULL; |
270 | write_unlock_bh(&ipip_lock); | 271 | write_unlock_bh(&ipip_lock); |
271 | } else | 272 | } else |
272 | ipip_tunnel_unlink(ipn, netdev_priv(dev)); | 273 | ipip_tunnel_unlink(ipn, netdev_priv(dev)); |
@@ -861,6 +862,7 @@ static int ipip_fb_tunnel_init(struct net_device *dev) | |||
861 | { | 862 | { |
862 | struct ip_tunnel *tunnel = netdev_priv(dev); | 863 | struct ip_tunnel *tunnel = netdev_priv(dev); |
863 | struct iphdr *iph = &tunnel->parms.iph; | 864 | struct iphdr *iph = &tunnel->parms.iph; |
865 | struct ipip_net *ipn = net_generic(dev_net(dev), ipip_net_id); | ||
864 | 866 | ||
865 | tunnel->dev = dev; | 867 | tunnel->dev = dev; |
866 | strcpy(tunnel->parms.name, dev->name); | 868 | strcpy(tunnel->parms.name, dev->name); |
@@ -870,7 +872,7 @@ static int ipip_fb_tunnel_init(struct net_device *dev) | |||
870 | iph->ihl = 5; | 872 | iph->ihl = 5; |
871 | 873 | ||
872 | dev_hold(dev); | 874 | dev_hold(dev); |
873 | tunnels_wc[0] = tunnel; | 875 | ipn->tunnels_wc[0] = tunnel; |
874 | return 0; | 876 | return 0; |
875 | } | 877 | } |
876 | 878 | ||
@@ -883,13 +885,27 @@ static struct xfrm_tunnel ipip_handler = { | |||
883 | static char banner[] __initdata = | 885 | static char banner[] __initdata = |
884 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; | 886 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; |
885 | 887 | ||
888 | static void ipip_destroy_tunnels(struct ipip_net *ipn) | ||
889 | { | ||
890 | int prio; | ||
891 | |||
892 | for (prio = 1; prio < 4; prio++) { | ||
893 | int h; | ||
894 | for (h = 0; h < HASH_SIZE; h++) { | ||
895 | struct ip_tunnel *t; | ||
896 | while ((t = ipn->tunnels[prio][h]) != NULL) | ||
897 | unregister_netdevice(t->dev); | ||
898 | } | ||
899 | } | ||
900 | } | ||
901 | |||
886 | static int ipip_init_net(struct net *net) | 902 | static int ipip_init_net(struct net *net) |
887 | { | 903 | { |
888 | int err; | 904 | int err; |
889 | struct ipip_net *ipn; | 905 | struct ipip_net *ipn; |
890 | 906 | ||
891 | err = -ENOMEM; | 907 | err = -ENOMEM; |
892 | ipn = kmalloc(sizeof(struct ipip_net), GFP_KERNEL); | 908 | ipn = kzalloc(sizeof(struct ipip_net), GFP_KERNEL); |
893 | if (ipn == NULL) | 909 | if (ipn == NULL) |
894 | goto err_alloc; | 910 | goto err_alloc; |
895 | 911 | ||
@@ -897,6 +913,11 @@ static int ipip_init_net(struct net *net) | |||
897 | if (err < 0) | 913 | if (err < 0) |
898 | goto err_assign; | 914 | goto err_assign; |
899 | 915 | ||
916 | ipn->tunnels[0] = ipn->tunnels_wc; | ||
917 | ipn->tunnels[1] = ipn->tunnels_l; | ||
918 | ipn->tunnels[2] = ipn->tunnels_r; | ||
919 | ipn->tunnels[3] = ipn->tunnels_r_l; | ||
920 | |||
900 | ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), | 921 | ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), |
901 | "tunl0", | 922 | "tunl0", |
902 | ipip_tunnel_setup); | 923 | ipip_tunnel_setup); |
@@ -929,6 +950,7 @@ static void ipip_exit_net(struct net *net) | |||
929 | 950 | ||
930 | ipn = net_generic(net, ipip_net_id); | 951 | ipn = net_generic(net, ipip_net_id); |
931 | rtnl_lock(); | 952 | rtnl_lock(); |
953 | ipip_destroy_tunnels(ipn); | ||
932 | unregister_netdevice(ipn->fb_tunnel_dev); | 954 | unregister_netdevice(ipn->fb_tunnel_dev); |
933 | rtnl_unlock(); | 955 | rtnl_unlock(); |
934 | kfree(ipn); | 956 | kfree(ipn); |
@@ -957,29 +979,11 @@ static int __init ipip_init(void) | |||
957 | return err; | 979 | return err; |
958 | } | 980 | } |
959 | 981 | ||
960 | static void __exit ipip_destroy_tunnels(void) | ||
961 | { | ||
962 | int prio; | ||
963 | |||
964 | for (prio = 1; prio < 4; prio++) { | ||
965 | int h; | ||
966 | for (h = 0; h < HASH_SIZE; h++) { | ||
967 | struct ip_tunnel *t; | ||
968 | while ((t = tunnels[prio][h]) != NULL) | ||
969 | unregister_netdevice(t->dev); | ||
970 | } | ||
971 | } | ||
972 | } | ||
973 | |||
974 | static void __exit ipip_fini(void) | 982 | static void __exit ipip_fini(void) |
975 | { | 983 | { |
976 | if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) | 984 | if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) |
977 | printk(KERN_INFO "ipip close: can't deregister tunnel\n"); | 985 | printk(KERN_INFO "ipip close: can't deregister tunnel\n"); |
978 | 986 | ||
979 | rtnl_lock(); | ||
980 | ipip_destroy_tunnels(); | ||
981 | rtnl_unlock(); | ||
982 | |||
983 | unregister_pernet_gen_device(ipip_net_id, &ipip_net_ops); | 987 | unregister_pernet_gen_device(ipip_net_id, &ipip_net_ops); |
984 | } | 988 | } |
985 | 989 | ||