summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2006-05-31 01:35:12 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2006-05-31 01:35:12 +0000
commit175c420c443c6a97db79a10d70be637f7cff641d (patch)
tree7846c56e2ebbb2ddfe7359330a7b434aa8a53b6f /sys/net
parentc6e71633f41158e32b4d1e9980d6ae22e4326b4a (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.c95
-rw-r--r--sys/net/route.h5
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_ */