svn commit: r243291 - in user/andre/tcp_workqueue/sys: net netinet netinet6 netipsec netpfil/ipfw netpfil/pf

Andre Oppermann andre at FreeBSD.org
Mon Nov 19 18:04:19 UTC 2012


Author: andre
Date: Mon Nov 19 18:04:17 2012
New Revision: 243291
URL: http://svnweb.freebsd.org/changeset/base/243291

Log:
  Convert IP, IPv6, UDP, TCP and SCTP to the new checksum offloading
  semantics on the inbound and outbound path.
  
  In short for inbound there are two levels the offloading NIC can
  set:
  
   CSUM_L3_CALC	for an IP layer 3 checksum calculated by the NIC;
   CSUM_L3_VALID	set when the calculated checksum matches the one
  		in the packet;
   CSUM_L4_CALC	for an UDP/TCP/SCTP layer 4 checksum calculated by
  		the NIC;
   CSUM_L4_VALID	set when the calculated checksum matche the one
  		in the packet.
  
  From this follows that a packet failed checksum verification when
  only *_CALC is set but not *_VALID.  The NIC is expected to deliver
  a failed packet up the stack anyways for capture by BPF and to
  record protocol specific checksum mismatch statistics.
  
  The old approach with CSUM_DATA_VALID and CSUM_PSEUDO_HDR could not
  signal a failed packet.  A failed packet was delivered into the stack
  and the protocol had to recalculate the checksum for verification
  every time to detect that as the absence of CSUM_DATA_VALID didn't
  signal that the packet was broken.  It was only saying that the
  checksum wasn't calculated by the NIC, which actually  wasn't the case.
  
  Drag the other stack infrastructure, including packet filters, along
  as well.

Modified:
  user/andre/tcp_workqueue/sys/net/if_bridge.c
  user/andre/tcp_workqueue/sys/net/if_ethersubr.c
  user/andre/tcp_workqueue/sys/net/if_loop.c
  user/andre/tcp_workqueue/sys/netinet/ip_divert.c
  user/andre/tcp_workqueue/sys/netinet/ip_fastfwd.c
  user/andre/tcp_workqueue/sys/netinet/ip_input.c
  user/andre/tcp_workqueue/sys/netinet/ip_ipsec.c
  user/andre/tcp_workqueue/sys/netinet/ip_mroute.c
  user/andre/tcp_workqueue/sys/netinet/ip_output.c
  user/andre/tcp_workqueue/sys/netinet/sctp_input.c
  user/andre/tcp_workqueue/sys/netinet/sctp_os_bsd.h
  user/andre/tcp_workqueue/sys/netinet/sctp_output.c
  user/andre/tcp_workqueue/sys/netinet/siftr.c
  user/andre/tcp_workqueue/sys/netinet/tcp_input.c
  user/andre/tcp_workqueue/sys/netinet/tcp_lro.c
  user/andre/tcp_workqueue/sys/netinet/tcp_output.c
  user/andre/tcp_workqueue/sys/netinet/tcp_subr.c
  user/andre/tcp_workqueue/sys/netinet/tcp_syncache.c
  user/andre/tcp_workqueue/sys/netinet/tcp_timewait.c
  user/andre/tcp_workqueue/sys/netinet/udp_usrreq.c
  user/andre/tcp_workqueue/sys/netinet6/ip6_forward.c
  user/andre/tcp_workqueue/sys/netinet6/ip6_ipsec.c
  user/andre/tcp_workqueue/sys/netinet6/ip6_output.c
  user/andre/tcp_workqueue/sys/netinet6/sctp6_usrreq.c
  user/andre/tcp_workqueue/sys/netinet6/udp6_usrreq.c
  user/andre/tcp_workqueue/sys/netipsec/ipsec_pfil.c
  user/andre/tcp_workqueue/sys/netpfil/ipfw/ip_fw_nat.c
  user/andre/tcp_workqueue/sys/netpfil/pf/pf.c
  user/andre/tcp_workqueue/sys/netpfil/pf/pf_ioctl.c

Modified: user/andre/tcp_workqueue/sys/net/if_bridge.c
==============================================================================
--- user/andre/tcp_workqueue/sys/net/if_bridge.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/net/if_bridge.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -3263,8 +3263,8 @@ bridge_ip_checkbasic(struct mbuf **mp)
 		if (ip == NULL) goto bad;
 	}
 
