Download raw body.
use struct route in ip input
On Tue, Apr 16, 2024 at 12:02:10AM +0200, Alexander Bluhm wrote:
> On Tue, Apr 09, 2024 at 03:58:05PM +0200, Alexander Bluhm wrote:
> > Hi,
> >
> > 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 with this diff.
> >
> > There is a small difference in the code. in_ouraddr() checks for
> > NULL and not rtisvalid(). Previous discussion showed that the route
> > UP flag should only be considered for multipath routing. Otherwise
> > it does not mean anything. Especially the local and broadcast check
> > should not be affected by interface link status.
> >
> > When doing cache lookups route must be valid, but after rtalloc_mpath()
> > lookup, we use any route we get.
> >
> > ok?
> >
> > bluhm
>
> Anyone?
OK claudio@.
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
> diff -u -p -r1.392 ip_input.c
> --- netinet/ip_input.c 14 Apr 2024 20:46:27 -0000 1.392
> +++ netinet/ip_input.c 15 Apr 2024 21:59:44 -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 *);
> @@ -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,
>
> 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,
> 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,
> }
> #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,
> #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
>
> 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
> 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
> 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
> }
> }
>
> - 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
> 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
> Index: netinet/ip_var.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v
> diff -u -p -r1.115 ip_var.h
> --- netinet/ip_var.h 14 Apr 2024 20:46:27 -0000 1.115
> +++ netinet/ip_var.h 15 Apr 2024 21:59:44 -0000
> @@ -260,7 +260,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, 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/ip6_forward.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v
> diff -u -p -r1.116 ip6_forward.c
> --- netinet6/ip6_forward.c 28 Feb 2024 10:57:20 -0000 1.116
> +++ netinet6/ip6_forward.c 15 Apr 2024 21:59:44 -0000
> @@ -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);
> Index: netinet6/ip6_input.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v
> diff -u -p -r1.260 ip6_input.c
> --- netinet6/ip6_input.c 14 Apr 2024 20:46:27 -0000 1.260
> +++ netinet6/ip6_input.c 15 Apr 2024 21:59:44 -0000
> @@ -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
>
> 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
> /*
> * 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
> }
> #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;
> }
>
> Index: netinet6/ip6_output.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
> diff -u -p -r1.289 ip6_output.c
> --- netinet6/ip6_output.c 9 Apr 2024 11:05:05 -0000 1.289
> +++ netinet6/ip6_output.c 15 Apr 2024 21:59:44 -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)
> 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 15 Apr 2024 21:59:44 -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
use struct route in ip input