aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/ulpqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/ulpqueue.c')
-rw-r--r--net/sctp/ulpqueue.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index c25caefa3bcb..5061a26c5028 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -1,4 +1,4 @@
1/* SCTP kernel reference Implementation 1/* SCTP kernel implementation
2 * (C) Copyright IBM Corp. 2001, 2004 2 * (C) Copyright IBM Corp. 2001, 2004
3 * Copyright (c) 1999-2000 Cisco, Inc. 3 * Copyright (c) 1999-2000 Cisco, Inc.
4 * Copyright (c) 1999-2001 Motorola, Inc. 4 * Copyright (c) 1999-2001 Motorola, Inc.
@@ -8,13 +8,13 @@
8 * 8 *
9 * This abstraction carries sctp events to the ULP (sockets). 9 * This abstraction carries sctp events to the ULP (sockets).
10 * 10 *
11 * The SCTP reference implementation is free software; 11 * This SCTP implementation is free software;
12 * you can redistribute it and/or modify it under the terms of 12 * you can redistribute it and/or modify it under the terms of
13 * the GNU General Public License as published by 13 * the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option) 14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version. 15 * any later version.
16 * 16 *
17 * The SCTP reference implementation is distributed in the hope that it 17 * This SCTP implementation is distributed in the hope that it
18 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 18 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19 * ************************ 19 * ************************
20 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 20 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -283,7 +283,7 @@ out_free:
283/* 2nd Level Abstractions */ 283/* 2nd Level Abstractions */
284 284
285/* Helper function to store chunks that need to be reassembled. */ 285/* Helper function to store chunks that need to be reassembled. */
286static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, 286static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
287 struct sctp_ulpevent *event) 287 struct sctp_ulpevent *event)
288{ 288{
289 struct sk_buff *pos; 289 struct sk_buff *pos;
@@ -405,7 +405,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
405/* Helper function to check if an incoming chunk has filled up the last 405/* Helper function to check if an incoming chunk has filled up the last
406 * missing fragment in a SCTP datagram and return the corresponding event. 406 * missing fragment in a SCTP datagram and return the corresponding event.
407 */ 407 */
408static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ulpq) 408static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ulpq)
409{ 409{
410 struct sk_buff *pos; 410 struct sk_buff *pos;
411 struct sctp_ulpevent *cevent; 411 struct sctp_ulpevent *cevent;
@@ -512,7 +512,7 @@ found:
512} 512}
513 513
514/* Retrieve the next set of fragments of a partial message. */ 514/* Retrieve the next set of fragments of a partial message. */
515static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq) 515static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
516{ 516{
517 struct sk_buff *pos, *last_frag, *first_frag; 517 struct sk_buff *pos, *last_frag, *first_frag;
518 struct sctp_ulpevent *cevent; 518 struct sctp_ulpevent *cevent;
@@ -606,7 +606,7 @@ static struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
606} 606}
607 607
608/* Retrieve the first part (sequential fragments) for partial delivery. */ 608/* Retrieve the first part (sequential fragments) for partial delivery. */
609static inline struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq) 609static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
610{ 610{
611 struct sk_buff *pos, *last_frag, *first_frag; 611 struct sk_buff *pos, *last_frag, *first_frag;
612 struct sctp_ulpevent *cevent; 612 struct sctp_ulpevent *cevent;
@@ -735,7 +735,7 @@ static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq)
735/* Helper function to gather skbs that have possibly become 735/* Helper function to gather skbs that have possibly become
736 * ordered by an an incoming chunk. 736 * ordered by an an incoming chunk.
737 */ 737 */
738static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, 738static void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
739 struct sctp_ulpevent *event) 739 struct sctp_ulpevent *event)
740{ 740{
741 struct sk_buff_head *event_list; 741 struct sk_buff_head *event_list;
@@ -779,7 +779,7 @@ static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
779} 779}
780 780
781/* Helper function to store chunks needing ordering. */ 781/* Helper function to store chunks needing ordering. */
782static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq, 782static void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
783 struct sctp_ulpevent *event) 783 struct sctp_ulpevent *event)
784{ 784{
785 struct sk_buff *pos; 785 struct sk_buff *pos;
@@ -867,13 +867,14 @@ static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
867/* Helper function to gather skbs that have possibly become 867/* Helper function to gather skbs that have possibly become
868 * ordered by forward tsn skipping their dependencies. 868 * ordered by forward tsn skipping their dependencies.
869 */ 869 */
870static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) 870static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
871{ 871{
872 struct sk_buff *pos, *tmp; 872 struct sk_buff *pos, *tmp;
873 struct sctp_ulpevent *cevent; 873 struct sctp_ulpevent *cevent;
874 struct sctp_ulpevent *event; 874 struct sctp_ulpevent *event;
875 struct sctp_stream *in; 875 struct sctp_stream *in;
876 struct sk_buff_head temp; 876 struct sk_buff_head temp;
877 struct sk_buff_head *lobby = &ulpq->lobby;
877 __u16 csid, cssn; 878 __u16 csid, cssn;
878 879
879 in = &ulpq->asoc->ssnmap->in; 880 in = &ulpq->asoc->ssnmap->in;
@@ -881,7 +882,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
881 /* We are holding the chunks by stream, by SSN. */ 882 /* We are holding the chunks by stream, by SSN. */
882 skb_queue_head_init(&temp); 883 skb_queue_head_init(&temp);
883 event = NULL; 884 event = NULL;
884 sctp_skb_for_each(pos, &ulpq->lobby, tmp) { 885 sctp_skb_for_each(pos, lobby, tmp) {
885 cevent = (struct sctp_ulpevent *) pos->cb; 886 cevent = (struct sctp_ulpevent *) pos->cb;
886 csid = cevent->stream; 887 csid = cevent->stream;
887 cssn = cevent->ssn; 888 cssn = cevent->ssn;
@@ -895,10 +896,10 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
895 continue; 896 continue;
896 897
897 /* see if this ssn has been marked by skipping */ 898 /* see if this ssn has been marked by skipping */
898 if (!SSN_lte(cssn, sctp_ssn_peek(in, csid))) 899 if (!SSN_lt(cssn, sctp_ssn_peek(in, csid)))
899 break; 900 break;
900 901
901 __skb_unlink(pos, &ulpq->lobby); 902 __skb_unlink(pos, lobby);
902 if (!event) 903 if (!event)
903 /* Create a temporary list to collect chunks on. */ 904 /* Create a temporary list to collect chunks on. */
904 event = sctp_skb2event(pos); 905 event = sctp_skb2event(pos);
@@ -907,6 +908,22 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
907 __skb_queue_tail(&temp, pos); 908 __skb_queue_tail(&temp, pos);
908 } 909 }
909 910
911 /* If we didn't reap any data, see if the next expected SSN
912 * is next on the queue and if so, use that.
913 */
914 if (event == NULL && pos != (struct sk_buff *)lobby) {
915 cevent = (struct sctp_ulpevent *) pos->cb;
916 csid = cevent->stream;
917 cssn = cevent->ssn;
918
919 if (csid == sid && cssn == sctp_ssn_peek(in, csid)) {
920 sctp_ssn_next(in, csid);
921 __skb_unlink(pos, lobby);
922 __skb_queue_tail(&temp, pos);
923 event = sctp_skb2event(pos);
924 }
925 }
926
910 /* Send event to the ULP. 'event' is the sctp_ulpevent for 927 /* Send event to the ULP. 'event' is the sctp_ulpevent for
911 * very first SKB on the 'temp' list. 928 * very first SKB on the 'temp' list.
912 */ 929 */