aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/route.c39
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
222static 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
251static 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