From owner-svn-src-projects@FreeBSD.ORG Sun Nov 9 00:36:42 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 1FFB9746; Sun, 9 Nov 2014 00:36:42 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::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 09BD9206; Sun, 9 Nov 2014 00:36:42 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sA90agAL030712; Sun, 9 Nov 2014 00:36:42 GMT (envelope-from melifaro@FreeBSD.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sA90aeAj030701; Sun, 9 Nov 2014 00:36:40 GMT (envelope-from melifaro@FreeBSD.org) Message-Id: <201411090036.sA90aeAj030701@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: melifaro set sender to melifaro@FreeBSD.org using -f From: "Alexander V. Chernikov" Date: Sun, 9 Nov 2014 00:36:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r274301 - in projects/routing/sys: kern net netinet netinet6 netpfil/ipfw netpfil/pf nfs X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 Nov 2014 00:36:42 -0000 Author: melifaro Date: Sun Nov 9 00:36:39 2014 New Revision: 274301 URL: https://svnweb.freebsd.org/changeset/base/274301 Log: Separate radix and routing: use different structures for route and for other customers. Introduce new 'struct rib_head' for routing purposes and make all routing api use it. Modified: projects/routing/sys/kern/vfs_export.c projects/routing/sys/net/radix.c projects/routing/sys/net/radix.h projects/routing/sys/net/radix_mpath.c projects/routing/sys/net/route.c projects/routing/sys/net/route.h projects/routing/sys/net/route_internal.h projects/routing/sys/net/rt_nhops.c projects/routing/sys/net/rt_nhops.h projects/routing/sys/net/rtsock.c projects/routing/sys/netinet/in_rmx.c projects/routing/sys/netinet/in_var.h projects/routing/sys/netinet/ip_icmp.c projects/routing/sys/netinet6/in6_rmx.c projects/routing/sys/netinet6/nd6_rtr.c projects/routing/sys/netpfil/ipfw/ip_fw_table_algo.c projects/routing/sys/netpfil/pf/pf_table.c projects/routing/sys/nfs/bootp_subr.c Modified: projects/routing/sys/kern/vfs_export.c ============================================================================== --- projects/routing/sys/kern/vfs_export.c Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/kern/vfs_export.c Sun Nov 9 00:36:39 2014 (r274301) @@ -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: projects/routing/sys/net/radix.c ============================================================================== --- projects/routing/sys/net/radix.c Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/net/radix.c Sun Nov 9 00:36:39 2014 (r274301) @@ -56,9 +56,6 @@ #include #endif /* !_KERNEL */ -static int rn_walktree_from(struct radix_head *h, void *a, void *m, - walktree_f_t *f, void *w); -static int rn_walktree(struct radix_head *, walktree_f_t *, void *); static struct radix_node *rn_insert(void *, struct radix_head *, int *, struct radix_node [2]), @@ -68,7 +65,6 @@ static struct radix_node static struct radix_node *rn_addmask(void *, struct radix_head *, int, int); static void rn_detachhead_internal(void **head); -static int rn_inithead_internal(void **head, int off); #define RADIX_MAX_KEY_LEN 32 @@ -225,7 +221,7 @@ rn_lookup(void *v_arg, void *m_arg, stru /* * Most common case: search exact prefix/mask */ - x = rn_addmask(m_arg, head->rnh_masks, 1, + x = rn_addmask(m_arg, head->s.rnh_masks, 1, head->rnh_treetop->rn_offset); if (x == NULL) return (NULL); @@ -507,7 +503,7 @@ rn_addmask(void *n_arg, struct radix_hea if (skip == 0) skip = 1; if (mlen <= skip) - return (((struct radix_node_head *)maskhead)->rnh_nodes); + return (maskhead->s.mask_nodes); bzero(addmask_key, RADIX_MAX_KEY_LEN); if (skip > 1) @@ -520,7 +516,7 @@ rn_addmask(void *n_arg, struct radix_hea cp--; mlen = cp - addmask_key; if (mlen <= skip) - return (((struct radix_node_head *)maskhead)->rnh_nodes); + return (maskhead->s.mask_nodes); *addmask_key = mlen; x = rn_search(addmask_key, maskhead->rnh_treetop); if (bcmp(addmask_key, x->rn_key, mlen) != 0) @@ -619,7 +615,7 @@ rn_addroute(void *v_arg, void *n_arg, st * nodes and possibly save time in calculating indices. */ if (netmask) { - x = rn_addmask(netmask, head->rnh_masks, 0, top->rn_offset); + x = rn_addmask(netmask, head->s.rnh_masks, 0, top->rn_offset); if (x == NULL) return (0); b_leaf = x->rn_bit; @@ -797,7 +793,7 @@ rn_delete(void *v_arg, void *netmask_arg * Delete our route from mask lists. */ if (netmask) { - x = rn_addmask(netmask, head->rnh_masks, 1, head_off); + x = rn_addmask(netmask, head->s.rnh_masks, 1, head_off); if (x == NULL) return (0); netmask = x->rn_key; @@ -961,7 +957,7 @@ out: * This is the same as rn_walktree() except for the parameters and the * exit. */ -static int +int rn_walktree_from(struct radix_head *h, void *a, void *m, walktree_f_t *f, void *w) { @@ -1067,7 +1063,7 @@ rn_walktree_from(struct radix_head *h, v return (0); } -static int +int rn_walktree(struct radix_head *h, walktree_f_t *f, void *w) { int error; @@ -1107,76 +1103,75 @@ rn_walktree(struct radix_head *h, walktr } /* - * 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_addaddr_f_t *)rn_addroute; - rnh->rnh_deladdr = (rn_deladdr_f_t *)rn_delete; - rnh->rnh_matchaddr = (rn_matchaddr_f_t *)rn_match; - rnh->rnh_lookup = (rn_lookup_f_t *)rn_lookup; - rnh->rnh_walktree = (rn_walktree_t *)rn_walktree; - rnh->rnh_walktree_from = (rn_walktree_from_t *)rn_walktree_from; - rnh->rh.rnh_treetop = t; - return (1); + + rh->rnh_treetop = t; } static void rn_detachhead_internal(void **head) { - struct radix_node_head *rnh; KASSERT((head != NULL && *head != NULL), ("%s: head already freed", __func__)); - rnh = *head; /* Free nodes. */ - Free(rnh); + Free(*head); *head = NULL; } +/* BELOW ARE FUNCTIONS TO SUPPORT struct radix_node_head USERS */ int rn_inithead(void **head, int off) { struct radix_node_head *rnh; + struct radix_mask_head *rmh; if (*head != NULL) return (1); - if (rn_inithead_internal(head, off) == 0) - return (0); - - rnh = (struct radix_node_head *)(*head); - - if (rn_inithead_internal((void **)&rnh->rh.rnh_masks, 0) == 0) { - rn_detachhead_internal(head); - return (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) + Free(rnh); + return (1); } + /* Init trees */ + rn_inithead_internal(&rnh->rh, rnh->rnh_nodes, off); + rn_inithead_internal(&rmh->head, rmh->mask_nodes, 0); + rnh->rh.s.rnh_masks = &rmh->head; + rmh->head.s.mask_nodes = rmh->mask_nodes; + + /* 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); } @@ -1202,8 +1197,8 @@ rn_detachhead(void **head) rnh = *head; - rn_walktree(rnh->rh.rnh_masks, rn_freeentry, rnh->rh.rnh_masks); - rn_detachhead_internal((void **)&rnh->rh.rnh_masks); + rn_walktree(rnh->rh.s.rnh_masks, rn_freeentry, rnh->rh.s.rnh_masks); + rn_detachhead_internal((void **)&rnh->rh.s.rnh_masks); rn_detachhead_internal(head); return (1); } Modified: projects/routing/sys/net/radix.h ============================================================================== --- projects/routing/sys/net/radix.h Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/net/radix.h Sun Nov 9 00:36:39 2014 (r274301) @@ -101,26 +101,29 @@ 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_node_head; +struct radix_head; typedef int walktree_f_t(struct radix_node *, void *); typedef struct radix_node *rn_matchaddr_f_t(void *v, - struct radix_node_head *head); + struct radix_head *head); typedef struct radix_node *rn_addaddr_f_t(void *v, void *mask, - struct radix_node_head *head, struct radix_node nodes[]); + struct radix_head *head, struct radix_node nodes[]); typedef struct radix_node *rn_deladdr_f_t(void *v, void *mask, - struct radix_node_head *head); + struct radix_head *head); typedef struct radix_node *rn_lookup_f_t(void *v, void *mask, - struct radix_node_head *head); -typedef int rn_walktree_t(struct radix_node_head *head, walktree_f_t *f, + 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_node_head *head, +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_node_head *head); +typedef void rn_close_t(struct radix_node *rn, struct radix_head *head); struct radix_head { struct radix_node *rnh_treetop; - struct radix_head *rnh_masks; /* Storage for our masks */ + union { + struct radix_head *rnh_masks; /* Storage for our masks */ + struct radix_node *mask_nodes; + } s; }; struct radix_node_head { @@ -140,6 +143,14 @@ struct radix_node_head { #endif }; +/* XXX: Temporarily xported to support external radix users */ +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))) @@ -172,5 +183,8 @@ struct radix_node *rn_delete(void *, voi 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: projects/routing/sys/net/radix_mpath.c ============================================================================== --- projects/routing/sys/net/radix_mpath.c Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/net/radix_mpath.c Sun Nov 9 00:36:39 2014 (r274301) @@ -167,7 +167,7 @@ rt_mpath_conflict(struct radix_node_head 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->rh); if (!rn1 || rn1->rn_flags & RNF_ROOT) return (0); Modified: projects/routing/sys/net/route.c ============================================================================== --- projects/routing/sys/net/route.c Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/net/route.c Sun Nov 9 00:36:39 2014 (r274301) @@ -116,7 +116,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 */ @@ -138,7 +138,7 @@ 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(struct rtentry *rt, void *arg); @@ -160,25 +160,25 @@ 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 **rh; KASSERT(table >= 0 && table < rt_numfibs, ("%s: table out of bounds.", __func__)); KASSERT(fam >= 0 && fam < (AF_MAX+1), ("%s: fam out of bounds.", __func__)); - /* rnh is [fib=0][af=0]. */ - rnh = (struct radix_node_head **)V_rt_tables; + /* rh is [fib=0][af=0]. */ + rh = (struct rib_head **)V_rt_tables; /* Get the offset to the requested table and fam. */ - rnh += table * (AF_MAX+1) + fam; + rh += table * (AF_MAX+1) + fam; - return (rnh); + return (rh); } -struct radix_node_head * +struct rib_head * rt_tables_get_rnh(int table, int fam) { @@ -247,12 +247,12 @@ static void vnet_route_init(const void *unused __unused) { struct domain *dom; - struct radix_node_head **rnh; + struct rib_head **rh; 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, @@ -266,10 +266,10 @@ vnet_route_init(const void *unused __unu if (table != 0 && fam != AF_INET6 && fam != AF_INET) break; - rnh = rt_tables_get_rnh_ptr(table, fam); - if (rnh == NULL) - panic("%s: rnh NULL", __func__); - dom->dom_rtattach((void **)rnh, 0); + rh = rt_tables_get_rnh_ptr(table, fam); + if (rh == NULL) + panic("%s: rh NULL", __func__); + dom->dom_rtattach((void **)rh, 0); } } } @@ -283,7 +283,7 @@ vnet_route_uninit(const void *unused __u int table; int fam; struct domain *dom; - struct radix_node_head **rnh; + struct rib_head **rh; for (dom = domains; dom; dom = dom->dom_next) { if (dom->dom_rtdetach == NULL) @@ -295,10 +295,10 @@ vnet_route_uninit(const void *unused __u if (table != 0 && fam != AF_INET6 && fam != AF_INET) break; - rnh = rt_tables_get_rnh_ptr(table, fam); - if (rnh == NULL) - panic("%s: rnh NULL", __func__); - dom->dom_rtdetach((void **)rnh, 0); + rh = rt_tables_get_rnh_ptr(table, fam); + if (rh == NULL) + panic("%s: rh NULL", __func__); + dom->dom_rtdetach((void **)rh, 0); } } @@ -309,6 +309,44 @@ 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); + + /* XXX: 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.s.rnh_masks = &rh->rmhead.head; + rh->rmhead.head.s.mask_nodes = rh->rmhead.mask_nodes; + + /* Init locks */ + rw_init(&rh->rib_lock, "rib head"); + + /* 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; @@ -388,7 +426,7 @@ 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; @@ -396,9 +434,9 @@ rtalloc1_fib(struct sockaddr *dst, int r int needlock; 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; /* @@ -406,22 +444,22 @@ rtalloc1_fib(struct sockaddr *dst, int r */ needlock = !(ignflags & RTF_RNH_LOCKED); if (needlock) - RADIX_NODE_HEAD_RLOCK(rnh); + RIB_RLOCK(rh); #ifdef INVARIANTS else - RADIX_NODE_HEAD_LOCK_ASSERT(rnh); + RIB_LOCK_ASSERT(rh); #endif - rn = rnh->rnh_matchaddr(dst, rnh); + rn = rh->rnh_matchaddr(dst, &rh->head); if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) { newrt = RNTORT(rn); RT_LOCK(newrt); RT_ADDREF(newrt); if (needlock) - RADIX_NODE_HEAD_RUNLOCK(rnh); + RIB_RUNLOCK(rh); goto done; } else if (needlock) - RADIX_NODE_HEAD_RUNLOCK(rnh); + RIB_RUNLOCK(rh); /* * Either we hit the root or couldn't find any match, @@ -454,11 +492,11 @@ done: void rtfree(struct rtentry *rt) { - struct radix_node_head *rnh; + struct rib_head *rh; KASSERT(rt != NULL,("%s: NULL rt", __func__)); - rnh = rt_tables_get_rnh(rt->rt_fibnum, rt_key(rt)->sa_family); - KASSERT(rnh != NULL,("%s: NULL rnh", __func__)); + rh = rt_tables_get_rnh(rt->rt_fibnum, rt_key(rt)->sa_family); + KASSERT(rh != NULL,("%s: NULL rh", __func__)); RT_LOCK_ASSERT(rt); @@ -481,8 +519,8 @@ rtfree(struct rtentry *rt) * typically calls rtexpunge which clears the RTF_UP flag * 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); + if (rt->rt_refcnt == 0 && rh->rnh_close) + rh->rnh_close((struct radix_node *)rt, &rh->head); /* * If we are no longer "up" (and ref == 0) @@ -557,11 +595,11 @@ rtredirect_fib(struct sockaddr *dst, short *stat = NULL; struct rt_addrinfo info; struct ifaddr *ifa; - struct radix_node_head *rnh; + struct rib_head *rh; ifa = NULL; - rnh = rt_tables_get_rnh(fibnum, dst->sa_family); - if (rnh == NULL) { + rh = rt_tables_get_rnh(fibnum, dst->sa_family); + if (rh == NULL) { error = EAFNOSUPPORT; goto out; } @@ -615,7 +653,7 @@ rtredirect_fib(struct sockaddr *dst, info.rti_ifa = ifa; info.rti_flags = flags; if (rt0 != NULL) - RT_UNLOCK(rt0); /* drop lock to avoid LOR with RNH */ + RT_UNLOCK(rt0); /* drop lock to avoid LOR with rh */ error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum); if (rt != NULL) { RT_LOCK(rt); @@ -641,11 +679,11 @@ 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(rh); RT_LOCK(rt); rt_setgate(rt, rt_key(rt), gateway); gwrt = rtalloc1(gateway, 1, RTF_RNH_LOCKED); - RADIX_NODE_HEAD_UNLOCK(rnh); + RIB_WUNLOCK(rh); EVENTHANDLER_INVOKE(route_redirect_event, rt, gwrt, dst); RTFREE_LOCKED(gwrt); } @@ -810,35 +848,35 @@ rtrequest_fib(int req, void rt_foreach_fib(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f, void *arg) { - struct radix_node_head *rnh; + struct rib_head *rh; uint32_t fibnum; int i; for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { /* Do we want some specific family? */ if (af != AF_UNSPEC) { - rnh = rt_tables_get_rnh(fibnum, af); - if (rnh == NULL) + rh = rt_tables_get_rnh(fibnum, af); + if (rh == NULL) continue; if (setwa_f != NULL) - setwa_f(rnh, fibnum, i, arg); + setwa_f(rh, 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(rh); + rh->rnh_walktree(&rh->head, (walktree_f_t *)wa_f, arg); + RIB_WUNLOCK(rh); continue; } for (i = 1; i <= AF_MAX; i++) { - rnh = rt_tables_get_rnh(fibnum, i); - if (rnh == NULL) + rh = rt_tables_get_rnh(fibnum, i); + if (rh == NULL) continue; if (setwa_f != NULL) - setwa_f(rnh, fibnum, i, arg); + setwa_f(rh, 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(rh); + rh->rnh_walktree(&rh->head, (walktree_f_t *)wa_f, arg); + RIB_WUNLOCK(rh); } } } @@ -846,12 +884,12 @@ rt_foreach_fib(int af, rt_setwarg_t *set /* * Delete Routes for a Network Interface * - * Called for each routing entry via the rnh->rnh_walktree() call above + * Called for each routing entry via the rh->rnh_walktree() call above * to delete all route entries referencing a detaching network interface. * * Arguments: * rt pointer to rtentry - * arg argument passed to rnh->rnh_walktree() - detaching interface + * arg argument passed to rh->rnh_walktree() - detaching interface * * Returns: * 0 successful @@ -963,7 +1001,7 @@ rt_getifa_fib(struct rt_addrinfo *info, * The route must be locked. */ int -rt_expunge(struct radix_node_head *rnh, struct rtentry *rt) +rt_expunge(struct rib_head *rh, struct rtentry *rt) { #if !defined(RADIX_MPATH) struct radix_node *rn; @@ -976,7 +1014,7 @@ rt_expunge(struct radix_node_head *rnh, int error = 0; RT_LOCK_ASSERT(rt); - RADIX_NODE_HEAD_LOCK_ASSERT(rnh); + RIB_LOCK_ASSERT(rh); #ifdef RADIX_MPATH fib = rt->rt_fibnum; @@ -1001,7 +1039,7 @@ rt_expunge(struct radix_node_head *rnh, * Remove the item from the tree; it should be there, * but when callers invoke us blindly it may not (sigh). */ - rn = rnh->rnh_deladdr(rt_key(rt), rt_mask(rt), rnh); + rn = rh->rnh_deladdr(rt_key(rt), rt_mask(rt), &rh->head); if (rn == NULL) { error = ESRCH; goto bad; @@ -1093,7 +1131,7 @@ rt_print(char *buf, int buflen, struct r #ifdef RADIX_MPATH static int rn_mpath_update(int req, struct rt_addrinfo *info, - struct radix_node_head *rnh, struct rtentry **ret_nrt) + struct rib_head *rh, struct rtentry **ret_nrt) { /* * if we got multipath routes, we require users to specify @@ -1103,7 +1141,7 @@ rn_mpath_update(int req, struct rt_addri struct radix_node *rn; int error = 0; - rn = rnh->rnh_lookup(dst, netmask, rnh); + rn = rh->rnh_lookup(dst, netmask, rh); if (rn == NULL) return (ESRCH); rto = rt = RNTORT(rn); @@ -1142,7 +1180,7 @@ rn_mpath_update(int req, struct rt_addri * remove from tree before returning it * to the caller */ - rn = rnh->rnh_deladdr(dst, netmask, rnh); + rn = rh->rnh_deladdr(dst, netmask, rh); KASSERT(rt == RNTORT(rn), ("radix node disappeared")); goto gwdelete; } @@ -1207,7 +1245,7 @@ rtrequest1_fib(int req, struct rt_addrin struct rtentry *rt0; #endif struct radix_node *rn; - struct radix_node_head *rnh; + struct rib_head *rh; struct ifaddr *ifa; struct sockaddr *ndst; struct sockaddr_storage mdst; @@ -1227,15 +1265,15 @@ rtrequest1_fib(int req, struct rt_addrin /* * Find the correct routing tree to use for this Address Family */ - rnh = rt_tables_get_rnh(fibnum, dst->sa_family); - if (rnh == NULL) + rh = rt_tables_get_rnh(fibnum, dst->sa_family); + if (rh == NULL) return (EAFNOSUPPORT); needlock = ((flags & RTF_RNH_LOCKED) == 0); flags &= ~RTF_RNH_LOCKED; if (needlock) - RADIX_NODE_HEAD_LOCK(rnh); + RIB_WLOCK(rh); else - RADIX_NODE_HEAD_LOCK_ASSERT(rnh); + RIB_LOCK_ASSERT(rh); /* * If we are adding a host route then we don't want to put * a netmask in the tree, nor do we want to clone it. @@ -1250,8 +1288,8 @@ rtrequest1_fib(int req, struct rt_addrin dst = (struct sockaddr *)&mdst; } #ifdef RADIX_MPATH - if (rn_mpath_capable(rnh)) { - error = rn_mpath_update(req, info, rnh, ret_nrt); + if (rn_mpath_capable(rh)) { + error = rn_mpath_update(req, info, rh, ret_nrt); /* * "bad" holds true for the success case * as well @@ -1263,8 +1301,8 @@ rtrequest1_fib(int req, struct rt_addrin #endif if ((flags & RTF_PINNED) == 0) { /* Check if target route can be deleted */ - rt = (struct rtentry *)rnh->rnh_lookup(dst, - netmask, rnh); + rt = (struct rtentry *)rh->rnh_lookup(dst, + netmask, &rh->head); if ((rt != NULL) && (rt->rt_flags & RTF_PINNED)) senderr(EADDRINUSE); } @@ -1273,7 +1311,7 @@ rtrequest1_fib(int req, struct rt_addrin * Remove the item from the tree and return it. * Complain if it is not there and do no more processing. */ - rn = rnh->rnh_deladdr(dst, netmask, rnh); + rn = rh->rnh_deladdr(dst, netmask, &rh->head); if (rn == NULL) senderr(ESRCH); if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) @@ -1359,7 +1397,7 @@ rtrequest1_fib(int req, struct rt_addrin /* * We use the ifa reference returned by rt_getifa_fib(). - * This moved from below so that rnh->rnh_addaddr() can + * This moved from below so that rh->rnh_addaddr() can * examine the ifa and ifa->ifa_ifp if it so desires. */ rt->rt_ifa = ifa; @@ -1370,8 +1408,8 @@ rtrequest1_fib(int req, struct rt_addrin #ifdef RADIX_MPATH /* do not permit exactly the same dst/mask/gw pair */ - if (rn_mpath_capable(rnh) && - rt_mpath_conflict(rnh, rt, netmask)) { + if (rn_mpath_capable(rh) && + rt_mpath_conflict(rh, rt, netmask)) { ifa_free(rt->rt_ifa); Free(rt_key(rt)); uma_zfree(V_rtzone, rt); @@ -1390,7 +1428,7 @@ rtrequest1_fib(int req, struct rt_addrin case AF_INET: #endif #if defined(INET6) || defined(INET) - rn = rnh->rnh_matchaddr(dst, rnh); + rn = rh->rnh_matchaddr(dst, rh); if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) { struct sockaddr *mask; u_char *m, *n; @@ -1433,7 +1471,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 = rh->rnh_addaddr(ndst, netmask, &rh->head, rt->rt_nodes); /* * If it still failed to go into the tree, * then un-make it (this should be a function) @@ -1473,14 +1511,14 @@ rtrequest1_fib(int req, struct rt_addrin RT_UNLOCK(rt); break; case RTM_CHANGE: - error = rtrequest1_fib_change(rnh, info, ret_nrt, fibnum); + error = rtrequest1_fib_change(rh, info, ret_nrt, fibnum); break; default: error = EOPNOTSUPP; } bad: if (needlock) - RADIX_NODE_HEAD_UNLOCK(rnh); + RIB_WUNLOCK(rh); return (error); #undef senderr } @@ -1493,7 +1531,7 @@ bad: #undef flags static int -rtrequest1_fib_change(struct radix_node_head *rnh, struct rt_addrinfo *info, +rtrequest1_fib_change(struct rib_head *rh, struct rt_addrinfo *info, struct rtentry **ret_nrt, u_int fibnum) { struct rtentry *rt = NULL; @@ -1501,8 +1539,8 @@ rtrequest1_fib_change(struct radix_node_ int free_ifa = 0; int family, mtu; - rt = (struct rtentry *)rnh->rnh_lookup(info->rti_info[RTAX_DST], - info->rti_info[RTAX_NETMASK], rnh); + rt = (struct rtentry *)rh->rnh_lookup(info->rti_info[RTAX_DST], + info->rti_info[RTAX_NETMASK], &rh->head); if (rt == NULL) return (ESRCH); @@ -1512,7 +1550,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 (rn_mpath_capable(rh)) { rt = rt_mpath_matchgate(rt, info->rti_info[RTAX_GATEWAY]); if (rt == NULL) return (ESRCH); @@ -1609,13 +1647,13 @@ rt_setgate(struct rtentry *rt, struct so /* XXX dst may be overwritten, can we move this to below */ int dlen = SA_SIZE(dst), glen = SA_SIZE(gate); #ifdef INVARIANTS - struct radix_node_head *rnh; + struct rib_head *rh; - rnh = rt_tables_get_rnh(rt->rt_fibnum, dst->sa_family); + rh = rt_tables_get_rnh(rt->rt_fibnum, dst->sa_family); #endif RT_LOCK_ASSERT(rt); - RADIX_NODE_HEAD_LOCK_ASSERT(rnh); + RIB_LOCK_ASSERT(rh); /* * Prepare to store the gateway in rt->rt_gateway. @@ -1688,7 +1726,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int int didwork = 0; int a_failure = 0; static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; - struct radix_node_head *rnh; + struct rib_head *rh; if (flags & RTF_HOST) { dst = ifa->ifa_dstaddr; @@ -1752,14 +1790,14 @@ rtinit1(struct ifaddr *ifa, int cmd, int * Look up an rtentry that is in the routing tree and * contains the correct info. */ - rnh = rt_tables_get_rnh(fibnum, dst->sa_family); - if (rnh == NULL) + rh = rt_tables_get_rnh(fibnum, dst->sa_family); + if (rh == NULL) /* this table doesn't exist but others might */ continue; - RADIX_NODE_HEAD_RLOCK(rnh); - rn = rnh->rnh_lookup(dst, netmask, rnh); + RIB_RLOCK(rh); + rn = rh->rnh_lookup(dst, netmask, &rh->head); #ifdef RADIX_MPATH - if (rn_mpath_capable(rnh)) { + if (rn_mpath_capable(rh)) { if (rn == NULL) error = ESRCH; @@ -1782,7 +1820,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int error = (rn == NULL || (rn->rn_flags & RNF_ROOT) || RNTORT(rn)->rt_ifa != ifa); - RADIX_NODE_HEAD_RUNLOCK(rnh); + RIB_RUNLOCK(rh); if (error) { /* this is only an error if bad on ALL tables */ continue; @@ -1814,8 +1852,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int * RTM_DELETE message, and retry adding * interface prefix. */ - rnh = rt_tables_get_rnh(fibnum, dst->sa_family); - RADIX_NODE_HEAD_LOCK(rnh); + rh = rt_tables_get_rnh(fibnum, dst->sa_family); + RIB_WLOCK(rh); /* Delete old prefix */ info.rti_ifa = NULL; @@ -1829,7 +1867,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int error = rtrequest1_fib(cmd, &info, &rt, fibnum); } - RADIX_NODE_HEAD_UNLOCK(rnh); + RIB_WUNLOCK(rh); } Modified: projects/routing/sys/net/route.h ============================================================================== --- projects/routing/sys/net/route.h Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/net/route.h Sun Nov 9 00:36:39 2014 (r274301) @@ -107,6 +107,7 @@ VNET_DECLARE(u_int, rt_add_addr_allfibs) #endif #endif +struct rib_head; struct rtentry; #if !defined(_KERNEL) || defined(_WANT_RTENTRY) /* This structure is kept for compatibility reasons only */ @@ -292,7 +293,7 @@ struct rt_addrinfo { #define RT_LINK_IS_UP(ifp) (!((ifp)->if_capabilities & IFCAP_LINKSTATE) \ || (ifp)->if_link_state == LINK_STATE_UP) -struct radix_node_head *rt_tables_get_rnh(int, int); +struct rib_head *rt_tables_get_rnh(int, int); struct ifmultiaddr; @@ -324,12 +325,12 @@ int rtsock_routemsg(int, struct ifnet *i * RTFREE() uses an unlocked entry. */ -int rt_expunge(struct radix_node_head *, struct rtentry *); +int rt_expunge(struct rib_head *, struct rtentry *); void rtfree(struct rtentry *); int rt_check(struct rtentry **, struct rtentry **, struct sockaddr *); typedef int rt_walktree_f_t(struct rtentry *, void *); -typedef void rt_setwarg_t(struct radix_node_head *, uint32_t, int, void *); +typedef void rt_setwarg_t(struct rib_head *, uint32_t, int, void *); void rt_foreach_fib(int af, rt_setwarg_t *, rt_walktree_f_t *, void *); void rt_flushifroutes(struct ifnet *ifp); Modified: projects/routing/sys/net/route_internal.h ============================================================================== --- projects/routing/sys/net/route_internal.h Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/net/route_internal.h Sun Nov 9 00:36:39 2014 (r274301) @@ -30,6 +30,31 @@ #ifndef _NET_ROUTE_INTERNAL_H_ #define _NET_ROUTE_INTERNAL_H_ +struct rib_head { + struct radix_head head; + 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 rwlock rib_lock; /* locks entire radix tree */ + struct radix_mask_head rmhead; /* masks radix head */ +}; + +#define RIB_RLOCK(rh) rw_rlock(&(rh)->rib_lock) +#define RIB_RUNLOCK(rh) rw_runlock(&(rh)->rib_lock) +#define RIB_WLOCK(rh) rw_wlock(&(rh)->rib_lock) +#define RIB_WUNLOCK(rh) rw_wunlock(&(rh)->rib_lock) +#define RIB_LOCK_ASSERT(rh) rw_assert(&(rh)->rib_lock, RA_LOCKED) +#define RIB_WLOCK_ASSERT(rh) rw_assert(&(rh)->rib_lock, RA_WLOCKED) + +struct rib_head *rt_table_init(int offset); +void rt_table_destroy(struct rib_head *rh); + + struct rtentry { struct radix_node rt_nodes[2]; /* tree glue, and other values */ /* Modified: projects/routing/sys/net/rt_nhops.c ============================================================================== --- projects/routing/sys/net/rt_nhops.c Sat Nov 8 19:38:34 2014 (r274300) +++ projects/routing/sys/net/rt_nhops.c Sun Nov 9 00:36:39 2014 (r274301) @@ -194,8 +194,8 @@ fib_choose_prepend(uint32_t fibnum, stru idx = nh_multi->nh_nhops[flowid % nh_multi->nh_count]; #if 0 KASSERT((fibnum < rt_numfibs), ("fib4_lookup_prependĀ§: bad fibnum")); - rnh = rt_tables_get_rnh(fibnum, AF_INET); - //nh_src = &rnh->nhops[i]; + rh = rt_tables_get_rnh(fibnum, AF_INET); + //nh_src = &rh->nhops[i]; #endif } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***