aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/route.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c1ee3813e1ae..f54e3a101098 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -476,6 +476,24 @@ out:
476} 476}
477 477
478#ifdef CONFIG_IPV6_ROUTER_PREF 478#ifdef CONFIG_IPV6_ROUTER_PREF
479struct __rt6_probe_work {
480 struct work_struct work;
481 struct in6_addr target;
482 struct net_device *dev;
483};
484
485static void rt6_probe_deferred(struct work_struct *w)
486{
487 struct in6_addr mcaddr;
488 struct __rt6_probe_work *work =
489 container_of(w, struct __rt6_probe_work, work);
490
491 addrconf_addr_solict_mult(&work->target, &mcaddr);
492 ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL);
493 dev_put(work->dev);
494 kfree(w);
495}
496
479static void rt6_probe(struct rt6_info *rt) 497static void rt6_probe(struct rt6_info *rt)
480{ 498{
481 struct neighbour *neigh; 499 struct neighbour *neigh;
@@ -499,17 +517,23 @@ static void rt6_probe(struct rt6_info *rt)
499 517
500 if (!neigh || 518 if (!neigh ||
501 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { 519 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
502 struct in6_addr mcaddr; 520 struct __rt6_probe_work *work;
503 struct in6_addr *target; 521
522 work = kmalloc(sizeof(*work), GFP_ATOMIC);
504 523
505 if (neigh) { 524 if (neigh && work)
506 neigh->updated = jiffies; 525 neigh->updated = jiffies;
526
527 if (neigh)
507 write_unlock(&neigh->lock); 528 write_unlock(&neigh->lock);
508 }
509 529
510 target = (struct in6_addr *)&rt->rt6i_gateway; 530 if (work) {
511 addrconf_addr_solict_mult(target, &mcaddr); 531 INIT_WORK(&work->work, rt6_probe_deferred);
512 ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); 532 work->target = rt->rt6i_gateway;
533 dev_hold(rt->dst.dev);
534 work->dev = rt->dst.dev;
535 schedule_work(&work->work);
536 }
513 } else { 537 } else {
514out: 538out:
515 write_unlock(&neigh->lock); 539 write_unlock(&neigh->lock);