On Fri, 2005-11-11 at 15:08 -0800, David S. Miller wrote:
> From: Sridhar Samudrala <[EMAIL PROTECTED]>
> Date: Fri, 11 Nov 2005 15:01:42 -0800
> 
> > I think it is much easier for me to send the patches as attachments
> > rather than re-applying on a new tree. So i am attaching the 4 patches
> > and hope this works for you.
> 
> Actually, there are no "Signed-off-by:" lines for any of
> these patches, could you please add them?

Sorry about that. Here are the patches with Signed-off-by lines.

Thanks
Sridhar
[SCTP] Fix potential NULL pointer dereference in sctp_v4_get_saddr

It is possible to get to sctp_v4_get_saddr() without a valid
association.  This happens when processing OOTB packets and
the cached route entry is no longer valid.
However, when responding to OOTB packets we already properly
set the source address based on the information in the OOTB
packet.  So, if we we get to sctp_v4_get_saddr() without an
association we can simply return.

Signed-off-by: Vladislav Yasevich <[EMAIL PROTECTED]>
Signed-off-by: Sridhar Samudrala <[EMAIL PROTECTED]>
---
commit 35f8e50574015eef79a278729119c7d627c4c970
tree fdcf02d7a0b2e09ce4edc6330625ee91877d8ec5
parent d12eb7e11cf30c30f639b2093735af2ac177830b
author Vladislav Yasevich <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:05:53 -0800
committer Sridhar Samudrala <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:05:53 -0800

 net/sctp/protocol.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 26de4d3..dc9dff3 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -530,6 +530,9 @@ static void sctp_v4_get_saddr(struct sct
 {
 	struct rtable *rt = (struct rtable *)dst;
 
+	if (!asoc)
+		return;
+
 	if (rt) {
 		saddr->v4.sin_family = AF_INET;
 		saddr->v4.sin_port = asoc->base.bind_addr.port;  
[SCTP] Remove timeouts[] array from sctp_endpoint.

The socket level timeout values are maintained in sctp_sock and
association level timeouts are in sctp_association. So there is
no need for ep->timeouts.

Signed-off-by: Vladislav Yasevich <[EMAIL PROTECTED]>
Signed-off-by: Sridhar Samudrala <[EMAIL PROTECTED]>
---
commit 0b9b68d7014c01769926afac6314db27fadd565d
tree 9583431d2983e604f9a4f091b4f06e2749944283
parent 35f8e50574015eef79a278729119c7d627c4c970
author Vladislav Yasevich <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:18:45 -0800
committer Sridhar Samudrala <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:18:45 -0800

 include/net/sctp/structs.h |    3 ---
 net/sctp/associola.c       |   24 ++++++++++++++++++++++--
 net/sctp/endpointola.c     |   23 -----------------------
 net/sctp/sm_sideeffect.c   |    6 +++---
 net/sctp/socket.c          |    1 -
 5 files changed, 25 insertions(+), 32 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 9c385b6..2aad446 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1222,9 +1222,6 @@ struct sctp_endpoint {
 	int last_key;
 	int key_changed_at;
 
-	/* Default timeouts.  */
-	int timeouts[SCTP_NUM_TIMEOUT_TYPES];
-
 	/* sendbuf acct. policy.	*/
 	__u32 sndbuf_policy;
 };
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 8c8ddf7..5f07ddb 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -128,9 +128,29 @@ static struct sctp_association *sctp_ass
 	 */
 	asoc->max_burst = sctp_max_burst;
 
-	/* Copy things from the endpoint.  */
+	/* initialize association timers */
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = asoc->rto_initial;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = asoc->rto_initial;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = asoc->rto_initial;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
+
+	/* sctpimpguide Section 2.12.2
+	 * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
+	 * recommended value of 5 times 'RTO.Max'.
+	 */
+        asoc->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
+		= 5 * asoc->rto_max;
+
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
+		SCTP_DEFAULT_TIMEOUT_SACK;
+	asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
+		sp->autoclose * HZ;
+	
+	/* Initilizes the timers */
 	for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
-		asoc->timeouts[i] = ep->timeouts[i];
 		init_timer(&asoc->timers[i]);
 		asoc->timers[i].function = sctp_timer_events[i];
 		asoc->timers[i].data = (unsigned long) asoc;
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 96984f7..0df7689 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -70,7 +70,6 @@ static struct sctp_endpoint *sctp_endpoi
 						struct sock *sk,
 						gfp_t gfp)
 {
-	struct sctp_sock *sp = sctp_sk(sk);
 	memset(ep, 0, sizeof(struct sctp_endpoint));
 
 	/* Initialize the base structure. */
@@ -100,28 +99,6 @@ static struct sctp_endpoint *sctp_endpoi
 	/* Create the lists of associations.  */
 	INIT_LIST_HEAD(&ep->asocs);
 
-	/* Set up the base timeout information.  */
-	ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
-	ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
-		msecs_to_jiffies(sp->rtoinfo.srto_initial);
-	ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
-		msecs_to_jiffies(sp->rtoinfo.srto_initial);
-	ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
-		msecs_to_jiffies(sp->rtoinfo.srto_initial);
-	ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
-	ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
-
-	/* sctpimpguide-05 Section 2.12.2
-	 * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
-	 * recommended value of 5 times 'RTO.Max'.
-	 */
-        ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
-		= 5 * msecs_to_jiffies(sp->rtoinfo.srto_max);
-
-	ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
-	ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] = sctp_sack_timeout;
-	ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
-
 	/* Use SCTP specific send buffer space queues.  */
 	ep->sndbuf_policy = sctp_sndbuf_policy;
 	sk->sk_write_space = sctp_write_space;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index f84173e..8239471 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -385,7 +385,7 @@ sctp_timer_event_t *sctp_timer_events[SC
 	NULL,
 	sctp_generate_t4_rto_event,
 	sctp_generate_t5_shutdown_guard_event,
-	sctp_generate_heartbeat_event,
+	NULL,
 	sctp_generate_sack_event,
 	sctp_generate_autoclose_event,
 };
@@ -689,9 +689,9 @@ static void sctp_cmd_new_state(sctp_cmd_
 		 * increased due to timer expirations.
 		 */
 		asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
-			asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT];
+						asoc->rto_initial;
 		asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
-			asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE];
+						asoc->rto_initial;
 	}
 
 	if (sctp_state(asoc, ESTABLISHED) ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index b529af5..4d1b8d8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1932,7 +1932,6 @@ static int sctp_setsockopt_autoclose(str
 	if (copy_from_user(&sp->autoclose, optval, optlen))
 		return -EFAULT;
 
-	sp->ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
 	return 0;
 }
 
[SCTP] Fix ia64 NaT consumption fault with sctp_sideffect commands.

On ia64, it is possible to get NaT Consumption Fault and a kernel panic
when initializing sctp sideeffect commands arguments.  The union
sctp_arg_t contains different sized elements and when loading a smaller
sized element (32 or 16 bits), it is possible for a speculative load to
fail and result in a NaT bit set which causes a kernel crash.  The easy
way to get around it is to load the largerst member of the union.

Signed-off-by: Vladislav Yasevich <[EMAIL PROTECTED]>
Signed-off-by: Sridhar Samudrala <[EMAIL PROTECTED]>
---
commit 015b19fd98d04bf27560393ccf45130208e2d41c
tree 2bfaf057427757ab4d974591613e22fa39171775
parent 0b9b68d7014c01769926afac6314db27fadd565d
author Vladislav Yasevich <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:22:30 -0800
committer Sridhar Samudrala <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:22:30 -0800

 include/net/sctp/command.h |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index dc107ff..34a1a09 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -120,6 +120,7 @@ typedef union {
 	int error;
 	sctp_state_t state;
 	sctp_event_timeout_t to;
+	unsigned long zero;
 	void *ptr;
 	struct sctp_chunk *chunk;
 	struct sctp_association *asoc;
@@ -148,17 +149,17 @@ static inline sctp_arg_t SCTP_NULL(void)
 }
 static inline sctp_arg_t SCTP_NOFORCE(void)
 {
-	sctp_arg_t retval; retval.i32 = 0; return retval;
+	sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval;
 }
 static inline sctp_arg_t SCTP_FORCE(void)
 {
-	sctp_arg_t retval; retval.i32 = 1; return retval;
+	sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval;
 }
 
 #define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
 static inline sctp_arg_t	\
 SCTP_## name (type arg)		\
-{ sctp_arg_t retval; retval.elt = arg; return retval; }
+{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; }
 
 SCTP_ARG_CONSTRUCTOR(I32,	__s32, i32)
 SCTP_ARG_CONSTRUCTOR(U32,	__u32, u32)
[SCTP] Include ulpevents in socket receive buffer accounting.

Also introduces a sysctl option to configure the receive buffer
accounting policy to be either at socket or association level.
Default is all the associations on the same socket share the
receive buffer.

Signed-off-by: Neil Horman <[EMAIL PROTECTED]> 
Signed-off-by: Sridhar Samudrala <[EMAIL PROTECTED]>
---
commit 9be34c87779a838a9fb86f53f30ab48da1a72a7a
tree f36343f35c4edfe283aa2381ca2913a665c510e9
parent 015b19fd98d04bf27560393ccf45130208e2d41c
author Neil Horman <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:34:23 -0800
committer Sridhar Samudrala <[EMAIL PROTECTED]> Fri, 11 Nov 2005 10:34:23 -0800

 include/linux/sysctl.h     |    1 +
 include/net/sctp/structs.h |   16 ++++++++++++++++
 net/sctp/associola.c       |    9 +++++++--
 net/sctp/endpointola.c     |    3 +++
 net/sctp/input.c           |   20 --------------------
 net/sctp/protocol.c        |    3 +++
 net/sctp/sm_statefuns.c    |   22 ++++++++++++++++++++++
 net/sctp/socket.c          |    4 ++++
 net/sctp/sysctl.c          |    8 ++++++++
 net/sctp/ulpevent.c        |   24 +++++++-----------------
 10 files changed, 71 insertions(+), 39 deletions(-)

diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index ab2791b..64f203c 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -715,6 +715,7 @@ enum {
 	NET_SCTP_PRSCTP_ENABLE		 = 14,
 	NET_SCTP_SNDBUF_POLICY		 = 15,
 	NET_SCTP_SACK_TIMEOUT		 = 16,
+	NET_SCTP_RCVBUF_POLICY		 = 17,
 };
 
 /* /proc/sys/net/bridge */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 2aad446..8e7794e 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -161,6 +161,13 @@ extern struct sctp_globals {
 	 */
 	int sndbuf_policy;
 
+	/*
+	 * Policy for preforming sctp/socket accounting
+	 * 0   - do socket level accounting, all assocs share sk_rcvbuf
+	 * 1   - do sctp accounting, each asoc may use sk_rcvbuf bytes
+	 */
+	int rcvbuf_policy;
+
 	/* Delayed SACK timeout  200ms default*/
 	int sack_timeout;
 
@@ -218,6 +225,7 @@ extern struct sctp_globals {
 #define sctp_cookie_preserve_enable	(sctp_globals.cookie_preserve_enable)
 #define sctp_max_retrans_association	(sctp_globals.max_retrans_association)
 #define sctp_sndbuf_policy	 	(sctp_globals.sndbuf_policy)
+#define sctp_rcvbuf_policy	 	(sctp_globals.rcvbuf_policy)
 #define sctp_max_retrans_path		(sctp_globals.max_retrans_path)
 #define sctp_max_retrans_init		(sctp_globals.max_retrans_init)
 #define sctp_sack_timeout		(sctp_globals.sack_timeout)
@@ -1224,6 +1232,9 @@ struct sctp_endpoint {
 
 	/* sendbuf acct. policy.	*/
 	__u32 sndbuf_policy;
+
+	/* rcvbuf acct. policy.	*/
+	__u32 rcvbuf_policy;
 };
 
 /* Recover the outter endpoint structure. */
@@ -1550,6 +1561,11 @@ struct sctp_association {
 	 */
 	int sndbuf_used;
 
+	/* This is the amount of memory that this association has allocated
+	 * in the receive path at any given time.
+	 */
+	atomic_t rmem_alloc;
+
 	/* This is the wait queue head for send requests waiting on
 	 * the association sndbuf space.
 	 */
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 5f07ddb..dec68a6 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -177,10 +177,10 @@ static struct sctp_association *sctp_ass
 	 * RFC 6 - A SCTP receiver MUST be able to receive a minimum of
 	 * 1500 bytes in one SCTP packet.
 	 */
-	if (sk->sk_rcvbuf < SCTP_DEFAULT_MINWINDOW)
+	if ((sk->sk_rcvbuf/2) < SCTP_DEFAULT_MINWINDOW)
 		asoc->rwnd = SCTP_DEFAULT_MINWINDOW;
 	else
-		asoc->rwnd = sk->sk_rcvbuf;
+		asoc->rwnd = sk->sk_rcvbuf/2;
 
 	asoc->a_rwnd = asoc->rwnd;
 
@@ -192,6 +192,9 @@ static struct sctp_association *sctp_ass
 	/* Set the sndbuf size for transmit.  */
 	asoc->sndbuf_used = 0;
 
+	/* Initialize the receive memory counter */
+	atomic_set(&asoc->rmem_alloc, 0);
+
 	init_waitqueue_head(&asoc->wait);
 
 	asoc->c.my_vtag = sctp_generate_tag(ep);
@@ -400,6 +403,8 @@ static void sctp_association_destroy(str
 		spin_unlock_bh(&sctp_assocs_id_lock);
 	}
 
+	BUG_TRAP(!atomic_read(&asoc->rmem_alloc));
+
 	if (asoc->base.malloced) {
 		kfree(asoc);
 		SCTP_DBG_OBJCNT_DEC(assoc);
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 0df7689..67bd530 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -104,6 +104,9 @@ static struct sctp_endpoint *sctp_endpoi
 	sk->sk_write_space = sctp_write_space;
 	sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
 
+	/* Get the receive buffer policy for this endpoint */
+	ep->rcvbuf_policy = sctp_rcvbuf_policy;
+
 	/* Initialize the secret key used with cookie. */
 	get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
 	ep->last_key = ep->current_key = 0;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 28f3224..b24ff2c 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -100,21 +100,6 @@ static inline int sctp_rcv_checksum(stru
 	return 0;
 }
 
-/* The free routine for skbuffs that sctp receives */
-static void sctp_rfree(struct sk_buff *skb)
-{
-	atomic_sub(sizeof(struct sctp_chunk),&skb->sk->sk_rmem_alloc);
-	sock_rfree(skb);
-}
-
-/* The ownership wrapper routine to do receive buffer accounting */
-static void sctp_rcv_set_owner_r(struct sk_buff *skb, struct sock *sk)
-{
-	skb_set_owner_r(skb,sk);
-	skb->destructor = sctp_rfree;
-	atomic_add(sizeof(struct sctp_chunk),&sk->sk_rmem_alloc);
-}
-
 struct sctp_input_cb {
 	union {
 		struct inet_skb_parm	h4;
@@ -217,9 +202,6 @@ int sctp_rcv(struct sk_buff *skb)
 		rcvr = &ep->base;
 	}
 
-	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
-		goto discard_release;
-
 	/*
 	 * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
 	 * An SCTP packet is called an "out of the blue" (OOTB)
@@ -256,8 +238,6 @@ int sctp_rcv(struct sk_buff *skb)
 	}
 	SCTP_INPUT_CB(skb)->chunk = chunk;
 
-	sctp_rcv_set_owner_r(skb,sk);
-
 	/* Remember what endpoint is to handle this packet. */
 	chunk->rcvr = rcvr;
 
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index dc9dff3..f775d78 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1050,6 +1050,9 @@ SCTP_STATIC __init int sctp_init(void)
 	/* Sendbuffer growth	    - do per-socket accounting */
 	sctp_sndbuf_policy		= 0;
 
+	/* Rcvbuffer growth	    - do per-socket accounting */
+	sctp_rcvbuf_policy		= 0;
+
 	/* HB.interval              - 30 seconds */
 	sctp_hb_interval		= SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 505c7de..475bfb4 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -5160,6 +5160,8 @@ static int sctp_eat_data(const struct sc
 	sctp_verb_t deliver;
 	int tmp;
 	__u32 tsn;
+	int account_value;
+	struct sock *sk = asoc->base.sk;
 
 	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
 	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
@@ -5169,6 +5171,26 @@ static int sctp_eat_data(const struct sc
 
 	/* ASSERT:  Now skb->data is really the user data.  */
 
+	/*
+	 * if we are established, and we have used up our receive
+	 * buffer memory, drop the frame
+	 */
+	if (asoc->state == SCTP_STATE_ESTABLISHED) {
+		/*
+		 * If the receive buffer policy is 1, then each
+		 * association can allocate up to sk_rcvbuf bytes
+		 * otherwise, all the associations in aggregate
+		 * may allocate up to sk_rcvbuf bytes
+		 */
+		if (asoc->ep->rcvbuf_policy)
+			account_value = atomic_read(&asoc->rmem_alloc);
+		else
+			account_value = atomic_read(&sk->sk_rmem_alloc);
+
+		if (account_value > sk->sk_rcvbuf)
+			return SCTP_IERROR_IGNORE_TSN;
+	}
+
 	/* Process ECN based congestion.
 	 *
 	 * Since the chunk structure is reused for all chunks within
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 4d1b8d8..abab81f 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5114,8 +5114,10 @@ static void sctp_sock_migrate(struct soc
 	sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
 		event = sctp_skb2event(skb);
 		if (event->asoc == assoc) {
+			sock_rfree(skb);
 			__skb_unlink(skb, &oldsk->sk_receive_queue);
 			__skb_queue_tail(&newsk->sk_receive_queue, skb);
+			skb_set_owner_r(skb, newsk);
 		}
 	}
 
@@ -5143,8 +5145,10 @@ static void sctp_sock_migrate(struct soc
 		sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
 			event = sctp_skb2event(skb);
 			if (event->asoc == assoc) {
+				sock_rfree(skb);
 				__skb_unlink(skb, &oldsp->pd_lobby);
 				__skb_queue_tail(queue, skb);
+				skb_set_owner_r(skb, newsk);
 			}
 		}
 
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 75b28dd..fcd7096 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -121,6 +121,14 @@ static ctl_table sctp_table[] = {
 		.proc_handler	= &proc_dointvec
 	},
 	{
+		.ctl_name	= NET_SCTP_RCVBUF_POLICY,
+		.procname	= "rcvbuf_policy",
+		.data		= &sctp_rcvbuf_policy,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
 		.ctl_name	= NET_SCTP_PATH_MAX_RETRANS,
 		.procname	= "path_max_retrans",
 		.data		= &sctp_max_retrans_path,
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index e049f41..ba97f97 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -52,19 +52,6 @@ static void sctp_ulpevent_receive_data(s
 				       struct sctp_association *asoc);
 static void sctp_ulpevent_release_data(struct sctp_ulpevent *event);
 
-/* Stub skb destructor.  */
-static void sctp_stub_rfree(struct sk_buff *skb)
-{
-/* WARNING:  This function is just a warning not to use the
- * skb destructor.  If the skb is shared, we may get the destructor
- * callback on some processor that does not own the sock_lock.  This
- * was occuring with PACKET socket applications that were monitoring
- * our skbs.   We can't take the sock_lock, because we can't risk
- * recursing if we do really own the sock lock.  Instead, do all
- * of our rwnd manipulation while we own the sock_lock outright.
- */
-}
-
 /* Initialize an ULP event from an given skb.  */
 SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
 {
@@ -111,15 +98,19 @@ static inline void sctp_ulpevent_set_own
 	 */
 	sctp_association_hold((struct sctp_association *)asoc);
 	skb = sctp_event2skb(event);
-	skb->sk = asoc->base.sk;
 	event->asoc = (struct sctp_association *)asoc;
-	skb->destructor = sctp_stub_rfree;
+	atomic_add(skb->truesize, &event->asoc->rmem_alloc);
+	skb_set_owner_r(skb, asoc->base.sk);
 }
 
 /* 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->asoc);
+	struct sctp_association *asoc = event->asoc;
+	struct sk_buff *skb = sctp_event2skb(event);
+
+	atomic_sub(skb->truesize, &asoc->rmem_alloc);
+	sctp_association_put(asoc);
 }
 
 /* Create and initialize an SCTP_ASSOC_CHANGE event.
@@ -922,7 +913,6 @@ done:
 /* Free a ulpevent that has an owner.  It includes releasing the reference
  * to the owner, updating the rwnd in case of a DATA event and freeing the
  * skb.
- * See comments in sctp_stub_rfree().
  */
 void sctp_ulpevent_free(struct sctp_ulpevent *event)
 {

Reply via email to