patch-2.4.27 linux-2.4.27/net/sctp/ulpqueue.c
Next file: linux-2.4.27/net/wanrouter/wanproc.c
Previous file: linux-2.4.27/net/sctp/ulpevent.c
Back to the patch index
Back to the overall index
- Lines: 230
- Date:
2004-08-07 16:26:07.115447900 -0700
- Orig file:
linux-2.4.26/net/sctp/ulpqueue.c
- Orig date:
2004-04-14 06:05:41.000000000 -0700
diff -urN linux-2.4.26/net/sctp/ulpqueue.c linux-2.4.27/net/sctp/ulpqueue.c
@@ -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
@@ -79,7 +79,7 @@
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
struct sctp_association *asoc)
{
- memset(ulpq, sizeof(struct sctp_ulpq), 0x00);
+ memset(ulpq, 0, sizeof(struct sctp_ulpq));
ulpq->asoc = asoc;
skb_queue_head_init(&ulpq->reasm);
@@ -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? */
@@ -680,6 +680,71 @@
return event;
}
+/* Helper function to gather skbs that have possibly become
+ * ordered by forward tsn skipping their dependencies.
+ */
+static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq)
+{
+ struct sk_buff *pos, *tmp;
+ struct sctp_ulpevent *cevent;
+ struct sctp_ulpevent *event = NULL;
+ struct sctp_stream *in;
+ struct sk_buff_head temp;
+ __u16 csid, cssn;
+
+ 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->stream;
+ cssn = cevent->ssn;
+
+ if (cssn != sctp_ssn_peek(in, csid))
+ break;
+
+ /* Found it, so mark in the ssnmap. */
+ sctp_ssn_next(in, csid);
+
+ __skb_unlink(pos, pos->list);
+ if (!event) {
+ /* Create a temporary list to collect chunks on. */
+ event = sctp_skb2event(pos);
+ skb_queue_head_init(&temp);
+ __skb_queue_tail(&temp, sctp_event2skb(event));
+ } else {
+ /* Attach all gathered skbs to the event. */
+ __skb_queue_tail(sctp_event2skb(event)->list, pos);
+ }
+ }
+
+ /* Send event to the ULP. */
+ if (event)
+ sctp_ulpq_tail_event(ulpq, event);
+}
+
+/* Skip over an SSN. */
+void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn)
+{
+ struct sctp_stream *in;
+
+ /* Note: The stream ID must be verified before this routine. */
+ in = &ulpq->asoc->ssnmap->in;
+
+ /* Is this an old SSN? If so ignore. */
+ if (SSN_lt(ssn, sctp_ssn_peek(in, sid)))
+ return;
+
+ /* Mark that we are no longer expecting this SSN or lower. */
+ sctp_ssn_skip(in, sid, ssn);
+
+ /* Go find any other chunks that were waiting for
+ * ordering and deliver them if needed.
+ */
+ sctp_ulpq_reap_ordered(ulpq);
+ return;
+}
+
/* Renege 'needed' bytes from the ordering queue. */
static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed)
{
@@ -694,7 +759,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 +785,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);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)