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 | |
| 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>
| -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 | ||
