Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Don't use rt_walktree to delete routes



details:   https://anonhg.NetBSD.org/src/rev/3d478e2ba2c8
branches:  trunk
changeset: 348905:3d478e2ba2c8
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Tue Nov 15 01:50:06 2016 +0000

description:
Don't use rt_walktree to delete routes

Some functions use rt_walktree to scan the routing table and delete
matched routes. However, we shouldn't use rt_walktree to delete
routes because rt_walktree is recursive to the routing table (radix
tree) and isn't friendly to MP-ification. rt_walktree allows a caller
to pass a callback function to delete an matched entry. The callback
function is called from an API of the radix tree (rn_walktree) but
also calls an API of the radix tree to delete an entry.

This change adds a new API of the radix tree, rn_search_matched,
which returns a matched entry that is selected by a callback
function passed by a caller and the caller itself deletes the
entry. By using the API, we can avoid the recursive form.

diffstat:

 sys/net/if.c           |  38 +++++++++++---------------------------
 sys/net/radix.c        |  35 +++++++++++++++++++++++++++++++++--
 sys/net/radix.h        |   6 +++++-
 sys/net/route.c        |  43 +++++++++++++++++++++++++++++++++++++++++--
 sys/net/route.h        |   7 ++++++-
 sys/net/rtbl.c         |  21 +++++++++++++++++++--
 sys/netinet6/nd6_rtr.c |  13 ++++++-------
 sys/nfs/nfs_boot.c     |  18 ++++++------------
 8 files changed, 127 insertions(+), 54 deletions(-)

diffs (truncated from 402 to 300 lines):

diff -r b3e7960962bf -r 3d478e2ba2c8 sys/net/if.c
--- a/sys/net/if.c      Tue Nov 15 00:37:18 2016 +0000
+++ b/sys/net/if.c      Tue Nov 15 01:50:06 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.361 2016/11/05 23:30:22 pgoyette Exp $        */
+/*     $NetBSD: if.c,v 1.362 2016/11/15 01:50:06 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.361 2016/11/05 23:30:22 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.362 2016/11/15 01:50:06 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -185,7 +185,7 @@
 
 struct psref_class             *ifa_psref_class __read_mostly;
 
-static int     if_rt_walktree(struct rtentry *, void *);
+static int     if_delroute_matcher(struct rtentry *, void *);
 
 static struct if_clone *if_clone_lookup(const char *, int *);
 
@@ -1279,11 +1279,9 @@
 
        if_free_sadl(ifp);
 
-       /* Walk the routing table looking for stragglers. */
-       for (i = 0; i <= AF_MAX; i++) {
-               while (rt_walktree(i, if_rt_walktree, ifp) == ERESTART)
-                       continue;
-       }
+       /* Delete stray routes from the routing table. */
+       for (i = 0; i <= AF_MAX; i++)
+               rt_delete_matched_entries(i, if_delroute_matcher, ifp);
 
        DOMAIN_FOREACH(dp) {
                if (dp->dom_ifdetach != NULL && ifp->if_afdata[dp->dom_family])
@@ -1403,28 +1401,14 @@
  * ifnet.
  */
 static int
-if_rt_walktree(struct rtentry *rt, void *v)
+if_delroute_matcher(struct rtentry *rt, void *v)
 {
        struct ifnet *ifp = (struct ifnet *)v;
-       int error;
-       struct rtentry *retrt;
-
-       if (rt->rt_ifp != ifp)
+
+       if (rt->rt_ifp == ifp)
+               return 1;
+       else
                return 0;
-
-       /* Delete the entry. */
-       error = rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
-           rt_mask(rt), rt->rt_flags, &retrt);
-       if (error == 0) {
-               KASSERT(retrt == rt);
-               KASSERT((retrt->rt_flags & RTF_UP) == 0);
-               retrt->rt_ifp = NULL;
-               rtfree(retrt);
-       } else {
-               printf("%s: warning: unable to delete rtentry @ %p, "
-                   "error = %d\n", ifp->if_xname, rt, error);
-       }
-       return ERESTART;
 }
 
 /*
diff -r b3e7960962bf -r 3d478e2ba2c8 sys/net/radix.c
--- a/sys/net/radix.c   Tue Nov 15 00:37:18 2016 +0000
+++ b/sys/net/radix.c   Tue Nov 15 01:50:06 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: radix.c,v 1.45 2015/08/24 22:21:26 pooka Exp $ */
+/*     $NetBSD: radix.c,v 1.46 2016/11/15 01:50:06 ozaki-r Exp $       */
 
 /*
  * Copyright (c) 1988, 1989, 1993
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: radix.c,v 1.45 2015/08/24 22:21:26 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: radix.c,v 1.46 2016/11/15 01:50:06 ozaki-r Exp $");
 
 #ifndef _NET_RADIX_H_
 #include <sys/param.h>
@@ -1005,6 +1005,37 @@
        /* NOTREACHED */
 }
 
