diff options
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r-- | net/ipv4/ip_gre.c | 88 |
1 files changed, 44 insertions, 44 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 143333852624..f36ce156cac6 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -125,7 +125,7 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev); | |||
125 | 125 | ||
126 | #define HASH_SIZE 16 | 126 | #define HASH_SIZE 16 |
127 | 127 | ||
128 | static int ipgre_net_id; | 128 | static int ipgre_net_id __read_mostly; |
129 | struct ipgre_net { | 129 | struct ipgre_net { |
130 | struct ip_tunnel *tunnels[4][HASH_SIZE]; | 130 | struct ip_tunnel *tunnels[4][HASH_SIZE]; |
131 | 131 | ||
@@ -156,8 +156,13 @@ struct ipgre_net { | |||
156 | #define tunnels_r tunnels[2] | 156 | #define tunnels_r tunnels[2] |
157 | #define tunnels_l tunnels[1] | 157 | #define tunnels_l tunnels[1] |
158 | #define tunnels_wc tunnels[0] | 158 | #define tunnels_wc tunnels[0] |
159 | /* | ||
160 | * Locking : hash tables are protected by RCU and a spinlock | ||
161 | */ | ||
162 | static DEFINE_SPINLOCK(ipgre_lock); | ||
159 | 163 | ||
160 | static DEFINE_RWLOCK(ipgre_lock); | 164 | #define for_each_ip_tunnel_rcu(start) \ |
165 | for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) | ||
161 | 166 | ||
162 | /* Given src, dst and key, find appropriate for input tunnel. */ | 167 | /* Given src, dst and key, find appropriate for input tunnel. */ |
163 | 168 | ||
@@ -175,7 +180,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, | |||
175 | ARPHRD_ETHER : ARPHRD_IPGRE; | 180 | ARPHRD_ETHER : ARPHRD_IPGRE; |
176 | int score, cand_score = 4; | 181 | int score, cand_score = 4; |
177 | 182 | ||
178 | for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { | 183 | for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) { |
179 | if (local != t->parms.iph.saddr || | 184 | if (local != t->parms.iph.saddr || |
180 | remote != t->parms.iph.daddr || | 185 | remote != t->parms.iph.daddr || |
181 | key != t->parms.i_key || | 186 | key != t->parms.i_key || |
@@ -200,7 +205,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, | |||
200 | } | 205 | } |
201 | } | 206 | } |
202 | 207 | ||
203 | for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { | 208 | for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) { |
204 | if (remote != t->parms.iph.daddr || | 209 | if (remote != t->parms.iph.daddr || |
205 | key != t->parms.i_key || | 210 | key != t->parms.i_key || |
206 | !(t->dev->flags & IFF_UP)) | 211 | !(t->dev->flags & IFF_UP)) |
@@ -224,7 +229,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, | |||
224 | } | 229 | } |
225 | } | 230 | } |
226 | 231 | ||
227 | for (t = ign->tunnels_l[h1]; t; t = t->next) { | 232 | for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) { |
228 | if ((local != t->parms.iph.saddr && | 233 | if ((local != t->parms.iph.saddr && |
229 | (local != t->parms.iph.daddr || | 234 | (local != t->parms.iph.daddr || |
230 | !ipv4_is_multicast(local))) || | 235 | !ipv4_is_multicast(local))) || |
@@ -250,7 +255,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, | |||
250 | } | 255 | } |
251 | } | 256 | } |
252 | 257 | ||
253 | for (t = ign->tunnels_wc[h1]; t; t = t->next) { | 258 | for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) { |
254 | if (t->parms.i_key != key || | 259 | if (t->parms.i_key != key || |
255 | !(t->dev->flags & IFF_UP)) | 260 | !(t->dev->flags & IFF_UP)) |
256 | continue; | 261 | continue; |
@@ -276,8 +281,9 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, | |||
276 | if (cand != NULL) | 281 | if (cand != NULL) |
277 | return cand; | 282 | return cand; |
278 | 283 | ||
279 | if (ign->fb_tunnel_dev->flags & IFF_UP) | 284 | dev = ign->fb_tunnel_dev; |
280 | return netdev_priv(ign->fb_tunnel_dev); | 285 | if (dev->flags & IFF_UP) |
286 | return netdev_priv(dev); | ||
281 | 287 | ||
282 | return NULL; | 288 | return NULL; |
283 | } | 289 | } |
@@ -311,10 +317,10 @@ static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t) | |||
311 | { | 317 | { |
312 | struct ip_tunnel **tp = ipgre_bucket(ign, t); | 318 | struct ip_tunnel **tp = ipgre_bucket(ign, t); |
313 | 319 | ||
320 | spin_lock_bh(&ipgre_lock); | ||
314 | t->next = *tp; | 321 | t->next = *tp; |
315 | write_lock_bh(&ipgre_lock); | 322 | rcu_assign_pointer(*tp, t); |
316 | *tp = t; | 323 | spin_unlock_bh(&ipgre_lock); |
317 | write_unlock_bh(&ipgre_lock); | ||
318 | } | 324 | } |
319 | 325 | ||
320 | static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t) | 326 | static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t) |
@@ -323,9 +329,9 @@ static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t) | |||
323 | 329 | ||
324 | for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) { | 330 | for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) { |
325 | if (t == *tp) { | 331 | if (t == *tp) { |
326 | write_lock_bh(&ipgre_lock); | 332 | spin_lock_bh(&ipgre_lock); |
327 | *tp = t->next; | 333 | *tp = t->next; |
328 | write_unlock_bh(&ipgre_lock); | 334 | spin_unlock_bh(&ipgre_lock); |
329 | break; | 335 | break; |
330 | } | 336 | } |
331 | } | 337 | } |
@@ -476,7 +482,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
476 | break; | 482 | break; |
477 | } | 483 | } |
478 | 484 | ||
479 | read_lock(&ipgre_lock); | 485 | rcu_read_lock(); |
480 | t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr, | 486 | t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr, |
481 | flags & GRE_KEY ? | 487 | flags & GRE_KEY ? |
482 | *(((__be32 *)p) + (grehlen / 4) - 1) : 0, | 488 | *(((__be32 *)p) + (grehlen / 4) - 1) : 0, |
@@ -494,7 +500,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
494 | t->err_count = 1; | 500 | t->err_count = 1; |
495 | t->err_time = jiffies; | 501 | t->err_time = jiffies; |
496 | out: | 502 | out: |
497 | read_unlock(&ipgre_lock); | 503 | rcu_read_unlock(); |
498 | return; | 504 | return; |
499 | } | 505 | } |
500 | 506 | ||
@@ -573,7 +579,7 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
573 | 579 | ||
574 | gre_proto = *(__be16 *)(h + 2); | 580 | gre_proto = *(__be16 *)(h + 2); |
575 | 581 | ||
576 | read_lock(&ipgre_lock); | 582 | rcu_read_lock(); |
577 | if ((tunnel = ipgre_tunnel_lookup(skb->dev, | 583 | if ((tunnel = ipgre_tunnel_lookup(skb->dev, |
578 | iph->saddr, iph->daddr, key, | 584 | iph->saddr, iph->daddr, key, |
579 | gre_proto))) { | 585 | gre_proto))) { |
@@ -647,13 +653,13 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
647 | ipgre_ecn_decapsulate(iph, skb); | 653 | ipgre_ecn_decapsulate(iph, skb); |
648 | 654 | ||
649 | netif_rx(skb); | 655 | netif_rx(skb); |
650 | read_unlock(&ipgre_lock); | 656 | rcu_read_unlock(); |
651 | return(0); | 657 | return(0); |
652 | } | 658 | } |
653 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | 659 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
654 | 660 | ||
655 | drop: | 661 | drop: |
656 | read_unlock(&ipgre_lock); | 662 | rcu_read_unlock(); |
657 | drop_nolock: | 663 | drop_nolock: |
658 | kfree_skb(skb); | 664 | kfree_skb(skb); |
659 | return(0); | 665 | return(0); |
@@ -662,7 +668,8 @@ drop_nolock: | |||
662 | static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 668 | static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
663 | { | 669 | { |
664 | struct ip_tunnel *tunnel = netdev_priv(dev); | 670 | struct ip_tunnel *tunnel = netdev_priv(dev); |
665 | struct net_device_stats *stats = &tunnel->dev->stats; | 671 | struct net_device_stats *stats = &dev->stats; |
672 | struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); | ||
666 | struct iphdr *old_iph = ip_hdr(skb); | 673 | struct iphdr *old_iph = ip_hdr(skb); |
667 | struct iphdr *tiph; | 674 | struct iphdr *tiph; |
668 | u8 tos; | 675 | u8 tos; |
@@ -810,7 +817,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
810 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 817 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
811 | if (!new_skb) { | 818 | if (!new_skb) { |
812 | ip_rt_put(rt); | 819 | ip_rt_put(rt); |
813 | stats->tx_dropped++; | 820 | txq->tx_dropped++; |
814 | dev_kfree_skb(skb); | 821 | dev_kfree_skb(skb); |
815 | return NETDEV_TX_OK; | 822 | return NETDEV_TX_OK; |
816 | } | 823 | } |
@@ -1283,33 +1290,27 @@ static const struct net_protocol ipgre_protocol = { | |||
1283 | .netns_ok = 1, | 1290 | .netns_ok = 1, |
1284 | }; | 1291 | }; |
1285 | 1292 | ||
1286 | static void ipgre_destroy_tunnels(struct ipgre_net *ign) | 1293 | static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head) |
1287 | { | 1294 | { |
1288 | int prio; | 1295 | int prio; |
1289 | 1296 | ||
1290 | for (prio = 0; prio < 4; prio++) { | 1297 | for (prio = 0; prio < 4; prio++) { |
1291 | int h; | 1298 | int h; |
1292 | for (h = 0; h < HASH_SIZE; h++) { | 1299 | for (h = 0; h < HASH_SIZE; h++) { |
1293 | struct ip_tunnel *t; | 1300 | struct ip_tunnel *t = ign->tunnels[prio][h]; |
1294 | while ((t = ign->tunnels[prio][h]) != NULL) | 1301 | |
1295 | unregister_netdevice(t->dev); | 1302 | while (t != NULL) { |
1303 | unregister_netdevice_queue(t->dev, head); | ||
1304 | t = t->next; | ||
1305 | } | ||
1296 | } | 1306 | } |
1297 | } | 1307 | } |
1298 | } | 1308 | } |
1299 | 1309 | ||
1300 | static int ipgre_init_net(struct net *net) | 1310 | static int ipgre_init_net(struct net *net) |
1301 | { | 1311 | { |
1312 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); | ||
1302 | int err; | 1313 | int err; |
1303 | struct ipgre_net *ign; | ||
1304 | |||
1305 | err = -ENOMEM; | ||
1306 | ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL); | ||
1307 | if (ign == NULL) | ||
1308 | goto err_alloc; | ||
1309 | |||
1310 | err = net_assign_generic(net, ipgre_net_id, ign); | ||
1311 | if (err < 0) | ||
1312 | goto err_assign; | ||
1313 | 1314 | ||
1314 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0", | 1315 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0", |
1315 | ipgre_tunnel_setup); | 1316 | ipgre_tunnel_setup); |
@@ -1330,27 +1331,26 @@ static int ipgre_init_net(struct net *net) | |||
1330 | err_reg_dev: | 1331 | err_reg_dev: |
1331 | free_netdev(ign->fb_tunnel_dev); | 1332 | free_netdev(ign->fb_tunnel_dev); |
1332 | err_alloc_dev: | 1333 | err_alloc_dev: |
1333 | /* nothing */ | ||
1334 | err_assign: | ||
1335 | kfree(ign); | ||
1336 | err_alloc: | ||
1337 | return err; | 1334 | return err; |
1338 | } | 1335 | } |
1339 | 1336 | ||
1340 | static void ipgre_exit_net(struct net *net) | 1337 | static void ipgre_exit_net(struct net *net) |
1341 | { | 1338 | { |
1342 | struct ipgre_net *ign; | 1339 | struct ipgre_net *ign; |
1340 | LIST_HEAD(list); | ||
1343 | 1341 | ||
1344 | ign = net_generic(net, ipgre_net_id); | 1342 | ign = net_generic(net, ipgre_net_id); |
1345 | rtnl_lock(); | 1343 | rtnl_lock(); |
1346 | ipgre_destroy_tunnels(ign); | 1344 | ipgre_destroy_tunnels(ign, &list); |
1345 | unregister_netdevice_many(&list); | ||
1347 | rtnl_unlock(); | 1346 | rtnl_unlock(); |
1348 | kfree(ign); | ||
1349 | } | 1347 | } |
1350 | 1348 | ||
1351 | static struct pernet_operations ipgre_net_ops = { | 1349 | static struct pernet_operations ipgre_net_ops = { |
1352 | .init = ipgre_init_net, | 1350 | .init = ipgre_init_net, |
1353 | .exit = ipgre_exit_net, | 1351 | .exit = ipgre_exit_net, |
1352 | .id = &ipgre_net_id, | ||
1353 | .size = sizeof(struct ipgre_net), | ||
1354 | }; | 1354 | }; |
1355 | 1355 | ||
1356 | static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) | 1356 | static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) |
@@ -1471,7 +1471,7 @@ static void ipgre_tap_setup(struct net_device *dev) | |||
1471 | dev->features |= NETIF_F_NETNS_LOCAL; | 1471 | dev->features |= NETIF_F_NETNS_LOCAL; |
1472 | } | 1472 | } |
1473 | 1473 | ||
1474 | static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], | 1474 | static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], |
1475 | struct nlattr *data[]) | 1475 | struct nlattr *data[]) |
1476 | { | 1476 | { |
1477 | struct ip_tunnel *nt; | 1477 | struct ip_tunnel *nt; |
@@ -1670,7 +1670,7 @@ static int __init ipgre_init(void) | |||
1670 | return -EAGAIN; | 1670 | return -EAGAIN; |
1671 | } | 1671 | } |
1672 | 1672 | ||
1673 | err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops); | 1673 | err = register_pernet_device(&ipgre_net_ops); |
1674 | if (err < 0) | 1674 | if (err < 0) |
1675 | goto gen_device_failed; | 1675 | goto gen_device_failed; |
1676 | 1676 | ||
@@ -1688,7 +1688,7 @@ out: | |||
1688 | tap_ops_failed: | 1688 | tap_ops_failed: |
1689 | rtnl_link_unregister(&ipgre_link_ops); | 1689 | rtnl_link_unregister(&ipgre_link_ops); |
1690 | rtnl_link_failed: | 1690 | rtnl_link_failed: |
1691 | unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); | 1691 | unregister_pernet_device(&ipgre_net_ops); |
1692 | gen_device_failed: | 1692 | gen_device_failed: |
1693 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); | 1693 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); |
1694 | goto out; | 1694 | goto out; |
@@ -1698,7 +1698,7 @@ static void __exit ipgre_fini(void) | |||
1698 | { | 1698 | { |
1699 | rtnl_link_unregister(&ipgre_tap_ops); | 1699 | rtnl_link_unregister(&ipgre_tap_ops); |
1700 | rtnl_link_unregister(&ipgre_link_ops); | 1700 | rtnl_link_unregister(&ipgre_link_ops); |
1701 | unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); | 1701 | unregister_pernet_device(&ipgre_net_ops); |
1702 | if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) | 1702 | if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) |
1703 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); | 1703 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); |
1704 | } | 1704 | } |