netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [BK PATCH] 2.6 SCTP updates.
@ 2003-10-02 23:46 Sridhar Samudrala
  2003-10-03  9:48 ` David S. Miller
  0 siblings, 1 reply; 11+ messages in thread
From: Sridhar Samudrala @ 2003-10-02 23:46 UTC (permalink / raw)
  To: davem; +Cc: netdev

Hi Dave,

Please do a
	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5
to get the following udpates to SCTP on top of linux 2.6.0-test6

The changesets include fixes for a couple of arch specific issues with ppc64 
and parisc64, few ADDIP extension related patches and a bug fix.

# This patch includes the following deltas:
#	           ChangeSet	1.1375  -> 1.1377 
#	net/sctp/associola.c	1.59    -> 1.61   
#	net/sctp/sm_statefuns.c	1.63    -> 1.64   
#	net/sctp/endpointola.c	1.28    -> 1.29   
#	net/sctp/sm_make_chunk.c	1.61    -> 1.64   
#	include/net/sctp/sctp.h	1.50    -> 1.52   
#	   net/sctp/sysctl.c	1.13    -> 1.14   
#	include/net/sctp/sm.h	1.29    -> 1.31   
#	include/linux/sctp.h	1.8     -> 1.9    
#	net/sctp/sm_sideeffect.c	1.48    -> 1.49   
#	net/sctp/bind_addr.c	1.21    -> 1.22   
#	include/net/sctp/command.h	1.14    -> 1.15   
#	include/net/sctp/structs.h	1.73    -> 1.75   
#	   net/sctp/socket.c	1.96    -> 1.99   
#
# The following is the BitKeeper ChangeSet Log
#
#ChangeSet@1.1377, 2003-10-02 11:36:34-07:00, sri@us.ibm.com
#  [SCTP] Fix bugs in conversions between msecs and jiffies.
#
#ChangeSet@1.1376, 2003-09-29 12:04:57-07:00, sri@us.ibm.com
#  Merge us.ibm.com:/home/sridhar/BK/linux-2.6.0-test6
#  into us.ibm.com:/home/sridhar/BK/lksctp-2.6.0-test6
#
#ChangeSet@1.1217.15.5, 2003-09-29 10:23:40-07:00, sri@us.ibm.com
#  [SCTP] Convert tv_add from static inline to a macro to fix an obscure
#  assembler problem with parisc64.
#
#ChangeSet@1.1217.15.4, 2003-09-22 14:29:35-07:00, sri@us.ibm.com
#  [SCTP] ADDIP: Support for the creation of ASCONF_ACK chunk (Kevin).
#
#ChangeSet@1.1217.15.3, 2003-09-18 14:44:14-07:00, sri@us.ibm.com
#  [SCTP] ADDIP: Handle ERROR chunk in response to an ASCONF chunk.
#  
#  Disable sending any further ASCONF chunks and stop its T-4 timer if
#  the peer responds to an ASCONF with an ERROR chunk.
#
#ChangeSet@1.1217.15.2, 2003-09-18 14:39:59-07:00, sri@us.ibm.com
#  [SCTP] ADDIP: Support to send ASCONF chunk with ADD/DEL IP params.
#
#ChangeSet@1.1217.15.1, 2003-09-09 11:03:31-07:00, sri@us.ibm.com
#  [SCTP] PPC64 port: Don't overload the optval arg of ADDRS_NUM socket
#  options with different types for input and output. Instead use it only
#  as an input arg and return the no. of addresses in the return value.

Thanks
Sridhar

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BK PATCH] 2.6 SCTP updates.
  2003-10-02 23:46 [BK PATCH] 2.6 SCTP updates Sridhar Samudrala
@ 2003-10-03  9:48 ` David S. Miller
  0 siblings, 0 replies; 11+ messages in thread
From: David S. Miller @ 2003-10-03  9:48 UTC (permalink / raw)
  To: Sridhar Samudrala; +Cc: netdev

On Thu, 2 Oct 2003 16:46:06 -0700 (PDT)
Sridhar Samudrala <sri@us.ibm.com> wrote:

> Please do a
> 	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5
> to get the following udpates to SCTP on top of linux 2.6.0-test6
> 
> The changesets include fixes for a couple of arch specific issues with ppc64 
> and parisc64, few ADDIP extension related patches and a bug fix.

Pulled, thanks a lot Sridhar.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [BK PATCH] 2.6 SCTP updates
@ 2004-02-14  0:07 Sridhar Samudrala
  2004-02-14  5:52 ` David S. Miller
  0 siblings, 1 reply; 11+ messages in thread
From: Sridhar Samudrala @ 2004-02-14  0:07 UTC (permalink / raw)
  To: davem; +Cc: netdev, lksctp-developers

Hi Dave,

Please do a
	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
to get the following fixes to SCTP on top of linux 2.6.2.

# This patch includes the following deltas:
#                  ChangeSet    1.1551  -> 1.1554
#          net/sctp/ssnmap.c    1.2     -> 1.3
#          net/sctp/socket.c    1.105   -> 1.107
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/02/12      sri@us.ibm.com  1.1552
# [SCTP] Use __get_free_pages() to allocate ssnmap.
#
# This is needed to avoid kmalloc()'s 128K limit when an association is
# initialized with a large no. of streams(more than 65000 inbound +
# outbound streams).
# --------------------------------------------
# 04/02/12      sri@us.ibm.com  1.1553
# [SCTP] Fix SCTP_INITMSG set socket option so that a parameter with 0
#        value will not change its current value.
# --------------------------------------------
# 04/02/13      sri@us.ibm.com  1.1554
# [SCTP] Fix sctp_getladdrs()/sctp_getpaddrs() API so that the port
#        value in the returned addresses is in network byte order.
# --------------------------------------------

Thanks
Sridhar

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BK PATCH] 2.6 SCTP updates
  2004-02-14  0:07 Sridhar Samudrala
@ 2004-02-14  5:52 ` David S. Miller
  2004-02-16  5:55   ` Sridhar Samudrala
  0 siblings, 1 reply; 11+ messages in thread
From: David S. Miller @ 2004-02-14  5:52 UTC (permalink / raw)
  To: Sridhar Samudrala; +Cc: netdev, lksctp-developers

On Fri, 13 Feb 2004 16:07:05 -0800 (PST)
Sridhar Samudrala <sri@us.ibm.com> wrote:

> Please do a
> 	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
> to get the following fixes to SCTP on top of linux 2.6.2.

I am pulling this, however I strongly disagree with this change:

> # 04/02/12      sri@us.ibm.com  1.1552
> # [SCTP] Use __get_free_pages() to allocate ssnmap.
> #
> # This is needed to avoid kmalloc()'s 128K limit when an association is
> # initialized with a large no. of streams(more than 65000 inbound +
> # outbound streams).

This is madness because it means that every assosciation created eats
at least PAGE_SIZE bytes of memory, even if the ssnmap is tiny.

Maybe you should just brance between two allocation schemes based upon
what sctp_ssnmap_size() returns.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BK PATCH] 2.6 SCTP updates
  2004-02-14  5:52 ` David S. Miller
@ 2004-02-16  5:55   ` Sridhar Samudrala
  0 siblings, 0 replies; 11+ messages in thread
From: Sridhar Samudrala @ 2004-02-16  5:55 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, lksctp-developers


On Fri, 13 Feb 2004, David S. Miller wrote:

> On Fri, 13 Feb 2004 16:07:05 -0800 (PST)
> Sridhar Samudrala <sri@us.ibm.com> wrote:
>
> > Please do a
> > 	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
> > to get the following fixes to SCTP on top of linux 2.6.2.
>
> I am pulling this, however I strongly disagree with this change:
>
> > # 04/02/12      sri@us.ibm.com  1.1552
> > # [SCTP] Use __get_free_pages() to allocate ssnmap.
> > #
> > # This is needed to avoid kmalloc()'s 128K limit when an association is
> > # initialized with a large no. of streams(more than 65000 inbound +
> > # outbound streams).
>
> This is madness because it means that every assosciation created eats
> at least PAGE_SIZE bytes of memory, even if the ssnmap is tiny.
>
> Maybe you should just brance between two allocation schemes based upon
> what sctp_ssnmap_size() returns.

Yes, I didn't realize that this will waste lots of memory for associations
with a few streams. Here is a patch that fixes it by reverting back to
kmalloc() for allocs < 128K.

I have pushed it to both 2.6 and 2.4 bk trees. You can pull them from
	http://linux-lksctp.bkbits.net/lksctp-2.5.work
	http://linux-lksctp.bkbits.net/lksctp-2.4.work

# This patch includes the following deltas:
#	           ChangeSet	1.1554  -> 1.1555
#	   net/sctp/ssnmap.c	1.3     -> 1.4
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/02/15	sri@us.ibm.com	1.1555
# [SCTP] Revert back to use kmalloc() for ssnmap allocs of sizes < 128K.
# --------------------------------------------
#
diff -Nru a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c
--- a/net/sctp/ssnmap.c	Sun Feb 15 21:34:49 2004
+++ b/net/sctp/ssnmap.c	Sun Feb 15 21:34:49 2004
@@ -40,6 +40,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>

+#define MAX_KMALLOC_SIZE	131072

 /* Storage size needed for map includes 2 headers and then the
  * specific needs of in or out streams.
@@ -56,11 +57,14 @@
 struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp)
 {
 	struct sctp_ssnmap *retval;
-	int order;
-
-	order = get_order(sctp_ssnmap_size(in,out));
-	retval = (struct sctp_ssnmap *)__get_free_pages(gfp, order);
+	int size;

+	size = sctp_ssnmap_size(in, out);
+	if (size <= MAX_KMALLOC_SIZE)
+		retval = kmalloc(size, gfp);
+	else
+		retval = (struct sctp_ssnmap *)
+			  __get_free_pages(gfp, get_order(size));
 	if (!retval)
 		goto fail;

@@ -73,7 +77,10 @@
 	return retval;

 fail_map:
-	free_pages((unsigned long)retval, order);
+	if (size <= MAX_KMALLOC_SIZE)
+		kfree(retval);
+	else
+		free_pages((unsigned long)retval, get_order(size));
 fail:
 	return NULL;
 }
@@ -109,9 +116,13 @@
 void sctp_ssnmap_free(struct sctp_ssnmap *map)
 {
 	if (map && map->malloced) {
-		free_pages((unsigned long)map,
-			   get_order(sctp_ssnmap_size(map->in.len,
-						      map->out.len)));
+		int size;
+
+		size = sctp_ssnmap_size(map->in.len, map->out.len);
+		if (size <= MAX_KMALLOC_SIZE)
+			kfree(map);
+		else
+			free_pages((unsigned long)map, get_order(size));
 		SCTP_DBG_OBJCNT_DEC(ssnmap);
 	}
 }

Thanks
Sridhar

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [BK PATCH] 2.6 SCTP updates.
@ 2004-03-23 20:13 Sridhar Samudrala
  2004-03-24 20:01 ` David S. Miller
  0 siblings, 1 reply; 11+ messages in thread
