From owner-svn-src-head@freebsd.org Wed Nov 13 12:05:50 2019 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 238D81AFCC7; Wed, 13 Nov 2019 12:05:50 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47CjxV0vWdz3xbJ; Wed, 13 Nov 2019 12:05:50 +0000 (UTC) (envelope-from bz@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 mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D73C6FDF7; Wed, 13 Nov 2019 12:05:49 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xADC5ncH023916; Wed, 13 Nov 2019 12:05:49 GMT (envelope-from bz@FreeBSD.org) Received: (from bz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xADC5nUv023913; Wed, 13 Nov 2019 12:05:49 GMT (envelope-from bz@FreeBSD.org) Message-Id: <201911131205.xADC5nUv023913@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bz set sender to bz@FreeBSD.org using -f From: "Bjoern A. Zeeb" Date: Wed, 13 Nov 2019 12:05:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r354680 - head/sys/netinet6 X-SVN-Group: head X-SVN-Commit-Author: bz X-SVN-Commit-Paths: head/sys/netinet6 X-SVN-Commit-Revision: 354680 X-SVN-Commit-Repository: base 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.29 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: Wed, 13 Nov 2019 12:05:50 -0000 Author: bz Date: Wed Nov 13 12:05:48 2019 New Revision: 354680 URL: https://svnweb.freebsd.org/changeset/base/354680 Log: nd6 defrouter: consolidate nd_defrouter manipulations in nd6_rtr.c Move the nd_defrouter along with the sysctl handler from nd6.c to nd6_rtr.c and make the variable file static. Provide (temporary) new accessor functions for code manipulating nd_defrouter from nd6.c, and stop exporting functions no longer needed outside nd6_rtr.c. This also shuffles a few functions around in nd6_rtr.c without functional changes. Given all nd_defrouter logic is now in one place we can tidy up the code, locking and, and other open items. MFC after: 3 weeks X-MFC: keep exporting the functions Sponsored by: Netflix Modified: head/sys/netinet6/nd6.c head/sys/netinet6/nd6.h head/sys/netinet6/nd6_rtr.c Modified: head/sys/netinet6/nd6.c ============================================================================== --- head/sys/netinet6/nd6.c Wed Nov 13 11:21:02 2019 (r354679) +++ head/sys/netinet6/nd6.c Wed Nov 13 12:05:48 2019 (r354680) @@ -116,7 +116,6 @@ VNET_DEFINE(int, nd6_debug) = 0; static eventhandler_tag lle_event_eh, iflladdr_event_eh, ifnet_link_event_eh; -VNET_DEFINE(struct nd_drhead, nd_defrouter); VNET_DEFINE(struct nd_prhead, nd_prefix); VNET_DEFINE(struct rwlock, nd6_lock); VNET_DEFINE(uint64_t, nd6_list_genid); @@ -218,7 +217,7 @@ nd6_init(void) rw_init(&V_nd6_lock, "nd6 list"); LIST_INIT(&V_nd_prefix); - TAILQ_INIT(&V_nd_defrouter); + nd6_defrouter_init(); /* Start timers. */ callout_init(&V_nd6_slowtimo_ch, 0); @@ -901,28 +900,16 @@ nd6_timer(void *arg) { CURVNET_SET((struct vnet *) arg); struct epoch_tracker et; - struct nd_drhead drq; struct nd_prhead prl; - struct nd_defrouter *dr, *ndr; struct nd_prefix *pr, *npr; struct ifnet *ifp; struct in6_ifaddr *ia6, *nia6; uint64_t genid; - TAILQ_INIT(&drq); LIST_INIT(&prl); - ND6_WLOCK(); - TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) - if (dr->expire && dr->expire < time_uptime) - defrouter_unlink(dr, &drq); - ND6_WUNLOCK(); - NET_EPOCH_ENTER(et); - while ((dr = TAILQ_FIRST(&drq)) != NULL) { - TAILQ_REMOVE(&drq, dr, dr_entry); - defrouter_del(dr); - } + nd6_defrouter_timer(); /* * expire interface addresses. @@ -1146,34 +1133,15 @@ regen_tmpaddr(struct in6_ifaddr *ia6) void nd6_purge(struct ifnet *ifp) { - struct nd_drhead drq; struct nd_prhead prl; - struct nd_defrouter *dr, *ndr; struct nd_prefix *pr, *npr; - TAILQ_INIT(&drq); LIST_INIT(&prl); - /* - * Nuke default router list entries toward ifp. - * We defer removal of default router list entries that is installed - * in the routing table, in order to keep additional side effects as - * small as possible. - */ - ND6_WLOCK(); - TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { - if (dr->installed) - continue; - if (dr->ifp == ifp) - defrouter_unlink(dr, &drq); - } - TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { - if (!dr->installed) - continue; - if (dr->ifp == ifp) - defrouter_unlink(dr, &drq); - } + /* Purge default router list entries toward ifp. */ + nd6_defrouter_purge(ifp); + ND6_WLOCK(); /* * Remove prefixes on ifp. We should have already removed addresses on * this interface, so no addresses should be referencing these prefixes. @@ -1184,11 +1152,7 @@ nd6_purge(struct ifnet *ifp) } ND6_WUNLOCK(); - /* Delete the unlinked router and prefix objects. */ - while ((dr = TAILQ_FIRST(&drq)) != NULL) { - TAILQ_REMOVE(&drq, dr, dr_entry); - defrouter_del(dr); - } + /* Delete the unlinked prefix objects. */ while ((pr = LIST_FIRST(&prl)) != NULL) { LIST_REMOVE(pr, ndpr_entry); nd6_prefix_del(pr); @@ -1376,7 +1340,7 @@ restart: * as on-link, and thus, as a neighbor. */ if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && - TAILQ_EMPTY(&V_nd_defrouter) && + nd6_defrouter_list_empty() && V_nd6_defifindex == ifp->if_index) { return (1); } @@ -1819,22 +1783,9 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) case SIOCSRTRFLUSH_IN6: { /* flush all the default routers */ - struct nd_drhead drq; - struct nd_defrouter *dr; - TAILQ_INIT(&drq); - defrouter_reset(); - - ND6_WLOCK(); - while ((dr = TAILQ_FIRST(&V_nd_defrouter)) != NULL) - defrouter_unlink(dr, &drq); - ND6_WUNLOCK(); - while ((dr = TAILQ_FIRST(&drq)) != NULL) { - TAILQ_REMOVE(&drq, dr, dr_entry); - defrouter_del(dr); - } - + nd6_defrouter_flush_all(); defrouter_select(); break; } @@ -2626,14 +2577,9 @@ clear_llinfo_pqueue(struct llentry *ln) ln->la_hold = NULL; } -static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS); static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS); SYSCTL_DECL(_net_inet6_icmp6); -SYSCTL_PROC(_net_inet6_icmp6, ICMPV6CTL_ND6_DRLIST, nd6_drlist, - CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, - NULL, 0, nd6_sysctl_drlist, "S,in6_defrouter", - "NDP default router list"); SYSCTL_PROC(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist, CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, nd6_sysctl_prlist, "S,in6_prefix", @@ -2642,42 +2588,6 @@ SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, ""); SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_gctimer, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24), ""); - -static int -nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS) -{ - struct in6_defrouter d; - struct nd_defrouter *dr; - int error; - - if (req->newptr != NULL) - return (EPERM); - - error = sysctl_wire_old_buffer(req, 0); - if (error != 0) - return (error); - - bzero(&d, sizeof(d)); - d.rtaddr.sin6_family = AF_INET6; - d.rtaddr.sin6_len = sizeof(d.rtaddr); - - ND6_RLOCK(); - TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) { - d.rtaddr.sin6_addr = dr->rtaddr; - error = sa6_recoverscope(&d.rtaddr); - if (error != 0) - break; - d.flags = dr->raflags; - d.rtlifetime = dr->rtlifetime; - d.expire = dr->expire + (time_second - time_uptime); - d.if_index = dr->ifp->if_index; - error = SYSCTL_OUT(req, &d, sizeof(d)); - if (error != 0) - break; - } - ND6_RUNLOCK(); - return (error); -} static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS) Modified: head/sys/netinet6/nd6.h ============================================================================== --- head/sys/netinet6/nd6.h Wed Nov 13 11:21:02 2019 (r354679) +++ head/sys/netinet6/nd6.h Wed Nov 13 12:05:48 2019 (r354680) @@ -335,7 +335,6 @@ VNET_DECLARE(int, nd6_mmaxtries); VNET_DECLARE(int, nd6_useloopback); VNET_DECLARE(int, nd6_maxnudhint); VNET_DECLARE(int, nd6_gctimer); -VNET_DECLARE(struct nd_drhead, nd_defrouter); VNET_DECLARE(struct nd_prhead, nd_prefix); VNET_DECLARE(int, nd6_debug); VNET_DECLARE(int, nd6_onlink_ns_rfc4861); @@ -346,7 +345,6 @@ VNET_DECLARE(int, nd6_onlink_ns_rfc4861); #define V_nd6_useloopback VNET(nd6_useloopback) #define V_nd6_maxnudhint VNET(nd6_maxnudhint) #define V_nd6_gctimer VNET(nd6_gctimer) -#define V_nd_defrouter VNET(nd_defrouter) #define V_nd_prefix VNET(nd_prefix) #define V_nd6_debug VNET(nd6_debug) #define V_nd6_onlink_ns_rfc4861 VNET(nd6_onlink_ns_rfc4861) @@ -477,14 +475,18 @@ void nd6_dad_stop(struct ifaddr *); void nd6_rs_input(struct mbuf *, int, int); void nd6_ra_input(struct mbuf *, int, int); void nd6_ifnet_link_event(void *, struct ifnet *, int); +struct nd_defrouter *defrouter_lookup(struct in6_addr *, struct ifnet *); +struct nd_defrouter *defrouter_lookup_locked(struct in6_addr *, struct ifnet *); void defrouter_reset(void); void defrouter_select_fib(int fibnum); void defrouter_select(void); -void defrouter_ref(struct nd_defrouter *); void defrouter_rele(struct nd_defrouter *); bool defrouter_remove(struct in6_addr *, struct ifnet *); -void defrouter_unlink(struct nd_defrouter *, struct nd_drhead *); -void defrouter_del(struct nd_defrouter *); +bool nd6_defrouter_list_empty(void); +void nd6_defrouter_flush_all(void); +void nd6_defrouter_purge(struct ifnet *); +void nd6_defrouter_timer(void); +void nd6_defrouter_init(void); int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *, struct nd_prefix **); void nd6_prefix_unlink(struct nd_prefix *, struct nd_prhead *); @@ -494,8 +496,6 @@ void nd6_prefix_rele(struct nd_prefix *); int nd6_prefix_onlink(struct nd_prefix *); int nd6_prefix_offlink(struct nd_prefix *); void pfxlist_onlink_check(void); -struct nd_defrouter *defrouter_lookup(struct in6_addr *, struct ifnet *); -struct nd_defrouter *defrouter_lookup_locked(struct in6_addr *, struct ifnet *); struct nd_prefix *nd6_prefix_lookup(struct nd_prefixctl *); void rt6_flush(struct in6_addr *, struct ifnet *); int nd6_setdefaultiface(int); Modified: head/sys/netinet6/nd6_rtr.c ============================================================================== --- head/sys/netinet6/nd6_rtr.c Wed Nov 13 11:21:02 2019 (r354679) +++ head/sys/netinet6/nd6_rtr.c Wed Nov 13 12:05:48 2019 (r354680) @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -91,6 +92,9 @@ static void in6_init_address_ltimes(struct nd_prefix * static int rt6_deleteroute(const struct rtentry *, void *); +VNET_DEFINE_STATIC(struct nd_drhead, nd_defrouter); +#define V_nd_defrouter VNET(nd_defrouter) + VNET_DECLARE(int, nd6_recalc_reachtm_interval); #define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval) @@ -117,7 +121,38 @@ VNET_DEFINE(int, nd6_ignore_ipv6_only_ra) = 1; #define RTPREF_RESERVED (-2) #define RTPREF_INVALID (-3) /* internal */ +static void +defrouter_ref(struct nd_defrouter *dr) +{ + + refcount_acquire(&dr->refcnt); +} + +void +defrouter_rele(struct nd_defrouter *dr) +{ + + if (refcount_release(&dr->refcnt)) + free(dr, M_IP6NDP); +} + /* + * Remove a router from the global list and optionally stash it in a + * caller-supplied queue. + */ +static void +defrouter_unlink(struct nd_defrouter *dr, struct nd_drhead *drq) +{ + + ND6_WLOCK_ASSERT(); + + TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry); + V_nd6_list_genid++; + if (drq != NULL) + TAILQ_INSERT_TAIL(drq, dr, dr_entry); +} + +/* * Receive Router Solicitation Message - just for routers. * Router solicitation/advertisement is mostly managed by userland program * (rtadvd) so here we have no function like nd6_ra_output(). @@ -670,21 +705,6 @@ defrouter_lookup(struct in6_addr *addr, struct ifnet * return (dr); } -void -defrouter_ref(struct nd_defrouter *dr) -{ - - refcount_acquire(&dr->refcnt); -} - -void -defrouter_rele(struct nd_defrouter *dr) -{ - - if (refcount_release(&dr->refcnt)) - free(dr, M_IP6NDP); -} - /* * Remove the default route for a given router. * This is just a subroutine function for defrouter_select_fib(), and @@ -759,47 +779,7 @@ defrouter_reset(void) */ } -/* - * Look up a matching default router list entry and remove it. Returns true if a - * matching entry was found, false otherwise. - */ -bool -defrouter_remove(struct in6_addr *addr, struct ifnet *ifp) -{ - struct nd_defrouter *dr; - - ND6_WLOCK(); - dr = defrouter_lookup_locked(addr, ifp); - if (dr == NULL) { - ND6_WUNLOCK(); - return (false); - } - - defrouter_unlink(dr, NULL); - ND6_WUNLOCK(); - defrouter_del(dr); - defrouter_rele(dr); - return (true); -} - -/* - * Remove a router from the global list and optionally stash it in a - * caller-supplied queue. - * - * The ND lock must be held. - */ -void -defrouter_unlink(struct nd_defrouter *dr, struct nd_drhead *drq) -{ - - ND6_WLOCK_ASSERT(); - TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry); - V_nd6_list_genid++; - if (drq != NULL) - TAILQ_INSERT_TAIL(drq, dr, dr_entry); -} - -void +static void defrouter_del(struct nd_defrouter *dr) { struct nd_defrouter *deldr = NULL; @@ -850,7 +830,31 @@ defrouter_del(struct nd_defrouter *dr) defrouter_rele(dr); } + /* + * Look up a matching default router list entry and remove it. Returns true if a + * matching entry was found, false otherwise. + */ +bool +defrouter_remove(struct in6_addr *addr, struct ifnet *ifp) +{ + struct nd_defrouter *dr; + + ND6_WLOCK(); + dr = defrouter_lookup_locked(addr, ifp); + if (dr == NULL) { + ND6_WUNLOCK(); + return (false); + } + + defrouter_unlink(dr, NULL); + ND6_WUNLOCK(); + defrouter_del(dr); + defrouter_rele(dr); + return (true); +} + +/* * Default Router Selection according to Section 6.3.6 of RFC 2461 and * draft-ietf-ipngwg-router-selection: * 1) Routers that are reachable or probably reachable should be preferred. @@ -2531,4 +2535,133 @@ nd6_setdefaultiface(int ifindex) } return (error); +} + +static int +nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS) +{ + struct in6_defrouter d; + struct nd_defrouter *dr; + int error; + + if (req->newptr != NULL) + return (EPERM); + + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + + bzero(&d, sizeof(d)); + d.rtaddr.sin6_family = AF_INET6; + d.rtaddr.sin6_len = sizeof(d.rtaddr); + + ND6_RLOCK(); + TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) { + d.rtaddr.sin6_addr = dr->rtaddr; + error = sa6_recoverscope(&d.rtaddr); + if (error != 0) + break; + d.flags = dr->raflags; + d.rtlifetime = dr->rtlifetime; + d.expire = dr->expire + (time_second - time_uptime); + d.if_index = dr->ifp->if_index; + error = SYSCTL_OUT(req, &d, sizeof(d)); + if (error != 0) + break; + } + ND6_RUNLOCK(); + return (error); +} +SYSCTL_DECL(_net_inet6_icmp6); +SYSCTL_PROC(_net_inet6_icmp6, ICMPV6CTL_ND6_DRLIST, nd6_drlist, + CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, + NULL, 0, nd6_sysctl_drlist, "S,in6_defrouter", + "NDP default router list"); + +bool +nd6_defrouter_list_empty(void) +{ + + return (TAILQ_EMPTY(&V_nd_defrouter)); +} + +void +nd6_defrouter_timer(void) +{ + struct nd_defrouter *dr, *ndr; + struct nd_drhead drq; + + TAILQ_INIT(&drq); + + ND6_WLOCK(); + TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) + if (dr->expire && dr->expire < time_uptime) + defrouter_unlink(dr, &drq); + ND6_WUNLOCK(); + + while ((dr = TAILQ_FIRST(&drq)) != NULL) { + TAILQ_REMOVE(&drq, dr, dr_entry); + defrouter_del(dr); + } +} + +/* + * Nuke default router list entries toward ifp. + * We defer removal of default router list entries that is installed in the + * routing table, in order to keep additional side effects as small as possible. + */ +void +nd6_defrouter_purge(struct ifnet *ifp) +{ + struct nd_defrouter *dr, *ndr; + struct nd_drhead drq; + + TAILQ_INIT(&drq); + + ND6_WLOCK(); + TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { + if (dr->installed) + continue; + if (dr->ifp == ifp) + defrouter_unlink(dr, &drq); + } + TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { + if (!dr->installed) + continue; + if (dr->ifp == ifp) + defrouter_unlink(dr, &drq); + } + ND6_WUNLOCK(); + + /* Delete the unlinked router objects. */ + while ((dr = TAILQ_FIRST(&drq)) != NULL) { + TAILQ_REMOVE(&drq, dr, dr_entry); + defrouter_del(dr); + } +} + +void +nd6_defrouter_flush_all(void) +{ + struct nd_defrouter *dr; + struct nd_drhead drq; + + TAILQ_INIT(&drq); + + ND6_WLOCK(); + while ((dr = TAILQ_FIRST(&V_nd_defrouter)) != NULL) + defrouter_unlink(dr, &drq); + ND6_WUNLOCK(); + + while ((dr = TAILQ_FIRST(&drq)) != NULL) { + TAILQ_REMOVE(&drq, dr, dr_entry); + defrouter_del(dr); + } +} + +void +nd6_defrouter_init(void) +{ + + TAILQ_INIT(&V_nd_defrouter); }