summaryrefslogtreecommitdiff
path: root/net/sctp/ulpqueue.c
diff options
context:
space:
mode:
authorJon Grimm <jgrimm@touki.austin.ibm.com>2003-04-10 00:55:29 -0500
committerSridhar Samudrala <sri@us.ibm.com>2003-04-10 00:55:29 -0500
commit293f0d65e085ee73ef91c2c5ad67f765fc06ed38 (patch)
tree37faf6c425199a483b6a2d3d74b340a97f280e9d /net/sctp/ulpqueue.c
parent276829d1f507167bdfd474de2c870bd94b47cd5f (diff)
[SCTP] short-circuit reassembly & ordering for best case.
Short circuit normal case. First check if the chunk belongs at the end of the queue. If so, don't bother walking the entire list, just just put at end.
Diffstat (limited to 'net/sctp/ulpqueue.c')
-rw-r--r--net/sctp/ulpqueue.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 4cc69b211c84..ae5cd8fc3b27 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -253,6 +253,21 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
tsn = event->sndrcvinfo.sinfo_tsn;
+ /* See if it belongs at the end. */
+ pos = skb_peek_tail(&ulpq->reasm);
+ if (!pos) {
+ __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
+ return;
+ }
+
+ /* Short circuit just dropping it at the end. */
+ cevent = sctp_skb2event(pos);
+ ctsn = cevent->sndrcvinfo.sinfo_tsn;
+ if (TSN_lt(ctsn, tsn)) {
+ __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
+ return;
+ }
+
/* Find the right place in this list. We store them by TSN. */
skb_queue_walk(&ulpq->reasm, pos) {
cevent = sctp_skb2event(pos);
@@ -262,12 +277,9 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
break;
}
- /* If the queue is empty, we have a different function to call. */
- if (skb_peek(&ulpq->reasm))
- __skb_insert(sctp_event2skb(event), pos->prev, pos,
- &ulpq->reasm);
- else
- __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
+ /* Insert before pos. */
+ __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->reasm);
+
}
/* Helper function to return an event corresponding to the reassembled
@@ -592,8 +604,27 @@ static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
__u16 sid, csid;
__u16 ssn, cssn;
+ pos = skb_peek_tail(&ulpq->lobby);
+ if (!pos) {
+ __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
+ return;
+ }
+
sid = event->sndrcvinfo.sinfo_stream;
ssn = event->sndrcvinfo.sinfo_ssn;
+
+ cevent = (struct sctp_ulpevent *) pos->cb;
+ csid = cevent->sndrcvinfo.sinfo_stream;
+ cssn = cevent->sndrcvinfo.sinfo_ssn;
+ if (sid > csid) {
+ __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
+ return;
+ }
+
+ if ((sid == csid) && SSN_lt(cssn, ssn)) {
+ __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
+ return;
+ }
/* Find the right place in this list. We store them by
* stream ID and then by SSN.
@@ -609,12 +640,10 @@ static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
break;
}
- /* If the queue is empty, we have a different function to call. */
- if (skb_peek(&ulpq->lobby))
- __skb_insert(sctp_event2skb(event), pos->prev, pos,
- &ulpq->lobby);
- else
- __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
+
+ /* Insert before pos. */
+ __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->lobby);
+
}
static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,