summaryrefslogtreecommitdiff
path: root/sys/net/rtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/rtable.c')
-rw-r--r--sys/net/rtable.c192
1 files changed, 51 insertions, 141 deletions
diff --git a/sys/net/rtable.c b/sys/net/rtable.c
index b9fb7ce22d5..1209f6a1bf5 100644
--- a/sys/net/rtable.c
+++ b/sys/net/rtable.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtable.c,v 1.26 2015/11/27 11:52:44 mpi Exp $ */
+/* $OpenBSD: rtable.c,v 1.27 2015/11/27 12:13:22 mpi Exp $ */
/*
* Copyright (c) 2014-2015 Martin Pieuchot
@@ -26,13 +26,18 @@
#include <sys/pool.h>
#include <sys/queue.h>
#include <sys/domain.h>
+#include <sys/srp.h>
#endif
#include <net/rtable.h>
#include <net/route.h>
/*
- * Per AF array.
+ * Structures used by rtable_get() to retrieve the corresponding
+ * routing table for a given pair of ``af'' and ``rtableid''.
+ *
+ * Note that once allocated routing table heads are never freed.
+ * This way we do not need to reference count them.
*
* afmap rtmap/dommp
* ----------- --------- -----
@@ -71,9 +76,7 @@ struct srp_gc rtmap_gc = SRP_GC_INITIALIZER(rtmap_dtor, NULL);
void rtable_init_backend(unsigned int);
void *rtable_alloc(unsigned int, sa_family_t, unsigned int);
-void rtable_free(unsigned int, sa_family_t);
void *rtable_get(unsigned int, sa_family_t);
-void rtable_put(void *);
void
rtmap_init(void)
@@ -223,20 +226,6 @@ rtable_add(unsigned int id)
return (0);
}
-void
-rtable_del(unsigned int id)
-{
- struct domain *dp;
- int i;
-
- for (i = 0; (dp = domains[i]) != NULL; i++) {
- if (dp->dom_rtoffset == 0)
- continue;
-
- rtable_free(id, dp->dom_family);
- }
-}
-
void *
rtable_get(unsigned int rtableid, sa_family_t af)
{
@@ -259,7 +248,7 @@ rtable_exists(unsigned int rtableid)
{
struct domain *dp;
void *tbl;
- int i, exist = 0;
+ int i;
for (i = 0; (dp = domains[i]) != NULL; i++) {
if (dp->dom_rtoffset == 0)
@@ -267,14 +256,10 @@ rtable_exists(unsigned int rtableid)
tbl = rtable_get(rtableid, dp->dom_family);
if (tbl != NULL)
- exist = 1;
- rtable_put(tbl);
-
- if (exist)
- break;
+ return (1);
}
- return (exist);
+ return (0);
}
unsigned int
@@ -327,23 +312,13 @@ rtable_alloc(unsigned int rtableid, sa_family_t af, unsigned int off)
return (rnh);
}
-void
-rtable_free(unsigned int rtableid, sa_family_t af)
-{
-}
-
-void
-rtable_put(void *tbl)
-{
-}
-
struct rtentry *
rtable_lookup(unsigned int rtableid, struct sockaddr *dst,
struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio)
{
struct radix_node_head *rnh;
struct radix_node *rn;
- struct rtentry *rt = NULL;
+ struct rtentry *rt;
rnh = rtable_get(rtableid, dst->sa_family);
if (rnh == NULL)
@@ -351,7 +326,7 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst,
rn = rn_lookup(dst, mask, rnh);
if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
- goto out;
+ return (NULL);
rt = ((struct rtentry *)rn);
@@ -359,14 +334,11 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst,
if (rnh->rnh_multipath) {
rt = rt_mpath_matchgate(rt, gateway, prio);
if (rt == NULL)
- goto out;
+ return (NULL);
}
#endif /* !SMALL_KERNEL */
rtref(rt);
-
-out:
- rtable_put(rnh);
return (rt);
}
@@ -375,7 +347,7 @@ rtable_match(unsigned int rtableid, struct sockaddr *dst)
{
struct radix_node_head *rnh;
struct radix_node *rn;
- struct rtentry *rt = NULL;
+ struct rtentry *rt;
rnh = rtable_get(rtableid, dst->sa_family);
if (rnh == NULL)
@@ -383,13 +355,11 @@ rtable_match(unsigned int rtableid, struct sockaddr *dst)
rn = rn_match(dst, rnh);
if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
- goto out;
+ return (NULL);
rt = ((struct rtentry *)rn);
rtref(rt);
-out:
- rtable_put(rnh);
return (rt);
}
@@ -400,7 +370,6 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
{
struct radix_node_head *rnh;
struct radix_node *rn = (struct radix_node *)rt;
- int error = 0;
rnh = rtable_get(rtableid, dst->sa_family);
if (rnh == NULL)
@@ -411,24 +380,19 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
/* Do not permit exactly the same dst/mask/gw pair. */
if (rt_mpath_conflict(rnh, dst, mask, gateway, prio,
ISSET(rt->rt_flags, RTF_MPATH))) {
- error = EEXIST;
- goto out;
+ return (EEXIST);
}
}
-#endif
+#endif /* SMALL_KERNEL */
rn = rn_addroute(dst, mask, rnh, rn, prio);
- if (rn == NULL) {
- error = ESRCH;
- goto out;
- }
+ if (rn == NULL)
+ return (ESRCH);
rt = ((struct rtentry *)rn);
rtref(rt);
-out:
- rtable_put(rnh);
- return (error);
+ return (0);
}
int
@@ -437,17 +401,14 @@ rtable_delete(unsigned int rtableid, struct sockaddr *dst,
{
struct radix_node_head *rnh;
struct radix_node *rn = (struct radix_node *)rt;
- int error = 0;
rnh = rtable_get(rtableid, dst->sa_family);
if (rnh == NULL)
return (EAFNOSUPPORT);
rn = rn_delete(dst, mask, rnh, rn);
- if (rn == NULL) {
- error = ESRCH;
- goto out;
- }
+ if (rn == NULL)
+ return (ESRCH);
if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
panic("active node flags=%x", rn->rn_flags);
@@ -455,9 +416,7 @@ rtable_delete(unsigned int rtableid, struct sockaddr *dst,
rt = ((struct rtentry *)rn);
rtfree(rt);
-out:
- rtable_put(rnh);
- return (error);
+ return (0);
}
int
@@ -466,16 +425,12 @@ rtable_walk(unsigned int rtableid, sa_family_t af,
{
struct radix_node_head *rnh;
int (*f)(struct radix_node *, void *, unsigned int) = (void *)func;
- int error;
rnh = rtable_get(rtableid, af);
if (rnh == NULL)
return (EAFNOSUPPORT);
- error = rn_walktree(rnh, f, arg);
-
- rtable_put(rnh);
- return (error);
+ return (rn_walktree(rnh, f, arg));
}
#ifndef SMALL_KERNEL
@@ -490,8 +445,6 @@ rtable_mpath_capable(unsigned int rtableid, sa_family_t af)
return (0);
mpath = rnh->rnh_multipath;
-
- rtable_put(rnh);
return (mpath);
}
@@ -562,33 +515,13 @@ rtable_alloc(unsigned int rtableid, sa_family_t af, unsigned int off)
return (art_alloc(rtableid, off));
}
-void
-rtable_free(unsigned int rtableid, sa_family_t af)
-{
- struct art_root *ar = NULL;
- struct rtmap *map;
-
- KERNEL_ASSERT_LOCKED();
-
- map = srp_get_locked(&afmap[af2idx[af]]);
- if (rtableid < map->limit) {
- ar = map->tbl[rtableid];
- KASSERT(ar->ar_root == NULL);
- }
-}
-
-void
-rtable_put(void *tbl)
-{
-}
-
struct rtentry *
rtable_lookup(unsigned int rtableid, struct sockaddr *dst,
struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio)
{
struct art_root *ar;
struct art_node *an;
- struct rtentry *rt = NULL;
+ struct rtentry *rt;
uint8_t *addr;
int plen;
@@ -602,17 +535,17 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst,
if (mask == NULL) {
an = art_match(ar, addr);
if (an == NULL)
- goto out;
+ return (NULL);
} else {
plen = satoplen(ar, mask);
if (plen == -1)
- goto out;
+ return (NULL);
an = art_lookup(ar, addr, plen);
/* Make sure we've got a perfect match. */
if (an == NULL || an->an_plen != plen ||
memcmp(an->an_dst, dst, dst->sa_len))
- goto out;
+ return (NULL);
}
#ifdef SMALL_KERNEL
@@ -631,13 +564,11 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst,
break;
}
if (rt == NULL)
- goto out;
+ return (NULL);
#endif /* SMALL_KERNEL */
rtref(rt);
-out:
- rtable_put(ar);
return (rt);
}
@@ -646,7 +577,7 @@ rtable_match(unsigned int rtableid, struct sockaddr *dst)
{
struct art_root *ar;
struct art_node *an;
- struct rtentry *rt = NULL;
+ struct rtentry *rt;
uint8_t *addr;
ar = rtable_get(rtableid, dst->sa_family);
@@ -656,13 +587,11 @@ rtable_match(unsigned int rtableid, struct sockaddr *dst)
addr = satoaddr(ar, dst);
an = art_match(ar, addr);
if (an == NULL)
- goto out;
+ return (NULL);
rt = SLIST_FIRST(&an->an_rtlist);
rtref(rt);
-out:
- rtable_put(ar);
return (rt);
}
@@ -673,11 +602,11 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
{
#ifndef SMALL_KERNEL
struct rtentry *mrt;
-#endif
+#endif /* SMALL_KERNEL */
struct art_root *ar;
struct art_node *an, *prev;
uint8_t *addr;
- int plen, error = 0;
+ int plen;
ar = rtable_get(rtableid, dst->sa_family);
if (ar == NULL)
@@ -685,10 +614,8 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
addr = satoaddr(ar, dst);
plen = satoplen(ar, mask);
- if (plen == -1) {
- error = EINVAL;
- goto out;
- }
+ if (plen == -1)
+ return (EINVAL);
#ifndef SMALL_KERNEL
/* Do not permit exactly the same dst/mask/gw pair. */
@@ -706,12 +633,11 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
if (!mpathok ||
(mrt->rt_gateway->sa_len == gateway->sa_len &&
!memcmp(mrt->rt_gateway, gateway, gateway->sa_len))){
- error = EEXIST;
- goto out;
+ return (EEXIST);
}
}
}
-#endif
+#endif /* SMALL_KERNEL */
/*
* XXX Allocating a sockaddr for the mask per node wastes a lot
@@ -722,19 +648,15 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
struct sockaddr *msk;
msk = malloc(dst->sa_len, M_RTABLE, M_NOWAIT | M_ZERO);
- if (msk == NULL) {
- error = ENOMEM;
- goto out;
- }
+ if (msk == NULL)
+ return (ENOMEM);
memcpy(msk, mask, dst->sa_len);
rt->rt_mask = msk;
}
an = pool_get(&an_pool, PR_NOWAIT | PR_ZERO);
- if (an == NULL) {
- error = ENOBUFS;
- goto out;
- }
+ if (an == NULL)
+ return (ENOBUFS);
an->an_dst = dst;
an->an_plen = plen;
@@ -744,8 +666,7 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
free(rt->rt_mask, M_RTABLE, 0);
rt->rt_mask = NULL;
pool_put(&an_pool, an);
- error = ESRCH;
- goto out;
+ return (ESRCH);
}
if (prev == an) {
@@ -777,8 +698,7 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
}
}
#else
- error = EEXIST;
- goto out;
+ return (EEXIST);
#endif /* SMALL_KERNEL */
}
@@ -792,9 +712,7 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
rtable_mpath_reprio(rt, rt->rt_priority);
#endif /* SMALL_KERNEL */
-out:
- rtable_put(ar);
- return (error);
+ return (0);
}
int
@@ -804,7 +722,7 @@ rtable_delete(unsigned int rtableid, struct sockaddr *dst,
struct art_root *ar;
struct art_node *an = rt->rt_node;
uint8_t *addr;
- int plen, error = 0;
+ int plen;
#ifndef SMALL_KERNEL
struct rtentry *mrt;
int npaths = 0;
@@ -841,15 +759,13 @@ rtable_delete(unsigned int rtableid, struct sockaddr *dst,
panic("destination do not match");
if (mask != NULL && an->an_plen != satoplen(ar, mask))
panic("mask do not match");
-#endif
+#endif /* DIAGNOSTIC */
addr = satoaddr(ar, an->an_dst);
plen = an->an_plen;
- if (art_delete(ar, an, addr, plen) == NULL) {
- error = ESRCH;
- goto out;
- }
+ if (art_delete(ar, an, addr, plen) == NULL)
+ return (ESRCH);
/*
* XXX Is it safe to free the mask now? Are we sure rt_mask()
@@ -863,9 +779,7 @@ rtable_delete(unsigned int rtableid, struct sockaddr *dst,
rtfree(rt);
pool_put(&an_pool, an);
-out:
- rtable_put(ar);
- return (error);
+ return (0);
}
struct rtable_walk_cookie {
@@ -898,7 +812,6 @@ rtable_walk(unsigned int rtableid, sa_family_t af,
{
struct art_root *ar;
struct rtable_walk_cookie rwc;
- int error;
ar = rtable_get(rtableid, af);
if (ar == NULL)
@@ -908,10 +821,7 @@ rtable_walk(unsigned int rtableid, sa_family_t af,
rwc.rwc_arg = arg;
rwc.rwc_rid = rtableid;
- error = art_walk(ar, rtable_walk_helper, &rwc);
-
- rtable_put(ar);
- return (error);
+ return (art_walk(ar, rtable_walk_helper, &rwc));
}
#ifndef SMALL_KERNEL
@@ -1083,7 +993,7 @@ out:
if (*ap != 0x00)
return (-1);
}
-#endif
+#endif /* DIAGNOSTIC */
return (plen);
}