NetBSD Problem Report #40137

From riastradh@slate.localdomain  Tue Dec  9 07:38:22 2008
Return-Path: <riastradh@slate.localdomain>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by narn.NetBSD.org (Postfix) with ESMTP id CDAAF63B121
	for <gnats-bugs@gnats.NetBSD.org>; Tue,  9 Dec 2008 07:38:21 +0000 (UTC)
Message-Id: <20081209073820.141FF76CC0@slate.localdomain>
Date: Tue,  9 Dec 2008 07:38:19 +0000 (UTC)
From: Taylor R Campbell <campbell@mumble.net>
Reply-To: Taylor R Campbell <campbell@mumble.net>
To: gnats-bugs@gnats.NetBSD.org
Subject: gem(4) drops TCP packets with tcp4csum-tx when on a bridge(4)
X-Send-Pr-Version: 3.95

>Number:         40137
>Category:       kern
>Synopsis:       gem(4) drops TCP packets with tcp4csum-tx when on a bridge(4)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          feedback
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Dec 09 07:40:00 +0000 2008
>Closed-Date:    
>Last-Modified:  Mon Mar 23 18:10:01 +0000 2020
>Originator:     Taylor R Campbell <campbell@mumble.net>
>Release:        NetBSD 4.0_STABLE
>Organization:
>Environment:
System: NetBSD slate.localdomain 4.0_STABLE NetBSD 4.0_STABLE (RIABWI) #35: Sun Nov 16 12:42:48 EST 2008 riastradh@Oberon.local:/Users/riastradh/os/netbsd/4/obj/sys/arch/macppc/compile/RIABWI macppc
Architecture: powerpc
Machine: macppc

	(My `RIABWI' kernel contains the bwi(4) driver and enables
	cgd(4), OFB_ENABLE_CACHE, and CAPS_IS_CONTROL; otherwise it is
	identical to GENERIC.  The only bwi(4) interface is down as I
	test this problem.)

>Description:

	Enabling tcp4csum-tx on a gem(4) interface, and adding that
	interface to a bridge(4), causes the gem(4) interface to drop
	incoming TCP packets.  Neither alone exhibits the problem; only
	the combination of circumstances does.

>How-To-Repeat:

	On a machine with a gem(4) interface, enable the tcp4csum-tx
	option, create a bridge(4) interface, and add the gem(4)
	interface to it.  Run tcpdump(8) on the gem(4) interface and
	initiate a TCP connection on the gem(4) interface; observe the
	outgoing, but not incoming, TCP packets.

>Fix:

	None known.

>Release-Note:

>Audit-Trail:
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: kern/40137: gem(4) drops TCP packets with tcp4csum-tx when on
	a bridge(4)
Date: Sun, 14 Mar 2010 19:40:32 +0000

 (not sent to gnats)

    ------

 From: MINOURA Makoto <minoura@netbsd.org>
 To: gnats-admin@netbsd.org, netbsd-bugs@NetBSD.org
 Cc: tech-net@NetBSD.org
 Subject: Re: kern/40137: gem(4) drops TCP packets with tcp4csum-tx when on a
 	bridge(4) 
 Date: Wed, 10 Mar 2010 22:14:23 +0900


 This is not a gem(4)-specific problem but common to all the
 modern (offloading) NICs.  Here's a patch to fix this.  It
 is for 5.0.2 but should basically be applicable to -current,
 unless I've missed some changes such as intruduction of
 kernel mutexes etc :)  By this patch a bridge(4) now has
 capability flags when all the members have their offloading
 engine (AND'ed).


 Index: net/if.c
 ===================================================================
 RCS file: /cvsroot/src/sys/net/if.c,v
 retrieving revision 1.230.4.1
 diff -u -r1.230.4.1 if.c
 --- net/if.c	24 Feb 2009 02:26:42 -0000	1.230.4.1
 +++ net/if.c	8 Mar 2010 13:50:04 -0000
 @@ -97,6 +97,7 @@
  #include "opt_atalk.h"
  #include "opt_natm.h"
  #include "opt_pfil_hooks.h"
 +#include "bridge.h"

  #include <sys/param.h>
  #include <sys/mbuf.h>
 @@ -117,6 +118,9 @@
  #include <net/if_dl.h>
  #include <net/if_ether.h>
  #include <net/if_media.h>
 +#if NBRIDGE > 0
 +#include <net/if_bridgevar.h>
 +#endif
  #include <net80211/ieee80211.h>
  #include <net80211/ieee80211_ioctl.h>
  #include <net/if_types.h>
 @@ -518,6 +522,7 @@
  	ifp->if_link_state = LINK_STATE_UNKNOWN;

  	ifp->if_capenable = 0;
 +	ifp->if_tso = 0;
  	ifp->if_csum_flags_tx = 0;
  	ifp->if_csum_flags_rx = 0;

 @@ -1466,6 +1471,14 @@
  		if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) {
  			ifp->if_csum_flags_rx |= M_CSUM_UDPv6;
  		}
 +		ifp->if_tso = ifp->if_capenable & (IFCAP_TSOv4|IFCAP_TSOv6);
 +#if NBRIDGE > 0
 +		if (ifp->if_bridge) {
 +			s = splnet();
 +			bridge_update_capflags(ifp->if_bridge);
 +			splx(s);
 +		}
 +#endif
  		if (ifp->if_flags & IFF_UP)
  			return ENETRESET;
  		return 0;
 Index: net/if.h
 ===================================================================
 RCS file: /cvsroot/src/sys/net/if.h,v
 retrieving revision 1.140
 diff -u -r1.140 if.h
 --- net/if.h	24 Oct 2008 17:07:33 -0000	1.140
 +++ net/if.h	8 Mar 2010 13:50:04 -0000
 @@ -275,6 +275,7 @@
  	struct pfil_head if_pfil;	/* filtering point */
  	uint64_t if_capabilities;	/* interface capabilities */
  	uint64_t if_capenable;		/* capabilities enabled */
 +	uint64_t if_tso;		/* TSO flags */
  	union {
  		void *		carp_s;	/* carp structure (used by !carp ifs) */
  		struct ifnet	*carp_d;/* ptr to carpdev (used by carp ifs) */
 Index: net/if_bridge.c
 ===================================================================
 RCS file: /cvsroot/src/sys/net/if_bridge.c,v
 retrieving revision 1.62.6.4
 diff -u -r1.62.6.4 if_bridge.c
 --- net/if_bridge.c	4 Apr 2009 18:03:06 -0000	1.62.6.4
 +++ net/if_bridge.c	8 Mar 2010 13:50:05 -0000
 @@ -173,6 +173,16 @@
  #define	BRIDGE_RTABLE_PRUNE_PERIOD	(5 * 60)
  #endif

 +/*
 + * Convert if_capenable to if_csum_flags_tx.
 + */
 +#define CSUM_FLAGS_TX(capenable)	\
 +	((((capenable) & IFCAP_CSUM_IPv4_Tx)?M_CSUM_IPv4:0) |	\
 +	 (((capenable) & IFCAP_CSUM_TCPv4_Tx)?M_CSUM_TCPv4:0) |	\
 +	 (((capenable) & IFCAP_CSUM_UDPv4_Tx)?M_CSUM_UDPv4:0) |	\
 +	 (((capenable) & IFCAP_CSUM_TCPv6_Tx)?M_CSUM_TCPv6:0) |	\
 +	 (((capenable) & IFCAP_CSUM_UDPv6_Tx)?M_CSUM_UDPv6:0))
 +
  int	bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;

  static struct pool bridge_rtnode_pool;
 @@ -588,7 +598,11 @@
  	}

  	ifs->if_bridge = NULL;
 +	ifs->if_tso = ifs->if_capenable & (IFCAP_TSOv4|IFCAP_TSOv6);
 +	ifs->if_csum_flags_tx = CSUM_FLAGS_TX(ifs->if_capenable);
 +
  	LIST_REMOVE(bif, bif_next);
 +	bridge_update_capflags(sc);

  	bridge_rtdelete(sc, ifs);

 @@ -644,6 +658,7 @@

  	ifs->if_bridge = sc;
  	LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);
 +	bridge_update_capflags(sc);

  	if (sc->sc_if.if_flags & IFF_RUNNING)
  		bstp_initialization(sc);
 @@ -1125,11 +1140,6 @@
  	int len, error;
  	short mflags;

 -	/*
 -	 * Clear any in-bound checksum flags for this packet.
 -	 */
 -	m->m_pkthdr.csum_flags = 0;
 -
  #ifdef PFIL_HOOKS
  	if (runfilt) {
  		if (pfil_run_hooks(&sc->sc_if.if_pfil, &m,
 @@ -2256,3 +2266,32 @@
  }
  # endif /* INET6 */
  #endif /* BRIDGE_IPF && PFIL_HOOKS */
 +
 +void
 +bridge_update_capflags(struct bridge_softc *sc)
 +{
 +	uint64_t capabilities = ~0;
 +	uint64_t capenable = ~0;
 +	struct bridge_iflist *bif;
 +	int tso = 0, csum_flags_tx = 0;
 +
 +	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 +		capabilities &= bif->bif_ifp->if_capabilities;
 +		capenable &= bif->bif_ifp->if_capenable;
 +	}
 +	if (capabilities == ~0) { /* nobody here */
 +		sc->sc_if.if_capabilities = 0;
 +		sc->sc_if.if_capenable = 0;
 +		return;
 +	}
 +	sc->sc_if.if_capabilities = capabilities;
 +	sc->sc_if.if_capenable = capenable;
 +
 +	tso = capenable & (IFCAP_TSOv4|IFCAP_TSOv6);
 +	csum_flags_tx = CSUM_FLAGS_TX(capenable);
 +
 +	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 +		bif->bif_ifp->if_tso = tso;
 +		bif->bif_ifp->if_csum_flags_tx = csum_flags_tx;
 +	}
 +}
 Index: net/if_bridgevar.h
 ===================================================================
 RCS file: /cvsroot/src/sys/net/if_bridgevar.h,v
 retrieving revision 1.11.46.1
 diff -u -r1.11.46.1 if_bridgevar.h
 --- net/if_bridgevar.h	4 Apr 2009 18:00:03 -0000	1.11.46.1
 +++ net/if_bridgevar.h	8 Mar 2010 13:50:05 -0000
 @@ -318,5 +318,7 @@
  void	bridge_enqueue(struct bridge_softc *, struct ifnet *, struct mbuf *,
  	    int);

 +void	bridge_update_capflags(struct bridge_softc *);
 +
  #endif /* _KERNEL */
  #endif /* !_NET_IF_BRIDGEVAR_H_ */
 Index: netinet/ip_output.c
 ===================================================================
 RCS file: /cvsroot/src/sys/netinet/ip_output.c,v
 retrieving revision 1.200.10.1
 diff -u -r1.200.10.1 ip_output.c
 --- netinet/ip_output.c	9 Jul 2009 19:35:56 -0000	1.200.10.1
 +++ netinet/ip_output.c	8 Mar 2010 13:50:06 -0000
 @@ -825,7 +825,7 @@

  		if (__predict_true(
  		    (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) == 0 ||
 -		    (ifp->if_capenable & IFCAP_TSOv4) != 0)) {
 +		    (ifp->if_tso & IFCAP_TSOv4) != 0)) {
  			error =
  			    (*ifp->if_output)(ifp, m,
  				(m->m_flags & M_MCAST) ?
 Index: netinet/tcp_output.c
 ===================================================================
 RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v
 retrieving revision 1.167
 diff -u -r1.167 tcp_output.c
 --- netinet/tcp_output.c	28 Apr 2008 20:24:09 -0000	1.167
 +++ netinet/tcp_output.c	8 Mar 2010 13:50:06 -0000
 @@ -637,7 +637,7 @@
  		  		       IPSEC_DIR_OUTBOUND) &&
  #endif
  		  (rt = rtcache_validate(&tp->t_inpcb->inp_route)) != NULL &&
 -		  (rt->rt_ifp->if_capenable & IFCAP_TSOv4) != 0;
 +		  (rt->rt_ifp->if_tso & IFCAP_TSOv4) != 0;
  #endif /* defined(INET) */
  #if defined(INET6)
  	has_tso6 = tp->t_in6pcb != NULL &&
 @@ -646,7 +646,7 @@
  		  		       IPSEC_DIR_OUTBOUND) &&
  #endif
  		  (rt = rtcache_validate(&tp->t_in6pcb->in6p_route)) != NULL &&
 -		  (rt->rt_ifp->if_capenable & IFCAP_TSOv6) != 0;
 +		  (rt->rt_ifp->if_tso & IFCAP_TSOv6) != 0;
  #endif /* defined(INET6) */
  	has_tso = (has_tso4 || has_tso6) && !alwaysfrag;

 Index: netinet6/ip6_output.c
 ===================================================================
 RCS file: /cvsroot/src/sys/netinet6/ip6_output.c,v
 retrieving revision 1.135.2.1
 diff -u -r1.135.2.1 ip6_output.c
 --- netinet6/ip6_output.c	20 Apr 2009 22:56:04 -0000	1.135.2.1
 +++ netinet6/ip6_output.c	8 Mar 2010 13:50:08 -0000
 @@ -980,7 +980,7 @@

  		KASSERT(dst != NULL);
  		if (__predict_true(!tso ||
 -		    (ifp->if_capenable & IFCAP_TSOv6) != 0)) {
 +		    (ifp->if_tso & IFCAP_TSOv6) != 0)) {
  			error = nd6_output(ifp, origifp, m, dst, rt);
  		} else {
  			error = ip6_tso_output(ifp, origifp, m, dst, rt);

State-Changed-From-To: open->feedback
State-Changed-By: jdolecek@NetBSD.org
State-Changed-When: Mon, 23 Mar 2020 17:49:48 +0000
State-Changed-Why:
This should have been fixed in rev. 1.442 of sys/net/if.c
Can you please confirm whether this is still problem with netbsd-9?


From: Taylor R Campbell <campbell@mumble.net>
To: gnats-bugs@netbsd.org
Cc: kern-bug-people@netbsd.org, netbsd-bugs@netbsd.org,
	gnats-admin@netbsd.org, jdolecek@NetBSD.org
Subject: Re: kern/40137 (gem(4) drops TCP packets with tcp4csum-tx when on a bridge(4))
Date: Mon, 23 Mar 2020 18:07:25 +0000

 > Date: Mon, 23 Mar 2020 17:49:48 +0000 (UTC)
 > From: jdolecek@NetBSD.org
 > 
 > Synopsis: gem(4) drops TCP packets with tcp4csum-tx when on a bridge(4)
 > 
 > State-Changed-From-To: open->feedback
 > State-Changed-By: jdolecek@NetBSD.org
 > State-Changed-When: Mon, 23 Mar 2020 17:49:48 +0000
 > State-Changed-Why:
 > This should have been fixed in rev. 1.442 of sys/net/if.c
 > Can you please confirm whether this is still problem with netbsd-9?

 Probably not in the foreseeable future!

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.