aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2020-04-26 18:42:38 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2020-04-26 18:42:38 +0000
commit55f57ca9ac9b886c1de7c2cfe81ee9b53acc2c4e (patch)
treee673370309bcb9deea6e1c327d1d00928d281131
parent49c9f84f54a193b42ed9a1dbfafd609181bf9fa4 (diff)
downloadsrc-55f57ca9ac9b886c1de7c2cfe81ee9b53acc2c4e.tar.gz
src-55f57ca9ac9b886c1de7c2cfe81ee9b53acc2c4e.zip
Convert debugnet to the new routing KPI.
Introduce new fib[46]_lookup_debugnet() functions serving as a special interface for the crash-time operations. Underlying implementation will try to return lookup result if datastructures are not corrupted, avoding locking. Convert debugnet to use fib4_lookup_debugnet() and switch it to use nexthops instead of rtentries. Reviewed by: cem Differential Revision: https://reviews.freebsd.org/D24555
Notes
Notes: svn path=/head/; revision=360349
-rw-r--r--sys/net/debugnet.c25
-rw-r--r--sys/netinet/in_fib.c42
-rw-r--r--sys/netinet/in_fib.h2
-rw-r--r--sys/netinet6/in6_fib.c41
-rw-r--r--sys/netinet6/in6_fib.h2
5 files changed, 100 insertions, 12 deletions
diff --git a/sys/net/debugnet.c b/sys/net/debugnet.c
index a69482d47c74..3930a87d46dc 100644
--- a/sys/net/debugnet.c
+++ b/sys/net/debugnet.c
@@ -53,8 +53,11 @@ __FBSDID("$FreeBSD$");
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_var.h>
+#include <net/route.h>
+#include <net/route/nhop.h>
#include <netinet/in.h>
+#include <netinet/in_fib.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
@@ -644,8 +647,8 @@ debugnet_connect(const struct debugnet_conn_params *dcp,
if (pcb->dp_client == INADDR_ANY || pcb->dp_gateway == INADDR_ANY ||
pcb->dp_ifp == NULL) {
struct sockaddr_in dest_sin, *gw_sin, *local_sin;
- struct rtentry *dest_rt;
struct ifnet *rt_ifp;
+ struct nhop_object *nh;
memset(&dest_sin, 0, sizeof(dest_sin));
dest_sin = (struct sockaddr_in) {
@@ -655,29 +658,29 @@ debugnet_connect(const struct debugnet_conn_params *dcp,
};
CURVNET_SET(vnet0);
- dest_rt = rtalloc1((struct sockaddr *)&dest_sin, 0,
- RTF_RNH_LOCKED);
+ nh = fib4_lookup_debugnet(RT_DEFAULT_FIB, dest_sin.sin_addr, 0,
+ NHR_NONE);
CURVNET_RESTORE();
- if (dest_rt == NULL) {
+ if (nh == NULL) {
printf("%s: Could not get route for that server.\n",
__func__);
error = ENOENT;
goto cleanup;
}
- if (dest_rt->rt_gateway->sa_family == AF_INET)
- gw_sin = (struct sockaddr_in *)dest_rt->rt_gateway;
+ if (nh->gw_sa.sa_family == AF_INET)
+ gw_sin = &nh->gw4_sa;
else {
- if (dest_rt->rt_gateway->sa_family == AF_LINK)
+ if (nh->gw_sa.sa_family == AF_LINK)
DNETDEBUG("Destination address is on link.\n");
gw_sin = NULL;
}
- MPASS(dest_rt->rt_ifa->ifa_addr->sa_family == AF_INET);
- local_sin = (struct sockaddr_in *)dest_rt->rt_ifa->ifa_addr;
+ MPASS(nh->nh_ifa->ifa_addr->sa_family == AF_INET);
+ local_sin = (struct sockaddr_in *)nh->nh_ifa->ifa_addr;
- rt_ifp = dest_rt->rt_ifp;
+ rt_ifp = nh->nh_ifp;
if (pcb->dp_client == INADDR_ANY)
pcb->dp_client = local_sin->sin_addr.s_addr;
@@ -685,8 +688,6 @@ debugnet_connect(const struct debugnet_conn_params *dcp,
pcb->dp_gateway = gw_sin->sin_addr.s_addr;
if (pcb->dp_ifp == NULL)
pcb->dp_ifp = rt_ifp;
-
- RTFREE_LOCKED(dest_rt);
}
ifp = pcb->dp_ifp;
diff --git a/sys/netinet/in_fib.c b/sys/netinet/in_fib.c
index fabf5a5f77ac..b70d1b1da14f 100644
--- a/sys/netinet/in_fib.c
+++ b/sys/netinet/in_fib.c
@@ -361,4 +361,46 @@ fib4_check_urpf(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
return (0);
}
+struct nhop_object *
+fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
+ uint32_t flags)
+{
+ struct rib_head *rh;
+ struct radix_node *rn;
+ struct rtentry *rt;
+ struct nhop_object *nh;
+
+ KASSERT((fibnum < rt_numfibs), ("fib4_lookup_debugnet: bad fibnum"));
+ rh = rt_tables_get_rnh(fibnum, AF_INET);
+ if (rh == NULL)
+ return (NULL);
+
+ /* Prepare lookup key */
+ struct sockaddr_in sin4;
+ memset(&sin4, 0, sizeof(sin4));
+ sin4.sin_family = AF_INET;
+ sin4.sin_len = sizeof(struct sockaddr_in);
+ sin4.sin_addr = dst;
+
+ nh = NULL;
+ /* unlocked lookup */
+ rn = rh->rnh_matchaddr((void *)&sin4, &rh->head);
+ if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
+ rt = RNTORT(rn);
+#ifdef RADIX_MPATH
+ if (rt_mpath_next(rt) != NULL)
+ rt = rt_mpath_selectrte(rt, 0);
+#endif
+ nh = rt->rt_nhop;
+ /* Ensure route & ifp is UP */
+ if (RT_LINK_IS_UP(nh->nh_ifp)) {
+ if (flags & NHR_REF)
+ nhop_ref_object(nh);
+ return (nh);
+ }
+ }
+
+ return (NULL);
+}
+
#endif
diff --git a/sys/netinet/in_fib.h b/sys/netinet/in_fib.h
index 1a3cdd73a5d7..7a58fbae94d8 100644
--- a/sys/netinet/in_fib.h
+++ b/sys/netinet/in_fib.h
@@ -75,5 +75,7 @@ struct nhop_object *fib4_lookup(uint32_t fibnum, struct in_addr dst,
uint32_t scopeid, uint32_t flags, uint32_t flowid);
int fib4_check_urpf(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
uint32_t flags, const struct ifnet *src_if);
+struct nhop_object *fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst,
+ uint32_t scopeid, uint32_t flags);
#endif
diff --git a/sys/netinet6/in6_fib.c b/sys/netinet6/in6_fib.c
index a141510f142d..35f5da142db0 100644
--- a/sys/netinet6/in6_fib.c
+++ b/sys/netinet6/in6_fib.c
@@ -397,5 +397,46 @@ fib6_check_urpf(uint32_t fibnum, const struct in6_addr *dst6,
return (0);
}
+struct nhop_object *
+fib6_lookup_debugnet(uint32_t fibnum, const struct in6_addr *dst6,
+ uint32_t scopeid, uint32_t flags)
+{
+ struct rib_head *rh;
+ struct radix_node *rn;
+ struct rtentry *rt;
+ struct nhop_object *nh;
+ struct sockaddr_in6 sin6;
+
+ KASSERT((fibnum < rt_numfibs), ("fib6_lookup: bad fibnum"));
+ rh = rt_tables_get_rnh(fibnum, AF_INET6);
+ if (rh == NULL)
+ return (NULL);
+
+ /* TODO: radix changes */
+ //addr = *dst6;
+ /* Prepare lookup key */
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_addr = *dst6;
+
+ /* Assume scopeid is valid and embed it directly */
+ if (IN6_IS_SCOPE_LINKLOCAL(dst6))
+ sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
+
+ rn = rh->rnh_matchaddr((void *)&sin6, &rh->head);
+ if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
+ rt = RNTORT(rn);
+ nh = rt->rt_nhop;
+ /* Ensure route & ifp is UP */
+ if (RT_LINK_IS_UP(nh->nh_ifp)) {
+ if (flags & NHR_REF)
+ nhop_ref_object(nh);
+ return (nh);
+ }
+ }
+
+ return (NULL);
+}
+
#endif
diff --git a/sys/netinet6/in6_fib.h b/sys/netinet6/in6_fib.h
index bf8d367309cc..907d2d731949 100644
--- a/sys/netinet6/in6_fib.h
+++ b/sys/netinet6/in6_fib.h
@@ -64,5 +64,7 @@ struct nhop_object *fib6_lookup(uint32_t fibnum,
uint32_t flowid);
int fib6_check_urpf(uint32_t fibnum, const struct in6_addr *dst6,
uint32_t scopeid, uint32_t flags, const struct ifnet *src_if);
+struct nhop_object *fib6_lookup_debugnet(uint32_t fibnum,
+ const struct in6_addr *dst6, uint32_t scopeid, uint32_t flags);
#endif