diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2006-05-31 01:35:12 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2006-05-31 01:35:12 +0000 |
commit | 175c420c443c6a97db79a10d70be637f7cff641d (patch) | |
tree | 7846c56e2ebbb2ddfe7359330a7b434aa8a53b6f /sys/net | |
parent | c6e71633f41158e32b4d1e9980d6ae22e4326b4a (diff) |
move us to multiple routing table heads.
-instead of staticaly declaring the heads, allocate memory for them
-add second dimension to the routing table head array, table ID
-space saver: do not use the AF as array index directly, but have an
AF->index translation array and only account for AFs actually attaching
a routing table
note that whil ethat allows for multiple routing table heads, nothing uses
taht yet.
tested by many, ok claudio reyk norby mcbride
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/route.c | 95 | ||||
-rw-r--r-- | sys/net/route.h | 5 |
2 files changed, 77 insertions, 23 deletions
diff --git a/sys/net/route.c b/sys/net/route.c index d7a59ffea06..191ee95341c 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.73 2006/05/20 20:43:57 reyk Exp $ */ +/* $OpenBSD: route.c,v 1.74 2006/05/31 01:35:11 henning Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -130,9 +130,12 @@ struct ifaddr *encap_findgwifa(struct sockaddr *); #define SA(p) ((struct sockaddr *)(p)) -struct route_cb route_cb; -struct rtstat rtstat; -struct radix_node_head *rt_tables[AF_MAX+1]; +struct route_cb route_cb; +struct rtstat rtstat; +struct radix_node_head ***rt_tables; +u_int8_t af2rtafidx[AF_MAX+1]; +u_int8_t rtafidx_max; +u_int rtbl_cnt = 0; int rttrash; /* routes not in table but not freed */ struct sockaddr wildcard; /* zero cookie for wildcard searches */ @@ -140,6 +143,8 @@ struct sockaddr wildcard; /* zero cookie for wildcard searches */ struct pool rtentry_pool; /* pool for rtentry structures */ struct pool rttimer_pool; /* pool for rttimer structures */ +int rtable_init(struct radix_node_head ***); +int rtable_add(char *); int okaytoclone(u_int, int); int rtdeletemsg(struct rtentry *); int rtflushclone1(struct radix_node *, void *); @@ -147,6 +152,7 @@ void rtflushclone(struct radix_node_head *, struct rtentry *); int rt_if_remove_rtdelete(struct radix_node *, void *); #define LABELID_MAX 50000 +#define RTBL_CNT_INC 4 /* allocate rtables in chunks of 4 */ struct rt_label { TAILQ_ENTRY(rt_label) rtl_entry; @@ -165,23 +171,72 @@ encap_findgwifa(struct sockaddr *gw) } #endif -void -rtable_init(void **table) +int +rtable_init(struct radix_node_head ***table) { - struct domain *dom; + void **p; + struct domain *dom; + + if ((p = malloc(sizeof(void *) * (rtafidx_max + 1), M_RTABLE, + M_NOWAIT)) == NULL) + return (-1); + bzero(p, sizeof(void *) * (rtafidx_max + 1)); + + /* 2nd pass: attach */ for (dom = domains; dom != NULL; dom = dom->dom_next) if (dom->dom_rtattach) - dom->dom_rtattach(&table[dom->dom_family], + dom->dom_rtattach(&p[af2rtafidx[dom->dom_family]], dom->dom_rtoffset); + + *table = (struct radix_node_head **)p; + return (0); } void route_init() { + struct domain *dom; + pool_init(&rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl", NULL); rn_init(); /* initialize all zeroes, all ones, mask table */ - rtable_init((void **)rt_tables); + + bzero(af2rtafidx, sizeof(af2rtafidx)); + rtafidx_max = 0; + + /* find out how many tables to allocate */ + for (dom = domains; dom != NULL; dom = dom->dom_next) + if (dom->dom_rtattach) + af2rtafidx[dom->dom_family] = rtafidx_max++; + + if (rtable_add("main") == -1) + panic("route_init rtable_add"); +} + +int +rtable_add(char *tblname) +{ + u_int i; + void *p; + + for (i = 0; i < rtbl_cnt; i++) + if (rt_tables[i] == NULL) + break; + + if (i == rtbl_cnt) { + rtbl_cnt += RTBL_CNT_INC; + if ((p = malloc(sizeof(void *) * rtbl_cnt, M_RTABLE, + M_NOWAIT)) == NULL) + return (-1); + bzero(p, sizeof(void *) * rtbl_cnt); + if (i > 0) { + bcopy(rt_tables, p, sizeof(void *) * i); + free(rt_tables, M_RTABLE); + } + rt_tables = p; + } + + return (rtable_init(&rt_tables[i])); } void @@ -205,13 +260,14 @@ okaytoclone(u_int flags, int howstrict) struct rtentry * rtalloc2(struct sockaddr *dst, int report, int howstrict) { - struct radix_node_head *rnh = rt_tables[dst->sa_family]; + struct radix_node_head *rnh; struct rtentry *rt; struct radix_node *rn; struct rtentry *newrt = 0; struct rt_addrinfo info; int s = splnet(), err = 0, msgtype = RTM_MISS; + rnh = rt_gettable(dst->sa_family, 0); if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { newrt = rt = (struct rtentry *)rn; @@ -257,13 +313,14 @@ rtalloc(struct route *ro) struct rtentry * rtalloc1(struct sockaddr *dst, int report) { - struct radix_node_head *rnh = rt_tables[dst->sa_family]; + struct radix_node_head *rnh; struct rtentry *rt; struct radix_node *rn; struct rtentry *newrt = 0; struct rt_addrinfo info; int s = splsoftnet(), err = 0, msgtype = RTM_MISS; + rnh = rt_gettable(dst->sa_family, 0); if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { newrt = rt = (struct rtentry *)rn; @@ -657,7 +714,7 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) struct sockaddr_rtlabel *sa_rl; #define senderr(x) { error = x ; goto bad; } - if ((rnh = rt_tables[info->rti_info[RTAX_DST]->sa_family]) == 0) + if ((rnh = rt_gettable(info->rti_info[RTAX_DST]->sa_family, 0)) == NULL) senderr(EAFNOSUPPORT); if (info->rti_flags & RTF_HOST) info->rti_info[RTAX_NETMASK] = NULL; @@ -1127,10 +1184,9 @@ rt_timer_add(struct rtentry *rt, void (*func)(struct rtentry *, } struct radix_node_head * -rt_gettable(sa_family_t af, int id) +rt_gettable(sa_family_t af, u_int id) { - /* ignore id for now */ - return (rt_tables[af]); + return (rt_tables[id][af2rtafidx[af]]); } struct radix_node * @@ -1143,6 +1199,7 @@ rt_lookup(struct sockaddr *dst, struct sockaddr *mask, int tableid) return (rnh->rnh_lookup(dst, mask, rnh)); } + /* ARGSUSED */ void rt_timer_timer(void *arg) @@ -1259,13 +1316,11 @@ rt_if_remove(struct ifnet *ifp) int i; struct radix_node_head *rnh; - for (i = 1; i <= AF_MAX; i++) { - rnh = rt_tables[i]; - if (rnh) + for (i = 1; i <= AF_MAX; i++) + if ((rnh = rt_gettable(i, 0)) != NULL) while ((*rnh->rnh_walktree)(rnh, rt_if_remove_rtdelete, ifp) == EAGAIN) - ; - } + ; /* nothing */ } /* diff --git a/sys/net/route.h b/sys/net/route.h index 372d8b1fc99..c2622e94ac8 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -1,4 +1,4 @@ -/* $OpenBSD: route.h,v 1.39 2006/04/22 19:43:07 claudio Exp $ */ +/* $OpenBSD: route.h,v 1.40 2006/05/31 01:35:11 henning Exp $ */ /* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ /* @@ -334,7 +334,6 @@ void rt_timer_queue_destroy(struct rttimer_queue *, int); void rt_timer_remove_all(struct rtentry *); unsigned long rt_timer_count(struct rttimer_queue *); void rt_timer_timer(void *); -void rtable_init(void **); void rtalloc(struct route *); struct rtentry * rtalloc1(struct sockaddr *, int); @@ -354,7 +353,7 @@ int rtrequest(int, struct sockaddr *, int rtrequest1(int, struct rt_addrinfo *, struct rtentry **); void rt_if_remove(struct ifnet *); -struct radix_node_head *rt_gettable(sa_family_t, int); +struct radix_node_head *rt_gettable(sa_family_t, u_int); struct radix_node *rt_lookup(struct sockaddr *, struct sockaddr *, int); #endif /* _KERNEL */ #endif /* _NET_ROUTE_H_ */ |