Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Remove routes on an address removal if the routes refere...
details: https://anonhg.NetBSD.org/src/rev/d1244fd3b1ed
branches: trunk
changeset: 370160:d1244fd3b1ed
user: knakahara <knakahara%NetBSD.org@localhost>
date: Tue Sep 20 02:23:37 2022 +0000
description:
Remove routes on an address removal if the routes referencing to the address. Implemented by ozaki-r@n.o.
A route that has a gateway is on a connected route can be invalid if the
connected route is deleted, i.e., an associated address is removed.
Traditionally NetBSD doesn't sweep such a route on the address removal. Sending
packets over the route fails with "No route to host". Also the route holds an
orphan ifaddr as rt_ifa that is destructed say by in_purgeaddr.
If the same address is assgined again in such a state, there can be two
different ifaddr objects with the same address. Until recently it's not a
big problem because we can send packets anyway. However after MP-ification
of the network stack, we can't send packets because we strictly check if rt_ifa
(i.e., the (old) ifaddr) is valid.
This change automatically removes such routes on a removal of an associated
address to avoid keeping inconsistent routes.
diffstat:
sys/net/if.c | 6 ++--
sys/net/route.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++--
sys/net/route.h | 6 +++-
sys/netinet/in.c | 32 +++++++++++++++++++++++++++-
sys/netinet6/in6.c | 32 +++++++++++++++++++++++++++-
sys/nfs/nfs_boot.c | 6 ++--
6 files changed, 125 insertions(+), 15 deletions(-)
diffs (truncated from 314 to 300 lines):
diff -r 0f4ed5a7514c -r d1244fd3b1ed sys/net/if.c
--- a/sys/net/if.c Mon Sep 19 22:30:19 2022 +0000
+++ b/sys/net/if.c Tue Sep 20 02:23:37 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.525 2022/09/03 02:53:18 thorpej Exp $ */
+/* $NetBSD: if.c,v 1.526 2022/09/20 02:23:37 knakahara 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.525 2022/09/03 02:53:18 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.526 2022/09/20 02:23:37 knakahara Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -1479,7 +1479,7 @@
/* Delete stray routes from the routing table. */
for (i = 0; i <= AF_MAX; i++)
- rt_delete_matched_entries(i, if_delroute_matcher, ifp);
+ rt_delete_matched_entries(i, if_delroute_matcher, ifp, false);
DOMAIN_FOREACH(dp) {
if (dp->dom_ifdetach != NULL && ifp->if_afdata[dp->dom_family])
diff -r 0f4ed5a7514c -r d1244fd3b1ed sys/net/route.c
--- a/sys/net/route.c Mon Sep 19 22:30:19 2022 +0000
+++ b/sys/net/route.c Tue Sep 20 02:23:37 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: route.c,v 1.233 2022/08/29 23:48:18 knakahara Exp $ */
+/* $NetBSD: route.c,v 1.234 2022/09/20 02:23:37 knakahara 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.233 2022/08/29 23:48:18 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.234 2022/09/20 02:23:37 knakahara Exp $");
#include <sys/param.h>
#ifdef RTFLUSH_DEBUG
@@ -2291,7 +2291,7 @@
void
rt_delete_matched_entries(sa_family_t family, int (*f)(struct rtentry *, void *),
- void *v)
+ void *v, bool notify)
{
for (;;) {
@@ -2308,6 +2308,7 @@
return;
}
rt_ref(rt);
+ RT_REFCNT_TRACE(rt);
splx(s);
RT_UNLOCK();
@@ -2316,12 +2317,16 @@
if (error == 0) {
KASSERT(retrt == rt);
KASSERT((retrt->rt_flags & RTF_UP) == 0);
+ if (notify)
+ rt_newmsg(RTM_DELETE, retrt);
retrt->rt_ifp = NULL;
rt_unref(rt);
+ RT_REFCNT_TRACE(rt);
rt_free(retrt);
} else if (error == ESRCH) {
/* Someone deleted the entry already. */
rt_unref(rt);
+ RT_REFCNT_TRACE(rt);
} else {
log(LOG_ERR, "%s: unable to delete rtentry @ %p, "
"error = %d\n", rt->rt_ifp->if_xname, rt, error);
@@ -2338,6 +2343,53 @@
return rtbl_walktree(family, f, v);
}
+void
+rt_replace_ifa_matched_entries(sa_family_t family,
+ int (*f)(struct rtentry *, void *), void *v, struct ifaddr *ifa)
+{
+
+ for (;;) {
+ int s;
+#ifdef NET_MPSAFE
+ int error;
+#endif
+ struct rtentry *rt;
+
+ RT_RLOCK();
+ s = splsoftnet();
+ rt = rtbl_search_matched_entry(family, f, v);
+ if (rt == NULL) {
+ splx(s);
+ RT_UNLOCK();
+ return;
+ }
+ rt_ref(rt);
+ RT_REFCNT_TRACE(rt);
+ splx(s);
+ RT_UNLOCK();
+
+#ifdef NET_MPSAFE
+ error = rt_update_prepare(rt);
+ if (error == 0) {
+ rt_replace_ifa(rt, ifa);
+ rt_update_finish(rt);
+ rt_newmsg(RTM_CHANGE, rt);
+ } else {
+ /*
+ * If error != 0, the rtentry is being
+ * destroyed, so doing nothing doesn't
+ * matter.
+ */
+ }
+#else
+ rt_replace_ifa(rt, ifa);
+ rt_newmsg(RTM_CHANGE, rt);
+#endif
+ rt_unref(rt);
+ RT_REFCNT_TRACE(rt);
+ }
+}
+
int
rt_walktree(sa_family_t family, int (*f)(struct rtentry *, void *), void *v)
{
diff -r 0f4ed5a7514c -r d1244fd3b1ed sys/net/route.h
--- a/sys/net/route.h Mon Sep 19 22:30:19 2022 +0000
+++ b/sys/net/route.h Tue Sep 20 02:23:37 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: route.h,v 1.131 2022/08/29 09:14:02 knakahara Exp $ */
+/* $NetBSD: route.h,v 1.132 2022/09/20 02:23:37 knakahara Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@@ -463,7 +463,9 @@
int rt_check_reject_route(const struct rtentry *, const struct ifnet *);
void rt_delete_matched_entries(sa_family_t,
- int (*)(struct rtentry *, void *), void *);
+ int (*)(struct rtentry *, void *), void *, bool);
+void rt_replace_ifa_matched_entries(sa_family_t,
+ int (*)(struct rtentry *, void *), void *, struct ifaddr *);
int rt_walktree(sa_family_t, int (*)(struct rtentry *, void *), void *);
static __inline void
diff -r 0f4ed5a7514c -r d1244fd3b1ed sys/netinet/in.c
--- a/sys/netinet/in.c Mon Sep 19 22:30:19 2022 +0000
+++ b/sys/netinet/in.c Tue Sep 20 02:23:37 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in.c,v 1.242 2021/09/21 15:05:41 christos Exp $ */
+/* $NetBSD: in.c,v 1.243 2022/09/20 02:23:37 knakahara Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.242 2021/09/21 15:05:41 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.243 2022/09/20 02:23:37 knakahara Exp $");
#include "arp.h"
@@ -1347,6 +1347,17 @@
return error;
}
+static int
+in_rt_ifa_matcher(struct rtentry *rt, void *v)
+{
+ struct ifaddr *ifa = v;
+
+ if (rt->rt_ifa == ifa)
+ return 1;
+ else
+ return 0;
+}
+
/*
* remove a route to prefix ("connected route" in cisco terminology).
* re-installs the route by using another interface address, if there's one
@@ -1403,6 +1414,16 @@
if (error == 0)
ia->ia_flags |= IFA_ROUTE;
+ if (!ISSET(target->ia_ifa.ifa_flags, IFA_DESTROYING))
+ goto skip;
+ /*
+ * Replace rt_ifa of routes that have the removing address
+ * with the new address.
+ */
+ rt_replace_ifa_matched_entries(AF_INET,
+ in_rt_ifa_matcher, &target->ia_ifa, &ia->ia_ifa);
+
+ skip:
ia4_release(ia, &psref);
curlwp_bindx(bound);
@@ -1416,6 +1437,13 @@
*/
rtinit(&target->ia_ifa, RTM_DELETE, rtinitflags(target));
target->ia_flags &= ~IFA_ROUTE;
+
+ if (ISSET(target->ia_ifa.ifa_flags, IFA_DESTROYING)) {
+ /* Remove routes that have the removing address as rt_ifa. */
+ rt_delete_matched_entries(AF_INET, in_rt_ifa_matcher,
+ &target->ia_ifa, true);
+ }
+
return 0;
}
diff -r 0f4ed5a7514c -r d1244fd3b1ed sys/netinet6/in6.c
--- a/sys/netinet6/in6.c Mon Sep 19 22:30:19 2022 +0000
+++ b/sys/netinet6/in6.c Tue Sep 20 02:23:37 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in6.c,v 1.285 2021/12/05 04:42:55 msaitoh Exp $ */
+/* $NetBSD: in6.c,v 1.286 2022/09/20 02:23:37 knakahara Exp $ */
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.285 2021/12/05 04:42:55 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.286 2022/09/20 02:23:37 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -279,6 +279,17 @@
return error;
}
+static int
+in6_rt_ifa_matcher(struct rtentry *rt, void *v)
+{
+ struct ifaddr *ifa = v;
+
+ if (rt->rt_ifa == ifa)
+ return 1;
+ else
+ return 0;
+}
+
/* Delete network prefix route if present.
* Re-add it to another address if the prefix matches. */
static int
@@ -319,6 +330,16 @@
error = in6_ifaddprefix(ia);
+ if (!ISSET(target->ia_ifa.ifa_flags, IFA_DESTROYING))
+ goto skip;
+ /*
+ * Replace rt_ifa of routes that have the removing address
+ * with the new address.
+ */
+ rt_replace_ifa_matched_entries(AF_INET6,
+ in6_rt_ifa_matcher, &target->ia_ifa, &ia->ia_ifa);
+
+ skip:
ia6_release(ia, &psref);
curlwp_bindx(bound);
@@ -332,6 +353,13 @@
*/
rtinit(&target->ia_ifa, RTM_DELETE, 0);
target->ia_flags &= ~IFA_ROUTE;
+
+ if (ISSET(target->ia_ifa.ifa_flags, IFA_DESTROYING)) {
+ /* Remove routes that have the removing address as rt_ifa. */
+ rt_delete_matched_entries(AF_INET6, in6_rt_ifa_matcher,
+ &target->ia_ifa, true);
+ }
+
return 0;
}
diff -r 0f4ed5a7514c -r d1244fd3b1ed sys/nfs/nfs_boot.c
--- a/sys/nfs/nfs_boot.c Mon Sep 19 22:30:19 2022 +0000
+++ b/sys/nfs/nfs_boot.c Tue Sep 20 02:23:37 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_boot.c,v 1.88 2018/05/17 02:34:31 thorpej Exp $ */
+/* $NetBSD: nfs_boot.c,v 1.89 2022/09/20 02:23:37 knakahara Exp $ */
/*-
* Copyright (c) 1995, 1997 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
Home |
Main Index |
Thread Index |
Old Index