From owner-freebsd-net@freebsd.org Wed Jan 13 20:10:29 2016 Return-Path: Delivered-To: freebsd-net@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 712BCA8130D for ; Wed, 13 Jan 2016 20:10:29 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2001:1900:2254:206a::16:76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 62B4B1DE5 for ; Wed, 13 Jan 2016 20:10:29 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from bugs.freebsd.org ([127.0.1.118]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id u0DKATi3011006 for ; Wed, 13 Jan 2016 20:10:29 GMT (envelope-from bugzilla-noreply@freebsd.org) From: bugzilla-noreply@freebsd.org To: freebsd-net@FreeBSD.org Subject: [Bug 203524] TCP checksum failed on igb network adapter Date: Wed, 13 Jan 2016 20:10:29 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: kern X-Bugzilla-Version: 10.1-RELEASE X-Bugzilla-Keywords: X-Bugzilla-Severity: Affects Some People X-Bugzilla-Who: fodillemlinkarim@gmail.com X-Bugzilla-Status: Closed X-Bugzilla-Resolution: Not A Bug X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: freebsd-net@FreeBSD.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: cc Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Jan 2016 20:10:29 -0000 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D203524 fodillemlinkarim@gmail.com changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |fodillemlinkarim@gmail.com --- Comment #2 from fodillemlinkarim@gmail.com --- Hi, I believe I have fixed something like this recently please see a post I just made: Hi, I've hit a very interesting problem with ipfw-nat and local TCP traffic that has enough TCP options to hit a special case in m_megapullup(). Here is the story: I am using the following NIC: igb0@pci0:4:0:0: class=3D0x020000 card=3D0x00008086 chip=3D0x150e808= 6 rev=3D0x01 hdr=3D0x00 And when I do ipfw nat to locally emitted packets I see packets not being processed in the igb driver for HW checksum. Now a quick search for m_pullu= p in the igb driver code will show that our igb driver expects a contiguous ethe= rnet + ip header in igb_tx_ctx_setup(). Now the friendly m_megapullup() in alias= .c doesn't reserve any space before the ip header for the ethernet header after its call to m_getcl like tcp_output.c (see m->m_data +=3D max_linkhdr in tcp_output.c). So the call to M_PREPEND() in ether_output() is forced to prepend a new mbuf for the ethernet header, leading to a non contiguous ether + ip. This in tu= rn leads to a failure to properly read the IP protocol in the igb driver and a= pply the proper HW checksum function. Particularly this call in igb_tcp_ctx_setu= p(): ip =3D (struct ip *)(mp->m_data + ehdrlen); To reproduce the issue I simply create a NAT rule for an igb interface and initiate a TCP connection locally going out through that interface (it shou= ld go through NAT obviously) something like: ipfw nat 1 config igb0 reset ipfw add 10 nat 1 via igb0 Although you need to make sure you fill enough of the SYN packet to trigger the allocation of new memory in m_megapullup. You can do this by using enou= gh TCP options so its filling up almost all of the 256 mbuf or make RESERVE something like 300 bytes in alias.c. The fix I propose is very simple and faster for all drivers, including the = ones that do perform a check for ether + ip to be contiguous upon accessing the = IP header. If the leading space is available it doesn't allocate any extra spa= ce (as it should for most cases) but if for some reason the mbuf used doesn't = have 100 bytes (RESERVE in megapullup) of free space it will reserve some at the front too. If the leading space isn't necessary then it won't cause any har= m. -Subproject commit cfe39807fe9b1a23c13f73aabde302046736fa1c +Subproject commit cfe39807fe9b1a23c13f73aabde302046736fa1c-dirty diff --git a/freebsd/sys/netinet/libalias/alias.c b/freebsd/sys/netinet/libalias/alias.c index 876e958..dc424a6 100644 --- a/freebsd/sys/netinet/libalias/alias.c +++ b/freebsd/sys/netinet/libalias/alias.c @@ -1757,7 +1757,8 @@ m_megapullup(struct mbuf *m, int len) { * writable and has some extra space for expansion. * XXX: Constant 100bytes is completely empirical. */ #define RESERVE 100 - if (m->m_next =3D=3D NULL && M_WRITABLE(m) && M_TRAILINGSPACE(m) >=3D R= ESERVE) + if (m->m_next =3D=3D NULL && M_WRITABLE(m) && + M_TRAILINGSPACE(m) >=3D RESERVE && M_LEADINGSPACE(m) >=3D max_linkhdr) return (m); if (len <=3D MCLBYTES - RESERVE) { @@ -1779,6 +1780,7 @@ m_megapullup(struct mbuf *m, int len) { goto bad; m_move_pkthdr(mcl, m); + mcl->m_data +=3D max_linkhdr; m_copydata(m, 0, len, mtod(mcl, caddr_t)); mcl->m_len =3D mcl->m_pkthdr.len =3D len; m_freem(m); It would be nice if some FBSD comitter could review and hopefully add this patch to FBSD. Thank you, Karim. --=20 You are receiving this mail because: You are the assignee for the bug.=