-	if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
-		sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
+	if (m->m_pkthdr.csum_flags & CSUM_L3_CALC) {
+		sum = !(m->m_pkthdr.csum_flags & CSUM_L3_VALID);
 	} else {
 		if (hlen == sizeof(struct ip)) {
 			sum = in_cksum_hdr(ip);

Modified: user/andre/tcp_workqueue/sys/net/if_ethersubr.c
==============================================================================
--- user/andre/tcp_workqueue/sys/net/if_ethersubr.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/net/if_ethersubr.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -299,12 +299,10 @@ ether_output(struct ifnet *ifp, struct m
 	if (lle != NULL && (lle->la_flags & LLE_IFADDR)) {
 		int csum_flags = 0;
 		if (m->m_pkthdr.csum_flags & CSUM_IP)
-			csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
-			csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
-		if (m->m_pkthdr.csum_flags & CSUM_SCTP)
-			csum_flags |= CSUM_SCTP_VALID;
-		m->m_pkthdr.csum_flags |= csum_flags;
+			csum_flags |= (CSUM_L3_CALC|CSUM_L3_VALID);
+		if (m->m_pkthdr.csum_flags & (CSUM_UDP|CSUM_TCP|CSUM_SCTP))
+			csum_flags |= (CSUM_L4_CALC|CSUM_L4_VALID);
+		m->m_pkthdr.csum_flags = csum_flags;
 		m->m_pkthdr.csum_data = 0xffff;
 		return (if_simloop(ifp, m, dst->sa_family, 0));
 	}
@@ -356,11 +354,9 @@ ether_output(struct ifnet *ifp, struct m
 		int csum_flags = 0;
 
 		if (m->m_pkthdr.csum_flags & CSUM_IP)
-			csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
-			csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
-		if (m->m_pkthdr.csum_flags & CSUM_SCTP)
-			csum_flags |= CSUM_SCTP_VALID;
+			csum_flags |= (CSUM_L3_CALC|CSUM_L3_VALID);
+		if (m->m_pkthdr.csum_flags & (CSUM_UDP|CSUM_TCP|CSUM_SCTP))
+			csum_flags |= (CSUM_L4_CALC|CSUM_L4_VALID);
 
 		if (m->m_flags & M_BCAST) {
 			struct mbuf *n;
@@ -379,16 +375,12 @@ ether_output(struct ifnet *ifp, struct m
 			 */
 			if ((n = m_dup(m, M_DONTWAIT)) != NULL) {
 				n->m_pkthdr.csum_flags |= csum_flags;
-				if (csum_flags & CSUM_DATA_VALID)
-					n->m_pkthdr.csum_data = 0xffff;
 				(void)if_simloop(ifp, n, dst->sa_family, hlen);
 			} else
 				ifp->if_iqdrops++;
 		} else if (bcmp(eh->ether_dhost, eh->ether_shost,
 				ETHER_ADDR_LEN) == 0) {
 			m->m_pkthdr.csum_flags |= csum_flags;
-			if (csum_flags & CSUM_DATA_VALID)
-				m->m_pkthdr.csum_data = 0xffff;
 			(void) if_simloop(ifp, m, dst->sa_family, hlen);
 			return (0);	/* XXX */
 		}

Modified: user/andre/tcp_workqueue/sys/net/if_loop.c
==============================================================================
--- user/andre/tcp_workqueue/sys/net/if_loop.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/net/if_loop.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -91,12 +91,10 @@
 #define LOMTU	16384
 #endif
 
-#define	LO_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)
-#define	LO_CSUM_FEATURES6	(CSUM_TCP_IPV6 | CSUM_UDP_IPV6 | CSUM_SCTP_IPV6)
-#define	LO_CSUM_SET		(CSUM_DATA_VALID | CSUM_DATA_VALID_IPV6 | \
-				    CSUM_PSEUDO_HDR | \
-				    CSUM_IP_CHECKED | CSUM_IP_VALID | \
-				    CSUM_SCTP_VALID)
+#define	LO_CSUM_FEATURES	(CSUM_IP|CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP)
+#define	LO_CSUM_FEATURES6	(CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP)
+#define	LO_CSUM_SET		(CSUM_L4_CALC | CSUM_L4_VALID | \
+				    CSUM_L3_CALC | CSUM_L3_VALID)
 
 int		loioctl(struct ifnet *, u_long, caddr_t);
 static void	lortrequest(int, struct rtentry *, struct rt_addrinfo *);

Modified: user/andre/tcp_workqueue/sys/netinet/ip_divert.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/ip_divert.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/ip_divert.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -207,14 +207,14 @@ divert_packet(struct mbuf *m, int incomi
 	ip = mtod(m, struct ip *);
 
 	/* Delayed checksums are currently not compatible with divert. */
-	if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+	if (m->m_pkthdr.csum_flags & (CSUM_IP_UDP|CSUM_IP_TCP)) {
 		in_delayed_cksum(m);
-		m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+		m->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP|CSUM_IP_TCP);
 	}
 #ifdef SCTP
-	if (m->m_pkthdr.csum_flags & CSUM_SCTP) {
+	if (m->m_pkthdr.csum_flags & CSUM_IP_SCTP) {
 		sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
-		m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+		m->m_pkthdr.csum_flags &= ~CSUM_IP_SCTP;
 	}
 #endif
 	bzero(&divsrc, sizeof(divsrc));

Modified: user/andre/tcp_workqueue/sys/netinet/ip_fastfwd.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/ip_fastfwd.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/ip_fastfwd.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -230,23 +230,25 @@ ip_fastforward(struct mbuf *m)
 	/*
 	 * Checksum correct?
 	 */
-	if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED)
-		sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
-	else {
+	if ((m->m_pkthdr.csum_flags & (CSUM_L3_CALC | CSUM_L3_VALID)) ==
+	    CSUM_L3_CALC) {
+		IPSTAT_INC(ips_badsum);
+		goto drop;
+	} else if (!(m->m_pkthdr.csum_flags & CSUM_L3_VALID)) {
 		if (hlen == sizeof(struct ip))
 			sum = in_cksum_hdr(ip);
 		else
 			sum = in_cksum(m, hlen);
+		if (sum) {
+			IPSTAT_INC(ips_badsum);
+			goto drop;
+		}
+		/*
+		 * Remember that we have checked the IP header and found
+		 * it valid.
+		 */
+		m->m_pkthdr.csum_flags |= (CSUM_L3_CALC | CSUM_L3_VALID);
 	}
-	if (sum) {
-		IPSTAT_INC(ips_badsum);
-		goto drop;
-	}
-
-	/*
-	 * Remember that we have checked the IP header and found it valid.
-	 */
-	m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID);
 
 	ip_len = ntohs(ip->ip_len);
 
@@ -523,7 +525,7 @@ passout:
 		mtu = ifp->if_mtu;
 
 	if (ip_len <= mtu ||
-	    (ifp->if_hwassist & CSUM_IPFRAG && (ip_off & IP_DF) == 0)) {
+	    ((ifp->if_hwassist & CSUM_IP_FRAGO) && (ip_off & IP_DF) == 0)) {
 		/*
 		 * Send off the packet via outgoing interface
 		 */

Modified: user/andre/tcp_workqueue/sys/netinet/ip_input.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/ip_input.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/ip_input.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -435,19 +435,20 @@ ip_input(struct mbuf *m)
 		}
 	}
 
-	if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
-		sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
-	} else {
-		if (hlen == sizeof(struct ip)) {
+	if ((m->m_pkthdr.csum_flags & (CSUM_L3_CALC|CSUM_L3_VALID)) ==
+	    CSUM_L3_CALC) {
+		IPSTAT_INC(ips_badsum);
+		goto bad;
+	} else if (!(m->m_pkthdr.csum_flags & CSUM_L3_VALID)) {
+		if (hlen == sizeof(struct ip))
 			sum = in_cksum_hdr(ip);
-		} else {
+		else
 			sum = in_cksum(m, hlen);
+		if (sum) {
+			IPSTAT_INC(ips_badsum);
+			goto bad;
 		}
 	}
-	if (sum) {
-		IPSTAT_INC(ips_badsum);
-		goto bad;
-	}
 
 #ifdef ALTQ
 	if (altq_input != NULL && (*altq_input)(m, AF_INET) == 0)

Modified: user/andre/tcp_workqueue/sys/netinet/ip_ipsec.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/ip_ipsec.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/ip_ipsec.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -327,16 +327,16 @@ ip_ipsec_output(struct mbuf **m, struct 
 		 * Do delayed checksums now because we send before
 		 * this is done in the normal processing path.
 		 */
-		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+		if ((*m)->m_pkthdr.csum_flags & (CSUM_IP_UDP|CSUM_IP_TCP)) {
 			in_delayed_cksum(*m);
-			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+			(*m)->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP|CSUM_IP_TCP);
 		}
 #ifdef SCTP
-		if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) {
+		if ((*m)->m_pkthdr.csum_flags & CSUM_IP_SCTP) {
 			struct ip *ip = mtod(*m, struct ip *);
 
 			sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2));
-			(*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+			(*m)->m_pkthdr.csum_flags &= ~CSUM_IP_SCTP;
 		}
 #endif
 

Modified: user/andre/tcp_workqueue/sys/netinet/ip_mroute.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/ip_mroute.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/ip_mroute.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -2375,9 +2375,9 @@ pim_register_prepare(struct ip *ip, stru
     int mtu;
 
     /* Take care of delayed checksums */
-    if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+    if (m->m_pkthdr.csum_flags & (CSUM_IP_UDP|CSUM_IP_TCP)) {
 	in_delayed_cksum(m);
-	m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+	m->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP|CSUM_IP_TCP);
     }
 
     /*

Modified: user/andre/tcp_workqueue/sys/netinet/ip_output.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/ip_output.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/ip_output.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -518,41 +518,31 @@ sendit:
 			m->m_flags |= M_FASTFWD_OURS;
 			if (m->m_pkthdr.rcvif == NULL)
 				m->m_pkthdr.rcvif = V_loif;
-			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+			/* Pretend that the checksum was verified by hw. */
+			if (m->m_pkthdr.csum_flags & CSUM_IP)
 				m->m_pkthdr.csum_flags |=
-				    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;
-#endif
+				    CSUM_L3_CALC | CSUM_L3_VALID;
+			if (m->m_pkthdr.csum_flags &
+			    (CSUM_UDP|CSUM_TCP|CSUM_SCTP))
+				m->m_pkthdr.csum_flags |=
+				    CSUM_L4_CALC | CSUM_L4_VALID;
 			error = netisr_queue(NETISR_IP, m);
 			goto done;
-		} else {
-			if (ia != NULL)
-				ifa_free(&ia->ia_ifa);
-			goto again;	/* Redo the routing table lookup. */
 		}
+		if (ia != NULL)
+			ifa_free(&ia->ia_ifa);
+		goto again;	/* Redo the routing table lookup. */
 	}
 
 	/* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
 	if (m->m_flags & M_FASTFWD_OURS) {
 		if (m->m_pkthdr.rcvif == NULL)
 			m->m_pkthdr.rcvif = V_loif;
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
-			m->m_pkthdr.csum_flags |=
-			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
-			m->m_pkthdr.csum_data = 0xffff;
-		}
-#ifdef SCTP
-		if (m->m_pkthdr.csum_flags & CSUM_SCTP)
-			m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
-#endif
-		m->m_pkthdr.csum_flags |=
-			    CSUM_IP_CHECKED | CSUM_IP_VALID;
+		/* Pretend that the checksum was verified by hw. */
+		if (m->m_pkthdr.csum_flags & CSUM_IP)
+			m->m_pkthdr.csum_flags |= CSUM_L3_CALC | CSUM_L3_VALID;
+		if (m->m_pkthdr.csum_flags & (CSUM_UDP|CSUM_TCP|CSUM_SCTP))
+			m->m_pkthdr.csum_flags |= CSUM_L4_CALC | CSUM_L4_VALID;
 
 		error = netisr_queue(NETISR_IP, m);
 		goto done;
