diff options
| author | Pavel Emelyanov <xemul@openvz.org> | 2008-04-16 04:10:05 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-04-16 04:10:05 -0400 |
| commit | 7daa0004895f0421bff41a3ac0464f2ff4d9cd41 (patch) | |
| tree | 59a6666156fe5236604df59ec1e749adb5eec177 /net/ipv4 | |
| parent | 3b4667f3db4d7d0b6d8f35c2ca80333ea141629a (diff) | |
[GRE]: Make the fallback tunnel device per-net.
Everything is prepared for this change now. Create on in
init callback, use it over the code and destroy on net exit.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/ip_gre.c | 63 |
1 files changed, 32 insertions, 31 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 1a17c5beffdc..a8ec0904e5a6 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -126,10 +126,9 @@ static int ipgre_fb_tunnel_init(struct net_device *dev); | |||
| 126 | 126 | ||
| 127 | static int ipgre_net_id; | 127 | static int ipgre_net_id; |
| 128 | struct ipgre_net { | 128 | struct ipgre_net { |
| 129 | struct net_device *fb_tunnel_dev; | ||
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| 131 | static struct net_device *ipgre_fb_tunnel_dev; | ||
| 132 | |||
| 133 | /* Tunnel hash table */ | 132 | /* Tunnel hash table */ |
| 134 | 133 | ||
| 135 | /* | 134 | /* |
| @@ -168,6 +167,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, | |||
| 168 | unsigned h0 = HASH(remote); | 167 | unsigned h0 = HASH(remote); |
| 169 | unsigned h1 = HASH(key); | 168 | unsigned h1 = HASH(key); |
| 170 | struct ip_tunnel *t; | 169 | struct ip_tunnel *t; |
| 170 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); | ||
| 171 | 171 | ||
| 172 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { | 172 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { |
| 173 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { | 173 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { |
| @@ -194,8 +194,8 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, | |||
| 194 | return t; | 194 | return t; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | if (ipgre_fb_tunnel_dev->flags&IFF_UP) | 197 | if (ign->fb_tunnel_dev->flags&IFF_UP) |
| 198 | return netdev_priv(ipgre_fb_tunnel_dev); | 198 | return netdev_priv(ign->fb_tunnel_dev); |
| 199 | return NULL; | 199 | return NULL; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| @@ -977,7 +977,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 977 | switch (cmd) { | 977 | switch (cmd) { |
| 978 | case SIOCGETTUNNEL: | 978 | case SIOCGETTUNNEL: |
| 979 | t = NULL; | 979 | t = NULL; |
| 980 | if (dev == ipgre_fb_tunnel_dev) { | 980 | if (dev == ign->fb_tunnel_dev) { |
| 981 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | 981 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { |
| 982 | err = -EFAULT; | 982 | err = -EFAULT; |
| 983 | break; | 983 | break; |
| @@ -1016,7 +1016,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1016 | 1016 | ||
| 1017 | t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); | 1017 | t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); |
| 1018 | 1018 | ||
| 1019 | if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 1019 | if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
| 1020 | if (t != NULL) { | 1020 | if (t != NULL) { |
| 1021 | if (t->dev != dev) { | 1021 | if (t->dev != dev) { |
| 1022 | err = -EEXIST; | 1022 | err = -EEXIST; |
| @@ -1071,7 +1071,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1071 | if (!capable(CAP_NET_ADMIN)) | 1071 | if (!capable(CAP_NET_ADMIN)) |
| 1072 | goto done; | 1072 | goto done; |
| 1073 | 1073 | ||
| 1074 | if (dev == ipgre_fb_tunnel_dev) { | 1074 | if (dev == ign->fb_tunnel_dev) { |
| 1075 | err = -EFAULT; | 1075 | err = -EFAULT; |
| 1076 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 1076 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
| 1077 | goto done; | 1077 | goto done; |
| @@ -1079,7 +1079,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1079 | if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL) | 1079 | if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL) |
| 1080 | goto done; | 1080 | goto done; |
| 1081 | err = -EPERM; | 1081 | err = -EPERM; |
| 1082 | if (t == netdev_priv(ipgre_fb_tunnel_dev)) | 1082 | if (t == netdev_priv(ign->fb_tunnel_dev)) |
| 1083 | goto done; | 1083 | goto done; |
| 1084 | dev = t->dev; | 1084 | dev = t->dev; |
| 1085 | } | 1085 | } |
| @@ -1270,7 +1270,7 @@ static int ipgre_tunnel_init(struct net_device *dev) | |||
| 1270 | return 0; | 1270 | return 0; |
| 1271 | } | 1271 | } |
| 1272 | 1272 | ||
| 1273 | static int __init ipgre_fb_tunnel_init(struct net_device *dev) | 1273 | static int ipgre_fb_tunnel_init(struct net_device *dev) |
| 1274 | { | 1274 | { |
| 1275 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1275 | struct ip_tunnel *tunnel = netdev_priv(dev); |
| 1276 | struct iphdr *iph = &tunnel->parms.iph; | 1276 | struct iphdr *iph = &tunnel->parms.iph; |
| @@ -1308,8 +1308,25 @@ static int ipgre_init_net(struct net *net) | |||
| 1308 | if (err < 0) | 1308 | if (err < 0) |
| 1309 | goto err_assign; | 1309 | goto err_assign; |
| 1310 | 1310 | ||
| 1311 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0", | ||
| 1312 | ipgre_tunnel_setup); | ||
| 1313 | if (!ign->fb_tunnel_dev) { | ||
| 1314 | err = -ENOMEM; | ||
| 1315 | goto err_alloc_dev; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | ign->fb_tunnel_dev->init = ipgre_fb_tunnel_init; | ||
| 1319 | dev_net_set(ign->fb_tunnel_dev, net); | ||
| 1320 | |||
| 1321 | if ((err = register_netdev(ign->fb_tunnel_dev))) | ||
| 1322 | goto err_reg_dev; | ||
| 1323 | |||
| 1311 | return 0; | 1324 | return 0; |
| 1312 | 1325 | ||
| 1326 | err_reg_dev: | ||
| 1327 | free_netdev(ign->fb_tunnel_dev); | ||
| 1328 | err_alloc_dev: | ||
| 1329 | /* nothing */ | ||
| 1313 | err_assign: | 1330 | err_assign: |
| 1314 | kfree(ign); | 1331 | kfree(ign); |
| 1315 | err_alloc: | 1332 | err_alloc: |
| @@ -1321,6 +1338,10 @@ static void ipgre_exit_net(struct net *net) | |||
| 1321 | struct ipgre_net *ign; | 1338 | struct ipgre_net *ign; |
| 1322 | 1339 | ||
| 1323 | ign = net_generic(net, ipgre_net_id); | 1340 | ign = net_generic(net, ipgre_net_id); |
| 1341 | rtnl_lock(); | ||
| 1342 | if (net != &init_net) | ||
| 1343 | unregister_netdevice(ign->fb_tunnel_dev); | ||
| 1344 | rtnl_unlock(); | ||
| 1324 | kfree(ign); | 1345 | kfree(ign); |
| 1325 | } | 1346 | } |
| 1326 | 1347 | ||
| @@ -1344,31 +1365,11 @@ static int __init ipgre_init(void) | |||
| 1344 | return -EAGAIN; | 1365 | return -EAGAIN; |
| 1345 | } | 1366 | } |
| 1346 | 1367 | ||
| 1347 | ipgre_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0", | ||
| 1348 | ipgre_tunnel_setup); | ||
| 1349 | if (!ipgre_fb_tunnel_dev) { | ||
| 1350 | err = -ENOMEM; | ||
| 1351 | goto err1; | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init; | ||
| 1355 | |||
| 1356 | if ((err = register_netdev(ipgre_fb_tunnel_dev))) | ||
| 1357 | goto err2; | ||
| 1358 | |||
| 1359 | err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops); | 1368 | err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops); |
| 1360 | if (err < 0) | 1369 | if (err < 0) |
| 1361 | goto err3; | 1370 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); |
| 1362 | out: | 1371 | |
| 1363 | return err; | 1372 | return err; |
| 1364 | err2: | ||
| 1365 | free_netdev(ipgre_fb_tunnel_dev); | ||
| 1366 | err1: | ||
| 1367 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); | ||
| 1368 | goto out; | ||
| 1369 | err3: | ||
| 1370 | unregister_netdevice(ipgre_fb_tunnel_dev); | ||
| 1371 | goto err1; | ||
| 1372 | } | 1373 | } |
| 1373 | 1374 | ||
| 1374 | static void __exit ipgre_destroy_tunnels(void) | 1375 | static void __exit ipgre_destroy_tunnels(void) |
