Author: melifaro
Date: Mon Nov 30 05:51:14 2015
New Revision: 291466
URL: https://svnweb.freebsd.org/changeset/base/291466

Log:
  Add new rt_foreach_fib_walk_del() function for deleting route entries
    by filter function instead of picking into routing table details in
    each consumer.
  Remove now-unused rt_expunge() (eliminating last external RTF_RNH_LOCKED
   user).
  This simplifies future nexthops/mulitipath changes and rtrequest1_fib()
    locking refactoring.
  
  Actual changes:
  Add "rt_chain" field to permit rte grouping while doing batched delete
    from routing table (thus growing rte 200->208 on amd64).
  Add "rti_filter" /  "rti_filterdata" / "rti_spare" fields to rt_addrinfo
    to pass filter function to various routing subsystems in standard way.
  Convert all rt_expunge() customers to new rt_addinfo-based api and eliminate
    rt_expunge().

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

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c        Mon Nov 30 04:59:01 2015        (r291465)
+++ head/sys/net/route.c        Mon Nov 30 05:51:14 2015        (r291466)
@@ -139,7 +139,14 @@ 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);
+static int rt_ifdelroute(const struct rtentry *rt, void *arg);
+static struct rtentry *rt_unlinkrte(struct radix_node_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,
+    struct rt_addrinfo *info, struct rtentry *rto, int *perror);
+#endif
 
 struct if_mtuinfo
 {
@@ -237,6 +244,7 @@ rtentry_ctor(void *mem, int size, void *
 
        bzero(rt, offsetof(struct rtentry, rt_endzero));
        counter_u64_zero(rt->rt_pksent);
+       rt->rt_chain = NULL;
 
        return (0);
 }
@@ -867,6 +875,108 @@ rt_foreach_fib_walk(int af, rt_setwarg_t
        }
 }
 
+struct rt_delinfo
+{
+       struct rt_addrinfo info;
+       struct radix_node_head *rnh;
+       struct rtentry *head;
+};
+
+/*
+ * Conditionally unlinks @rn from radix tree based
+ * on info data passed in @arg.
+ */
+static int
+rt_checkdelroute(struct radix_node *rn, void *arg)
+{
+       struct rt_delinfo *di;
+       struct rt_addrinfo *info;
+       struct rtentry *rt;
+       int error;
+
+       di = (struct rt_delinfo *)arg;
+       rt = (struct rtentry *)rn;
+       info = &di->info;
+       error = 0;
+
+       info->rti_info[RTAX_DST] = rt_key(rt);
+       info->rti_info[RTAX_NETMASK] = rt_mask(rt);
+       info->rti_info[RTAX_GATEWAY] = rt->rt_gateway;
+
+       rt = rt_unlinkrte(di->rnh, info, &error);
+       if (rt == NULL) {
+               /* Either not allowed or not matched. Skip entry */
+               return (0);
+       }
+
+       /* Entry was unlinked. Add to the list and return */
+       rt->rt_chain = di->head;
+       di->head = rt;
+
+       return (0);
+}
+
+/*
+ * Iterates over all existing fibs in system.
+ * Deletes each element for which @filter_f function returned
+ * non-zero value.
+ * If @af is not AF_UNSPEC, iterates over fibs in particular
+ * address family.
+ */
+void
+rt_foreach_fib_walk_del(int af, rt_filter_f_t *filter_f, void *arg)
+{
+       struct radix_node_head *rnh;
+       struct rt_delinfo di;
+       struct rtentry *rt;
+       uint32_t fibnum;
+       int i, start, end;
+
+       bzero(&di, sizeof(di));
+       di.info.rti_filter = filter_f;
+       di.info.rti_filterdata = arg;
+
+       for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+               /* Do we want some specific family? */
+               if (af != AF_UNSPEC) {
+                       start = af;
+                       end = af;
+               } else {
+                       start = 1;
+                       end = AF_MAX;
+               }
+
+               for (i = start; i <= end; i++) {
+                       rnh = rt_tables_get_rnh(fibnum, i);
+                       if (rnh == NULL)
+                               continue;
+                       di.rnh = rnh;
+
+                       RADIX_NODE_HEAD_LOCK(rnh);
+                       rnh->rnh_walktree(rnh, rt_checkdelroute, &di);
+                       RADIX_NODE_HEAD_UNLOCK(rnh);
+
+                       if (di.head == NULL)
+                               continue;
+
+                       /* We might have something to reclaim */
+                       while (di.head != NULL) {
+                               rt = di.head;
+                               di.head = rt->rt_chain;
+                               rt->rt_chain = NULL;
+
+                               /* TODO std rt -> rt_addrinfo export */
+                               di.info.rti_info[RTAX_DST] = rt_key(rt);
+                               di.info.rti_info[RTAX_NETMASK] = rt_mask(rt);
+
+                               rt_notifydelete(rt, &di.info);
+                               RTFREE_LOCKED(rt);
+                       }
+
+               }
+       }
+}
+
 /*
  * Delete Routes for a Network Interface
  *
@@ -882,10 +992,9 @@ rt_foreach_fib_walk(int af, rt_setwarg_t
  *     errno   failed - reason indicated
  */
 static int
