diff options
author | rrs <rrs@FreeBSD.org> | 2009-02-03 11:00:43 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2009-02-03 11:00:43 +0000 |
commit | 2688c691800f6933c6b9eeeb46cf522db6f1af5c (patch) | |
tree | 23b147e1d579bbf8d4eb4845fe7846b01184ffc7 | |
parent | 3091212869dee5f2673091658796eb1badc0135f (diff) | |
download | FreeBSD-src-2688c691800f6933c6b9eeeb46cf522db6f1af5c.zip FreeBSD-src-2688c691800f6933c6b9eeeb46cf522db6f1af5c.tar.gz |
Adds support for SCTP checksum offload. This means
we, like TCP and UDP, move the checksum calculation
into the IP routines when there is no hardware support
we call into the normal SCTP checksum routine.
The next round of SCTP updates will use
this functionality. Of course the IGB driver needs
a few updates to support the new intel controller set
that actually does SCTP csum offload too.
Reviewed by: gnn, rwatson, kmacy
-rw-r--r-- | sys/dev/xen/netback/netback.c | 13 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_divert.c | 13 | ||||
-rw-r--r-- | sys/netinet/ip_ipsec.c | 11 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 28 |
5 files changed, 64 insertions, 5 deletions
diff --git a/sys/dev/xen/netback/netback.c b/sys/dev/xen/netback/netback.c index 950a68c..a6111e2 100644 --- a/sys/dev/xen/netback/netback.c +++ b/sys/dev/xen/netback/netback.c @@ -30,6 +30,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_sctp.h" #include <sys/param.h> #include <sys/systm.h> @@ -57,6 +58,10 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip.h> #include <netinet/tcp.h> #include <netinet/udp.h> +#ifdef SCTP +#include <netinet/sctp.h> +#include <netinet/sctp_crc32.h> +#endif #include <vm/vm_extern.h> #include <vm/vm_kern.h> @@ -295,6 +300,11 @@ fixup_checksum(struct mbuf *m) htons(IPPROTO_TCP + (iplen - iphlen))); th->th_sum = in_cksum_skip(m, iplen + sizeof(*eh), sizeof(*eh) + iphlen); m->m_pkthdr.csum_flags &= ~CSUM_TCP; +#ifdef SCTP + } else if (sw_csum & CSUM_SCTP) { + sctp_delayed_cksum(m); + sw_csum &= ~CSUM_SCTP; +#endif } else { u_short csum; struct udphdr *uh = (struct udphdr *)((caddr_t)ip + iphlen); @@ -908,7 +918,8 @@ netif_rx(netif_t *netif) #ifdef XEN_NETBACK_FIXUP_CSUM /* Check if we need to compute a checksum. This happens */ /* when bridging from one domain to another. */ - if ((m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) + if ((m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) || + (m->m_pkthdr.csum_flags & CSUM_SCTP)) fixup_checksum(m); #endif diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 73a08dd..e74bb74 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -299,6 +299,8 @@ ether_output(struct ifnet *ifp, struct mbuf *m, 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; m->m_pkthdr.csum_data = 0xffff; return (if_simloop(ifp, m, dst->sa_family, 0)); @@ -339,6 +341,8 @@ ether_output(struct ifnet *ifp, struct mbuf *m, 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; if (m->m_flags & M_BCAST) { struct mbuf *n; diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index d6eb16f..c2e3191 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_ipfw.h" #include "opt_mac.h" +#include "opt_sctp.h" #ifndef INET #error "IPDIVERT requires INET." #endif @@ -76,6 +77,9 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_var.h> #include <netinet/ip_fw.h> #include <netinet/vinet.h> +#ifdef SCTP +#include <netinet/sctp_crc32.h> +#endif #include <security/mac/mac_framework.h> @@ -222,7 +226,14 @@ divert_packet(struct mbuf *m, int incoming) m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; ip->ip_len = htons(ip->ip_len); } - +#ifdef SCTP + if (m->m_pkthdr.csum_flags & CSUM_SCTP) { + ip->ip_len = ntohs(ip->ip_len); + sctp_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_SCTP; + ip->ip_len = htons(ip->ip_len); + } +#endif /* * Record receive interface address, if any. * But only for incoming packets. diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c index a1e082b..77e9aa7 100644 --- a/sys/netinet/ip_ipsec.c +++ b/sys/netinet/ip_ipsec.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ipsec.h" +#include "opt_sctp.h" #include <sys/param.h> #include <sys/systm.h> @@ -56,6 +57,9 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_options.h> #include <netinet/ip_ipsec.h> #include <netinet/vinet.h> +#ifdef SCTP +#include <netinet/sctp_crc32.h> +#endif #include <machine/in_cksum.h> @@ -328,7 +332,12 @@ ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, in_delayed_cksum(*m); (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } - +#ifdef SCTP + if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) { + sctp_delayed_cksum(*m); + (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP; + } +#endif ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 2717d6e..feacb51 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include "opt_mac.h" #include "opt_mbuf_stress_test.h" #include "opt_mpath.h" +#include "opt_sctp.h" #include <sys/param.h> #include <sys/systm.h> @@ -70,6 +71,10 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_var.h> #include <netinet/ip_options.h> #include <netinet/vinet.h> +#ifdef SCTP +#include <netinet/sctp.h> +#include <netinet/sctp_crc32.h> +#endif #ifdef IPSEC #include <netinet/ip_ipsec.h> @@ -485,7 +490,10 @@ sendit: } 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_IP, m); goto done; } else @@ -502,6 +510,10 @@ sendit: 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; @@ -536,6 +548,12 @@ passout: in_delayed_cksum(m); sw_csum &= ~CSUM_DELAY_DATA; } +#ifdef SCTP + if (sw_csum & CSUM_SCTP) { + sctp_delayed_cksum(m); + sw_csum &= ~CSUM_SCTP; + } +#endif m->m_pkthdr.csum_flags &= ifp->if_hwassist; /* @@ -670,7 +688,13 @@ ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, in_delayed_cksum(m0); m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } - +#ifdef SCTP + if (m0->m_pkthdr.csum_flags & CSUM_SCTP && + (if_hwassist_flags & CSUM_IP_FRAGS) == 0) { + sctp_delayed_cksum(m0); + m0->m_pkthdr.csum_flags &= ~CSUM_SCTP; + } +#endif if (len > PAGE_SIZE) { /* * Fragment large datagrams such that each segment |