From 00dd306946903dc5215e47918b7f5a3d599480c5 Mon Sep 17 00:00:00 2001 From: bluhm Date: Tue, 16 Apr 2024 12:56:39 +0000 Subject: [PATCH] Use route cache function in IP input. Instaed of passing a struct rtentry from ip_input() to ip_forward() and then embed it into a struct route for ip_output(), start with struct route and pass it along. Then the route cache is used consistently. Also the route cache hit and missed counters should reflect reality after this commit. There is a small difference in the code. in_ouraddr() checks for NULL and not rtisvalid(). Previous discussion showed that the route RTF_UP flag should only be considered for multipath routing. Otherwise it does not mean anything. Especially the local and broadcast check in in_ouraddr() should not be affected by interface link status. When doing cache lookups, route must be valid, but after rtalloc_mpath() lookup, use any route that route_mpath() returns. OK claudio@ --- sys/netinet/ip_input.c | 63 +++++++++++++++++--------------------- sys/netinet/ip_var.h | 4 +-- sys/netinet6/ip6_forward.c | 50 +++++++++++++++--------------- sys/netinet6/ip6_input.c | 20 +++++------- sys/netinet6/ip6_output.c | 4 +-- sys/netinet6/ip6_var.h | 4 +-- 6 files changed, 67 insertions(+), 78 deletions(-) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 25f9cc5ebd1..1d1510470f3 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.392 2024/04/14 20:46:27 bluhm Exp $ */ +/* $OpenBSD: ip_input.c,v 1.393 2024/04/16 12:56:39 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -138,7 +138,7 @@ extern struct niqueue arpinq; int ip_ours(struct mbuf **, int *, int, int); int ip_dooptions(struct mbuf *, struct ifnet *); -int in_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **); +int in_ouraddr(struct mbuf *, struct ifnet *, struct route *); int ip_fragcheck(struct mbuf **, int *); struct mbuf * ip_reass(struct ipqent *, struct ipq *); @@ -424,9 +424,9 @@ bad: int ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) { - struct mbuf *m; - struct rtentry *rt = NULL; - struct ip *ip; + struct route ro; + struct mbuf *m; + struct ip *ip; int hlen; #if NPF > 0 struct in_addr odst; @@ -435,6 +435,7 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) KASSERT(*offp == 0); + ro.ro_rt = NULL; ipstat_inc(ips_total); m = *mp = ipv4_check(ifp, *mp); if (m == NULL) @@ -482,7 +483,7 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) goto out; } - switch(in_ouraddr(m, ifp, &rt)) { + switch(in_ouraddr(m, ifp, &ro)) { case 2: goto bad; case 1: @@ -584,14 +585,14 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) } #endif /* IPSEC */ - ip_forward(m, ifp, rt, pfrdr); + ip_forward(m, ifp, &ro, pfrdr); *mp = NULL; return IPPROTO_DONE; bad: nxt = IPPROTO_DONE; m_freemp(mp); out: - rtfree(rt); + rtfree(ro.ro_rt); return nxt; } @@ -805,11 +806,10 @@ ip_deliver(struct mbuf **mp, int *offp, int nxt, int af, int shared) #undef IPSTAT_INC int -in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct rtentry **prt) +in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro) { struct rtentry *rt; struct ip *ip; - struct sockaddr_in sin; int match = 0; #if NPF > 0 @@ -826,13 +826,8 @@ in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct rtentry **prt) ip = mtod(m, struct ip *); - memset(&sin, 0, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr = ip->ip_dst; - rt = rtalloc_mpath(sintosa(&sin), &ip->ip_src.s_addr, - m->m_pkthdr.ph_rtableid); - if (rtisvalid(rt)) { + rt = route_mpath(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid); + if (rt != NULL) { if (ISSET(rt->rt_flags, RTF_LOCAL)) match = 1; @@ -848,7 +843,6 @@ in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct rtentry **prt) m->m_flags |= M_BCAST; } } - *prt = rt; if (!match) { struct ifaddr *ifa; @@ -1527,11 +1521,12 @@ const u_char inetctlerrmap[PRC_NCMDS] = { * via a source route. */ void -ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt) +ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int srcrt) { struct mbuf mfake, *mcopy; struct ip *ip = mtod(m, struct ip *); - struct route ro; + struct route iproute; + struct rtentry *rt; int error = 0, type = 0, code = 0, destmtu = 0, fake = 0, len; u_int32_t dest; @@ -1546,19 +1541,16 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt) goto done; } - ro.ro_rt = NULL; - route_cache(&ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid); - if (!rtisvalid(rt)) { - rtfree(rt); - rt = rtalloc_mpath(&ro.ro_dstsa, &ip->ip_src.s_addr, - m->m_pkthdr.ph_rtableid); - if (rt == NULL) { - ipstat_inc(ips_noroute); - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); - return; - } + if (ro == NULL) { + ro = &iproute; + ro->ro_rt = NULL; + } + rt = route_mpath(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid); + if (rt == NULL) { + ipstat_inc(ips_noroute); + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); + goto done; } - ro.ro_rt = rt; /* * Save at most 68 bytes of the packet in case @@ -1609,10 +1601,10 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt) } } - error = ip_output(m, NULL, &ro, + error = ip_output(m, NULL, ro, (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), NULL, NULL, 0); - rt = ro.ro_rt; + rt = ro->ro_rt; if (error) ipstat_inc(ips_cantforward); else { @@ -1680,9 +1672,10 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt) icmp_error(mcopy, type, code, dest, destmtu); done: + if (ro == &iproute) + rtfree(ro->ro_rt); if (fake) m_tag_delete_chain(&mfake); - rtfree(rt); } int diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index c5b92847561..cdbdd2d4358 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.115 2024/04/14 20:46:27 bluhm Exp $ */ +/* $OpenBSD: ip_var.h,v 1.116 2024/04/16 12:56:39 bluhm Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -260,7 +260,7 @@ void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *); int ip_deliver(struct mbuf **, int *, int, int, int); -void ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int); +void ip_forward(struct mbuf *, struct ifnet *, struct route *, int); int rip_ctloutput(int, struct socket *, int, int, struct mbuf *); void rip_init(void); int rip_input(struct mbuf **, int *, int, int); diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index 84c872a192f..913fb64304c 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_forward.c,v 1.116 2024/02/28 10:57:20 bluhm Exp $ */ +/* $OpenBSD: ip6_forward.c,v 1.117 2024/04/16 12:56:39 bluhm Exp $ */ /* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */ /* @@ -82,11 +82,12 @@ */ void -ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt) +ip6_forward(struct mbuf *m, struct route *ro, int srcrt) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); + struct route iproute; + struct rtentry *rt; struct sockaddr *dst; - struct route ro; struct ifnet *ifp = NULL; int error = 0, type = 0, code = 0, destmtu = 0; struct mbuf *mcopy; @@ -165,25 +166,22 @@ reroute: } #endif /* IPSEC */ - ro.ro_rt = NULL; - route6_cache(&ro, &ip6->ip6_dst, &ip6->ip6_src, + if (ro == NULL) { + ro = &iproute; + ro->ro_rt = NULL; + } + rt = route6_mpath(ro, &ip6->ip6_dst, &ip6->ip6_src, m->m_pkthdr.ph_rtableid); - dst = &ro.ro_dstsa; - if (!rtisvalid(rt)) { - rtfree(rt); - rt = rtalloc_mpath(dst, &ip6->ip6_src.s6_addr32[0], - m->m_pkthdr.ph_rtableid); - if (rt == NULL) { - ip6stat_inc(ip6s_noroute); - if (mcopy != NULL) { - icmp6_error(mcopy, ICMP6_DST_UNREACH, - ICMP6_DST_UNREACH_NOROUTE, 0); - } - m_freem(m); - goto done; + if (rt == NULL) { + ip6stat_inc(ip6s_noroute); + if (mcopy != NULL) { + icmp6_error(mcopy, ICMP6_DST_UNREACH, + ICMP6_DST_UNREACH_NOROUTE, 0); } + m_freem(m); + goto done; } - ro.ro_rt = rt; + dst = &ro->ro_dstsa; /* * Scope check: if a packet can't be delivered to its destination @@ -225,8 +223,8 @@ reroute: */ if (tdb != NULL) { /* Callee frees mbuf */ - error = ip6_output_ipsec_send(tdb, m, &ro, 0, 1); - rt = ro.ro_rt; + error = ip6_output_ipsec_send(tdb, m, ro, 0, 1); + rt = ro->ro_rt; if (error) goto senderr; goto freecopy; @@ -254,7 +252,7 @@ reroute: ip6_sendredirects && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) { if ((ifp->if_flags & IFF_POINTOPOINT) && - nd6_is_addr_neighbor(&ro.ro_dstsin6, ifp)) { + nd6_is_addr_neighbor(&ro->ro_dstsin6, ifp)) { /* * If the incoming interface is equal to the outgoing * one, the link attached to the interface is @@ -308,8 +306,9 @@ reroute: /* tag as generated to skip over pf_test on rerun */ m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; srcrt = 1; - rtfree(rt); - rt = NULL; + if (ro == &iproute) + rtfree(ro->ro_rt); + ro = NULL; if_put(ifp); ifp = NULL; goto reroute; @@ -388,7 +387,8 @@ senderr: freecopy: m_freem(mcopy); done: - rtfree(rt); + if (ro == &iproute) + rtfree(ro->ro_rt); if_put(ifp); #ifdef IPSEC tdb_unref(tdb); diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 5f4e991e0f8..e389bc0aa35 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_input.c,v 1.260 2024/04/14 20:46:27 bluhm Exp $ */ +/* $OpenBSD: ip6_input.c,v 1.261 2024/04/16 12:56:39 bluhm Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* @@ -356,10 +356,10 @@ bad: int ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) { + struct route ro; struct mbuf *m; struct ip6_hdr *ip6; - struct sockaddr_in6 sin6; - struct rtentry *rt = NULL; + struct rtentry *rt; int ours = 0; u_int16_t src_scope, dst_scope; #if NPF > 0 @@ -369,8 +369,8 @@ ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) KASSERT(*offp == 0); + ro.ro_rt = NULL; ip6stat_inc(ip6s_total); - m = *mp = ipv6_check(ifp, *mp); if (m == NULL) goto bad; @@ -516,18 +516,14 @@ ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) /* * Unicast check */ - memset(&sin6, 0, sizeof(struct sockaddr_in6)); - sin6.sin6_len = sizeof(struct sockaddr_in6); - sin6.sin6_family = AF_INET6; - sin6.sin6_addr = ip6->ip6_dst; - rt = rtalloc_mpath(sin6tosa(&sin6), &ip6->ip6_src.s6_addr32[0], + rt = route6_mpath(&ro, &ip6->ip6_dst, &ip6->ip6_src, m->m_pkthdr.ph_rtableid); /* * Accept the packet if the route to the destination is marked * as local. */ - if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL)) { + if (rt != NULL && ISSET(rt->rt_flags, RTF_LOCAL)) { struct in6_ifaddr *ia6 = ifatoia6(rt->rt_ifa); if (ip6_forwarding == 0 && rt->rt_ifidx != ifp->if_index && @@ -617,14 +613,14 @@ ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) } #endif /* IPSEC */ - ip6_forward(m, rt, pfrdr); + ip6_forward(m, &ro, pfrdr); *mp = NULL; return IPPROTO_DONE; bad: nxt = IPPROTO_DONE; m_freemp(mp); out: - rtfree(rt); + rtfree(ro.ro_rt); return nxt; } diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index a2ba550fa5a..99d494df528 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_output.c,v 1.289 2024/04/09 11:05:05 bluhm Exp $ */ +/* $OpenBSD: ip6_output.c,v 1.290 2024/04/16 12:56:39 bluhm Exp $ */ /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */ /* @@ -391,7 +391,7 @@ reroute: /* initialize cached route */ if (ro == NULL) { ro = &iproute; - bzero((caddr_t)ro, sizeof(*ro)); + ro->ro_rt = NULL; } ro_pmtu = ro; if (opt && opt->ip6po_rthdr) diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index c1249f7974f..1b9ae82c482 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_var.h,v 1.114 2024/02/14 13:18:21 claudio Exp $ */ +/* $OpenBSD: ip6_var.h,v 1.115 2024/04/16 12:56:39 bluhm Exp $ */ /* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */ /* @@ -320,7 +320,7 @@ int ip6_process_hopopts(struct mbuf **, u_int8_t *, int, u_int32_t *, void ip6_savecontrol(struct inpcb *, struct mbuf *, struct mbuf **); int ip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); -void ip6_forward(struct mbuf *, struct rtentry *, int); +void ip6_forward(struct mbuf *, struct route *, int); void ip6_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in6 *); int ip6_output(struct mbuf *, struct ip6_pktopts *, struct route *, int, -- 2.20.1