-rt_ifdelroute(struct rtentry *rt, void *arg)
+rt_ifdelroute(const struct rtentry *rt, void *arg)
 {
        struct ifnet    *ifp = arg;
-       int             err;
 
        if (rt->rt_ifp != ifp)
                return (0);
@@ -897,14 +1006,7 @@ rt_ifdelroute(struct rtentry *rt, void *
        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);
+       return (1);
 }
 
 /*
@@ -917,9 +1019,105 @@ void
 rt_flushifroutes(struct ifnet *ifp)
 {
 
-       rt_foreach_fib_walk(AF_UNSPEC, NULL, rt_ifdelroute, ifp);
+       rt_foreach_fib_walk_del(AF_UNSPEC, rt_ifdelroute, ifp);
+}
+
+/*
+ * Conditionally unlinks rtentry matching data inside @info from @rnh.
+ * Returns unlinked, locked and referenced @rtentry on success,
+ * Returns NULL and sets @perror to:
+ * ESRCH - if prefix was not found,
+ * EADDRINUSE - if trying to delete PINNED route without appropriate flag.
+ * 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)
+{
+       struct sockaddr *dst, *netmask;
+       struct rtentry *rt;
+       struct radix_node *rn;
+
+       dst = info->rti_info[RTAX_DST];
+       netmask = info->rti_info[RTAX_NETMASK];
+
+       rt = (struct rtentry *)rnh->rnh_lookup(dst, netmask, rnh);
+       if (rt == NULL) {
+               *perror = ESRCH;
+               return (NULL);
+       }
+
+       if ((info->rti_flags & RTF_PINNED) == 0) {
+               /* Check if target route can be deleted */
+               if (rt->rt_flags & RTF_PINNED) {
+                       *perror = EADDRINUSE;
+                       return (NULL);
+               }
+       }
+
+       if (info->rti_filter != NULL) {
+               if (info->rti_filter(rt, info->rti_filterdata) == 0) {
+                       /* Not matched */
+                       *perror = ENOENT;
+                       return (NULL);
+               }
+
+               /*
+                * Filter function requested rte deletion.
+                * Ease the caller work by filling in remaining info
+                * from that particular entry.
+                */
+               info->rti_info[RTAX_GATEWAY] = rt->rt_gateway;
+       }
+
+       /*
+        * Remove the item from the tree and return it.
+        * Complain if it is not there and do no more processing.
+        */
+       *perror = ESRCH;
+#ifdef RADIX_MPATH
+       if (rn_mpath_capable(rnh))
+               rn = rt_mpath_unlink(rnh, info, rt, perror);
+       else
+#endif
+       rn = rnh->rnh_deladdr(dst, netmask, rnh);
+       if (rn == NULL)
+               return (NULL);
+
+       if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
+               panic ("rtrequest delete");
+
+       rt = RNTORT(rn);
+       RT_LOCK(rt);
+       RT_ADDREF(rt);
+
+       *perror = 0;
+
+       return (rt);
+}
+
+static void
+rt_notifydelete(struct rtentry *rt, struct rt_addrinfo *info)
+{
+       struct ifaddr *ifa;
+
+       rt->rt_flags &= ~RTF_UP;
+
+       /*
+        * give the protocol a chance to keep things in sync.
+        */
+       ifa = rt->rt_ifa;
+       if (ifa != NULL && ifa->ifa_rtrequest != NULL)
+               ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+
+       /*
+        * One more rtentry floating around that is not
+        * linked to the routing table. rttrash will be decremented
+        * when RTFREE(rt) is eventually called.
+        */
+       V_rttrash++;
 }
 
