Index: sys/netinet6/nd6_rtr.c =================================================================== --- sys/netinet6/nd6_rtr.c +++ sys/netinet6/nd6_rtr.c @@ -915,6 +915,18 @@ /* NOTREACHED */ } +static bool +is_dr_reachable(const struct nd_defrouter *dr) { + struct llentry *ln = NULL; + + ln = nd6_lookup(&dr->rtaddr, LLE_SF(AF_INET6, 0), dr->ifp); + if (ln == NULL) + return (false); + bool reachable = ND6_IS_LLINFO_PROBREACH(ln); + LLE_RUNLOCK(ln); + return reachable; +} + /* * Default Router Selection according to Section 6.3.6 of RFC 2461 and * draft-ietf-ipngwg-router-selection: @@ -945,12 +957,12 @@ { struct epoch_tracker et; struct nd_defrouter *dr, *selected_dr, *installed_dr; - struct llentry *ln = NULL; if (fibnum == RT_ALL_FIBS) { for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { defrouter_select_fib(fibnum); } + return; } ND6_RLOCK(); @@ -969,21 +981,17 @@ * the ordering rule of the list described in defrtrlist_update(). */ selected_dr = installed_dr = NULL; + NET_EPOCH_ENTER(et); TAILQ_FOREACH(dr, &V_nd6_defrouter, dr_entry) { - NET_EPOCH_ENTER(et); - if (selected_dr == NULL && dr->ifp->if_fib == fibnum && - (ln = nd6_lookup(&dr->rtaddr, LLE_SF(AF_INET6, 0), dr->ifp)) && - ND6_IS_LLINFO_PROBREACH(ln)) { + if (dr->ifp->if_fib != fibnum) + continue; + + if (selected_dr == NULL && is_dr_reachable(dr)) { selected_dr = dr; defrouter_ref(selected_dr); } - NET_EPOCH_EXIT(et); - if (ln != NULL) { - LLE_RUNLOCK(ln); - ln = NULL; - } - if (dr->installed && dr->ifp->if_fib == fibnum) { + if (dr->installed) { if (installed_dr == NULL) { installed_dr = dr; defrouter_ref(installed_dr); @@ -997,6 +1005,7 @@ } } } + /* * If none of the default routers was found to be reachable, * round-robin the list regardless of preference. @@ -1021,22 +1030,14 @@ } } } else if (installed_dr != NULL) { - NET_EPOCH_ENTER(et); - if ((ln = nd6_lookup(&installed_dr->rtaddr, 0, - installed_dr->ifp)) && - ND6_IS_LLINFO_PROBREACH(ln) && - installed_dr->ifp->if_fib == fibnum && + if (is_dr_reachable(installed_dr) && rtpref(selected_dr) <= rtpref(installed_dr)) { defrouter_rele(selected_dr); selected_dr = installed_dr; } - NET_EPOCH_EXIT(et); - if (ln != NULL) - LLE_RUNLOCK(ln); } ND6_RUNLOCK(); - NET_EPOCH_ENTER(et); /* * If we selected a router for this FIB and it's different * than the installed one, remove the installed router and @@ -1807,20 +1808,12 @@ { struct epoch_tracker et; struct nd_pfxrouter *pfxrtr; - struct llentry *ln; - int canreach; ND6_LOCK_ASSERT(); NET_EPOCH_ENTER(et); LIST_FOREACH(pfxrtr, &pr->ndpr_advrtrs, pfr_entry) { - ln = nd6_lookup(&pfxrtr->router->rtaddr, LLE_SF(AF_INET6, 0), - pfxrtr->router->ifp); - if (ln == NULL) - continue; - canreach = ND6_IS_LLINFO_PROBREACH(ln); - LLE_RUNLOCK(ln); - if (canreach) + if (is_dr_reachable(pfxrtr->router)) break; } NET_EPOCH_EXIT(et);