testing feng (multimedia streaming server) between freebsd and linux to stream video over ipv6/sctp. Connection never gets to established state initiator linux running mplayer responder freebsd running feng I took a packet trace at the linux end with wireshark. It seems that the freebsd machine is sending the init_ack with a checksum of 0x00000000 linux machine also reports sctp checksum errors in proportion to number of init_acks it recieves. I am new to freebsd so feel free to tell me I'm an idiot if I've missed something or done something daft Fix: Not sure if this is relavent or not but I had a quick look in the code for sctp_output.c and ip_output.c and ip6_output.c - and there appears to code which handles delayed checksum calculation based on a flag in ip_output.c but not in ip6_output.c Workaround is use ipv4 - I tested over ipv4 without problems How-To-Repeat: run feng on freebsd configured to use sctp over ipv6 run mplayer with -rtsp-stream-over-sctp option
Responsible Changed From-To: freebsd-bugs->freebsd-net Over to maintainer(s).
Author: rrs Date: Fri Mar 12 08:10:30 2010 New Revision: 205075 URL: http://svn.freebsd.org/changeset/base/205075 Log: With the recent change of the sctp checksum to support offload, no delayed checksum was added to the ip6 output code. This causes cards that do not support SCTP checksum offload to have SCTP packets that are IPv6 NOT have the sctp checksum performed. Thus you could not communicate with a peer. This adds the missing bits to make the checksum happen for these cards. PR: 144529 MFC after: 2 weeks Modified: head/sys/netinet6/ip6_output.c Modified: head/sys/netinet6/ip6_output.c ============================================================================== --- head/sys/netinet6/ip6_output.c Fri Mar 12 07:49:10 2010 (r205074) +++ head/sys/netinet6/ip6_output.c Fri Mar 12 08:10:30 2010 (r205075) @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_sctp.h" #include <sys/param.h> #include <sys/kernel.h> @@ -102,6 +103,10 @@ __FBSDID("$FreeBSD$"); #include <netipsec/key.h> #include <netinet6/ip6_ipsec.h> #endif /* IPSEC */ +#ifdef SCTP +#include <netinet/sctp.h> +#include <netinet/sctp_crc32.h> +#endif #include <netinet6/ip6protosw.h> #include <netinet6/scope6_var.h> @@ -208,6 +213,9 @@ ip6_output(struct mbuf *m0, struct ip6_p struct route_in6 *ro_pmtu = NULL; int hdrsplit = 0; int needipsec = 0; +#ifdef SCTP + int sw_csum; +#endif #ifdef IPSEC struct ipsec_output_state state; struct ip6_rthdr *rh = NULL; @@ -829,6 +837,10 @@ again: } 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 error = netisr_queue(NETISR_IPV6, m); goto done; } else @@ -857,6 +869,13 @@ passout: * 4: if dontfrag == 1 && alwaysfrag == 1 * error, as we cannot handle this conflicting request */ +#ifdef SCTP + sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist; + if (sw_csum & CSUM_SCTP) { + sctp_delayed_cksum(m); + sw_csum &= ~CSUM_SCTP; + } +#endif tlen = m->m_pkthdr.len; if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: rrs Date: Fri Mar 12 22:58:52 2010 New Revision: 205104 URL: http://svn.freebsd.org/changeset/base/205104 Log: The proper fix for the delayed SCTP checksum is to have the delayed function take an argument as to the offset to the SCTP header. This allows it to work for V4 and V6. This of course means changing all callers of the function to either pass the header len, if they have it, or create it (ip_hl << 2 or sizeof(ip6_hdr)). PR: 144529 MFC after: 2 weeks Modified: head/sys/dev/xen/netback/netback.c head/sys/netinet/ip_divert.c head/sys/netinet/ip_ipsec.c head/sys/netinet/ip_output.c head/sys/netinet/sctp_crc32.c head/sys/netinet/sctp_crc32.h head/sys/netinet6/ip6_output.c Modified: head/sys/dev/xen/netback/netback.c ============================================================================== --- head/sys/dev/xen/netback/netback.c Fri Mar 12 22:39:35 2010 (r205103) +++ head/sys/dev/xen/netback/netback.c Fri Mar 12 22:58:52 2010 (r205104) @@ -302,7 +302,7 @@ fixup_checksum(struct mbuf *m) m->m_pkthdr.csum_flags &= ~CSUM_TCP; #ifdef SCTP } else if (sw_csum & CSUM_SCTP) { - sctp_delayed_cksum(m); + sctp_delayed_cksum(m, iphlen); sw_csum &= ~CSUM_SCTP; #endif } else { Modified: head/sys/netinet/ip_divert.c ============================================================================== --- head/sys/netinet/ip_divert.c Fri Mar 12 22:39:35 2010 (r205103) +++ head/sys/netinet/ip_divert.c Fri Mar 12 22:58:52 2010 (r205104) @@ -227,7 +227,7 @@ divert_packet(struct mbuf *m, int incomi #ifdef SCTP if (m->m_pkthdr.csum_flags & CSUM_SCTP) { ip->ip_len = ntohs(ip->ip_len); - sctp_delayed_cksum(m); + sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); m->m_pkthdr.csum_flags &= ~CSUM_SCTP; ip->ip_len = htons(ip->ip_len); } Modified: head/sys/netinet/ip_ipsec.c ============================================================================== --- head/sys/netinet/ip_ipsec.c Fri Mar 12 22:39:35 2010 (r205103) +++ head/sys/netinet/ip_ipsec.c Fri Mar 12 22:58:52 2010 (r205104) @@ -342,7 +342,7 @@ ip_ipsec_output(struct mbuf **m, struct } #ifdef SCTP if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) { - sctp_delayed_cksum(*m); + sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2)); (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP; } #endif Modified: head/sys/netinet/ip_output.c ============================================================================== --- head/sys/netinet/ip_output.c Fri Mar 12 22:39:35 2010 (r205103) +++ head/sys/netinet/ip_output.c Fri Mar 12 22:58:52 2010 (r205104) @@ -583,7 +583,7 @@ passout: } #ifdef SCTP if (sw_csum & CSUM_SCTP) { - sctp_delayed_cksum(m); + sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); sw_csum &= ~CSUM_SCTP; } #endif @@ -725,7 +725,7 @@ ip_fragment(struct ip *ip, struct mbuf * #ifdef SCTP if (m0->m_pkthdr.csum_flags & CSUM_SCTP && (if_hwassist_flags & CSUM_IP_FRAGS) == 0) { - sctp_delayed_cksum(m0); + sctp_delayed_cksum(m0, hlen); m0->m_pkthdr.csum_flags &= ~CSUM_SCTP; } #endif Modified: head/sys/netinet/sctp_crc32.c ============================================================================== --- head/sys/netinet/sctp_crc32.c Fri Mar 12 22:39:35 2010 (r205103) +++ head/sys/netinet/sctp_crc32.c Fri Mar 12 22:58:52 2010 (r205104) @@ -127,14 +127,12 @@ sctp_calculate_cksum(struct mbuf *m, uin void -sctp_delayed_cksum(struct mbuf *m) +sctp_delayed_cksum(struct mbuf *m, uint32_t offset) { struct ip *ip; uint32_t checksum; - uint32_t offset; ip = mtod(m, struct ip *); - offset = ip->ip_hl << 2; checksum = sctp_calculate_cksum(m, offset); SCTP_STAT_DECR(sctps_sendhwcrc); SCTP_STAT_INCR(sctps_sendswcrc); Modified: head/sys/netinet/sctp_crc32.h ============================================================================== --- head/sys/netinet/sctp_crc32.h Fri Mar 12 22:39:35 2010 (r205103) +++ head/sys/netinet/sctp_crc32.h Fri Mar 12 22:58:52 2010 (r205104) @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #if defined(_KERNEL) || defined(__Userspace__) uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t); -void sctp_delayed_cksum(struct mbuf *); +void sctp_delayed_cksum(struct mbuf *, uint32_t offset); #endif /* _KERNEL */ Modified: head/sys/netinet6/ip6_output.c ============================================================================== --- head/sys/netinet6/ip6_output.c Fri Mar 12 22:39:35 2010 (r205103) +++ head/sys/netinet6/ip6_output.c Fri Mar 12 22:58:52 2010 (r205104) @@ -872,7 +872,7 @@ passout: #ifdef SCTP sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist; if (sw_csum & CSUM_SCTP) { - sctp_delayed_cksum(m); + sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); sw_csum &= ~CSUM_SCTP; } #endif _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: rrs Date: Mon Apr 5 13:48:23 2010 New Revision: 206181 URL: http://svn.freebsd.org/changeset/base/206181 Log: MFC of 2 items to fix the csum for v6 issue: Revision 205075 and 205104: ---------205075---------- With the recent change of the sctp checksum to support offload, no delayed checksum was added to the ip6 output code. This causes cards that do not support SCTP checksum offload to have SCTP packets that are IPv6 NOT have the sctp checksum performed. Thus you could not communicate with a peer. This adds the missing bits to make the checksum happen for these cards. ------------------------- ---------205104---------- The proper fix for the delayed SCTP checksum is to have the delayed function take an argument as to the offset to the SCTP header. This allows it to work for V4 and V6. This of course means changing all callers of the function to either pass the header len, if they have it, or create it (ip_hl << 2 or sizeof(ip6_hdr)). ------------------------- PR: 144529 Modified: stable/8/sys/dev/xen/netback/netback.c stable/8/sys/netinet/ip_divert.c stable/8/sys/netinet/ip_ipsec.c stable/8/sys/netinet/ip_output.c stable/8/sys/netinet/sctp_crc32.c stable/8/sys/netinet/sctp_crc32.h stable/8/sys/netinet6/ip6_output.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/dev/xen/netback/netback.c ============================================================================== --- stable/8/sys/dev/xen/netback/netback.c Mon Apr 5 13:33:54 2010 (r206180) +++ stable/8/sys/dev/xen/netback/netback.c Mon Apr 5 13:48:23 2010 (r206181) @@ -302,7 +302,7 @@ fixup_checksum(struct mbuf *m) m->m_pkthdr.csum_flags &= ~CSUM_TCP; #ifdef SCTP } else if (sw_csum & CSUM_SCTP) { - sctp_delayed_cksum(m); + sctp_delayed_cksum(m, iphlen); sw_csum &= ~CSUM_SCTP; #endif } else { Modified: stable/8/sys/netinet/ip_divert.c ============================================================================== --- stable/8/sys/netinet/ip_divert.c Mon Apr 5 13:33:54 2010 (r206180) +++ stable/8/sys/netinet/ip_divert.c Mon Apr 5 13:48:23 2010 (r206181) @@ -234,7 +234,7 @@ divert_packet(struct mbuf *m, int incomi #ifdef SCTP if (m->m_pkthdr.csum_flags & CSUM_SCTP) { ip->ip_len = ntohs(ip->ip_len); - sctp_delayed_cksum(m); + sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); m->m_pkthdr.csum_flags &= ~CSUM_SCTP; ip->ip_len = htons(ip->ip_len); } Modified: stable/8/sys/netinet/ip_ipsec.c ============================================================================== --- stable/8/sys/netinet/ip_ipsec.c Mon Apr 5 13:33:54 2010 (r206180) +++ stable/8/sys/netinet/ip_ipsec.c Mon Apr 5 13:48:23 2010 (r206181) @@ -343,7 +343,7 @@ ip_ipsec_output(struct mbuf **m, struct } #ifdef SCTP if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) { - sctp_delayed_cksum(*m); + sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2)); (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP; } #endif Modified: stable/8/sys/netinet/ip_output.c ============================================================================== --- stable/8/sys/netinet/ip_output.c Mon Apr 5 13:33:54 2010 (r206180) +++ stable/8/sys/netinet/ip_output.c Mon Apr 5 13:48:23 2010 (r206181) @@ -589,7 +589,7 @@ passout: } #ifdef SCTP if (sw_csum & CSUM_SCTP) { - sctp_delayed_cksum(m); + sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); sw_csum &= ~CSUM_SCTP; } #endif @@ -731,7 +731,7 @@ ip_fragment(struct ip *ip, struct mbuf * #ifdef SCTP if (m0->m_pkthdr.csum_flags & CSUM_SCTP && (if_hwassist_flags & CSUM_IP_FRAGS) == 0) { - sctp_delayed_cksum(m0); + sctp_delayed_cksum(m0, hlen); m0->m_pkthdr.csum_flags &= ~CSUM_SCTP; } #endif Modified: stable/8/sys/netinet/sctp_crc32.c ============================================================================== --- stable/8/sys/netinet/sctp_crc32.c Mon Apr 5 13:33:54 2010 (r206180) +++ stable/8/sys/netinet/sctp_crc32.c Mon Apr 5 13:48:23 2010 (r206181) @@ -127,14 +127,12 @@ sctp_calculate_cksum(struct mbuf *m, uin void -sctp_delayed_cksum(struct mbuf *m) +sctp_delayed_cksum(struct mbuf *m, uint32_t offset) { struct ip *ip; uint32_t checksum; - uint32_t offset; ip = mtod(m, struct ip *); - offset = ip->ip_hl << 2; checksum = sctp_calculate_cksum(m, offset); SCTP_STAT_DECR(sctps_sendhwcrc); SCTP_STAT_INCR(sctps_sendswcrc); Modified: stable/8/sys/netinet/sctp_crc32.h ============================================================================== --- stable/8/sys/netinet/sctp_crc32.h Mon Apr 5 13:33:54 2010 (r206180) +++ stable/8/sys/netinet/sctp_crc32.h Mon Apr 5 13:48:23 2010 (r206181) @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #if defined(_KERNEL) || defined(__Userspace__) uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t); -void sctp_delayed_cksum(struct mbuf *); +void sctp_delayed_cksum(struct mbuf *, uint32_t offset); #endif /* _KERNEL */ Modified: stable/8/sys/netinet6/ip6_output.c ============================================================================== --- stable/8/sys/netinet6/ip6_output.c Mon Apr 5 13:33:54 2010 (r206180) +++ stable/8/sys/netinet6/ip6_output.c Mon Apr 5 13:48:23 2010 (r206181) @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_sctp.h" #include <sys/param.h> #include <sys/kernel.h> @@ -102,6 +103,10 @@ __FBSDID("$FreeBSD$"); #include <netipsec/key.h> #include <netinet6/ip6_ipsec.h> #endif /* IPSEC */ +#ifdef SCTP +#include <netinet/sctp.h> +#include <netinet/sctp_crc32.h> +#endif #include <netinet6/ip6protosw.h> #include <netinet6/scope6_var.h> @@ -208,6 +213,9 @@ ip6_output(struct mbuf *m0, struct ip6_p struct route_in6 *ro_pmtu = NULL; int hdrsplit = 0; int needipsec = 0; +#ifdef SCTP + int sw_csum; +#endif #ifdef IPSEC struct ipsec_output_state state; struct ip6_rthdr *rh = NULL; @@ -829,6 +837,10 @@ again: } 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 error = netisr_queue(NETISR_IPV6, m); goto done; } else @@ -857,6 +869,13 @@ passout: * 4: if dontfrag == 1 && alwaysfrag == 1 * error, as we cannot handle this conflicting request */ +#ifdef SCTP + sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist; + if (sw_csum & CSUM_SCTP) { + sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); + sw_csum &= ~CSUM_SCTP; + } +#endif tlen = m->m_pkthdr.len; if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
State Changed From-To: open->closed Fixed in stable/8 and head.