From: Sridhar Samudrala @ 2004-03-23 20:13 UTC (permalink / raw)
  To: davem; +Cc: netdev

Hi Dave,

please do a
	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
to get the following updates to SCTP on top of linux 2.6.5-rc2.

# This patch includes the following deltas:
#	           ChangeSet	1.1817  -> 1.1819
#	net/sctp/sm_make_chunk.c	1.66    -> 1.67
#	 net/sctp/ulpevent.c	1.23    -> 1.24
#	    net/sctp/Kconfig	1.11    -> 1.12
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/03/23	sri@us.ibm.com	1.1818
# [SCTP] Don't do any ppid byte-order conversions as it is opaque to SCTP.
# --------------------------------------------
# 04/03/23	sri@us.ibm.com	1.1819
# [SCTP] Avoid the use of hackish CONFIG_IPV6_SCTP__ option.
# --------------------------------------------
#
diff -Nru a/net/sctp/Kconfig b/net/sctp/Kconfig
--- a/net/sctp/Kconfig	Tue Mar 23 11:54:23 2004
+++ b/net/sctp/Kconfig	Tue Mar 23 11:54:23 2004
@@ -5,14 +5,9 @@
 menu "SCTP Configuration (EXPERIMENTAL)"
 	depends on INET && EXPERIMENTAL

-config IPV6_SCTP__
-	tristate
-	default y if IPV6=n
-	default IPV6 if IPV6
-
 config IP_SCTP
 	tristate "The SCTP Protocol (EXPERIMENTAL)"
-	depends on IPV6_SCTP__
+	depends on IPV6 || IPV6=n
 	---help---
 	  Stream Control Transmission Protocol

@@ -61,6 +56,7 @@
 choice
 	prompt "SCTP: Cookie HMAC Algorithm"
 	depends on IP_SCTP
+	default SCTP_HMAC_MD5
 	help
 	  HMAC algorithm to be used during association initialization.  It
 	  is strongly recommended to use HMAC-SHA1 or HMAC-MD5.  See
diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c	Tue Mar 23 11:54:23 2004
+++ b/net/sctp/sm_make_chunk.c	Tue Mar 23 11:54:23 2004
@@ -516,7 +516,7 @@
 	 */
 	dp.tsn = 0;
 	dp.stream = htons(sinfo->sinfo_stream);
-	dp.ppid   = htonl(sinfo->sinfo_ppid);
+	dp.ppid   = sinfo->sinfo_ppid;

 	/* Set the flags for an unordered send.  */
 	if (sinfo->sinfo_flags & MSG_UNORDERED) {
diff -Nru a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
--- a/net/sctp/ulpevent.c	Tue Mar 23 11:54:23 2004
+++ b/net/sctp/ulpevent.c	Tue Mar 23 11:54:23 2004
@@ -663,7 +663,7 @@
 	 * for and this information is passed opaquely by the SCTP stack from
 	 * one end to the other.
 	 */
-	info->sinfo_ppid = ntohl(chunk->subh.data_hdr->ppid);
+	info->sinfo_ppid = chunk->subh.data_hdr->ppid;

 	/* Sockets API Extensions for SCTP
 	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BK PATCH] 2.6 SCTP updates.
  2004-03-23 20:13 Sridhar Samudrala
@ 2004-03-24 20:01 ` David S. Miller
  0 siblings, 0 replies; 11+ messages in thread
From: David S. Miller @ 2004-03-24 20:01 UTC (permalink / raw)
  To: Sridhar Samudrala; +Cc: netdev

On Tue, 23 Mar 2004 12:13:56 -0800 (PST)
Sridhar Samudrala <sri@us.ibm.com> wrote:

> please do a
> 	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
> to get the following updates to SCTP on top of linux 2.6.5-rc2.

Pulled, thanks.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [BK PATCH] 2.6 SCTP updates.
@ 2004-04-06 17:28 Sridhar Samudrala
  0 siblings, 0 replies; 11+ messages in thread
From: Sridhar Samudrala @ 2004-04-06 17:28 UTC (permalink / raw)
  To: davem; +Cc: netdev, lksctp-developers

Hi Dave,

Please do a
	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
to get the following updates to SCTP on top of linux 2.6.5

Thanks
Sridhar

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/06 07:32:30-07:00 sri@us.ibm.com
#   [SCTP] Use id to ptr translation service in lib/idr.c to assign and
#   validate ids of associations.
#
#   This patch avoids the use of virt_addr_valid() to validate the address
#   of associations passed by the user. Currently the address of an
#   association is used as its id. virt_addr_valid doesn't work as
#   expected when PAGEALLOC debugging is enabled.
#
# net/sctp/socket.c
# net/sctp/sm_make_chunk.c
# net/sctp/protocol.c
# net/sctp/associola.c
# include/net/sctp/structs.h
# include/net/sctp/sctp.h
# ChangeSet
#   2004/04/06 07:24:04-07:00 sri@us.ibm.com
#   [SCTP] Update sctp_ulpevent structure to include assoc pointer and
#   only the receive specific fields of sctp_sndrcvinfo.
#
# net/sctp/ulpqueue.c
# net/sctp/ulpevent.c
# net/sctp/socket.c
# net/sctp/protocol.c
# net/sctp/ipv6.c
# include/net/sctp/ulpevent.h
#
# ChangeSet
#   2004/04/06 00:28:31-07:00 sri@us.ibm.com
#   [SCTP] Fix typo in entry name of the remove_proc_entry() call.
#
# net/sctp/objcnt.c
#
diff -Nru a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
--- a/include/net/sctp/sctp.h	Tue Apr  6 07:35:28 2004
+++ b/include/net/sctp/sctp.h	Tue Apr  6 07:35:28 2004
@@ -1,5 +1,5 @@
 /* SCTP kernel reference Implementation
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2003 Intel Corp.
@@ -78,6 +78,7 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
+#include <linux/idr.h>

 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #include <net/ipv6.h>
@@ -223,24 +224,6 @@
 #define SCTP_INC_STATS_USER(field) SNMP_INC_STATS_USER(sctp_statistics, field)
 #define SCTP_DEC_STATS(field)      SNMP_DEC_STATS(sctp_statistics, field)

-/* Determine if this is a valid kernel address.  */
-static inline int sctp_is_valid_kaddr(unsigned long addr)
-{
-	struct page *page;
-
-	/* Make sure the address is not in the user address space. */
-	if (addr < PAGE_OFFSET)
-		return 0;
-
-	page = virt_to_page(addr);
-
-	/* Is this page valid? */
-	if (!virt_addr_valid(addr) || PageReserved(page))
-		return 0;
-
-	return 1;
-}
-
 #endif /* !TEST_FRAME */


@@ -357,7 +340,7 @@
 /* Map an association to an assoc_id. */
 static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
 {
-	return (sctp_assoc_t) asoc;
+	return (asoc?asoc->assoc_id:NULL);
 }

 /* Look up the association by its id.  */
@@ -518,6 +501,9 @@
 extern struct proto sctp_prot;
 extern struct proc_dir_entry *proc_net_sctp;
 void sctp_put_port(struct sock *sk);
+
+extern struct idr sctp_assocs_id;
+extern spinlock_t sctp_assocs_id_lock;

 /* Static inline functions. */

diff -Nru a/include/net/sctp/structs.h b/include/net/sctp/structs.h
--- a/include/net/sctp/structs.h	Tue Apr  6 07:35:28 2004
+++ b/include/net/sctp/structs.h	Tue Apr  6 07:35:28 2004
@@ -1,5 +1,5 @@
 /* SCTP kernel reference Implementation
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
@@ -1282,11 +1282,8 @@
 	/* Associations on the same socket. */
 	struct list_head asocs;

-	/* This is a signature that lets us know that this is a
-	 * struct sctp_association data structure.  Used for mapping an
-	 * association id to an association.
-	 */
-	__u32 eyecatcher;
+	/* association id. */
+	sctp_assoc_t assoc_id;

 	/* This is our parent endpoint.	 */
 	struct sctp_endpoint *ep;
diff -Nru a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
--- a/include/net/sctp/ulpevent.h	Tue Apr  6 07:35:27 2004
+++ b/include/net/sctp/ulpevent.h	Tue Apr  6 07:35:27 2004
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001 International Business Machines, Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -54,7 +54,13 @@
  * growing this structure as it is at the maximum limit now.
  */
 struct sctp_ulpevent {
-	struct sctp_sndrcvinfo sndrcvinfo;
+	struct sctp_association *asoc;
+	__u16 stream;
+	__u16 ssn;
+	__u16 flags;
+	__u32 ppid;
+	__u32 tsn;
+	__u32 cumtsn;
 	int msg_flags;
 	int iif;
 };
diff -Nru a/net/sctp/associola.c b/net/sctp/associola.c
--- a/net/sctp/associola.c	Tue Apr  6 07:35:27 2004
+++ b/net/sctp/associola.c	Tue Apr  6 07:35:27 2004
@@ -1,5 +1,5 @@
 /* SCTP kernel reference Implementation
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
@@ -276,7 +276,7 @@

 	asoc->need_ecne = 0;

-	asoc->eyecatcher = SCTP_ASSOC_EYECATCHER;
+	asoc->assoc_id = (sctp_assoc_t)-1;

 	/* Assume that peer would support both address types unless we are
 	 * told otherwise.
@@ -360,8 +360,6 @@
 		sctp_transport_free(transport);
 	}

-	asoc->eyecatcher = 0;
-
 	/* Free any cached ASCONF_ACK chunk. */
 	if (asoc->addip_last_asconf_ack)
 		sctp_chunk_free(asoc->addip_last_asconf_ack);
@@ -381,6 +379,12 @@
 	sctp_endpoint_put(asoc->ep);
 	sock_put(asoc->base.sk);

+	if ((int)asoc->assoc_id != -1) {
+		spin_lock_bh(&sctp_assocs_id_lock);
+		idr_remove(&sctp_assocs_id, (int)asoc->assoc_id);
+		spin_unlock_bh(&sctp_assocs_id_lock);
+	}
+
 	if (asoc->base.malloced) {
 		kfree(asoc);
 		SCTP_DBG_OBJCNT_DEC(assoc);
@@ -856,26 +860,6 @@
 	return transport;
 }

-/*  Is this a live association structure. */
-int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc)
-{
-
-	/* First, verify that this is a kernel address. */
-	if (!sctp_is_valid_kaddr((unsigned long) asoc))
-		return 0;
-
-	/* Verify that this _is_ an sctp_association
-	 * data structure and if so, that the socket matches.
-	 */
-	if (SCTP_ASSOC_EYECATCHER != asoc->eyecatcher)
-		return 0;
-	if (asoc->base.sk != sk)
-		return 0;
-
-	/* The association is valid. */
-	return 1;
-}
-
 /* Do delayed input processing.  This is scheduled by sctp_rcv(). */
 static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
 {
@@ -891,6 +875,7 @@
 	sk = asoc->base.sk;

 	inqueue = &asoc->base.inqueue;
+	sctp_association_hold(asoc);
 	while (NULL != (chunk = sctp_inq_pop(inqueue))) {
 		state = asoc->state;
 		subtype = chunk->chunk_hdr->type;
@@ -913,14 +898,14 @@
 		/* Check to see if the association is freed in response to
 		 * the incoming chunk.  If so, get out of the while loop.
 		 */
-		if (!sctp_assoc_valid(sk, asoc))
+		if (asoc->base.dead)
 			break;

 		/* If there is an error on chunk, discard this packet. */
 		if (error && chunk)
 			chunk->pdiscard = 1;
 	}
-
+	sctp_association_put(asoc);
 }

 /* This routine moves an association from its old sk to a new sk.  */
