On 23/05/16(Mon) 15:59, Alexander Bluhm wrote:
> On Mon, May 23, 2016 at 02:47:02PM +0200, Martin Pieuchot wrote:
> > @@ -750,7 +750,15 @@ pf_refragment6(struct mbuf **m0, struct 
> >                     if (ifp == NULL) {
> >                             ip6_forward(m, 0);
> >                     } else if ((u_long)m->m_pkthdr.len <= ifp->if_mtu) {
> > -                           nd6_output(ifp, m, dst, NULL);
> > +                           struct rtentry *rt;
> > +                           rt = rtalloc(sin6tosa(dst), RT_RESOLVE,
> > +                               m->m_pkthdr.ph_rtableid);
> 
> Should we place the rtalloc() outside of the loop and use the same
> route or all fragments?

That would be a performance improvement!

> > @@ -1507,20 +1507,15 @@ nd6_output(struct ifnet *ifp, struct mbu
> >     struct mbuf *m = m0;
> >     struct rtentry *rt = rt0;
> >     struct llinfo_nd6 *ln = NULL;
> > -   int created = 0, error = 0;
> > +   int error = 0;
> >  
> >     if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
> >             goto sendpkt;
> 
> No kassert rt0 != NULL in here in nd6_output() ?

nop because next step is to merge nd6_output() and nd6_storelladdr()
into nd6_resolve() and match the behavior of arpresolve().  So the
KASSERT() in ether_output() should be enough.

Index: net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.971
diff -u -p -r1.971 pf.c
--- net/pf.c    23 May 2016 12:26:28 -0000      1.971
+++ net/pf.c    23 May 2016 14:43:19 -0000
@@ -5665,11 +5665,13 @@ pf_route6(struct mbuf **m, struct pf_rul
 {
        struct mbuf             *m0;
        struct sockaddr_in6     *dst, sin6;
+       struct rtentry          *rt = NULL;
        struct ip6_hdr          *ip6;
        struct ifnet            *ifp = NULL;
        struct pf_addr           naddr;
        struct pf_src_node      *sns[PF_SN_MAX];
        struct m_tag            *mtag;
+       unsigned int             rtableid;
 
        if (m == NULL || *m == NULL || r == NULL ||
            (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
@@ -5702,6 +5704,7 @@ pf_route6(struct mbuf **m, struct pf_rul
        dst->sin6_family = AF_INET6;
        dst->sin6_len = sizeof(*dst);
        dst->sin6_addr = ip6->ip6_dst;
+       rtableid = m0->m_pkthdr.ph_rtableid;
 
        if (!r->rt) {
                m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
@@ -5754,7 +5757,13 @@ pf_route6(struct mbuf **m, struct pf_rul
        if ((mtag = m_tag_find(m0, PACKET_TAG_PF_REASSEMBLED, NULL))) {
                (void) pf_refragment6(&m0, mtag, dst, ifp);
        } else if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
-               nd6_output(ifp, m0, dst, NULL);
+               rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid);
+               if (rt == NULL) {
+                       ip6stat.ip6s_noroute++;
+                       goto bad;
+               }
+               nd6_output(ifp, m0, dst, rt);
+               rtfree(rt);
        } else {
                icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
        }
Index: net/pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.183
diff -u -p -r1.183 pf_norm.c
--- net/pf_norm.c       24 Nov 2015 13:37:16 -0000      1.183
+++ net/pf_norm.c       23 May 2016 14:48:01 -0000
@@ -687,6 +687,7 @@ pf_refragment6(struct mbuf **m0, struct 
 {
        struct mbuf             *m = *m0, *t;
        struct pf_fragment_tag  *ftag = (struct pf_fragment_tag *)(mtag + 1);
+       struct rtentry          *rt = NULL;
        u_int32_t                mtu;
        u_int16_t                hdrlen, extoff, maxlen;
        u_int8_t                 proto;
@@ -742,6 +743,16 @@ pf_refragment6(struct mbuf **m0, struct 
                DPFPRINTF(LOG_NOTICE, "refragment error %d", error);
                action = PF_DROP;
        }
+
+       if (ifp == NULL) {
+               rt = rtalloc(sin6tosa(dst), RT_RESOLVE,
+                   m->m_pkthdr.ph_rtableid);
+               if (rt == NULL) {
+                       ip6stat.ip6s_noroute++;
+                       error = -1;
+               }
+       }
+
        for (t = m; m; m = t) {
                t = m->m_nextpkt;
                m->m_nextpkt = NULL;
@@ -750,7 +761,7 @@ pf_refragment6(struct mbuf **m0, struct 
                        if (ifp == NULL) {
                                ip6_forward(m, 0);
                        } else if ((u_long)m->m_pkthdr.len <= ifp->if_mtu) {
-                               nd6_output(ifp, m, dst, NULL);
+                               nd6_output(ifp, m, dst, rt);
                        } else {
                                icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0,
                                    ifp->if_mtu);
@@ -759,6 +770,7 @@ pf_refragment6(struct mbuf **m0, struct 
                        m_freem(m);
                }
        }
+       rtfree(rt);
 
        return (action);
 }
Index: netinet6/nd6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6.c,v
retrieving revision 1.179
diff -u -p -r1.179 nd6.c
--- netinet6/nd6.c      17 May 2016 08:29:14 -0000      1.179
+++ netinet6/nd6.c      23 May 2016 12:38:56 -0000
@@ -1507,20 +1507,15 @@ nd6_output(struct ifnet *ifp, struct mbu
        struct mbuf *m = m0;
        struct rtentry *rt = rt0;
        struct llinfo_nd6 *ln = NULL;
-       int created = 0, error = 0;
+       int error = 0;
 
        if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
                goto sendpkt;
 
-       /*
-        * next hop determination.
-        */
-       if (rt0 != NULL) {
-               error = rt_checkgate(rt0, &rt);
-               if (error) {
-                       m_freem(m);
-                       return (error);
-               }
+       error = rt_checkgate(rt0, &rt);
+       if (error) {
+               m_freem(m);
+               return (error);
        }
 
        if (nd6_need_cache(ifp) == 0)
@@ -1532,42 +1527,17 @@ nd6_output(struct ifnet *ifp, struct mbu
         * At this point, the destination of the packet must be a unicast
         * or an anycast address(i.e. not a multicast).
         */
-
-       /* Look up the neighbor cache for the nexthop */
-       if (rt != NULL && (rt->rt_flags & RTF_LLINFO) != 0)
-               ln = (struct llinfo_nd6 *)rt->rt_llinfo;
-       else {
-               /*
-                * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
-                * the condition below is not very efficient.  But we believe
-                * it is tolerable, because this should be a rare case.
-                */
-               if (nd6_is_addr_neighbor(dst, ifp)) {
-                       rt = nd6_lookup(&dst->sin6_addr, 1, ifp,
-                           ifp->if_rdomain);
-                       if (rt != NULL) {
-                               created = 1;
-                               ln = (struct llinfo_nd6 *)rt->rt_llinfo;
-                       }
-               }
+       if (!ISSET(rt->rt_flags, RTF_LLINFO)) {
+               char addr[INET6_ADDRSTRLEN];
+               log(LOG_DEBUG, "%s: %s: route contains no ND information\n",
+                   __func__, inet_ntop(AF_INET6,
+                   &satosin6(rt_key(rt))->sin6_addr, addr, sizeof(addr)));
+               m_freem(m);
+               return (EINVAL);
        }
-       if (ln == NULL || rt == NULL) {
-               if ((ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD) == 0) {
-                       char addr[INET6_ADDRSTRLEN];
-
-                       log(LOG_DEBUG, "%s: can't allocate llinfo for %s "
-                           "(ln=%p, rt=%p)\n", __func__,
-                           inet_ntop(AF_INET6, &dst->sin6_addr,
-                               addr, sizeof(addr)),
-                           ln, rt);
-                       m_freem(m);
-                       if (created)
-                               rtfree(rt);
-                       return (EIO);   /* XXX: good error? */
-               }
 
-               goto sendpkt;   /* send anyway */
-       }
+       ln = (struct llinfo_nd6 *)rt->rt_llinfo;
+       KASSERT(ln != NULL);
 
        /*
         * Move this entry to the head of the queue so that it is less likely
@@ -1617,14 +1587,10 @@ nd6_output(struct ifnet *ifp, struct mbu
                    (long)ND_IFINFO(ifp)->retrans * hz / 1000);
                nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
        }
-       if (created)
-               rtfree(rt);
        return (0);
 
   sendpkt:
        error = ifp->if_output(ifp, m, sin6tosa(dst), rt);
-       if (created)
-               rtfree(rt);
        return (error);
 }
 
@@ -1665,12 +1631,6 @@ nd6_storelladdr(struct ifnet *ifp, struc
                        m_freem(m);
                        return (EINVAL);
                }
-       }
-
-       if (rt0 == NULL) {
-               /* this could happen, if we could not allocate memory */
-               m_freem(m);
-               return (ENOMEM);
        }
 
        error = rt_checkgate(rt0, &rt);

Reply via email to