summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net/radix.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net/radix.c')
-rw-r--r--freebsd/sys/net/radix.c225
1 files changed, 98 insertions, 127 deletions
diff --git a/freebsd/sys/net/radix.c b/freebsd/sys/net/radix.c
index ba15eb51..2615de65 100644
--- a/freebsd/sys/net/radix.c
+++ b/freebsd/sys/net/radix.c
@@ -58,18 +58,15 @@
#include <net/radix.h>
#endif /* !_KERNEL */
-static int rn_walktree_from(struct radix_node_head *h, void *a, void *m,
- walktree_f_t *f, void *w);
-static int rn_walktree(struct radix_node_head *, walktree_f_t *, void *);
static struct radix_node
- *rn_insert(void *, struct radix_node_head *, int *,
+ *rn_insert(void *, struct radix_head *, int *,
struct radix_node [2]),
*rn_newpair(void *, int, struct radix_node[2]),
*rn_search(void *, struct radix_node *),
*rn_search_m(void *, struct radix_node *, void *);
+static struct radix_node *rn_addmask(void *, struct radix_mask_head *, int,int);
-static void rn_detachhead_internal(void **head);
-static int rn_inithead_internal(void **head, int off);
+static void rn_detachhead_internal(struct radix_head *);
#define RADIX_MAX_KEY_LEN 32
@@ -81,14 +78,6 @@ static char rn_ones[RADIX_MAX_KEY_LEN] = {
-1, -1, -1, -1, -1, -1, -1, -1,
};
-/*
- * XXX: Compat stuff for old rn_addmask() users
- */
-static struct radix_node_head *mask_rnhead_compat;
-#ifdef _KERNEL
-static struct mtx mask_mtx;
-#endif
-
static int rn_lexobetter(void *m_arg, void *n_arg);
static struct radix_mask *
@@ -225,7 +214,7 @@ rn_refines(void *m_arg, void *n_arg)
* from host routes.
*/
struct radix_node *
-rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
+rn_lookup(void *v_arg, void *m_arg, struct radix_head *head)
{
struct radix_node *x;
caddr_t netmask;
@@ -234,7 +223,7 @@ rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
/*
* Most common case: search exact prefix/mask
*/
- x = rn_addmask_r(m_arg, head->rnh_masks, 1,
+ x = rn_addmask(m_arg, head->rnh_masks, 1,
head->rnh_treetop->rn_offset);
if (x == NULL)
return (NULL);
@@ -287,7 +276,7 @@ rn_satisfies_leaf(char *trial, struct radix_node *leaf, int skip)
* Search for longest-prefix match in given @head
*/
struct radix_node *
-rn_match(void *v_arg, struct radix_node_head *head)
+rn_match(void *v_arg, struct radix_head *head)
{
caddr_t v = v_arg;
struct radix_node *t = head->rnh_treetop, *x;
@@ -436,7 +425,7 @@ rn_newpair(void *v, int b, struct radix_node nodes[2])
}
static struct radix_node *
-rn_insert(void *v_arg, struct radix_node_head *head, int *dupentry,
+rn_insert(void *v_arg, struct radix_head *head, int *dupentry,
struct radix_node nodes[2])
{
caddr_t v = v_arg;
@@ -500,9 +489,9 @@ on1:
}
struct radix_node *
-rn_addmask_r(void *arg, struct radix_node_head *maskhead, int search, int skip)
+rn_addmask(void *n_arg, struct radix_mask_head *maskhead, int search, int skip)
{
- unsigned char *netmask = arg;
+ unsigned char *netmask = n_arg;
unsigned char *cp, *cplim;
struct radix_node *x;
int b = 0, mlen, j;
@@ -515,7 +504,7 @@ rn_addmask_r(void *arg, struct radix_node_head *maskhead, int search, int skip)
if (skip == 0)
skip = 1;
if (mlen <= skip)
- return (maskhead->rnh_nodes);
+ return (maskhead->mask_nodes);
bzero(addmask_key, RADIX_MAX_KEY_LEN);
if (skip > 1)
@@ -528,22 +517,22 @@ rn_addmask_r(void *arg, struct radix_node_head *maskhead, int search, int skip)
cp--;
mlen = cp - addmask_key;
if (mlen <= skip)
- return (maskhead->rnh_nodes);
+ return (maskhead->mask_nodes);
*addmask_key = mlen;
- x = rn_search(addmask_key, maskhead->rnh_treetop);
+ x = rn_search(addmask_key, maskhead->head.rnh_treetop);
if (bcmp(addmask_key, x->rn_key, mlen) != 0)
- x = 0;
+ x = NULL;
if (x || search)
return (x);
R_Zalloc(x, struct radix_node *, RADIX_MAX_KEY_LEN + 2 * sizeof (*x));
- if ((saved_x = x) == 0)
+ if ((saved_x = x) == NULL)
return (0);
- netmask = cp = (caddr_t)(x + 2);
+ netmask = cp = (unsigned char *)(x + 2);
bcopy(addmask_key, cp, mlen);
- x = rn_insert(cp, maskhead, &maskduplicated, x);
+ x = rn_insert(cp, &maskhead->head, &maskduplicated, x);
if (maskduplicated) {
log(LOG_ERR, "rn_addmask: mask impossibly already in tree");
- Free(saved_x);
+ R_Free(saved_x);
return (x);
}
/*
@@ -571,23 +560,6 @@ rn_addmask_r(void *arg, struct radix_node_head *maskhead, int search, int skip)
return (x);
}
-struct radix_node *
-rn_addmask(void *n_arg, int search, int skip)
-{
- struct radix_node *tt;
-
-#ifdef _KERNEL
- mtx_lock(&mask_mtx);
-#endif
- tt = rn_addmask_r(&mask_rnhead_compat, n_arg, search, skip);
-
-#ifdef _KERNEL
- mtx_unlock(&mask_mtx);
-#endif
-
- return (tt);
-}
-
static int /* XXX: arbitrary ordering for non-contiguous masks */
rn_lexobetter(void *m_arg, void *n_arg)
{
@@ -625,11 +597,11 @@ rn_new_radix_mask(struct radix_node *tt, struct radix_mask *next)
}
struct radix_node *
-rn_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
+rn_addroute(void *v_arg, void *n_arg, struct radix_head *head,
struct radix_node treenodes[2])
{
caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
- struct radix_node *t, *x = 0, *tt;
+ struct radix_node *t, *x = NULL, *tt;
struct radix_node *saved_tt, *top = head->rnh_treetop;
short b = 0, b_leaf = 0;
int keyduplicated;
@@ -644,7 +616,7 @@ rn_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
* nodes and possibly save time in calculating indices.
*/
if (netmask) {
- x = rn_addmask_r(netmask, head->rnh_masks, 0, top->rn_offset);
+ x = rn_addmask(netmask, head->rnh_masks, 0, top->rn_offset);
if (x == NULL)
return (0);
b_leaf = x->rn_bit;
@@ -752,7 +724,7 @@ rn_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
if (m->rm_bit >= b_leaf)
break;
- t->rn_mklist = m; *mp = 0;
+ t->rn_mklist = m; *mp = NULL;
}
on2:
/* Add new route to highest possible ancestor's list */
@@ -799,7 +771,7 @@ on2:
}
struct radix_node *
-rn_delete(void *v_arg, void *netmask_arg, struct radix_node_head *head)
+rn_delete(void *v_arg, void *netmask_arg, struct radix_head *head)
{
struct radix_node *t, *p, *x, *tt;
struct radix_mask *m, *saved_m, **mp;
@@ -815,22 +787,22 @@ rn_delete(void *v_arg, void *netmask_arg, struct radix_node_head *head)
vlen = LEN(v);
saved_tt = tt;
top = x;
- if (tt == 0 ||
+ if (tt == NULL ||
bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
return (0);
/*
* Delete our route from mask lists.
*/
if (netmask) {
- x = rn_addmask_r(netmask, head->rnh_masks, 1, head_off);
+ x = rn_addmask(netmask, head->rnh_masks, 1, head_off);
if (x == NULL)
return (0);
netmask = x->rn_key;
while (tt->rn_mask != netmask)
- if ((tt = tt->rn_dupedkey) == 0)
+ if ((tt = tt->rn_dupedkey) == NULL)
return (0);
}
- if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)
+ if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == NULL)
goto on1;
if (tt->rn_flags & RNF_NORMAL) {
if (m->rm_leaf != tt || m->rm_refs > 0) {
@@ -856,10 +828,10 @@ rn_delete(void *v_arg, void *netmask_arg, struct radix_node_head *head)
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
if (m == saved_m) {
*mp = m->rm_mklist;
- Free(m);
+ R_Free(m);
break;
}
- if (m == 0) {
+ if (m == NULL) {
log(LOG_ERR, "rn_delete: couldn't find our annotation\n");
if (tt->rn_flags & RNF_NORMAL)
return (0); /* Dangling ref to us */
@@ -947,7 +919,7 @@ on1:
struct radix_mask *mm = m->rm_mklist;
x->rn_mklist = 0;
if (--(m->rm_refs) < 0)
- Free(m);
+ R_Free(m);
m = mm;
}
if (m)
@@ -986,8 +958,8 @@ out:
* This is the same as rn_walktree() except for the parameters and the
* exit.
*/
-static int
-rn_walktree_from(struct radix_node_head *h, void *a, void *m,
+int
+rn_walktree_from(struct radix_head *h, void *a, void *m,
walktree_f_t *f, void *w)
{
int error;
@@ -998,6 +970,8 @@ rn_walktree_from(struct radix_node_head *h, void *a, void *m,
int stopping = 0;
int lastb;
+ KASSERT(m != NULL, ("%s: mask needs to be specified", __func__));
+
/*
* rn_search_m is sort-of-open-coded here. We cannot use the
* function because we need to keep track of the last node seen.
@@ -1021,11 +995,11 @@ rn_walktree_from(struct radix_node_head *h, void *a, void *m,
/*
* Two cases: either we stepped off the end of our mask,
* in which case last == rn, or we reached a leaf, in which
- * case we want to start from the last node we looked at.
- * Either way, last is the node we want to start from.
+ * case we want to start from the leaf.
*/
- rn = last;
- lastb = rn->rn_bit;
+ if (rn->rn_bit >= 0)
+ rn = last;
+ lastb = last->rn_bit;
/* printf("rn %p, lastb %d\n", rn, lastb);*/
@@ -1072,7 +1046,7 @@ rn_walktree_from(struct radix_node_head *h, void *a, void *m,
rn = rn->rn_left;
next = rn;
/* Process leaves */
- while ((rn = base) != 0) {
+ while ((rn = base) != NULL) {
base = rn->rn_dupedkey;
/* printf("leaf %p\n", rn); */
if (!(rn->rn_flags & RNF_ROOT)
@@ -1090,8 +1064,8 @@ rn_walktree_from(struct radix_node_head *h, void *a, void *m,
return (0);
}
-static int
-rn_walktree(struct radix_node_head *h, walktree_f_t *f, void *w)
+int
+rn_walktree(struct radix_head *h, walktree_f_t *f, void *w)
{
int error;
struct radix_node *base, *next;
@@ -1130,82 +1104,94 @@ rn_walktree(struct radix_node_head *h, walktree_f_t *f, void *w)
}
/*
- * Allocate and initialize an empty tree. This has 3 nodes, which are
- * part of the radix_node_head (in the order <left,root,right>) and are
+ * Initialize an empty tree. This has 3 nodes, which are passed
+ * via base_nodes (in the order <left,root,right>) and are
* marked RNF_ROOT so they cannot be freed.
* The leaves have all-zero and all-one keys, with significant
* bits starting at 'off'.
- * Return 1 on success, 0 on error.
*/
-static int
-rn_inithead_internal(void **head, int off)
+void
+rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes, int off)
{
- struct radix_node_head *rnh;
struct radix_node *t, *tt, *ttt;
- if (*head)
- return (1);
- R_Zalloc(rnh, struct radix_node_head *, sizeof (*rnh));
- if (rnh == 0)
- return (0);
-#ifdef _KERNEL
- RADIX_NODE_HEAD_LOCK_INIT(rnh);
-#endif
- *head = rnh;
- t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
- ttt = rnh->rnh_nodes + 2;
+
+ t = rn_newpair(rn_zeros, off, base_nodes);
+ ttt = base_nodes + 2;
t->rn_right = ttt;
t->rn_parent = t;
- tt = t->rn_left; /* ... which in turn is rnh->rnh_nodes */
+ tt = t->rn_left; /* ... which in turn is base_nodes */
tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
tt->rn_bit = -1 - off;
*ttt = *tt;
ttt->rn_key = rn_ones;
- rnh->rnh_addaddr = rn_addroute;
- rnh->rnh_deladdr = rn_delete;
- rnh->rnh_matchaddr = rn_match;
- rnh->rnh_lookup = rn_lookup;
- rnh->rnh_walktree = rn_walktree;
- rnh->rnh_walktree_from = rn_walktree_from;
- rnh->rnh_treetop = t;
- return (1);
+
+ rh->rnh_treetop = t;
}
static void
-rn_detachhead_internal(void **head)
+rn_detachhead_internal(struct radix_head *head)
{
- struct radix_node_head *rnh;
- KASSERT((head != NULL && *head != NULL),
+ KASSERT((head != NULL),
("%s: head already freed", __func__));
- rnh = *head;
/* Free <left,root,right> nodes. */
- Free(rnh);
-
- *head = NULL;
+ R_Free(head);
}
+/* Functions used by 'struct radix_node_head' users */
+
int
rn_inithead(void **head, int off)
{
struct radix_node_head *rnh;
+ struct radix_mask_head *rmh;
+
+ rnh = *head;
+ rmh = NULL;
if (*head != NULL)
return (1);
- if (rn_inithead_internal(head, off) == 0)
+ R_Zalloc(rnh, struct radix_node_head *, sizeof (*rnh));
+ R_Zalloc(rmh, struct radix_mask_head *, sizeof (*rmh));
+ if (rnh == NULL || rmh == NULL) {
+ if (rnh != NULL)
+ R_Free(rnh);
+ if (rmh != NULL)
+ R_Free(rmh);
return (0);
+ }
- rnh = (struct radix_node_head *)(*head);
+ /* Init trees */
+ rn_inithead_internal(&rnh->rh, rnh->rnh_nodes, off);
+ rn_inithead_internal(&rmh->head, rmh->mask_nodes, 0);
+ *head = rnh;
+ rnh->rh.rnh_masks = rmh;
- if (rn_inithead_internal((void **)&rnh->rnh_masks, 0) == 0) {
- rn_detachhead_internal(head);
- return (0);
- }
+ /* Finally, set base callbacks */
+ rnh->rnh_addaddr = rn_addroute;
+ rnh->rnh_deladdr = rn_delete;
+ rnh->rnh_matchaddr = rn_match;
+ rnh->rnh_lookup = rn_lookup;
+ rnh->rnh_walktree = rn_walktree;
+ rnh->rnh_walktree_from = rn_walktree_from;
return (1);
}
+static int
+rn_freeentry(struct radix_node *rn, void *arg)
+{
+ struct radix_head * const rnh = arg;
+ struct radix_node *x;
+
+ x = (struct radix_node *)rn_delete(rn + 2, NULL, rnh);
+ if (x != NULL)
+ R_Free(x);
+ return (0);
+}
+
int
rn_detachhead(void **head)
{
@@ -1214,29 +1200,14 @@ rn_detachhead(void **head)
KASSERT((head != NULL && *head != NULL),
("%s: head already freed", __func__));
- rnh = *head;
+ rnh = (struct radix_node_head *)(*head);
- rn_detachhead_internal((void **)&rnh->rnh_masks);
- rn_detachhead_internal(head);
- return (1);
-}
+ rn_walktree(&rnh->rh.rnh_masks->head, rn_freeentry, rnh->rh.rnh_masks);
+ rn_detachhead_internal(&rnh->rh.rnh_masks->head);
+ rn_detachhead_internal(&rnh->rh);
-void
-rn_init(int maxk)
-{
- if ((maxk <= 0) || (maxk > RADIX_MAX_KEY_LEN)) {
- log(LOG_ERR,
- "rn_init: max_keylen must be within 1..%d\n",
- RADIX_MAX_KEY_LEN);
- return;
- }
+ *head = NULL;
- /*
- * XXX: Compat for old rn_addmask() users
- */
- if (rn_inithead((void **)(void *)&mask_rnhead_compat, 0) == 0)
- panic("rn_init 2");
-#ifdef _KERNEL
- mtx_init(&mask_mtx, "radix_mask", NULL, MTX_DEF);
-#endif
+ return (1);
}
+