diff options
author | markj <markj@FreeBSD.org> | 2016-03-17 19:01:44 +0000 |
---|---|---|
committer | markj <markj@FreeBSD.org> | 2016-03-17 19:01:44 +0000 |
commit | 8c873a2b1b739e5168f3c8a74fe25a6e5d4c3b04 (patch) | |
tree | f1a4a3a309fcccdeeb401a3627f503f301ed4bc2 /sys/netinet6 | |
parent | 6b1b5da7587e3a6e2aab4f7b06ae87890f52b730 (diff) | |
download | FreeBSD-src-8c873a2b1b739e5168f3c8a74fe25a6e5d4c3b04.zip FreeBSD-src-8c873a2b1b739e5168f3c8a74fe25a6e5d4c3b04.tar.gz |
Modify defrouter_remove() to perform the router lookup before removal.
This allows some simplification of its callers. No functional change
intended.
Tested by: Larry Rosenman (as part of a larger change)
MFC after: 1 month
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/nd6.h | 2 | ||||
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 31 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 60 |
3 files changed, 39 insertions, 54 deletions
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 4c83467..149e6f5 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -459,7 +459,7 @@ void defrouter_reset(void); void defrouter_select(void); void defrouter_ref(struct nd_defrouter *); void defrouter_rele(struct nd_defrouter *); -void defrouter_remove(struct nd_defrouter *); +bool defrouter_remove(struct in6_addr *, struct ifnet *); void defrouter_unlink(struct nd_defrouter *, struct nd_drhead *); void defrouter_del(struct nd_defrouter *); void prelist_remove(struct nd_prefix *); diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index d528575..d621b52 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -857,30 +857,19 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) * Remove the sender from the Default Router List and * update the Destination Cache entries. */ - struct nd_defrouter *dr; struct ifnet *nd6_ifp; nd6_ifp = lltable_get_ifp(ln->lle_tbl); - ND6_WLOCK(); - dr = defrouter_lookup_locked(&ln->r_l3addr.addr6, - nd6_ifp); - if (dr != NULL) { - /* releases the ND lock */ - defrouter_remove(dr); - dr = NULL; - } else { - ND6_WUNLOCK(); - if ((ND_IFINFO(nd6_ifp)->flags & ND6_IFF_ACCEPT_RTADV) != 0) { - /* - * Even if the neighbor is not in the default - * router list, the neighbor may be used - * as a next hop for some destinations - * (e.g. redirect case). So we must - * call rt6_flush explicitly. - */ - rt6_flush(&ip6->ip6_src, ifp); - } - } + if (!defrouter_remove(&ln->r_l3addr.addr6, nd6_ifp) && + (ND_IFINFO(nd6_ifp)->flags & + ND6_IFF_ACCEPT_RTADV) != 0) + /* + * Even if the neighbor is not in the default + * router list, the neighbor may be used as a + * next hop for some destinations (e.g. redirect + * case). So we must call rt6_flush explicitly. + */ + rt6_flush(&ip6->ip6_src, ifp); } ln->ln_router = is_router; } diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 294c90a..6fee830 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -627,22 +627,26 @@ defrouter_reset(void) } /* - * Remove a router from the global list and free it. - * - * The ND lock must be held and is released before returning. The caller must - * hold a reference on the router object. + * Look up a matching default router list entry and remove it. Returns true if a + * matching entry was found, false otherwise. */ -void -defrouter_remove(struct nd_defrouter *dr) +bool +defrouter_remove(struct in6_addr *addr, struct ifnet *ifp) { + struct nd_defrouter *dr; - ND6_WLOCK_ASSERT(); - KASSERT(dr->refcnt >= 2, ("unexpected refcount 0x%x", dr->refcnt)); + ND6_WLOCK(); + dr = defrouter_lookup_locked(addr, ifp); + if (dr == NULL) { + ND6_WUNLOCK(); + return (false); + } defrouter_unlink(dr, NULL); ND6_WUNLOCK(); defrouter_del(dr); defrouter_rele(dr); + return (true); } /* @@ -850,14 +854,14 @@ defrtrlist_update(struct nd_defrouter *new) struct nd_defrouter *dr, *n; int oldpref; - ND6_WLOCK(); - if ((dr = defrouter_lookup_locked(&new->rtaddr, new->ifp)) != NULL) { - if (new->rtlifetime == 0) { - /* releases the ND lock */ - defrouter_remove(dr); - return (NULL); - } + if (new->rtlifetime == 0) { + defrouter_remove(&new->rtaddr, new->ifp); + return (NULL); + } + ND6_WLOCK(); + dr = defrouter_lookup_locked(&new->rtaddr, new->ifp); + if (dr != NULL) { oldpref = rtpref(dr); /* override */ @@ -881,25 +885,17 @@ defrtrlist_update(struct nd_defrouter *new) */ TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry); n = dr; - goto insert; - } - - /* entry does not exist */ - if (new->rtlifetime == 0) { - ND6_WUNLOCK(); - return (NULL); - } - - n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO); - if (n == NULL) { - ND6_WUNLOCK(); - return (NULL); + } else { + n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO); + if (n == NULL) { + ND6_WUNLOCK(); + return (NULL); + } + memcpy(n, new, sizeof(*n)); + /* Initialize with an extra reference for the caller. */ + refcount_init(&n->refcnt, 2); } - memcpy(n, new, sizeof(*n)); - /* Initialize with an extra reference for the caller. */ - refcount_init(&n->refcnt, 2); -insert: /* * Insert the new router in the Default Router List; * The Default Router List should be in the descending order |