diff options
-rw-r--r-- | include/net/ip_tunnels.h | 1 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 7 | ||||
-rw-r--r-- | net/ipv6/sit.c | 19 |
3 files changed, 24 insertions, 3 deletions
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 48ed75c21260..e77c10405d51 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
@@ -129,6 +129,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], | |||
129 | int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], | 129 | int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], |
130 | struct ip_tunnel_parm *p); | 130 | struct ip_tunnel_parm *p); |
131 | void ip_tunnel_setup(struct net_device *dev, int net_id); | 131 | void ip_tunnel_setup(struct net_device *dev, int net_id); |
132 | void ip_tunnel_dst_reset_all(struct ip_tunnel *t); | ||
132 | 133 | ||
133 | /* Extract dsfield from inner protocol */ | 134 | /* Extract dsfield from inner protocol */ |
134 | static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, | 135 | static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 08f8cf99b3a2..78a89e61925d 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -93,13 +93,14 @@ static void tunnel_dst_reset(struct ip_tunnel *t) | |||
93 | tunnel_dst_set(t, NULL); | 93 | tunnel_dst_set(t, NULL); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void tunnel_dst_reset_all(struct ip_tunnel *t) | 96 | void ip_tunnel_dst_reset_all(struct ip_tunnel *t) |
97 | { | 97 | { |
98 | int i; | 98 | int i; |
99 | 99 | ||
100 | for_each_possible_cpu(i) | 100 | for_each_possible_cpu(i) |
101 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); | 101 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); |
102 | } | 102 | } |
103 | EXPORT_SYMBOL(ip_tunnel_dst_reset_all); | ||
103 | 104 | ||
104 | static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) | 105 | static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) |
105 | { | 106 | { |
@@ -713,7 +714,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, | |||
713 | if (set_mtu) | 714 | if (set_mtu) |
714 | dev->mtu = mtu; | 715 | dev->mtu = mtu; |
715 | } | 716 | } |
716 | tunnel_dst_reset_all(t); | 717 | ip_tunnel_dst_reset_all(t); |
717 | netdev_state_change(dev); | 718 | netdev_state_change(dev); |
718 | } | 719 | } |
719 | 720 | ||
@@ -1042,7 +1043,7 @@ void ip_tunnel_uninit(struct net_device *dev) | |||
1042 | if (itn->fb_tunnel_dev != dev) | 1043 | if (itn->fb_tunnel_dev != dev) |
1043 | ip_tunnel_del(netdev_priv(dev)); | 1044 | ip_tunnel_del(netdev_priv(dev)); |
1044 | 1045 | ||
1045 | tunnel_dst_reset_all(tunnel); | 1046 | ip_tunnel_dst_reset_all(tunnel); |
1046 | } | 1047 | } |
1047 | EXPORT_SYMBOL_GPL(ip_tunnel_uninit); | 1048 | EXPORT_SYMBOL_GPL(ip_tunnel_uninit); |
1048 | 1049 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3dfbcf1dcb1c..b4d74c86586c 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -475,6 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
475 | ipip6_tunnel_unlink(sitn, tunnel); | 475 | ipip6_tunnel_unlink(sitn, tunnel); |
476 | ipip6_tunnel_del_prl(tunnel, NULL); | 476 | ipip6_tunnel_del_prl(tunnel, NULL); |
477 | } | 477 | } |
478 | ip_tunnel_dst_reset_all(tunnel); | ||
478 | dev_put(dev); | 479 | dev_put(dev); |
479 | } | 480 | } |
480 | 481 | ||
@@ -1082,6 +1083,7 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) | |||
1082 | t->parms.link = p->link; | 1083 | t->parms.link = p->link; |
1083 | ipip6_tunnel_bind_dev(t->dev); | 1084 | ipip6_tunnel_bind_dev(t->dev); |
1084 | } | 1085 | } |
1086 | ip_tunnel_dst_reset_all(t); | ||
1085 | netdev_state_change(t->dev); | 1087 | netdev_state_change(t->dev); |
1086 | } | 1088 | } |
1087 | 1089 | ||
@@ -1112,6 +1114,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t, | |||
1112 | t->ip6rd.relay_prefix = relay_prefix; | 1114 | t->ip6rd.relay_prefix = relay_prefix; |
1113 | t->ip6rd.prefixlen = ip6rd->prefixlen; | 1115 | t->ip6rd.prefixlen = ip6rd->prefixlen; |
1114 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; | 1116 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; |
1117 | ip_tunnel_dst_reset_all(t); | ||
1115 | netdev_state_change(t->dev); | 1118 | netdev_state_change(t->dev); |
1116 | return 0; | 1119 | return 0; |
1117 | } | 1120 | } |
@@ -1271,6 +1274,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1271 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | 1274 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); |
1272 | break; | 1275 | break; |
1273 | } | 1276 | } |
1277 | ip_tunnel_dst_reset_all(t); | ||
1274 | netdev_state_change(dev); | 1278 | netdev_state_change(dev); |
1275 | break; | 1279 | break; |
1276 | 1280 | ||
@@ -1326,6 +1330,9 @@ static const struct net_device_ops ipip6_netdev_ops = { | |||
1326 | 1330 | ||
1327 | static void ipip6_dev_free(struct net_device *dev) | 1331 | static void ipip6_dev_free(struct net_device *dev) |
1328 | { | 1332 | { |
1333 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
1334 | |||
1335 | free_percpu(tunnel->dst_cache); | ||
1329 | free_percpu(dev->tstats); | 1336 | free_percpu(dev->tstats); |
1330 | free_netdev(dev); | 1337 | free_netdev(dev); |
1331 | } | 1338 | } |
@@ -1375,6 +1382,12 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1375 | u64_stats_init(&ipip6_tunnel_stats->syncp); | 1382 | u64_stats_init(&ipip6_tunnel_stats->syncp); |
1376 | } | 1383 | } |
1377 | 1384 | ||
1385 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
1386 | if (!tunnel->dst_cache) { | ||
1387 | free_percpu(dev->tstats); | ||
1388 | return -ENOMEM; | ||
1389 | } | ||
1390 | |||
1378 | return 0; | 1391 | return 0; |
1379 | } | 1392 | } |
1380 | 1393 | ||
@@ -1405,6 +1418,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1405 | u64_stats_init(&ipip6_fb_stats->syncp); | 1418 | u64_stats_init(&ipip6_fb_stats->syncp); |
1406 | } | 1419 | } |
1407 | 1420 | ||
1421 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
1422 | if (!tunnel->dst_cache) { | ||
1423 | free_percpu(dev->tstats); | ||
1424 | return -ENOMEM; | ||
1425 | } | ||
1426 | |||
1408 | dev_hold(dev); | 1427 | dev_hold(dev); |
1409 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); | 1428 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
1410 | return 0; | 1429 | return 0; |