On Mon, Aug 22, 2016 at 01:50:53PM +0200, Martin Pieuchot wrote:
> Diff below replace in6_selectsrc() by rtalloc(9) for source address
> selection when send NS and NA.

OK bluhm@

> While this can be a controversial change, it's the only way I found to
> move forward to change the existing route caching mechanism.  My goal
> is to stop passing a 'struct route{_in6}' to ip{,6}_output() and only
> give it a *valid* 'struct rtentry'.  But since too many code paths
> currently use a 'struct route{,_in6}', I'm doing small steps.
> 
> That means that we're going to do 2 route lookups per NS/NA packets
> until ip6_output() is changed to take a 'struct rtentry'.  That's fine
> since such packets are not sent too often.
> 
> Index: netinet6/nd6_nbr.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v
> retrieving revision 1.109
> diff -u -p -r1.109 nd6_nbr.c
> --- netinet6/nd6_nbr.c        22 Aug 2016 10:33:22 -0000      1.109
> +++ netinet6/nd6_nbr.c        22 Aug 2016 11:35:40 -0000
> @@ -368,10 +368,6 @@ nd6_ns_output(struct ifnet *ifp, struct 
>       int icmp6len;
>       int maxlen;
>       caddr_t mac;
> -     struct route_in6 ro;
> -
> -     bzero(&ro, sizeof(ro));
> -     ro.ro_tableid = ifp->if_rdomain;
>  
>       if (IN6_IS_ADDR_MULTICAST(taddr6))
>               return;
> @@ -467,24 +463,23 @@ nd6_ns_output(struct ifnet *ifp, struct 
>               if (saddr6 && in6ifa_ifpwithaddr(ifp, saddr6))
>                       src_sa.sin6_addr = *saddr6;
>               else {
> -                     struct in6_addr *src0;
> -                     int error;
> +                     struct rtentry *rt;
>  
> -                     bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
> -                     error = in6_selectsrc(&src0, &dst_sa, NULL, &ro,
> +                     rt = rtalloc(sin6tosa(&dst_sa), RT_RESOLVE,
>                           m->m_pkthdr.ph_rtableid);
> -                     if (error) {
> +                     if (!rtisvalid(rt)) {
>                               char addr[INET6_ADDRSTRLEN];
>  
>                               nd6log((LOG_DEBUG,
> -                                 "nd6_ns_output: source can't be "
> -                                 "determined: dst=%s, error=%d\n",
> -                                 inet_ntop(AF_INET6, &dst_sa.sin6_addr,
> -                                     addr, sizeof(addr)),
> -                                 error));
> +                                 "%s: source can't be determined: dst=%s\n",
> +                                 __func__, inet_ntop(AF_INET6,
> +                                 &dst_sa.sin6_addr, addr, sizeof(addr))));
> +                             rtfree(rt);
>                               goto bad;
>                       }
> -                     src_sa.sin6_addr = *src0;
> +                     src_sa.sin6_addr =
> +                         ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr;
> +                     rtfree(rt);
>               }
>       } else {
>               /*
> @@ -537,20 +532,12 @@ nd6_ns_output(struct ifnet *ifp, struct 
>       nd_ns->nd_ns_cksum = 0;
>       m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
>  
> -     ip6_output(m, NULL, &ro, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL);
> +     ip6_output(m, NULL, NULL, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL);
>       icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
> -
> -     if (ro.ro_rt) {         /* we don't cache this route. */
> -             rtfree(ro.ro_rt);
> -     }
>       return;
>  
>    bad:
> -     if (ro.ro_rt) {
> -             rtfree(ro.ro_rt);
> -     }
>       m_freem(m);
> -     return;
>  }
>  
>  /*
> @@ -913,18 +900,13 @@ nd6_na_output(struct ifnet *ifp, struct 
>      struct sockaddr *sdl0)
>  {
>       struct mbuf *m;
> +     struct rtentry *rt = NULL;
>       struct ip6_hdr *ip6;
>       struct nd_neighbor_advert *nd_na;
>       struct ip6_moptions im6o;
> -     struct sockaddr_in6 src_sa, dst_sa;
> -     struct in6_addr *src0;
> -     int icmp6len, maxlen, error;
> -     caddr_t mac;
> -     struct route_in6 ro;
> -
> -     mac = NULL;
> -     bzero(&ro, sizeof(ro));
> -     ro.ro_tableid = ifp->if_rdomain;
> +     struct sockaddr_in6 dst_sa;
> +     int icmp6len, maxlen;
> +     caddr_t mac = NULL;
>  
>       /* estimate the size of message */
>       maxlen = sizeof(*ip6) + sizeof(*nd_na);
> @@ -969,10 +951,9 @@ nd6_na_output(struct ifnet *ifp, struct 
>       ip6->ip6_vfc |= IPV6_VERSION;
>       ip6->ip6_nxt = IPPROTO_ICMPV6;
>       ip6->ip6_hlim = 255;
> -     bzero(&src_sa, sizeof(src_sa));
>       bzero(&dst_sa, sizeof(dst_sa));
> -     src_sa.sin6_len = dst_sa.sin6_len = sizeof(struct sockaddr_in6);
> -     src_sa.sin6_family = dst_sa.sin6_family = AF_INET6;
> +     dst_sa.sin6_len = sizeof(struct sockaddr_in6);
> +     dst_sa.sin6_family = AF_INET6;
>       dst_sa.sin6_addr = *daddr6;
>       if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) {
>               /* reply to DAD */
> @@ -989,20 +970,18 @@ nd6_na_output(struct ifnet *ifp, struct 
>       /*
>        * Select a source whose scope is the same as that of the dest.
>        */
> -     bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
> -     error = in6_selectsrc(&src0, &dst_sa, NULL, &ro,
> -         m->m_pkthdr.ph_rtableid);
> -     if (error) {
> +     rt = rtalloc(sin6tosa(&dst_sa), RT_RESOLVE, ifp->if_rdomain);
> +     if (!rtisvalid(rt)) {
>               char addr[INET6_ADDRSTRLEN];
>  
> -             nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
> -                 "determined: dst=%s, error=%d\n",
> -                 inet_ntop(AF_INET6, &dst_sa.sin6_addr, addr, sizeof(addr)),
> -                 error));
> +             nd6log((LOG_DEBUG, "%s: source can't be determined: dst=%s\n",
> +                 __func__, inet_ntop(AF_INET6, &dst_sa.sin6_addr, addr,
> +                 sizeof(addr))));
> +             rtfree(rt);
>               goto bad;
>       }
> -     src_sa.sin6_addr = *src0;
> -     ip6->ip6_src = src_sa.sin6_addr;
> +     ip6->ip6_src = ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr;
> +     rtfree(rt);
>       nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
>       nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
>       nd_na->nd_na_code = 0;
> @@ -1059,20 +1038,12 @@ nd6_na_output(struct ifnet *ifp, struct 
>       nd_na->nd_na_cksum = 0;
>       m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
>  
> -     ip6_output(m, NULL, &ro, 0, &im6o, NULL);
> +     ip6_output(m, NULL, NULL, 0, &im6o, NULL);
>       icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
> -
> -     if (ro.ro_rt) {         /* we don't cache this route. */
> -             rtfree(ro.ro_rt);
> -     }
>       return;
>  
>    bad:
> -     if (ro.ro_rt) {
> -             rtfree(ro.ro_rt);
> -     }
>       m_freem(m);
> -     return;
>  }
>  
>  caddr_t

Reply via email to