From owner-freebsd-net@FreeBSD.ORG Thu Sep 29 15:25:11 2011 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8EF201065670 for ; Thu, 29 Sep 2011 15:25:11 +0000 (UTC) (envelope-from bhutchings@solarflare.com) Received: from exchange.solarflare.com (exchange.solarflare.com [216.237.3.220]) by mx1.freebsd.org (Postfix) with ESMTP id 70EE48FC12 for ; Thu, 29 Sep 2011 15:25:10 +0000 (UTC) Received: from [10.17.20.137] ([10.17.20.137]) by exchange.solarflare.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Thu, 29 Sep 2011 08:25:09 -0700 From: Ben Hutchings To: freebsd-net@freebsd.org Content-Type: text/plain; charset="UTF-8" Organization: Solarflare Communications Date: Thu, 29 Sep 2011 16:25:06 +0100 Message-ID: <1317309906.2743.9.camel@bwh-desktop> Mime-Version: 1.0 X-Mailer: Evolution 2.32.2 (2.32.2-1.fc14) Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 29 Sep 2011 15:25:10.0314 (UTC) FILETIME=[F9E0B8A0:01CC7EBB] X-TM-AS-Product-Ver: SMEX-8.0.0.1181-6.500.1024-18414.005 X-TM-AS-Result: No--7.317400-0.000000-31 X-TM-AS-User-Approved-Sender: Yes X-TM-AS-User-Blocked-Sender: No Subject: TSO broken with jumbo MTU X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Sep 2011 15:25:11 -0000 tcp_output() does: if (... && len > tp->t_maxseg && ...) tso = 1; Then: if (len + optlen + ipoptlen > tp->t_maxopd) { ... if (tso) { ... if (sendalot && off + len < so->so_snd.sb_cc) { len -= len % (tp->t_maxopd - optlen); sendalot = 1; } Then later: if (tso) { KASSERT(len > tp->t_maxopd - optlen, ("%s: len <= tso_segsz", __func__)); m->m_pkthdr.csum_flags |= CSUM_TSO; m->m_pkthdr.tso_segsz = tp->t_maxopd - optlen; } So there is an assumption here that tp->t_maxseg >= tp->t_maxopd - optlen. But tcp_mss_update() does not ensure that at all, because it rounds down tp->t_maxseg to a multiple of MCLBYTES and does not change tp->t_maxopd accordingly: tp->t_maxopd = mss; if (...) mss -= TCPOLEN_TSTAMP_APPA; #if (MCLBYTES & (MCLBYTES - 1)) == 0 if (mss > MCLBYTES) mss &= ~(MCLBYTES-1); #else if (mss > MCLBYTES) mss = mss / MCLBYTES * MCLBYTES; #endif tp->t_maxseg = mss; (All the above code is from 9, but I found the assertion failure on 8.2 which has fairly similar code.) Ben. -- Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.