From owner-svn-src-head@freebsd.org Mon Jan 25 06:33:18 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id EE68C79A8; Mon, 25 Jan 2016 06:33:17 +0000 (UTC) (envelope-from melifaro@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8EB352DE; Mon, 25 Jan 2016 06:33:17 +0000 (UTC) (envelope-from melifaro@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u0P6XG3w075370; Mon, 25 Jan 2016 06:33:16 GMT (envelope-from melifaro@FreeBSD.org) Received: (from melifaro@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u0P6XGfr075362; Mon, 25 Jan 2016 06:33:16 GMT (envelope-from melifaro@FreeBSD.org) Message-Id: <201601250633.u0P6XGfr075362@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: melifaro set sender to melifaro@FreeBSD.org using -f From: "Alexander V. Chernikov" Date: Mon, 25 Jan 2016 06:33:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r294706 - in head/sys: kern net netinet netinet6 netpfil/ipfw netpfil/pf nfs X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Jan 2016 06:33:18 -0000 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 #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 ) and are + * Initialize an empty tree. This has 3 nodes, which are passed + * via base_nodes (in the order ) 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 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 #include #include +#include #include #include @@ -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 #include #include +#include #include #include @@ -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 ***