| From: |
| Sridhar Samudrala <sri@us.ibm.com> |
| To: |
| davem@redhat.com |
| Subject: |
| [BK PATCH] 2.6 SCTP updates. |
| Date: |
| Tue, 6 Apr 2004 10:28:36 -0700 (PDT) |
| Cc: |
| netdev@oss.sgi.com, lksctp-developers@lists.sourceforge.net |
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);