diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-03-20 20:05:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 20:05:13 -0500 |
commit | 270972554c91acd29412d8b6a10e606041012106 (patch) | |
tree | 1d8f563c5c79ccd805d3ab8c5acfe1ceb73b08db /net/ipv6/route.c | |
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/route.c')
-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 a7030fed1a18..8ba8900c0a5f 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, | |||
218 | return rt; | 218 | return rt; |
219 | } | 219 | } |
220 | 220 | ||
221 | #ifdef CONFIG_IPV6_ROUTER_PREF | ||
222 | static void rt6_probe(struct rt6_info *rt) | ||
223 | { | ||
224 | struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL; | ||
225 | /* | ||
226 | * Okay, this does not seem to be appropriate | ||
227 | * for now, however, we need to check if it | ||
228 | * is really so; aka Router Reachability Probing. | ||
229 | * | ||
230 | * Router Reachability Probe MUST be rate-limited | ||
231 | * to no more than one per minute. | ||
232 | */ | ||
233 | if (!neigh || (neigh->nud_state & NUD_VALID)) | ||
234 | return; | ||
235 | read_lock_bh(&neigh->lock); | ||
236 | if (!(neigh->nud_state & NUD_VALID) && | ||
237 | time_after(jiffies, neigh->updated + 60 * HZ)) { | ||
238 | struct in6_addr mcaddr; | ||
239 | struct in6_addr *target; | ||
240 | |||
241 | neigh->updated = jiffies; | ||
242 | read_unlock_bh(&neigh->lock); | ||
243 | |||
244 | target = (struct in6_addr *)&neigh->primary_key; | ||
245 | addrconf_addr_solict_mult(target, &mcaddr); | ||
246 | ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL); | ||
247 | } else | ||
248 | read_unlock_bh(&neigh->lock); | ||
249 | } | ||
250 | #else | ||
251 | static inline void rt6_probe(struct rt6_info *rt) | ||
252 | { | ||
253 | return; | ||
254 | } | ||
255 | #endif | ||
256 | |||
221 | /* | 257 | /* |
222 | * Default Router Selection (RFC 2461 6.3.6) | 258 | * Default Router Selection (RFC 2461 6.3.6) |
223 | */ | 259 | */ |
@@ -287,8 +323,11 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, | |||
287 | continue; | 323 | continue; |
288 | 324 | ||
289 | if (m > mpri) { | 325 | if (m > mpri) { |
326 | rt6_probe(match); | ||
290 | match = rt; | 327 | match = rt; |
291 | mpri = m; | 328 | mpri = m; |
329 | } else { | ||
330 | rt6_probe(rt); | ||
292 | } | 331 | } |
293 | } | 332 | } |
294 | 333 | ||