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
This commit is contained in:
Randall Stewart 2010-04-05 13:48:23 +00:00
parent 9b355dc71d
commit 54bb41671a
7 changed files with 26 additions and 9 deletions

View file

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

View file

@ -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);
}

View file

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

View file

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

View file

@ -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);

View file

@ -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 */

View file

@ -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_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))