svn commit: r294706 - in head/sys: kern net netinet netinet6 netpfil/ipfw netpfil/pf nfs

Alexander V. Chernikov melifaro at FreeBSD.org
Mon Jan 25 06:33:18 UTC 2016


Author: melifaro
Date: Mon Jan 25 06:33:15 2016
New Revision: 294706
URL: https://svnweb.freebsd.org/changeset/base/294706

Log:
  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.

Added:
  head/sys/net/route_var.h   (contents, props changed)
Modified:
  head/sys/kern/vfs_export.c
  head/sys/net/radix.c
  head/sys/net/radix.h
  head/sys/net/radix_mpath.c
  head/sys/net/radix_mpath.h
  head/sys/net/route.c
  head/sys/net/route.h
  head/sys/net/rtsock.c
  head/sys/netinet/in_fib.c
  head/sys/netinet/in_rmx.c
  head/sys/netinet/in_var.h
  head/sys/netinet6/in6_fib.c
  head/sys/netinet6/in6_rmx.c
  head/sys/netinet6/nd6_rtr.c
  head/sys/netpfil/ipfw/ip_fw_table_algo.c
  head/sys/netpfil/pf/pf_table.c
  head/sys/nfs/bootp_subr.c

Modified: head/sys/kern/vfs_export.c
==============================================================================
--- head/sys/kern/vfs_export.c	Mon Jan 25 05:33:18 2016	(r294705)
+++ head/sys/kern/vfs_export.c	Mon Jan 25 06:33:15 2016	(r294706)
@@ -199,7 +199,7 @@ vfs_hang_addrlist(struct mount *mp, stru
 		goto out;
 	}
 	RADIX_NODE_HEAD_LOCK(rnh);
