aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipip.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2008-04-16 04:05:32 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-16 04:05:32 -0400
commit44d3c299dcfee094f10e0c686ad6588fd36d4f8f (patch)
tree437aa81b715eee3805ca016df77923c3cb770892 /net/ipv4/ipip.c
parentcec3ffae1a019f02cd6b5fa291f279c8e9f86157 (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.c68
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
124static int ipip_net_id; 124static int ipip_net_id;
125struct ipip_net { 125struct 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);
130static int ipip_tunnel_init(struct net_device *dev); 136static int ipip_tunnel_init(struct net_device *dev);
131static void ipip_tunnel_setup(struct net_device *dev); 137static void ipip_tunnel_setup(struct net_device *dev);
132 138
133static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
134static struct ip_tunnel *tunnels_r[HASH_SIZE];
135static struct ip_tunnel *tunnels_l[HASH_SIZE];
136static struct ip_tunnel *tunnels_wc[1];
137static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
138
139static DEFINE_RWLOCK(ipip_lock); 139static DEFINE_RWLOCK(ipip_lock);
140 140
141static struct ip_tunnel * ipip_tunnel_lookup(struct net *net, 141static 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
185static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn, 186static 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 = {
883static char banner[] __initdata = 885static char banner[] __initdata =
884 KERN_INFO "IPv4 over IPv4 tunneling driver\n"; 886 KERN_INFO "IPv4 over IPv4 tunneling driver\n";
885 887
888static 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
886static int ipip_init_net(struct net *net) 902static 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
960static 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
974static void __exit ipip_fini(void) 982static 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