Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Jul 2012 12:12:34 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r238237 - stable/9/sys/netinet
Message-ID:  <201207081212.q68CCYMN050281@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bz
Date: Sun Jul  8 12:12:34 2012
New Revision: 238237
URL: http://svn.freebsd.org/changeset/base/238237

Log:
  MFC r235961:
  
     Add code to handle pre-checked TCP checksums as indicated by mbuf
     flags to save the entire computation for validation if not needed.
  
     In the IPv6 TCP output path only compute the pseudo-header checksum,
     set the checksum offset in the mbuf field along the appropriate flag
     as done in IPv4.
  
     In tcp_respond() just initialize the IPv6 payload length to 0 as
     ip6_output() will properly set it.
  
  Approved by:	re

Modified:
  stable/9/sys/netinet/tcp_input.c
  stable/9/sys/netinet/tcp_output.c
  stable/9/sys/netinet/tcp_subr.c
  stable/9/sys/netinet/tcp_syncache.c
  stable/9/sys/netinet/tcp_timewait.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/netinet/tcp_input.c
==============================================================================
--- stable/9/sys/netinet/tcp_input.c	Sun Jul  8 12:01:11 2012	(r238236)
+++ stable/9/sys/netinet/tcp_input.c	Sun Jul  8 12:12:34 2012	(r238237)
@@ -610,13 +610,31 @@ tcp_input(struct mbuf *m, int off0)
 #ifdef INET6
 	if (isipv6) {
 		/* IP6_EXTHDR_CHECK() is already done at tcp6_input(). */
+
+		if (m->m_len < (sizeof(*ip6) + sizeof(*th))) {
+			m = m_pullup(m, sizeof(*ip6) + sizeof(*th));
+			if (m == NULL) {
+				TCPSTAT_INC(tcps_rcvshort);
+				return;
+			}
+		}
+
 		ip6 = mtod(m, struct ip6_hdr *);
+		th = (struct tcphdr *)((caddr_t)ip6 + off0);
 		tlen = sizeof(*ip6) + ntohs(ip6->ip6_plen) - off0;
-		if (in6_cksum(m, IPPROTO_TCP, off0, tlen)) {
+		if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+			if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
+				th->th_sum = m->m_pkthdr.csum_data;
+			else
+				th->th_sum = in6_cksum_pseudo(ip6, tlen,
+				    IPPROTO_TCP, m->m_pkthdr.csum_data);
+			th->th_sum ^= 0xffff;
+		} else
+			th->th_sum = in6_cksum(m, IPPROTO_TCP, off0, tlen);
+		if (th->th_sum) {
 			TCPSTAT_INC(tcps_rcvbadsum);
 			goto drop;
 		}
-		th = (struct tcphdr *)((caddr_t)ip6 + off0);
 
 		/*
 		 * Be proactive about unspecified IPv6 address in source.

Modified: stable/9/sys/netinet/tcp_output.c
==============================================================================
--- stable/9/sys/netinet/tcp_output.c	Sun Jul  8 12:01:11 2012	(r238236)
+++ stable/9/sys/netinet/tcp_output.c	Sun Jul  8 12:12:34 2012	(r238237)
@@ -1052,19 +1052,23 @@ send:
 	 * checksum extended header and data.
 	 */
 	m->m_pkthdr.len = hdrlen + len; /* in6_cksum() need this */
+	m->m_pkthdr.csum_flags = CSUM_TCP;
+	m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 #ifdef INET6
-	if (isipv6)
+	if (isipv6) {
 		/*
 		 * ip6_plen is not need to be filled now, and will be filled
 		 * in ip6_output.
 		 */
-		th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr),
-				       sizeof(struct tcphdr) + optlen + len);
+		th->th_sum = in6_cksum_pseudo(ip6, sizeof(struct tcphdr) +
+		    optlen + len, IPPROTO_TCP, 0);
+	}
+#endif
+#if defined(INET6) && defined(INET)
 	else
-#endif /* INET6 */
+#endif
+#ifdef INET
 	{
-		m->m_pkthdr.csum_flags = CSUM_TCP;
-		m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 		th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
 		    htons(sizeof(struct tcphdr) + IPPROTO_TCP + len + optlen));
 
@@ -1072,6 +1076,7 @@ send:
 		KASSERT(ip->ip_v == IPVERSION,
 		    ("%s: IP version incorrect: %d", __func__, ip->ip_v));
 	}
