From: Alexander Bluhm Subject: Re: route cache mpath To: tech@openbsd.org Date: Mon, 26 Feb 2024 15:51:37 +0100 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? 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. > > 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