diff options
author | sam <sam@FreeBSD.org> | 2003-10-04 03:44:50 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2003-10-04 03:44:50 +0000 |
commit | 9d93fce265aeeeb266999d5092d6d4224cc16829 (patch) | |
tree | 7bd40aa381e3ec3f09e84ae6cc70b74bf5683aa2 /sys/netinet6/in6.c | |
parent | 420e26096448ac273dab52190262aa9d55cb6c91 (diff) | |
download | FreeBSD-src-9d93fce265aeeeb266999d5092d6d4224cc16829.zip FreeBSD-src-9d93fce265aeeeb266999d5092d6d4224cc16829.tar.gz |
Locking for updates to routing table entries. Each rtentry gets a mutex
that covers updates to the contents. Note this is separate from holding
a reference and/or locking the routing table itself.
Other/related changes:
o rtredirect loses the final parameter by which an rtentry reference
may be returned; this was never used and added unwarranted complexity
for locking.
o minor style cleanups to routing code (e.g. ansi-fy function decls)
o remove the logic to bump the refcnt on the parent of cloned routes,
we assume the parent will remain as long as the clone; doing this avoids
a circularity in locking during delete
o convert some timeouts to MPSAFE callouts
Notes:
1. rt_mtx in struct rtentry is guarded by #ifdef _KERNEL as user-level
applications cannot/do-no know about mutex's. Doing this requires
that the mutex be the last element in the structure. A better solution
is to introduce an externalized version of struct rtentry but this is
a major task because of the intertwining of rtentry and other data
structures that are visible to user applications.
2. There are known LOR's that are expected to go away with forthcoming
work to eliminate many held references. If not these will be resolved
prior to release.
3. ATM changes are untested.
Sponsored by: FreeBSD Foundation
Obtained from: BSD/OS (partly)
Diffstat (limited to 'sys/netinet6/in6.c')
-rw-r--r-- | sys/netinet6/in6.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 945ab65..838df1e 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -175,32 +175,35 @@ in6_ifloop_request(int cmd, struct ifaddr *ifa) e); } - /* - * Make sure rt_ifa be equal to IFA, the second argument of the - * function. - * We need this because when we refer to rt_ifa->ia6_flags in - * ip6_input, we assume that the rt_ifa points to the address instead - * of the loopback address. - */ - if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) { - IFAFREE(nrt->rt_ifa); - IFAREF(ifa); - nrt->rt_ifa = ifa; - } - - /* - * Report the addition/removal of the address to the routing socket. - * XXX: since we called rtinit for a p2p interface with a destination, - * we end up reporting twice in such a case. Should we rather - * omit the second report? - */ if (nrt) { + RT_LOCK(nrt); + /* + * Make sure rt_ifa be equal to IFA, the second argument of + * the function. We need this because when we refer to + * rt_ifa->ia6_flags in ip6_input, we assume that the rt_ifa + * points to the address instead of the loopback address. + */ + if (cmd == RTM_ADD && ifa != nrt->rt_ifa) { + IFAFREE(nrt->rt_ifa); + IFAREF(ifa); + nrt->rt_ifa = ifa; + } + + /* + * Report the addition/removal of the address to the routing + * socket. + * + * XXX: since we called rtinit for a p2p interface with a + * destination, we end up reporting twice in such a case. + * Should we rather omit the second report? + */ rt_newaddrmsg(cmd, ifa, e, nrt); if (cmd == RTM_DELETE) { - RTFREE(nrt); + rtfree(nrt); } else { /* the cmd must be RTM_ADD here */ nrt->rt_refcnt--; + RT_UNLOCK(nrt); } } } @@ -223,7 +226,7 @@ in6_ifaddloop(struct ifaddr *ifa) (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) in6_ifloop_request(RTM_ADD, ifa); if (rt) - rt->rt_refcnt--; + rtfree(rt); } /* @@ -271,10 +274,13 @@ in6_ifremloop(struct ifaddr *ifa) * to a shared medium. */ rt = rtalloc1(ifa->ifa_addr, 0, 0); - if (rt != NULL && (rt->rt_flags & RTF_HOST) != 0 && - (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) { - rt->rt_refcnt--; - in6_ifloop_request(RTM_DELETE, ifa); + if (rt != NULL) { + if ((rt->rt_flags & RTF_HOST) != 0 && + (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) { + rtfree(rt); + in6_ifloop_request(RTM_DELETE, ifa); + } else + RT_UNLOCK(rt); } } } |