Author: melifaro
Date: Sat Aug  8 18:14:59 2015
New Revision: 286458
URL: https://svnweb.freebsd.org/changeset/base/286458

Log:
  MFP r274295:
  
  * Move interface route cleanup to route.c:rt_flushifroutes()
  * Convert most of "for (fibnum = 0; fibnum < rt_numfibs; fibnum++)" users
    to use new rt_foreach_fib() instead of hand-rolling cycles.

Modified:
  head/sys/net/if.c
  head/sys/net/route.c
  head/sys/net/route.h
  head/sys/netinet/in_rmx.c
  head/sys/netinet6/in6_rmx.c
  head/sys/netinet6/nd6_rtr.c

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c   Sat Aug  8 17:48:54 2015        (r286457)
+++ head/sys/net/if.c   Sat Aug  8 18:14:59 2015        (r286458)
@@ -166,7 +166,6 @@ static int  if_setflag(struct ifnet *, in
 static int     if_transmit(struct ifnet *ifp, struct mbuf *m);
 static void    if_unroute(struct ifnet *, int flag, int fam);
 static void    link_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
-static int     if_rtdel(struct radix_node *, void *);
 static int     ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *);
 static int     if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int);
 static void    do_link_state_change(void *, int);
@@ -885,8 +884,7 @@ static void
 if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
 {
        struct ifaddr *ifa;
-       struct radix_node_head  *rnh;
-       int i, j;
+       int i;
        struct domain *dp;
        struct ifnet *iter;
        int found = 0;
@@ -974,23 +972,7 @@ if_detach_internal(struct ifnet *ifp, in
                }
        }
 
-       /*
-        * Delete all remaining routes using this interface
-        * Unfortuneatly the only way to do this is to slog through
-        * the entire routing table looking for routes which point
-        * to this interface...oh well...
-        */
-       for (i = 1; i <= AF_MAX; i++) {
-               for (j = 0; j < rt_numfibs; j++) {
-                       rnh = rt_tables_get_rnh(j, i);
-                       if (rnh == NULL)
-                               continue;
-                       RADIX_NODE_HEAD_LOCK(rnh);
-                       (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
-                       RADIX_NODE_HEAD_UNLOCK(rnh);
-               }
-       }
-
+       rt_flushifroutes(ifp);
        if_delgroups(ifp);
 
        /*
@@ -1411,49 +1393,6 @@ if_getgroupmembers(struct ifgroupreq *da
 }
 
 /*
- * Delete Routes for a Network Interface
- *
- * Called for each routing entry via the rnh->rnh_walktree() call above
- * to delete all route entries referencing a detaching network interface.
- *
- * Arguments:
- *     rn      pointer to node in the routing table
- *     arg     argument passed to rnh->rnh_walktree() - detaching interface
- *
- * Returns:
- *     0       successful
- *     errno   failed - reason indicated
- *
- */
-static int
-if_rtdel(struct radix_node *rn, void *arg)
-{
-       struct rtentry  *rt = (struct rtentry *)rn;
-       struct ifnet    *ifp = arg;
-       int             err;
-
-       if (rt->rt_ifp == ifp) {
-
-               /*
-                * Protect (sorta) against walktree recursion problems
-                * with cloned routes
-                */
-               if ((rt->rt_flags & RTF_UP) == 0)
-                       return (0);
-
-               err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
-                               rt_mask(rt),
-                               rt->rt_flags|RTF_RNH_LOCKED|RTF_PINNED,
-                               (struct rtentry **) NULL, rt->rt_fibnum);
-               if (err) {
-                       log(LOG_WARNING, "if_rtdel: error %d\n", err);
-               }
-       }
-
-       return (0);
-}
-
-/*
  * Return counter values from counter(9)s stored in ifnet.
  */
 uint64_t

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c        Sat Aug  8 17:48:54 2015        (r286457)
+++ head/sys/net/route.c        Sat Aug  8 18:14:59 2015        (r286458)
@@ -139,6 +139,7 @@ static VNET_DEFINE(uma_zone_t, rtzone);     
 static int rtrequest1_fib_change(struct radix_node_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);
 
 struct if_mtuinfo
 {
@@ -811,6 +812,96 @@ rtrequest_fib(int req,
        return rtrequest1_fib(req, &info, ret_nrt, fibnum);
 }
 
+
+void
+rt_foreach_fib(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f, void *arg)
+{
+       struct radix_node_head *rnh;
+       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)
+                               continue;
+                       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);
+                       continue;
+               }
+
+               for (i = 1; i <= AF_MAX; i++) {
+                       rnh = rt_tables_get_rnh(fibnum, i);
+                       if (rnh == NULL)
+                               continue;
+                       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);
+               }
+       }
+}
+
+/*
+ * Delete Routes for a Network Interface
+ *
+ * Called for each routing entry via the rnh->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
+ *
+ * Returns:
+ *     0       successful
+ *     errno   failed - reason indicated
+ */
+static int
+rt_ifdelroute(struct rtentry *rt, void *arg)
+{
+       struct ifnet    *ifp = arg;
+       int             err;
+
+       if (rt->rt_ifp != ifp)
+               return (0);
+
+       /*
+        * Protect (sorta) against walktree recursion problems
+        * with cloned routes
+        */
+       if ((rt->rt_flags & RTF_UP) == 0)
+               return (0);
+
+       err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
+                       rt_mask(rt),
+                       rt->rt_flags | RTF_RNH_LOCKED | RTF_PINNED,
+                       (struct rtentry **) NULL, rt->rt_fibnum);
+       if (err != 0)
+               log(LOG_WARNING, "rt_ifdelroute: error %d\n", err);
+
+       return (0);
+}
+
+/*
+ * Delete all remaining routes using this interface
+ * Unfortuneatly the only way to do this is to slog through
+ * the entire routing table looking for routes which point
+ * to this interface...oh well...
+ */
+void
+rt_flushifroutes(struct ifnet *ifp)
+{
+
+       rt_foreach_fib(AF_UNSPEC, NULL, rt_ifdelroute, ifp);
+}
+
 /*
  * These (questionable) definitions of apparent local variables apply
  * to the next two functions.  XXXXXX!!!

Modified: head/sys/net/route.h
==============================================================================
--- head/sys/net/route.h        Sat Aug  8 17:48:54 2015        (r286457)
+++ head/sys/net/route.h        Sat Aug  8 18:14:59 2015        (r286458)
@@ -380,6 +380,11 @@ void        rtfree(struct rtentry *);
 int     rt_check(struct rtentry **, struct rtentry **, struct sockaddr *);
 void   rt_updatemtu(struct ifnet *);
 
+typedef int rt_walktree_f_t(struct rtentry *, void *);
+typedef void rt_setwarg_t(struct radix_node_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);
+
 /* XXX MRT COMPAT VERSIONS THAT SET UNIVERSE to 0 */
 /* Thes are used by old code not yet converted to use multiple FIBS */
 int     rt_getifa(struct rt_addrinfo *);

