[IPV6]: ROUTE: Add Router Reachability Probing (RFC4191).
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Tue, 21 Mar 2006 01:05:13 +0000 (17:05 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Mar 2006 01:05:13 +0000 (17:05 -0800)
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/route.c

index a7030fed1a18bdc2decf6dd75724c24a1dac3572..8ba8900c0a5fdec163fb12063df6abd0315fa66f 100644 (file)
@@ -218,6 +218,42 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
        return rt;
 }
 
+#ifdef CONFIG_IPV6_ROUTER_PREF
+static void rt6_probe(struct rt6_info *rt)
+{
+       struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL;
+       /*
+        * Okay, this does not seem to be appropriate
+        * for now, however, we need to check if it
+        * is really so; aka Router Reachability Probing.
+        *
+        * Router Reachability Probe MUST be rate-limited
+        * to no more than one per minute.
+        */
+       if (!neigh || (neigh->nud_state & NUD_VALID))
+               return;
+       read_lock_bh(&neigh->lock);
+       if (!(neigh->nud_state & NUD_VALID) &&
+           time_after(jiffies, neigh->updated + 60 * HZ)) {
+               struct in6_addr mcaddr;
+               struct in6_addr *target;
+
+               neigh->updated = jiffies;
+               read_unlock_bh(&neigh->lock);
+
+               target = (struct in6_addr *)&neigh->primary_key;
+               addrconf_addr_solict_mult(target, &mcaddr);
+               ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL);
+       } else
+               read_unlock_bh(&neigh->lock);
+}
+#else
+static inline void rt6_probe(struct rt6_info *rt)
+{
+       return;
+}
+#endif
+
 /*
  * Default Router Selection (RFC 2461 6.3.6)
  */
@@ -287,8 +323,11 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
                        continue;
 
                if (m > mpri) {
+                       rt6_probe(match);
                        match = rt;
                        mpri = m;
+               } else {
+                       rt6_probe(rt);
                }
        }