Date: Tue, 3 Feb 2009 11:04:03 +0000 (UTC) From: Randall Stewart <rrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r188067 - in head/sys: netinet netinet6 Message-ID: <200902031104.n13B43DG028622@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rrs Date: Tue Feb 3 11:04:03 2009 New Revision: 188067 URL: http://svn.freebsd.org/changeset/base/188067 Log: - Cleanup checksum code. - Prepare for CRC offloading, add MIB counters (RS/MT). - Bugfix: Disable CRC computation for IPv6 addresses with local scope (MT). - Bugfix: Handle close() with SO_LINGER correctly when notifications are generated during the close() call(MT). - Bugfix: Generate DRY event when sender is dry during subscription. Only for 1-to-1 style sockets (RS/MT) - Bugfix: Put vtags for the correct amount of time into time-wait (MT). - Bugfix: Clear vtag entries correctly on expiration (MT). - Bugfix: shutdown() indicates ENOTCONN when called for unconnected 1-to-1 style sockets (MT). - Bugfix: In sctp Auth code (PL). - Add support for devices that support SCTP csum offload (igb). - Add missing sctp_associd to mib sysctl xsctp_tcb structure (RS) Obtained from: With help from Peter Lei and Michael Tuexen Modified: head/sys/netinet/sctp_auth.c head/sys/netinet/sctp_constants.h head/sys/netinet/sctp_crc32.c head/sys/netinet/sctp_crc32.h head/sys/netinet/sctp_input.c head/sys/netinet/sctp_os_bsd.h head/sys/netinet/sctp_output.c head/sys/netinet/sctp_pcb.c head/sys/netinet/sctp_pcb.h head/sys/netinet/sctp_sysctl.c head/sys/netinet/sctp_uio.h head/sys/netinet/sctp_usrreq.c head/sys/netinet/sctputil.c head/sys/netinet/sctputil.h head/sys/netinet6/sctp6_usrreq.c Modified: head/sys/netinet/sctp_auth.c ============================================================================== --- head/sys/netinet/sctp_auth.c Tue Feb 3 11:00:43 2009 (r188066) +++ head/sys/netinet/sctp_auth.c Tue Feb 3 11:04:03 2009 (r188067) @@ -1645,8 +1645,10 @@ sctp_auth_get_cookie_params(struct sctp_ bcopy(p_random->random_data, new_key->key, random_len); } #else - keylen = sizeof(*p_random) + random_len + sizeof(*chunks) + num_chunks + - sizeof(*hmacs) + hmacs_len; + keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len; + if (chunks != NULL) { + keylen += sizeof(*chunks) + num_chunks; + } new_key = sctp_alloc_key(keylen); if (new_key != NULL) { /* copy in the RANDOM */ Modified: head/sys/netinet/sctp_constants.h ============================================================================== --- head/sys/netinet/sctp_constants.h Tue Feb 3 11:00:43 2009 (r188066) +++ head/sys/netinet/sctp_constants.h Tue Feb 3 11:04:03 2009 (r188067) @@ -37,8 +37,15 @@ __FBSDID("$FreeBSD$"); #define __sctp_constants_h__ /* IANA assigned port number for SCTP over UDP encapsulation */ -#define SCTP_OVER_UDP_TUNNELING_PORT 9899 - +/* For freebsd we cannot bind the port at + * startup. Otherwise what will happen is + * we really won't be bound. The user must + * put it into the sysctl... or we need + * to build a special timer for this to allow + * us to wait 1 second or so after the system + * comes up. + */ +#define SCTP_OVER_UDP_TUNNELING_PORT 0 /* Number of packets to get before sack sent by default */ #define SCTP_DEFAULT_SACK_FREQ 2 @@ -310,10 +317,6 @@ __FBSDID("$FreeBSD$"); #define SCTP_PARTIAL_DELIVERY_SHIFT 1 -/* Minimum number of bytes read by user before we - * condsider doing a rwnd update - */ - /* * default HMAC for cookies, etc... use one of the AUTH HMAC id's * SCTP_HMAC is the HMAC_ID to use @@ -323,21 +326,6 @@ __FBSDID("$FreeBSD$"); #define SCTP_SIGNATURE_SIZE SCTP_AUTH_DIGEST_LEN_SHA1 #define SCTP_SIGNATURE_ALOC_SIZE SCTP_SIGNATURE_SIZE -/* DEFINE HERE WHAT CRC YOU WANT TO USE */ -#define SCTP_USECRC_RFC2960 1 -/* #define SCTP_USECRC_FLETCHER 1 */ -/* #define SCTP_USECRC_SSHCRC32 1 */ -/* #define SCTP_USECRC_FASTCRC32 1 */ -/* #define SCTP_USECRC_CRC32 1 */ -/* #define SCTP_USECRC_TCP32 1 */ -/* #define SCTP_USECRC_CRC16SMAL 1 */ -/* #define SCTP_USECRC_CRC16 1 */ -/* #define SCTP_USECRC_MODADLER 1 */ - -#ifndef SCTP_ADLER32_BASE -#define SCTP_ADLER32_BASE 65521 -#endif - /* * the SCTP protocol signature this includes the version number encoded in * the last 4 bits of the signature. @@ -619,43 +607,16 @@ __FBSDID("$FreeBSD$"); -/* - * Number of ticks before the soxwakeup() event that is delayed is sent AFTER - * the accept() call - */ - -/* - * Of course we really don't collect stale cookies, being folks of decerning - * taste. However we do count them, if we get too many before the association - * comes up.. we give up. Below is the constant that dictates when we give it - * up...this is a implemenation dependent treatment. In ours we do not ask - * for a extension of time, but just retry this many times... - */ - /* max number of TSN's dup'd that I will hold */ #define SCTP_MAX_DUP_TSNS 20 /* * Here we define the types used when setting the retry amounts. */ -/* constants for type of set */ - -/* Maximum TSN's we will summarize in a drop report */ - /* How many drop re-attempts we make on INIT/COOKIE-ECHO */ #define SCTP_RETRY_DROPPED_THRESH 4 /* - * And the max we will keep a history of in the tcb which MUST be lower than - * 256. - */ - -/* - * Here we define the default timers and the default number of attemts we - * make for each respective side (send/init). - */ - -/* * Maxmium number of chunks a single association can have on it. Note that * this is a squishy number since the count can run over this if the user * sends a large message down .. the fragmented chunks don't count until @@ -763,7 +724,7 @@ __FBSDID("$FreeBSD$"); #define SCTP_DEBUG_INDATA1 0x01000000 #define SCTP_DEBUG_INDATA2 0x02000000 /* unused */ #define SCTP_DEBUG_INDATA3 0x04000000 /* unused */ -#define SCTP_DEBUG_INDATA4 0x08000000 /* unused */ +#define SCTP_DEBUG_CRCOFFLOAD 0x08000000 /* unused */ #define SCTP_DEBUG_USRREQ1 0x10000000 /* unused */ #define SCTP_DEBUG_USRREQ2 0x20000000 /* unused */ #define SCTP_DEBUG_PEEL1 0x40000000 @@ -783,7 +744,7 @@ __FBSDID("$FreeBSD$"); #define SCTP_INITIAL_CWND 4380 -#define SCTP_DEFAULT_MTU 1500 /* emegency default MTU */ +#define SCTP_DEFAULT_MTU 1500 /* emergency default MTU */ /* amount peer is obligated to have in rwnd or I will abort */ #define SCTP_MIN_RWND 1500 @@ -996,13 +957,6 @@ __FBSDID("$FreeBSD$"); */ #define SCTP_STACK_VTAG_HASH_SIZE 32 - -/* - * If we use the per-endpoint model than we do not have a hash table of - * entries but instead have a single head pointer and we must crawl through - * the entire list. - */ - /* * Number of seconds of time wait for a vtag. */ Modified: head/sys/netinet/sctp_crc32.c ============================================================================== --- head/sys/netinet/sctp_crc32.c Tue Feb 3 11:00:43 2009 (r188066) +++ head/sys/netinet/sctp_crc32.c Tue Feb 3 11:04:03 2009 (r188067) @@ -34,12 +34,16 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/uio.h> +#include <netinet/sctp.h> #include <netinet/sctp_os.h> #include <netinet/sctp_crc32.h> +#include <netinet/sctp_pcb.h> -#ifndef SCTP_USE_ADLER32 - - +#if !defined(SCTP_WITH_NO_CSUM) /** * * Routine Description: @@ -80,12 +84,14 @@ __FBSDID("$FreeBSD$"); * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o32[256] = @@ -134,12 +140,14 @@ uint32_t sctp_crc_tableil8_o32[256] = * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o40[256] = @@ -188,12 +196,14 @@ uint32_t sctp_crc_tableil8_o40[256] = * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o48[256] = @@ -242,12 +252,14 @@ uint32_t sctp_crc_tableil8_o48[256] = * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o56[256] = @@ -296,12 +308,14 @@ uint32_t sctp_crc_tableil8_o56[256] = * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o64[256] = @@ -350,12 +364,14 @@ uint32_t sctp_crc_tableil8_o64[256] = * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o72[256] = @@ -404,12 +420,14 @@ uint32_t sctp_crc_tableil8_o72[256] = * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o80[256] = @@ -458,12 +476,14 @@ uint32_t sctp_crc_tableil8_o80[256] = * The following CRC lookup table was generated automagically using the * following model parameters: * - * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial - * Length = .......... 32 bits Reflected Bits = ....................... TRUE - * Table Generation Offset = .............. 32 bits Number of Slices = - * ..................... 8 slices Slice Lengths = ........................ 8 - * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name = - * ............................ 8x256_tables.c + * Generator Polynomial = ................. 0x1EDC6F41 + * Generator Polynomial Length = .......... 32 bits + * Reflected Bits = ....................... TRUE + * Table Generation Offset = .............. 32 bits + * Number of Slices = ..................... 8 slices + * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 + * Directory Name = ....................... .\ + * File Name = ............................ 8x256_tables.c */ uint32_t sctp_crc_tableil8_o88[256] = @@ -506,6 +526,7 @@ uint32_t sctp_crc_tableil8_o88[256] = * end of the CRC lookup table crc_tableil8_o88 */ + static uint32_t sctp_crc32c_sb8_64_bit(uint32_t crc, unsigned char *p_buf, @@ -578,7 +599,7 @@ sctp_crc32c_sb8_64_bit(uint32_t crc, * * none */ -uint32_t +static uint32_t update_crc32(uint32_t crc32c, unsigned char *buffer, unsigned int length) @@ -662,7 +683,7 @@ uint32_t sctp_crc_c[256] = { #define SCTP_CRC32C(c,d) (c=(c>>8)^sctp_crc_c[(c^(d))&0xFF]) -uint32_t +static uint32_t old_update_crc32(uint32_t crc32c, unsigned char *buffer, unsigned int length) @@ -676,8 +697,8 @@ old_update_crc32(uint32_t crc32c, } -uint32_t -sctp_csum_finalize(uint32_t crc32c) +static uint32_t +sctp_finalize_crc32(uint32_t crc32c) { uint32_t result; @@ -709,4 +730,88 @@ sctp_csum_finalize(uint32_t crc32c) return (crc32c); } +#endif /* !defined(SCTP_WITH_NO_CSUM) */ + +#if defined(SCTP_WITH_NO_CSUM) +uint32_t +sctp_calculate_cksum(struct mbuf *m, uint32_t offset) +{ + return (0); +} + +#else +uint32_t +sctp_calculate_cksum(struct mbuf *m, uint32_t offset) +{ + /* + * given a mbuf chain with a packetheader offset by 'offset' + * pointing at a sctphdr (with csum set to 0) go through the chain + * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also + * has a side bonus as it will calculate the total length of the + * mbuf chain. Note: if offset is greater than the total mbuf + * length, checksum=1, pktlen=0 is returned (ie. no real error code) + */ + uint32_t base = 0xffffffff; + struct mbuf *at; + + at = m; + /* find the correct mbuf and offset into mbuf */ + while ((at != NULL) && (offset > (uint32_t) SCTP_BUF_LEN(at))) { + offset -= SCTP_BUF_LEN(at); /* update remaining offset + * left */ + at = SCTP_BUF_NEXT(at); + } + while (at != NULL) { + if ((SCTP_BUF_LEN(at) - offset) > 0) { + if ((SCTP_BUF_LEN(at) - offset) < 4) { + /* Use old method if less than 4 bytes */ + base = old_update_crc32(base, + (unsigned char *)(SCTP_BUF_AT(at, offset)), + (unsigned int)(SCTP_BUF_LEN(at) - offset)); + } else { + base = update_crc32(base, + (unsigned char *)(SCTP_BUF_AT(at, offset)), + (unsigned int)(SCTP_BUF_LEN(at) - offset)); + } + /* we only offset once into the first mbuf */ + } + if (offset) { + if (offset < (uint32_t) SCTP_BUF_LEN(at)) + offset = 0; + else + offset -= SCTP_BUF_LEN(at); + } + at = SCTP_BUF_NEXT(at); + } + base = sctp_finalize_crc32(base); + return (base); +} + #endif + +void +sctp_delayed_cksum(struct mbuf *m) +{ + 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); + offset += offsetof(struct sctphdr, checksum); + + if (offset + sizeof(uint32_t) > (uint32_t) (m->m_len)) { + printf("delayed m_pullup, m->len: %d off: %d p: %d\n", + (uint32_t) m->m_len, offset, ip->ip_p); + /* + * XXX this shouldn't happen, but if it does, the correct + * behavior may be to insert the checksum in the appropriate + * next mbuf in the chain. + */ + return; + } + *(uint32_t *) (m->m_data + offset) = checksum; +} Modified: head/sys/netinet/sctp_crc32.h ============================================================================== --- head/sys/netinet/sctp_crc32.h Tue Feb 3 11:00:43 2009 (r188066) +++ head/sys/netinet/sctp_crc32.h Tue Feb 3 11:04:03 2009 (r188067) @@ -36,16 +36,10 @@ __FBSDID("$FreeBSD$"); #ifndef __crc32c_h__ #define __crc32c_h__ -#ifndef SCTP_USE_ADLER32 - #if defined(_KERNEL) || defined(__Userspace__) -uint32_t update_crc32(uint32_t, unsigned char *, unsigned int); - -uint32_t old_update_crc32(uint32_t, unsigned char *, unsigned int); - -uint32_t sctp_csum_finalize(uint32_t); - +uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t); +void sctp_delayed_cksum(struct mbuf *); #endif /* _KERNEL */ -#endif /* !SCTP_USE_ADLER32 */ + #endif /* __crc32c_h__ */ Modified: head/sys/netinet/sctp_input.c ============================================================================== --- head/sys/netinet/sctp_input.c Tue Feb 3 11:00:43 2009 (r188066) +++ head/sys/netinet/sctp_input.c Tue Feb 3 11:04:03 2009 (r188067) @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_asconf.h> #include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_timer.h> +#include <netinet/sctp_crc32.h> #include <netinet/udp.h> @@ -1384,14 +1385,6 @@ sctp_process_cookie_existing(struct mbuf /* FOOBAR */ return (NULL); } - /* pre-reserve some space */ -#ifdef INET6 - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); -#else - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); -#endif - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); /* Set the len */ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); ph = mtod(op_err, struct sctp_paramhdr *); @@ -2504,15 +2497,6 @@ sctp_handle_cookie_echo(struct mbuf *m, /* FOOBAR */ return (NULL); } - /* pre-reserve some space */ -#ifdef INET6 - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); -#else - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); -#endif - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); - /* Set the len */ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); scm = mtod(op_err, struct sctp_stale_cookie_msg *); @@ -2598,9 +2582,9 @@ sctp_handle_cookie_echo(struct mbuf *m, } } } - if (to == NULL) + if (to == NULL) { return (NULL); - + } cookie_len -= SCTP_SIGNATURE_SIZE; if (*stcb == NULL) { /* this is the "normal" case... get a new TCB */ @@ -5594,7 +5578,6 @@ sctp_input_with_port(i_pak, off, port) int refcount_up = 0; int length, mlen, offset; - if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { SCTP_RELEASE_PKT(i_pak); return; @@ -5642,6 +5625,11 @@ sctp_input_with_port(i_pak, off, port) } ip = mtod(m, struct ip *); } + /* validate mbuf chain length with IP payload length */ + if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) { + SCTP_STAT_INCR(sctps_hdrops); + goto bad; + } sh = (struct sctphdr *)((caddr_t)ip + iphlen); ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(*sh)); SCTPDBG(SCTP_DEBUG_INPUT1, @@ -5659,15 +5647,26 @@ sctp_input_with_port(i_pak, off, port) goto bad; } /* validate SCTP checksum */ + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, + "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", + m->m_pkthdr.len, + if_name(m->m_pkthdr.rcvif), + m->m_pkthdr.csum_flags); + if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { + SCTP_STAT_INCR(sctps_recvhwcrc); + goto sctp_skip_csum_4; + } check = sh->checksum; /* save incoming checksum */ if ((check == 0) && (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback)) && ((ip->ip_src.s_addr == ip->ip_dst.s_addr) || (SCTP_IS_IT_LOOPBACK(m))) ) { + SCTP_STAT_INCR(sctps_recvnocrc); goto sctp_skip_csum_4; } sh->checksum = 0; /* prepare for calc */ - calc_check = sctp_calculate_sum(m, &mlen, iphlen); + calc_check = sctp_calculate_cksum(m, iphlen); + SCTP_STAT_INCR(sctps_recvswcrc); if (calc_check != check) { SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", calc_check, check, m, mlen, iphlen); @@ -5699,11 +5698,6 @@ sctp_skip_csum_4: SCTP_STAT_INCR(sctps_hdrops); goto bad; } - /* validate mbuf chain length with IP payload length */ - if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) { - SCTP_STAT_INCR(sctps_hdrops); - goto bad; - } /* * Locate pcb and tcb for datagram sctp_findassociation_addr() wants * IP/SCTP/first chunk header... Modified: head/sys/netinet/sctp_os_bsd.h ============================================================================== --- head/sys/netinet/sctp_os_bsd.h Tue Feb 3 11:00:43 2009 (r188066) +++ head/sys/netinet/sctp_os_bsd.h Tue Feb 3 11:04:03 2009 (r188067) @@ -154,11 +154,8 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT); #define MOD_IPSEC ipsec /* then define the macro(s) that hook into the vimage macros */ -#if defined(__FreeBSD__) && __FreeBSD_version >= 800056 #define MODULE_GLOBAL(__MODULE, __SYMBOL) V_ ## __SYMBOL -#else -#define MODULE_GLOBAL(__MODULE, __SYMBOL) (__SYMBOL) -#endif + /* * */ Modified: head/sys/netinet/sctp_output.c ============================================================================== --- head/sys/netinet/sctp_output.c Tue Feb 3 11:00:43 2009 (r188066) +++ head/sys/netinet/sctp_output.c Tue Feb 3 11:04:03 2009 (r188067) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_indata.h> #include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_input.h> +#include <netinet/sctp_crc32.h> #include <netinet/udp.h> #include <machine/in_cksum.h> @@ -5213,6 +5214,9 @@ sctp_lowlevel_chunk_output(struct sctp_i int ecn_ok, struct sctp_tmit_chunk *chk, int out_of_asoc_ok, + uint16_t src_port, + uint16_t dest_port, + uint32_t v_tag, uint16_t port, int so_locked, #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) @@ -5237,7 +5241,6 @@ sctp_lowlevel_chunk_output(struct sctp_i struct mbuf *newm; struct sctphdr *sctphdr; int packet_length; - uint32_t csum; int ret; uint32_t vrf_id; sctp_route_t *ro = NULL; @@ -5263,51 +5266,27 @@ sctp_lowlevel_chunk_output(struct sctp_i if ((auth != NULL) && (stcb != NULL)) { sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid); } - /* Calculate the csum and fill in the length of the packet */ - sctphdr = mtod(m, struct sctphdr *); - if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && - (stcb) && - (to->sa_family == AF_INET) && - (stcb->asoc.loopback_scope)) { - sctphdr->checksum = 0; - /* - * This can probably now be taken out since my audit shows - * no more bad pktlen's coming in. But we will wait a while - * yet. - */ - packet_length = sctp_calculate_len(m); - } else { - sctphdr->checksum = 0; - csum = sctp_calculate_sum(m, &packet_length, 0); - sctphdr->checksum = csum; - } - if (to->sa_family == AF_INET) { struct ip *ip = NULL; sctp_route_t iproute; uint8_t tos_value; + int len; + len = sizeof(struct ip) + sizeof(struct sctphdr); if (port) { - newm = sctp_get_mbuf_for_msg(sizeof(struct ip) + sizeof(struct udphdr), 1, M_DONTWAIT, 1, MT_DATA); - } else { - newm = sctp_get_mbuf_for_msg(sizeof(struct ip), 1, M_DONTWAIT, 1, MT_DATA); + len += sizeof(struct udphdr); } + newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); if (newm == NULL) { sctp_m_freem(m); SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); return (ENOMEM); } - if (port) { - SCTP_ALIGN_TO_END(newm, sizeof(struct ip) + sizeof(struct udphdr)); - SCTP_BUF_LEN(newm) = sizeof(struct ip) + sizeof(struct udphdr); - packet_length += sizeof(struct ip) + sizeof(struct udphdr); - } else { - SCTP_ALIGN_TO_END(newm, sizeof(struct ip)); - SCTP_BUF_LEN(newm) = sizeof(struct ip); - packet_length += sizeof(struct ip); - } + SCTP_ALIGN_TO_END(newm, len); + SCTP_BUF_LEN(newm) = len; SCTP_BUF_NEXT(newm) = m; m = newm; + packet_length = sctp_calculate_len(m); ip = mtod(m, struct ip *); ip->ip_v = IPVERSION; ip->ip_hl = (sizeof(struct ip) >> 2); @@ -5401,12 +5380,21 @@ sctp_lowlevel_chunk_output(struct sctp_i } } if (port) { - udp = (struct udphdr *)(ip + 1); + udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip)); udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); udp->uh_dport = port; udp->uh_ulen = htons(packet_length - sizeof(struct ip)); udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP)); + sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr)); + } else { + sctphdr = (struct sctphdr *)((caddr_t)ip + sizeof(struct ip)); } + + sctphdr->src_port = src_port; + sctphdr->dest_port = dest_port; + sctphdr->v_tag = v_tag; + sctphdr->checksum = 0; + /* * If source address selection fails and we find no route * then the ip_output should fail as well with a @@ -5517,7 +5505,25 @@ sctp_lowlevel_chunk_output(struct sctp_i #endif SCTP_ATTACH_CHAIN(o_pak, m, packet_length); if (port) { + if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && + (stcb) && + (stcb->asoc.loopback_scope))) { + sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr)); + SCTP_STAT_INCR(sctps_sendswcrc); + } else { + SCTP_STAT_INCR(sctps_sendnocrc); + } SCTP_ENABLE_UDP_CSUM(o_pak); + } else { + if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && + (stcb) && + (stcb->asoc.loopback_scope))) { + m->m_pkthdr.csum_flags = CSUM_SCTP; + m->m_pkthdr.csum_data = 0; /* FIXME MT */ + SCTP_STAT_INCR(sctps_sendhwcrc); + } else { + SCTP_STAT_INCR(sctps_sendnocrc); + } } /* send it out. table id is taken from stcb */ #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) @@ -5591,6 +5597,7 @@ sctp_lowlevel_chunk_output(struct sctp_i struct sockaddr_in6 lsa6_storage; int error; u_short prev_port = 0; + int len; if (net != NULL) { flowlabel = net->tos_flowlabel; @@ -5598,27 +5605,21 @@ sctp_lowlevel_chunk_output(struct sctp_i flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo; } + len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr); if (port) { - newm = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr) + sizeof(struct udphdr), 1, M_DONTWAIT, 1, MT_DATA); - } else { - newm = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr), 1, M_DONTWAIT, 1, MT_DATA); + len += sizeof(struct udphdr); } + newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA); if (newm == NULL) { sctp_m_freem(m); SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); return (ENOMEM); } - if (port) { - SCTP_ALIGN_TO_END(newm, sizeof(struct ip6_hdr) + sizeof(struct udphdr)); - SCTP_BUF_LEN(newm) = sizeof(struct ip6_hdr) + sizeof(struct udphdr); - packet_length += sizeof(struct ip6_hdr) + sizeof(struct udphdr); - } else { - SCTP_ALIGN_TO_END(newm, sizeof(struct ip6_hdr)); - SCTP_BUF_LEN(newm) = sizeof(struct ip6_hdr); - packet_length += sizeof(struct ip6_hdr); - } + SCTP_ALIGN_TO_END(newm, len); + SCTP_BUF_LEN(newm) = len; SCTP_BUF_NEXT(newm) = m; m = newm; + packet_length = sctp_calculate_len(m); ip6h = mtod(m, struct ip6_hdr *); /* @@ -5763,12 +5764,21 @@ sctp_lowlevel_chunk_output(struct sctp_i ip6h->ip6_src = lsa6->sin6_addr; if (port) { - udp = (struct udphdr *)(ip6h + 1); + udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr)); udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)); udp->uh_dport = port; udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr)); udp->uh_sum = 0; + sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr)); + } else { + sctphdr = (struct sctphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr)); } + + sctphdr->src_port = src_port; + sctphdr->dest_port = dest_port; + sctphdr->v_tag = v_tag; + sctphdr->checksum = 0; + /* * We set the hop limit now since there is a good chance * that our ro pointer is now filled @@ -5805,9 +5815,27 @@ sctp_lowlevel_chunk_output(struct sctp_i #endif SCTP_ATTACH_CHAIN(o_pak, m, packet_length); if (port) { + if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && + (stcb) && + (stcb->asoc.loopback_scope))) { + sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr)); + SCTP_STAT_INCR(sctps_sendswcrc); + } else { + SCTP_STAT_INCR(sctps_sendnocrc); + } if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), packet_length - sizeof(struct ip6_hdr))) == 0) { udp->uh_sum = 0xffff; } + } else { + if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && + (stcb) && + (stcb->asoc.loopback_scope))) { + m->m_pkthdr.csum_flags = CSUM_SCTP; + m->m_pkthdr.csum_data = 0; /* FIXME MT */ + SCTP_STAT_INCR(sctps_sendhwcrc); + } else { + SCTP_STAT_INCR(sctps_sendnocrc); + } } /* send it out. table id is taken from stcb */ #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING) @@ -5905,7 +5933,7 @@ sctp_send_initiate(struct sctp_inpcb *in { struct mbuf *m, *m_at, *mp_last; struct sctp_nets *net; - struct sctp_init_msg *initm; + struct sctp_init_chunk *init; struct sctp_supported_addr_param *sup_addr; struct sctp_adaptation_layer_indication *ali; struct sctp_ecn_supported_param *ecn; @@ -5961,7 +5989,7 @@ sctp_send_initiate(struct sctp_inpcb *in SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - mbuf?\n"); return; } - SCTP_BUF_LEN(m) = sizeof(struct sctp_init_msg); + SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk); /* * assume peer supports asconf in order to be able to queue local * address changes while an INIT is in flight and before the assoc @@ -5969,28 +5997,24 @@ sctp_send_initiate(struct sctp_inpcb *in */ stcb->asoc.peer_supports_asconf = 1; /* Now lets put the SCTP header in place */ - initm = mtod(m, struct sctp_init_msg *); - initm->sh.src_port = inp->sctp_lport; - initm->sh.dest_port = stcb->rport; - initm->sh.v_tag = 0; - initm->sh.checksum = 0; /* calculate later */ + init = mtod(m, struct sctp_init_chunk *); /* now the chunk header */ - initm->msg.ch.chunk_type = SCTP_INITIATION; - initm->msg.ch.chunk_flags = 0; + init->ch.chunk_type = SCTP_INITIATION; + init->ch.chunk_flags = 0; /* fill in later from mbuf we build */ - initm->msg.ch.chunk_length = 0; + init->ch.chunk_length = 0; /* place in my tag */ - initm->msg.init.initiate_tag = htonl(stcb->asoc.my_vtag); + init->init.initiate_tag = htonl(stcb->asoc.my_vtag); /* set up some of the credits. */ - initm->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), + init->init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND)); - initm->msg.init.num_outbound_streams = htons(stcb->asoc.pre_open_streams); - initm->msg.init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams); - initm->msg.init.initial_tsn = htonl(stcb->asoc.init_seq_number); + init->init.num_outbound_streams = htons(stcb->asoc.pre_open_streams); + init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams); + init->init.initial_tsn = htonl(stcb->asoc.init_seq_number); /* now the address restriction */ - sup_addr = (struct sctp_supported_addr_param *)((caddr_t)initm + - sizeof(*initm)); + sup_addr = (struct sctp_supported_addr_param *)((caddr_t)init + + sizeof(*init)); sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE); #ifdef INET6 /* we support 2 types: IPv6/IPv4 */ @@ -6004,7 +6028,6 @@ sctp_send_initiate(struct sctp_inpcb *in sup_addr->addr_type[1] = htons(0); /* this is the padding */ #endif SCTP_BUF_LEN(m) += sizeof(*sup_addr) + sizeof(uint16_t); - /* adaptation layer indication parameter */ ali = (struct sctp_adaptation_layer_indication *)((caddr_t)sup_addr + sizeof(*sup_addr) + sizeof(uint16_t)); ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); @@ -6013,6 +6036,16 @@ sctp_send_initiate(struct sctp_inpcb *in SCTP_BUF_LEN(m) += sizeof(*ali); ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali)); + if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) { + /* Add NAT friendly parameter */ + struct sctp_paramhdr *ph; + + ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); + ph->param_type = htons(SCTP_HAS_NAT_SUPPORT); + ph->param_length = htons(sizeof(struct sctp_paramhdr)); + SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr); + ecn = (struct sctp_ecn_supported_param *)((caddr_t)ph + sizeof(*ph)); + } /* now any cookie time extensions */ if (stcb->asoc.cookie_preserve_req) { struct sctp_cookie_perserve_param *cookie_preserve; @@ -6052,19 +6085,22 @@ sctp_send_initiate(struct sctp_inpcb *in pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN; pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED; pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET; - if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) + if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) { pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION; + } /* * EY if the initiator supports nr_sacks, need to report that to * responder in INIT chunk */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) + if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) { pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK; + } p_len = sizeof(*pr_supported) + num_ext; pr_supported->ph.param_length = htons(p_len); bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len); SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); + /* ECN nonce: And now tell the peer we support ECN nonce */ if (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) { ecn_nonce = (struct sctp_ecn_nonce_supported_param *) @@ -6073,15 +6109,6 @@ sctp_send_initiate(struct sctp_inpcb *in ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce)); SCTP_BUF_LEN(m) += sizeof(*ecn_nonce); } - if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) { - /* Add NAT friendly parameter */ - struct sctp_paramhdr *ph; - - ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); - ph->param_type = htons(SCTP_HAS_NAT_SUPPORT); - ph->param_length = htons(sizeof(struct sctp_paramhdr)); - SCTP_BUF_LEN(m) += sizeof(sizeof(struct sctp_paramhdr)); - } /* add authentication parameters */ if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) { struct sctp_auth_random *randp; @@ -6160,7 +6187,7 @@ sctp_send_initiate(struct sctp_inpcb *in mp_last = m_at; p_len += SCTP_BUF_LEN(m_at); } - initm->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr))); + init->ch.chunk_length = htons(p_len); /* * We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return * here since the timer will drive a retranmission. @@ -6185,7 +6212,9 @@ sctp_send_initiate(struct sctp_inpcb *in SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - calls lowlevel_output\n"); ret = sctp_lowlevel_chunk_output(inp, stcb, net, (struct sockaddr *)&net->ro._l_addr, - m, 0, NULL, 0, 0, 0, NULL, 0, net->port, so_locked, NULL); + m, 0, NULL, 0, 0, 0, NULL, 0, + inp->sctp_lport, stcb->rport, htonl(0), + net->port, so_locked, NULL); SCTPDBG(SCTP_DEBUG_OUTPUT4, "lowlevel_output - %d\n", ret); SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks); sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, net); @@ -6711,7 +6740,7 @@ sctp_send_initiate_ack(struct sctp_inpcb { struct sctp_association *asoc; struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last; - struct sctp_init_msg *initackm_out; + struct sctp_init_ack_chunk *initack; struct sctp_adaptation_layer_indication *ali; struct sctp_ecn_supported_param *ecn; struct sctp_prsctp_supported_param *prsctp; @@ -6776,7 +6805,7 @@ do_a_abort: sctp_m_freem(op_err); return; } - SCTP_BUF_LEN(m) = sizeof(struct sctp_init_msg); + SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk); /* the time I built cookie */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902031104.n13B43DG028622>