diff options
Diffstat (limited to 'net/sctp/ulpqueue.c')
-rw-r--r-- | net/sctp/ulpqueue.c | 43 |
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. */ |
286 | static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, | 286 | static 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 | */ |
408 | static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ulpq) | 408 | static 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. */ |
515 | static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq) | 515 | static 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. */ |
609 | static inline struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq) | 609 | static 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 | */ |
738 | static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, | 738 | static 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. */ |
782 | static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq, | 782 | static 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 | */ |
870 | static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) | 870 | static 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 | */ |