This follows the direction of IPv4.  The idea is to stop using a single
cache entry and continue the cleanup to be able to cache route entries
in PF state keys.

Since we're no longer using a single cache entry the destination &
rtableid checks become obsolete.

As for IPv4 the rule I'm trying to follow is that if you pass a 'struct
rtentry *' to a function, this function is responsible for freeing it.

Ok?

Index: net/pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.189
diff -u -p -r1.189 pf_norm.c
--- net/pf_norm.c       17 Aug 2016 03:24:12 -0000      1.189
+++ net/pf_norm.c       22 Aug 2016 12:35:52 -0000
@@ -759,7 +759,7 @@ pf_refragment6(struct mbuf **m0, struct 
                m->m_pkthdr.pf.flags |= PF_TAG_REFRAGMENTED;
                if (error == 0) {
                        if (ifp == NULL) {
-                               ip6_forward(m, 0);
+                               ip6_forward(m, NULL, 0);
                        } else if ((u_long)m->m_pkthdr.len <= ifp->if_mtu) {
                                ifp->if_output(ifp, m, sin6tosa(dst), rt);
                        } else {
Index: netinet6/frag6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/frag6.c,v
retrieving revision 1.68
diff -u -p -r1.68 frag6.c
--- netinet6/frag6.c    22 Aug 2016 10:33:22 -0000      1.68
+++ netinet6/frag6.c    22 Aug 2016 12:35:52 -0000
@@ -596,9 +596,9 @@ void
 frag6_slowtimo(void)
 {
        struct ip6q *q6, *nq6;
-       int s = splsoftnet();
-       extern struct route_in6 ip6_forward_rt;
+       int s;
 
+       s = splsoftnet();
        IP6Q_LOCK();
        TAILQ_FOREACH_SAFE(q6, &frag6_queue, ip6q_queue, nq6)
                if (--q6->ip6q_ttl == 0) {
@@ -617,17 +617,6 @@ frag6_slowtimo(void)
                frag6_freef(TAILQ_LAST(&frag6_queue, ip6q_head));
        }
        IP6Q_UNLOCK();
-
-       /*
-        * Routing changes might produce a better route than we last used;
-        * make sure we notice eventually, even if forwarding only for one
-        * destination and the cache is never replaced.
-        */
-       if (ip6_forward_rt.ro_rt) {
-               rtfree(ip6_forward_rt.ro_rt);
-               ip6_forward_rt.ro_rt = NULL;
-       }
-
        splx(s);
 }
 
Index: netinet6/ip6_forward.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v
retrieving revision 1.91
diff -u -p -r1.91 ip6_forward.c
--- netinet6/ip6_forward.c      15 Jun 2016 11:49:34 -0000      1.91
+++ netinet6/ip6_forward.c      22 Aug 2016 12:35:52 -0000
@@ -68,8 +68,6 @@
 #include <netinet/tcp.h>
 #endif
 
-struct route_in6 ip6_forward_rt;
-
 /*
  * Forward a packet.  If some error occurs return the sender
  * an icmp packet.  Note we can't always generate a meaningful
@@ -84,18 +82,16 @@ struct      route_in6 ip6_forward_rt;
  */
 
 void
-ip6_forward(struct mbuf *m, int srcrt)
+ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt)
 {
        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
-       struct sockaddr_in6 *dst;
-       struct rtentry *rt;
+       struct sockaddr_in6 *dst, sin6;
        struct ifnet *ifp = NULL;
        int error = 0, type = 0, code = 0;
        struct mbuf *mcopy = NULL;
 #ifdef IPSEC
        struct tdb *tdb = NULL;
 #endif /* IPSEC */
-       u_int rtableid = 0;
        char src6[INET6_ADDRSTRLEN], dst6[INET6_ADDRSTRLEN];
 
        /*
@@ -120,13 +116,13 @@ ip6_forward(struct mbuf *m, int srcrt)
                            m->m_pkthdr.ph_ifidx);
                }
                m_freem(m);
-               return;
+               goto out;
        }
 
        if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
                icmp6_error(m, ICMP6_TIME_EXCEEDED,
                                ICMP6_TIME_EXCEED_TRANSIT, 0);
-               return;
+               goto out;
        }
        ip6->ip6_hlim -= IPV6_HLIMDEC;
 
@@ -164,40 +160,26 @@ reroute:
        }
 #endif /* IPSEC */
 
-#if NPF > 0
-       rtableid = m->m_pkthdr.ph_rtableid;
-#endif
-
-       dst = &ip6_forward_rt.ro_dst;
-       if (!rtisvalid(ip6_forward_rt.ro_rt) ||
-          ISSET(ip6_forward_rt.ro_rt->rt_flags, RTF_MPATH) ||
-          !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr) ||
-          ip6_forward_rt.ro_tableid != rtableid) {
-               if (ip6_forward_rt.ro_rt) {
-                       rtfree(ip6_forward_rt.ro_rt);
-                       ip6_forward_rt.ro_rt = NULL;
-               }
-               bzero(dst, sizeof(*dst));
-               dst->sin6_len = sizeof(struct sockaddr_in6);
-               dst->sin6_family = AF_INET6;
-               dst->sin6_addr = ip6->ip6_dst;
-               ip6_forward_rt.ro_tableid = rtableid;
-               ip6_forward_rt.ro_rt = rtalloc_mpath(
-                   sin6tosa(&ip6_forward_rt.ro_dst),
-                   &ip6->ip6_src.s6_addr32[0],
-                   ip6_forward_rt.ro_tableid);
-
-               if (ip6_forward_rt.ro_rt == NULL) {
+       dst = &sin6;
+       memset(dst, 0, sizeof(*dst));
+       dst->sin6_len = sizeof(struct sockaddr_in6);
+       dst->sin6_family = AF_INET6;
+       dst->sin6_addr = ip6->ip6_dst;
+
+       if (!rtisvalid(rt)) {
+               rtfree(rt);
+               rt = rtalloc_mpath(sin6tosa(dst), &ip6->ip6_src.s6_addr32[0],
+                   m->m_pkthdr.ph_rtableid);
+               if (rt == NULL) {
                        ip6stat.ip6s_noroute++;
                        if (mcopy) {
                                icmp6_error(mcopy, ICMP6_DST_UNREACH,
                                            ICMP6_DST_UNREACH_NOROUTE, 0);
                        }
                        m_freem(m);
-                       return;
+                       goto out;
                }
        }
-       rt = ip6_forward_rt.ro_rt;
 
        /*
         * Scope check: if a packet can't be delivered to its destination
@@ -262,7 +244,7 @@ reroute:
            ip6_sendredirects &&
            (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
                if ((ifp->if_flags & IFF_POINTOPOINT) &&
-                   nd6_is_addr_neighbor(&ip6_forward_rt.ro_dst, ifp)) {
+                   nd6_is_addr_neighbor(&sin6, ifp)) {
                        /*
                         * If the incoming interface is equal to the outgoing
                         * one, the link attached to the interface is
@@ -381,5 +363,6 @@ senderr:
 freecopy:
        m_freem(mcopy);
 out:
+       rtfree(rt);
        if_put(ifp);
 }
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.167
diff -u -p -r1.167 ip6_input.c
--- netinet6/ip6_input.c        19 Jul 2016 15:57:13 -0000      1.167
+++ netinet6/ip6_input.c        22 Aug 2016 12:35:52 -0000
@@ -184,13 +184,13 @@ ip6intr(void)
                ip6_input(m);
 }
 
-extern struct  route_in6 ip6_forward_rt;
-
 void
 ip6_input(struct mbuf *m)
 {
        struct ifnet *ifp;
        struct ip6_hdr *ip6;
+       struct sockaddr_in6 sin6;
+       struct rtentry *rt = NULL;
        int off, nest;
        u_int16_t src_scope, dst_scope;
        int nxt, ours = 0;
@@ -414,43 +414,23 @@ ip6_input(struct mbuf *m)
                goto hbhcheck;
        }
 
+
        /*
         *  Unicast check
         */
-       if (rtisvalid(ip6_forward_rt.ro_rt) &&
-           !ISSET(ip6_forward_rt.ro_rt->rt_flags, RTF_MPATH) &&
-           IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
-                              &ip6_forward_rt.ro_dst.sin6_addr) &&
-           m->m_pkthdr.ph_rtableid == ip6_forward_rt.ro_tableid)
-               ip6stat.ip6s_forward_cachehit++;
-       else {
-               if (ip6_forward_rt.ro_rt) {
-                       /* route is down or destination is different */
-                       ip6stat.ip6s_forward_cachemiss++;
-                       rtfree(ip6_forward_rt.ro_rt);
-                       ip6_forward_rt.ro_rt = NULL;
-               }
-
-               bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
-               ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
-               ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
-               ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
-               ip6_forward_rt.ro_tableid = m->m_pkthdr.ph_rtableid;
-
-               ip6_forward_rt.ro_rt = rtalloc_mpath(
-                   sin6tosa(&ip6_forward_rt.ro_dst),
-                   &ip6->ip6_src.s6_addr32[0],
-                   ip6_forward_rt.ro_tableid);
-       }
+       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],
+           m->m_pkthdr.ph_rtableid);
 
        /*
         * Accept the packet if the route to the destination is marked
         * as local.
         */
-       if (rtisvalid(ip6_forward_rt.ro_rt) &&
-           ISSET(ip6_forward_rt.ro_rt->rt_flags, RTF_LOCAL)) {
-               struct in6_ifaddr *ia6 =
-                       ifatoia6(ip6_forward_rt.ro_rt->rt_ifa);
+       if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL)) {
+               struct in6_ifaddr *ia6 = ifatoia6(rt->rt_ifa);
                if (ia6->ia6_flags & IN6_IFF_ANYCAST)
                        m->m_flags |= M_ACAST;
                /*
@@ -493,6 +473,7 @@ ip6_input(struct mbuf *m)
   hbhcheck:
 
        if (ip6_hbhchcheck(m, &off, &nxt, &ours)) {
+               rtfree(rt);
                if_put(ifp);
                return; /* m have already been freed */
        }
@@ -522,7 +503,7 @@ ip6_input(struct mbuf *m)
                if (!ours)
                        goto bad;
        } else if (!ours) {
-               ip6_forward(m, srcrt);
+               ip6_forward(m, rt, srcrt);
                if_put(ifp);
                return;
        }
@@ -566,9 +547,11 @@ ip6_input(struct mbuf *m)
 
                nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
        }
+       rtfree(rt);
        if_put(ifp);
        return;
  bad:
+       rtfree(rt);
        if_put(ifp);
        m_freem(m);
 }
Index: netinet6/ip6_var.h
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
retrieving revision 1.63
diff -u -p -r1.63 ip6_var.h
--- netinet6/ip6_var.h  4 Aug 2016 20:46:24 -0000       1.63
+++ netinet6/ip6_var.h  22 Aug 2016 12:35:52 -0000
@@ -258,7 +258,7 @@ int ip6_process_hopopts(struct mbuf *, u
 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 *, int);
+void   ip6_forward(struct mbuf *, struct rtentry *, int);
 
 void   ip6_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in6 *);
 int    ip6_output(struct mbuf *, struct ip6_pktopts *, struct route_in6 *, int,

Reply via email to