diff --git a/sys/dev/xen/netback/netback.c b/sys/dev/xen/netback/netback.c index a6111e265f5..3088ecbdd12 100644 --- a/sys/dev/xen/netback/netback.c +++ b/sys/dev/xen/netback/netback.c @@ -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 { diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index a2caef54a30..6c48b5b89d6 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -234,7 +234,7 @@ divert_packet(struct mbuf *m, int incoming) #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); } diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c index 0eb4673a038..65ec49eb5a4 100644 --- a/sys/netinet/ip_ipsec.c +++ b/sys/netinet/ip_ipsec.c @@ -343,7 +343,7 @@ ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, } #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 diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 00c3c3ceacf..a10976a06b6 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -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 **m_frag, int mtu, #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 diff --git a/sys/netinet/sctp_crc32.c b/sys/netinet/sctp_crc32.c index aeb97153855..d9ae238835f 100644 --- a/sys/netinet/sctp_crc32.c +++ b/sys/netinet/sctp_crc32.c @@ -127,14 +127,12 @@ sctp_calculate_cksum(struct mbuf *m, uint32_t offset) 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); diff --git a/sys/netinet/sctp_crc32.h b/sys/netinet/sctp_crc32.h index 44196b16abe..e66815ee517 100644 --- a/sys/netinet/sctp_crc32.h +++ b/sys/netinet/sctp_crc32.h @@ -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 */ diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index c2ec49aa350..a878aacf79f 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_sctp.h" #include #include @@ -102,6 +103,10 @@ __FBSDID("$FreeBSD$"); #include #include #endif /* IPSEC */ +#ifdef SCTP +#include +#include +#endif #include #include @@ -208,6 +213,9 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, 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))