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

Michael Tuexen tuexen at fh-muenster.de
Mon Nov 19 18:57:36 UTC 2012


On Nov 19, 2012, at 7:04 PM, Andre Oppermann wrote:

> 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.
I looked at the code for SCTP. If the NIC reports that it computed the
checksum and the checksum is not reported as valid, you are dropping the
packet. The problem with this code is, that at least some NICs report
for small SCTP packets that the checksum is wrong. To deal with this,
I did the checksum verification is software in case the hardware reported
a bad checksum. Are you planning to deal with this in the specific drivers?

Best regards
Michael

> 
> 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