1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#include <linux/slab.h>
45#include <linux/types.h>
46#include <linux/skbuff.h>
47#include <net/sock.h>
48#include <net/sctp/structs.h>
49#include <net/sctp/sctp.h>
50#include <net/sctp/sm.h>
51
52
53static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
54 struct sctp_ulpevent *);
55static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *,
56 struct sctp_ulpevent *);
57static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq);
58
59
60
61
62struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
63 struct sctp_association *asoc)
64{
65 memset(ulpq, 0, sizeof(struct sctp_ulpq));
66
67 ulpq->asoc = asoc;
68 skb_queue_head_init(&ulpq->reasm);
69 skb_queue_head_init(&ulpq->lobby);
70 ulpq->pd_mode = 0;
71 ulpq->malloced = 0;
72
73 return ulpq;
74}
75
76
77
78void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
79{
80 struct sk_buff *skb;
81 struct sctp_ulpevent *event;
82
83 while ((skb = __skb_dequeue(&ulpq->lobby)) != NULL) {
84 event = sctp_skb2event(skb);
85 sctp_ulpevent_free(event);
86 }
87
88 while ((skb = __skb_dequeue(&ulpq->reasm)) != NULL) {
89 event = sctp_skb2event(skb);
90 sctp_ulpevent_free(event);
91 }
92
93}
94
95
96void sctp_ulpq_free(struct sctp_ulpq *ulpq)
97{
98 sctp_ulpq_flush(ulpq);
99 if (ulpq->malloced)
100 kfree(ulpq);
101}
102
103
104int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
105 gfp_t gfp)
106{
107 struct sk_buff_head temp;
108 struct sctp_ulpevent *event;
109
110
111 event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp);
112 if (!event)
113 return -ENOMEM;
114
115
116 event = sctp_ulpq_reasm(ulpq, event);
117
118
119 if ((event) && (event->msg_flags & MSG_EOR)){
120
121 skb_queue_head_init(&temp);
122 __skb_queue_tail(&temp, sctp_event2skb(event));
123
124 event = sctp_ulpq_order(ulpq, event);
125 }
126
127
128
129
130 if (event)
131 sctp_ulpq_tail_event(ulpq, event);
132
133 return 0;
134}
135
136
137
138
139
140int sctp_clear_pd(struct sock *sk, struct sctp_association *asoc)
141{
142 struct sctp_sock *sp = sctp_sk(sk);
143
144 if (atomic_dec_and_test(&sp->pd_mode)) {
145
146
147
148 if (!skb_queue_empty(&sp->pd_lobby)) {
149 struct list_head *list;
150 sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue);
151 list = (struct list_head *)&sctp_sk(sk)->pd_lobby;
152 INIT_LIST_HEAD(list);
153 return 1;
154 }
155 } else {
156
157
158
159
160
161 if (!skb_queue_empty(&sp->pd_lobby) && asoc) {
162 struct sk_buff *skb, *tmp;
163 struct sctp_ulpevent *event;
164
165 sctp_skb_for_each(skb, &sp->pd_lobby, tmp) {
166 event = sctp_skb2event(skb);
167 if (event->asoc == asoc) {
168 __skb_unlink(skb, &sp->pd_lobby);
169 __skb_queue_tail(&sk->sk_receive_queue,
170 skb);
171 }
172 }
173 }
174 }
175
176 return 0;
177}
178
179
180static void sctp_ulpq_set_pd(struct sctp_ulpq *ulpq)
181{
182 struct sctp_sock *sp = sctp_sk(ulpq->asoc->base.sk);
183
184 atomic_inc(&sp->pd_mode);
185 ulpq->pd_mode = 1;
186}
187
188
189static int sctp_ulpq_clear_pd(struct sctp_ulpq *ulpq)
190{
191 ulpq->pd_mode = 0;
192 sctp_ulpq_reasm_drain(ulpq);
193 return sctp_clear_pd(ulpq->asoc->base.sk, ulpq->asoc);
194}
195
196
197
198
199int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
200{
201 struct sock *sk = ulpq->asoc->base.sk;
202 struct sk_buff_head *queue, *skb_list;
203 struct sk_buff *skb = sctp_event2skb(event);
204 int clear_pd = 0;
205
206 skb_list = (struct sk_buff_head *) skb->prev;
207
208
209
210
211 if (sock_flag(sk, SOCK_DEAD) || (sk->sk_shutdown & RCV_SHUTDOWN))
212 goto out_free;
213
214
215 if (!sctp_ulpevent_is_enabled(event, &sctp_sk(sk)->subscribe))
216 goto out_free;
217
218
219
220
221
222
223 if (atomic_read(&sctp_sk(sk)->pd_mode) == 0) {
224 queue = &sk->sk_receive_queue;
225 } else {
226 if (ulpq->pd_mode) {
227
228
229
230
231
232 if ((event->msg_flags & MSG_NOTIFICATION) ||
233 (SCTP_DATA_NOT_FRAG ==
234 (event->msg_flags & SCTP_DATA_FRAG_MASK)))
235 queue = &sctp_sk(sk)->pd_lobby;
236 else {
237 clear_pd = event->msg_flags & MSG_EOR;
238 queue = &sk->sk_receive_queue;
239 }
240 } else {
241
242
243
244
245
246 if (sctp_sk(sk)->frag_interleave)
247 queue = &sk->sk_receive_queue;
248 else
249 queue = &sctp_sk(sk)->pd_lobby;
250 }
251 }
252
253
254
255
256 if (skb_list)
257 sctp_skb_list_tail(skb_list, queue);
258 else
259 __skb_queue_tail(queue, skb);
260
261
262
263
264
265 if (clear_pd)
266 sctp_ulpq_clear_pd(ulpq);
267
268 if (queue == &sk->sk_receive_queue)
269 sk->sk_data_ready(sk, 0);
270 return 1;
271
272out_free:
273 if (skb_list)
274 sctp_queue_purge_ulpevents(skb_list);
275 else
276 sctp_ulpevent_free(event);
277
278 return 0;
279}
280
281
282
283
284static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
285 struct sctp_ulpevent *event)
286{
287 struct sk_buff *pos;
288 struct sctp_ulpevent *cevent;
289 __u32 tsn, ctsn;
290
291 tsn = event->tsn;
292
293
294 pos = skb_peek_tail(&ulpq->reasm);
295 if (!pos) {
296 __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
297 return;
298 }
299
300
301 cevent = sctp_skb2event(pos);
302 ctsn = cevent->tsn;
303 if (TSN_lt(ctsn, tsn)) {
304 __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
305 return;
306 }
307
308
309 skb_queue_walk(&ulpq->reasm, pos) {
310 cevent = sctp_skb2event(pos);
311 ctsn = cevent->tsn;
312
313 if (TSN_lt(tsn, ctsn))
314 break;
315 }
316
317
318 __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event));
319
320}
321
322
323
324
325
326
327
328
329static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
330{
331 struct sk_buff *pos;
332 struct sk_buff *new = NULL;
333 struct sctp_ulpevent *event;
334 struct sk_buff *pnext, *last;
335 struct sk_buff *list = skb_shinfo(f_frag)->frag_list;
336
337
338 if (f_frag == l_frag)
339 pos = NULL;
340 else
341 pos = f_frag->next;
342
343
344 for (last = list; list; last = list, list = list->next);
345
346
347
348
349 if (last)
350 last->next = pos;
351 else {
352 if (skb_cloned(f_frag)) {
353
354
355
356
357
358 new = skb_copy(f_frag, GFP_ATOMIC);
359 if (!new)
360 return NULL;
361
362 sctp_skb_set_owner_r(new, f_frag->sk);
363
364 skb_shinfo(new)->frag_list = pos;
365 } else
366 skb_shinfo(f_frag)->frag_list = pos;
367 }
368
369
370 __skb_unlink(f_frag, queue);
371
372
373 if (new) {
374 kfree_skb(f_frag);
375 f_frag = new;
376 }
377
378 while (pos) {
379
380 pnext = pos->next;
381
382
383 f_frag->len += pos->len;
384 f_frag->data_len += pos->len;
385
386
387 __skb_unlink(pos, queue);
388
389
390 if (pos == l_frag)
391 break;
392 pos->next = pnext;
393 pos = pnext;
394 }
395
396 event = sctp_skb2event(f_frag);
397 SCTP_INC_STATS(SCTP_MIB_REASMUSRMSGS);
398
399 return event;
400}
401
402
403
404
405
406static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ulpq)
407{
408 struct sk_buff *pos;
409 struct sctp_ulpevent *cevent;
410 struct sk_buff *first_frag = NULL;
411 __u32 ctsn, next_tsn;
412 struct sctp_ulpevent *retval = NULL;
413 struct sk_buff *pd_first = NULL;
414 struct sk_buff *pd_last = NULL;
415 size_t pd_len = 0;
416 struct sctp_association *asoc;
417 u32 pd_point;
418
419
420
421
422
423 next_tsn = 0;
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 skb_queue_walk(&ulpq->reasm, pos) {
439 cevent = sctp_skb2event(pos);
440 ctsn = cevent->tsn;
441
442 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
443 case SCTP_DATA_FIRST_FRAG:
444
445
446
447
448 if (pos == ulpq->reasm.next) {
449 pd_first = pos;
450 pd_last = pos;
451 pd_len = pos->len;
452 } else {
453 pd_first = NULL;
454 pd_last = NULL;
455 pd_len = 0;
456 }
457
458 first_frag = pos;
459 next_tsn = ctsn + 1;
460 break;
461
462 case SCTP_DATA_MIDDLE_FRAG:
463 if ((first_frag) && (ctsn == next_tsn)) {
464 next_tsn++;
465 if (pd_first) {
466 pd_last = pos;
467 pd_len += pos->len;
468 }
469 } else
470 first_frag = NULL;
471 break;
472
473 case SCTP_DATA_LAST_FRAG:
474 if (first_frag && (ctsn == next_tsn))
475 goto found;
476 else
477 first_frag = NULL;
478 break;
479 }
480 }
481
482 asoc = ulpq->asoc;
483 if (pd_first) {
484
485
486
487
488
489 if (!sctp_sk(asoc->base.sk)->frag_interleave &&
490 atomic_read(&sctp_sk(asoc->base.sk)->pd_mode))
491 goto done;
492
493 cevent = sctp_skb2event(pd_first);
494 pd_point = sctp_sk(asoc->base.sk)->pd_point;
495 if (pd_point && pd_point <= pd_len) {
496 retval = sctp_make_reassembled_event(&ulpq->reasm,
497 pd_first,
498 pd_last);
499 if (retval)
500 sctp_ulpq_set_pd(ulpq);
501 }
502 }
503done:
504 return retval;
505found:
506 retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos);
507 if (retval)
508 retval->msg_flags |= MSG_EOR;
509 goto done;
510}
511
512
513static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
514{
515 struct sk_buff *pos, *last_frag, *first_frag;
516 struct sctp_ulpevent *cevent;
517 __u32 ctsn, next_tsn;
518 int is_last;
519 struct sctp_ulpevent *retval;
520
521
522
523
524
525
526 if (skb_queue_empty(&ulpq->reasm))
527 return NULL;
528
529 last_frag = first_frag = NULL;
530 retval = NULL;
531 next_tsn = 0;
532 is_last = 0;
533
534 skb_queue_walk(&ulpq->reasm, pos) {
535 cevent = sctp_skb2event(pos);
536 ctsn = cevent->tsn;
537
538 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
539 case SCTP_DATA_MIDDLE_FRAG:
540 if (!first_frag) {
541 first_frag = pos;
542 next_tsn = ctsn + 1;
543 last_frag = pos;
544 } else if (next_tsn == ctsn)
545 next_tsn++;
546 else
547 goto done;
548 break;
549 case SCTP_DATA_LAST_FRAG:
550 if (!first_frag)
551 first_frag = pos;
552 else if (ctsn != next_tsn)
553 goto done;
554 last_frag = pos;
555 is_last = 1;
556 goto done;
557 default:
558 return NULL;
559 }
560 }
561
562
563
564
565done:
566 retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
567 if (retval && is_last)
568 retval->msg_flags |= MSG_EOR;
569
570 return retval;
571}
572
573
574
575
576
577static struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
578 struct sctp_ulpevent *event)
579{
580 struct sctp_ulpevent *retval = NULL;
581
582
583 if (SCTP_DATA_NOT_FRAG == (event->msg_flags & SCTP_DATA_FRAG_MASK)) {
584 event->msg_flags |= MSG_EOR;
585 return event;
586 }
587
588 sctp_ulpq_store_reasm(ulpq, event);
589 if (!ulpq->pd_mode)
590 retval = sctp_ulpq_retrieve_reassembled(ulpq);
591 else {
592 __u32 ctsn, ctsnap;
593
594
595
596
597 ctsn = event->tsn;
598 ctsnap = sctp_tsnmap_get_ctsn(&ulpq->asoc->peer.tsn_map);
599 if (TSN_lte(ctsn, ctsnap))
600 retval = sctp_ulpq_retrieve_partial(ulpq);
601 }
602
603 return retval;
604}
605
606
607static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
608{
609 struct sk_buff *pos, *last_frag, *first_frag;
610 struct sctp_ulpevent *cevent;
611 __u32 ctsn, next_tsn;
612 struct sctp_ulpevent *retval;
613
614
615
616
617
618
619 if (skb_queue_empty(&ulpq->reasm))
620 return NULL;
621
622 last_frag = first_frag = NULL;
623 retval = NULL;
624 next_tsn = 0;
625
626 skb_queue_walk(&ulpq->reasm, pos) {
627 cevent = sctp_skb2event(pos);
628 ctsn = cevent->tsn;
629
630 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
631 case SCTP_DATA_FIRST_FRAG:
632 if (!first_frag) {
633 first_frag = pos;
634 next_tsn = ctsn + 1;
635 last_frag = pos;
636 } else
637 goto done;
638 break;
639
640 case SCTP_DATA_MIDDLE_FRAG:
641 if (!first_frag)
642 return NULL;
643 if (ctsn == next_tsn) {
644 next_tsn++;
645 last_frag = pos;
646 } else
647 goto done;
648 break;
649 default:
650 return NULL;
651 }
652 }
653
654
655
656
657done:
658 retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag);
659 return retval;
660}
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676void sctp_ulpq_reasm_flushtsn(struct sctp_ulpq *ulpq, __u32 fwd_tsn)
677{
678 struct sk_buff *pos, *tmp;
679 struct sctp_ulpevent *event;
680 __u32 tsn;
681
682 if (skb_queue_empty(&ulpq->reasm))
683 return;
684
685 skb_queue_walk_safe(&ulpq->reasm, pos, tmp) {
686 event = sctp_skb2event(pos);
687 tsn = event->tsn;
688
689
690
691
692
693
694 if (TSN_lte(tsn, fwd_tsn)) {
695 __skb_unlink(pos, &ulpq->reasm);
696 sctp_ulpevent_free(event);
697 } else
698 break;
699 }
700}
701
702
703
704
705
706
707static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq)
708{
709 struct sctp_ulpevent *event = NULL;
710 struct sk_buff_head temp;
711
712 if (skb_queue_empty(&ulpq->reasm))
713 return;
714
715 while ((event = sctp_ulpq_retrieve_reassembled(ulpq)) != NULL) {
716
717 if ((event) && (event->msg_flags & MSG_EOR)){
718 skb_queue_head_init(&temp);
719 __skb_queue_tail(&temp, sctp_event2skb(event));
720
721 event = sctp_ulpq_order(ulpq, event);
722 }
723
724
725
726
727 if (event)
728 sctp_ulpq_tail_event(ulpq, event);
729 }
730}
731
732
733
734
735
736static void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
737 struct sctp_ulpevent *event)
738{
739 struct sk_buff_head *event_list;
740 struct sk_buff *pos, *tmp;
741 struct sctp_ulpevent *cevent;
742 struct sctp_stream *in;
743 __u16 sid, csid, cssn;
744
745 sid = event->stream;
746 in = &ulpq->asoc->ssnmap->in;
747
748 event_list = (struct sk_buff_head *) sctp_event2skb(event)->prev;
749
750
751 sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
752 cevent = (struct sctp_ulpevent *) pos->cb;
753 csid = cevent->stream;
754 cssn = cevent->ssn;
755
756
757 if (csid > sid)
758 break;
759
760
761 if (csid < sid)
762 continue;
763
764 if (cssn != sctp_ssn_peek(in, sid))
765 break;
766
767
768 sctp_ssn_next(in, sid);
769
770 __skb_unlink(pos, &ulpq->lobby);
771
772
773 __skb_queue_tail(event_list, pos);
774 }
775}
776
777
778static void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
779 struct sctp_ulpevent *event)
780{
781 struct sk_buff *pos;
782 struct sctp_ulpevent *cevent;
783 __u16 sid, csid;
784 __u16 ssn, cssn;
785
786 pos = skb_peek_tail(&ulpq->lobby);
787 if (!pos) {
788 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
789 return;
790 }
791
792 sid = event->stream;
793 ssn = event->ssn;
794
795 cevent = (struct sctp_ulpevent *) pos->cb;
796 csid = cevent->stream;
797 cssn = cevent->ssn;
798 if (sid > csid) {
799 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
800 return;
801 }
802
803 if ((sid == csid) && SSN_lt(cssn, ssn)) {
804 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
805 return;
806 }
807
808
809
810
811 skb_queue_walk(&ulpq->lobby, pos) {
812 cevent = (struct sctp_ulpevent *) pos->cb;
813 csid = cevent->stream;
814 cssn = cevent->ssn;
815
816 if (csid > sid)
817 break;
818 if (csid == sid && SSN_lt(ssn, cssn))
819 break;
820 }
821
822
823
824 __skb_queue_before(&ulpq->lobby, pos, sctp_event2skb(event));
825}
826
827static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
828 struct sctp_ulpevent *event)
829{
830 __u16 sid, ssn;
831 struct sctp_stream *in;
832
833
834 if (SCTP_DATA_UNORDERED & event->msg_flags)
835 return event;
836
837
838 sid = event->stream;
839 ssn = event->ssn;
840 in = &ulpq->asoc->ssnmap->in;
841
842
843 if (ssn != sctp_ssn_peek(in, sid)) {
844
845
846
847 sctp_ulpq_store_ordered(ulpq, event);
848 return NULL;
849 }
850
851
852 sctp_ssn_next(in, sid);
853
854
855
856
857 sctp_ulpq_retrieve_ordered(ulpq, event);
858
859 return event;
860}
861
862
863
864
865static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
866{
867 struct sk_buff *pos, *tmp;
868 struct sctp_ulpevent *cevent;
869 struct sctp_ulpevent *event;
870 struct sctp_stream *in;
871 struct sk_buff_head temp;
872 struct sk_buff_head *lobby = &ulpq->lobby;
873 __u16 csid, cssn;
874
875 in = &ulpq->asoc->ssnmap->in;
876
877
878 skb_queue_head_init(&temp);
879 event = NULL;
880 sctp_skb_for_each(pos, lobby, tmp) {
881 cevent = (struct sctp_ulpevent *) pos->cb;
882 csid = cevent->stream;
883 cssn = cevent->ssn;
884
885
886 if (csid > sid)
887 break;
888
889
890 if (csid < sid)
891 continue;
892
893
894 if (!SSN_lt(cssn, sctp_ssn_peek(in, csid)))
895 break;
896
897 __skb_unlink(pos, lobby);
898 if (!event)
899
900 event = sctp_skb2event(pos);
901
902
903 __skb_queue_tail(&temp, pos);
904 }
905
906
907
908
909 if (event == NULL && pos != (struct sk_buff *)lobby) {
910 cevent = (struct sctp_ulpevent *) pos->cb;
911 csid = cevent->stream;
912 cssn = cevent->ssn;
913
914 if (csid == sid && cssn == sctp_ssn_peek(in, csid)) {
915 sctp_ssn_next(in, csid);
916 __skb_unlink(pos, lobby);
917 __skb_queue_tail(&temp, pos);
918 event = sctp_skb2event(pos);
919 }
920 }
921
922
923
924
925 if (event) {
926
927 sctp_ulpq_retrieve_ordered(ulpq, event);
928 sctp_ulpq_tail_event(ulpq, event);
929 }
930}
931
932
933
934
935void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn)
936{
937 struct sctp_stream *in;
938
939
940 in = &ulpq->asoc->ssnmap->in;
941
942
943 if (SSN_lt(ssn, sctp_ssn_peek(in, sid)))
944 return;
945
946
947 sctp_ssn_skip(in, sid, ssn);
948
949
950
951
952 sctp_ulpq_reap_ordered(ulpq, sid);
953}
954
955static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq,
956 struct sk_buff_head *list, __u16 needed)
957{
958 __u16 freed = 0;
959 __u32 tsn;
960 struct sk_buff *skb;
961 struct sctp_ulpevent *event;
962 struct sctp_tsnmap *tsnmap;
963
964 tsnmap = &ulpq->asoc->peer.tsn_map;
965
966 while ((skb = __skb_dequeue_tail(list)) != NULL) {
967 freed += skb_headlen(skb);
968 event = sctp_skb2event(skb);
969 tsn = event->tsn;
970
971 sctp_ulpevent_free(event);
972 sctp_tsnmap_renege(tsnmap, tsn);
973 if (freed >= needed)
974 return freed;
975 }
976
977 return freed;
978}
979
980
981static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed)
982{
983 return sctp_ulpq_renege_list(ulpq, &ulpq->lobby, needed);
984}
985
986
987static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed)
988{
989 return sctp_ulpq_renege_list(ulpq, &ulpq->reasm, needed);
990}
991
992
993void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
994 struct sctp_chunk *chunk,
995 gfp_t gfp)
996{
997 struct sctp_ulpevent *event;
998 struct sctp_association *asoc;
999 struct sctp_sock *sp;
1000
1001 asoc = ulpq->asoc;
1002 sp = sctp_sk(asoc->base.sk);
1003
1004
1005
1006
1007 if (ulpq->pd_mode)
1008 return;
1009
1010
1011
1012
1013
1014
1015 if (sp->frag_interleave || atomic_read(&sp->pd_mode) == 0) {
1016
1017 event = sctp_ulpq_retrieve_first(ulpq);
1018
1019 if (event) {
1020 sctp_ulpq_tail_event(ulpq, event);
1021 sctp_ulpq_set_pd(ulpq);
1022 return;
1023 }
1024 }
1025}
1026
1027
1028void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
1029 gfp_t gfp)
1030{
1031 struct sctp_association *asoc;
1032 __u16 needed, freed;
1033
1034 asoc = ulpq->asoc;
1035
1036 if (chunk) {
1037 needed = ntohs(chunk->chunk_hdr->length);
1038 needed -= sizeof(sctp_data_chunk_t);
1039 } else
1040 needed = SCTP_DEFAULT_MAXWINDOW;
1041
1042 freed = 0;
1043
1044 if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) {
1045 freed = sctp_ulpq_renege_order(ulpq, needed);
1046 if (freed < needed) {
1047 freed += sctp_ulpq_renege_frags(ulpq, needed - freed);
1048 }
1049 }
1050
1051 if (chunk && (freed >= needed)) {
1052 __u32 tsn;
1053 tsn = ntohl(chunk->subh.data_hdr->tsn);
1054 sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn);
1055 sctp_ulpq_tail_data(ulpq, chunk, gfp);
1056
1057 sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
1058 }
1059
1060 sk_mem_reclaim(asoc->base.sk);
1061}
1062
1063
1064
1065
1066
1067
1068void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp)
1069{
1070 struct sctp_ulpevent *ev = NULL;
1071 struct sock *sk;
1072
1073 if (!ulpq->pd_mode)
1074 return;
1075
1076 sk = ulpq->asoc->base.sk;
1077 if (sctp_ulpevent_type_enabled(SCTP_PARTIAL_DELIVERY_EVENT,
1078 &sctp_sk(sk)->subscribe))
1079 ev = sctp_ulpevent_make_pdapi(ulpq->asoc,
1080 SCTP_PARTIAL_DELIVERY_ABORTED,
1081 gfp);
1082 if (ev)
1083 __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev));
1084
1085
1086 if (sctp_ulpq_clear_pd(ulpq) || ev)
1087 sk->sk_data_ready(sk, 0);
1088}
1089