diff -Nru a/net/sctp/ipv6.c b/net/sctp/ipv6.c
--- a/net/sctp/ipv6.c	Tue Apr  6 07:35:28 2004
+++ b/net/sctp/ipv6.c	Tue Apr  6 07:35:28 2004
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2002, 2004
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
- * Copyright (c) 2002-2003 International Business Machines, Corp.
  * Copyright (c) 2002-2003 Intel Corp.
  *
  * This file is part of the SCTP kernel reference Implementation
@@ -698,7 +698,7 @@
 		union sctp_addr *addr;
 		struct sctp_association *asoc;

-		asoc = event->sndrcvinfo.sinfo_assoc_id;
+		asoc = event->asoc;
 		sctp_inet6_msgname(msgname, addrlen);
 		sin6 = (struct sockaddr_in6 *)msgname;
 		sin6->sin6_port = htons(asoc->peer.port);
diff -Nru a/net/sctp/objcnt.c b/net/sctp/objcnt.c
--- a/net/sctp/objcnt.c	Tue Apr  6 07:35:27 2004
+++ b/net/sctp/objcnt.c	Tue Apr  6 07:35:27 2004
@@ -1,5 +1,5 @@
 /* SCTP kernel reference Implementation
- * Copyright (c) 2001 International Business Machines Corp.
+ * (C) Copyright IBM Corp. 2001, 2004
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -134,7 +134,7 @@
 /* Cleanup the objcount entry in the proc filesystem.  */
 void sctp_dbg_objcnt_exit(void)
 {
-	remove_proc_entry("sctp_dbg_objcount", proc_net_sctp);
+	remove_proc_entry("sctp_dbg_objcnt", proc_net_sctp);
 }


diff -Nru a/net/sctp/protocol.c b/net/sctp/protocol.c
--- a/net/sctp/protocol.c	Tue Apr  6 07:35:28 2004
+++ b/net/sctp/protocol.c	Tue Apr  6 07:35:28 2004
@@ -64,6 +64,9 @@
 struct proc_dir_entry	*proc_net_sctp;
 DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);

+struct idr sctp_assocs_id;
+spinlock_t sctp_assocs_id_lock = SPIN_LOCK_UNLOCKED;
+
 /* This is the global socket data structure used for responding to
  * the Out-of-the-blue (OOTB) packets.  A control sock will be created
  * for this socket at the initialization time.
@@ -721,7 +724,7 @@
 	if (msgname) {
 		struct sctp_association *asoc;

-		asoc = event->sndrcvinfo.sinfo_assoc_id;
+		asoc = event->asoc;
 		sctp_inet_msgname(msgname, addr_len);
 		sin = (struct sockaddr_in *)msgname;
 		sinfrom = &asoc->peer.primary_addr.v4;
@@ -1048,6 +1051,9 @@
 	/* Initialize default stream count setup information. */
 	sctp_max_instreams    		= SCTP_DEFAULT_INSTREAMS;
 	sctp_max_outstreams   		= SCTP_DEFAULT_OUTSTREAMS;
+
+	/* Initialize handle used for association ids. */
+	idr_init(&sctp_assocs_id);

 	/* Size and allocate the association hash table.
 	 * The methodology is similar to that of the tcp hash tables.
diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c	Tue Apr  6 07:35:28 2004
+++ b/net/sctp/sm_make_chunk.c	Tue Apr  6 07:35:28 2004
@@ -1,5 +1,5 @@
 /* SCTP kernel reference Implementation
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2002 Intel Corp.
@@ -1817,10 +1817,23 @@
 	/* Allocate storage for the negotiated streams if it is not a temporary 	 * association.
 	 */
 	if (!asoc->temp) {
+		sctp_assoc_t assoc_id;
+
 		asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams,
 					       asoc->c.sinit_num_ostreams, gfp);
 		if (!asoc->ssnmap)
-			goto nomem_ssnmap;
+			goto clean_up;
+
+		do {
+			if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+				goto clean_up;
+			spin_lock_bh(&sctp_assocs_id_lock);
+			assoc_id = (sctp_assoc_t)idr_get_new(&sctp_assocs_id,
+							     (void *)asoc);
+			spin_unlock_bh(&sctp_assocs_id_lock);
+		} while (unlikely((int)assoc_id == -1));
+
+		asoc->assoc_id = assoc_id;
 	}

 	/* ADDIP Section 4.1 ASCONF Chunk Procedures
@@ -1836,7 +1849,6 @@
 	asoc->peer.addip_serial = asoc->peer.i.initial_tsn - 1;
 	return 1;

-nomem_ssnmap:
 clean_up:
 	/* Release the transport structures. */
 	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c	Tue Apr  6 07:35:28 2004
+++ b/net/sctp/socket.c	Tue Apr  6 07:35:28 2004
@@ -135,8 +135,14 @@
 	}

 	/* Otherwise this is a UDP-style socket. */
-	asoc = (struct sctp_association *)id;
-	if (!sctp_assoc_valid(sk, asoc))
+	if (!id || (id == (sctp_assoc_t)-1))
+		return NULL;
+
+	spin_lock_bh(&sctp_assocs_id_lock);
+	asoc = (struct sctp_association *)idr_find(&sctp_assocs_id, (int)id);
+	spin_unlock_bh(&sctp_assocs_id_lock);
+
+	if (!asoc || (asoc->base.sk != sk) || asoc->base.dead)
 		return NULL;

 	return asoc;
@@ -1498,8 +1504,7 @@
 		 * rwnd by that amount. If all the data in the skb is read,
 		 * rwnd is updated when the event is freed.
 		 */
-		sctp_assoc_rwnd_increase(event->sndrcvinfo.sinfo_assoc_id,
-					 copied);
+		sctp_assoc_rwnd_increase(event->asoc, copied);
 		goto out;
 	} else if ((event->msg_flags & MSG_NOTIFICATION) ||
 		   (event->msg_flags & MSG_EOR))
@@ -4477,7 +4482,7 @@
 	 */
 	sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
 		event = sctp_skb2event(skb);
