aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2008-04-16 04:10:26 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-16 04:10:26 -0400
commiteb8ce741a3c4d4ba5f345ff19689c7d2e4555668 (patch)
treee66ef0b4f3e5f13be195e4bdce2ac72d7d10dead /net
parent7daa0004895f0421bff41a3ac0464f2ff4d9cd41 (diff)
[GRE]: Make tunnels hashes per-net.
Very similar to what was done for the IPIP code. Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/ip_gre.c65
1 files changed, 31 insertions, 34 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index a8ec0904e5a6..74d4c515772e 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -124,8 +124,12 @@ static void ipgre_tunnel_setup(struct net_device *dev);
124 124
125static int ipgre_fb_tunnel_init(struct net_device *dev); 125static int ipgre_fb_tunnel_init(struct net_device *dev);
126 126
127#define HASH_SIZE 16
128
127static int ipgre_net_id; 129static int ipgre_net_id;
128struct ipgre_net { 130struct ipgre_net {
131 struct ip_tunnel *tunnels[4][HASH_SIZE];
132
129 struct net_device *fb_tunnel_dev; 133 struct net_device *fb_tunnel_dev;
130}; 134};
131 135
@@ -147,15 +151,12 @@ struct ipgre_net {
147 will match fallback tunnel. 151 will match fallback tunnel.
148 */ 152 */
149 153
150#define HASH_SIZE 16
151#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) 154#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
152 155
153static struct ip_tunnel *tunnels[4][HASH_SIZE]; 156#define tunnels_r_l tunnels[3]
154 157#define tunnels_r tunnels[2]
155#define tunnels_r_l (tunnels[3]) 158#define tunnels_l tunnels[1]
156#define tunnels_r (tunnels[2]) 159#define tunnels_wc tunnels[0]
157#define tunnels_l (tunnels[1])
158#define tunnels_wc (tunnels[0])
159 160
160static DEFINE_RWLOCK(ipgre_lock); 161static DEFINE_RWLOCK(ipgre_lock);
161 162
@@ -169,19 +170,19 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
169 struct ip_tunnel *t; 170 struct ip_tunnel *t;
170 struct ipgre_net *ign = net_generic(net, ipgre_net_id); 171 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
171 172
172 for (t = tunnels_r_l[h0^h1]; t; t = t->next) { 173 for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
173 if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { 174 if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
174 if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) 175 if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
175 return t; 176 return t;
176 } 177 }
177 } 178 }
178 for (t = tunnels_r[h0^h1]; t; t = t->next) { 179 for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
179 if (remote == t->parms.iph.daddr) { 180 if (remote == t->parms.iph.daddr) {
180 if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) 181 if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
181 return t; 182 return t;
182 } 183 }
183 } 184 }
184 for (t = tunnels_l[h1]; t; t = t->next) { 185 for (t = ign->tunnels_l[h1]; t; t = t->next) {
185 if (local == t->parms.iph.saddr || 186 if (local == t->parms.iph.saddr ||
186 (local == t->parms.iph.daddr && 187 (local == t->parms.iph.daddr &&
187 ipv4_is_multicast(local))) { 188 ipv4_is_multicast(local))) {
@@ -189,7 +190,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
189 return t; 190 return t;
190 } 191 }
191 } 192 }
192 for (t = tunnels_wc[h1]; t; t = t->next) { 193 for (t = ign->tunnels_wc[h1]; t; t = t->next) {
193 if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) 194 if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
194 return t; 195 return t;
195 } 196 }
@@ -215,7 +216,7 @@ static struct ip_tunnel **__ipgre_bucket(struct ipgre_net *ign,
215 h ^= HASH(remote); 216 h ^= HASH(remote);
216 } 217 }
217 218
218 return &tunnels[prio][h]; 219 return &ign->tunnels[prio][h];
219} 220}
220 221
221static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign, 222static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign,
@@ -1274,6 +1275,7 @@ static int ipgre_fb_tunnel_init(struct net_device *dev)
1274{ 1275{
1275 struct ip_tunnel *tunnel = netdev_priv(dev); 1276 struct ip_tunnel *tunnel = netdev_priv(dev);
1276 struct iphdr *iph = &tunnel->parms.iph; 1277 struct iphdr *iph = &tunnel->parms.iph;
1278 struct ipgre_net *ign = net_generic(dev_net(dev), ipgre_net_id);
1277 1279
1278 tunnel->dev = dev; 1280 tunnel->dev = dev;
1279 strcpy(tunnel->parms.name, dev->name); 1281 strcpy(tunnel->parms.name, dev->name);
@@ -1284,7 +1286,7 @@ static int ipgre_fb_tunnel_init(struct net_device *dev)
1284 tunnel->hlen = sizeof(struct iphdr) + 4; 1286 tunnel->hlen = sizeof(struct iphdr) + 4;
1285 1287
1286 dev_hold(dev); 1288 dev_hold(dev);
1287 tunnels_wc[0] = tunnel; 1289 ign->tunnels_wc[0] = tunnel;
1288 return 0; 1290 return 0;
1289} 1291}
1290 1292
@@ -1294,13 +1296,27 @@ static struct net_protocol ipgre_protocol = {
1294 .err_handler = ipgre_err, 1296 .err_handler = ipgre_err,
1295}; 1297};
1296 1298
1299static void ipgre_destroy_tunnels(struct ipgre_net *ign)
1300{
1301 int prio;
1302
1303 for (prio = 0; prio < 4; prio++) {
1304 int h;
1305 for (h = 0; h < HASH_SIZE; h++) {
1306 struct ip_tunnel *t;
1307 while ((t = ign->tunnels[prio][h]) != NULL)
1308 unregister_netdevice(t->dev);
1309 }
1310 }
1311}
1312
1297static int ipgre_init_net(struct net *net) 1313static int ipgre_init_net(struct net *net)
1298{ 1314{
1299 int err; 1315 int err;
1300 struct ipgre_net *ign; 1316 struct ipgre_net *ign;
1301 1317
1302 err = -ENOMEM; 1318 err = -ENOMEM;
1303 ign = kmalloc(sizeof(struct ipgre_net), GFP_KERNEL); 1319 ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL);
1304 if (ign == NULL) 1320 if (ign == NULL)
1305 goto err_alloc; 1321 goto err_alloc;
1306 1322
@@ -1339,8 +1355,7 @@ static void ipgre_exit_net(struct net *net)
1339 1355
1340 ign = net_generic(net, ipgre_net_id); 1356 ign = net_generic(net, ipgre_net_id);
1341 rtnl_lock(); 1357 rtnl_lock();
1342 if (net != &init_net) 1358 ipgre_destroy_tunnels(ign);
1343 unregister_netdevice(ign->fb_tunnel_dev);
1344 rtnl_unlock(); 1359 rtnl_unlock();
1345 kfree(ign); 1360 kfree(ign);
1346} 1361}
@@ -1372,29 +1387,11 @@ static int __init ipgre_init(void)
1372 return err; 1387 return err;
1373} 1388}
1374 1389
1375static void __exit ipgre_destroy_tunnels(void)
1376{
1377 int prio;
1378
1379 for (prio = 0; prio < 4; prio++) {
1380 int h;
1381 for (h = 0; h < HASH_SIZE; h++) {
1382 struct ip_tunnel *t;
1383 while ((t = tunnels[prio][h]) != NULL)
1384 unregister_netdevice(t->dev);
1385 }
1386 }
1387}
1388
1389static void __exit ipgre_fini(void) 1390static void __exit ipgre_fini(void)
1390{ 1391{
1391 if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) 1392 if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
1392 printk(KERN_INFO "ipgre close: can't remove protocol\n"); 1393 printk(KERN_INFO "ipgre close: can't remove protocol\n");
1393 1394
1394 rtnl_lock();
1395 ipgre_destroy_tunnels();
1396 rtnl_unlock();
1397
1398 unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); 1395 unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
1399} 1396}
1400 1397