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