From: Claudio Jeker Subject: Re: route cache mpath To: Alexander Bluhm Cc: tech@openbsd.org Date: Mon, 26 Feb 2024 17:22:50 +0100 On Mon, Feb 26, 2024 at 03:51:37PM +0100, Alexander Bluhm wrote: > On Mon, Feb 26, 2024 at 11:56:08AM +0100, Claudio Jeker wrote: > > On Mon, Feb 26, 2024 at 11:44:57AM +0100, Alexander Bluhm wrote: > > > Hi, > > > > > > We can combine route_cache() and rtalloc_mpath() in a new route_mpath() > > > function. Then the caller does not have to care about the uint32_t > > > *src pointer and just pass struct in_addr. All the conversions are > > > done inside the functions. ro->ro_rt is either valid or NULL. > > > > > > Also IP input should pass a struct route to IP forward. This is > > > the same logic that is done when passing a route from IP forward > > > to IP output. As a result the numbers of route cache lookups in > > > netstat -s should be correct now. > > > > > > Finally I removed some inconsistencies between IPv4 and IPv4 and > > > IP forward and IP output. > > > > > > ok? > > > > I would prefer if rtalloc_mpath() is fixed and just takes a struct route * > > as argument. This uint32_t * in rtalloc_mpath() and rtable_match() needs > > to be changed. Passing the source as a uint32_t * is bad in many regards. > > Do you have a diff to explain what you want? > > route6_mpath() takes struct in_addr and writes it into struct route. > What is bad about this design? Nothing. I wonder if we need yet another wrapper around a wrapper so that another wrapper can wrap it into a wrapper before passing it the function doing the lookup. If rtalloc_mpath() would be as simple as struct rtentry *rtalloc_mpath(const struct route *); then a lot of this would just go away since it is not needed. Actually most of the code of route_mpath() and route6_mpath() could be collapsed into rtalloc_mpath() (or vice versa). Btw. I think the check to set 's' in route6_mpath() is reversed. > We might get rid of rtalloc_mpath(). But then we have to use route > cache everywhere. Rewriting the uint32_t * mess in the routing > code is not on my agenda. I try to improve things in small steps. > Moving part of rtalloc_mpath() calls to route6_mpath() makes it > better. Are route6_mpath() parameter the arguments you wish? > > I like the changes to ip_forward and ip6_forward and the general trend to > > make code more consistent. > > Splitting the diff to change ip_forward() first is hard. The API > of route6_mpath() or rtalloc_mpath() decides the way how consistent > code should look like. > > How do we proceed? I don't understand how the code you wish looks. Not against moving on with this but ideally there will be a few more steps after this that slowly make rtalloc() and rtalloc_mpath() better functions. As I said I like the trajectory of this work since it does a lot of good cleanup at higher levels. > > > Or should I split the diff in smaller pieces? > > > > > > bluhm > > > > > > Index: net/route.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/net/route.c,v > > > diff -u -p -r1.433 route.c > > > --- net/route.c 22 Feb 2024 14:25:58 -0000 1.433 > > > +++ net/route.c 23 Feb 2024 23:58:57 -0000 > > > @@ -239,6 +239,28 @@ route_cache(struct route *ro, const stru > > > return (ESRCH); > > > } > > > > > > +/* > > > + * Check cache for route, else allocate a new one, potentially using multipath > > > + * to select the peer. Update cache and return valid route or NULL. > > > + */ > > > +struct rtentry * > > > +route_mpath(struct route *ro, const struct in_addr *dst, > > > + const struct in_addr *src, u_int rtableid) > > > +{ > > > + if (route_cache(ro, dst, src, rtableid)) { > > > + uint32_t *s = NULL; > > > + > > > + if (ro->ro_srcin.s_addr != INADDR_ANY) > > > + s = &ro->ro_srcin.s_addr; > > > + ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, s, ro->ro_tableid); > > > + if (!rtisvalid(ro->ro_rt)) { > > > + rtfree(ro->ro_rt); > > > + ro->ro_rt = NULL; > > > + } > > > + } > > > + return (ro->ro_rt); > > > +} > > > + > > > #ifdef INET6 > > > int > > > route6_cache(struct route *ro, const struct in6_addr *dst, > > > @@ -276,6 +298,24 @@ route6_cache(struct route *ro, const str > > > ro->ro_srcin6 = *src; > > > > > > return (ESRCH); > > > +} > > > + > > > +struct rtentry * > > > +route6_mpath(struct route *ro, const struct in6_addr *dst, > > > + const struct in6_addr *src, u_int rtableid) > > > +{ > > > + if (route6_cache(ro, dst, src, rtableid)) { > > > + uint32_t *s = NULL; > > > + > > > + if (IN6_IS_ADDR_UNSPECIFIED(&ro->ro_srcin6)) > > > + s = &ro->ro_srcin6.s6_addr32[0]; > > > + ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, s, ro->ro_tableid); > > > + if (!rtisvalid(ro->ro_rt)) { > > > + rtfree(ro->ro_rt); > > > + ro->ro_rt = NULL; > > > + } > > > + } > > > + return (ro->ro_rt); > > > } > > > #endif > > > > > > Index: net/route.h > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/net/route.h,v > > > diff -u -p -r1.207 route.h > > > --- net/route.h 22 Feb 2024 14:25:58 -0000 1.207 > > > +++ net/route.h 23 Feb 2024 23:58:57 -0000 > > > @@ -465,7 +465,11 @@ struct bfd_config; > > > void route_init(void); > > > int route_cache(struct route *, const struct in_addr *, > > > const struct in_addr *, u_int); > > > +struct rtentry *route_mpath(struct route *, const struct in_addr *, > > > + const struct in_addr *, u_int); > > > int route6_cache(struct route *, const struct in6_addr *, > > > + const struct in6_addr *, u_int); > > > +struct rtentry *route6_mpath(struct route *, const struct in6_addr *, > > > const struct in6_addr *, u_int); > > > void rtm_ifchg(struct ifnet *); > > > void rtm_ifannounce(struct ifnet *, int); > > > Index: netinet/in_pcb.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v > > > diff -u -p -r1.294 in_pcb.c > > > --- netinet/in_pcb.c 22 Feb 2024 14:25:58 -0000 1.294 > > > +++ netinet/in_pcb.c 23 Feb 2024 23:58:57 -0000 > > > @@ -908,23 +908,15 @@ in_pcblookup_local_lock(struct inpcbtabl > > > struct rtentry * > > > in_pcbrtentry(struct inpcb *inp) > > > { > > > - struct route *ro; > > > - > > > #ifdef INET6 > > > if (ISSET(inp->inp_flags, INP_IPV6)) > > > return in6_pcbrtentry(inp); > > > #endif > > > > > > - ro = &inp->inp_route; > > > - > > > if (inp->inp_faddr.s_addr == INADDR_ANY) > > > return (NULL); > > > - if (route_cache(ro, &inp->inp_faddr, &inp->inp_laddr, > > > - inp->inp_rtableid)) { > > > - ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, > > > - &inp->inp_laddr.s_addr, ro->ro_tableid); > > > - } > > > - return (ro->ro_rt); > > > + return (route_mpath(&inp->inp_route, &inp->inp_faddr, &inp->inp_laddr, > > > + inp->inp_rtableid)); > > > } > > > > > > /* > > > @@ -938,7 +930,7 @@ in_pcbselsrc(struct in_addr *insrc, stru > > > struct inpcb *inp) > > > { > > > struct ip_moptions *mopts = inp->inp_moptions; > > > - struct route *ro = &inp->inp_route; > > > + struct rtentry *rt; > > > const struct in_addr *laddr = &inp->inp_laddr; > > > u_int rtableid = inp->inp_rtableid; > > > struct sockaddr *ip4_source = NULL; > > > @@ -983,17 +975,14 @@ in_pcbselsrc(struct in_addr *insrc, stru > > > * If route is known or can be allocated now, > > > * our src addr is taken from the i/f, else punt. > > > */ > > > - if (route_cache(ro, &sin->sin_addr, NULL, rtableid)) { > > > - /* No route yet, so try to acquire one */ > > > - ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, NULL, ro->ro_tableid); > > > - } > > > + rt = route_mpath(&inp->inp_route, &sin->sin_addr, NULL, rtableid); > > > > > > /* > > > * If we found a route, use the address > > > * corresponding to the outgoing interface. > > > */ > > > - if (ro->ro_rt != NULL) > > > - ia = ifatoia(ro->ro_rt->rt_ifa); > > > + if (rt != NULL) > > > + ia = ifatoia(rt->rt_ifa); > > > > > > /* > > > * Use preferred source address if : > > > @@ -1001,8 +990,7 @@ in_pcbselsrc(struct in_addr *insrc, stru > > > * - preferred source address is set > > > * - output interface is UP > > > */ > > > - if (ro->ro_rt && !(ro->ro_rt->rt_flags & RTF_LLINFO) && > > > - !(ro->ro_rt->rt_flags & RTF_HOST)) { > > > + if (rt && !(rt->rt_flags & RTF_LLINFO) && !(rt->rt_flags & RTF_HOST)) { > > > ip4_source = rtable_getsource(rtableid, AF_INET); > > > if (ip4_source != NULL) { > > > struct ifaddr *ifa; > > > Index: netinet/ip_input.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v > > > diff -u -p -r1.390 ip_input.c > > > --- netinet/ip_input.c 22 Feb 2024 14:25:58 -0000 1.390 > > > +++ netinet/ip_input.c 23 Feb 2024 23:58:57 -0000 > > > @@ -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 *); > > > @@ -387,14 +387,18 @@ 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; > > > - in_addr_t pfrdr = 0; > > > +#if NPF > 0 > > > + struct in_addr odst; > > > +#endif > > > + int pfrdr = 0; > > > > > > KASSERT(*offp == 0); > > > > > > + ro.ro_rt = NULL; > > > ipstat_inc(ips_total); > > > m = *mp = ipv4_check(ifp, *mp); > > > if (m == NULL) > > > @@ -412,7 +416,7 @@ ip_input_if(struct mbuf **mp, int *offp, > > > /* > > > * Packet filter > > > */ > > > - pfrdr = ip->ip_dst.s_addr; > > > + odst = ip->ip_dst; > > > if (pf_test(AF_INET, PF_IN, ifp, mp) != PF_PASS) > > > goto bad; > > > m = *mp; > > > @@ -420,7 +424,7 @@ ip_input_if(struct mbuf **mp, int *offp, > > > goto bad; > > > > > > ip = mtod(m, struct ip *); > > > - pfrdr = (pfrdr != ip->ip_dst.s_addr); > > > + pfrdr = odst.s_addr != ip->ip_dst.s_addr; > > > #endif > > > > > > hlen = ip->ip_hl << 2; > > > @@ -442,7 +446,7 @@ ip_input_if(struct mbuf **mp, int *offp, > > > goto out; > > > } > > > > > > - switch(in_ouraddr(m, ifp, &rt)) { > > > + switch(in_ouraddr(m, ifp, &ro)) { > > > case 2: > > > goto bad; > > > case 1: > > > @@ -544,14 +548,14 @@ ip_input_if(struct mbuf **mp, int *offp, > > > } > > > #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; > > > } > > > > > > @@ -748,11 +752,10 @@ ip_deliver(struct mbuf **mp, int *offp, > > > #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 > > > @@ -769,13 +772,8 @@ in_ouraddr(struct mbuf *m, struct ifnet > > > > > > 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; > > > > > > @@ -791,7 +789,6 @@ in_ouraddr(struct mbuf *m, struct ifnet > > > m->m_flags |= M_BCAST; > > > } > > > } > > > - *prt = rt; > > > > > > if (!match) { > > > struct ifaddr *ifa; > > > @@ -1470,11 +1467,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 = NULL; > > > + 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; > > > > > > @@ -1482,26 +1480,23 @@ ip_forward(struct mbuf *m, struct ifnet > > > if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) { > > > ipstat_inc(ips_cantforward); > > > m_freem(m); > > > - goto freecopy; > > > + goto done; > > > } > > > if (ip->ip_ttl <= IPTTLDEC) { > > > icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); > > > - goto freecopy; > > > + 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 > > > @@ -1552,10 +1547,10 @@ ip_forward(struct mbuf *m, struct ifnet > > > } > > > } > > > > > > - 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 { > > > @@ -1563,10 +1558,10 @@ ip_forward(struct mbuf *m, struct ifnet > > > if (type) > > > ipstat_inc(ips_redirectsent); > > > else > > > - goto freecopy; > > > + goto done; > > > } > > > if (!fake) > > > - goto freecopy; > > > + goto done; > > > > > > switch (error) { > > > case 0: /* forwarded, but need redirect */ > > > @@ -1590,7 +1585,7 @@ ip_forward(struct mbuf *m, struct ifnet > > > } > > > ipstat_inc(ips_cantfrag); > > > if (destmtu == 0) > > > - goto freecopy; > > > + goto done; > > > break; > > > > > > case EACCES: > > > @@ -1598,7 +1593,7 @@ ip_forward(struct mbuf *m, struct ifnet > > > * pf(4) blocked the packet. There is no need to send an ICMP > > > * packet back since pf(4) takes care of it. > > > */ > > > - goto freecopy; > > > + goto done; > > > > > > case ENOBUFS: > > > /* > > > @@ -1607,7 +1602,7 @@ ip_forward(struct mbuf *m, struct ifnet > > > * source quench could be a big problem under DoS attacks, > > > * or the underlying interface is rate-limited. > > > */ > > > - goto freecopy; > > > + goto done; > > > > > > case ENETUNREACH: /* shouldn't happen, checked above */ > > > case EHOSTUNREACH: > > > @@ -1622,10 +1617,11 @@ ip_forward(struct mbuf *m, struct ifnet > > > if (mcopy) > > > icmp_error(mcopy, type, code, dest, destmtu); > > > > > > -freecopy: > > > +done: > > > + if (ro == &iproute && ro->ro_rt) > > > + rtfree(ro->ro_rt); > > > if (fake) > > > m_tag_delete_chain(&mfake); > > > - rtfree(rt); > > > } > > > > > > int > > > Index: netinet/ip_var.h > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v > > > diff -u -p -r1.113 ip_var.h > > > --- netinet/ip_var.h 13 Feb 2024 12:22:09 -0000 1.113 > > > +++ netinet/ip_var.h 23 Feb 2024 18:59:54 -0000 > > > @@ -255,7 +255,7 @@ void ip_savecontrol(struct inpcb *, str > > > struct mbuf *); > > > int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *); > > > int ip_deliver(struct mbuf **, 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); > > > Index: netinet6/in6_pcb.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_pcb.c,v > > > diff -u -p -r1.139 in6_pcb.c > > > --- netinet6/in6_pcb.c 22 Feb 2024 14:25:58 -0000 1.139 > > > +++ netinet6/in6_pcb.c 23 Feb 2024 23:58:57 -0000 > > > @@ -561,16 +561,10 @@ in6_pcbnotify(struct inpcbtable *table, > > > struct rtentry * > > > in6_pcbrtentry(struct inpcb *inp) > > > { > > > - struct route *ro = &inp->inp_route; > > > - > > > if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) > > > return (NULL); > > > - if (route6_cache(ro, &inp->inp_faddr6, &inp->inp_laddr6, > > > - inp->inp_rtableid)) { > > > - ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, > > > - &inp->inp_laddr6.s6_addr32[0], ro->ro_tableid); > > > - } > > > - return (ro->ro_rt); > > > + return (route6_mpath(&inp->inp_route, &inp->inp_faddr6, > > > + &inp->inp_laddr6, inp->inp_rtableid)); > > > } > > > > > > struct inpcb * > > > Index: netinet6/in6_src.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_src.c,v > > > diff -u -p -r1.95 in6_src.c > > > --- netinet6/in6_src.c 22 Feb 2024 14:25:58 -0000 1.95 > > > +++ netinet6/in6_src.c 23 Feb 2024 23:58:57 -0000 > > > @@ -95,7 +95,7 @@ in6_pcbselsrc(const struct in6_addr **in > > > struct inpcb *inp, struct ip6_pktopts *opts) > > > { > > > struct ip6_moptions *mopts = inp->inp_moptions6; > > > - struct route *ro = &inp->inp_route; > > > + struct rtentry *rt; > > > const struct in6_addr *laddr = &inp->inp_laddr6; > > > u_int rtableid = inp->inp_rtableid; > > > struct ifnet *ifp = NULL; > > > @@ -118,7 +118,8 @@ in6_pcbselsrc(const struct in6_addr **in > > > struct sockaddr_in6 sa6; > > > > > > /* get the outgoing interface */ > > > - error = in6_selectif(dst, opts, mopts, ro, &ifp, rtableid); > > > + error = in6_selectif(dst, opts, mopts, &inp->inp_route, &ifp, > > > + rtableid); > > > if (error) > > > return (error); > > > > > > @@ -179,9 +180,7 @@ 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 (route6_cache(ro, dst, NULL, rtableid)) { > > > - ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, NULL, ro->ro_tableid); > > > - } > > > + rt = route6_mpath(&inp->inp_route, dst, NULL, rtableid); > > > > > > /* > > > * in_pcbconnect() checks out IFF_LOOPBACK to skip using > > > @@ -190,14 +189,14 @@ in6_pcbselsrc(const struct in6_addr **in > > > * so doesn't check out IFF_LOOPBACK. > > > */ > > > > > > - if (ro->ro_rt) { > > > - ifp = if_get(ro->ro_rt->rt_ifidx); > > > + if (rt != NULL) { > > > + ifp = if_get(rt->rt_ifidx); > > > if (ifp != NULL) { > > > ia6 = in6_ifawithscope(ifp, dst, rtableid); > > > if_put(ifp); > > > } > > > if (ia6 == NULL) /* xxx scope error ?*/ > > > - ia6 = ifatoia6(ro->ro_rt->rt_ifa); > > > + ia6 = ifatoia6(rt->rt_ifa); > > > } > > > > > > /* > > > @@ -206,8 +205,7 @@ in6_pcbselsrc(const struct in6_addr **in > > > * - preferred source address is set > > > * - output interface is UP > > > */ > > > - if (ro->ro_rt && !(ro->ro_rt->rt_flags & RTF_LLINFO) && > > > - !(ro->ro_rt->rt_flags & RTF_HOST)) { > > > + if (rt && !(rt->rt_flags & RTF_LLINFO) && !(rt->rt_flags & RTF_HOST)) { > > > ip6_source = rtable_getsource(rtableid, AF_INET6); > > > if (ip6_source != NULL) { > > > struct ifaddr *ifa; > > > @@ -304,11 +302,9 @@ in6_selectroute(const struct in6_addr *d > > > * a new one. > > > */ > > > if (ro) { > > > - if (route6_cache(ro, dst, NULL, rtableid)) { > > > - /* No route yet, so try to acquire one */ > > > - ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, NULL, > > > - ro->ro_tableid); > > > - } > > > + struct rtentry *rt; > > > + > > > + rt = route6_mpath(ro, dst, NULL, rtableid); > > > > > > /* > > > * Check if the outgoing interface conflicts with > > > @@ -319,15 +315,13 @@ in6_selectroute(const struct in6_addr *d > > > */ > > > if (opts && opts->ip6po_pktinfo && > > > opts->ip6po_pktinfo->ipi6_ifindex) { > > > - if (ro->ro_rt != NULL && > > > - !ISSET(ro->ro_rt->rt_flags, RTF_LOCAL) && > > > - ro->ro_rt->rt_ifidx != > > > - opts->ip6po_pktinfo->ipi6_ifindex) { > > > + if (rt != NULL && !ISSET(rt->rt_flags, RTF_LOCAL) && > > > + rt->rt_ifidx != opts->ip6po_pktinfo->ipi6_ifindex) { > > > return (NULL); > > > } > > > } > > > > > > - return (ro->ro_rt); > > > + return (rt); > > > } > > > > > > return (NULL); > > > @@ -338,7 +332,7 @@ in6_selectif(const struct in6_addr *dst, > > > struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp, > > > u_int rtableid) > > > { > > > - struct rtentry *rt = NULL; > > > + struct rtentry *rt; > > > struct in6_pktinfo *pi = NULL; > > > > > > /* If the caller specify the outgoing interface explicitly, use it. */ > > > Index: netinet6/ip6_forward.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v > > > diff -u -p -r1.115 ip6_forward.c > > > --- netinet6/ip6_forward.c 22 Feb 2024 14:25:58 -0000 1.115 > > > +++ netinet6/ip6_forward.c 23 Feb 2024 23:58:57 -0000 > > > @@ -82,14 +82,15 @@ > > > */ > > > > > > 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 = NULL; > > > + struct mbuf *mcopy; > > > #ifdef IPSEC > > > struct tdb *tdb = NULL; > > > #endif /* IPSEC */ > > > @@ -121,13 +122,13 @@ ip6_forward(struct mbuf *m, struct rtent > > > m->m_pkthdr.ph_ifidx); > > > } > > > m_freem(m); > > > - goto out; > > > + goto done; > > > } > > > > > > if (ip6->ip6_hlim <= IPV6_HLIMDEC) { > > > icmp6_error(m, ICMP6_TIME_EXCEEDED, > > > ICMP6_TIME_EXCEED_TRANSIT, 0); > > > - goto out; > > > + goto done; > > > } > > > ip6->ip6_hlim -= IPV6_HLIMDEC; > > > > > > @@ -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) { > > > - icmp6_error(mcopy, ICMP6_DST_UNREACH, > > > - ICMP6_DST_UNREACH_NOROUTE, 0); > > > - } > > > - m_freem(m); > > > - goto out; > > > + if (rt == NULL) { > > > + ip6stat_inc(ip6s_noroute); > > > + if (mcopy) { > > > + 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 > > > @@ -215,7 +213,7 @@ reroute: > > > icmp6_error(mcopy, ICMP6_DST_UNREACH, > > > ICMP6_DST_UNREACH_BEYONDSCOPE, 0); > > > m_freem(m); > > > - goto out; > > > + goto done; > > > } > > > > > > #ifdef IPSEC > > > @@ -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 > > > @@ -274,7 +272,7 @@ reroute: > > > icmp6_error(mcopy, ICMP6_DST_UNREACH, > > > ICMP6_DST_UNREACH_ADDR, 0); > > > m_freem(m); > > > - goto out; > > > + goto done; > > > } > > > type = ND_REDIRECT; > > > } > > > @@ -308,8 +306,7 @@ 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; > > > + ro = NULL; > > > if_put(ifp); > > > ifp = NULL; > > > goto reroute; > > > @@ -324,21 +321,21 @@ reroute: > > > if (error || m == NULL) > > > goto senderr; > > > > > > - if (mcopy != NULL) > > > + if (mcopy) > > > icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu); > > > m_freem(m); > > > - goto out; > > > + goto done; > > > > > > senderr: > > > if (mcopy == NULL) > > > - goto out; > > > + goto done; > > > > > > switch (error) { > > > case 0: > > > if (type == ND_REDIRECT) { > > > icmp6_redirect_output(mcopy, rt); > > > ip6stat_inc(ip6s_redirectsent); > > > - goto out; > > > + goto done; > > > } > > > goto freecopy; > > > > > > @@ -383,12 +380,13 @@ senderr: > > > break; > > > } > > > icmp6_error(mcopy, type, code, destmtu); > > > - goto out; > > > + goto done; > > > > > > freecopy: > > > m_freem(mcopy); > > > -out: > > > - rtfree(rt); > > > +done: > > > + if (ro == &iproute && ro->ro_rt) > > > + rtfree(ro->ro_rt); > > > if_put(ifp); > > > #ifdef IPSEC > > > tdb_unref(tdb); > > > Index: netinet6/ip6_input.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v > > > diff -u -p -r1.258 ip6_input.c > > > --- netinet6/ip6_input.c 22 Feb 2024 14:25:58 -0000 1.258 > > > +++ netinet6/ip6_input.c 23 Feb 2024 23:58:57 -0000 > > > @@ -357,21 +357,21 @@ 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 > > > struct in6_addr odst; > > > #endif > > > - int srcrt = 0; > > > + int pfrdr = 0; > > > > > > KASSERT(*offp == 0); > > > > > > + ro.ro_rt = NULL; > > > ip6stat_inc(ip6s_total); > > > - > > > m = *mp = ipv6_check(ifp, *mp); > > > if (m == NULL) > > > goto bad; > > > @@ -413,7 +413,7 @@ ip6_input_if(struct mbuf **mp, int *offp > > > goto bad; > > > > > > ip6 = mtod(m, struct ip6_hdr *); > > > - srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); > > > + pfrdr = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); > > > #endif > > > > > > /* > > > @@ -517,18 +517,14 @@ ip6_input_if(struct mbuf **mp, int *offp > > > /* > > > * 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 && > > > @@ -618,14 +614,14 @@ ip6_input_if(struct mbuf **mp, int *offp > > > } > > > #endif /* IPSEC */ > > > > > > - ip6_forward(m, rt, srcrt); > > > + 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; > > > } > > > > > > Index: netinet6/ip6_output.c > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v > > > diff -u -p -r1.287 ip6_output.c > > > --- netinet6/ip6_output.c 22 Feb 2024 14:25:58 -0000 1.287 > > > +++ netinet6/ip6_output.c 23 Feb 2024 23:58:57 -0000 > > > @@ -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) > > > @@ -748,7 +748,15 @@ reroute: > > > (error = if_output_ml(ifp, &ml, sin6tosa(dst), ro->ro_rt))) > > > goto done; > > > ip6stat_inc(ip6s_fragmented); > > > + goto done; > > > > > > +freehdrs: > > > + m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */ > > > + m_freem(exthdrs.ip6e_dest1); > > > + m_freem(exthdrs.ip6e_rthdr); > > > + m_freem(exthdrs.ip6e_dest2); > > > +bad: > > > + m_freem(m); > > > done: > > > if (ro == &iproute && ro->ro_rt) { > > > rtfree(ro->ro_rt); > > > @@ -760,16 +768,6 @@ done: > > > tdb_unref(tdb); > > > #endif /* IPSEC */ > > > return (error); > > > - > > > -freehdrs: > > > - m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */ > > > - m_freem(exthdrs.ip6e_dest1); > > > - m_freem(exthdrs.ip6e_rthdr); > > > - m_freem(exthdrs.ip6e_dest2); > > > - /* FALLTHROUGH */ > > > -bad: > > > - m_freem(m); > > > - goto done; > > > } > > > > > > int > > > Index: netinet6/ip6_var.h > > > =================================================================== > > > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_var.h,v > > > diff -u -p -r1.114 ip6_var.h > > > --- netinet6/ip6_var.h 14 Feb 2024 13:18:21 -0000 1.114 > > > +++ netinet6/ip6_var.h 23 Feb 2024 23:21:02 -0000 > > > @@ -320,7 +320,7 @@ int ip6_process_hopopts(struct mbuf **, > > > 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, > > > > > > > -- > > :wq Claudio > -- :wq Claudio