+struct radix_node *
+rn_search_matched(struct radix_node_head *h,
+    int (*matcher)(struct radix_node *, void *), void *w)
+{
+       bool matched;
+       struct radix_node *base, *next, *rn;
+       /*
+        * This gets complicated because we may delete the node
+        * while applying the function f to it, so we need to calculate
+        * the successor node in advance.
+        */
+       rn = rn_walkfirst(h->rnh_treetop, NULL, NULL);
+       for (;;) {
+               base = rn;
+               next = rn_walknext(rn, NULL, NULL);
+               /* Process leaves */
+               while ((rn = base) != NULL) {
+                       base = rn->rn_dupedkey;
+                       if (!(rn->rn_flags & RNF_ROOT)) {
+                               matched = (*matcher)(rn, w);
+                               if (matched)
+                                       return rn;
+                       }
+               }
+               rn = next;
+               if (rn->rn_flags & RNF_ROOT)
+                       return NULL;
+       }
+       /* NOTREACHED */
+}
+
 struct delayinit {
        void **head;
        int off;
diff -r b3e7960962bf -r 3d478e2ba2c8 sys/net/radix.h
--- a/sys/net/radix.h   Tue Nov 15 00:37:18 2016 +0000
+++ b/sys/net/radix.h   Tue Nov 15 01:50:06 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: radix.h,v 1.22 2009/05/27 17:46:50 pooka Exp $ */
+/*     $NetBSD: radix.h,v 1.23 2016/11/15 01:50:06 ozaki-r Exp $       */
 
 /*
  * Copyright (c) 1988, 1989, 1993
@@ -139,6 +139,10 @@
 int    rn_walktree(struct radix_node_head *,
                    int (*)(struct radix_node *, void *),
                    void *);
+struct radix_node *
+       rn_search_matched(struct radix_node_head *,
+                         int (*)(struct radix_node *, void *),
+                         void *);
 struct radix_node
         *rn_addmask(const void *, int, int),
         *rn_addroute(const void *, const void *, struct radix_node_head *,
diff -r b3e7960962bf -r 3d478e2ba2c8 sys/net/route.c
--- a/sys/net/route.c   Tue Nov 15 00:37:18 2016 +0000
+++ b/sys/net/route.c   Tue Nov 15 01:50:06 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: route.c,v 1.181 2016/10/25 02:45:09 ozaki-r Exp $      */
+/*     $NetBSD: route.c,v 1.182 2016/11/15 01:50:06 ozaki-r Exp $      */
 
 /*-
  * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.181 2016/10/25 02:45:09 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.182 2016/11/15 01:50:06 ozaki-r Exp $");
 
 #include <sys/param.h>
 #ifdef RTFLUSH_DEBUG
@@ -116,6 +116,7 @@
 #include <sys/pool.h>
 #include <sys/kauth.h>
 #include <sys/workqueue.h>
+#include <sys/syslog.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -1634,6 +1635,44 @@
        return 0;
 }
 
+void
+rt_delete_matched_entries(sa_family_t family, int (*f)(struct rtentry *, void *),
+    void *v)
+{
+
+       for (;;) {
+               int s;
+               int error;
+               struct rtentry *rt, *retrt = NULL;
+
+               s = splsoftnet();
+               rt = rtbl_search_matched_entry(family, f, v);
+               if (rt == NULL) {
+                       splx(s);
+                       return;
+               }
+               rt->rt_refcnt++;
+               splx(s);
+
+               error = rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
+                   rt_mask(rt), rt->rt_flags, &retrt);
+               if (error == 0) {
+                       KASSERT(retrt == rt);
+                       KASSERT((retrt->rt_flags & RTF_UP) == 0);
+                       retrt->rt_ifp = NULL;
+                       rtfree(rt);
+                       rtfree(retrt);
+               } else if (error == ESRCH) {
+                       /* Someone deleted the entry already. */
+                       rtfree(rt);
+               } else {
+                       log(LOG_ERR, "%s: unable to delete rtentry @ %p, "
+                           "error = %d\n", rt->rt_ifp->if_xname, rt, error);
+                       /* XXX how to treat this case? */
+               }
+       }
+}
+
 #ifdef DDB
 
 #include <machine/db_machdep.h>
