diff options
-rw-r--r-- | net/sctp/ulpqueue.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index d300f4973a79..5061a26c5028 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -874,6 +874,7 @@ static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) | |||
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 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 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 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 | */ |