+#endif
 
 	/*
 	 * Enable TSO and specify the size of the segments.

Modified: stable/9/sys/netinet/tcp_subr.c
==============================================================================
--- stable/9/sys/netinet/tcp_subr.c	Sun Jul  8 12:01:11 2012	(r238236)
+++ stable/9/sys/netinet/tcp_subr.c	Sun Jul  8 12:12:34 2012	(r238237)
@@ -573,8 +573,7 @@ tcp_respond(struct tcpcb *tp, void *ipge
 		ip6->ip6_flow = 0;
 		ip6->ip6_vfc = IPV6_VERSION;
 		ip6->ip6_nxt = IPPROTO_TCP;
-		ip6->ip6_plen = htons((u_short)(sizeof (struct tcphdr) +
-						tlen));
+		ip6->ip6_plen = 0;		/* Set in ip6_output(). */
 		tlen += sizeof (struct ip6_hdr) + sizeof (struct tcphdr);
 	}
 #endif
@@ -619,12 +618,13 @@ tcp_respond(struct tcpcb *tp, void *ipge
 	else
 		nth->th_win = htons((u_short)win);
 	nth->th_urp = 0;
+
+	m->m_pkthdr.csum_flags = CSUM_TCP;
+	m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 #ifdef INET6
 	if (isipv6) {
-		nth->th_sum = 0;
-		nth->th_sum = in6_cksum(m, IPPROTO_TCP,
-					sizeof(struct ip6_hdr),
-					tlen - sizeof(struct ip6_hdr));
+		nth->th_sum = in6_cksum_pseudo(ip6,
+		    tlen - sizeof(struct ip6_hdr), IPPROTO_TCP, 0);
 		ip6->ip6_hlim = in6_selecthlim(tp != NULL ? tp->t_inpcb :
 		    NULL, NULL);
 	}
@@ -636,8 +636,6 @@ tcp_respond(struct tcpcb *tp, void *ipge
 	{
 		nth->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
 		    htons((u_short)(tlen - sizeof(struct ip) + ip->ip_p)));
-		m->m_pkthdr.csum_flags = CSUM_TCP;
-		m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 	}
 #endif /* INET */
 #ifdef TCPDEBUG

Modified: stable/9/sys/netinet/tcp_syncache.c
==============================================================================
--- stable/9/sys/netinet/tcp_syncache.c	Sun Jul  8 12:01:11 2012	(r238236)
+++ stable/9/sys/netinet/tcp_syncache.c	Sun Jul  8 12:12:34 2012	(r238237)
@@ -1472,11 +1472,12 @@ syncache_respond(struct syncache *sc)
 		optlen = 0;
 
 	M_SETFIB(m, sc->sc_inc.inc_fibnum);
+	m->m_pkthdr.csum_flags = CSUM_TCP;
+	m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 #ifdef INET6
 	if (sc->sc_inc.inc_flags & INC_ISIPV6) {
-		th->th_sum = 0;
-		th->th_sum = in6_cksum(m, IPPROTO_TCP, hlen,
-				       tlen + optlen - hlen);
+		th->th_sum = in6_cksum_pseudo(ip6, tlen + optlen - hlen,
+		    IPPROTO_TCP, 0);
 		ip6->ip6_hlim = in6_selecthlim(NULL, NULL);
 		error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
 	}
@@ -1488,8 +1489,6 @@ syncache_respond(struct syncache *sc)
 	{
 		th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
 		    htons(tlen + optlen - hlen + IPPROTO_TCP));
-		m->m_pkthdr.csum_flags = CSUM_TCP;
-		m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 		error = ip_output(m, sc->sc_ipopts, NULL, 0, NULL, NULL);
 	}
 #endif

Modified: stable/9/sys/netinet/tcp_timewait.c
==============================================================================
--- stable/9/sys/netinet/tcp_timewait.c	Sun Jul  8 12:01:11 2012	(r238236)
+++ stable/9/sys/netinet/tcp_timewait.c	Sun Jul  8 12:12:34 2012	(r238237)
@@ -574,10 +574,12 @@ tcp_twrespond(struct tcptw *tw, int flag
 	th->th_flags = flags;
 	th->th_win = htons(tw->last_win);
 
+	m->m_pkthdr.csum_flags = CSUM_TCP;
+	m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 #ifdef INET6
 	if (isipv6) {
-		th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr),
-		    sizeof(struct tcphdr) + optlen);
+		th->th_sum = in6_cksum_pseudo(ip6,
+		    sizeof(struct tcphdr) + optlen, IPPROTO_TCP, 0);
 		ip6->ip6_hlim = in6_selecthlim(inp, NULL);
 		error = ip6_output(m, inp->in6p_outputopts, NULL,
 		    (tw->tw_so_options & SO_DONTROUTE), NULL, NULL, inp);
@@ -590,8 +592,6 @@ tcp_twrespond(struct tcptw *tw, int flag
 	{
 		th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
 		    htons(sizeof(struct tcphdr) + optlen + IPPROTO_TCP));
-		m->m_pkthdr.csum_flags = CSUM_TCP;
-		m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 		ip->ip_len = m->m_pkthdr.len;
 		if (V_path_mtu_discovery)
 			ip->ip_off |= IP_DF;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207081212.q68CCYMN050281>