diff -r b3e7960962bf -r 3d478e2ba2c8 sys/net/route.h
--- a/sys/net/route.h   Tue Nov 15 00:37:18 2016 +0000
+++ b/sys/net/route.h   Tue Nov 15 01:50:06 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: route.h,v 1.106 2016/10/25 02:45:09 ozaki-r Exp $      */
+/*     $NetBSD: route.h,v 1.107 2016/11/15 01:50:06 ozaki-r Exp $      */
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -408,6 +408,8 @@
        rt_gettag(const struct rtentry *);
 
 int    rt_check_reject_route(const struct rtentry *, const struct ifnet *);
+void   rt_delete_matched_entries(sa_family_t,
+           int (*)(struct rtentry *, void *), void *);
 
 static inline void
 rt_assert_referenced(const struct rtentry *rt)
@@ -504,6 +506,9 @@
        rt_matchaddr(rtbl_t *, const struct sockaddr *);
 int    rt_refines(const struct sockaddr *, const struct sockaddr *);
 int    rt_walktree(sa_family_t, int (*)(struct rtentry *, void *), void *);
+struct rtentry *
+       rtbl_search_matched_entry(sa_family_t,
+           int (*)(struct rtentry *, void *), void *);
 void   rtbl_init(void);
 
 #endif /* _KERNEL */
diff -r b3e7960962bf -r 3d478e2ba2c8 sys/net/rtbl.c
--- a/sys/net/rtbl.c    Tue Nov 15 00:37:18 2016 +0000
+++ b/sys/net/rtbl.c    Tue Nov 15 01:50:06 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtbl.c,v 1.3 2016/04/11 09:21:18 ozaki-r Exp $ */
+/*     $NetBSD: rtbl.c,v 1.4 2016/11/15 01:50:06 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 1998, 2008, 2011 The NetBSD Foundation, Inc.
@@ -95,7 +95,7 @@
 #endif /* _KERNEL && _KERNEL_OPT */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtbl.c,v 1.3 2016/04/11 09:21:18 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtbl.c,v 1.4 2016/11/15 01:50:06 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -204,6 +204,23 @@
        return rn_walktree(&t->t_rnh, rt_walktree_visitor, &rw);
 }
 
+struct rtentry *
+rtbl_search_matched_entry(sa_family_t family,
+    int (*f)(struct rtentry *, void *), void *v)
+{
+       rtbl_t *t = rt_tables[family];
+       struct rtwalk rw;
+
+       if (t == NULL)
+               return 0;
+
+       rw.rw_f = f;
+       rw.rw_v = v;
+
+       return (struct rtentry *)
+           rn_search_matched(&t->t_rnh, rt_walktree_visitor, &rw);
+}
+
 rtbl_t *
 rt_gettable(sa_family_t af)
 {
diff -r b3e7960962bf -r 3d478e2ba2c8 sys/netinet6/nd6_rtr.c
--- a/sys/netinet6/nd6_rtr.c    Tue Nov 15 00:37:18 2016 +0000
+++ b/sys/netinet6/nd6_rtr.c    Tue Nov 15 01:50:06 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nd6_rtr.c,v 1.119 2016/08/16 10:31:57 roy Exp $        */
+/*     $NetBSD: nd6_rtr.c,v 1.120 2016/11/15 01:50:06 ozaki-r Exp $    */
 /*     $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $        */



Home | Main Index | Thread Index | Old Index