-		if (event->sndrcvinfo.sinfo_assoc_id == assoc) {
+		if (event->asoc == assoc) {
 			__skb_unlink(skb, skb->list);
 			__skb_queue_tail(&newsk->sk_receive_queue, skb);
 		}
@@ -4506,7 +4511,7 @@
 		 */
 		sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
 			event = sctp_skb2event(skb);
-			if (event->sndrcvinfo.sinfo_assoc_id == assoc) {
+			if (event->asoc == assoc) {
 				__skb_unlink(skb, skb->list);
 				__skb_queue_tail(queue, skb);
 			}
diff -Nru a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
--- a/net/sctp/ulpevent.c	Tue Apr  6 07:35:28 2004
+++ b/net/sctp/ulpevent.c	Tue Apr  6 07:35:28 2004
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001 International Business Machines, Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -590,8 +590,7 @@
 						struct sctp_chunk *chunk,
 						int gfp)
 {
-	struct sctp_ulpevent *event;
-	struct sctp_sndrcvinfo *info;
+	struct sctp_ulpevent *event = NULL;
 	struct sk_buff *skb;
 	size_t padding, len;

@@ -624,101 +623,21 @@
 	/* Initialize event with flags 0.  */
 	sctp_ulpevent_init(event, 0);

-	event->iif = sctp_chunk_iif(chunk);
-
 	sctp_ulpevent_receive_data(event, asoc);

-	info = (struct sctp_sndrcvinfo *) &event->sndrcvinfo;
-
-	/* Sockets API Extensions for SCTP
-	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
-	 *
-	 * sinfo_stream: 16 bits (unsigned integer)
-	 *
-	 * For recvmsg() the SCTP stack places the message's stream number in
-	 * this value.
-	 */
-	info->sinfo_stream = ntohs(chunk->subh.data_hdr->stream);
-
-	/* Sockets API Extensions for SCTP
-	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
-	 *
-	 * sinfo_ssn: 16 bits (unsigned integer)
-	 *
-	 * For recvmsg() this value contains the stream sequence number that
-	 * the remote endpoint placed in the DATA chunk.  For fragmented
-	 * messages this is the same number for all deliveries of the message
-	 * (if more than one recvmsg() is needed to read the message).
-	 */
-	info->sinfo_ssn = ntohs(chunk->subh.data_hdr->ssn);
-
-        /* Sockets API Extensions for SCTP
-	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
-	 *
-	 * sinfo_ppid: 32 bits (unsigned integer)
-	 *
-	 * In recvmsg() this value is
-	 * the same information that was passed by the upper layer in the peer
-	 * application.  Please note that byte order issues are NOT accounted
-	 * for and this information is passed opaquely by the SCTP stack from
-	 * one end to the other.
-	 */
-	info->sinfo_ppid = chunk->subh.data_hdr->ppid;
-
-	/* Sockets API Extensions for SCTP
-	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
-	 *
-	 * sinfo_flags: 16 bits (unsigned integer)
-	 *
-	 * This field may contain any of the following flags and is composed of
-	 * a bitwise OR of these values.
-	 *
-	 * recvmsg() flags:
-	 *
-	 * MSG_UNORDERED - This flag is present when the message was sent
-	 *                 non-ordered.
-	 */
+	event->stream = ntohs(chunk->subh.data_hdr->stream);
+	event->ssn = ntohs(chunk->subh.data_hdr->ssn);
+	event->ppid = chunk->subh.data_hdr->ppid;
 	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
-		info->sinfo_flags |= MSG_UNORDERED;
-
-		/* sinfo_cumtsn: 32 bit (unsigned integer)
-		 *
-		 * This field will hold the current cumulative TSN as
-		 * known by the underlying SCTP layer.  Note this field is
-		 * ignored when sending and only valid for a receive
-		 * operation when sinfo_flags are set to MSG_UNORDERED.
-		 */
-		info->sinfo_cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
+		event->flags |= MSG_UNORDERED;
+		event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
 	}
-
-	/* Note:  For reassembly, we need to have the fragmentation bits.
-	 * For now, merge these into the msg_flags, since those bit
-	 * possitions are not used.
-	 */
+	event->tsn = ntohl(chunk->subh.data_hdr->tsn);
 	event->msg_flags |= chunk->chunk_hdr->flags;
-
-	/* With 04 draft, tsn moves into sndrcvinfo. */
-	info->sinfo_tsn = ntohl(chunk->subh.data_hdr->tsn);
-
-	/* Context is not used on receive. */
-	info->sinfo_context = 0;
-
-	/* Sockets API Extensions for SCTP
-	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
-	 *
-	 * sinfo_assoc_id: sizeof (sctp_assoc_t)
-	 *
-	 * The association handle field, sinfo_assoc_id, holds the identifier
-	 * for the association announced in the COMMUNICATION_UP notification.
-	 * All notifications for a given association have the same identifier.
-	 * Ignored for TCP-style sockets.
-	 */
-	info->sinfo_assoc_id = sctp_assoc2id(asoc);
-
-	return event;
+	event->iif = sctp_chunk_iif(chunk);

 fail:
-	return NULL;
+	return event;
 }

 /* Create a partial delivery related event.
@@ -797,11 +716,77 @@
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *msghdr)
 {
-	if (!sctp_ulpevent_is_notification(event)) {
-		put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV,
-			 sizeof(struct sctp_sndrcvinfo),
-			 (void *) &event->sndrcvinfo);
-	}
+	struct sctp_sndrcvinfo sinfo;
+
+	if (sctp_ulpevent_is_notification(event))
+		return;
+
+	/* Sockets API Extensions for SCTP
+ 	 * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
+ 	 *
+ 	 * sinfo_stream: 16 bits (unsigned integer)
+ 	 *
+ 	 * For recvmsg() the SCTP stack places the message's stream number in
+ 	 * this value.
+ 	*/
+	sinfo.sinfo_stream = event->stream;
+	/* sinfo_ssn: 16 bits (unsigned integer)
+	 *
+	 * For recvmsg() this value contains the stream sequence number that
+	 * the remote endpoint placed in the DATA chunk.  For fragmented
+	 * messages this is the same number for all deliveries of the message
+	 * (if more than one recvmsg() is needed to read the message).
+	 */
+	sinfo.sinfo_ssn = event->ssn;
+	/* sinfo_ppid: 32 bits (unsigned integer)
+	 *
+	 * In recvmsg() this value is
+	 * the same information that was passed by the upper layer in the peer
+	 * application.  Please note that byte order issues are NOT accounted
+	 * for and this information is passed opaquely by the SCTP stack from
+	 * one end to the other.
+	 */
+	sinfo.sinfo_ppid = event->ppid;
+	/* sinfo_flags: 16 bits (unsigned integer)
+	 *
+	 * This field may contain any of the following flags and is composed of
+	 * a bitwise OR of these values.
+	 *
+	 * recvmsg() flags:
+	 *
+	 * MSG_UNORDERED - This flag is present when the message was sent
+	 *                 non-ordered.
+	 */
+	sinfo.sinfo_flags = event->flags;
+	/* sinfo_tsn: 32 bit (unsigned integer)
+	 *
+	 * For the receiving side, this field holds a TSN that was
+	 * assigned to one of the SCTP Data Chunks.
+	 */
+	sinfo.sinfo_tsn = event->tsn;
+	/* sinfo_cumtsn: 32 bit (unsigned integer)
+	 *
+	 * This field will hold the current cumulative TSN as
+	 * known by the underlying SCTP layer.  Note this field is
+	 * ignored when sending and only valid for a receive
+	 * operation when sinfo_flags are set to MSG_UNORDERED.
+	 */
+	sinfo.sinfo_cumtsn = event->cumtsn;
+	/* sinfo_assoc_id: sizeof (sctp_assoc_t)
+	 *
+	 * The association handle field, sinfo_assoc_id, holds the identifier
+	 * for the association announced in the COMMUNICATION_UP notification.
+	 * All notifications for a given association have the same identifier.
+	 * Ignored for one-to-one style sockets.
+	 */
+	sinfo.sinfo_assoc_id = sctp_assoc2id(event->asoc);
+
+	/* These fields are not used while receiving. */
+	sinfo.sinfo_context = 0;
+	sinfo.sinfo_timetolive = 0;
+
+	put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV,
+		 sizeof(struct sctp_sndrcvinfo), (void *)&sinfo);
 }

 /* Stub skb destructor.  */
@@ -831,14 +816,14 @@
 	sctp_association_hold((struct sctp_association *)asoc);
 	skb = sctp_event2skb(event);
 	skb->sk = asoc->base.sk;
-	event->sndrcvinfo.sinfo_assoc_id = sctp_assoc2id(asoc);
+	event->asoc = (struct sctp_association *)asoc;
 	skb->destructor = sctp_stub_rfree;
 }

 /* A simple destructor to give up the reference to the association. */
 static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
 {
-	sctp_association_put(event->sndrcvinfo.sinfo_assoc_id);
+	sctp_association_put(event->asoc);
 }

 /* Do accounting for bytes received and hold a reference to the association
@@ -880,8 +865,7 @@
 	 */

 	skb = sctp_event2skb(event);
-	sctp_assoc_rwnd_increase(event->sndrcvinfo.sinfo_assoc_id,
-				 skb_headlen(skb));
+	sctp_assoc_rwnd_increase(event->asoc, skb_headlen(skb));

 	/* Don't forget the fragments. */
 	for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
diff -Nru a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
--- a/net/sctp/ulpqueue.c	Tue Apr  6 07:35:28 2004
+++ b/net/sctp/ulpqueue.c	Tue Apr  6 07:35:28 2004
@@ -1,7 +1,7 @@
 /* SCTP kernel reference Implementation
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 International Business Machines, Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -251,7 +251,7 @@
 	struct sctp_ulpevent *cevent;
 	__u32 tsn, ctsn;

-	tsn = event->sndrcvinfo.sinfo_tsn;
+	tsn = event->tsn;

 	/* See if it belongs at the end. */
 	pos = skb_peek_tail(&ulpq->reasm);
@@ -262,7 +262,7 @@

 	/* Short circuit just dropping it at the end. */
 	cevent = sctp_skb2event(pos);
