From owner-svn-src-stable-9@FreeBSD.ORG Sun Jul 8 11:53:14 2012 Return-Path: Delivered-To: svn-src-stable-9@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5BCBD106564A; Sun, 8 Jul 2012 11:53:14 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3D01B8FC0A; Sun, 8 Jul 2012 11:53:14 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q68BrEhk049334; Sun, 8 Jul 2012 11:53:14 GMT (envelope-from bz@svn.freebsd.org) Received: (from bz@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q68BrEGj049331; Sun, 8 Jul 2012 11:53:14 GMT (envelope-from bz@svn.freebsd.org) Message-Id: <201207081153.q68BrEGj049331@svn.freebsd.org> From: "Bjoern A. Zeeb" Date: Sun, 8 Jul 2012 11:53:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r238234 - stable/9/sys/netinet6 X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 08 Jul 2012 11:53:14 -0000 Author: bz Date: Sun Jul 8 11:53:13 2012 New Revision: 238234 URL: http://svn.freebsd.org/changeset/base/238234 Log: MFC r235958,236130: Add support for delayed checksum calculations in the IPv6 output path. We currently cannot offload to the card if we add extension headers (which incl. fragmentation). Fix two SCTP offload support copy&paste bugs: calculate checksums if fragmenting and no need to flag IPv4 header checksums in the IPv6 forwarding path. Correctly get the payload length in host byte order. While we already plan to support >64k payload here, the IPv6 header payload length obviously is only 16 bit and the calculations need to be right. Approved by: re Modified: stable/9/sys/netinet6/ip6_forward.c stable/9/sys/netinet6/ip6_output.c Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/netinet6/ip6_forward.c ============================================================================== --- stable/9/sys/netinet6/ip6_forward.c Sun Jul 8 11:42:21 2012 (r238233) +++ stable/9/sys/netinet6/ip6_forward.c Sun Jul 8 11:53:13 2012 (r238234) @@ -586,8 +586,6 @@ skip_routing: CSUM_DATA_VALID | CSUM_PSEUDO_HDR; m->m_pkthdr.csum_data = 0xffff; } - m->m_pkthdr.csum_flags |= - CSUM_IP_CHECKED | CSUM_IP_VALID; #ifdef SCTP if (m->m_pkthdr.csum_flags & CSUM_SCTP) m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; Modified: stable/9/sys/netinet6/ip6_output.c ============================================================================== --- stable/9/sys/netinet6/ip6_output.c Sun Jul 8 11:42:21 2012 (r238233) +++ stable/9/sys/netinet6/ip6_output.c Sun Jul 8 11:53:13 2012 (r238234) @@ -83,6 +83,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include #include @@ -182,6 +184,29 @@ static int copypktopts(struct ip6_pktopt }\ } while (/*CONSTCOND*/ 0) +static void +in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset) +{ + u_short csum; + + csum = in_cksum_skip(m, offset + plen, offset); + if (m->m_pkthdr.csum_flags & CSUM_UDP && csum == 0) + csum = 0xffff; + offset += m->m_pkthdr.csum_data; /* checksum offset */ + + if (offset + sizeof(u_short) > m->m_len) { + printf("%s: delayed m_pullup, m->len: %d off: %d\n", + __func__, m->m_len, offset); + /* + * XXX this should not happen, but if it does, the correct + * behavior may be to insert the checksum in the appropriate + * next mbuf in the chain. + */ + return; + } + *(u_short *)(m->m_data + offset) = csum; +} + /* * IP6 output. The packet in mbuf chain m contains a skeletal IP6 * header (with pri, len, nxt, hlim, src, dst). @@ -221,9 +246,7 @@ ip6_output(struct mbuf *m0, struct ip6_p int flevalid = 0; int hdrsplit = 0; int needipsec = 0; -#ifdef SCTP - int sw_csum; -#endif + int sw_csum, tso; #ifdef IPSEC struct ipsec_output_state state; struct ip6_rthdr *rh = NULL; @@ -867,8 +890,6 @@ again: CSUM_DATA_VALID | CSUM_PSEUDO_HDR; m->m_pkthdr.csum_data = 0xffff; } - m->m_pkthdr.csum_flags |= - CSUM_IP_CHECKED | CSUM_IP_VALID; #ifdef SCTP if (m->m_pkthdr.csum_flags & CSUM_SCTP) m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; @@ -891,7 +912,7 @@ again: } #ifdef SCTP if (m->m_pkthdr.csum_flags & CSUM_SCTP) - m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; + m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; #endif error = netisr_queue(NETISR_IPV6, m); goto done; @@ -927,16 +948,32 @@ passout: * 4: if dontfrag == 1 && alwaysfrag == 1 * error, as we cannot handle this conflicting request */ + sw_csum = m->m_pkthdr.csum_flags; + if (!hdrsplit) { + tso = ((sw_csum & ifp->if_hwassist & CSUM_TSO) != 0) ? 1 : 0; + sw_csum &= ~ifp->if_hwassist; + } else + tso = 0; + /* + * If we added extension headers, we will not do TSO and calculate the + * checksums ourselves for now. + * XXX-BZ Need a framework to know when the NIC can handle it, even + * with ext. hdrs. + */ + if (sw_csum & CSUM_DELAY_DATA) { + sw_csum &= ~CSUM_DELAY_DATA; + in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr)); + } #ifdef SCTP - sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist; if (sw_csum & CSUM_SCTP) { - sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); sw_csum &= ~CSUM_SCTP; + sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); } #endif + m->m_pkthdr.csum_flags &= ifp->if_hwassist; tlen = m->m_pkthdr.len; - if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) + if ((opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) || tso) dontfrag = 1; else dontfrag = 0; @@ -945,7 +982,7 @@ passout: error = EMSGSIZE; goto bad; } - if (dontfrag && tlen > IN6_LINKMTU(ifp)) { /* case 2-b */ + if (dontfrag && tlen > IN6_LINKMTU(ifp) && !tso) { /* case 2-b */ /* * Even if the DONTFRAG option is specified, we cannot send the * packet when the data length is larger than the MTU of the @@ -1033,6 +1070,22 @@ passout: goto bad; } + + /* + * If the interface will not calculate checksums on + * fragmented packets, then do it here. + * XXX-BZ handle the hw offloading case. Need flags. + */ + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in6_delayed_cksum(m, plen, hlen); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } +#ifdef SCTP + if (m->m_pkthdr.csum_flags & CSUM_SCTP) { + sctp_delayed_cksum(m, hlen); + m->m_pkthdr.csum_flags &= ~CSUM_SCTP; + } +#endif mnext = &m->m_nextpkt; /*