diff options
| -rw-r--r-- | include/net/sctp/sctp.h | 1 | ||||
| -rw-r--r-- | net/sctp/adler32.c | 45 | ||||
| -rw-r--r-- | net/sctp/crc32c.c | 17 | ||||
| -rw-r--r-- | net/sctp/output.c | 93 |
4 files changed, 95 insertions, 61 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 8df5bc7983af..b589528d646d 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -153,6 +153,7 @@ extern int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg) extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count); extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum); extern __u32 sctp_end_cksum(__u32 cksum); +extern __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum); /* * sctp/input.c diff --git a/net/sctp/adler32.c b/net/sctp/adler32.c index 336620187cbb..93068b2d55cf 100644 --- a/net/sctp/adler32.c +++ b/net/sctp/adler32.c @@ -2,43 +2,43 @@ * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2003 International Business Machines, Corp. - * + * * This file is part of the SCTP kernel reference Implementation - * - * This file has direct heritage from the SCTP user-level reference + * + * This file has direct heritage from the SCTP user-level reference * implementation by R. Stewart, et al. These functions implement the - * Adler-32 algorithm as specified by RFC 2960. - * - * The SCTP reference implementation is free software; - * you can redistribute it and/or modify it under the terms of + * Adler-32 algorithm as specified by RFC 2960. + * + * The SCTP reference implementation is free software; + * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. - * - * The SCTP reference implementation is distributed in the hope that it + * + * The SCTP reference implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied * ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * Boston, MA 02111-1307, USA. + * * Please send any bug reports or fixes you make to the * email address(es): * lksctp developers <lksctp-developers@lists.sourceforge.net> - * + * * Or submit a bug report through the following website: * http://www.sf.net/projects/lksctp * - * Written or modified by: + * Written or modified by: * Randall Stewart <rstewar1@email.mot.com> * Ken Morneau <kmorneau@cisco.com> * Qiaobing Xie <qxie1@email.mot.com> * Sridhar Samudrala <sri@us.ibm.com> - * + * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ @@ -65,7 +65,7 @@ * tad, but I have commented the original lines below */ -#include <linux/types.h> +#include <linux/types.h> #include <net/sctp/sctp.h> #define BASE 65521 /* largest prime smaller than 65536 */ @@ -111,7 +111,7 @@ unsigned long update_adler32(unsigned long adler, * This would then be (2 * BASE) - 2, which * will still only do one subtract. On Intel * this is much better to do this way and - * avoid the divide. Have not -pg'd on + * avoid the divide. Have not -pg'd on * sparc. */ if (s2 >= BASE) { @@ -135,7 +135,7 @@ __u32 sctp_start_cksum(__u8 *ptr, __u16 count) __u32 zero = 0L; /* Calculate the CRC up to the checksum field. */ - adler = update_adler32(adler, ptr, + adler = update_adler32(adler, ptr, sizeof(struct sctphdr) - sizeof(__u32)); /* Skip over the checksum field. */ adler = update_adler32(adler, (unsigned char *) &zero, @@ -156,6 +156,15 @@ __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler) return adler; } +__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 count, __u32 adler) +{ + /* Its not worth it to try harder. Adler32 is obsolescent. */ + adler = update_adler32(adler, from, count); + memcpy(to, from, count); + + return adler; +} + __u32 sctp_end_cksum(__u32 adler) { return adler; diff --git a/net/sctp/crc32c.c b/net/sctp/crc32c.c index 8307ae67b9b8..bf20588d4901 100644 --- a/net/sctp/crc32c.c +++ b/net/sctp/crc32c.c @@ -170,6 +170,23 @@ __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32) return crc32; } +__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 length, __u32 crc32) +{ + __u32 i; + __u32 *_to = (__u32 *)to; + __u32 *_from = (__u32 *)from; + + for (i = 0; i < (length/4); i++) { + _to[i] = _from[i]; + CRC32C(crc32, from[i*4]); + CRC32C(crc32, from[i*4+1]); + CRC32C(crc32, from[i*4+2]); + CRC32C(crc32, from[i*4+3]); + } + + return crc32; +} + __u32 sctp_end_cksum(__u32 crc32) { __u32 result; diff --git a/net/sctp/output.c b/net/sctp/output.c index a269f68b6555..663132f22077 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -166,11 +166,11 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, /* If sending DATA and haven't aleady bundled a SACK, try to * bundle one in to the packet. */ - if (sctp_chunk_is_data(chunk) && !pkt->has_sack && + if (sctp_chunk_is_data(chunk) && !pkt->has_sack && !pkt->has_cookie_echo) { struct sctp_association *asoc; asoc = pkt->transport->asoc; - + if (asoc->a_rwnd > asoc->rwnd) { struct sctp_chunk *sack; asoc->a_rwnd = asoc->rwnd; @@ -205,7 +205,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, if (retval != SCTP_XMIT_OK) goto finish; - + pmtu = ((packet->transport->asoc) ? (packet->transport->asoc->pmtu) : (packet->transport->pmtu)); @@ -259,7 +259,7 @@ append: goto finish; } else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type) packet->has_cookie_echo = 1; - else if (SCTP_CID_SACK == chunk->chunk_hdr->type) + else if (SCTP_CID_SACK == chunk->chunk_hdr->type) packet->has_sack = 1; /* It is OK to send this chunk. */ @@ -276,8 +276,8 @@ finish: */ int sctp_packet_transmit(struct sctp_packet *packet) { - struct sctp_transport *transport = packet->transport; - struct sctp_association *asoc = transport->asoc; + struct sctp_transport *tp = packet->transport; + struct sctp_association *asoc = tp->asoc; struct sctphdr *sh; __u32 crc32; struct sk_buff *nskb; @@ -311,6 +311,32 @@ int sctp_packet_transmit(struct sctp_packet *packet) */ skb_set_owner_w(nskb, sk); + /* Build the SCTP header. */ + sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); + sh->source = htons(packet->source_port); + sh->dest = htons(packet->destination_port); + + /* From 6.8 Adler-32 Checksum Calculation: + * After the packet is constructed (containing the SCTP common + * header and one or more control or DATA chunks), the + * transmitter shall: + * + * 1) Fill in the proper Verification Tag in the SCTP common + * header and initialize the checksum field to 0's. + */ + sh->vtag = htonl(packet->vtag); + sh->checksum = 0; + + + /* 2) Calculate the Adler-32 checksum of the whole packet, + * including the SCTP common header and all the + * chunks. + * + * Note: Adler-32 is no longer applicable, as has been replaced + * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. + */ + crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr)); + /** * 6.10 Bundling * @@ -344,16 +370,20 @@ int sctp_packet_transmit(struct sctp_packet *packet) * for a given destination transport address. */ if ((1 == chunk->num_times_sent) && - (!transport->rto_pending)) { + (!tp->rto_pending)) { chunk->rtt_in_progress = 1; - transport->rto_pending = 1; + tp->rto_pending = 1; } has_data = 1; } - memcpy(skb_put(nskb, chunk->skb->len), - chunk->skb->data, chunk->skb->len); padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len; - memset(skb_put(nskb, padding), 0, padding); + if (padding) + memset(skb_put(chunk->skb, padding), 0, padding); + + crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len), + chunk->skb->data, + chunk->skb->len, crc32); + SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d, " "%s %d\n", "*** Chunk", chunk, @@ -376,30 +406,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) sctp_free_chunk(chunk); } - /* Build the SCTP header. */ - sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); - sh->source = htons(packet->source_port); - sh->dest = htons(packet->destination_port); - - /* From 6.8 Adler-32 Checksum Calculation: - * After the packet is constructed (containing the SCTP common - * header and one or more control or DATA chunks), the - * transmitter shall: - * - * 1) Fill in the proper Verification Tag in the SCTP common - * header and initialize the checksum field to 0's. - */ - sh->vtag = htonl(packet->vtag); - sh->checksum = 0; - - /* 2) Calculate the Adler-32 checksum of the whole packet, - * including the SCTP common header and all the - * chunks. - * - * Note: Adler-32 is no longer applicable, as has been replaced - * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. - */ - crc32 = sctp_start_cksum((__u8 *)sh, nskb->len); + /* Perform final transformation on checksum. */ crc32 = sctp_end_cksum(crc32); /* 3) Put the resultant value into the checksum field in the @@ -431,18 +438,18 @@ int sctp_packet_transmit(struct sctp_packet *packet) */ /* Dump that on IP! */ - if (asoc && asoc->peer.last_sent_to != transport) { + if (asoc && asoc->peer.last_sent_to != tp) { /* Considering the multiple CPU scenario, this is a * "correcter" place for last_sent_to. --xguo */ - asoc->peer.last_sent_to = transport; + asoc->peer.last_sent_to = tp; } if (has_data) { struct timer_list *timer; unsigned long timeout; - transport->last_time_used = jiffies; + tp->last_time_used = jiffies; /* Restart the AUTOCLOSE timer when sending data. */ if ((SCTP_STATE_ESTABLISHED == asoc->state) && @@ -455,21 +462,21 @@ int sctp_packet_transmit(struct sctp_packet *packet) } } - dst = transport->dst; + dst = tp->dst; /* The 'obsolete' field of dst is set to 2 when a dst is freed. */ if (!dst || (dst->obsolete > 1)) { dst_release(dst); - sctp_transport_route(transport, NULL, sctp_sk(sk)); + sctp_transport_route(tp, NULL, sctp_sk(sk)); sctp_assoc_sync_pmtu(asoc); } - nskb->dst = dst_clone(transport->dst); + nskb->dst = dst_clone(tp->dst); if (!nskb->dst) goto no_route; SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n", nskb->len); - (*transport->af_specific->sctp_xmit)(nskb, transport, packet->ipfragok); + (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok); out: packet->size = SCTP_IP_OVERHEAD; return err; @@ -596,7 +603,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, * if any previously transmitted data on the connection remains * unacknowledged. */ - if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size && + if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size && q->outstanding_bytes && SCTP_STATE_ESTABLISHED == asoc->state) { unsigned len = datasize + q->out_qlen; |
