On Fri, Sep 11, 2015 at 02:21:54PM +0200, Martin Pieuchot wrote:
> In order to keep if_get()/if_put() dances in the same function, I need
> to change in6_selectroute() to no longer return an ``ifp''.
> 
> This is a first step towards this goal.  It moves the multicast code out
> of in6_selectroute().  I could simplify things further but I'd prefer to
> do that in small diffs.
> 
> ok?

Yes please. This code is just horrid.

 
> Index: netinet6/in6_src.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6_src.c,v
> retrieving revision 1.58
> diff -u -p -r1.58 in6_src.c
> --- netinet6/in6_src.c        11 Sep 2015 09:58:33 -0000      1.58
> +++ netinet6/in6_src.c        11 Sep 2015 10:33:18 -0000
> @@ -295,43 +295,17 @@ in6_selectsrc(struct in6_addr **in6src, 
>  
>  int
>  in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
> -    struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
> -    struct rtentry **retrt, int norouteok, u_int rtableid)
> +    struct route_in6 *ro, struct ifnet **retifp,
> +    struct rtentry **retrt, unsigned int rtableid)
>  {
>       int error = 0;
>       struct ifnet *ifp = NULL;
>       struct rtentry *rt = NULL;
>       struct sockaddr_in6 *sin6_next;
> -     struct in6_pktinfo *pi = NULL;
>       struct in6_addr *dst;
>  
>       dst = &dstsock->sin6_addr;
>  
> -     /* If the caller specify the outgoing interface explicitly, use it. */
> -     if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
> -             ifp = if_get(pi->ipi6_ifindex);
> -             if (ifp != NULL &&
> -                 (norouteok || retrt == NULL ||
> -                  IN6_IS_ADDR_MULTICAST(dst))) {
> -                     /*
> -                      * we do not have to check or get the route for
> -                      * multicast.
> -                      */
> -                     goto done;
> -             } else
> -                     goto getroute;
> -     }
> -
> -     /*
> -      * 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(dst) &&
> -         mopts != NULL && (ifp = if_get(mopts->im6o_ifidx)) != NULL) {
> -             goto done; /* we do not need a route for multicast. */
> -     }
> -
> -  getroute:
>       /*
>        * If the next hop address for the packet is specified by the caller,
>        * use it as the gateway.
> @@ -467,8 +441,6 @@ in6_selectroute(struct sockaddr_in6 *dst
>                */
>               error = EHOSTUNREACH;
>       }
> -     if (error == EHOSTUNREACH)
> -             ip6stat.ip6s_noroute++;
>  
>       if (retifp != NULL)
>               *retifp = ifp;
> @@ -484,10 +456,26 @@ in6_selectif(struct sockaddr_in6 *dstsoc
>      u_int rtableid)
>  {
>       struct rtentry *rt = NULL;
> +     struct in6_pktinfo *pi = NULL;
>       int error;
>  
> -     if ((error = in6_selectroute(dstsock, opts, mopts, ro, retifp,
> -         &rt, 1, rtableid)) != 0)
> +     /* If the caller specify the outgoing interface explicitly, use it. */
> +     if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
> +             *retifp = if_get(pi->ipi6_ifindex);
> +             if (*retifp != NULL)
> +                     return (0);
> +     }
> +
> +     /*
> +      * 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) &&
> +         mopts != NULL && (*retifp = if_get(mopts->im6o_ifidx)) != NULL)
> +             return (0);
> +
> +     if ((error = in6_selectroute(dstsock, opts, ro, retifp,
> +         &rt, rtableid)) != 0)
>               return (error);
>  
>       /*
> Index: netinet6/ip6_output.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
> retrieving revision 1.182
> diff -u -p -r1.182 ip6_output.c
> --- netinet6/ip6_output.c     11 Sep 2015 09:58:33 -0000      1.182
> +++ netinet6/ip6_output.c     11 Sep 2015 12:09:42 -0000
> @@ -155,7 +155,7 @@ ip6_output(struct mbuf *m0, struct ip6_p
>      int flags, struct ip6_moptions *im6o, struct inpcb *inp)
>  {
>       struct ip6_hdr *ip6;
> -     struct ifnet *ifp;
> +     struct ifnet *ifp = NULL;
>       struct mbuf *m = m0;
>       int hlen, tlen;
>       struct route_in6 ip6route;
> @@ -528,17 +528,27 @@ reroute:
>       dstsock.sin6_addr = ip6->ip6_dst;
>       dstsock.sin6_len = sizeof(dstsock);
>       ro->ro_tableid = m->m_pkthdr.ph_rtableid;
> -     if ((error = in6_selectroute(&dstsock, opt, im6o, ro, &ifp,
> -         &rt, 0, m->m_pkthdr.ph_rtableid)) != 0) {
> -             switch (error) {
> -             case EHOSTUNREACH:
> +
> +     if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)) {
> +             struct in6_pktinfo *pi = NULL;
> +
> +             /*
> +              * If the caller specify the outgoing interface
> +              * explicitly, use it.
> +              */
> +             if (opt != NULL && (pi = opt->ip6po_pktinfo) != NULL)
> +                     ifp = if_get(pi->ipi6_ifindex);
> +
> +             if (ifp == NULL && im6o != NULL)
> +                     ifp = if_get(im6o->im6o_ifidx);
> +     }
> +
> +     if (ifp == NULL) {
> +             if ((error = in6_selectroute(&dstsock, opt, ro, &ifp,
> +                 &rt, m->m_pkthdr.ph_rtableid)) != 0) {
>                       ip6stat.ip6s_noroute++;
> -                     break;
> -             case EADDRNOTAVAIL:
> -             default:
> -                     break;  /* XXX statistics? */
> +                     goto bad;
>               }
> -             goto bad;
>       }
>       if (rt == NULL) {
>               /*
> Index: netinet6/ip6_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
> retrieving revision 1.53
> diff -u -p -r1.53 ip6_var.h
> --- netinet6/ip6_var.h        11 Sep 2015 09:58:33 -0000      1.53
> +++ netinet6/ip6_var.h        11 Sep 2015 10:29:26 -0000
> @@ -311,8 +311,8 @@ int       in6_selectsrc(struct in6_addr **, st
>           struct ip6_pktopts *, struct ip6_moptions *, struct route_in6 *,
>           struct in6_addr *, u_int);
>  int  in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
> -         struct ip6_moptions *, struct route_in6 *, struct ifnet **,
> -         struct rtentry **, int, u_int rtableid);
> +         struct route_in6 *, struct ifnet **,
> +         struct rtentry **, unsigned int rtableid);
>  
>  u_int32_t ip6_randomflowlabel(void);
>  #endif /* _KERNEL */
> 

-- 
:wq Claudio

Reply via email to