mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-28 11:57:28 +00:00
Switch route radix to dual-lock model:
use rmlock for data patch access, and config rwlock for conrol plane processing. Route table changes require bock locks held.
This commit is contained in:
parent
69d149adf5
commit
f7bab8d0dd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/routing/; revision=274336
@ -44,6 +44,9 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
@ -281,7 +284,8 @@ rt_table_init(int offset)
|
||||
rh->rmhead.head.s.mask_nodes = rh->rmhead.mask_nodes;
|
||||
|
||||
/* Init locks */
|
||||
rw_init(&rh->rib_lock, "rib head");
|
||||
rm_init(&rh->rib_lock, "rib head run");
|
||||
rw_init(&rh->rib_cfglock, "rib head cfg");
|
||||
|
||||
/* Finally, set base callbacks */
|
||||
rh->rnh_addaddr = rn_addroute;
|
||||
@ -299,7 +303,8 @@ rt_table_destroy(struct rib_head *rh)
|
||||
{
|
||||
|
||||
/* Assume table is already empty */
|
||||
rw_destroy(&rh->rib_lock);
|
||||
rw_destroy(&rh->rib_cfglock);
|
||||
rm_destroy(&rh->rib_lock);
|
||||
free(rh, M_RTABLE);
|
||||
}
|
||||
|
||||
@ -365,6 +370,7 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
|
||||
struct rt_addrinfo info;
|
||||
int err = 0, msgtype = RTM_MISS;
|
||||
int needlock;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, dst->sa_family);
|
||||
@ -612,11 +618,13 @@ rtredirect_fib(struct sockaddr *dst,
|
||||
* add the key and gateway (in one malloc'd chunk).
|
||||
*/
|
||||
RT_UNLOCK(rt);
|
||||
RIB_CFG_WLOCK(rh);
|
||||
RIB_WLOCK(rh);
|
||||
RT_LOCK(rt);
|
||||
rt_setgate(rt, rt_key(rt), gateway);
|
||||
gwrt = rtalloc1(gateway, 1, RTF_RNH_LOCKED);
|
||||
RIB_WUNLOCK(rh);
|
||||
RIB_CFG_WUNLOCK(rh);
|
||||
EVENTHANDLER_INVOKE(route_redirect_event, rt, gwrt, dst);
|
||||
RTFREE_LOCKED(gwrt);
|
||||
}
|
||||
@ -794,9 +802,12 @@ rt_foreach_fib(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f, void *arg)
|
||||
if (setwa_f != NULL)
|
||||
setwa_f(rh, fibnum, i, arg);
|
||||
|
||||
RIB_CFG_WLOCK(rh);
|
||||
/* Do runtime locking for now */
|
||||
RIB_WLOCK(rh);
|
||||
rh->rnh_walktree(&rh->head, (walktree_f_t *)wa_f, arg);
|
||||
RIB_WUNLOCK(rh);
|
||||
RIB_CFG_WUNLOCK(rh);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -807,9 +818,12 @@ rt_foreach_fib(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f, void *arg)
|
||||
if (setwa_f != NULL)
|
||||
setwa_f(rh, fibnum, i, arg);
|
||||
|
||||
RIB_CFG_WLOCK(rh);
|
||||
RIB_WLOCK(rh);
|
||||
/* Do runtime locking for now */
|
||||
rh->rnh_walktree(&rh->head, (walktree_f_t *)wa_f, arg);
|
||||
RIB_WUNLOCK(rh);
|
||||
RIB_CFG_WUNLOCK(rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1203,9 +1217,10 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
|
||||
return (EAFNOSUPPORT);
|
||||
needlock = ((flags & RTF_RNH_LOCKED) == 0);
|
||||
flags &= ~RTF_RNH_LOCKED;
|
||||
if (needlock)
|
||||
if (needlock) {
|
||||
RIB_CFG_WLOCK(rh);
|
||||
RIB_WLOCK(rh);
|
||||
else
|
||||
} else
|
||||
RIB_LOCK_ASSERT(rh);
|
||||
/*
|
||||
* If we are adding a host route then we don't want to put
|
||||
@ -1453,8 +1468,10 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
|
||||
error = EOPNOTSUPP;
|
||||
}
|
||||
bad:
|
||||
if (needlock)
|
||||
if (needlock) {
|
||||
RIB_WUNLOCK(rh);
|
||||
RIB_CFG_WUNLOCK(rh);
|
||||
}
|
||||
return (error);
|
||||
#undef senderr
|
||||
}
|
||||
@ -1730,7 +1747,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
if (rh == NULL)
|
||||
/* this table doesn't exist but others might */
|
||||
continue;
|
||||
RIB_RLOCK(rh);
|
||||
RIB_CFG_RLOCK(rh);
|
||||
rn = rh->rnh_lookup(dst, netmask, &rh->head);
|
||||
#ifdef RADIX_MPATH
|
||||
if (rn_mpath_capable(rh)) {
|
||||
@ -1756,7 +1773,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
error = (rn == NULL ||
|
||||
(rn->rn_flags & RNF_ROOT) ||
|
||||
RNTORT(rn)->rt_ifa != ifa);
|
||||
RIB_RUNLOCK(rh);
|
||||
RIB_CFG_RUNLOCK(rh);
|
||||
if (error) {
|
||||
/* this is only an error if bad on ALL tables */
|
||||
continue;
|
||||
@ -1789,6 +1806,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
* interface prefix.
|
||||
*/
|
||||
rh = rt_tables_get_rnh(fibnum, dst->sa_family);
|
||||
RIB_CFG_WLOCK(rh);
|
||||
RIB_WLOCK(rh);
|
||||
|
||||
/* Delete old prefix */
|
||||
@ -1804,6 +1822,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
}
|
||||
|
||||
RIB_WUNLOCK(rh);
|
||||
RIB_CFG_WUNLOCK(rh);
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
struct rib_head {
|
||||
struct radix_head head;
|
||||
struct rmlock rib_lock; /* data path lock */
|
||||
rn_matchaddr_f_t *rnh_matchaddr; /* longest match for sockaddr */
|
||||
rn_addaddr_f_t *rnh_addaddr; /* add based on sockaddr*/
|
||||
rn_deladdr_f_t *rnh_deladdr; /* remove based on sockaddr */
|
||||
@ -40,16 +41,24 @@ struct rib_head {
|
||||
rn_walktree_from_t *rnh_walktree_from; /* traverse tree below a */
|
||||
rn_close_t *rnh_close; /*do something when the last ref drops*/
|
||||
struct radix_node rnh_nodes[3]; /* empty tree for common case */
|
||||
struct rwlock rib_lock; /* locks entire radix tree */
|
||||
struct rwlock rib_cfglock; /* config lock */
|
||||
struct radix_mask_head rmhead; /* masks radix head */
|
||||
};
|
||||
|
||||
#define RIB_RLOCK(rh) rw_rlock(&(rh)->rib_lock)
|
||||
#define RIB_RUNLOCK(rh) rw_runlock(&(rh)->rib_lock)
|
||||
#define RIB_WLOCK(rh) rw_wlock(&(rh)->rib_lock)
|
||||
#define RIB_WUNLOCK(rh) rw_wunlock(&(rh)->rib_lock)
|
||||
#define RIB_LOCK_ASSERT(rh) rw_assert(&(rh)->rib_lock, RA_LOCKED)
|
||||
#define RIB_WLOCK_ASSERT(rh) rw_assert(&(rh)->rib_lock, RA_WLOCKED)
|
||||
#define RIB_RLOCK(rh) rm_rlock(&(rh)->rib_lock, &tracker)
|
||||
#define RIB_RUNLOCK(rh) rm_runlock(&(rh)->rib_lock, &tracker)
|
||||
#define RIB_WLOCK(rh) rm_wlock(&(rh)->rib_lock)
|
||||
#define RIB_WUNLOCK(rh) rm_wunlock(&(rh)->rib_lock)
|
||||
#define RIB_WLOCK_ASSERT(rh) rm_assert(&(rh)->rib_lock, RA_WLOCKED)
|
||||
#define RIB_LOCK_READER struct rm_priotracker tracker
|
||||
#define RIB_LOCK_ASSERT(rh) rm_assert(&(rh)->rib_lock, RA_LOCKED)
|
||||
|
||||
#define RIB_CFG_RLOCK(rh) rw_rlock(&(rh)->rib_cfglock)
|
||||
#define RIB_CFG_RUNLOCK(rh) rw_runlock(&(rh)->rib_cfglock)
|
||||
#define RIB_CFG_WLOCK(rh) rw_wlock(&(rh)->rib_cfglock)
|
||||
#define RIB_CFG_WUNLOCK(rh) rw_wunlock(&(rh)->rib_cfglock)
|
||||
#define RIB_CFG_LOCK_ASSERT(rh) rw_assert(&(rh)->rib_cfglock, RA_LOCKED)
|
||||
#define RIB_CFG_WLOCK_ASSERT(rh) rw_assert(&(rh)->rib_cfglock, RA_WLOCKED)
|
||||
|
||||
struct rib_head *rt_table_init(int offset);
|
||||
void rt_table_destroy(struct rib_head *rh);
|
||||
|
@ -40,6 +40,9 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
@ -262,8 +265,8 @@ fib4_lookup_prepend(uint32_t fibnum, struct in_addr dst, struct mbuf *m,
|
||||
struct in_addr gw;
|
||||
struct ether_header *eh;
|
||||
int error, flags;
|
||||
//uint32_t flowid;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_prepend: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
@ -506,6 +509,7 @@ fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in sin;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_basic: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
@ -542,6 +546,7 @@ fib4_lookup_nh_ifp(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in sin;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_ifp: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
@ -587,6 +592,7 @@ fib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in sin;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_ext: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
@ -632,6 +638,7 @@ rib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in sin;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("rib4_lookup_nh_ext: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
@ -757,6 +764,7 @@ fib6_lookup_prepend(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
|
||||
struct rtentry *rte;
|
||||
struct ifnet *lifp;
|
||||
struct ether_header *eh;
|
||||
RIB_LOCK_READER;
|
||||
uint32_t flags;
|
||||
int error;
|
||||
|
||||
@ -1129,6 +1137,7 @@ fib6_lookup_nh_ifp(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
|
||||
/* Do not lookup link-local addresses in rtable */
|
||||
@ -1172,6 +1181,7 @@ fib6_lookup_nh_basic(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
|
||||
/* Do not lookup link-local addresses in rtable */
|
||||
@ -1222,6 +1232,7 @@ fib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
|
||||
/* Do not lookup link-local addresses in rtable */
|
||||
@ -1275,6 +1286,7 @@ rib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct rtentry *rte;
|
||||
RIB_LOCK_READER;
|
||||
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
|
||||
/* Do not lookup link-local addresses in rtable */
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/priv.h>
|
||||
@ -703,7 +706,7 @@ route_output(struct mbuf *m, struct socket *so, ...)
|
||||
if (rh == NULL)
|
||||
senderr(EAFNOSUPPORT);
|
||||
|
||||
RIB_RLOCK(rh);
|
||||
RIB_CFG_RLOCK(rh);
|
||||
|
||||
if (info.rti_info[RTAX_NETMASK] == NULL &&
|
||||
rtm->rtm_type == RTM_GET) {
|
||||
@ -720,7 +723,7 @@ route_output(struct mbuf *m, struct socket *so, ...)
|
||||
info.rti_info[RTAX_NETMASK], &rh->head);
|
||||
|
||||
if (rt == NULL) {
|
||||
RIB_RUNLOCK(rh);
|
||||
RIB_CFG_RUNLOCK(rh);
|
||||
senderr(ESRCH);
|
||||
}
|
||||
#ifdef RADIX_MPATH
|
||||
@ -736,7 +739,7 @@ route_output(struct mbuf *m, struct socket *so, ...)
|
||||
(rtm->rtm_type != RTM_GET || info.rti_info[RTAX_GATEWAY])) {
|
||||
rt = rt_mpath_matchgate(rt, info.rti_info[RTAX_GATEWAY]);
|
||||
if (!rt) {
|
||||
RIB_RUNLOCK(rh);
|
||||
RIB_CFG_RUNLOCK(rh);
|
||||
senderr(ESRCH);
|
||||
}
|
||||
}
|
||||
@ -769,13 +772,13 @@ route_output(struct mbuf *m, struct socket *so, ...)
|
||||
*/
|
||||
rt = (struct rtentry *)rh->rnh_matchaddr(&laddr, &rh->head);
|
||||
if (rt == NULL) {
|
||||
RIB_RUNLOCK(rh);
|
||||
RIB_CFG_RUNLOCK(rh);
|
||||
senderr(ESRCH);
|
||||
}
|
||||
}
|
||||
RT_LOCK(rt);
|
||||
RT_ADDREF(rt);
|
||||
RIB_RUNLOCK(rh);
|
||||
RIB_CFG_RUNLOCK(rh);
|
||||
|
||||
report:
|
||||
RT_LOCK_ASSERT(rt);
|
||||
@ -1868,10 +1871,10 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
|
||||
for (error = 0; error == 0 && i <= lim; i++) {
|
||||
rh = rt_tables_get_rnh(fib, i);
|
||||
if (rh != NULL) {
|
||||
RIB_RLOCK(rh);
|
||||
RIB_CFG_RLOCK(rh);
|
||||
error = rh->rnh_walktree(&rh->head,
|
||||
sysctl_dumpentry, &w);
|
||||
RIB_RUNLOCK(rh);
|
||||
RIB_CFG_RUNLOCK(rh);
|
||||
} else if (af != 0)
|
||||
error = EAFNOSUPPORT;
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/mbuf.h>
|
||||
@ -192,7 +195,7 @@ in_rtqkill(struct rtentry *rt, void *rock)
|
||||
struct rtqk_arg *ap = rock;
|
||||
int err;
|
||||
|
||||
RIB_WLOCK_ASSERT(ap->rh);
|
||||
//RIB_WLOCK_ASSERT(ap->rh);
|
||||
|
||||
if (rt->rt_flags & RTPRF_OURS) {
|
||||
ap->found++;
|
||||
@ -278,9 +281,11 @@ void
|
||||
in_setmatchfunc(struct rib_head *rh, int val)
|
||||
{
|
||||
|
||||
RIB_CFG_WLOCK(rh);
|
||||
RIB_WLOCK(rh);
|
||||
rh->rnh_matchaddr = (val != 0) ? rn_match : in_matroute;
|
||||
RIB_WUNLOCK(rh);
|
||||
RIB_CFG_WUNLOCK(rh);
|
||||
}
|
||||
|
||||
static int _in_rt_was_here;
|
||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/lock.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
@ -1547,6 +1548,7 @@ nd6_prefix_onlink_rtrequest(struct nd_prefix *pr, struct ifaddr *ifa)
|
||||
|
||||
rh = rt_tables_get_rnh(rt->rt_fibnum, AF_INET6);
|
||||
/* XXX what if rhn == NULL? */
|
||||
RIB_CFG_WLOCK(rh);
|
||||
RIB_WLOCK(rh);
|
||||
RT_LOCK(rt);
|
||||
if (rt_setgate(rt, rt_key(rt),
|
||||
@ -1558,6 +1560,7 @@ nd6_prefix_onlink_rtrequest(struct nd_prefix *pr, struct ifaddr *ifa)
|
||||
dl->sdl_index = rt->rt_ifp->if_index;
|
||||
}
|
||||
RIB_WUNLOCK(rh);
|
||||
RIB_CFG_WUNLOCK(rh);
|
||||
nd6_rtmsg(RTM_ADD, rt);
|
||||
RT_UNLOCK(rt);
|
||||
pr->ndpr_stateflags |= NDPRF_ONLINK;
|
||||
|
@ -4019,6 +4019,7 @@ ta_foreach_kfib(void *ta_state, struct table_info *ti, ta_foreach_f *f,
|
||||
void *arg)
|
||||
{
|
||||
struct rib_head *rh;
|
||||
RIB_LOCK_READER;
|
||||
int error;
|
||||
|
||||
rh = rt_tables_get_rnh(ti->data, AF_INET);
|
||||
|
@ -375,9 +375,9 @@ bootpboot_p_rtlist(void)
|
||||
rnh = rt_tables_get_rnh(0, AF_INET);
|
||||
if (rnh == NULL)
|
||||
return;
|
||||
RIB_RLOCK(rnh); /* could sleep XXX */
|
||||
RIB_CFG_RLOCK(rnh); /* could sleep XXX */
|
||||
bootpboot_p_tree(rh->rnh_treetop);
|
||||
RIB_RUNLOCK(rnh);
|
||||
RIB_CFG_RUNLOCK(rnh);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user