Modified: head/sys/netinet/in_rmx.c
==============================================================================
--- head/sys/netinet/in_rmx.c   Sat Aug  8 17:48:54 2015        (r286457)
+++ head/sys/netinet/in_rmx.c   Sat Aug  8 18:14:59 2015        (r286458)
@@ -53,6 +53,11 @@ extern int   in_inithead(void **head, int 
 extern int     in_detachhead(void **head, int off);
 #endif
 
+static void in_setifarnh(struct radix_node_head *rnh, uint32_t fibnum,
+    int af, void *_arg);
+static void in_rtqtimo_setrnh(struct radix_node_head *rnh, uint32_t fibnum,
+    int af, void *_arg);
+
 /*
  * Do what we need to do when inserting a route.
  */
@@ -153,10 +158,9 @@ struct in_ifadown_arg {
 };
 
 static int
-in_ifadownkill(struct radix_node *rn, void *xap)
+in_ifadownkill(struct rtentry *rt, void *xap)
 {
        struct in_ifadown_arg *ap = xap;
-       struct rtentry *rt = (struct rtentry *)rn;
 
        RT_LOCK(rt);
        if (rt->rt_ifa == ap->ifa &&
@@ -189,26 +193,30 @@ in_ifadownkill(struct radix_node *rn, vo
        return 0;
 }
 
+static void
+in_setifarnh(struct radix_node_head *rnh, uint32_t fibnum, int af,
+    void *_arg)
+{
+       struct in_ifadown_arg *arg;
+
+       arg = (struct in_ifadown_arg *)_arg;
+
+       arg->rnh = rnh;
+}
+
 void
 in_ifadown(struct ifaddr *ifa, int delete)
 {
        struct in_ifadown_arg arg;
-       struct radix_node_head *rnh;
-       int     fibnum;
 
        KASSERT(ifa->ifa_addr->sa_family == AF_INET,
            ("%s: wrong family", __func__));
 
-       for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) {
-               rnh = rt_tables_get_rnh(fibnum, AF_INET);
-               arg.rnh = rnh;
-               arg.ifa = ifa;
-               arg.del = delete;
-               RADIX_NODE_HEAD_LOCK(rnh);
-               rnh->rnh_walktree(rnh, in_ifadownkill, &arg);
-               RADIX_NODE_HEAD_UNLOCK(rnh);
-               ifa->ifa_flags &= ~IFA_ROUTE;           /* XXXlocking? */
-       }
+       arg.ifa = ifa;
+       arg.del = delete;
+
+       rt_foreach_fib(AF_INET, in_setifarnh, in_ifadownkill, &arg);
+       ifa->ifa_flags &= ~IFA_ROUTE;           /* XXXlocking? */
 }
 
 /*

Modified: head/sys/netinet6/in6_rmx.c
==============================================================================
--- head/sys/netinet6/in6_rmx.c Sat Aug  8 17:48:54 2015        (r286457)
+++ head/sys/netinet6/in6_rmx.c Sat Aug  8 18:14:59 2015        (r286458)
@@ -189,15 +189,10 @@ static VNET_DEFINE(struct callout, rtq_m
 #define        V_rtq_mtutimer                  VNET(rtq_mtutimer)
 
 static int
-in6_mtuexpire(struct radix_node *rn, void *rock)
+in6_mtuexpire(struct rtentry *rt, void *rock)
 {
-       struct rtentry *rt = (struct rtentry *)rn;
        struct mtuex_arg *ap = rock;
 
-       /* sanity */
-       if (!rt)
-               panic("rt == NULL in in6_mtuexpire");
-
        if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) {
                if (rt->rt_expire <= time_uptime) {
                        rt->rt_flags |= RTF_PROBEMTU;
@@ -206,36 +201,29 @@ in6_mtuexpire(struct radix_node *rn, voi
                }
        }
 
-       return 0;
+       return (0);
 }
 
 #define        MTUTIMO_DEFAULT (60*1)
 
 static void
-in6_mtutimo_one(struct radix_node_head *rnh)
+in6_mtutimo_setwa(struct radix_node_head *rnh, uint32_t fibum, int af, void 
*_arg)
 {
-       struct mtuex_arg arg;
+       struct mtuex_arg *arg;
+
+       arg = (struct mtuex_arg *)_arg;
 
-       arg.rnh = rnh;
-       arg.nextstop = time_uptime + MTUTIMO_DEFAULT;
-       RADIX_NODE_HEAD_LOCK(rnh);
-       rnh->rnh_walktree(rnh, in6_mtuexpire, &arg);
-       RADIX_NODE_HEAD_UNLOCK(rnh);
+       arg->rnh = rnh;
 }
 
 static void
 in6_mtutimo(void *rock)
 {
        CURVNET_SET_QUIET((struct vnet *) rock);
-       struct radix_node_head *rnh;
        struct timeval atv;
-       u_int fibnum;
+       struct mtuex_arg arg;
 
-       for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
-               rnh = rt_tables_get_rnh(fibnum, AF_INET6);
-               if (rnh != NULL)
-                       in6_mtutimo_one(rnh);
-       }
+       rt_foreach_fib(AF_INET6, in6_mtutimo_setwa, in6_mtuexpire, &arg);
 
        atv.tv_sec = MTUTIMO_DEFAULT;
        atv.tv_usec = 0;

Modified: head/sys/netinet6/nd6_rtr.c
==============================================================================
--- head/sys/netinet6/nd6_rtr.c Sat Aug  8 17:48:54 2015        (r286457)
+++ head/sys/netinet6/nd6_rtr.c Sat Aug  8 18:14:59 2015        (r286458)
@@ -88,7 +88,7 @@ static void in6_init_address_ltimes(stru
 static int nd6_prefix_onlink(struct nd_prefix *);
 static int nd6_prefix_offlink(struct nd_prefix *);
 
-static int rt6_deleteroute(struct radix_node *, void *);
+static int rt6_deleteroute(struct rtentry *, void *);
 
 VNET_DECLARE(int, nd6_recalc_reachtm_interval);
 #define        V_nd6_recalc_reachtm_interval   
VNET(nd6_recalc_reachtm_interval)
@@ -2067,30 +2067,19 @@ in6_init_address_ltimes(struct nd_prefix
 void
 rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
 {
-       struct radix_node_head *rnh;
-       u_int fibnum;
 
        /* We'll care only link-local addresses */
        if (!IN6_IS_ADDR_LINKLOCAL(gateway))
                return;
 
        /* XXX Do we really need to walk any but the default FIB? */
-       for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
-               rnh = rt_tables_get_rnh(fibnum, AF_INET6);
-               if (rnh == NULL)
-                       continue;
-
-               RADIX_NODE_HEAD_LOCK(rnh);
-               rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
-               RADIX_NODE_HEAD_UNLOCK(rnh);
-       }
+       rt_foreach_fib(AF_INET6, NULL, rt6_deleteroute, (void *)gateway);
 }
 
 static int
-rt6_deleteroute(struct radix_node *rn, void *arg)
+rt6_deleteroute(struct rtentry *rt, void *arg)
 {
 #define SIN6(s)        ((struct sockaddr_in6 *)s)
-       struct rtentry *rt = (struct rtentry *)rn;
        struct in6_addr *gate = (struct in6_addr *)arg;
 
        if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to