-	rn = (*rnh->rnh_addaddr)(saddr, smask, rnh, np->netc_rnodes);
+	rn = (*rnh->rnh_addaddr)(saddr, smask, &rnh->rh, np->netc_rnodes);
 	RADIX_NODE_HEAD_UNLOCK(rnh);
 	if (rn == NULL || np != (struct netcred *)rn) {	/* already exists */
 		error = EPERM;
@@ -231,7 +231,7 @@ vfs_free_netcred(struct radix_node *rn, 
 	struct radix_node_head *rnh = (struct radix_node_head *) w;
 	struct ucred *cred;
 
-	(*rnh->rnh_deladdr) (rn->rn_key, rn->rn_mask, rnh);
+	(*rnh->rnh_deladdr) (rn->rn_key, rn->rn_mask, &rnh->rh);
 	cred = ((struct netcred *)rn)->netc_anon;
 	if (cred != NULL)
 		crfree(cred);
@@ -256,7 +256,7 @@ vfs_free_addrlist_af(struct radix_node_h
 
 	rnh = *prnh;
 	RADIX_NODE_HEAD_LOCK(rnh);
-	(*rnh->rnh_walktree) (rnh, vfs_free_netcred, rnh);
+	(*rnh->rnh_walktree)(&rnh->rh, vfs_free_netcred, &rnh->rh);
 	RADIX_NODE_HEAD_UNLOCK(rnh);
 	RADIX_NODE_HEAD_DESTROY(rnh);
 	free(rnh, M_RTABLE);
@@ -470,7 +470,7 @@ vfs_export_lookup(struct mount *mp, stru
 			if (rnh != NULL) {
 				RADIX_NODE_HEAD_RLOCK(rnh);
 				np = (struct netcred *)
-				    (*rnh->rnh_matchaddr)(saddr, rnh);
+				    (*rnh->rnh_matchaddr)(saddr, &rnh->rh);
 				RADIX_NODE_HEAD_RUNLOCK(rnh);
 				if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
 					np = NULL;

Modified: head/sys/net/radix.c
==============================================================================
--- head/sys/net/radix.c	Mon Jan 25 05:33:18 2016	(r294705)
+++ head/sys/net/radix.c	Mon Jan 25 06:33:15 2016	(r294706)
@@ -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 ra
  * 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_
 }
 
 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_nod
 	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_nod
 		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_nod
 		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_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 
 	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, 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);
 }
 

Modified: head/sys/net/radix.h
==============================================================================
--- head/sys/net/radix.h	Mon Jan 25 05:33:18 2016	(r294705)
+++ head/sys/net/radix.h	Mon Jan 25 06:33:15 2016	(r294706)
@@ -101,35 +101,53 @@ struct radix_mask {
 #define	rm_mask rm_rmu.rmu_mask
 #define	rm_leaf rm_rmu.rmu_leaf		/* extra field would make 32 bytes */
 
+struct radix_head;
+
 typedef int walktree_f_t(struct radix_node *, void *);
+typedef struct radix_node *rn_matchaddr_f_t(void *v,
+    struct radix_head *head);
+typedef struct radix_node *rn_addaddr_f_t(void *v, void *mask,
+    struct radix_head *head, struct radix_node nodes[]);
+typedef struct radix_node *rn_deladdr_f_t(void *v, void *mask,
+    struct radix_head *head);
+typedef struct radix_node *rn_lookup_f_t(void *v, void *mask,
+    struct radix_head *head);
+typedef int rn_walktree_t(struct radix_head *head, walktree_f_t *f,
+    void *w);
+typedef int rn_walktree_from_t(struct radix_head *head,
+    void *a, void *m, walktree_f_t *f, void *w);
+typedef void rn_close_t(struct radix_node *rn, struct radix_head *head);
 
-struct radix_node_head {
+struct radix_mask_head;
+
+struct radix_head {
 	struct	radix_node *rnh_treetop;
-	u_int	rnh_gen;		/* generation counter */
-	int	rnh_multipath;		/* multipath capable ? */
-	struct	radix_node *(*rnh_addaddr)	/* add based on sockaddr */
-		(void *v, void *mask,
-		     struct radix_node_head *head, struct radix_node nodes[]);
-	struct	radix_node *(*rnh_deladdr)	/* remove based on sockaddr */
-		(void *v, void *mask, struct radix_node_head *head);
-	struct	radix_node *(*rnh_matchaddr)	/* longest match for sockaddr */
-		(void *v, struct radix_node_head *head);
-	struct	radix_node *(*rnh_lookup)	/*exact match for sockaddr*/
-		(void *v, void *mask, struct radix_node_head *head);
-	int	(*rnh_walktree)			/* traverse tree */
-		(struct radix_node_head *head, walktree_f_t *f, void *w);
-	int	(*rnh_walktree_from)		/* traverse tree below a */
-		(struct radix_node_head *head, void *a, void *m,
-		     walktree_f_t *f, void *w);
-	void	(*rnh_close)	/* do something when the last ref drops */
-		(struct radix_node *rn, struct radix_node_head *head);
+	struct	radix_mask_head *rnh_masks;	/* Storage for our masks */
+};
+
+struct radix_node_head {
+	struct radix_head rh;
+	rn_matchaddr_f_t	*rnh_matchaddr;	/* longest match for sockaddr */
+	rn_addaddr_f_t	*rnh_addaddr;	/* add based on sockaddr*/
+	rn_deladdr_f_t	*rnh_deladdr;	/* remove based on sockaddr */
+	rn_lookup_f_t	*rnh_lookup;	/* exact match for sockaddr */
+	rn_walktree_t	*rnh_walktree;	/* traverse tree */
+	rn_walktree_from_t	*rnh_walktree_from; /* traverse tree below a */
+	rn_close_t	*rnh_close;	/*do something when the last ref drops*/
 	struct	radix_node rnh_nodes[3];	/* empty tree for common case */
-	struct	radix_node_head *rnh_masks;	/* Storage for our masks */
 #ifdef _KERNEL
 	struct	rwlock rnh_lock;		/* locks entire radix tree */
 #endif
 };
 
+struct radix_mask_head {
+	struct radix_head head;
+	struct radix_node mask_nodes[3];
+};
+
+void rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes,
+    int off);
+
 #ifndef _KERNEL
 #define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
 #define R_Zalloc(p, t, n) (p = (t) calloc(1,(unsigned int)(n)))
@@ -156,13 +174,14 @@ struct radix_node_head {
 int	 rn_inithead(void **, int);
 int	 rn_detachhead(void **);
 int	 rn_refines(void *, void *);
-struct radix_node
-	 *rn_addmask(void *, struct radix_node_head *, int, int),
-	 *rn_addroute (void *, void *, struct radix_node_head *,
-			struct radix_node [2]),
-	 *rn_delete(void *, void *, struct radix_node_head *),
-	 *rn_lookup (void *v_arg, void *m_arg,
-		        struct radix_node_head *head),
-	 *rn_match(void *, struct radix_node_head *);
+struct radix_node *rn_addroute(void *, void *, struct radix_head *,
+    struct radix_node[2]);
+struct radix_node *rn_delete(void *, void *, struct radix_head *);
+struct radix_node *rn_lookup (void *v_arg, void *m_arg,
+    struct radix_head *head);
+struct radix_node *rn_match(void *, struct radix_head *);
+int rn_walktree_from(struct radix_head *h, void *a, void *m,
+    walktree_f_t *f, void *w);
+int rn_walktree(struct radix_head *, walktree_f_t *, void *);
 
 #endif /* _RADIX_H_ */

Modified: head/sys/net/radix_mpath.c
==============================================================================
--- head/sys/net/radix_mpath.c	Mon Jan 25 05:33:18 2016	(r294705)
+++ head/sys/net/radix_mpath.c	Mon Jan 25 06:33:15 2016	(r294706)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #include <net/radix.h>
 #include <net/radix_mpath.h>
 #include <net/route.h>
+#include <net/route_var.h>
 #include <net/if.h>
 #include <net/if_var.h>
 
@@ -57,12 +58,19 @@ __FBSDID("$FreeBSD$");
 static uint32_t hashjitter;
 
 int
-rn_mpath_capable(struct radix_node_head *rnh)
+rt_mpath_capable(struct rib_head *rnh)
 {
 
 	return rnh->rnh_multipath;
 }
 
+int
+rn_mpath_capable(struct radix_head *rh)
+{
+
+	return (rt_mpath_capable((struct rib_head *)rh));
+}
+
 struct radix_node *
 rn_mpath_next(struct radix_node *rn)
 {
@@ -159,14 +167,14 @@ rt_mpath_deldup(struct rtentry *headrt, 
  * Assume @rt rt_key host bits are cleared according to @netmask
  */
 int
-rt_mpath_conflict(struct radix_node_head *rnh, struct rtentry *rt,
+rt_mpath_conflict(struct rib_head *rnh, struct rtentry *rt,
     struct sockaddr *netmask)
 {
 	struct radix_node *rn, *rn1;
 	struct rtentry *rt1;
 
 	rn = (struct radix_node *)rt;
-	rn1 = rnh->rnh_lookup(rt_key(rt), netmask, rnh);
+	rn1 = rnh->rnh_lookup(rt_key(rt), netmask, &rnh->head);
 	if (!rn1 || rn1->rn_flags & RNF_ROOT)
 		return (0);
 
@@ -284,11 +292,11 @@ extern int	in_inithead(void **head, int 
 int
 rn4_mpath_inithead(void **head, int off)
 {
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 
 	hashjitter = arc4random();
 	if (in_inithead(head, off) == 1) {
-		rnh = (struct radix_node_head *)*head;
+		rnh = (struct rib_head *)*head;
 		rnh->rnh_multipath = 1;
 		return 1;
 	} else
@@ -300,11 +308,11 @@ rn4_mpath_inithead(void **head, int off)
 int
 rn6_mpath_inithead(void **head, int off)
 {
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 
 	hashjitter = arc4random();
 	if (in6_inithead(head, off) == 1) {
-		rnh = (struct radix_node_head *)*head;
+		rnh = (struct rib_head *)*head;
 		rnh->rnh_multipath = 1;
 		return 1;
 	} else

Modified: head/sys/net/radix_mpath.h
==============================================================================
--- head/sys/net/radix_mpath.h	Mon Jan 25 05:33:18 2016	(r294705)
+++ head/sys/net/radix_mpath.h	Mon Jan 25 06:33:15 2016	(r294706)
@@ -44,11 +44,13 @@
 struct route;
 struct rtentry;
 struct sockaddr;
-int	rn_mpath_capable(struct radix_node_head *);
+struct rib_head;
+int	rt_mpath_capable(struct rib_head *);
+int	rn_mpath_capable(struct radix_head *);
 struct radix_node *rn_mpath_next(struct radix_node *);
 u_int32_t rn_mpath_count(struct radix_node *);
 struct rtentry *rt_mpath_matchgate(struct rtentry *, struct sockaddr *);
-int rt_mpath_conflict(struct radix_node_head *, struct rtentry *,
+int rt_mpath_conflict(struct rib_head *, struct rtentry *,
     struct sockaddr *);
 void rtalloc_mpath_fib(struct route *, u_int32_t, u_int);
 struct rtentry *rt_mpath_select(struct rtentry *, uint32_t);

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c	Mon Jan 25 05:33:18 2016	(r294705)
+++ head/sys/net/route.c	Mon Jan 25 06:33:15 2016	(r294706)
@@ -57,6 +57,7 @@
 #include <net/if_var.h>
 #include <net/if_dl.h>
 #include <net/route.h>
+#include <net/route_var.h>
 #include <net/vnet.h>
 #include <net/flowtable.h>
 
@@ -114,7 +115,7 @@ SYSCTL_UINT(_net, OID_AUTO, add_addr_all
 VNET_DEFINE(struct rtstat, rtstat);
 #define	V_rtstat	VNET(rtstat)
 
-VNET_DEFINE(struct radix_node_head *, rt_tables);
+VNET_DEFINE(struct rib_head *, rt_tables);
 #define	V_rt_tables	VNET(rt_tables)
 
 VNET_DEFINE(int, rttrash);		/* routes not in table but not freed */
@@ -136,15 +137,15 @@ VNET_DEFINE(int, rttrash);		/* routes no
 static VNET_DEFINE(uma_zone_t, rtzone);		/* Routing table UMA zone. */
 #define	V_rtzone	VNET(rtzone)
 
-static int rtrequest1_fib_change(struct radix_node_head *, struct rt_addrinfo *,
+static int rtrequest1_fib_change(struct rib_head *, struct rt_addrinfo *,
     struct rtentry **, u_int);
 static void rt_setmetrics(const struct rt_addrinfo *, struct rtentry *);
 static int rt_ifdelroute(const struct rtentry *rt, void *arg);
-static struct rtentry *rt_unlinkrte(struct radix_node_head *rnh,
+static struct rtentry *rt_unlinkrte(struct rib_head *rnh,
     struct rt_addrinfo *info, int *perror);
 static void rt_notifydelete(struct rtentry *rt, struct rt_addrinfo *info);
 #ifdef RADIX_MPATH
-static struct radix_node *rt_mpath_unlink(struct radix_node_head *rnh,
+static struct radix_node *rt_mpath_unlink(struct rib_head *rnh,
     struct rt_addrinfo *info, struct rtentry *rto, int *perror);
 #endif
 static int rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info,
@@ -175,10 +176,10 @@ sysctl_my_fibnum(SYSCTL_HANDLER_ARGS)
 SYSCTL_PROC(_net, OID_AUTO, my_fibnum, CTLTYPE_INT|CTLFLAG_RD,
             NULL, 0, &sysctl_my_fibnum, "I", "default FIB of caller");
 
-static __inline struct radix_node_head **
+static __inline struct rib_head **
 rt_tables_get_rnh_ptr(int table, int fam)
 {
-	struct radix_node_head **rnh;
+	struct rib_head **rnh;
 
 	KASSERT(table >= 0 && table < rt_numfibs, ("%s: table out of bounds.",
 	    __func__));
@@ -186,14 +187,14 @@ rt_tables_get_rnh_ptr(int table, int fam
 	    __func__));
 
 	/* rnh is [fib=0][af=0]. */
-	rnh = (struct radix_node_head **)V_rt_tables;
+	rnh = (struct rib_head **)V_rt_tables;
 	/* Get the offset to the requested table and fam. */
 	rnh += table * (AF_MAX+1) + fam;
 
 	return (rnh);
 }
 
-struct radix_node_head *
+struct rib_head *
 rt_tables_get_rnh(int table, int fam)
 {
 
@@ -263,12 +264,12 @@ static void
 vnet_route_init(const void *unused __unused)
 {
 	struct domain *dom;
-	struct radix_node_head **rnh;
+	struct rib_head **rnh;
 	int table;
 	int fam;
 
 	V_rt_tables = malloc(rt_numfibs * (AF_MAX+1) *
-	    sizeof(struct radix_node_head *), M_RTABLE, M_WAITOK|M_ZERO);
+	    sizeof(struct rib_head *), M_RTABLE, M_WAITOK|M_ZERO);
 
 	V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry),
 	    rtentry_ctor, rtentry_dtor,
@@ -299,7 +300,7 @@ vnet_route_uninit(const void *unused __u
 	int table;
 	int fam;
 	struct domain *dom;
-	struct radix_node_head **rnh;
+	struct rib_head **rnh;
 
 	for (dom = domains; dom; dom = dom->dom_next) {
 		if (dom->dom_rtdetach == NULL)
@@ -325,6 +326,43 @@ VNET_SYSUNINIT(vnet_route_uninit, SI_SUB
     vnet_route_uninit, 0);
 #endif
 
+struct rib_head *
+rt_table_init(int offset)
+{
+	struct rib_head *rh;
+
+	rh = malloc(sizeof(struct rib_head), M_RTABLE, M_WAITOK | M_ZERO);
+
+	/* TODO: These details should be hidded inside radix.c */
+	/* Init masks tree */
+	rn_inithead_internal(&rh->head, rh->rnh_nodes, offset);
+	rn_inithead_internal(&rh->rmhead.head, rh->rmhead.mask_nodes, 0);
+	rh->head.rnh_masks = &rh->rmhead;
+
+	/* Init locks */
+	rw_init(&rh->rib_lock, "rib head lock");
+
+	/* Finally, set base callbacks */
+	rh->rnh_addaddr = rn_addroute;
+	rh->rnh_deladdr = rn_delete;
+	rh->rnh_matchaddr = rn_match;
+	rh->rnh_lookup = rn_lookup;
+	rh->rnh_walktree = rn_walktree;
+	rh->rnh_walktree_from = rn_walktree_from;
+
+	return (rh);
+}
+
+void
+rt_table_destroy(struct rib_head *rh)
+{
+
+	/* Assume table is already empty */
+	rw_destroy(&rh->rib_lock);
+	free(rh, M_RTABLE);
+}
+
+
 #ifndef _SYS_SYSPROTO_H_
 struct setfib_args {
 	int     fibnum;
@@ -375,32 +413,32 @@ struct rtentry *
 rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
 		    u_int fibnum)
 {
-	struct radix_node_head *rnh;
+	struct rib_head *rh;
 	struct radix_node *rn;
 	struct rtentry *newrt;
 	struct rt_addrinfo info;
 	int err = 0, msgtype = RTM_MISS;
 
 	KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
-	rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
+	rh = rt_tables_get_rnh(fibnum, dst->sa_family);
 	newrt = NULL;
-	if (rnh == NULL)
+	if (rh == NULL)
 		goto miss;
 
 	/*
 	 * Look up the address in the table for that Address Family
 	 */
-	RADIX_NODE_HEAD_RLOCK(rnh);
-	rn = rnh->rnh_matchaddr(dst, rnh);
+	RIB_RLOCK(rh);
+	rn = rh->rnh_matchaddr(dst, &rh->head);
 	if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
 		newrt = RNTORT(rn);
 		RT_LOCK(newrt);
 		RT_ADDREF(newrt);
-		RADIX_NODE_HEAD_RUNLOCK(rnh);
+		RIB_RUNLOCK(rh);
 		return (newrt);
 
 	} else
-		RADIX_NODE_HEAD_RUNLOCK(rnh);
+		RIB_RUNLOCK(rh);
 	
 	/*
 	 * Either we hit the root or couldn't find any match,
@@ -430,7 +468,7 @@ miss:
 void
 rtfree(struct rtentry *rt)
 {
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 
 	KASSERT(rt != NULL,("%s: NULL rt", __func__));
 	rnh = rt_tables_get_rnh(rt->rt_fibnum, rt_key(rt)->sa_family);
@@ -458,7 +496,7 @@ rtfree(struct rtentry *rt)
 	 * on the entry so that the code below reclaims the storage.
 	 */
 	if (rt->rt_refcnt == 0 && rnh->rnh_close)
-		rnh->rnh_close((struct radix_node *)rt, rnh);
+		rnh->rnh_close((struct radix_node *)rt, &rnh->head);
 
 	/*
 	 * If we are no longer "up" (and ref == 0)
@@ -522,7 +560,7 @@ rtredirect_fib(struct sockaddr *dst,
 	short *stat = NULL;
 	struct rt_addrinfo info;
 	struct ifaddr *ifa;
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 
 	ifa = NULL;
 	rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
@@ -608,10 +646,10 @@ rtredirect_fib(struct sockaddr *dst,
 			 * add the key and gateway (in one malloc'd chunk).
 			 */
 			RT_UNLOCK(rt);
-			RADIX_NODE_HEAD_LOCK(rnh);
+			RIB_WLOCK(rnh);
 			RT_LOCK(rt);
 			rt_setgate(rt, rt_key(rt), gateway);
-			RADIX_NODE_HEAD_UNLOCK(rnh);
+			RIB_WUNLOCK(rnh);
 		}
 	} else
 		error = EHOSTUNREACH;
@@ -853,7 +891,7 @@ int
 rib_lookup_info(uint32_t fibnum, const struct sockaddr *dst, uint32_t flags,
     uint32_t flowid, struct rt_addrinfo *info)
 {
-	struct radix_node_head *rh;
+	struct rib_head *rh;
 	struct radix_node *rn;
 	struct rtentry *rt;
 	int error;
@@ -863,20 +901,20 @@ rib_lookup_info(uint32_t fibnum, const s
 	if (rh == NULL)
 		return (ENOENT);
 
-	RADIX_NODE_HEAD_RLOCK(rh);
-	rn = rh->rnh_matchaddr(__DECONST(void *, dst), rh);
+	RIB_RLOCK(rh);
+	rn = rh->rnh_matchaddr(__DECONST(void *, dst), &rh->head);
 	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
 		rt = RNTORT(rn);
 		/* Ensure route & ifp is UP */
 		if (RT_LINK_IS_UP(rt->rt_ifp)) {
 			flags = (flags & NHR_REF) | NHR_COPY;
 			error = rt_exportinfo(rt, info, flags);
-			RADIX_NODE_HEAD_RUNLOCK(rh);
+			RIB_RUNLOCK(rh);
 
 			return (error);
 		}
 	}
-	RADIX_NODE_HEAD_RUNLOCK(rh);
+	RIB_RUNLOCK(rh);
 
 	return (ENOENT);
 }
@@ -903,7 +941,7 @@ void
 rt_foreach_fib_walk(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f,
     void *arg)
 {
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 	uint32_t fibnum;
 	int i;
 
@@ -916,9 +954,9 @@ rt_foreach_fib_walk(int af, rt_setwarg_t
 			if (setwa_f != NULL)
 				setwa_f(rnh, fibnum, af, arg);
 
-			RADIX_NODE_HEAD_LOCK(rnh);
-			rnh->rnh_walktree(rnh, (walktree_f_t *)wa_f, arg);
-			RADIX_NODE_HEAD_UNLOCK(rnh);
+			RIB_WLOCK(rnh);
+			rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f,arg);
+			RIB_WUNLOCK(rnh);
 			continue;
 		}
 
@@ -929,9 +967,9 @@ rt_foreach_fib_walk(int af, rt_setwarg_t
 			if (setwa_f != NULL)
 				setwa_f(rnh, fibnum, i, arg);
 
-			RADIX_NODE_HEAD_LOCK(rnh);
-			rnh->rnh_walktree(rnh, (walktree_f_t *)wa_f, arg);
-			RADIX_NODE_HEAD_UNLOCK(rnh);
+			RIB_WLOCK(rnh);
+			rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f,arg);
+			RIB_WUNLOCK(rnh);
 		}
 	}
 }
@@ -939,7 +977,7 @@ rt_foreach_fib_walk(int af, rt_setwarg_t
 struct rt_delinfo
 {
 	struct rt_addrinfo info;
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 	struct rtentry *head;
 };
 
@@ -987,7 +1025,7 @@ rt_checkdelroute(struct radix_node *rn, 
 void
 rt_foreach_fib_walk_del(int af, rt_filter_f_t *filter_f, void *arg)
 {
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 	struct rt_delinfo di;
 	struct rtentry *rt;
 	uint32_t fibnum;
@@ -1013,9 +1051,9 @@ rt_foreach_fib_walk_del(int af, rt_filte
 				continue;
 			di.rnh = rnh;
 
-			RADIX_NODE_HEAD_LOCK(rnh);
-			rnh->rnh_walktree(rnh, rt_checkdelroute, &di);
-			RADIX_NODE_HEAD_UNLOCK(rnh);
+			RIB_WLOCK(rnh);
+			rnh->rnh_walktree(&rnh->head, rt_checkdelroute, &di);
+			RIB_WUNLOCK(rnh);
 
 			if (di.head == NULL)
 				continue;
@@ -1092,7 +1130,7 @@ rt_flushifroutes(struct ifnet *ifp)
  * ENOENT - if supplied filter function returned 0 (not matched).
  */
 static struct rtentry *
-rt_unlinkrte(struct radix_node_head *rnh, struct rt_addrinfo *info, int *perror)
+rt_unlinkrte(struct rib_head *rnh, struct rt_addrinfo *info, int *perror)
 {
 	struct sockaddr *dst, *netmask;
 	struct rtentry *rt;
@@ -1101,7 +1139,7 @@ rt_unlinkrte(struct radix_node_head *rnh
 	dst = info->rti_info[RTAX_DST];
 	netmask = info->rti_info[RTAX_NETMASK];
 
-	rt = (struct rtentry *)rnh->rnh_lookup(dst, netmask, rnh);
+	rt = (struct rtentry *)rnh->rnh_lookup(dst, netmask, &rnh->head);
 	if (rt == NULL) {
 		*perror = ESRCH;
 		return (NULL);
@@ -1136,11 +1174,11 @@ rt_unlinkrte(struct radix_node_head *rnh
 	 */
 	*perror = ESRCH;
 #ifdef RADIX_MPATH
-	if (rn_mpath_capable(rnh))
+	if (rt_mpath_capable(rnh))
 		rn = rt_mpath_unlink(rnh, info, rt, perror);
 	else
 #endif
-	rn = rnh->rnh_deladdr(dst, netmask, rnh);
+	rn = rnh->rnh_deladdr(dst, netmask, &rnh->head);
 	if (rn == NULL)
 		return (NULL);
 
@@ -1273,7 +1311,7 @@ void
 rt_updatemtu(struct ifnet *ifp)
 {
 	struct if_mtuinfo ifmtu;
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 	int i, j;
 
 	ifmtu.ifp = ifp;
@@ -1289,9 +1327,9 @@ rt_updatemtu(struct ifnet *ifp)
 			rnh = rt_tables_get_rnh(j, i);
 			if (rnh == NULL)
 				continue;
-			RADIX_NODE_HEAD_LOCK(rnh);
-			rnh->rnh_walktree(rnh, if_updatemtu_cb, &ifmtu);
-			RADIX_NODE_HEAD_UNLOCK(rnh);
+			RIB_WLOCK(rnh);
+			rnh->rnh_walktree(&rnh->head, if_updatemtu_cb, &ifmtu);
+			RIB_WUNLOCK(rnh);
 		}
 	}
 }
@@ -1357,7 +1395,7 @@ rt_print(char *buf, int buflen, struct r
  * and sets @perror to ESRCH.
  */
 static struct radix_node *
-rt_mpath_unlink(struct radix_node_head *rnh, struct rt_addrinfo *info,
+rt_mpath_unlink(struct rib_head *rnh, struct rt_addrinfo *info,
     struct rtentry *rto, int *perror)
 {
 	/*
@@ -1409,7 +1447,7 @@ rt_mpath_unlink(struct radix_node_head *
 		 * use the normal delete code to remove
 		 * the first entry
 		 */
-		rn = rnh->rnh_deladdr(dst, netmask, rnh);
+		rn = rnh->rnh_deladdr(dst, netmask, &rnh->head);
 		*perror = 0;
 		return (rn);
 	}
@@ -1427,7 +1465,7 @@ rt_mpath_unlink(struct radix_node_head *
 
 #ifdef FLOWTABLE
 static struct rtentry *
-rt_flowtable_check_route(struct radix_node_head *rnh, struct rt_addrinfo *info)
+rt_flowtable_check_route(struct rib_head *rnh, struct rt_addrinfo *info)
 {
 #if defined(INET6) || defined(INET)
 	struct radix_node *rn;
@@ -1499,7 +1537,7 @@ rtrequest1_fib(int req, struct rt_addrin
 	struct rtentry *rt0;
 #endif
 	struct radix_node *rn;
-	struct radix_node_head *rnh;
+	struct rib_head *rnh;
 	struct ifaddr *ifa;
 	struct sockaddr *ndst;
 	struct sockaddr_storage mdst;
@@ -1537,9 +1575,9 @@ rtrequest1_fib(int req, struct rt_addrin
 			dst = (struct sockaddr *)&mdst;
 		}
 
-		RADIX_NODE_HEAD_LOCK(rnh);
+		RIB_WLOCK(rnh);
 		rt = rt_unlinkrte(rnh, info, &error);
-		RADIX_NODE_HEAD_UNLOCK(rnh);
+		RIB_WUNLOCK(rnh);
 		if (error != 0)
 			return (error);
 
@@ -1616,13 +1654,13 @@ rtrequest1_fib(int req, struct rt_addrin
 
 		rt_setmetrics(info, rt);
 
-		RADIX_NODE_HEAD_LOCK(rnh);
+		RIB_WLOCK(rnh);
 		RT_LOCK(rt);
 #ifdef RADIX_MPATH
 		/* do not permit exactly the same dst/mask/gw pair */
-		if (rn_mpath_capable(rnh) &&
+		if (rt_mpath_capable(rnh) &&
 			rt_mpath_conflict(rnh, rt, netmask)) {
-			RADIX_NODE_HEAD_UNLOCK(rnh);
+			RIB_WUNLOCK(rnh);
 
 			ifa_free(rt->rt_ifa);
 			R_Free(rt_key(rt));
@@ -1636,7 +1674,7 @@ rtrequest1_fib(int req, struct rt_addrin
 #endif /* FLOWTABLE */
 
 		/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
-		rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes);
+		rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, rt->rt_nodes);
 
 		rt_old = NULL;
 		if (rn == NULL && (info->rti_flags & RTF_PINNED) != 0) {
@@ -1653,10 +1691,10 @@ rtrequest1_fib(int req, struct rt_addrin
 			info->rti_flags |= RTF_PINNED;
 			info->rti_info[RTAX_DST] = info_dst;
 			if (rt_old != NULL)
-				rn = rnh->rnh_addaddr(ndst, netmask, rnh,
+				rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head,
 				    rt->rt_nodes);
 		}
-		RADIX_NODE_HEAD_UNLOCK(rnh);
+		RIB_WUNLOCK(rnh);
 
 		if (rt_old != NULL)
 			RT_UNLOCK(rt_old);
@@ -1705,9 +1743,9 @@ rtrequest1_fib(int req, struct rt_addrin
 		RT_UNLOCK(rt);
 		break;
 	case RTM_CHANGE:
-		RADIX_NODE_HEAD_LOCK(rnh);
+		RIB_WLOCK(rnh);
 		error = rtrequest1_fib_change(rnh, info, ret_nrt, fibnum);
-		RADIX_NODE_HEAD_UNLOCK(rnh);
+		RIB_WUNLOCK(rnh);
 		break;
 	default:
 		error = EOPNOTSUPP;
@@ -1724,7 +1762,7 @@ rtrequest1_fib(int req, struct rt_addrin
 #undef flags
 
 static int
-rtrequest1_fib_change(struct radix_node_head *rnh, struct rt_addrinfo *info,
+rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info,
     struct rtentry **ret_nrt, u_int fibnum)
 {
 	struct rtentry *rt = NULL;
@@ -1734,7 +1772,7 @@ rtrequest1_fib_change(struct radix_node_
 	struct if_mtuinfo ifmtu;
 
 	rt = (struct rtentry *)rnh->rnh_lookup(info->rti_info[RTAX_DST],
-	    info->rti_info[RTAX_NETMASK], rnh);
+	    info->rti_info[RTAX_NETMASK], &rnh->head);
 
 	if (rt == NULL)
 		return (ESRCH);
@@ -1744,7 +1782,7 @@ rtrequest1_fib_change(struct radix_node_
 	 * If we got multipath routes,
 	 * we require users to specify a matching RTAX_GATEWAY.
 	 */
-	if (rn_mpath_capable(rnh)) {
+	if (rt_mpath_capable(rnh)) {
 		rt = rt_mpath_matchgate(rt, info->rti_info[RTAX_GATEWAY]);
 		if (rt == NULL)
 			return (ESRCH);
@@ -1935,7 +1973,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int
 	int didwork = 0;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list