svn commit: r287861 - in head/sys: net netinet6 netpfil/pf ofed/drivers/infiniband/ulp/ipoib

Gleb Smirnoff glebius at FreeBSD.org
Wed Sep 16 16:56:22 UTC 2015


  Hi!

  The main disaster is still in its place in nd6_output_ifp(), as
it was before in nd6_output()::

        error = (*ifp->if_output)(origifp, m, (struct sockaddr *)dst, NULL);
                  ^^^             ^^^^^^^

:(

On Wed, Sep 16, 2015 at 02:26:29PM +0000, Alexander V. Chernikov wrote:
A> Author: melifaro
A> Date: Wed Sep 16 14:26:28 2015
A> New Revision: 287861
A> URL: https://svnweb.freebsd.org/changeset/base/287861
A> 
A> Log:
A>   Simplify the way of attaching IPv6 link-layer header.
A>   
A>   Problem description:
A>   How do we currently perform layer 2 resolution and header imposition:
A>   
A>   For IPv4 we have the following chain:
A>     ip_output() -> (ether|atm|whatever)_output() -> arpresolve()
A>   
A>   Lookup is done in proper place (link-layer output routine) and it is possible
A>     to provide cached lle data.
A>   
A>   For IPv6 situation is more complex:
A>     ip6_output() -> nd6_output() -> nd6_output_ifp() -> (whatever)_output() ->
A>       nd6_storelladdr()
A>   
A>   We have ip6_ouput() which calls nd6_output() instead of link output routine.
A>   nd6_output() does the following:
A>     * checks if lle exists, creates it if needed (similar to arpresolve())
A>     * performes lle state transitions (similar to arpresolve())
A>     * calls nd6_output_ifp() which pushes packets to link output routine along
A>       with running SeND/MAC hooks regardless of lle state
A>       (e.g. works as run-hooks placeholder).
A>   
A>   After that, iface output routine like ether_output() calls nd6_storelladdr()
A>     which performs lle lookup once again.
A>   
A>   As a result, we perform lookup twice for each outgoing packet for most types
A>     of interfaces. We also need to maintain runtime-checked table of 'nd6-free'
A>     interfaces (see nd6_need_cache()).
A>   
A>   Fix this behavior by eliminating first ND lookup. To be more specific:
A>     * make all nd6_output() consumers use nd6_output_ifp() instead
A>     * rename nd6_output[_slow]() to nd6_resolve_[slow]()
A>     * convert nd6_resolve() and nd6_resolve_slow() to arpresolve() semantics,
A>       e.g. copy L2 address to buffer instead of pushing packet towards lower
A>       layers
A>     * Make all nd6_storelladdr() users use nd6_resolve()
A>     * eliminate nd6_storelladdr()
A>   
A>   The resulting callchain is the following:
A>     ip6_output() -> nd6_output_ifp() -> (whatever)_output() -> nd6_resolve()
A>   
A>   Error handling:
A>   Currently sending packet to non-existing la results in ip6_<output|forward>
A>     -> nd6_output() -> nd6_output _lle() which returns 0.
A>   In new scenario packet is propagated to <ether|whatever>_output() ->
A>     nd6_resolve() which will return EWOULDBLOCK, and that result
A>     will be converted to 0.
A>   
A>   (And EWOULDBLOCK is actually used by IB/TOE code).
A>   
A>   Sponsored by:		Yandex LLC
A>   Differential Revision:	https://reviews.freebsd.org/D1469
A> 
A> Modified:
A>   head/sys/net/if_arcsubr.c
A>   head/sys/net/if_ethersubr.c
A>   head/sys/net/if_fddisubr.c
A>   head/sys/net/if_fwsubr.c
A>   head/sys/net/if_iso88025subr.c
A>   head/sys/netinet6/ip6_forward.c
A>   head/sys/netinet6/ip6_output.c
A>   head/sys/netinet6/nd6.c
A>   head/sys/netinet6/nd6.h
A>   head/sys/netpfil/pf/pf.c
A>   head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
A> 
A> Modified: head/sys/net/if_arcsubr.c
A> ==============================================================================
A> --- head/sys/net/if_arcsubr.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/net/if_arcsubr.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -103,8 +103,8 @@ arc_output(struct ifnet *ifp, struct mbu
A>  	u_int8_t		atype, adst;
A>  	int			loop_copy = 0;
A>  	int			isphds;
A> -#ifdef INET
A> -	int			is_gw;
A> +#if defined(INET) || defined(INET6)
A> +	int			is_gw = 0;
A>  #endif
A>  
A>  	if (!((ifp->if_flags & IFF_UP) &&
A> @@ -112,6 +112,11 @@ arc_output(struct ifnet *ifp, struct mbu
A>  		return(ENETDOWN); /* m, m1 aren't initialized yet */
A>  
A>  	error = 0;
A> +#if defined(INET) || defined(INET6)
A> +	if (ro != NULL && ro->ro_rt != NULL &&
A> +	    (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
A> +		is_gw = 1;
A> +#endif
A>  
A>  	switch (dst->sa_family) {
A>  #ifdef INET
A> @@ -125,10 +130,6 @@ arc_output(struct ifnet *ifp, struct mbu
A>  		else if (ifp->if_flags & IFF_NOARP)
A>  			adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
A>  		else {
A> -			is_gw = 0;
A> -			if (ro != NULL && ro->ro_rt != NULL &&
A> -			    (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
A> -				is_gw = 1;
A>  			error = arpresolve(ifp, is_gw, m, dst, &adst, NULL);
A>  			if (error)
A>  				return (error == EWOULDBLOCK ? 0 : error);
A> @@ -169,10 +170,11 @@ arc_output(struct ifnet *ifp, struct mbu
A>  	case AF_INET6:
A>  		if ((m->m_flags & M_MCAST) != 0)
A>  			adst = arcbroadcastaddr; /* ARCnet broadcast address */
A> -		else
A> -			error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, NULL);
A> -		if (error)
A> -			return (error);
A> +		else {
A> +			error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL);
A> +			if (error != 0)
A> +				return (error == EWOULDBLOCK ? 0 : error);
A> +		}
A>  		atype = ARCTYPE_INET6;
A>  		break;
A>  #endif
A> 
A> Modified: head/sys/net/if_ethersubr.c
A> ==============================================================================
A> --- head/sys/net/if_ethersubr.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/net/if_ethersubr.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -225,10 +225,10 @@ ether_output(struct ifnet *ifp, struct m
A>  		if (lle != NULL && (pflags & LLE_VALID))
A>  			memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
A>  		else
A> -			error = nd6_storelladdr(ifp, m, dst, (u_char *)edst,
A> +			error = nd6_resolve(ifp, is_gw, m, dst, (u_char *)edst,
A>  			    &pflags);
A>  		if (error)
A> -			return error;
A> +			return (error == EWOULDBLOCK ? 0 : error);
A>  		type = htons(ETHERTYPE_IPV6);
A>  		break;
A>  #endif
A> 
A> Modified: head/sys/net/if_fddisubr.c
A> ==============================================================================
A> --- head/sys/net/if_fddisubr.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/net/if_fddisubr.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -101,8 +101,8 @@ fddi_output(struct ifnet *ifp, struct mb
A>  	int loop_copy = 0, error = 0, hdrcmplt = 0;
A>   	u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN];
A>  	struct fddi_header *fh;
A> -#ifdef INET
A> -	int is_gw;
A> +#if defined(INET) || defined(INET6)
A> +	int is_gw = 0;
A>  #endif
A>  
A>  #ifdef MAC
A> @@ -118,13 +118,15 @@ fddi_output(struct ifnet *ifp, struct mb
A>  		senderr(ENETDOWN);
A>  	getmicrotime(&ifp->if_lastchange);
A>  
A> +#if defined(INET) || defined(INET6)
A> +	if (ro != NULL && ro->ro_rt != NULL &&
A> +	    (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
A> +		is_gw = 1;
A> +#endif
A> +
A>  	switch (dst->sa_family) {
A>  #ifdef INET
A>  	case AF_INET: {
A> -		is_gw = 0;
A> -		if (ro != NULL && ro->ro_rt != NULL &&
A> -		    (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
A> -			is_gw = 1;
A>  		error = arpresolve(ifp, is_gw, m, dst, edst, NULL);
A>  		if (error)
A>  			return (error == EWOULDBLOCK ? 0 : error);
A> @@ -161,9 +163,9 @@ fddi_output(struct ifnet *ifp, struct mb
A>  #endif /* INET */
A>  #ifdef INET6
A>  	case AF_INET6:
A> -		error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
A> +		error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
A>  		if (error)
A> -			return (error); /* Something bad happened */
A> +			return (error == EWOULDBLOCK ? 0 : error);
A>  		type = htons(ETHERTYPE_IPV6);
A>  		break;
A>  #endif /* INET6 */
A> 
A> Modified: head/sys/net/if_fwsubr.c
A> ==============================================================================
A> --- head/sys/net/if_fwsubr.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/net/if_fwsubr.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -89,8 +89,8 @@ firewire_output(struct ifnet *ifp, struc
A>  	struct mbuf *mtail;
A>  	int unicast, dgl, foff;
A>  	static int next_dgl;
A> -#ifdef INET
A> -	int is_gw;
A> +#if defined(INET) || defined(INET6)
A> +	int is_gw = 0;
A>  #endif
A>  
A>  #ifdef MAC
A> @@ -105,6 +105,11 @@ firewire_output(struct ifnet *ifp, struc
A>  		goto bad;
A>  	}
A>  
A> +#if defined(INET) || defined(INET6)
A> +	if (ro != NULL && ro->ro_rt != NULL &&
A> +	    (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
A> +		is_gw = 1;
A> +#endif
A>  	/*
A>  	 * For unicast, we make a tag to store the lladdr of the
A>  	 * destination. This might not be the first time we have seen
A> @@ -173,10 +178,10 @@ firewire_output(struct ifnet *ifp, struc
A>  #ifdef INET6
A>  	case AF_INET6:
A>  		if (unicast) {
A> -			error = nd6_storelladdr(fc->fc_ifp, m, dst,
A> +			error = nd6_resolve(fc->fc_ifp, is_gw, m, dst,
A>  			    (u_char *) destfw, NULL);
A>  			if (error)
A> -				return (error);
A> +				return (error == EWOULDBLOCK ? 0 : error);
A>  		}
A>  		type = ETHERTYPE_IPV6;
A>  		break;
A> 
A> Modified: head/sys/net/if_iso88025subr.c
A> ==============================================================================
A> --- head/sys/net/if_iso88025subr.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/net/if_iso88025subr.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -293,9 +293,9 @@ iso88025_output(struct ifnet *ifp, struc
A>  #endif	/* INET */
A>  #ifdef INET6
A>  	case AF_INET6:
A> -		error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
A> +		error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
A>  		if (error)
A> -			return (error);
A> +			return (error == EWOULDBLOCK ? 0 : error);
A>  		snap_type = ETHERTYPE_IPV6;
A>  		break;
A>  #endif	/* INET6 */
A> 
A> Modified: head/sys/netinet6/ip6_forward.c
A> ==============================================================================
A> --- head/sys/netinet6/ip6_forward.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/netinet6/ip6_forward.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -571,7 +571,7 @@ pass:
A>  		goto bad;
A>  	}
A>  
A> -	error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
A> +	error = nd6_output_ifp(rt->rt_ifp, origifp, m, dst);
A>  	if (error) {
A>  		in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
A>  		IP6STAT_INC(ip6s_cantforward);
A> 
A> Modified: head/sys/netinet6/ip6_output.c
A> ==============================================================================
A> --- head/sys/netinet6/ip6_output.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/netinet6/ip6_output.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -935,7 +935,7 @@ passout:
A>  			    m->m_pkthdr.len);
A>  			ifa_free(&ia6->ia_ifa);
A>  		}
A> -		error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
A> +		error = nd6_output_ifp(ifp, origifp, m, dst);
A>  		goto done;
A>  	}
A>  
A> @@ -1034,7 +1034,7 @@ sendorfree:
A>  				counter_u64_add(ia->ia_ifa.ifa_obytes,
A>  				    m->m_pkthdr.len);
A>  			}
A> -			error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
A> +			error = nd6_output_ifp(ifp, origifp, m, dst);
A>  		} else
A>  			m_freem(m);
A>  	}
A> 
A> Modified: head/sys/netinet6/nd6.c
A> ==============================================================================
A> --- head/sys/netinet6/nd6.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/netinet6/nd6.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -136,10 +136,10 @@ static void nd6_free_redirect(const stru
A>  static void nd6_llinfo_timer(void *);
A>  static void clear_llinfo_pqueue(struct llentry *);
A>  static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
A> -static int nd6_output_lle(struct ifnet *, struct ifnet *, struct mbuf *,
A> -	struct sockaddr_in6 *);
A> -static int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *,
A> -    struct sockaddr_in6 *);
A> +static int nd6_resolve_slow(struct ifnet *, struct mbuf *,
A> +    const struct sockaddr_in6 *, u_char *, uint32_t *);
A> +static int nd6_need_cache(struct ifnet *);
A> + 
A>  
A>  static VNET_DEFINE(struct callout, nd6_slowtimo_ch);
A>  #define	V_nd6_slowtimo_ch		VNET(nd6_slowtimo_ch)
A> @@ -1904,7 +1904,7 @@ nd6_grab_holdchain(struct llentry *ln, s
A>  	}
A>  }
A>  
A> -static int
A> +int
A>  nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
A>      struct sockaddr_in6 *dst)
A>  {
A> @@ -1950,16 +1950,29 @@ nd6_output_ifp(struct ifnet *ifp, struct
A>  }
A>  
A>  /*
A> - * IPv6 packet output - light version.
A> - * Checks if destination LLE exists and is in proper state
A> - * (e.g no modification required). If not true, fall back to
A> - * "heavy" version.
A> + * Do L2 address resolution for @sa_dst address. Stores found
A> + * address in @desten buffer. Copy of lle ln_flags can be also
A> + * saved in @pflags if @pflags is non-NULL.
A> + *
A> + * If destination LLE does not exists or lle state modification
A> + * is required, call "slow" version.
A> + *
A> + * Return values:
A> + * - 0 on success (address copied to buffer).
A> + * - EWOULDBLOCK (no local error, but address is still unresolved)
A> + * - other errors (alloc failure, etc)
A>   */
A>  int
A> -nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
A> -    struct sockaddr_in6 *dst, struct rtentry *rt0)
A> +nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
A> +    const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags)
A>  {
A>  	struct llentry *ln = NULL;
A> +	const struct sockaddr_in6 *dst6;
A> +
A> +	if (pflags != NULL)
A> +		*pflags = 0;
A> +
A> +	dst6 = (const struct sockaddr_in6 *)sa_dst;
A>  
A>  	/* discard the packet if IPv6 operation is disabled on the interface */
A>  	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
A> @@ -1967,14 +1980,25 @@ nd6_output(struct ifnet *ifp, struct ifn
A>  		return (ENETDOWN); /* better error? */
A>  	}
A>  
A> -	if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
A> -		goto sendpkt;
A> -
A> -	if (nd6_need_cache(ifp) == 0)
A> -		goto sendpkt;
A> +	if (m != NULL && m->m_flags & M_MCAST) {
A> +		switch (ifp->if_type) {
A> +		case IFT_ETHER:
A> +		case IFT_FDDI:
A> +		case IFT_L2VLAN:
A> +		case IFT_IEEE80211:
A> +		case IFT_BRIDGE:
A> +		case IFT_ISO88025:
A> +			ETHER_MAP_IPV6_MULTICAST(&dst6->sin6_addr,
A> +						 desten);
A> +			return (0);
A> +		default:
A> +			m_freem(m);
A> +			return (EAFNOSUPPORT);
A> +		}
A> +	}
A>  
A>  	IF_AFDATA_RLOCK(ifp);
A> -	ln = nd6_lookup(&dst->sin6_addr, 0, ifp);
A> +	ln = nd6_lookup(&dst6->sin6_addr, 0, ifp);
A>  	IF_AFDATA_RUNLOCK(ifp);
A>  
A>  	/*
A> @@ -1990,45 +2014,33 @@ nd6_output(struct ifnet *ifp, struct ifn
A>  		/* Fall back to slow processing path */
A>  		if (ln != NULL)
A>  			LLE_RUNLOCK(ln);
A> -		return (nd6_output_lle(ifp, origifp, m, dst));
A> +		return (nd6_resolve_slow(ifp, m, dst6, desten, pflags));
A>  	}
A>  
A> -sendpkt:
A> -	if (ln != NULL)
A> -		LLE_RUNLOCK(ln);
A>  
A> -	return (nd6_output_ifp(ifp, origifp, m, dst));
A> +	bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
A> +	if (pflags != NULL)
A> +		*pflags = ln->la_flags;
A> +	LLE_RUNLOCK(ln);
A> +	return (0);
A>  }
A>  
A>  
A>  /*
A> - * Output IPv6 packet - heavy version.
A> - * Function assume that either
A> - * 1) destination LLE does not exist, is invalid or stale, so
A> - *   ND6_EXCLUSIVE lock needs to be acquired
A> - * 2) destination lle is provided (with ND6_EXCLUSIVE lock),
A> - *   in that case packets are queued in &chain.
A> + * Do L2 address resolution for @sa_dst address. Stores found
A> + * address in @desten buffer. Copy of lle ln_flags can be also
A> + * saved in @pflags if @pflags is non-NULL.
A>   *
A> + * Heavy version.
A> + * Function assume that destination LLE does not exist,
A> + * is invalid or stale, so ND6_EXCLUSIVE lock needs to be acquired.
A>   */
A>  static int
A> -nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
A> -    struct sockaddr_in6 *dst)
A> +nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
A> +    const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
A>  {
A>  	struct llentry *lle = NULL, *lle_tmp;
A>  
A> -	KASSERT(m != NULL, ("NULL mbuf, nothing to send"));
A> -	/* discard the packet if IPv6 operation is disabled on the interface */
A> -	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
A> -		m_freem(m);
A> -		return (ENETDOWN); /* better error? */
A> -	}
A> -
A> -	if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
A> -		goto sendpkt;
A> -
A> -	if (nd6_need_cache(ifp) == 0)
A> -		goto sendpkt;
A> -
A>  	/*
A>  	 * Address resolution or Neighbor Unreachability Detection
A>  	 * for the next hop.
A> @@ -2072,23 +2084,18 @@ nd6_output_lle(struct ifnet *ifp, struct
A>  		}
A>  	} 
A>  	if (lle == NULL) {
A> -		if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
A> -		    !(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
A> +		if (!(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
A>  			m_freem(m);
A>  			return (ENOBUFS);
A>  		}
A> -		goto sendpkt;	/* send anyway */
A> +
A> +		if (m != NULL)
A> +			m_freem(m);
A> +		return (ENOBUFS);
A>  	}
A>  
A>  	LLE_WLOCK_ASSERT(lle);
A>  
A> -	/* We don't have to do link-layer address resolution on a p2p link. */
A> -	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
A> -	    lle->ln_state < ND6_LLINFO_REACHABLE) {
A> -		lle->ln_state = ND6_LLINFO_STALE;
A> -		nd6_llinfo_settimer_locked(lle, (long)V_nd6_gctimer * hz);
A> -	}
A> -
A>  	/*
A>  	 * The first time we send a packet to a neighbor whose entry is
A>  	 * STALE, we have to change the state to DELAY and a sets a timer to
A> @@ -2107,8 +2114,13 @@ nd6_output_lle(struct ifnet *ifp, struct
A>  	 * (i.e. its link-layer address is already resolved), just
A>  	 * send the packet.
A>  	 */
A> -	if (lle->ln_state > ND6_LLINFO_INCOMPLETE)
A> -		goto sendpkt;
A> +	if (lle->ln_state > ND6_LLINFO_INCOMPLETE) {
A> +		bcopy(&lle->ll_addr, desten, ifp->if_addrlen);
A> +		if (pflags != NULL)
A> +			*pflags = lle->la_flags;
A> +		LLE_WUNLOCK(lle);
A> +		return (0);
A> +	}
A>  
A>  	/*
A>  	 * There is a neighbor cache entry, but no ethernet address
A> @@ -2160,13 +2172,7 @@ nd6_output_lle(struct ifnet *ifp, struct
A>  		LLE_WUNLOCK(lle);
A>  	}
A>  
A> -	return (0);
A> -
A> -  sendpkt:
A> -	if (lle != NULL)
A> -		LLE_WUNLOCK(lle);
A> -
A> -	return (nd6_output_ifp(ifp, origifp, m, dst));
A> +	return (EWOULDBLOCK);
A>  }
A>  
A>  
A> @@ -2192,15 +2198,12 @@ nd6_flush_holdchain(struct ifnet *ifp, s
A>  
A>  	/*
A>  	 * XXX
A> -	 * note that intermediate errors are blindly ignored - but this is 
A> -	 * the same convention as used with nd6_output when called by
A> -	 * nd6_cache_lladdr
A> +	 * note that intermediate errors are blindly ignored
A>  	 */
A>  	return (error);
A>  }	
A>  
A> -
A> -int
A> +static int
A>  nd6_need_cache(struct ifnet *ifp)
A>  {
A>  	/*
A> @@ -2297,61 +2300,6 @@ nd6_rem_ifa_lle(struct in6_ifaddr *ia, i
A>  		lltable_delete_addr(LLTABLE6(ifp), LLE_IFADDR, saddr);
A>  }
A>  
A> -/*
A> - * the callers of this function need to be re-worked to drop
A> - * the lle lock, drop here for now
A> - */
A> -int
A> -nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
A> -    const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
A> -{
A> -	struct llentry *ln;
A> -
A> -	if (pflags != NULL)
A> -		*pflags = 0;
A> -	IF_AFDATA_UNLOCK_ASSERT(ifp);
A> -	if (m != NULL && m->m_flags & M_MCAST) {
A> -		switch (ifp->if_type) {
A> -		case IFT_ETHER:
A> -		case IFT_FDDI:
A> -		case IFT_L2VLAN:
A> -		case IFT_IEEE80211:
A> -		case IFT_BRIDGE:
A> -		case IFT_ISO88025:
A> -			ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr,
A> -						 desten);
A> -			return (0);
A> -		default:
A> -			m_freem(m);
A> -			return (EAFNOSUPPORT);
A> -		}
A> -	}
A> -
A> -
A> -	/*
A> -	 * the entry should have been created in nd6_store_lladdr
A> -	 */
A> -	IF_AFDATA_RLOCK(ifp);
A> -	ln = lla_lookup(LLTABLE6(ifp), 0, dst);
A> -	IF_AFDATA_RUNLOCK(ifp);
A> -	if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
A> -		if (ln != NULL)
A> -			LLE_RUNLOCK(ln);
A> -		/* this could happen, if we could not allocate memory */
A> -		m_freem(m);
A> -		return (1);
A> -	}
A> -
A> -	bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
A> -	if (pflags != NULL)
A> -		*pflags = ln->la_flags;
A> -	LLE_RUNLOCK(ln);
A> -	/*
A> -	 * A *small* use after free race exists here
A> -	 */
A> -	return (0);
A> -}
A> -
A>  static void 
A>  clear_llinfo_pqueue(struct llentry *ln)
A>  {
A> 
A> Modified: head/sys/netinet6/nd6.h
A> ==============================================================================
A> --- head/sys/netinet6/nd6.h	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/netinet6/nd6.h	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -414,22 +414,19 @@ void nd6_llinfo_settimer_locked(struct l
A>  void nd6_timer(void *);
A>  void nd6_purge(struct ifnet *);
A>  void nd6_nud_hint(struct rtentry *, struct in6_addr *, int);
A> -int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *,
A> -	struct sockaddr *, u_char *);
A> +int nd6_resolve(struct ifnet *, int, struct mbuf *,
A> +    const struct sockaddr *, u_char *, uint32_t *);
A>  int nd6_ioctl(u_long, caddr_t, struct ifnet *);
A>  void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
A>  	char *, int, int, int);
A> -int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *,
A> -	struct sockaddr_in6 *, struct rtentry *);
A>  void nd6_grab_holdchain(struct llentry *, struct mbuf **,
A>      struct sockaddr_in6 *);
A>  int nd6_flush_holdchain(struct ifnet *, struct ifnet *, struct mbuf *,
A>      struct sockaddr_in6 *);
A> -int nd6_need_cache(struct ifnet *);
A>  int nd6_add_ifa_lle(struct in6_ifaddr *);
A>  void nd6_rem_ifa_lle(struct in6_ifaddr *, int);
A> -int nd6_storelladdr(struct ifnet *, struct mbuf *,
A> -	const struct sockaddr *, u_char *, uint32_t *); 
A> +int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *,
A> +    struct sockaddr_in6 *);
A>  
A>  /* nd6_nbr.c */
A>  void nd6_na_input(struct mbuf *, int, int);
A> 
A> Modified: head/sys/netpfil/pf/pf.c
A> ==============================================================================
A> --- head/sys/netpfil/pf/pf.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/netpfil/pf/pf.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -5534,7 +5534,7 @@ pf_route6(struct mbuf **m, struct pf_rul
A>  	if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr))
A>  		dst.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
A>  	if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu)
A> -		nd6_output(ifp, ifp, m0, &dst, NULL);
A> +		nd6_output_ifp(ifp, ifp, m0, &dst);
A>  	else {
A>  		in6_ifstat_inc(ifp, ifs6_in_toobig);
A>  		if (r->rt != PF_DUPTO)
A> 
A> Modified: head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
A> ==============================================================================
A> --- head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c	Wed Sep 16 13:25:35 2015	(r287860)
A> +++ head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c	Wed Sep 16 14:26:28 2015	(r287861)
A> @@ -1333,7 +1333,7 @@ ipoib_output(struct ifnet *ifp, struct m
A>  		else if (m->m_flags & M_MCAST)
A>  			ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst);
A>  		else
A> -			error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL);
A> +			error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL);
A>  		if (error)
A>  			return error;
A>  		type = htons(ETHERTYPE_IPV6);
A> 

-- 
Totus tuus, Glebius.


More information about the svn-src-all mailing list