-	ctsn = cevent->sndrcvinfo.sinfo_tsn;
+	ctsn = cevent->tsn;
 	if (TSN_lt(ctsn, tsn)) {
 		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
 		return;
@@ -271,7 +271,7 @@
 	/* Find the right place in this list. We store them by TSN.  */
 	skb_queue_walk(&ulpq->reasm, pos) {
 		cevent = sctp_skb2event(pos);
-		ctsn = cevent->sndrcvinfo.sinfo_tsn;
+		ctsn = cevent->tsn;

 		if (TSN_lt(tsn, ctsn))
 			break;
@@ -368,7 +368,7 @@
 	 */
 	skb_queue_walk(&ulpq->reasm, pos) {
 		cevent = sctp_skb2event(pos);
-		ctsn = cevent->sndrcvinfo.sinfo_tsn;
+		ctsn = cevent->tsn;

 		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 		case SCTP_DATA_FIRST_FRAG:
@@ -425,7 +425,7 @@

 	skb_queue_walk(&ulpq->reasm, pos) {
 		cevent = sctp_skb2event(pos);
-		ctsn = cevent->sndrcvinfo.sinfo_tsn;
+		ctsn = cevent->tsn;

 		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 		case SCTP_DATA_MIDDLE_FRAG:
@@ -486,7 +486,7 @@
 		/* Do not even bother unless this is the next tsn to
 		 * be delivered.
 		 */
-		ctsn = event->sndrcvinfo.sinfo_tsn;
+		ctsn = event->tsn;
 		ctsnap = sctp_tsnmap_get_ctsn(&ulpq->asoc->peer.tsn_map);
 		if (TSN_lte(ctsn, ctsnap))
 			retval = sctp_ulpq_retrieve_partial(ulpq);
@@ -517,7 +517,7 @@

 	skb_queue_walk(&ulpq->reasm, pos) {
 		cevent = sctp_skb2event(pos);
-		ctsn = cevent->sndrcvinfo.sinfo_tsn;
+		ctsn = cevent->tsn;

 		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 		case SCTP_DATA_FIRST_FRAG:
@@ -563,15 +563,15 @@
 	__u16 sid, csid;
 	__u16 ssn, cssn;

-	sid = event->sndrcvinfo.sinfo_stream;
-	ssn = event->sndrcvinfo.sinfo_ssn;
+	sid = event->stream;
+	ssn = event->ssn;
 	in  = &ulpq->asoc->ssnmap->in;

 	/* We are holding the chunks by stream, by SSN.  */
 	sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
 		cevent = (struct sctp_ulpevent *) pos->cb;
-		csid = cevent->sndrcvinfo.sinfo_stream;
-		cssn = cevent->sndrcvinfo.sinfo_ssn;
+		csid = cevent->stream;
+		cssn = cevent->ssn;

 		/* Have we gone too far?  */
 		if (csid > sid)
@@ -609,12 +609,12 @@
 		return;
 	}

-	sid = event->sndrcvinfo.sinfo_stream;
-	ssn = event->sndrcvinfo.sinfo_ssn;
+	sid = event->stream;
+	ssn = event->ssn;

 	cevent = (struct sctp_ulpevent *) pos->cb;
-	csid = cevent->sndrcvinfo.sinfo_stream;
-	cssn = cevent->sndrcvinfo.sinfo_ssn;
+	csid = cevent->stream;
+	cssn = cevent->ssn;
 	if (sid > csid) {
 		__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
 		return;
@@ -630,8 +630,8 @@
 	 */
 	skb_queue_walk(&ulpq->lobby, pos) {
 		cevent = (struct sctp_ulpevent *) pos->cb;
-		csid = cevent->sndrcvinfo.sinfo_stream;
-		cssn = cevent->sndrcvinfo.sinfo_ssn;
+		csid = cevent->stream;
+		cssn = cevent->ssn;

 		if (csid > sid)
 			break;
@@ -656,8 +656,8 @@
 		return event;

 	/* Note: The stream ID must be verified before this routine.  */
-	sid = event->sndrcvinfo.sinfo_stream;
-	ssn = event->sndrcvinfo.sinfo_ssn;
+	sid = event->stream;
+	ssn = event->ssn;
 	in  = &ulpq->asoc->ssnmap->in;

 	/* Is this the expected SSN for this stream ID?  */
@@ -694,7 +694,7 @@
 	while ((skb = __skb_dequeue_tail(&ulpq->lobby))) {
 		freed += skb_headlen(skb);
 		event = sctp_skb2event(skb);
-		tsn = event->sndrcvinfo.sinfo_tsn;
+		tsn = event->tsn;

 		sctp_ulpevent_free(event);
 		sctp_tsnmap_renege(tsnmap, tsn);
@@ -720,7 +720,7 @@
 	while ((skb = __skb_dequeue_tail(&ulpq->reasm))) {
 		freed += skb_headlen(skb);
 		event = sctp_skb2event(skb);
-		tsn = event->sndrcvinfo.sinfo_tsn;
+		tsn = event->tsn;

 		sctp_ulpevent_free(event);
 		sctp_tsnmap_renege(tsnmap, tsn);

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [BK PATCH] 2.6 SCTP updates
@ 2004-07-24  0:18 Sridhar Samudrala
  2004-07-25  5:27 ` David S. Miller
  0 siblings, 1 reply; 11+ messages in thread
From: Sridhar Samudrala @ 2004-07-24  0:18 UTC (permalink / raw)
  To: davem; +Cc: netdev, lksctp-developers

Dave,

Please do a
	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work

to get the following SCTP updates to 2.6.8-rc2.

Thanks
Sridhar

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/07/23 16:41:31-07:00 sri@us.ibm.com
#   [SCTP] Mark chunks as ineligible for fast retransmit after they are
#   retransmitted. Also mark any chunks that could not be fit in the
#   PMTU sized packet as ineligible for fast retransmit.
#
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
#
# net/sctp/outqueue.c
#
# ChangeSet
#   2004/07/22 23:22:01-07:00 sri@us.ibm.com
#   [SCTP] Fix missing '+' in the computation of sack chunk size in
#   sctp_sm_pull_sack().
#
#   Signed-off-by: Jorge Hernandez <jhh@lucent.com>
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
#
# net/sctp/sm_statefuns.c
#
# ChangeSet
#   2004/07/22 23:18:24-07:00 sri@us.ibm.com
#   [SCTP] Use idr_get_new_above() with a starting id of 1 to avoid returning
#   an associd of 0.
#
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
#
# net/sctp/sm_make_chunk.c
#
# ChangeSet
#   2004/07/22 23:15:55-07:00 sri@us.ibm.com
#   [SCTP] Fix issues with handling stale cookie error over multihoming
#   associations.
#
#   Signed-off-by: Jorge Hernandez <jhh@lucent.com>
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
#
# net/sctp/sm_statefuns.c
# net/sctp/sm_sideeffect.c
# include/net/sctp/command.h
#
# ChangeSet
#   2004/07/22 23:13:05-07:00 sri@us.ibm.com
#   [SCTP] Fix data not being delivered to user in SHUTDOWN_SENT state.
#
#   Also cleaned up sctp_sf_eat_data_6_2() and sctp_sf_eat_data_fast_4_4()
#   as they have a lot of common code.
#
#   Signed-off-by: Jorge Hernandez <jhh@lucent.com>
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
#
# net/sctp/sm_statefuns.c
# net/sctp/associola.c
# include/net/sctp/sm.h
# include/net/sctp/constants.h
#
# ChangeSet
#   2004/07/22 23:09:04-07:00 sri@us.ibm.com
#   [SCTP] Set/Get default SCTP_PEER_ADDR_PARAMS for endpoint when associd
#   and peer address are 0.
#
#   Signed-off-by: Anand R. Setlur <asetlur@lucent.com>
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
#
# net/sctp/socket.c
#
diff -Nru a/include/net/sctp/command.h b/include/net/sctp/command.h
--- a/include/net/sctp/command.h	2004-07-23 17:08:07 -07:00
+++ b/include/net/sctp/command.h	2004-07-23 17:08:07 -07:00
@@ -94,6 +94,9 @@
 	SCTP_CMD_REPORT_FWDTSN,	 /* Report new cumulative TSN Ack. */
 	SCTP_CMD_PROCESS_FWDTSN, /* Skips were reported, so process further. */
 	SCTP_CMD_CLEAR_INIT_TAG, /* Clears association peer's inittag. */
+	SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */
+	SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */
+	SCTP_CMD_FORCE_PRIM_RETRAN,  /* Forces retrans. over primary path. */
 	SCTP_CMD_LAST
 } sctp_verb_t;

diff -Nru a/include/net/sctp/constants.h b/include/net/sctp/constants.h
--- a/include/net/sctp/constants.h	2004-07-23 17:08:07 -07:00
+++ b/include/net/sctp/constants.h	2004-07-23 17:08:07 -07:00
@@ -175,6 +175,10 @@
 	SCTP_IERROR_BAD_TAG,
 	SCTP_IERROR_BIG_GAP,
 	SCTP_IERROR_DUP_TSN,
+	SCTP_IERROR_HIGH_TSN,
+	SCTP_IERROR_IGNORE_TSN,
+	SCTP_IERROR_NO_DATA,
+	SCTP_IERROR_BAD_STREAM,

 } sctp_ierror_t;

diff -Nru a/include/net/sctp/sm.h b/include/net/sctp/sm.h
--- a/include/net/sctp/sm.h	2004-07-23 17:08:07 -07:00
+++ b/include/net/sctp/sm.h	2004-07-23 17:08:07 -07:00
@@ -322,6 +322,9 @@
 				const struct sctp_chunk *chunk,
 				sctp_cmd_seq_t *commands,
 				struct sctp_chunk *err_chunk);
+int sctp_eat_data(const struct sctp_association *asoc,
+		  struct sctp_chunk *chunk,
+		  sctp_cmd_seq_t *commands);

 /* 3rd level prototypes */
 __u32 sctp_generate_tag(const struct sctp_endpoint *);
diff -Nru a/net/sctp/associola.c b/net/sctp/associola.c
--- a/net/sctp/associola.c	2004-07-23 17:08:07 -07:00
+++ b/net/sctp/associola.c	2004-07-23 17:08:07 -07:00
@@ -1093,6 +1093,7 @@
 	case SCTP_STATE_ESTABLISHED:
 	case SCTP_STATE_SHUTDOWN_PENDING:
 	case SCTP_STATE_SHUTDOWN_RECEIVED:
+	case SCTP_STATE_SHUTDOWN_SENT:
 		if ((asoc->rwnd > asoc->a_rwnd) &&
 		    ((asoc->rwnd - asoc->a_rwnd) >=
 		     min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pmtu)))
diff -Nru a/net/sctp/outqueue.c b/net/sctp/outqueue.c
--- a/net/sctp/outqueue.c	2004-07-23 17:08:07 -07:00
+++ b/net/sctp/outqueue.c	2004-07-23 17:08:07 -07:00
@@ -525,10 +525,10 @@
 			       int rtx_timeout, int *start_timer)
 {
 	struct list_head *lqueue;
-	struct list_head *lchunk;
+	struct list_head *lchunk, *lchunk1;
 	struct sctp_transport *transport = pkt->transport;
 	sctp_xmit_t status;
-	struct sctp_chunk *chunk;
+	struct sctp_chunk *chunk, *chunk1;
 	struct sctp_association *asoc;
 	int error = 0;

@@ -615,6 +615,12 @@
 			 * the transmitted list.
 			 */
 			list_add_tail(lchunk, &transport->transmitted);
+
+			/* Mark the chunk as ineligible for fast retransmit
+			 * after it is retransmitted.
+			 */
+			chunk->fast_retransmit = 0;
+
 			*start_timer = 1;
 			q->empty = 0;

@@ -622,6 +628,18 @@
 			lchunk = sctp_list_dequeue(lqueue);
 			break;
 		};
+
+		/* If we are here due to a retransmit timeout or a fast
+		 * retransmit and if there are any chunks left in the retransmit
+		 * queue that could not fit in the PMTU sized packet, they need			 * to be marked as ineligible for a subsequent fast retransmit.
+		 */
+		if (rtx_timeout && !lchunk) {
+			list_for_each(lchunk1, lqueue) {
+				chunk1 = list_entry(lchunk1, struct sctp_chunk,
+						    transmitted_list);
+				chunk1->fast_retransmit = 0;
+			}
+		}
 	}

 	return error;
diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c	2004-07-23 17:08:07 -07:00
+++ b/net/sctp/sm_make_chunk.c	2004-07-23 17:08:07 -07:00
@@ -1846,9 +1846,8 @@
 		if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
 			goto clean_up;
 		spin_lock_bh(&sctp_assocs_id_lock);
-		error = idr_get_new(&sctp_assocs_id,
-				    (void *)asoc,
-				    &assoc_id);
+		error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, 1,
+					  &assoc_id);
 		spin_unlock_bh(&sctp_assocs_id_lock);
 		if (error == -EAGAIN)
 			goto retry;
diff -Nru a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
--- a/net/sctp/sm_sideeffect.c	2004-07-23 17:08:07 -07:00
+++ b/net/sctp/sm_sideeffect.c	2004-07-23 17:08:07 -07:00
@@ -529,6 +529,23 @@
 	}
 }

+/* Helper function to stop any pending T3-RTX timers */
+static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
+				        struct sctp_association *asoc)
+{
+	struct sctp_transport *t;
+	struct list_head *pos;
+
+	list_for_each(pos, &asoc->peer.transport_addr_list) {
+		t = list_entry(pos, struct sctp_transport, transports);
+		if (timer_pending(&t->T3_rtx_timer) &&
+		    del_timer(&t->T3_rtx_timer)) {
+			sctp_transport_put(t);
+		}
+	}
+}
+
+
 /* Helper function to update the heartbeat timer. */
 static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
 				     struct sctp_association *asoc,
@@ -749,6 +766,26 @@
 	return;
 }

+/* Helper function to remove the association non-primary peer
+ * transports.
+ */
+static void sctp_cmd_del_non_primary(struct sctp_association *asoc)
+{
+	struct sctp_transport *t;
+	struct list_head *pos;
+	struct list_head *temp;
+
+	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
+		t = list_entry(pos, struct sctp_transport, transports);
+		if (!sctp_cmp_addr_exact(&t->ipaddr,
+		                         &asoc->peer.primary_addr)) {
+			sctp_assoc_del_peer(asoc, &t->ipaddr);
+		}
+	}
+
+	return;
+}
+
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
  * functionality there.
@@ -1048,6 +1085,27 @@
 			if (cmd->obj.ptr)
 				sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
 						SCTP_CHUNK(cmd->obj.ptr));
+
+			/* FIXME - Eventually come up with a cleaner way to
+			 * enabling COOKIE-ECHO + DATA bundling during
+			 * multihoming stale cookie scenarios, the following
+			 * command plays with asoc->peer.retran_path to
+			 * avoid the problem of sending the COOKIE-ECHO and
+			 * DATA in different paths, which could result
+			 * in the association being ABORTed if the DATA chunk
+			 * is processed first by the server.  Checking the
+			 * init error counter simply causes this command
+			 * to be executed only during failed attempts of
+			 * association establishment.
+			 */
+			if ((asoc->peer.retran_path !=
+			     asoc->peer.primary_path) &&
+			    (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) {
+				sctp_add_cmd_sf(commands,
+				                SCTP_CMD_FORCE_PRIM_RETRAN,
+						SCTP_NULL());
+			}
+
 			break;

 		case SCTP_CMD_GEN_SHUTDOWN:
@@ -1281,6 +1339,19 @@
 			break;
 		case SCTP_CMD_CLEAR_INIT_TAG:
 			asoc->peer.i.init_tag = 0;
+			break;
+		case SCTP_CMD_DEL_NON_PRIMARY:
+			sctp_cmd_del_non_primary(asoc);
+			break;
+		case SCTP_CMD_T3_RTX_TIMERS_STOP:
+			sctp_cmd_t3_rtx_timers_stop(commands, asoc);
+			break;
+		case SCTP_CMD_FORCE_PRIM_RETRAN:
+			t = asoc->peer.retran_path;
+			asoc->peer.retran_path = asoc->peer.primary_path;
+			error = sctp_outq_uncork(&asoc->outqueue);
+			local_cork = 0;
+			asoc->peer.retran_path = t;
 			break;
 		default:
 			printk(KERN_WARNING "Impossible command: %u, %p\n",
diff -Nru a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
--- a/net/sctp/sm_statefuns.c	2004-07-23 17:08:07 -07:00
+++ b/net/sctp/sm_statefuns.c	2004-07-23 17:08:07 -07:00
@@ -472,8 +472,6 @@
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
-	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
-			SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -674,6 +672,15 @@
 	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);

+	/* Reset init error count upon receipt of COOKIE-ACK,
+	 * to avoid problems with the managemement of this
+	 * counter in stale cookie situations when a transition back
+	 * from the COOKIE-ECHOED state to the COOKIE-WAIT
+	 * state is performed.
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
+	                SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+
 	/* RFC 2960 5.1 Normal Establishment of an Association
 	 *
 	 * E) Upon reception of the COOKIE ACK, endpoint "A" will move
@@ -1872,8 +1879,6 @@
 	time_t stale;
 	sctp_cookie_preserve_param_t bht;
 	sctp_errhdr_t *err;
-	struct list_head *pos;
-	struct sctp_transport *t;
 	struct sctp_chunk *reply;
 	struct sctp_bind_addr *bp;
 	int attempts;
@@ -1920,20 +1925,27 @@
 	/* Clear peer's init_tag cached in assoc as we are sending a new INIT */
 	sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL());

+	/* Stop pending T3-rtx and heartbeat timers */
+	sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL());
+	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL());
+
+	/* Delete non-primary peer ip addresses since we are transitioning
+	 * back to the COOKIE-WAIT state
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+
+	/* If we've sent any data bundled with COOKIE-ECHO we will need to
+	 * resend
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN,
+			SCTP_TRANSPORT(asoc->peer.primary_path));
+
 	/* Cast away the const modifier, as we want to just
 	 * rerun it through as a sideffect.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,
 			SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));

-	/* If we've sent any data bundled with COOKIE-ECHO we need to
-	 * resend.
-	 */
-	list_for_each(pos, &asoc->peer.transport_addr_list) {
-		t = list_entry(pos, struct sctp_transport, transports);
-		sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(t));
-	}
-
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -2321,12 +2333,7 @@
 					sctp_cmd_seq_t *commands)
 {
 	struct sctp_chunk *chunk = arg;
-	sctp_datahdr_t *data_hdr;
-	struct sctp_chunk *err;
-	size_t datalen;
-	sctp_verb_t deliver;
-	int tmp;
-	__u32 tsn;
+	int error;

 	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -2334,158 +2341,22 @@
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
         }

-	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
-	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
-
-	tsn = ntohl(data_hdr->tsn);
-	SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
-
-	/* ASSERT:  Now skb->data is really the user data.  */
-
-	/* Process ECN based congestion.
-	 *
-	 * Since the chunk structure is reused for all chunks within
-	 * a packet, we use ecn_ce_done to track if we've already
-	 * done CE processing for this packet.
-	 *
-	 * We need to do ECN processing even if we plan to discard the
-	 * chunk later.
-	 */
-
-	if (!chunk->ecn_ce_done) {
-		struct sctp_af *af;
-		chunk->ecn_ce_done = 1;
-
-		af = sctp_get_af_specific(
-			ipver2af(chunk->skb->nh.iph->version));
-
-		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
-			/* Do real work as sideffect. */
-			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
-					SCTP_U32(tsn));
-		}
-	}
-
-	tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn);
-	if (tmp < 0) {
-		/* The TSN is too high--silently discard the chunk and
-		 * count on it getting retransmitted later.
-		 */
+	error = sctp_eat_data(asoc, chunk, commands );
+	switch (error) {
+	case SCTP_IERROR_NO_ERROR:
+		break;
+	case SCTP_IERROR_HIGH_TSN:
+	case SCTP_IERROR_BAD_STREAM:
 		goto discard_noforce;
-	} else if (tmp > 0) {
-		/* This is a duplicate.  Record it.  */
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn));
+	case SCTP_IERROR_DUP_TSN:
+	case SCTP_IERROR_IGNORE_TSN:
 		goto discard_force;
+	case SCTP_IERROR_NO_DATA:
+		goto consume;
+	default:
+		BUG();
 	}

-	/* This is a new TSN.  */
-
-	/* Discard if there is no room in the receive window.
-	 * Actually, allow a little bit of overflow (up to a MTU).
-	 */
-	datalen = ntohs(chunk->chunk_hdr->length);
-	datalen -= sizeof(sctp_data_chunk_t);
-
-	deliver = SCTP_CMD_CHUNK_ULP;
-
-	/* Think about partial delivery. */
-	if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
-
-		/* Even if we don't accept this chunk there is
-		 * memory pressure.
-		 */
-		sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL());
-	}
-
-        /* Spill over rwnd a little bit.  Note: While allowed, this spill over
-	 * seems a bit troublesome in that frag_point varies based on
-	 * PMTU.  In cases, such as loopback, this might be a rather
-	 * large spill over.
-	 */
-	if (!asoc->rwnd || asoc->rwnd_over ||
-	    (datalen > asoc->rwnd + asoc->frag_point)) {
-
-		/* If this is the next TSN, consider reneging to make
-		 * room.   Note: Playing nice with a confused sender.  A
-		 * malicious sender can still eat up all our buffer
-		 * space and in the future we may want to detect and
-		 * do more drastic reneging.
-		 */
-		if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
-		    (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
-			SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
-			deliver = SCTP_CMD_RENEGE;
-		} else {
-			SCTP_DEBUG_PRINTK("Discard tsn: %u len: %Zd, "
-					  "rwnd: %d\n", tsn, datalen,
-					  asoc->rwnd);
-			goto discard_force;
-		}
-	}
-
-	/*
-	 * Section 3.3.10.9 No User Data (9)
-	 *
-	 * Cause of error
-	 * ---------------
-	 * No User Data:  This error cause is returned to the originator of a
-	 * DATA chunk if a received DATA chunk has no user data.
-	 */
-	if (unlikely(0 == datalen)) {
-		err = sctp_make_abort_no_data(asoc, chunk, tsn);
-		if (err) {
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		}
-		/* We are going to ABORT, so we might as well stop
-		 * processing the rest of the chunks in the packet.
-		 */
-		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
-		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-				SCTP_U32(SCTP_ERROR_NO_DATA));
-		SCTP_INC_STATS(SctpAborteds);
-		SCTP_DEC_STATS(SctpCurrEstab);
-		return SCTP_DISPOSITION_CONSUME;
-	}
-
-	/* If definately accepting the DATA chunk, record its TSN, otherwise
-	 * wait for renege processing.
-	 */
-	if (SCTP_CMD_CHUNK_ULP == deliver)
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
-	/* Note: Some chunks may get overcounted (if we drop) or overcounted
-	 * if we renege and the chunk arrives again.
-	 */
-	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
-		SCTP_INC_STATS(SctpInUnorderChunks);
-	else
-		SCTP_INC_STATS(SctpInOrderChunks);
-
-	/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
-	 *
-	 * If an endpoint receive a DATA chunk with an invalid stream
-	 * identifier, it shall acknowledge the reception of the DATA chunk
-	 * following the normal procedure, immediately send an ERROR chunk
-	 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10)
-	 * and discard the DATA chunk.
-	 */
-	if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
-		err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
-					 &data_hdr->stream,
-					 sizeof(data_hdr->stream));
-		if (err)
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		goto discard_noforce;
-	}
-
-	/* Send the data up to the user.  Note:  Schedule  the
-	 * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK
-	 * chunk needs the updated rwnd.
-	 */
-	sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk));
-
 	if (asoc->autoclose) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
@@ -2551,6 +2422,9 @@
 				SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
 	}
 	return SCTP_DISPOSITION_DISCARD;
+consume:
+	return SCTP_DISPOSITION_CONSUME;
+
 }

 /*
@@ -2576,11 +2450,7 @@
 				     sctp_cmd_seq_t *commands)
 {
 	struct sctp_chunk *chunk = arg;
-	sctp_datahdr_t *data_hdr;
-	struct sctp_chunk *err;
-	size_t datalen;
-	int tmp;
-	__u32 tsn;
+	int error;

 	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -2588,110 +2458,23 @@
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 	}

-	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *) chunk->skb->data;
-	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
-
-	tsn = ntohl(data_hdr->tsn);
-
-	SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
-
-	/* ASSERT:  Now skb->data is really the user data.  */
-
-	/* Process ECN based congestion.
-	 *
-	 * Since the chunk structure is reused for all chunks within
-	 * a packet, we use ecn_ce_done to track if we've already
-	 * done CE processing for this packet.
-	 *
-	 * We need to do ECN processing even if we plan to discard the
-	 * chunk later.
-	 */
-	if (!chunk->ecn_ce_done) {
-		struct sctp_af *af;
-		chunk->ecn_ce_done = 1;
-
-		af = sctp_get_af_specific(
-			ipver2af(chunk->skb->nh.iph->version));
-
-		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
-			/* Do real work as sideffect. */
-			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
-					SCTP_U32(tsn));
-		}
-	}
-
-	tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn);
-	if (tmp < 0) {
-		/* The TSN is too high--silently discard the chunk and
-		 * count on it getting retransmitted later.
-		 */
-		goto gen_shutdown;
-	} else if (tmp > 0) {
-		/* This is a duplicate.  Record it.  */
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn));
-		goto gen_shutdown;
-	}
-
-	/* This is a new TSN.  */

-	datalen = ntohs(chunk->chunk_hdr->length);
-	datalen -= sizeof(sctp_data_chunk_t);
-
-	/*
-	 * Section 3.3.10.9 No User Data (9)
-	 *
-	 * Cause of error
-	 * ---------------
-	 * No User Data:  This error cause is returned to the originator of a
-	 * DATA chunk if a received DATA chunk has no user data.
-	 */
-	if (unlikely(0 == datalen)) {
-		err = sctp_make_abort_no_data(asoc, chunk, tsn);
-		if (err) {
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		}
-		/* We are going to ABORT, so we might as well stop
-		 * processing the rest of the chunks in the packet.
-		 */
-		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
-		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-				SCTP_U32(SCTP_ERROR_NO_DATA));
-		SCTP_INC_STATS(SctpAborteds);
-		SCTP_DEC_STATS(SctpCurrEstab);
-		return SCTP_DISPOSITION_CONSUME;
-	}
-
-	/* We are accepting this DATA chunk. */
-
-	/* Record the fact that we have received this TSN.  */
-	sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
-	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
-		SCTP_INC_STATS(SctpInUnorderChunks);
-	else
-		SCTP_INC_STATS(SctpInOrderChunks);
-
-	/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
-	 *
-	 * If an endpoint receive a DATA chunk with an invalid stream
-	 * identifier, it shall acknowledge the reception of the DATA chunk
-	 * following the normal procedure, immediately send an ERROR chunk
-	 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10)
-	 * and discard the DATA chunk.
-	 */
-	if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
-		err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
-					 &data_hdr->stream,
-					 sizeof(data_hdr->stream));
-		if (err) {
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		}
+	error = sctp_eat_data(asoc, chunk, commands );
+	switch (error) {
+	case SCTP_IERROR_NO_ERROR:
+	case SCTP_IERROR_HIGH_TSN:
+	case SCTP_IERROR_DUP_TSN:
+	case SCTP_IERROR_IGNORE_TSN:
+	case SCTP_IERROR_BAD_STREAM:
+		break;
+	case SCTP_IERROR_NO_DATA:
+		goto consume;
+	default:
+		BUG();
 	}

 	/* Go a head and force a SACK, since we are shutting down. */
-gen_shutdown:
+
 	/* Implementor's Guide.
 	 *
 	 * While in SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately
@@ -2707,6 +2490,8 @@
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
 	}
+
+consume:
 	return SCTP_DISPOSITION_CONSUME;
 }

@@ -4709,7 +4494,7 @@
 	num_blocks = ntohs(sack->num_gap_ack_blocks);
 	num_dup_tsns = ntohs(sack->num_dup_tsns);
 	len = sizeof(struct sctp_sackhdr);
-	len = (num_blocks + num_dup_tsns) * sizeof(__u32);
+	len += (num_blocks + num_dup_tsns) * sizeof(__u32);
 	if (len > chunk->skb->len)
 		return NULL;

@@ -4847,4 +4632,172 @@
 		} else
 			sctp_chunk_free (err_chunk);
 	}
+}
+
+
+/* Process a data chunk */
+int sctp_eat_data(const struct sctp_association *asoc,
+		  struct sctp_chunk *chunk,
+		  sctp_cmd_seq_t *commands)
+{
+	sctp_datahdr_t *data_hdr;
+	struct sctp_chunk *err;
+	size_t datalen;
+	sctp_verb_t deliver;
+	int tmp;
+	__u32 tsn;
+
+	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
+	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
+
+	tsn = ntohl(data_hdr->tsn);
+	SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
+
+	/* ASSERT:  Now skb->data is really the user data.  */
+
+	/* Process ECN based congestion.
+	 *
+	 * Since the chunk structure is reused for all chunks within
+	 * a packet, we use ecn_ce_done to track if we've already
+	 * done CE processing for this packet.
+	 *
+	 * We need to do ECN processing even if we plan to discard the
+	 * chunk later.
+	 */
+
+	if (!chunk->ecn_ce_done) {
+		struct sctp_af *af;
+		chunk->ecn_ce_done = 1;
+
+		af = sctp_get_af_specific(
+			ipver2af(chunk->skb->nh.iph->version));
+
+		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
+			/* Do real work as sideffect. */
+			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
+					SCTP_U32(tsn));
+		}
+	}
+
+	tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn);
+	if (tmp < 0) {
+		/* The TSN is too high--silently discard the chunk and
+		 * count on it getting retransmitted later.
+		 */
+		return SCTP_IERROR_HIGH_TSN;
+	} else if (tmp > 0) {
+		/* This is a duplicate.  Record it.  */
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn));
+		return SCTP_IERROR_DUP_TSN;
+	}
+
+	/* This is a new TSN.  */
+
+	/* Discard if there is no room in the receive window.
+	 * Actually, allow a little bit of overflow (up to a MTU).
+	 */
+	datalen = ntohs(chunk->chunk_hdr->length);
+	datalen -= sizeof(sctp_data_chunk_t);
+
+	deliver = SCTP_CMD_CHUNK_ULP;
+
+	/* Think about partial delivery. */
+	if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
+
+		/* Even if we don't accept this chunk there is
+		 * memory pressure.
+		 */
+		sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL());
+	}
+
+        /* Spill over rwnd a little bit.  Note: While allowed, this spill over
+	 * seems a bit troublesome in that frag_point varies based on
+	 * PMTU.  In cases, such as loopback, this might be a rather
+	 * large spill over.
+	 */
+	if (!asoc->rwnd || asoc->rwnd_over ||
+	    (datalen > asoc->rwnd + asoc->frag_point)) {
+
+		/* If this is the next TSN, consider reneging to make
+		 * room.   Note: Playing nice with a confused sender.  A
+		 * malicious sender can still eat up all our buffer
+		 * space and in the future we may want to detect and
+		 * do more drastic reneging.
+		 */
+		if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
+		    (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
+			SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
+			deliver = SCTP_CMD_RENEGE;
+		} else {
+			SCTP_DEBUG_PRINTK("Discard tsn: %u len: %Zd, "
+					  "rwnd: %d\n", tsn, datalen,
+					  asoc->rwnd);
+			return SCTP_IERROR_IGNORE_TSN;
+		}
+	}
+
+	/*
+	 * Section 3.3.10.9 No User Data (9)
+	 *
+	 * Cause of error
+	 * ---------------
+	 * No User Data:  This error cause is returned to the originator of a
+	 * DATA chunk if a received DATA chunk has no user data.
+	 */
+	if (unlikely(0 == datalen)) {
+		err = sctp_make_abort_no_data(asoc, chunk, tsn);
+		if (err) {
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(err));
+		}
+		/* We are going to ABORT, so we might as well stop
+		 * processing the rest of the chunks in the packet.
+		 */
+		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
+				SCTP_U32(SCTP_ERROR_NO_DATA));
+		SCTP_INC_STATS(SctpAborteds);
+		SCTP_DEC_STATS(SctpCurrEstab);
+		return SCTP_IERROR_NO_DATA;
+	}
+
+	/* If definately accepting the DATA chunk, record its TSN, otherwise
+	 * wait for renege processing.
+	 */
+	if (SCTP_CMD_CHUNK_ULP == deliver)
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
+
+	/* Note: Some chunks may get overcounted (if we drop) or overcounted
+	 * if we renege and the chunk arrives again.
+	 */
+	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
+		SCTP_INC_STATS(SctpInUnorderChunks);
+	else
+		SCTP_INC_STATS(SctpInOrderChunks);
+
+	/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
+	 *
+	 * If an endpoint receive a DATA chunk with an invalid stream
+	 * identifier, it shall acknowledge the reception of the DATA chunk
+	 * following the normal procedure, immediately send an ERROR chunk
+	 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10)
+	 * and discard the DATA chunk.
+	 */
+	if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
+		err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
+					 &data_hdr->stream,
+					 sizeof(data_hdr->stream));
+		if (err)
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(err));
+		return SCTP_IERROR_BAD_STREAM;
+	}
+
+	/* Send the data up to the user.  Note:  Schedule  the
+	 * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK
+	 * chunk needs the updated rwnd.
+	 */
+	sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk));
+
+	return SCTP_IERROR_NO_ERROR;
 }
diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c	2004-07-23 17:08:07 -07:00
+++ b/net/sctp/socket.c	2004-07-23 17:08:07 -07:00
@@ -1697,6 +1697,32 @@
 	if (copy_from_user(&params, optval, optlen))
 		return -EFAULT;

+	/*
+	 * API 7. Socket Options (setting the default value for the endpoint)
+	 * All options that support specific settings on an association by
+	 * filling in either an association id variable or a sockaddr_storage
+	 * SHOULD also support setting of the same value for the entire endpoint
+	 * (i.e. future associations). To accomplish this the following logic is
+	 * used when setting one of these options:
+
+	 * c) If neither the sockaddr_storage or association identification is
+	 *    set i.e. the sockaddr_storage is set to all 0's (INADDR_ANY) and
+	 *    the association identification is 0, the settings are a default
+	 *    and to be applied to the endpoint (all future associations).
+	 */
+
+	/* update default value for endpoint (all future associations) */
+	if (!params.spp_assoc_id &&
+	    sctp_is_any(( union sctp_addr *)&params.spp_address)) {
+		if (params.spp_hbinterval)
+			sctp_sk(sk)->paddrparam.spp_hbinterval =
+						params.spp_hbinterval;
+		if (sctp_max_retrans_path)
+			sctp_sk(sk)->paddrparam.spp_pathmaxrxt =
+						params.spp_pathmaxrxt;
+		return 0;
+	}
+
 	trans = sctp_addr_id2transport(sk, &params.spp_address,
 				       params.spp_assoc_id);
 	if (!trans)
@@ -2864,6 +2890,17 @@
 	if (copy_from_user(&params, optval, len))
 		return -EFAULT;

+	/* If no association id is specified retrieve the default value
+	 * for the endpoint that will be used for all future associations
+	 */
+	if (!params.spp_assoc_id &&
+	    sctp_is_any(( union sctp_addr *)&params.spp_address)) {
+		params.spp_hbinterval = sctp_sk(sk)->paddrparam.spp_hbinterval;
+		params.spp_pathmaxrxt = sctp_sk(sk)->paddrparam.spp_pathmaxrxt;
+
+		goto done;
+	}
+
 	trans = sctp_addr_id2transport(sk, &params.spp_address,
 				       params.spp_assoc_id);
 	if (!trans)
@@ -2883,6 +2920,7 @@
 	 */
 	params.spp_pathmaxrxt = trans->error_threshold;

+done:
 	if (copy_to_user(optval, &params, len))
 		return -EFAULT;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BK PATCH] 2.6 SCTP updates
  2004-07-24  0:18 Sridhar Samudrala
@ 2004-07-25  5:27 ` David S. Miller
  2004-07-26 13:51   ` Sridhar Samudrala
  0 siblings, 1 reply; 11+ messages in thread
From: David S. Miller @ 2004-07-25  5:27 UTC (permalink / raw)
  To: Sridhar Samudrala; +Cc: netdev, lksctp-developers

On Fri, 23 Jul 2004 17:18:11 -0700 (PDT)
Sridhar Samudrala <sri@us.ibm.com> wrote:

> Please do a
> 	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
> 
> to get the following SCTP updates to 2.6.8-rc2.

Pulled, thanks Sridhar.  Will there be a 2.4.x version of
any of these SCTP changes?

Thanks again.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BK PATCH] 2.6 SCTP updates
  2004-07-25  5:27 ` David S. Miller
@ 2004-07-26 13:51   ` Sridhar Samudrala
  0 siblings, 0 replies; 11+ messages in thread
From: Sridhar Samudrala @ 2004-07-26 13:51 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, lksctp-developers

David S. Miller wrote:

>On Fri, 23 Jul 2004 17:18:11 -0700 (PDT)
>Sridhar Samudrala <sri@us.ibm.com> wrote:
>
>  
>
>>Please do a
>>	bk pull http://linux-lksctp.bkbits.net/lksctp-2.5.work
>>
>>to get the following SCTP updates to 2.6.8-rc2.
>>    
>>
>
>Pulled, thanks Sridhar.  Will there be a 2.4.x version of
>any of these SCTP changes?
>
>  
>
Dave,

I plan to submit a 2.4 version of these patches along with the 2.6 
sparse cleanup stuff
so that both the codebases don't deviate too much, but it may be a 
couple of  weeks
from now. I am currently at an SCTP interop event and will be on 
vacation next week.

Thanks
Sridhar

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2004-07-26 13:51 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-10-02 23:46 [BK PATCH] 2.6 SCTP updates Sridhar Samudrala
2003-10-03  9:48 ` David S. Miller
  -- strict thread matches above, loose matches on Subject: below --
2004-02-14  0:07 Sridhar Samudrala
2004-02-14  5:52 ` David S. Miller
2004-02-16  5:55   ` Sridhar Samudrala
2004-03-23 20:13 Sridhar Samudrala
2004-03-24 20:01 ` David S. Miller
2004-04-06 17:28 Sridhar Samudrala
2004-07-24  0:18 Sridhar Samudrala
2004-07-25  5:27 ` David S. Miller
2004-07-26 13:51   ` Sridhar Samudrala

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).