diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 58 |
1 files changed, 24 insertions, 34 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a7bda0757053..498b927f68be 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -289,19 +289,19 @@ static int snmp6_alloc_dev(struct inet6_dev *idev) | |||
289 | sizeof(struct ipstats_mib), | 289 | sizeof(struct ipstats_mib), |
290 | __alignof__(struct ipstats_mib)) < 0) | 290 | __alignof__(struct ipstats_mib)) < 0) |
291 | goto err_ip; | 291 | goto err_ip; |
292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, | 292 | idev->stats.icmpv6dev = kzalloc(sizeof(struct icmpv6_mib_device), |
293 | sizeof(struct icmpv6_mib), | 293 | GFP_KERNEL); |
294 | __alignof__(struct icmpv6_mib)) < 0) | 294 | if (!idev->stats.icmpv6dev) |
295 | goto err_icmp; | 295 | goto err_icmp; |
296 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, | 296 | idev->stats.icmpv6msgdev = kzalloc(sizeof(struct icmpv6msg_mib_device), |
297 | sizeof(struct icmpv6msg_mib), | 297 | GFP_KERNEL); |
298 | __alignof__(struct icmpv6msg_mib)) < 0) | 298 | if (!idev->stats.icmpv6msgdev) |
299 | goto err_icmpmsg; | 299 | goto err_icmpmsg; |
300 | 300 | ||
301 | return 0; | 301 | return 0; |
302 | 302 | ||
303 | err_icmpmsg: | 303 | err_icmpmsg: |
304 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); | 304 | kfree(idev->stats.icmpv6dev); |
305 | err_icmp: | 305 | err_icmp: |
306 | snmp_mib_free((void __percpu **)idev->stats.ipv6); | 306 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
307 | err_ip: | 307 | err_ip: |
@@ -310,19 +310,13 @@ err_ip: | |||
310 | 310 | ||
311 | static void snmp6_free_dev(struct inet6_dev *idev) | 311 | static void snmp6_free_dev(struct inet6_dev *idev) |
312 | { | 312 | { |
313 | snmp_mib_free((void __percpu **)idev->stats.icmpv6msg); | 313 | kfree(idev->stats.icmpv6msgdev); |
314 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); | 314 | kfree(idev->stats.icmpv6dev); |
315 | snmp_mib_free((void __percpu **)idev->stats.ipv6); | 315 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
316 | } | 316 | } |
317 | 317 | ||
318 | /* Nobody refers to this device, we may destroy it. */ | 318 | /* Nobody refers to this device, we may destroy it. */ |
319 | 319 | ||
320 | static void in6_dev_finish_destroy_rcu(struct rcu_head *head) | ||
321 | { | ||
322 | struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu); | ||
323 | kfree(idev); | ||
324 | } | ||
325 | |||
326 | void in6_dev_finish_destroy(struct inet6_dev *idev) | 320 | void in6_dev_finish_destroy(struct inet6_dev *idev) |
327 | { | 321 | { |
328 | struct net_device *dev = idev->dev; | 322 | struct net_device *dev = idev->dev; |
@@ -339,7 +333,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
339 | return; | 333 | return; |
340 | } | 334 | } |
341 | snmp6_free_dev(idev); | 335 | snmp6_free_dev(idev); |
342 | call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu); | 336 | kfree_rcu(idev, rcu); |
343 | } | 337 | } |
344 | 338 | ||
345 | EXPORT_SYMBOL(in6_dev_finish_destroy); | 339 | EXPORT_SYMBOL(in6_dev_finish_destroy); |
@@ -535,12 +529,6 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
535 | } | 529 | } |
536 | #endif | 530 | #endif |
537 | 531 | ||
538 | static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head) | ||
539 | { | ||
540 | struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu); | ||
541 | kfree(ifp); | ||
542 | } | ||
543 | |||
544 | /* Nobody refers to this ifaddr, destroy it */ | 532 | /* Nobody refers to this ifaddr, destroy it */ |
545 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | 533 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) |
546 | { | 534 | { |
@@ -561,7 +549,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
561 | } | 549 | } |
562 | dst_release(&ifp->rt->dst); | 550 | dst_release(&ifp->rt->dst); |
563 | 551 | ||
564 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); | 552 | kfree_rcu(ifp, rcu); |
565 | } | 553 | } |
566 | 554 | ||
567 | static void | 555 | static void |
@@ -825,6 +813,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
825 | dst_release(&rt->dst); | 813 | dst_release(&rt->dst); |
826 | } | 814 | } |
827 | 815 | ||
816 | /* clean up prefsrc entries */ | ||
817 | rt6_remove_prefsrc(ifp); | ||
828 | out: | 818 | out: |
829 | in6_ifa_put(ifp); | 819 | in6_ifa_put(ifp); |
830 | } | 820 | } |
@@ -1281,7 +1271,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1281 | return cnt; | 1271 | return cnt; |
1282 | } | 1272 | } |
1283 | 1273 | ||
1284 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | 1274 | int ipv6_chk_addr(struct net *net, const struct in6_addr *addr, |
1285 | struct net_device *dev, int strict) | 1275 | struct net_device *dev, int strict) |
1286 | { | 1276 | { |
1287 | struct inet6_ifaddr *ifp; | 1277 | struct inet6_ifaddr *ifp; |
@@ -1324,7 +1314,7 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | |||
1324 | return false; | 1314 | return false; |
1325 | } | 1315 | } |
1326 | 1316 | ||
1327 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | 1317 | int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) |
1328 | { | 1318 | { |
1329 | struct inet6_dev *idev; | 1319 | struct inet6_dev *idev; |
1330 | struct inet6_ifaddr *ifa; | 1320 | struct inet6_ifaddr *ifa; |
@@ -1455,7 +1445,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1455 | 1445 | ||
1456 | /* Join to solicited addr multicast group. */ | 1446 | /* Join to solicited addr multicast group. */ |
1457 | 1447 | ||
1458 | void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr) | 1448 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) |
1459 | { | 1449 | { |
1460 | struct in6_addr maddr; | 1450 | struct in6_addr maddr; |
1461 | 1451 | ||
@@ -1466,7 +1456,7 @@ void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr) | |||
1466 | ipv6_dev_mc_inc(dev, &maddr); | 1456 | ipv6_dev_mc_inc(dev, &maddr); |
1467 | } | 1457 | } |
1468 | 1458 | ||
1469 | void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr) | 1459 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) |
1470 | { | 1460 | { |
1471 | struct in6_addr maddr; | 1461 | struct in6_addr maddr; |
1472 | 1462 | ||
@@ -2111,7 +2101,7 @@ err_exit: | |||
2111 | /* | 2101 | /* |
2112 | * Manual configuration of address on an interface | 2102 | * Manual configuration of address on an interface |
2113 | */ | 2103 | */ |
2114 | static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | 2104 | static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx, |
2115 | unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, | 2105 | unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, |
2116 | __u32 valid_lft) | 2106 | __u32 valid_lft) |
2117 | { | 2107 | { |
@@ -2185,7 +2175,7 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2185 | return PTR_ERR(ifp); | 2175 | return PTR_ERR(ifp); |
2186 | } | 2176 | } |
2187 | 2177 | ||
2188 | static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | 2178 | static int inet6_addr_del(struct net *net, int ifindex, const struct in6_addr *pfx, |
2189 | unsigned int plen) | 2179 | unsigned int plen) |
2190 | { | 2180 | { |
2191 | struct inet6_ifaddr *ifp; | 2181 | struct inet6_ifaddr *ifp; |
@@ -2348,7 +2338,7 @@ static void init_loopback(struct net_device *dev) | |||
2348 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); | 2338 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
2349 | } | 2339 | } |
2350 | 2340 | ||
2351 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) | 2341 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) |
2352 | { | 2342 | { |
2353 | struct inet6_ifaddr * ifp; | 2343 | struct inet6_ifaddr * ifp; |
2354 | u32 addr_flags = IFA_F_PERMANENT; | 2344 | u32 addr_flags = IFA_F_PERMANENT; |
@@ -3119,7 +3109,7 @@ void if6_proc_exit(void) | |||
3119 | 3109 | ||
3120 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 3110 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
3121 | /* Check if address is a home address configured on any interface. */ | 3111 | /* Check if address is a home address configured on any interface. */ |
3122 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | 3112 | int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr) |
3123 | { | 3113 | { |
3124 | int ret = 0; | 3114 | int ret = 0; |
3125 | struct inet6_ifaddr *ifp = NULL; | 3115 | struct inet6_ifaddr *ifp = NULL; |
@@ -3836,7 +3826,7 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
3836 | + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */ | 3826 | + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */ |
3837 | } | 3827 | } |
3838 | 3828 | ||
3839 | static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | 3829 | static inline void __snmp6_fill_statsdev(u64 *stats, atomic_long_t *mib, |
3840 | int items, int bytes) | 3830 | int items, int bytes) |
3841 | { | 3831 | { |
3842 | int i; | 3832 | int i; |
@@ -3846,7 +3836,7 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
3846 | /* Use put_unaligned() because stats may not be aligned for u64. */ | 3836 | /* Use put_unaligned() because stats may not be aligned for u64. */ |
3847 | put_unaligned(items, &stats[0]); | 3837 | put_unaligned(items, &stats[0]); |
3848 | for (i = 1; i < items; i++) | 3838 | for (i = 1; i < items; i++) |
3849 | put_unaligned(snmp_fold_field(mib, i), &stats[i]); | 3839 | put_unaligned(atomic_long_read(&mib[i]), &stats[i]); |
3850 | 3840 | ||
3851 | memset(&stats[items], 0, pad); | 3841 | memset(&stats[items], 0, pad); |
3852 | } | 3842 | } |
@@ -3875,7 +3865,7 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | |||
3875 | IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp)); | 3865 | IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp)); |
3876 | break; | 3866 | break; |
3877 | case IFLA_INET6_ICMP6STATS: | 3867 | case IFLA_INET6_ICMP6STATS: |
3878 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | 3868 | __snmp6_fill_statsdev(stats, idev->stats.icmpv6dev->mibs, ICMP6_MIB_MAX, bytes); |
3879 | break; | 3869 | break; |
3880 | } | 3870 | } |
3881 | } | 3871 | } |