Loading net/ipv6/ip6_tunnel.c +34 −29 Original line number Diff line number Diff line Loading @@ -84,12 +84,11 @@ static int ip6_tnl_net_id; struct ip6_tnl_net { /* the IPv6 tunnel fallback device */ struct net_device *fb_tnl_dev; }; /* lists for storing tunnels in use */ static struct ip6_tnl *tnls_r_l[HASH_SIZE]; static struct ip6_tnl *tnls_wc[1]; static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l }; struct ip6_tnl *tnls_r_l[HASH_SIZE]; struct ip6_tnl *tnls_wc[1]; struct ip6_tnl **tnls[2]; }; /* lock for the tunnel lists */ static DEFINE_RWLOCK(ip6_tnl_lock); Loading Loading @@ -139,14 +138,15 @@ ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local) unsigned h0 = HASH(remote); unsigned h1 = HASH(local); struct ip6_tnl *t; struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); for (t = tnls_r_l[h0 ^ h1]; t; t = t->next) { for (t = ip6n->tnls_r_l[h0 ^ h1]; t; t = t->next) { if (ipv6_addr_equal(local, &t->parms.laddr) && ipv6_addr_equal(remote, &t->parms.raddr) && (t->dev->flags & IFF_UP)) return t; } if ((t = tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP)) if ((t = ip6n->tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP)) return t; return NULL; Loading Loading @@ -175,7 +175,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p) prio = 1; h = HASH(remote) ^ HASH(local); } return &tnls[prio][h]; return &ip6n->tnls[prio][h]; } /** Loading Loading @@ -314,7 +314,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) if (dev == ip6n->fb_tnl_dev) { write_lock_bh(&ip6_tnl_lock); tnls_wc[0] = NULL; ip6n->tnls_wc[0] = NULL; write_unlock_bh(&ip6_tnl_lock); } else { ip6_tnl_unlink(ip6n, t); Loading Loading @@ -1378,10 +1378,13 @@ static int ip6_fb_tnl_dev_init(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ip6_tnl_dev_init_gen(dev); t->parms.proto = IPPROTO_IPV6; dev_hold(dev); tnls_wc[0] = t; ip6n->tnls_wc[0] = t; return 0; } Loading @@ -1397,13 +1400,27 @@ static struct xfrm6_tunnel ip6ip6_handler = { .priority = 1, }; static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) { int h; struct ip6_tnl *t; for (h = 0; h < HASH_SIZE; h++) { while ((t = ip6n->tnls_r_l[h]) != NULL) unregister_netdevice(t->dev); } t = ip6n->tnls_wc[0]; unregister_netdevice(t->dev); } static int ip6_tnl_init_net(struct net *net) { int err; struct ip6_tnl_net *ip6n; err = -ENOMEM; ip6n = kmalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL); ip6n = kzalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL); if (ip6n == NULL) goto err_alloc; Loading @@ -1411,6 +1428,9 @@ static int ip6_tnl_init_net(struct net *net) if (err < 0) goto err_assign; ip6n->tnls[0] = ip6n->tnls_wc; ip6n->tnls[1] = ip6n->tnls_r_l; err = -ENOMEM; ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", ip6_tnl_dev_setup); Loading Loading @@ -1441,6 +1461,9 @@ static void ip6_tnl_exit_net(struct net *net) struct ip6_tnl_net *ip6n; ip6n = net_generic(net, ip6_tnl_net_id); rtnl_lock(); ip6_tnl_destroy_tunnels(ip6n); rtnl_unlock(); kfree(ip6n); } Loading Loading @@ -1483,20 +1506,6 @@ static int __init ip6_tunnel_init(void) return err; } static void __exit ip6_tnl_destroy_tunnels(void) { int h; struct ip6_tnl *t; for (h = 0; h < HASH_SIZE; h++) { while ((t = tnls_r_l[h]) != NULL) unregister_netdevice(t->dev); } t = tnls_wc[0]; unregister_netdevice(t->dev); } /** * ip6_tunnel_cleanup - free resources and unregister protocol **/ Loading @@ -1509,10 +1518,6 @@ static void __exit ip6_tunnel_cleanup(void) if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) printk(KERN_INFO "ip6_tunnel close: can't deregister ip6ip6\n"); rtnl_lock(); ip6_tnl_destroy_tunnels(); rtnl_unlock(); unregister_pernet_gen_device(ip6_tnl_net_id, &ip6_tnl_net_ops); } Loading Loading
net/ipv6/ip6_tunnel.c +34 −29 Original line number Diff line number Diff line Loading @@ -84,12 +84,11 @@ static int ip6_tnl_net_id; struct ip6_tnl_net { /* the IPv6 tunnel fallback device */ struct net_device *fb_tnl_dev; }; /* lists for storing tunnels in use */ static struct ip6_tnl *tnls_r_l[HASH_SIZE]; static struct ip6_tnl *tnls_wc[1]; static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l }; struct ip6_tnl *tnls_r_l[HASH_SIZE]; struct ip6_tnl *tnls_wc[1]; struct ip6_tnl **tnls[2]; }; /* lock for the tunnel lists */ static DEFINE_RWLOCK(ip6_tnl_lock); Loading Loading @@ -139,14 +138,15 @@ ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local) unsigned h0 = HASH(remote); unsigned h1 = HASH(local); struct ip6_tnl *t; struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); for (t = tnls_r_l[h0 ^ h1]; t; t = t->next) { for (t = ip6n->tnls_r_l[h0 ^ h1]; t; t = t->next) { if (ipv6_addr_equal(local, &t->parms.laddr) && ipv6_addr_equal(remote, &t->parms.raddr) && (t->dev->flags & IFF_UP)) return t; } if ((t = tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP)) if ((t = ip6n->tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP)) return t; return NULL; Loading Loading @@ -175,7 +175,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p) prio = 1; h = HASH(remote) ^ HASH(local); } return &tnls[prio][h]; return &ip6n->tnls[prio][h]; } /** Loading Loading @@ -314,7 +314,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) if (dev == ip6n->fb_tnl_dev) { write_lock_bh(&ip6_tnl_lock); tnls_wc[0] = NULL; ip6n->tnls_wc[0] = NULL; write_unlock_bh(&ip6_tnl_lock); } else { ip6_tnl_unlink(ip6n, t); Loading Loading @@ -1378,10 +1378,13 @@ static int ip6_fb_tnl_dev_init(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ip6_tnl_dev_init_gen(dev); t->parms.proto = IPPROTO_IPV6; dev_hold(dev); tnls_wc[0] = t; ip6n->tnls_wc[0] = t; return 0; } Loading @@ -1397,13 +1400,27 @@ static struct xfrm6_tunnel ip6ip6_handler = { .priority = 1, }; static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) { int h; struct ip6_tnl *t; for (h = 0; h < HASH_SIZE; h++) { while ((t = ip6n->tnls_r_l[h]) != NULL) unregister_netdevice(t->dev); } t = ip6n->tnls_wc[0]; unregister_netdevice(t->dev); } static int ip6_tnl_init_net(struct net *net) { int err; struct ip6_tnl_net *ip6n; err = -ENOMEM; ip6n = kmalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL); ip6n = kzalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL); if (ip6n == NULL) goto err_alloc; Loading @@ -1411,6 +1428,9 @@ static int ip6_tnl_init_net(struct net *net) if (err < 0) goto err_assign; ip6n->tnls[0] = ip6n->tnls_wc; ip6n->tnls[1] = ip6n->tnls_r_l; err = -ENOMEM; ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", ip6_tnl_dev_setup); Loading Loading @@ -1441,6 +1461,9 @@ static void ip6_tnl_exit_net(struct net *net) struct ip6_tnl_net *ip6n; ip6n = net_generic(net, ip6_tnl_net_id); rtnl_lock(); ip6_tnl_destroy_tunnels(ip6n); rtnl_unlock(); kfree(ip6n); } Loading Loading @@ -1483,20 +1506,6 @@ static int __init ip6_tunnel_init(void) return err; } static void __exit ip6_tnl_destroy_tunnels(void) { int h; struct ip6_tnl *t; for (h = 0; h < HASH_SIZE; h++) { while ((t = tnls_r_l[h]) != NULL) unregister_netdevice(t->dev); } t = tnls_wc[0]; unregister_netdevice(t->dev); } /** * ip6_tunnel_cleanup - free resources and unregister protocol **/ Loading @@ -1509,10 +1518,6 @@ static void __exit ip6_tunnel_cleanup(void) if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) printk(KERN_INFO "ip6_tunnel close: can't deregister ip6ip6\n"); rtnl_lock(); ip6_tnl_destroy_tunnels(); rtnl_unlock(); unregister_pernet_gen_device(ip6_tnl_net_id, &ip6_tnl_net_ops); } Loading