From: Claudio Jeker Subject: Re: route generation number for IPv6 To: Alexander Bluhm Cc: tech@openbsd.org Date: Wed, 7 Feb 2024 11:19:20 +0100 On Mon, Feb 05, 2024 at 08:21:38PM +0100, Alexander Bluhm wrote: > On Sun, Feb 04, 2024 at 07:21:46PM +0100, Alexander Bluhm wrote: > > Let's use the route generation number also for IPv6 and in_pcbrtentry(). > > New diff after fixing m88k build. Prototype route6_cache() is now > in netinet6/in6.h. > > ok? Lets get this in. OK claudio@ > bluhm > > Index: net/route.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/net/route.c,v > diff -u -p -r1.427 route.c > --- net/route.c 31 Jan 2024 14:56:42 -0000 1.427 > +++ net/route.c 5 Feb 2024 19:12:07 -0000 > @@ -228,6 +228,34 @@ route_cache(struct route *ro, struct in_ > satosin(&ro->ro_dst)->sin_addr = addr; > } > > +void > +route6_cache(struct route_in6 *ro, const struct in6_addr *addr, > + u_int rtableid) > +{ > + u_long gen; > + > + gen = atomic_load_long(&rtgeneration); > + membar_consumer(); > + > + if (rtisvalid(ro->ro_rt) && > + ro->ro_generation == gen && > + ro->ro_tableid == rtableid && > + ro->ro_dst.sin6_family == AF_INET6 && > + IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, addr)) { > + return; > + } > + > + rtfree(ro->ro_rt); > + ro->ro_rt = NULL; > + ro->ro_generation = gen; > + ro->ro_tableid = rtableid; > + > + memset(&ro->ro_dst, 0, sizeof(ro->ro_dst)); > + ro->ro_dst.sin6_family = AF_INET6; > + ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6); > + ro->ro_dst.sin6_addr = *addr; > +} > + > /* > * Returns 1 if the (cached) ``rt'' entry is still valid, 0 otherwise. > */ > Index: netinet/in_pcb.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v > diff -u -p -r1.289 in_pcb.c > --- netinet/in_pcb.c 2 Feb 2024 15:39:23 -0000 1.289 > +++ netinet/in_pcb.c 5 Feb 2024 19:12:07 -0000 > @@ -916,24 +916,10 @@ in_pcbrtentry(struct inpcb *inp) > > ro = &inp->inp_route; > > - /* check if route is still valid */ > - if (!rtisvalid(ro->ro_rt)) { > - rtfree(ro->ro_rt); > - ro->ro_rt = NULL; > - } > - > - /* > - * No route yet, so try to acquire one. > - */ > + if (inp->inp_faddr.s_addr == INADDR_ANY) > + return (NULL); > + route_cache(ro, inp->inp_faddr, inp->inp_rtableid); > if (ro->ro_rt == NULL) { > - memset(ro, 0, sizeof(struct route)); > - > - if (inp->inp_faddr.s_addr == INADDR_ANY) > - return (NULL); > - ro->ro_dst.sa_family = AF_INET; > - ro->ro_dst.sa_len = sizeof(struct sockaddr_in); > - satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr; > - ro->ro_tableid = inp->inp_rtableid; > ro->ro_rt = rtalloc_mpath(&ro->ro_dst, > &inp->inp_laddr.s_addr, ro->ro_tableid); > } > Index: netinet6/in6.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6.h,v > diff -u -p -r1.113 in6.h > --- netinet6/in6.h 31 Jan 2024 14:56:43 -0000 1.113 > +++ netinet6/in6.h 5 Feb 2024 19:12:07 -0000 > @@ -428,6 +428,8 @@ int in6_mask2len(struct in6_addr *, u_ch > int in6_nam2sin6(const struct mbuf *, struct sockaddr_in6 **); > int in6_sa2sin6(struct sockaddr *, struct sockaddr_in6 **); > > +void route6_cache(struct route_in6 *, const struct in6_addr *, u_int); > + > struct ip6_pktopts; > struct ip6_moptions; > > Index: netinet6/in6_pcb.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_pcb.c,v > diff -u -p -r1.134 in6_pcb.c > --- netinet6/in6_pcb.c 31 Jan 2024 12:27:57 -0000 1.134 > +++ netinet6/in6_pcb.c 5 Feb 2024 19:12:07 -0000 > @@ -566,24 +566,10 @@ in6_pcbrtentry(struct inpcb *inp) > { > struct route_in6 *ro = &inp->inp_route6; > > - /* check if route is still valid */ > - if (!rtisvalid(ro->ro_rt)) { > - rtfree(ro->ro_rt); > - ro->ro_rt = NULL; > - } > - > - /* > - * No route yet, so try to acquire one. > - */ > + if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) > + return (NULL); > + route6_cache(ro, &inp->inp_faddr6, inp->inp_rtableid); > if (ro->ro_rt == NULL) { > - memset(ro, 0, sizeof(struct route_in6)); > - > - if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) > - return (NULL); > - ro->ro_dst.sin6_family = AF_INET6; > - ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6); > - ro->ro_dst.sin6_addr = inp->inp_faddr6; > - ro->ro_tableid = inp->inp_rtableid; > ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst), > &inp->inp_laddr6.s6_addr32[0], ro->ro_tableid); > } > Index: netinet6/in6_src.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_src.c,v > diff -u -p -r1.91 in6_src.c > --- netinet6/in6_src.c 9 Jan 2024 19:57:01 -0000 1.91 > +++ netinet6/in6_src.c 5 Feb 2024 19:12:07 -0000 > @@ -82,7 +82,7 @@ > #include > #include > > -int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *, > +int in6_selectif(const struct in6_addr *, struct ip6_pktopts *, > struct ip6_moptions *, struct route_in6 *, struct ifnet **, u_int); > > /* > @@ -118,7 +118,7 @@ in6_pcbselsrc(const struct in6_addr **in > struct sockaddr_in6 sa6; > > /* get the outgoing interface */ > - error = in6_selectif(dstsock, opts, mopts, ro, &ifp, rtableid); > + error = in6_selectif(dst, opts, mopts, ro, &ifp, rtableid); > if (error) > return (error); > > @@ -179,22 +179,8 @@ in6_pcbselsrc(const struct in6_addr **in > * If route is known or can be allocated now, > * our src addr is taken from the i/f, else punt. > */ > - if (!rtisvalid(ro->ro_rt) || (ro->ro_tableid != rtableid) || > - !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) { > - rtfree(ro->ro_rt); > - ro->ro_rt = NULL; > - } > + route6_cache(ro, dst, rtableid); > if (ro->ro_rt == NULL) { > - struct sockaddr_in6 *sa6; > - > - /* No route yet, so try to acquire one */ > - bzero(&ro->ro_dst, sizeof(struct sockaddr_in6)); > - ro->ro_tableid = rtableid; > - sa6 = &ro->ro_dst; > - sa6->sin6_family = AF_INET6; > - sa6->sin6_len = sizeof(struct sockaddr_in6); > - sa6->sin6_addr = *dst; > - sa6->sin6_scope_id = dstsock->sin6_scope_id; > ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst), > RT_RESOLVE, ro->ro_tableid); > } > @@ -312,35 +298,17 @@ in6_selectsrc(const struct in6_addr **in > } > > struct rtentry * > -in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, > +in6_selectroute(const struct in6_addr *dst, struct ip6_pktopts *opts, > struct route_in6 *ro, unsigned int rtableid) > { > - struct in6_addr *dst; > - > - dst = &dstsock->sin6_addr; > - > /* > * Use a cached route if it exists and is valid, else try to allocate > * a new one. > */ > if (ro) { > - if (rtisvalid(ro->ro_rt)) > - KASSERT(sin6tosa(&ro->ro_dst)->sa_family == AF_INET6); > - if (!rtisvalid(ro->ro_rt) || > - !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) { > - rtfree(ro->ro_rt); > - ro->ro_rt = NULL; > - } > + route6_cache(ro, dst, rtableid); > if (ro->ro_rt == NULL) { > - struct sockaddr_in6 *sa6; > - > /* No route yet, so try to acquire one */ > - bzero(&ro->ro_dst, sizeof(struct sockaddr_in6)); > - ro->ro_tableid = rtableid; > - sa6 = &ro->ro_dst; > - *sa6 = *dstsock; > - sa6->sin6_scope_id = 0; > - ro->ro_tableid = rtableid; > ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst), > NULL, ro->ro_tableid); > } > @@ -369,7 +337,7 @@ in6_selectroute(struct sockaddr_in6 *dst > } > > int > -in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, > +in6_selectif(const struct in6_addr *dst, struct ip6_pktopts *opts, > struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp, > u_int rtableid) > { > @@ -387,11 +355,11 @@ in6_selectif(struct sockaddr_in6 *dstsoc > * If the destination address is a multicast address and the outgoing > * interface for the address is specified by the caller, use it. > */ > - if (IN6_IS_ADDR_MULTICAST(&dstsock->sin6_addr) && > + if (IN6_IS_ADDR_MULTICAST(dst) && > mopts != NULL && (*retifp = if_get(mopts->im6o_ifidx)) != NULL) > return (0); > > - rt = in6_selectroute(dstsock, opts, ro, rtableid); > + rt = in6_selectroute(dst, opts, ro, rtableid); > if (rt == NULL) > return (EHOSTUNREACH); > > Index: netinet6/ip6_forward.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v > diff -u -p -r1.112 ip6_forward.c > --- netinet6/ip6_forward.c 7 Jul 2023 08:05:02 -0000 1.112 > +++ netinet6/ip6_forward.c 5 Feb 2024 19:12:07 -0000 > @@ -85,7 +85,7 @@ void > ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt) > { > struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); > - struct sockaddr_in6 *sin6; > + struct sockaddr *dst; > struct route_in6 ro; > struct ifnet *ifp = NULL; > int error = 0, type = 0, code = 0, destmtu = 0; > @@ -165,15 +165,12 @@ reroute: > } > #endif /* IPSEC */ > > - memset(&ro, 0, sizeof(ro)); > - sin6 = &ro.ro_dst; > - sin6->sin6_family = AF_INET6; > - sin6->sin6_len = sizeof(*sin6); > - sin6->sin6_addr = ip6->ip6_dst; > - > + ro.ro_rt = NULL; > + route6_cache(&ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid); > + dst = sin6tosa(&ro.ro_dst); > if (!rtisvalid(rt)) { > rtfree(rt); > - rt = rtalloc_mpath(sin6tosa(sin6), &ip6->ip6_src.s6_addr32[0], > + rt = rtalloc_mpath(dst, &ip6->ip6_src.s6_addr32[0], > m->m_pkthdr.ph_rtableid); > if (rt == NULL) { > ip6stat_inc(ip6s_noroute); > @@ -185,6 +182,7 @@ reroute: > goto out; > } > } > + ro.ro_rt = rt; > > /* > * Scope check: if a packet can't be delivered to its destination > @@ -226,8 +224,6 @@ reroute: > */ > if (tdb != NULL) { > /* Callee frees mbuf */ > - ro.ro_rt = rt; > - ro.ro_tableid = m->m_pkthdr.ph_rtableid; > error = ip6_output_ipsec_send(tdb, m, &ro, 0, 1); > rt = ro.ro_rt; > if (error) > @@ -237,7 +233,7 @@ reroute: > #endif /* IPSEC */ > > if (rt->rt_flags & RTF_GATEWAY) > - sin6 = satosin6(rt->rt_gateway); > + dst = rt->rt_gateway; > > /* > * If we are to forward the packet using the same interface > @@ -319,7 +315,7 @@ reroute: > } > #endif > > - error = if_output_tso(ifp, &m, sin6tosa(sin6), rt, ifp->if_mtu); > + error = if_output_tso(ifp, &m, dst, rt, ifp->if_mtu); > if (error) > ip6stat_inc(ip6s_cantforward); > else if (m == NULL) > Index: netinet6/ip6_output.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v > diff -u -p -r1.284 ip6_output.c > --- netinet6/ip6_output.c 31 Jan 2024 12:27:57 -0000 1.284 > +++ netinet6/ip6_output.c 5 Feb 2024 19:12:07 -0000 > @@ -169,7 +169,7 @@ ip6_output(struct mbuf *m, struct ip6_pk > int hlen, tlen; > struct route_in6 ip6route; > struct rtentry *rt = NULL; > - struct sockaddr_in6 *dst, dstsock; > + struct sockaddr_in6 *dst; > int error = 0; > u_long mtu; > int dontfrag; > @@ -442,13 +442,7 @@ reroute: > } > #endif /* IPSEC */ > > - bzero(&dstsock, sizeof(dstsock)); > - dstsock.sin6_family = AF_INET6; > - dstsock.sin6_addr = ip6->ip6_dst; > - dstsock.sin6_len = sizeof(dstsock); > - ro->ro_tableid = m->m_pkthdr.ph_rtableid; > - > - if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)) { > + if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { > struct in6_pktinfo *pi = NULL; > > /* > @@ -463,7 +457,8 @@ reroute: > } > > if (ifp == NULL) { > - rt = in6_selectroute(&dstsock, opt, ro, ro->ro_tableid); > + rt = in6_selectroute(&ip6->ip6_dst, opt, ro, > + m->m_pkthdr.ph_rtableid); > if (rt == NULL) { > ip6stat_inc(ip6s_noroute); > error = EHOSTUNREACH; > @@ -485,7 +480,7 @@ reroute: > goto bad; > } > } else { > - *dst = dstsock; > + route6_cache(ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid); > } > > if (rt && (rt->rt_flags & RTF_GATEWAY) && > Index: netinet6/ip6_var.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_var.h,v > diff -u -p -r1.110 ip6_var.h > --- netinet6/ip6_var.h 3 Feb 2024 22:50:09 -0000 1.110 > +++ netinet6/ip6_var.h 5 Feb 2024 19:12:07 -0000 > @@ -369,7 +369,7 @@ int in6_pcbselsrc(const struct in6_addr > struct inpcb *, struct ip6_pktopts *); > int in6_selectsrc(const struct in6_addr **, struct sockaddr_in6 *, > struct ip6_moptions *, unsigned int); > -struct rtentry *in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *, > +struct rtentry *in6_selectroute(const struct in6_addr *, struct ip6_pktopts *, > struct route_in6 *, unsigned int rtableid); > > u_int32_t ip6_randomflowlabel(void); -- :wq Claudio