+
 /*
  * These (questionable) definitions of apparent local variables apply
  * to the next two functions.  XXXXXX!!!
@@ -975,87 +1173,6 @@ rt_getifa_fib(struct rt_addrinfo *info, 
        return (error);
 }
 
-/*
- * Expunges references to a route that's about to be reclaimed.
- * The route must be locked.
- */
-int
-rt_expunge(struct radix_node_head *rnh, struct rtentry *rt)
-{
-#if !defined(RADIX_MPATH)
-       struct radix_node *rn;
-#else
-       struct rt_addrinfo info;
-       int fib;
-       struct rtentry *rt0;
-#endif
-       struct ifaddr *ifa;
-       int error = 0;
-
-       RT_LOCK_ASSERT(rt);
-       RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
-
-#ifdef RADIX_MPATH
-       fib = rt->rt_fibnum;
-       bzero(&info, sizeof(info));
-       info.rti_ifp = rt->rt_ifp;
-       info.rti_flags = RTF_RNH_LOCKED;
-       info.rti_info[RTAX_DST] = rt_key(rt);
-       info.rti_info[RTAX_GATEWAY] = rt->rt_ifa->ifa_addr;
-
-       RT_UNLOCK(rt);
-       error = rtrequest1_fib(RTM_DELETE, &info, &rt0, fib);
-
-       if (error == 0 && rt0 != NULL) {
-               rt = rt0;
-               RT_LOCK(rt);
-       } else if (error != 0) {
-               RT_LOCK(rt);
-               return (error);
-       }
-#else
-       /*
-        * 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);
-       if (rn == NULL) {
-               error = ESRCH;
-               goto bad;
-       }
-       KASSERT((rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) == 0,
-               ("unexpected flags 0x%x", rn->rn_flags));
-       KASSERT(rt == RNTORT(rn),
-               ("lookup mismatch, rt %p rn %p", rt, rn));
-#endif /* RADIX_MPATH */
-
-       rt->rt_flags &= ~RTF_UP;
-
-       /*
-        * Give the protocol a chance to keep things in sync.
-        */
-       if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) {
-               struct rt_addrinfo info;
-
-               bzero((caddr_t)&info, sizeof(info));
-               info.rti_flags = rt->rt_flags;
-               info.rti_info[RTAX_DST] = rt_key(rt);
-               info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
-               info.rti_info[RTAX_NETMASK] = rt_mask(rt);
-               ifa->ifa_rtrequest(RTM_DELETE, rt, &info);
-       }
-
-       /*
-        * one more rtentry floating around that is not
-        * linked to the routing table.
-        */
-       V_rttrash++;
-#if !defined(RADIX_MPATH)
-bad:
-#endif
-       return (error);
-}
-
 static int
 if_updatemtu_cb(struct radix_node *rn, void *arg)
 {
@@ -1172,26 +1289,32 @@ rt_print(char *buf, int buflen, struct r
 #endif
 
 #ifdef RADIX_MPATH
-static int
-rn_mpath_update(int req, struct rt_addrinfo *info,
-    struct radix_node_head *rnh, struct rtentry **ret_nrt)
+/*
+ * Deletes key for single-path routes, unlinks rtentry with
+ * gateway specified in @info from multi-path routes.
+ *
+ * Returnes unlinked entry. In case of failure, returns NULL
+ * and sets @perror to ESRCH.
+ */
+static struct radix_node *
+rt_mpath_unlink(struct radix_node_head *rnh, struct rt_addrinfo *info,
+    struct rtentry *rto, int *perror)
 {
        /*
         * if we got multipath routes, we require users to specify
         * a matching RTAX_GATEWAY.
         */
-       struct rtentry *rt, *rto = NULL;
+       struct rtentry *rt; // *rto = NULL;
        struct radix_node *rn;
-       int error = 0;
+       struct sockaddr *gw;
 
-       rn = rnh->rnh_lookup(dst, netmask, rnh);
-       if (rn == NULL)
-               return (ESRCH);
-       rto = rt = RNTORT(rn);
+       gw = info->rti_info[RTAX_GATEWAY];
+       rt = rt_mpath_matchgate(rto, gw);
+       if (rt == NULL) {
+               *perror = ESRCH;
+               return (NULL);
+       }
 
-       rt = rt_mpath_matchgate(rt, gateway);
-       if (rt == NULL)
-               return (ESRCH);
        /*
         * this is the first entry in the chain
         */
@@ -1214,67 +1337,31 @@ rn_mpath_update(int req, struct rt_addri
                         * check the case when there is only
                         * one route in the chain.  
                         */
-                       if (gateway &&
-                           (rt->rt_gateway->sa_len != gateway->sa_len ||
-                               memcmp(rt->rt_gateway, gateway, 
gateway->sa_len)))
-                               error = ESRCH;
-                       else {
-                               /*
-                                * remove from tree before returning it
-                                * to the caller
-                                */
-                               rn = rnh->rnh_deladdr(dst, netmask, rnh);
-                               KASSERT(rt == RNTORT(rn), ("radix node 
disappeared"));
-                               goto gwdelete;
+                       if (gw &&
+                           (rt->rt_gateway->sa_len != gw->sa_len ||
+                               memcmp(rt->rt_gateway, gw, gw->sa_len))) {
+                               *perror = ESRCH;
+                               return (NULL);
                        }
-                       
                }
+
                /*
                 * use the normal delete code to remove
                 * the first entry
                 */
-               if (req != RTM_DELETE) 
-                       goto nondelete;
-
-               error = ENOENT;
-               goto done;
+               rn = rnh->rnh_deladdr(dst, netmask, rnh);
+               *perror = 0;
+               return (rn);
        }
                
        /*
         * if the entry is 2nd and on up
         */
-       if ((req == RTM_DELETE) && !rt_mpath_deldup(rto, rt))
+       if (rt_mpath_deldup(rto, rt) == 0)
                panic ("rtrequest1: rt_mpath_deldup");
-gwdelete:
-       RT_LOCK(rt);
-       RT_ADDREF(rt);
-       if (req == RTM_DELETE) {
-               rt->rt_flags &= ~RTF_UP;
-               /*
-                * One more rtentry floating around that is not
-                * linked to the routing table. rttrash will be decremented
-                * when RTFREE(rt) is eventually called.
-                */
-               V_rttrash++;
-       }
-       
-nondelete:
-       if (req != RTM_DELETE)
-               panic("unrecognized request %d", req);
-       
-
-       /*
-        * If the caller wants it, then it can have it,
-        * but it's up to it to free the rtentry as we won't be
-        * doing it.
-        */
-       if (ret_nrt) {
-               *ret_nrt = rt;
-               RT_UNLOCK(rt);
-       } else
-               RTFREE_LOCKED(rt);
-done:
-       return (error);
+       *perror = 0;
+       rn = (struct radix_node *)rt;
+       return (rn);
 }
 #endif
 
@@ -1330,52 +1417,12 @@ rtrequest1_fib(int req, struct rt_addrin
                        rt_maskedcopy(dst, (struct sockaddr *)&mdst, netmask);
                        dst = (struct sockaddr *)&mdst;
                }
-#ifdef RADIX_MPATH
-               if (rn_mpath_capable(rnh)) {
-                       error = rn_mpath_update(req, info, rnh, ret_nrt);
-                       /*
-                        * "bad" holds true for the success case
-                        * as well
-                        */
-                       if (error != ENOENT)
-                               goto bad;
-                       error = 0;
-               }
-#endif
-               if ((flags & RTF_PINNED) == 0) {
-                       /* Check if target route can be deleted */
-                       rt = (struct rtentry *)rnh->rnh_lookup(dst,
-                           netmask, rnh);
-                       if ((rt != NULL) && (rt->rt_flags & RTF_PINNED))
-                               senderr(EADDRINUSE);
-               }
 
-               /*
-                * 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);
-               if (rn == NULL)
-                       senderr(ESRCH);
-               if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
-                       panic ("rtrequest delete");
-               rt = RNTORT(rn);
-               RT_LOCK(rt);
-               RT_ADDREF(rt);
-               rt->rt_flags &= ~RTF_UP;
-
-               /*
-                * give the protocol a chance to keep things in sync.
-                */
-               if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
-                       ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+               rt = rt_unlinkrte(rnh, info, &error);
+               if (error != 0)
+                       goto bad;
 
-               /*
-                * One more rtentry floating around that is not
-                * linked to the routing table. rttrash will be decremented
-                * when RTFREE(rt) is eventually called.
-                */
-               V_rttrash++;
+               rt_notifydelete(rt, info);
 
                /*
                 * If the caller wants it, then it can have it,

Modified: head/sys/net/route.h
==============================================================================
--- head/sys/net/route.h        Mon Nov 30 04:59:01 2015        (r291465)
+++ head/sys/net/route.h        Mon Nov 30 05:51:14 2015        (r291466)
@@ -128,6 +128,7 @@ struct rtentry {
 #define        rt_endzero      rt_pksent
        counter_u64_t   rt_pksent;      /* packets sent using this route */
        struct mtx      rt_mtx;         /* mutex for routing entry */
+       struct rtentry  *rt_chain;      /* pointer to next rtentry to delete */
 };
 #endif /* _KERNEL || _WANT_RTENTRY */
 
@@ -259,14 +260,19 @@ struct rt_msghdr {
 #define RTAX_BRD       7       /* for NEWADDR, broadcast or p-p dest addr */
 #define RTAX_MAX       8       /* size of array to allocate */
 
+typedef int rt_filter_f_t(const struct rtentry *, void *);
+
 struct rt_addrinfo {
-       int     rti_addrs;
-       struct  sockaddr *rti_info[RTAX_MAX];
-       int     rti_flags;
-       struct  ifaddr *rti_ifa;
-       struct  ifnet *rti_ifp;
-       u_long  rti_mflags;
-       struct  rt_metrics *rti_rmx;
+       int     rti_addrs;                      /* Route RTF_ flags */
+       int     rti_flags;                      /* Route RTF_ flags */
+       struct  sockaddr *rti_info[RTAX_MAX];   /* Sockaddr data */
+       struct  ifaddr *rti_ifa;                /* value of rt_ifa addr */
+       struct  ifnet *rti_ifp;                 /* route interface */
+       rt_filter_f_t   *rti_filter;            /* filter function */
+       void    *rti_filterdata;                /* filter paramenters */
+       u_long  rti_mflags;                     /* metrics RTV_ flags */
+       u_long  rti_spare;                      /* Will be used for fib */
+       struct  rt_metrics *rti_rmx;            /* Pointer to route metrics */
 };
 
 /*
@@ -383,6 +389,7 @@ 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_walk(int af, rt_setwarg_t *, rt_walktree_f_t *, void *);
+void   rt_foreach_fib_walk_del(int af, rt_filter_f_t *filter_f, void *arg);
 void   rt_flushifroutes(struct ifnet *ifp);
 
 /* XXX MRT COMPAT VERSIONS THAT SET UNIVERSE to 0 */

Modified: head/sys/netinet/in_rmx.c
==============================================================================
--- head/sys/netinet/in_rmx.c   Mon Nov 30 04:59:01 2015        (r291465)
+++ head/sys/netinet/in_rmx.c   Mon Nov 30 05:51:14 2015        (r291466)
@@ -150,56 +150,22 @@ in_detachhead(void **head, int off)
  * plug back in.
  */
 struct in_ifadown_arg {
-       struct radix_node_head *rnh;
        struct ifaddr *ifa;
        int del;
 };
 
 static int
-in_ifadownkill(struct rtentry *rt, void *xap)
+in_ifadownkill(const struct rtentry *rt, void *xap)
 {
        struct in_ifadown_arg *ap = xap;
 
-       RT_LOCK(rt);
-       if (rt->rt_ifa == ap->ifa &&
-           (ap->del || !(rt->rt_flags & RTF_STATIC))) {
-               /*
-                * Aquire a reference so that it can later be freed
-                * as the refcount would be 0 here in case of at least
-                * ap->del.
-                */
-               RT_ADDREF(rt);
-               /*
-                * Disconnect it from the tree and permit protocols
-                * to cleanup.
-                */
-               rt_expunge(ap->rnh, rt);
-               /*
-                * At this point it is an rttrash node, and in case
-                * the above is the only reference we must free it.
-                * If we do not noone will have a pointer and the
-                * rtentry will be leaked forever.
-                * In case someone else holds a reference, we are
-                * fine as we only decrement the refcount. In that
-                * case if the other entity calls RT_REMREF, we
-                * will still be leaking but at least we tried.
-                */
-               RTFREE_LOCKED(rt);
+       if (rt->rt_ifa != ap->ifa)
                return (0);
-       }
-       RT_UNLOCK(rt);
-       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;
+       if ((rt->rt_flags & RTF_STATIC) != 0 && ap->del == 0)
+               return (0);
 
-       arg->rnh = rnh;
+       return (1);
 }
 
 void
@@ -213,7 +179,7 @@ in_ifadown(struct ifaddr *ifa, int delet
        arg.ifa = ifa;
        arg.del = delete;
 
-       rt_foreach_fib_walk(AF_INET, in_setifarnh, in_ifadownkill, &arg);
+       rt_foreach_fib_walk_del(AF_INET, in_ifadownkill, &arg);
        ifa->ifa_flags &= ~IFA_ROUTE;           /* XXXlocking? */
 }
 

Modified: head/sys/netinet6/nd6.c
==============================================================================
--- head/sys/netinet6/nd6.c     Mon Nov 30 04:59:01 2015        (r291465)
+++ head/sys/netinet6/nd6.c     Mon Nov 30 05:51:14 2015        (r291466)
@@ -1307,6 +1307,15 @@ nd6_free(struct llentry *ln, int gc)
        llentry_free(ln);
 }
 
+static int
+nd6_isdynrte(const struct rtentry *rt, void *xap)
+{
+
+       if (rt->rt_flags == (RTF_UP | RTF_HOST | RTF_DYNAMIC))
+               return (1);
+
+       return (0);
+}
 /*
  * Remove the rtentry for the given llentry,
  * both of which were installed by a redirect.
@@ -1315,26 +1324,16 @@ static void
 nd6_free_redirect(const struct llentry *ln)
 {
        int fibnum;
-       struct rtentry *rt;
-       struct radix_node_head *rnh;
        struct sockaddr_in6 sin6;
+       struct rt_addrinfo info;
 
        lltable_fill_sa_entry(ln, (struct sockaddr *)&sin6);
-       for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
-               rnh = rt_tables_get_rnh(fibnum, AF_INET6);
-               if (rnh == NULL)
-                       continue;
+       memset(&info, 0, sizeof(info));
+       info.rti_info[RTAX_DST] = (struct sockaddr *)&sin6;
+       info.rti_filter = nd6_isdynrte;
 
-               RADIX_NODE_HEAD_LOCK(rnh);
-               rt = in6_rtalloc1((struct sockaddr *)&sin6, 0,
-                   RTF_RNH_LOCKED, fibnum);
-               if (rt) {
-                       if (rt->rt_flags == (RTF_UP | RTF_HOST | RTF_DYNAMIC))
-                               rt_expunge(rnh, rt);
-                       RTFREE_LOCKED(rt);
-               }
-               RADIX_NODE_HEAD_UNLOCK(rnh);
-       }
+       for (fibnum = 0; fibnum < rt_numfibs; fibnum++)
+               rtrequest1_fib(RTM_DELETE, &info, NULL, fibnum);
 }
 
 /*

Modified: head/sys/netinet6/nd6_rtr.c
==============================================================================
--- head/sys/netinet6/nd6_rtr.c Mon Nov 30 04:59:01 2015        (r291465)
+++ head/sys/netinet6/nd6_rtr.c Mon Nov 30 05:51:14 2015        (r291466)
@@ -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 rtentry *, void *);
+static int rt6_deleteroute(const struct rtentry *, void *);
 
 VNET_DECLARE(int, nd6_recalc_reachtm_interval);
 #define        V_nd6_recalc_reachtm_interval   
VNET(nd6_recalc_reachtm_interval)
@@ -2073,11 +2073,11 @@ rt6_flush(struct in6_addr *gateway, stru
                return;
 
        /* XXX Do we really need to walk any but the default FIB? */
-       rt_foreach_fib_walk(AF_INET6, NULL, rt6_deleteroute, (void *)gateway);
+       rt_foreach_fib_walk_del(AF_INET6, rt6_deleteroute, (void *)gateway);
 }
 
 static int
-rt6_deleteroute(struct rtentry *rt, void *arg)
+rt6_deleteroute(const struct rtentry *rt, void *arg)
 {
 #define SIN6(s)        ((struct sockaddr_in6 *)s)
        struct in6_addr *gate = (struct in6_addr *)arg;
@@ -2104,8 +2104,7 @@ rt6_deleteroute(struct rtentry *rt, void
        if ((rt->rt_flags & RTF_HOST) == 0)
                return (0);
 
-       return (in6_rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
-           rt_mask(rt), rt->rt_flags | RTF_RNH_LOCKED, NULL, rt->rt_fibnum));
+       return (1);
 #undef SIN6
 }
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to