Use the route generation number also for IPv6.
authorbluhm <bluhm@openbsd.org>
Wed, 7 Feb 2024 23:40:40 +0000 (23:40 +0000)
committerbluhm <bluhm@openbsd.org>
Wed, 7 Feb 2024 23:40:40 +0000 (23:40 +0000)
Implement route6_cache() to check whether the cached route is still
valid and otherwise fill caching parameter of struct route_in6.
Also count cache hits and misses in netstat.  in_pcbrtentry() uses
route cache now.

OK claudio@

sys/net/route.c
sys/netinet/in_pcb.c
sys/netinet6/in6.h
sys/netinet6/in6_pcb.c
sys/netinet6/in6_src.c
sys/netinet6/ip6_forward.c
sys/netinet6/ip6_output.c
sys/netinet6/ip6_var.h

index adb3719..5a6f7aa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: route.c,v 1.428 2024/02/05 23:16:39 bluhm Exp $       */
+/*     $OpenBSD: route.c,v 1.429 2024/02/07 23:40:40 bluhm Exp $       */
 /*     $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $      */
 
 /*
@@ -230,6 +230,36 @@ route_cache(struct route *ro, struct in_addr addr, u_int rtableid)
        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)) {
+               ip6stat_inc(ip6s_rtcachehit);
+               return;
+       }
+
+       ip6stat_inc(ip6s_rtcachemiss);
+       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 fd6417e..456135a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_pcb.c,v 1.289 2024/02/02 15:39:23 bluhm Exp $      */
+/*     $OpenBSD: in_pcb.c,v 1.290 2024/02/07 23:40:40 bluhm Exp $      */
 /*     $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $     */
 
 /*
@@ -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 909166c..771f26c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6.h,v 1.113 2024/01/31 14:56:43 bluhm Exp $ */
+/*     $OpenBSD: in6.h,v 1.114 2024/02/07 23:40:40 bluhm Exp $ */
 /*     $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $    */
 
 /*
@@ -428,6 +428,8 @@ int in6_mask2len(struct in6_addr *, u_char *);
 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 d447beb..0be0c45 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6_pcb.c,v 1.134 2024/01/31 12:27:57 bluhm Exp $     */
+/*     $OpenBSD: in6_pcb.c,v 1.135 2024/02/07 23:40:40 bluhm Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -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 2c989ec..78205a0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6_src.c,v 1.91 2024/01/09 19:57:01 bluhm Exp $      */
+/*     $OpenBSD: in6_src.c,v 1.92 2024/02/07 23:40:40 bluhm Exp $      */
 /*     $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $        */
 
 /*
@@ -82,7 +82,7 @@
 #include <netinet6/ip6_var.h>
 #include <netinet6/nd6.h>
 
-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 **in6src, struct sockaddr_in6 *dstsock,
                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 **in6src, struct sockaddr_in6 *dstsock,
         * 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 **in6src, struct sockaddr_in6 *dstsock,
 }
 
 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 *dstsock, struct ip6_pktopts *opts,
 }
 
 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 *dstsock, struct ip6_pktopts *opts,
         * 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 7de1e0e..54b7615 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_forward.c,v 1.112 2023/07/07 08:05:02 bluhm Exp $ */
+/*     $OpenBSD: ip6_forward.c,v 1.113 2024/02/07 23:40:40 bluhm Exp $ */
 /*     $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $    */
 
 /*
@@ -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 f3da197..3efd261 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_output.c,v 1.284 2024/01/31 12:27:57 bluhm Exp $  */
+/*     $OpenBSD: ip6_output.c,v 1.285 2024/02/07 23:40:40 bluhm Exp $  */
 /*     $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $    */
 
 /*
@@ -169,7 +169,7 @@ ip6_output(struct mbuf *m, struct ip6_pktopts *opt, struct route_in6 *ro,
        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 06d6ce7..f23287b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_var.h,v 1.111 2024/02/05 23:16:39 bluhm Exp $     */
+/*     $OpenBSD: ip6_var.h,v 1.112 2024/02/07 23:40:40 bluhm Exp $     */
 /*     $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $        */
 
 /*
@@ -369,7 +369,7 @@ int in6_pcbselsrc(const struct in6_addr **, struct sockaddr_in6 *,
            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);