diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-03-20 17:05:13 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 17:05:13 -0800 |
commit | 270972554c91acd29412d8b6a10e606041012106 (patch) | |
tree | 1d8f563c5c79ccd805d3ab8c5acfe1ceb73b08db /net/ipv6 | |
parent | ebacaaa0fdf4402cdf4c8e569f54af36b6f0aa2d (diff) |
[IPV6]: ROUTE: Add Router Reachability Probing (RFC4191).
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/route.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a7030fed1a1..8ba8900c0a5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -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); } } |