@@ -583,14 +573,15 @@ passout:
 
 	m->m_pkthdr.csum_flags |= CSUM_IP;
 	m->m_pkthdr.csum_l3hlen += ip_len;
-	if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA & ~ifp->if_hwassist) {
+	if (m->m_pkthdr.csum_flags & (CSUM_IP_UDP|CSUM_IP_TCP) &
+	    ~ifp->if_hwassist) {
 		in_delayed_cksum(m);
-		m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+		m->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP|CSUM_IP_TCP);
 	}
 #ifdef SCTP
-	if (m->m_pkthdr.csum_flags & CSUM_SCTP & ~ifp->if_hwassist) {
+	else if (m->m_pkthdr.csum_flags & CSUM_IP_SCTP & ~ifp->if_hwassist) {
 		sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
-		m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+		m->m_pkthdr.csum_flags &= ~CSUM_IP_SCTP;
 	}
 #endif
 
@@ -599,8 +590,8 @@ passout:
 	 * care of the fragmentation for us, we can just send directly.
 	 */
 	if (ip_len <= mtu ||
-	    (m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 ||
-	    ((ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_IPFRAG))) {
+	    (m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_IP_TSO) != 0 ||
+	    ((ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_IP_FRAGO))) {
 		ip->ip_sum = 0;
 		if (m->m_pkthdr.csum_flags & CSUM_IP & ~ifp->if_hwassist) {
 			ip->ip_sum = in_cksum(m, hlen);
@@ -609,12 +600,12 @@ passout:
 
 		/*
 		 * Record statistics for this interface address.
-		 * With CSUM_TSO the byte/packet count will be slightly
+		 * With CSUM_IP_TSO the byte/packet count will be slightly
 		 * incorrect because we count the IP+TCP headers only
 		 * once instead of for every generated packet.
 		 */
 		if (!(flags & IP_FORWARDING) && ia) {
-			if (m->m_pkthdr.csum_flags & CSUM_TSO)
+			if (m->m_pkthdr.csum_flags & CSUM_IP_TSO)
 				ia->ia_ifa.if_opackets +=
 				    m->m_pkthdr.len / m->m_pkthdr.tso_segsz;
 			else
@@ -636,7 +627,7 @@ passout:
 	}
 
 	/* Balk when DF bit is set or the interface didn't support TSO. */
-	if ((ip_off & IP_DF) || (m->m_pkthdr.csum_flags & CSUM_TSO)) {
+	if ((ip_off & IP_DF) || (m->m_pkthdr.csum_flags & CSUM_IP_TSO)) {
 		error = EMSGSIZE;
 		IPSTAT_INC(ips_cantfrag);
 		goto bad;
@@ -724,14 +715,14 @@ ip_fragment(struct ip *ip, struct mbuf *
 	 * If the interface will not calculate checksums on
 	 * fragmented packets, then do it here.
 	 */
-	if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+	if (m0->m_pkthdr.csum_flags & (CSUM_IP_UDP|CSUM_IP_TCP)) {
 		in_delayed_cksum(m0);
-		m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+		m0->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP|CSUM_IP_TCP);
 	}
 #ifdef SCTP
-	if (m0->m_pkthdr.csum_flags & CSUM_SCTP) {
+	if (m0->m_pkthdr.csum_flags & CSUM_IP_SCTP) {
 		sctp_delayed_cksum(m0, hlen);
-		m0->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+		m0->m_pkthdr.csum_flags &= ~CSUM_IP_SCTP;
 	}
 #endif
 	if (len > PAGE_SIZE) {
@@ -872,7 +863,7 @@ in_delayed_cksum(struct mbuf *m)
 	offset = ip->ip_hl << 2 ;
 	ip_len = ntohs(ip->ip_len);
 	csum = in_cksum_skip(m, ip_len, offset);
-	if (m->m_pkthdr.csum_flags & CSUM_UDP && csum == 0)
+	if (m->m_pkthdr.csum_flags & CSUM_IP_UDP && csum == 0)
 		csum = 0xffff;
 	offset += m->m_pkthdr.csum_data;	/* checksum offset */
 
@@ -1296,11 +1287,11 @@ ip_mloopback(struct ifnet *ifp, struct m
 		copym = m_pullup(copym, hlen);
 	if (copym != NULL) {
 		/* If needed, compute the checksum and mark it as valid. */
-		if (copym->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+		if (copym->m_pkthdr.csum_flags & (CSUM_IP_UDP|CSUM_IP_TCP)) {
 			in_delayed_cksum(copym);
-			copym->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+			copym->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP|CSUM_IP_TCP);
 			copym->m_pkthdr.csum_flags |=
-			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+			    CSUM_L4_CALC | CSUM_L4_VALID;
 			copym->m_pkthdr.csum_data = 0xffff;
 		}
 		/*

Modified: user/andre/tcp_workqueue/sys/netinet/sctp_input.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/sctp_input.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/sctp_input.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -6064,9 +6064,15 @@ sctp_input_with_port(struct mbuf *i_pak,
 #if defined(SCTP_WITH_NO_CSUM)
 	SCTP_STAT_INCR(sctps_recvnocrc);
 #else
-	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
+	if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+	    (CSUM_L4_CALC | CSUM_L4_VALID)) {
 		SCTP_STAT_INCR(sctps_recvhwcrc);
 		compute_crc = 0;
+	} else if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+	    CSUM_L4_CALC) {
+		SCTP_STAT_INCR(sctps_badsum);
+		SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
+		goto out;
 	} else {
 		SCTP_STAT_INCR(sctps_recvswcrc);
 		compute_crc = 1;

Modified: user/andre/tcp_workqueue/sys/netinet/sctp_os_bsd.h
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/sctp_os_bsd.h	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/sctp_os_bsd.h	Mon Nov 19 18:04:17 2012	(r243291)
@@ -366,8 +366,8 @@ typedef struct callout sctp_os_timer_t;
 #define SCTP_RELEASE_HEADER(m)
 #define SCTP_RELEASE_PKT(m)	sctp_m_freem(m)
 #define SCTP_ENABLE_UDP_CSUM(m) do { \
-					m->m_pkthdr.csum_flags = CSUM_UDP; \
-					m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); \
+					m->m_pkthdr.csum_flags = CSUM_IP_UDP; \
+					m->m_pkthdr.csum_l4hlen = sizeof(struct udphdr); \
 				} while (0)
 
 #define SCTP_GET_PKT_VRFID(m, vrf_id)  ((vrf_id = SCTP_DEFAULT_VRFID) != SCTP_DEFAULT_VRFID)

Modified: user/andre/tcp_workqueue/sys/netinet/sctp_output.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/sctp_output.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/sctp_output.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -4129,7 +4129,7 @@ sctp_lowlevel_chunk_output(struct sctp_i
 #if defined(SCTP_WITH_NO_CSUM)
 				SCTP_STAT_INCR(sctps_sendnocrc);
 #else
-				m->m_pkthdr.csum_flags = CSUM_SCTP;
+				m->m_pkthdr.csum_flags = CSUM_IP_SCTP;
 				m->m_pkthdr.csum_l4hlen = sizeof(struct sctphdr);
 				SCTP_STAT_INCR(sctps_sendhwcrc);
 #endif
@@ -4478,7 +4478,7 @@ sctp_lowlevel_chunk_output(struct sctp_i
 #if defined(SCTP_WITH_NO_CSUM)
 				SCTP_STAT_INCR(sctps_sendnocrc);
 #else
-				m->m_pkthdr.csum_flags = CSUM_SCTP_IPV6;
+				m->m_pkthdr.csum_flags = CSUM_IP6_SCTP;
 				m->m_pkthdr.csum_l4hlen = sizeof(struct sctphdr);
 				SCTP_STAT_INCR(sctps_sendhwcrc);
 #endif
@@ -11005,7 +11005,7 @@ sctp_send_resp_msg(struct sockaddr *src,
 #if defined(SCTP_WITH_NO_CSUM)
 			SCTP_STAT_INCR(sctps_sendnocrc);
 #else
-			mout->m_pkthdr.csum_flags = CSUM_SCTP;
+			mout->m_pkthdr.csum_flags = CSUM_IP_SCTP;
 			mout->m_pkthdr.csum_l4hlen = sizeof(struct sctphdr);
 			SCTP_STAT_INCR(sctps_sendhwcrc);
 #endif
@@ -11035,7 +11035,7 @@ sctp_send_resp_msg(struct sockaddr *src,
 #if defined(SCTP_WITH_NO_CSUM)
 			SCTP_STAT_INCR(sctps_sendnocrc);
 #else
-			mout->m_pkthdr.csum_flags = CSUM_SCTP_IPV6;
+			mout->m_pkthdr.csum_flags = CSUM_IP6_SCTP;
 			mout->m_pkthdr.csum_l4hlen = sizeof(struct sctphdr);
 			SCTP_STAT_INCR(sctps_sendhwcrc);
 #endif

Modified: user/andre/tcp_workqueue/sys/netinet/siftr.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/siftr.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/siftr.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -904,7 +904,7 @@ siftr_chkpkt(void *arg, struct mbuf **m,
 	siftr_siftdata(pn, inp, tp, INP_IPV4, dir, inp_locally_locked);
 
 	if (siftr_generate_hashes) {
-		if ((*m)->m_pkthdr.csum_flags & CSUM_TCP) {
+		if ((*m)->m_pkthdr.csum_flags & CSUM_IP_TCP) {
 			/*
 			 * For outbound packets, the TCP checksum isn't
 			 * calculated yet. This is a problem for our packet
@@ -915,7 +915,7 @@ siftr_chkpkt(void *arg, struct mbuf **m,
 			 * software. We unset the CSUM_TCP flag so the lower
 			 * layers don't recalc it.
 			 */
-			(*m)->m_pkthdr.csum_flags &= ~CSUM_TCP;
+			(*m)->m_pkthdr.csum_flags &= ~CSUM_IP_TCP;
 
 			/*
 			 * Calculate the TCP checksum in software and assign

Modified: user/andre/tcp_workqueue/sys/netinet/tcp_input.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/tcp_input.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/tcp_input.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -614,16 +614,13 @@ tcp_input(struct mbuf *m, int off0)
 		ip6 = mtod(m, struct ip6_hdr *);
 		th = (struct tcphdr *)((caddr_t)ip6 + off0);
 		tlen = sizeof(*ip6) + ntohs(ip6->ip6_plen) - off0;
-		if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) {
-			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) {
+
+		if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+		    CSUM_L4_CALC) {
+			TCPSTAT_INC(tcps_rcvbadsum);
+			goto drop;
+		} else if (!(m->m_pkthdr.csum_flags & CSUM_L4_VALID) &&
+		    in6_cksum(m, IPPROTO_TCP, off0, tlen)) {
 			TCPSTAT_INC(tcps_rcvbadsum);
 			goto drop;
 		}
@@ -666,16 +663,11 @@ tcp_input(struct mbuf *m, int off0)
 		th = (struct tcphdr *)((caddr_t)ip + off0);
 		tlen = ntohs(ip->ip_len) - off0;
 
-		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 = in_pseudo(ip->ip_src.s_addr,
-				    ip->ip_dst.s_addr,
-				    htonl(m->m_pkthdr.csum_data + tlen +
-				    IPPROTO_TCP));
-			th->th_sum ^= 0xffff;
-		} else {
+		if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+		    CSUM_L4_CALC) {
+			TCPSTAT_INC(tcps_rcvbadsum);
+			goto drop;
+		} else if (!(m->m_pkthdr.csum_flags & CSUM_L4_VALID)) {
 			struct ipovly *ipov = (struct ipovly *)ip;
 
 			/*
@@ -685,10 +677,11 @@ tcp_input(struct mbuf *m, int off0)
 			bzero(ipov->ih_x1, sizeof(ipov->ih_x1));
 			ipov->ih_len = htons(tlen);
 			th->th_sum = in_cksum(m, len);
-		}
-		if (th->th_sum) {
-			TCPSTAT_INC(tcps_rcvbadsum);
-			goto drop;
+
+			if (th->th_sum) {
+				TCPSTAT_INC(tcps_rcvbadsum);
+				goto drop;
+			}
 		}
 		/* Re-initialization for later version check */
 		ip->ip_v = IPVERSION;
@@ -3610,7 +3603,7 @@ tcp_mss(struct tcpcb *tp, int offer)
 	SOCKBUF_UNLOCK(&so->so_rcv);
 
 	/* Check the interface for TSO capabilities. */
-	if (mtuflags & CSUM_TSO)
+	if (mtuflags & CSUM_IP_TSO)
 		tp->t_flags |= TF_TSO;
 }
 

Modified: user/andre/tcp_workqueue/sys/netinet/tcp_lro.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/tcp_lro.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/tcp_lro.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -211,8 +211,8 @@ tcp_lro_flush(struct lro_ctrl *lc, struc
 			ip6 = le->le_ip6;
 			ip6->ip6_plen = p_len;
 			th = (struct tcphdr *)(ip6 + 1);
-			le->m_head->m_pkthdr.csum_flags = CSUM_DATA_VALID |
-			    CSUM_PSEUDO_HDR;
+			le->m_head->m_pkthdr.csum_flags = CSUM_L4_CALC |
+			    CSUM_L4_VALID;
 			le->p_len += ETHER_HDR_LEN + sizeof(*ip6);
 			break;
 		}
@@ -242,8 +242,8 @@ tcp_lro_flush(struct lro_ctrl *lc, struc
 #endif
 			ip4->ip_len = p_len;
 			th = (struct tcphdr *)(ip4 + 1);
-			le->m_head->m_pkthdr.csum_flags = CSUM_DATA_VALID |
-			    CSUM_PSEUDO_HDR | CSUM_IP_CHECKED | CSUM_IP_VALID;
+			le->m_head->m_pkthdr.csum_flags = CSUM_L4_CALC |
+			    CSUM_L4_VALID | CSUM_L3_CALC | CSUM_L3_VALID;
 			le->p_len += ETHER_HDR_LEN;
 			break;
 		}
@@ -310,7 +310,6 @@ static int
 tcp_lro_rx_ipv4(struct lro_ctrl *lc, struct mbuf *m, struct ip *ip4,
     struct tcphdr **th)
 {
-	int csum_flags;
 	uint16_t csum;
 
 	if (ip4->ip_p != IPPROTO_TCP)
@@ -325,18 +324,17 @@ tcp_lro_rx_ipv4(struct lro_ctrl *lc, str
 		return (TCP_LRO_CANNOT);
 
 	/* Legacy IP has a header checksum that needs to be correct. */
-	csum_flags = m->m_pkthdr.csum_flags;
-	if (csum_flags & CSUM_IP_CHECKED) {
-		if (__predict_false((csum_flags & CSUM_IP_VALID) == 0)) {
-			lc->lro_bad_csum++;
-			return (TCP_LRO_CANNOT);
-		}
-	} else {
+	if ((m->m_pkthdr.csum_flags & (CSUM_L3_CALC | CSUM_L3_VALID)) ==
+	    CSUM_L3_CALC) {
+		lc->lro_bad_csum++;
+		return (TCP_LRO_CANNOT);
+	} else if (!(m->m_pkthdr.csum_flags & CSUM_L3_VALID)) {
 		csum = in_cksum_hdr(ip4);
 		if (__predict_false((csum ^ 0xffff) != 0)) {
 			lc->lro_bad_csum++;
 			return (TCP_LRO_CANNOT);
 		}
+		m->m_pkthdr.csum_flags |= (CSUM_L3_CALC | CSUM_L3_VALID);
 	}
 
 	/* Find the TCP header (we assured there are no IP options). */

Modified: user/andre/tcp_workqueue/sys/netinet/tcp_output.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/tcp_output.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/tcp_output.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -1085,7 +1085,7 @@ send:
 		 * ip6_plen is not need to be filled now, and will be filled
 		 * in ip6_output.
 		 */
-		m->m_pkthdr.csum_flags = CSUM_TCP_IPV6;
+		m->m_pkthdr.csum_flags = CSUM_IP6_TCP;
 		th->th_sum = in6_cksum_pseudo(ip6, sizeof(struct tcphdr) +
 		    optlen + len, IPPROTO_TCP, 0);
 	}
@@ -1095,7 +1095,7 @@ send:
 #endif
 #ifdef INET
 	{
-		m->m_pkthdr.csum_flags = CSUM_TCP;
+		m->m_pkthdr.csum_flags = CSUM_IP_TCP;
 		th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
 		    htons(sizeof(struct tcphdr) + IPPROTO_TCP + len + optlen));
 
@@ -1113,7 +1113,10 @@ send:
 	if (tso) {
 		KASSERT(len > tp->t_maxopd - optlen,
 		    ("%s: len <= tso_segsz", __func__));
-		m->m_pkthdr.csum_flags |= CSUM_TSO;
+		if (isipv6)
+			m->m_pkthdr.csum_flags |= CSUM_IP6_TSO;
+		else
+			m->m_pkthdr.csum_flags |= CSUM_IP_TSO;
 		m->m_pkthdr.tso_segsz = tp->t_maxopd - optlen;
 	}
 

Modified: user/andre/tcp_workqueue/sys/netinet/tcp_subr.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/tcp_subr.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/tcp_subr.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -623,12 +623,10 @@ tcp_respond(struct tcpcb *tp, void *ipge
 		nth->th_win = htons((u_short)win);
 	nth->th_urp = 0;
 
-	m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+	m->m_pkthdr.csum_l4hlen = sizeof(struct tcphdr);
 #ifdef INET6
 	if (isipv6) {
-		m->m_pkthdr.csum_flags = CSUM_TCP_IPV6;
-		nth->th_sum = in6_cksum_pseudo(ip6,
-		    tlen - sizeof(struct ip6_hdr), IPPROTO_TCP, 0);
+		m->m_pkthdr.csum_flags = CSUM_IP6_TCP;
 		ip6->ip6_hlim = in6_selecthlim(tp != NULL ? tp->t_inpcb :
 		    NULL, NULL);
 	}
@@ -638,9 +636,7 @@ tcp_respond(struct tcpcb *tp, void *ipge
 #endif
 #ifdef INET
 	{
-		m->m_pkthdr.csum_flags = CSUM_TCP;
-		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_IP_TCP;
 	}
 #endif /* INET */
 #ifdef TCPDEBUG
@@ -1744,8 +1740,8 @@ tcp_maxmtu(struct in_conninfo *inc, int 
 		/* Report additional interface capabilities. */
 		if (flags != NULL) {
 			if (ifp->if_capenable & IFCAP_TSO4 &&
-			    ifp->if_hwassist & CSUM_TSO)
-				*flags |= CSUM_TSO;
+			    ifp->if_hwassist & CSUM_IP_TSO)
+				*flags |= CSUM_IP_TSO;
 		}
 		RTFREE(sro.ro_rt);
 	}
@@ -1781,8 +1777,8 @@ tcp_maxmtu6(struct in_conninfo *inc, int
 		/* Report additional interface capabilities. */
 		if (flags != NULL) {
 			if (ifp->if_capenable & IFCAP_TSO6 &&
-			    ifp->if_hwassist & CSUM_TSO)
-				*flags |= CSUM_TSO;
+			    ifp->if_hwassist & CSUM_IP6_TSO)
+				*flags |= CSUM_IP6_TSO;
 		}
 		RTFREE(sro6.ro_rt);
 	}

Modified: user/andre/tcp_workqueue/sys/netinet/tcp_syncache.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/tcp_syncache.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/tcp_syncache.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -1509,12 +1509,10 @@ syncache_respond(struct syncache *sc)
 		optlen = 0;
 
 	M_SETFIB(m, sc->sc_inc.inc_fibnum);
-	m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+	m->m_pkthdr.csum_l4hlen = sizeof(struct tcphdr) + optlen;
 #ifdef INET6
 	if (sc->sc_inc.inc_flags & INC_ISIPV6) {
-		m->m_pkthdr.csum_flags = CSUM_TCP_IPV6;
-		th->th_sum = in6_cksum_pseudo(ip6, tlen + optlen - hlen,
-		    IPPROTO_TCP, 0);
+		m->m_pkthdr.csum_flags = CSUM_IP6_TCP;
 		ip6->ip6_hlim = in6_selecthlim(NULL, NULL);
 		error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
 	}
@@ -1524,9 +1522,7 @@ syncache_respond(struct syncache *sc)
 #endif
 #ifdef INET
 	{
-		m->m_pkthdr.csum_flags = CSUM_TCP;
-		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_IP_TCP;
 #ifdef TCP_OFFLOAD
 		if (ADDED_BY_TOE(sc)) {
 			struct toedev *tod = sc->sc_tod;

Modified: user/andre/tcp_workqueue/sys/netinet/tcp_timewait.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/tcp_timewait.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/tcp_timewait.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -575,12 +575,10 @@ tcp_twrespond(struct tcptw *tw, int flag
 	th->th_flags = flags;
 	th->th_win = htons(tw->last_win);
 
-	m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+	m->m_pkthdr.csum_l4hlen = sizeof(struct tcphdr) + optlen;
 #ifdef INET6
 	if (isipv6) {
-		m->m_pkthdr.csum_flags = CSUM_TCP_IPV6;
-		th->th_sum = in6_cksum_pseudo(ip6,
-		    sizeof(struct tcphdr) + optlen, IPPROTO_TCP, 0);
+		m->m_pkthdr.csum_flags = CSUM_IP6_TCP;
 		ip6->ip6_hlim = in6_selecthlim(inp, NULL);
 		error = ip6_output(m, inp->in6p_outputopts, NULL,
 		    (tw->tw_so_options & SO_DONTROUTE), NULL, NULL, inp);
@@ -591,9 +589,7 @@ tcp_twrespond(struct tcptw *tw, int flag
 #endif
 #ifdef INET
 	{
-		m->m_pkthdr.csum_flags = CSUM_TCP;
-		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_IP_TCP;
 		ip->ip_len = htons(m->m_pkthdr.len);
 		if (V_path_mtu_discovery)
 			ip->ip_off |= htons(IP_DF);

Modified: user/andre/tcp_workqueue/sys/netinet/udp_usrreq.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/udp_usrreq.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet/udp_usrreq.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -410,19 +410,15 @@ udp_input(struct mbuf *m, int off)
 
 	/*
 	 * Checksum extended UDP header and data.
+	 * NB: UDP doesn't require the checksum to be present.
 	 */
 	if (uh->uh_sum) {
-		u_short uh_sum;
+		u_short uh_sum = 0;
 
-		if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
-			if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
-				uh_sum = m->m_pkthdr.csum_data;
-			else
-				uh_sum = in_pseudo(ip->ip_src.s_addr,
-				    ip->ip_dst.s_addr, htonl((u_short)len +
-				    m->m_pkthdr.csum_data + IPPROTO_UDP));
-			uh_sum ^= 0xffff;
-		} else {
+		if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+		    CSUM_L4_CALC) {
+			uh_sum = 0x1;	/* Failed checksum check. */
+		} else if (!(m->m_pkthdr.csum_flags & CSUM_L4_VALID)) {
 			char b[9];
 
 			bcopy(((struct ipovly *)ip)->ih_x1, b, 9);
@@ -1226,7 +1222,7 @@ udp_output(struct inpcb *inp, struct mbu
 			faddr.s_addr = INADDR_BROADCAST;
 		ui->ui_sum = in_pseudo(ui->ui_src.s_addr, faddr.s_addr,
 		    htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
-		m->m_pkthdr.csum_flags = CSUM_UDP;
+		m->m_pkthdr.csum_flags = CSUM_IP_UDP;
 		m->m_pkthdr.csum_l4hlen = sizeof(struct udphdr);
 	} else
 		ui->ui_sum = 0;
@@ -1387,8 +1383,8 @@ udp4_espdecap(struct inpcb *inp, struct 
 	 * We cannot yet update the cksums so clear any
 	 * h/w cksum flags as they are no longer valid.
 	 */
-	if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID)
-		m->m_pkthdr.csum_flags &= ~(CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
+	if (m->m_pkthdr.csum_flags & CSUM_L4_CALC)
+		m->m_pkthdr.csum_flags &= ~(CSUM_L4_CALC|CSUM_L4_VALID);
 
 	(void) ipsec4_common_input(m, iphlen, ip->ip_p);
 	return (NULL);			/* NB: consumed, bypass processing. */

Modified: user/andre/tcp_workqueue/sys/netinet6/ip6_forward.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet6/ip6_forward.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet6/ip6_forward.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -577,14 +577,16 @@ skip_routing:
 			m->m_flags |= M_FASTFWD_OURS;
 			if (m->m_pkthdr.rcvif == NULL)
 				m->m_pkthdr.rcvif = V_loif;
-			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+			if (m->m_pkthdr.csum_flags &
+			    (CSUM_IP6_UDP|CSUM_IP6_TCP)) {
 				m->m_pkthdr.csum_flags |=
-				    CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
+				    CSUM_L4_CALC | CSUM_L4_VALID;
 				m->m_pkthdr.csum_data = 0xffff;
 			}
 #ifdef SCTP
-			if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
-				m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+			if (m->m_pkthdr.csum_flags & CSUM_IP6_SCTP)
+				m->m_pkthdr.csum_flags |=
+				    CSUM_L4_CALC | CSUM_L4_VALID;
 #endif
 			error = netisr_queue(NETISR_IPV6, m);
 			goto out;
@@ -596,14 +598,13 @@ skip_routing:
 	if (m->m_flags & M_FASTFWD_OURS) {
 		if (m->m_pkthdr.rcvif == NULL)
 			m->m_pkthdr.rcvif = V_loif;
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
-			m->m_pkthdr.csum_flags |=
-			    CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
+		if (m->m_pkthdr.csum_flags & (CSUM_IP6_UDP|CSUM_IP6_TCP)) {
+			m->m_pkthdr.csum_flags |= CSUM_L4_CALC | CSUM_L4_VALID;
 			m->m_pkthdr.csum_data = 0xffff;
 		}
 #ifdef SCTP
-		if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
-			m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+		if (m->m_pkthdr.csum_flags & CSUM_IP6_SCTP)
+			m->m_pkthdr.csum_flags |= CSUM_L4_CALC | CSUM_L4_VALID;
 #endif
 		error = netisr_queue(NETISR_IPV6, m);
 		goto out;

Modified: user/andre/tcp_workqueue/sys/netinet6/ip6_ipsec.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet6/ip6_ipsec.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet6/ip6_ipsec.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -288,11 +288,11 @@ ip6_ipsec_output(struct mbuf **m, struct
 		 * For IPv6 we do delayed checksums in ip6_output.c.
 		 */
 #ifdef INET
-		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+		if ((*m)->m_pkthdr.csum_flags & (CSUM_IP_UDP|CSUM_IP_TCP)) {
 			ipseclog((LOG_DEBUG,
 			    "%s: we do not support IPv4 over IPv6", __func__));
 			in_delayed_cksum(*m);
-			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+			(*m)->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP|CSUM_IP_TCP);
 		}
 #endif
 

Modified: user/andre/tcp_workqueue/sys/netinet6/ip6_output.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet6/ip6_output.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet6/ip6_output.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -307,15 +307,15 @@ ip6_output(struct mbuf *m0, struct ip6_p
 		/*
 		 * Do delayed checksums now, as we may send before returning.
 		 */
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+		if (m->m_pkthdr.csum_flags & (CSUM_IP6_UDP|CSUM_IP6_TCP)) {
 			plen = m->m_pkthdr.len - sizeof(*ip6);
 			in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr));
-			m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
+			m->m_pkthdr.csum_flags &= ~(CSUM_IP6_UDP|CSUM_IP6_TCP);
 		}
 #ifdef SCTP
-		if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
+		if (m->m_pkthdr.csum_flags & CSUM_IP6_SCTP) {
 			sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
-			m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
+			m->m_pkthdr.csum_flags &= ~CSUM_IP6_SCTP;
 		}
 #endif
 	case 0:                 /* No IPSec */
@@ -898,14 +898,16 @@ again:
 			m->m_flags |= M_FASTFWD_OURS;
 			if (m->m_pkthdr.rcvif == NULL)
 				m->m_pkthdr.rcvif = V_loif;
-			if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+			if (m->m_pkthdr.csum_flags &
+			    (CSUM_IP6_UDP|CSUM_IP6_TCP)) {
 				m->m_pkthdr.csum_flags |=
-				    CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
+				    CSUM_L4_CALC | CSUM_L4_VALID;
 				m->m_pkthdr.csum_data = 0xffff;
 			}
 #ifdef SCTP
 			if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
-				m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+				m->m_pkthdr.csum_flags |=
+				    CSUM_L4_CALC | CSUM_L4_VALID;
 #endif
 			error = netisr_queue(NETISR_IPV6, m);
 			goto done;
@@ -917,14 +919,14 @@ again:
 	if (m->m_flags & M_FASTFWD_OURS) {
 		if (m->m_pkthdr.rcvif == NULL)
 			m->m_pkthdr.rcvif = V_loif;
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+		if (m->m_pkthdr.csum_flags & (CSUM_IP6_UDP|CSUM_IP6_TCP)) {
 			m->m_pkthdr.csum_flags |=
-			    CSUM_DATA_VALID_IPV6 | CSUM_PSEUDO_HDR;
+			    CSUM_L4_CALC | CSUM_L4_VALID;
 			m->m_pkthdr.csum_data = 0xffff;
 		}
 #ifdef SCTP
 		if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
-			m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+			m->m_pkthdr.csum_flags |= CSUM_L4_CALC | CSUM_L4_VALID;
 #endif
 		error = netisr_queue(NETISR_IPV6, m);
 		goto done;
@@ -972,13 +974,13 @@ passout:
 	 * XXX-BZ  Need a framework to know when the NIC can handle it, even
 	 * with ext. hdrs.
 	 */
-	if (sw_csum & CSUM_DELAY_DATA_IPV6) {
-		sw_csum &= ~CSUM_DELAY_DATA_IPV6;
+	if (sw_csum & (CSUM_IP6_UDP|CSUM_IP6_TCP)) {
+		sw_csum &= ~(CSUM_IP6_UDP|CSUM_IP6_TCP);
 		in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr));
 	}
 #ifdef SCTP
-	if (sw_csum & CSUM_SCTP_IPV6) {
-		sw_csum &= ~CSUM_SCTP_IPV6;
+	if (sw_csum & CSUM_IP6_SCTP) {
+		sw_csum &= ~CSUM_IP6_SCTP;
 		sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
 	}
 #endif
@@ -1091,14 +1093,14 @@ passout:
 		 * fragmented packets, then do it here.
 		 * XXX-BZ handle the hw offloading case.  Need flags.
 		 */
-		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+		if (m->m_pkthdr.csum_flags & (CSUM_IP6_UDP|CSUM_IP6_TCP)) {
 			in6_delayed_cksum(m, plen, hlen);
-			m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
+			m->m_pkthdr.csum_flags &= ~(CSUM_IP6_UDP|CSUM_IP6_TCP);
 		}
 #ifdef SCTP
-		if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
+		if (m->m_pkthdr.csum_flags & CSUM_IP6_SCTP) {
 			sctp_delayed_cksum(m, hlen);
-			m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
+			m->m_pkthdr.csum_flags &= ~CSUM_IP6_SCTP;
 		}
 #endif
 		mnext = &m->m_nextpkt;

Modified: user/andre/tcp_workqueue/sys/netinet6/sctp6_usrreq.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet6/sctp6_usrreq.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet6/sctp6_usrreq.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -169,9 +169,15 @@ sctp6_input(struct mbuf **i_pak, int *of
 #if defined(SCTP_WITH_NO_CSUM)
 	SCTP_STAT_INCR(sctps_recvnocrc);
 #else
-	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
+	if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+	    (CSUM_L4_CALC | CSUM_L4_VALID)) {
 		SCTP_STAT_INCR(sctps_recvhwcrc);
 		compute_crc = 0;
+	} else if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+	    CSUM_L4_CALC) {
+		SCTP_STAT_INCR(sctps_badsum);
+		SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
+		goto out;
 	} else {
 		SCTP_STAT_INCR(sctps_recvswcrc);
 		compute_crc = 1;

Modified: user/andre/tcp_workqueue/sys/netinet6/udp6_usrreq.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet6/udp6_usrreq.c	Mon Nov 19 17:33:45 2012	(r243290)
+++ user/andre/tcp_workqueue/sys/netinet6/udp6_usrreq.c	Mon Nov 19 18:04:17 2012	(r243291)
@@ -183,7 +183,7 @@ udp6_input(struct mbuf **mp, int *offp, 
 	int plen, ulen;
 	struct sockaddr_in6 fromsa;
 	struct m_tag *fwd_tag;
-	uint16_t uh_sum;
+	uint16_t uh_sum = 0;
 
 	ifp = m->m_pkthdr.rcvif;
 	ip6 = mtod(m, struct ip6_hdr *);
@@ -228,14 +228,10 @@ udp6_input(struct mbuf **mp, int *offp, 
 		goto badunlocked;
 	}
 
-	if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) {
-		if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
-			uh_sum = m->m_pkthdr.csum_data;
-		else
-			uh_sum = in6_cksum_pseudo(ip6, ulen,
-			    IPPROTO_UDP, m->m_pkthdr.csum_data);
-		uh_sum ^= 0xffff;
-	} else
+	if ((m->m_pkthdr.csum_flags & (CSUM_L4_CALC|CSUM_L4_VALID)) ==
+	    CSUM_L4_CALC) {
+		uh_sum = 1;
+	} else if (!(m->m_pkthdr.csum_flags & CSUM_L4_VALID))
 		uh_sum = in6_cksum(m, IPPROTO_UDP, off, ulen);
 
 	if (uh_sum != 0) {
@@ -780,8 +776,8 @@ udp6_output(struct inpcb *inp, struct mb
 		ip6->ip6_dst	= *faddr;
 
 		udp6->uh_sum = in6_cksum_pseudo(ip6, plen, IPPROTO_UDP, 0);
-		m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
-		m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+		m->m_pkthdr.csum_flags = CSUM_IP6_UDP;
+		m->m_pkthdr.csum_l4hlen = sizeof(struct udphdr);
 
 		flags = 0;
 

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list