aboutsummaryrefslogtreecommitdiff
path: root/sys/net/radix.c
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2016-01-25 06:33:15 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2016-01-25 06:33:15 +0000
commit61eee0e202c2bda75971193c95d870e6148a6152 (patch)
treee3d1ff0a530bc18a45f34e089f84583c63d778c7 /sys/net/radix.c
parent51f6f18c88deda7b3dc79ccef5fe008170380277 (diff)
downloadsrc-61eee0e202c2bda75971193c95d870e6148a6152.tar.gz
src-61eee0e202c2bda75971193c95d870e6148a6152.zip
MFP r287070,r287073: split radix implementation and route table structure.
There are number of radix consumers in kernel land (pf,ipfw,nfs,route) with different requirements. In fact, first 3 don't have _any_ requirements and first 2 does not use radix locking. On the other hand, routing structure do have these requirements (rnh_gen, multipath, custom to-be-added control plane functions, different locking). Additionally, radix should not known anything about its consumers internals. So, radix code now uses tiny 'struct radix_head' structure along with internal 'struct radix_mask_head' instead of 'struct radix_node_head'. Existing consumers still uses the same 'struct radix_node_head' with slight modifications: they need to pass pointer to (embedded) 'struct radix_head' to all radix callbacks. Routing code now uses new 'struct rib_head' with different locking macro: RADIX_NODE_HEAD prefix was renamed to RIB_ (which stands for routing information base). New net/route_var.h header was added to hold routing subsystem internal data. 'struct rib_head' was placed there. 'struct rtentry' will also be moved there soon.
Notes
Notes: svn path=/head/; revision=294706
Diffstat (limited to 'sys/net/radix.c')
-rw-r--r--sys/net/radix.c123
1 files changed, 62 insertions, 61 deletions
diff --git a/sys/net/radix.c b/sys/net/radix.c
index d6db35ea3a94..2b4b9542b58f 100644
--- a/sys/net/radix.c
+++ b/sys/net/radix.c
@@ -56,18 +56,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
@@ -215,7 +212,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;
@@ -277,7 +274,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;
@@ -426,7 +423,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;
@@ -490,7 +487,7 @@ on1:
}
struct radix_node *
-rn_addmask(void *n_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 = n_arg;
unsigned char *cp, *cplim;
@@ -505,7 +502,7 @@ rn_addmask(void *n_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)
@@ -518,9 +515,9 @@ rn_addmask(void *n_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;
if (x || search)
@@ -530,7 +527,7 @@ rn_addmask(void *n_arg, struct radix_node_head *maskhead, int search, int skip)
return (0);
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");
R_Free(saved_x);
@@ -598,7 +595,7 @@ 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;
@@ -772,7 +769,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;
@@ -959,8 +956,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;
@@ -1065,8 +1062,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;
@@ -1105,75 +1102,76 @@ 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);
- *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. */
- R_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);
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);
}
@@ -1181,7 +1179,7 @@ rn_inithead(void **head, int off)
static int
rn_freeentry(struct radix_node *rn, void *arg)
{
- struct radix_node_head * const rnh = arg;
+ struct radix_head * const rnh = arg;
struct radix_node *x;
x = (struct radix_node *)rn_delete(rn + 2, NULL, rnh);
@@ -1198,11 +1196,14 @@ rn_detachhead(void **head)
KASSERT((head != NULL && *head != NULL),
("%s: head already freed", __func__));
- rnh = *head;
+ rnh = (struct radix_node_head *)(*head);
+
+ 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);
+
+ *head = NULL;
- rn_walktree(rnh->rnh_masks, rn_freeentry, rnh->rnh_masks);
- rn_detachhead_internal((void **)&rnh->rnh_masks);
- rn_detachhead_internal(head);
return (1);
}