sctp: implement report_ftsn for sctp_stream_interleave
[linux-2.6-block.git] / net / sctp / stream_interleave.c
CommitLineData
0c3f6f65
XL
1/* SCTP kernel implementation
2 * (C) Copyright Red Hat Inc. 2017
3 *
4 * This file is part of the SCTP kernel implementation
5 *
6 * These functions manipulate sctp stream queue/scheduling.
7 *
8 * This SCTP implementation is free software;
9 * you can redistribute it and/or modify it under the terms of
10 * the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This SCTP implementation is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * ************************
17 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 * See the GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with GNU CC; see the file COPYING. If not, see
22 * <http://www.gnu.org/licenses/>.
23 *
24 * Please send any bug reports or fixes you make to the
25 * email addresched(es):
26 * lksctp developers <linux-sctp@vger.kernel.org>
27 *
28 * Written or modified by:
29 * Xin Long <lucien.xin@gmail.com>
30 */
31
bd4d627d 32#include <net/busy_poll.h>
0c3f6f65
XL
33#include <net/sctp/sctp.h>
34#include <net/sctp/sm.h>
bd4d627d 35#include <net/sctp/ulpevent.h>
0c3f6f65
XL
36#include <linux/sctp.h>
37
38static struct sctp_chunk *sctp_make_idatafrag_empty(
39 const struct sctp_association *asoc,
40 const struct sctp_sndrcvinfo *sinfo,
41 int len, __u8 flags, gfp_t gfp)
42{
43 struct sctp_chunk *retval;
44 struct sctp_idatahdr dp;
45
46 memset(&dp, 0, sizeof(dp));
47 dp.stream = htons(sinfo->sinfo_stream);
48
49 if (sinfo->sinfo_flags & SCTP_UNORDERED)
50 flags |= SCTP_DATA_UNORDERED;
51
52 retval = sctp_make_idata(asoc, flags, sizeof(dp) + len, gfp);
53 if (!retval)
54 return NULL;
55
56 retval->subh.idata_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
57 memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
58
59 return retval;
60}
61
668c9beb
XL
62static void sctp_chunk_assign_mid(struct sctp_chunk *chunk)
63{
64 struct sctp_stream *stream;
65 struct sctp_chunk *lchunk;
66 __u32 cfsn = 0;
67 __u16 sid;
68
69 if (chunk->has_mid)
70 return;
71
72 sid = sctp_chunk_stream_no(chunk);
73 stream = &chunk->asoc->stream;
74
75 list_for_each_entry(lchunk, &chunk->msg->chunks, frag_list) {
76 struct sctp_idatahdr *hdr;
13228238 77 __u32 mid;
668c9beb
XL
78
79 lchunk->has_mid = 1;
80
668c9beb
XL
81 hdr = lchunk->subh.idata_hdr;
82
83 if (lchunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG)
84 hdr->ppid = lchunk->sinfo.sinfo_ppid;
85 else
86 hdr->fsn = htonl(cfsn++);
87
13228238
XL
88 if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
89 mid = lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG ?
90 sctp_mid_uo_next(stream, out, sid) :
91 sctp_mid_uo_peek(stream, out, sid);
92 } else {
93 mid = lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG ?
94 sctp_mid_next(stream, out, sid) :
95 sctp_mid_peek(stream, out, sid);
96 }
97 hdr->mid = htonl(mid);
668c9beb
XL
98 }
99}
100
9d4ceaf1
XL
101static bool sctp_validate_data(struct sctp_chunk *chunk)
102{
103 const struct sctp_stream *stream;
104 __u16 sid, ssn;
105
106 if (chunk->chunk_hdr->type != SCTP_CID_DATA)
107 return false;
108
109 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
110 return true;
111
112 stream = &chunk->asoc->stream;
113 sid = sctp_chunk_stream_no(chunk);
114 ssn = ntohs(chunk->subh.data_hdr->ssn);
115
116 return !SSN_lt(ssn, sctp_ssn_peek(stream, in, sid));
117}
118
119static bool sctp_validate_idata(struct sctp_chunk *chunk)
120{
121 struct sctp_stream *stream;
122 __u32 mid;
123 __u16 sid;
124
125 if (chunk->chunk_hdr->type != SCTP_CID_I_DATA)
126 return false;
127
128 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
129 return true;
130
131 stream = &chunk->asoc->stream;
132 sid = sctp_chunk_stream_no(chunk);
133 mid = ntohl(chunk->subh.idata_hdr->mid);
134
135 return !MID_lt(mid, sctp_mid_peek(stream, in, sid));
136}
137
bd4d627d
XL
138static void sctp_intl_store_reasm(struct sctp_ulpq *ulpq,
139 struct sctp_ulpevent *event)
140{
141 struct sctp_ulpevent *cevent;
142 struct sk_buff *pos;
143
144 pos = skb_peek_tail(&ulpq->reasm);
145 if (!pos) {
146 __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
147 return;
148 }
149
150 cevent = sctp_skb2event(pos);
151
152 if (event->stream == cevent->stream &&
153 event->mid == cevent->mid &&
154 (cevent->msg_flags & SCTP_DATA_FIRST_FRAG ||
155 (!(event->msg_flags & SCTP_DATA_FIRST_FRAG) &&
156 event->fsn > cevent->fsn))) {
157 __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
158 return;
159 }
160
161 if ((event->stream == cevent->stream &&
162 MID_lt(cevent->mid, event->mid)) ||
163 event->stream > cevent->stream) {
164 __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
165 return;
166 }
167
168 skb_queue_walk(&ulpq->reasm, pos) {
169 cevent = sctp_skb2event(pos);
170
171 if (event->stream < cevent->stream ||
172 (event->stream == cevent->stream &&
173 MID_lt(event->mid, cevent->mid)))
174 break;
175
176 if (event->stream == cevent->stream &&
177 event->mid == cevent->mid &&
178 !(cevent->msg_flags & SCTP_DATA_FIRST_FRAG) &&
179 (event->msg_flags & SCTP_DATA_FIRST_FRAG ||
180 event->fsn < cevent->fsn))
181 break;
182 }
183
184 __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event));
185}
186
187static struct sctp_ulpevent *sctp_intl_retrieve_partial(
188 struct sctp_ulpq *ulpq,
189 struct sctp_ulpevent *event)
190{
191 struct sk_buff *first_frag = NULL;
192 struct sk_buff *last_frag = NULL;
193 struct sctp_ulpevent *retval;
194 struct sctp_stream_in *sin;
195 struct sk_buff *pos;
196 __u32 next_fsn = 0;
197 int is_last = 0;
198
199 sin = sctp_stream_in(ulpq->asoc, event->stream);
200
201 skb_queue_walk(&ulpq->reasm, pos) {
202 struct sctp_ulpevent *cevent = sctp_skb2event(pos);
203
204 if (cevent->stream < event->stream)
205 continue;
206
207 if (cevent->stream > event->stream ||
208 cevent->mid != sin->mid)
209 break;
210
211 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
212 case SCTP_DATA_FIRST_FRAG:
213 goto out;
214 case SCTP_DATA_MIDDLE_FRAG:
215 if (!first_frag) {
216 if (cevent->fsn == sin->fsn) {
217 first_frag = pos;
218 last_frag = pos;
219 next_fsn = cevent->fsn + 1;
220 }
221 } else if (cevent->fsn == next_fsn) {
222 last_frag = pos;
223 next_fsn++;
224 } else {
225 goto out;
226 }
227 break;
228 case SCTP_DATA_LAST_FRAG:
229 if (!first_frag) {
230 if (cevent->fsn == sin->fsn) {
231 first_frag = pos;
232 last_frag = pos;
233 next_fsn = 0;
234 is_last = 1;
235 }
236 } else if (cevent->fsn == next_fsn) {
237 last_frag = pos;
238 next_fsn = 0;
239 is_last = 1;
240 }
241 goto out;
242 default:
243 goto out;
244 }
245 }
246
247out:
248 if (!first_frag)
249 return NULL;
250
251 retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
252 &ulpq->reasm, first_frag,
253 last_frag);
254 if (retval) {
255 sin->fsn = next_fsn;
256 if (is_last) {
257 retval->msg_flags |= MSG_EOR;
258 sin->pd_mode = 0;
259 }
260 }
261
262 return retval;
263}
264
265static struct sctp_ulpevent *sctp_intl_retrieve_reassembled(
266 struct sctp_ulpq *ulpq,
267 struct sctp_ulpevent *event)
268{
269 struct sctp_association *asoc = ulpq->asoc;
270 struct sk_buff *pos, *first_frag = NULL;
271 struct sctp_ulpevent *retval = NULL;
272 struct sk_buff *pd_first = NULL;
273 struct sk_buff *pd_last = NULL;
274 struct sctp_stream_in *sin;
275 __u32 next_fsn = 0;
276 __u32 pd_point = 0;
277 __u32 pd_len = 0;
278 __u32 mid = 0;
279
280 sin = sctp_stream_in(ulpq->asoc, event->stream);
281
282 skb_queue_walk(&ulpq->reasm, pos) {
283 struct sctp_ulpevent *cevent = sctp_skb2event(pos);
284
285 if (cevent->stream < event->stream)
286 continue;
287 if (cevent->stream > event->stream)
288 break;
289
290 if (MID_lt(cevent->mid, event->mid))
291 continue;
292 if (MID_lt(event->mid, cevent->mid))
293 break;
294
295 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
296 case SCTP_DATA_FIRST_FRAG:
297 if (cevent->mid == sin->mid) {
298 pd_first = pos;
299 pd_last = pos;
300 pd_len = pos->len;
301 }
302
303 first_frag = pos;
304 next_fsn = 0;
305 mid = cevent->mid;
306 break;
307
308 case SCTP_DATA_MIDDLE_FRAG:
309 if (first_frag && cevent->mid == mid &&
310 cevent->fsn == next_fsn) {
311 next_fsn++;
312 if (pd_first) {
313 pd_last = pos;
314 pd_len += pos->len;
315 }
316 } else {
317 first_frag = NULL;
318 }
319 break;
320
321 case SCTP_DATA_LAST_FRAG:
322 if (first_frag && cevent->mid == mid &&
323 cevent->fsn == next_fsn)
324 goto found;
325 else
326 first_frag = NULL;
327 break;
328 }
329 }
330
331 if (!pd_first)
332 goto out;
333
334 pd_point = sctp_sk(asoc->base.sk)->pd_point;
335 if (pd_point && pd_point <= pd_len) {
336 retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
337 &ulpq->reasm,
338 pd_first, pd_last);
339 if (retval) {
340 sin->fsn = next_fsn;
341 sin->pd_mode = 1;
342 }
343 }
344 goto out;
345
346found:
347 retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
348 &ulpq->reasm,
349 first_frag, pos);
350 if (retval)
351 retval->msg_flags |= MSG_EOR;
352
353out:
354 return retval;
355}
356
357static struct sctp_ulpevent *sctp_intl_reasm(struct sctp_ulpq *ulpq,
358 struct sctp_ulpevent *event)
359{
360 struct sctp_ulpevent *retval = NULL;
361 struct sctp_stream_in *sin;
362
363 if (SCTP_DATA_NOT_FRAG == (event->msg_flags & SCTP_DATA_FRAG_MASK)) {
364 event->msg_flags |= MSG_EOR;
365 return event;
366 }
367
368 sctp_intl_store_reasm(ulpq, event);
369
370 sin = sctp_stream_in(ulpq->asoc, event->stream);
371 if (sin->pd_mode && event->mid == sin->mid &&
372 event->fsn == sin->fsn)
373 retval = sctp_intl_retrieve_partial(ulpq, event);
374
375 if (!retval)
376 retval = sctp_intl_retrieve_reassembled(ulpq, event);
377
378 return retval;
379}
380
381static void sctp_intl_store_ordered(struct sctp_ulpq *ulpq,
382 struct sctp_ulpevent *event)
383{
384 struct sctp_ulpevent *cevent;
385 struct sk_buff *pos;
386
387 pos = skb_peek_tail(&ulpq->lobby);
388 if (!pos) {
389 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
390 return;
391 }
392
393 cevent = (struct sctp_ulpevent *)pos->cb;
394 if (event->stream == cevent->stream &&
395 MID_lt(cevent->mid, event->mid)) {
396 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
397 return;
398 }
399
400 if (event->stream > cevent->stream) {
401 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
402 return;
403 }
404
405 skb_queue_walk(&ulpq->lobby, pos) {
406 cevent = (struct sctp_ulpevent *)pos->cb;
407
408 if (cevent->stream > event->stream)
409 break;
410
411 if (cevent->stream == event->stream &&
412 MID_lt(event->mid, cevent->mid))
413 break;
414 }
415
416 __skb_queue_before(&ulpq->lobby, pos, sctp_event2skb(event));
417}
418
419static void sctp_intl_retrieve_ordered(struct sctp_ulpq *ulpq,
420 struct sctp_ulpevent *event)
421{
422 struct sk_buff_head *event_list;
423 struct sctp_stream *stream;
424 struct sk_buff *pos, *tmp;
425 __u16 sid = event->stream;
426
427 stream = &ulpq->asoc->stream;
428 event_list = (struct sk_buff_head *)sctp_event2skb(event)->prev;
429
430 sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
431 struct sctp_ulpevent *cevent = (struct sctp_ulpevent *)pos->cb;
432
433 if (cevent->stream > sid)
434 break;
435
436 if (cevent->stream < sid)
437 continue;
438
439 if (cevent->mid != sctp_mid_peek(stream, in, sid))
440 break;
441
442 sctp_mid_next(stream, in, sid);
443
444 __skb_unlink(pos, &ulpq->lobby);
445
446 __skb_queue_tail(event_list, pos);
447 }
448}
449
450static struct sctp_ulpevent *sctp_intl_order(struct sctp_ulpq *ulpq,
451 struct sctp_ulpevent *event)
452{
453 struct sctp_stream *stream;
454 __u16 sid;
455
bd4d627d
XL
456 stream = &ulpq->asoc->stream;
457 sid = event->stream;
458
459 if (event->mid != sctp_mid_peek(stream, in, sid)) {
460 sctp_intl_store_ordered(ulpq, event);
461 return NULL;
462 }
463
464 sctp_mid_next(stream, in, sid);
465
466 sctp_intl_retrieve_ordered(ulpq, event);
467
468 return event;
469}
470
471static int sctp_enqueue_event(struct sctp_ulpq *ulpq,
472 struct sctp_ulpevent *event)
473{
474 struct sk_buff *skb = sctp_event2skb(event);
475 struct sock *sk = ulpq->asoc->base.sk;
476 struct sctp_sock *sp = sctp_sk(sk);
477 struct sk_buff_head *skb_list;
478
479 skb_list = (struct sk_buff_head *)skb->prev;
480
481 if (sk->sk_shutdown & RCV_SHUTDOWN &&
482 (sk->sk_shutdown & SEND_SHUTDOWN ||
483 !sctp_ulpevent_is_notification(event)))
484 goto out_free;
485
486 if (!sctp_ulpevent_is_notification(event)) {
487 sk_mark_napi_id(sk, skb);
488 sk_incoming_cpu_update(sk);
489 }
490
491 if (!sctp_ulpevent_is_enabled(event, &sp->subscribe))
492 goto out_free;
493
494 if (skb_list)
495 skb_queue_splice_tail_init(skb_list,
496 &sk->sk_receive_queue);
497 else
498 __skb_queue_tail(&sk->sk_receive_queue, skb);
499
500 if (!sp->data_ready_signalled) {
501 sp->data_ready_signalled = 1;
502 sk->sk_data_ready(sk);
503 }
504
505 return 1;
506
507out_free:
508 if (skb_list)
509 sctp_queue_purge_ulpevents(skb_list);
510 else
511 sctp_ulpevent_free(event);
512
513 return 0;
514}
515
13228238
XL
516static void sctp_intl_store_reasm_uo(struct sctp_ulpq *ulpq,
517 struct sctp_ulpevent *event)
518{
519 struct sctp_ulpevent *cevent;
520 struct sk_buff *pos;
521
522 pos = skb_peek_tail(&ulpq->reasm_uo);
523 if (!pos) {
524 __skb_queue_tail(&ulpq->reasm_uo, sctp_event2skb(event));
525 return;
526 }
527
528 cevent = sctp_skb2event(pos);
529
530 if (event->stream == cevent->stream &&
531 event->mid == cevent->mid &&
532 (cevent->msg_flags & SCTP_DATA_FIRST_FRAG ||
533 (!(event->msg_flags & SCTP_DATA_FIRST_FRAG) &&
534 event->fsn > cevent->fsn))) {
535 __skb_queue_tail(&ulpq->reasm_uo, sctp_event2skb(event));
536 return;
537 }
538
539 if ((event->stream == cevent->stream &&
540 MID_lt(cevent->mid, event->mid)) ||
541 event->stream > cevent->stream) {
542 __skb_queue_tail(&ulpq->reasm_uo, sctp_event2skb(event));
543 return;
544 }
545
546 skb_queue_walk(&ulpq->reasm_uo, pos) {
547 cevent = sctp_skb2event(pos);
548
549 if (event->stream < cevent->stream ||
550 (event->stream == cevent->stream &&
551 MID_lt(event->mid, cevent->mid)))
552 break;
553
554 if (event->stream == cevent->stream &&
555 event->mid == cevent->mid &&
556 !(cevent->msg_flags & SCTP_DATA_FIRST_FRAG) &&
557 (event->msg_flags & SCTP_DATA_FIRST_FRAG ||
558 event->fsn < cevent->fsn))
559 break;
560 }
561
562 __skb_queue_before(&ulpq->reasm_uo, pos, sctp_event2skb(event));
563}
564
565static struct sctp_ulpevent *sctp_intl_retrieve_partial_uo(
566 struct sctp_ulpq *ulpq,
567 struct sctp_ulpevent *event)
568{
569 struct sk_buff *first_frag = NULL;
570 struct sk_buff *last_frag = NULL;
571 struct sctp_ulpevent *retval;
572 struct sctp_stream_in *sin;
573 struct sk_buff *pos;
574 __u32 next_fsn = 0;
575 int is_last = 0;
576
577 sin = sctp_stream_in(ulpq->asoc, event->stream);
578
579 skb_queue_walk(&ulpq->reasm_uo, pos) {
580 struct sctp_ulpevent *cevent = sctp_skb2event(pos);
581
582 if (cevent->stream < event->stream)
583 continue;
584 if (cevent->stream > event->stream)
585 break;
586
587 if (MID_lt(cevent->mid, sin->mid_uo))
588 continue;
589 if (MID_lt(sin->mid_uo, cevent->mid))
590 break;
591
592 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
593 case SCTP_DATA_FIRST_FRAG:
594 goto out;
595 case SCTP_DATA_MIDDLE_FRAG:
596 if (!first_frag) {
597 if (cevent->fsn == sin->fsn_uo) {
598 first_frag = pos;
599 last_frag = pos;
600 next_fsn = cevent->fsn + 1;
601 }
602 } else if (cevent->fsn == next_fsn) {
603 last_frag = pos;
604 next_fsn++;
605 } else {
606 goto out;
607 }
608 break;
609 case SCTP_DATA_LAST_FRAG:
610 if (!first_frag) {
611 if (cevent->fsn == sin->fsn_uo) {
612 first_frag = pos;
613 last_frag = pos;
614 next_fsn = 0;
615 is_last = 1;
616 }
617 } else if (cevent->fsn == next_fsn) {
618 last_frag = pos;
619 next_fsn = 0;
620 is_last = 1;
621 }
622 goto out;
623 default:
624 goto out;
625 }
626 }
627
628out:
629 if (!first_frag)
630 return NULL;
631
632 retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
633 &ulpq->reasm_uo, first_frag,
634 last_frag);
635 if (retval) {
636 sin->fsn_uo = next_fsn;
637 if (is_last) {
638 retval->msg_flags |= MSG_EOR;
639 sin->pd_mode_uo = 0;
640 }
641 }
642
643 return retval;
644}
645
646static struct sctp_ulpevent *sctp_intl_retrieve_reassembled_uo(
647 struct sctp_ulpq *ulpq,
648 struct sctp_ulpevent *event)
649{
650 struct sctp_association *asoc = ulpq->asoc;
651 struct sk_buff *pos, *first_frag = NULL;
652 struct sctp_ulpevent *retval = NULL;
653 struct sk_buff *pd_first = NULL;
654 struct sk_buff *pd_last = NULL;
655 struct sctp_stream_in *sin;
656 __u32 next_fsn = 0;
657 __u32 pd_point = 0;
658 __u32 pd_len = 0;
659 __u32 mid = 0;
660
661 sin = sctp_stream_in(ulpq->asoc, event->stream);
662
663 skb_queue_walk(&ulpq->reasm_uo, pos) {
664 struct sctp_ulpevent *cevent = sctp_skb2event(pos);
665
666 if (cevent->stream < event->stream)
667 continue;
668 if (cevent->stream > event->stream)
669 break;
670
671 if (MID_lt(cevent->mid, event->mid))
672 continue;
673 if (MID_lt(event->mid, cevent->mid))
674 break;
675
676 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
677 case SCTP_DATA_FIRST_FRAG:
678 if (!sin->pd_mode_uo) {
679 sin->mid_uo = cevent->mid;
680 pd_first = pos;
681 pd_last = pos;
682 pd_len = pos->len;
683 }
684
685 first_frag = pos;
686 next_fsn = 0;
687 mid = cevent->mid;
688 break;
689
690 case SCTP_DATA_MIDDLE_FRAG:
691 if (first_frag && cevent->mid == mid &&
692 cevent->fsn == next_fsn) {
693 next_fsn++;
694 if (pd_first) {
695 pd_last = pos;
696 pd_len += pos->len;
697 }
698 } else {
699 first_frag = NULL;
700 }
701 break;
702
703 case SCTP_DATA_LAST_FRAG:
704 if (first_frag && cevent->mid == mid &&
705 cevent->fsn == next_fsn)
706 goto found;
707 else
708 first_frag = NULL;
709 break;
710 }
711 }
712
713 if (!pd_first)
714 goto out;
715
716 pd_point = sctp_sk(asoc->base.sk)->pd_point;
717 if (pd_point && pd_point <= pd_len) {
718 retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
719 &ulpq->reasm_uo,
720 pd_first, pd_last);
721 if (retval) {
722 sin->fsn_uo = next_fsn;
723 sin->pd_mode_uo = 1;
724 }
725 }
726 goto out;
727
728found:
729 retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
730 &ulpq->reasm_uo,
731 first_frag, pos);
732 if (retval)
733 retval->msg_flags |= MSG_EOR;
734
735out:
736 return retval;
737}
738
739static struct sctp_ulpevent *sctp_intl_reasm_uo(struct sctp_ulpq *ulpq,
740 struct sctp_ulpevent *event)
741{
742 struct sctp_ulpevent *retval = NULL;
743 struct sctp_stream_in *sin;
744
745 if (SCTP_DATA_NOT_FRAG == (event->msg_flags & SCTP_DATA_FRAG_MASK)) {
746 event->msg_flags |= MSG_EOR;
747 return event;
748 }
749
750 sctp_intl_store_reasm_uo(ulpq, event);
751
752 sin = sctp_stream_in(ulpq->asoc, event->stream);
753 if (sin->pd_mode_uo && event->mid == sin->mid_uo &&
754 event->fsn == sin->fsn_uo)
755 retval = sctp_intl_retrieve_partial_uo(ulpq, event);
756
757 if (!retval)
758 retval = sctp_intl_retrieve_reassembled_uo(ulpq, event);
759
760 return retval;
761}
762
763static struct sctp_ulpevent *sctp_intl_retrieve_first_uo(struct sctp_ulpq *ulpq)
764{
765 struct sctp_stream_in *csin, *sin = NULL;
766 struct sk_buff *first_frag = NULL;
767 struct sk_buff *last_frag = NULL;
768 struct sctp_ulpevent *retval;
769 struct sk_buff *pos;
770 __u32 next_fsn = 0;
771 __u16 sid = 0;
772
773 skb_queue_walk(&ulpq->reasm_uo, pos) {
774 struct sctp_ulpevent *cevent = sctp_skb2event(pos);
775
776 csin = sctp_stream_in(ulpq->asoc, cevent->stream);
777 if (csin->pd_mode_uo)
778 continue;
779
780 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
781 case SCTP_DATA_FIRST_FRAG:
782 if (first_frag)
783 goto out;
784 first_frag = pos;
785 last_frag = pos;
786 next_fsn = 0;
787 sin = csin;
788 sid = cevent->stream;
789 sin->mid_uo = cevent->mid;
790 break;
791 case SCTP_DATA_MIDDLE_FRAG:
792 if (!first_frag)
793 break;
794 if (cevent->stream == sid &&
795 cevent->mid == sin->mid_uo &&
796 cevent->fsn == next_fsn) {
797 next_fsn++;
798 last_frag = pos;
799 } else {
800 goto out;
801 }
802 break;
803 case SCTP_DATA_LAST_FRAG:
804 if (first_frag)
805 goto out;
806 break;
807 default:
808 break;
809 }
810 }
811
812 if (!first_frag)
813 return NULL;
814
815out:
816 retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
817 &ulpq->reasm_uo, first_frag,
818 last_frag);
819 if (retval) {
820 sin->fsn_uo = next_fsn;
821 sin->pd_mode_uo = 1;
822 }
823
824 return retval;
825}
826
bd4d627d
XL
827static int sctp_ulpevent_idata(struct sctp_ulpq *ulpq,
828 struct sctp_chunk *chunk, gfp_t gfp)
829{
830 struct sctp_ulpevent *event;
831 struct sk_buff_head temp;
832 int event_eor = 0;
833
834 event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp);
835 if (!event)
836 return -ENOMEM;
837
838 event->mid = ntohl(chunk->subh.idata_hdr->mid);
839 if (event->msg_flags & SCTP_DATA_FIRST_FRAG)
840 event->ppid = chunk->subh.idata_hdr->ppid;
841 else
842 event->fsn = ntohl(chunk->subh.idata_hdr->fsn);
843
13228238
XL
844 if (!(event->msg_flags & SCTP_DATA_UNORDERED)) {
845 event = sctp_intl_reasm(ulpq, event);
846 if (event && event->msg_flags & MSG_EOR) {
847 skb_queue_head_init(&temp);
848 __skb_queue_tail(&temp, sctp_event2skb(event));
bd4d627d 849
13228238
XL
850 event = sctp_intl_order(ulpq, event);
851 }
852 } else {
853 event = sctp_intl_reasm_uo(ulpq, event);
bd4d627d
XL
854 }
855
856 if (event) {
857 event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0;
858 sctp_enqueue_event(ulpq, event);
859 }
860
861 return event_eor;
862}
863
94014e8d
XL
864static struct sctp_ulpevent *sctp_intl_retrieve_first(struct sctp_ulpq *ulpq)
865{
866 struct sctp_stream_in *csin, *sin = NULL;
867 struct sk_buff *first_frag = NULL;
868 struct sk_buff *last_frag = NULL;
869 struct sctp_ulpevent *retval;
870 struct sk_buff *pos;
871 __u32 next_fsn = 0;
872 __u16 sid = 0;
873
874 skb_queue_walk(&ulpq->reasm, pos) {
875 struct sctp_ulpevent *cevent = sctp_skb2event(pos);
876
877 csin = sctp_stream_in(ulpq->asoc, cevent->stream);
878 if (csin->pd_mode)
879 continue;
880
881 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
882 case SCTP_DATA_FIRST_FRAG:
883 if (first_frag)
884 goto out;
885 if (cevent->mid == csin->mid) {
886 first_frag = pos;
887 last_frag = pos;
888 next_fsn = 0;
889 sin = csin;
890 sid = cevent->stream;
891 }
892 break;
893 case SCTP_DATA_MIDDLE_FRAG:
894 if (!first_frag)
895 break;
896 if (cevent->stream == sid &&
897 cevent->mid == sin->mid &&
898 cevent->fsn == next_fsn) {
899 next_fsn++;
900 last_frag = pos;
901 } else {
902 goto out;
903 }
904 break;
905 case SCTP_DATA_LAST_FRAG:
906 if (first_frag)
907 goto out;
908 break;
909 default:
910 break;
911 }
912 }
913
914 if (!first_frag)
915 return NULL;
916
917out:
918 retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
919 &ulpq->reasm, first_frag,
920 last_frag);
921 if (retval) {
922 sin->fsn = next_fsn;
923 sin->pd_mode = 1;
924 }
925
926 return retval;
927}
928
929static void sctp_intl_start_pd(struct sctp_ulpq *ulpq, gfp_t gfp)
930{
931 struct sctp_ulpevent *event;
932
13228238
XL
933 if (!skb_queue_empty(&ulpq->reasm)) {
934 do {
935 event = sctp_intl_retrieve_first(ulpq);
936 if (event)
937 sctp_enqueue_event(ulpq, event);
938 } while (event);
939 }
94014e8d 940
13228238
XL
941 if (!skb_queue_empty(&ulpq->reasm_uo)) {
942 do {
943 event = sctp_intl_retrieve_first_uo(ulpq);
944 if (event)
945 sctp_enqueue_event(ulpq, event);
946 } while (event);
947 }
94014e8d
XL
948}
949
950static void sctp_renege_events(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
951 gfp_t gfp)
952{
953 struct sctp_association *asoc = ulpq->asoc;
954 __u32 freed = 0;
955 __u16 needed;
956
957 if (chunk) {
958 needed = ntohs(chunk->chunk_hdr->length);
959 needed -= sizeof(struct sctp_idata_chunk);
960 } else {
961 needed = SCTP_DEFAULT_MAXWINDOW;
962 }
963
964 if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) {
965 freed = sctp_ulpq_renege_list(ulpq, &ulpq->lobby, needed);
966 if (freed < needed)
967 freed += sctp_ulpq_renege_list(ulpq, &ulpq->reasm,
968 needed);
13228238
XL
969 if (freed < needed)
970 freed += sctp_ulpq_renege_list(ulpq, &ulpq->reasm_uo,
971 needed);
94014e8d
XL
972 }
973
974 if (chunk && freed >= needed)
975 if (sctp_ulpevent_idata(ulpq, chunk, gfp) <= 0)
976 sctp_intl_start_pd(ulpq, gfp);
977
978 sk_mem_reclaim(asoc->base.sk);
979}
980
65f5e357
XL
981static void sctp_intl_stream_abort_pd(struct sctp_ulpq *ulpq, __u16 sid,
982 __u32 mid, __u16 flags, gfp_t gfp)
983{
984 struct sock *sk = ulpq->asoc->base.sk;
985 struct sctp_ulpevent *ev = NULL;
986
987 if (!sctp_ulpevent_type_enabled(SCTP_PARTIAL_DELIVERY_EVENT,
988 &sctp_sk(sk)->subscribe))
989 return;
990
991 ev = sctp_ulpevent_make_pdapi(ulpq->asoc, SCTP_PARTIAL_DELIVERY_ABORTED,
992 sid, mid, flags, gfp);
993 if (ev) {
994 __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev));
995
996 if (!sctp_sk(sk)->data_ready_signalled) {
997 sctp_sk(sk)->data_ready_signalled = 1;
998 sk->sk_data_ready(sk);
999 }
1000 }
1001}
1002
1003static void sctp_intl_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
1004{
1005 struct sctp_stream *stream = &ulpq->asoc->stream;
1006 struct sctp_ulpevent *cevent, *event = NULL;
1007 struct sk_buff_head *lobby = &ulpq->lobby;
1008 struct sk_buff *pos, *tmp;
1009 struct sk_buff_head temp;
1010 __u16 csid;
1011 __u32 cmid;
1012
1013 skb_queue_head_init(&temp);
1014 sctp_skb_for_each(pos, lobby, tmp) {
1015 cevent = (struct sctp_ulpevent *)pos->cb;
1016 csid = cevent->stream;
1017 cmid = cevent->mid;
1018
1019 if (csid > sid)
1020 break;
1021
1022 if (csid < sid)
1023 continue;
1024
1025 if (!MID_lt(cmid, sctp_mid_peek(stream, in, csid)))
1026 break;
1027
1028 __skb_unlink(pos, lobby);
1029 if (!event)
1030 event = sctp_skb2event(pos);
1031
1032 __skb_queue_tail(&temp, pos);
1033 }
1034
1035 if (!event && pos != (struct sk_buff *)lobby) {
1036 cevent = (struct sctp_ulpevent *)pos->cb;
1037 csid = cevent->stream;
1038 cmid = cevent->mid;
1039
1040 if (csid == sid && cmid == sctp_mid_peek(stream, in, csid)) {
1041 sctp_mid_next(stream, in, csid);
1042 __skb_unlink(pos, lobby);
1043 __skb_queue_tail(&temp, pos);
1044 event = sctp_skb2event(pos);
1045 }
1046 }
1047
1048 if (event) {
1049 sctp_intl_retrieve_ordered(ulpq, event);
1050 sctp_enqueue_event(ulpq, event);
1051 }
1052}
1053
1054static void sctp_intl_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp)
1055{
1056 struct sctp_stream *stream = &ulpq->asoc->stream;
1057 __u16 sid;
1058
1059 for (sid = 0; sid < stream->incnt; sid++) {
1060 struct sctp_stream_in *sin = &stream->in[sid];
1061 __u32 mid;
1062
13228238
XL
1063 if (sin->pd_mode_uo) {
1064 sin->pd_mode_uo = 0;
1065
1066 mid = sin->mid_uo;
1067 sctp_intl_stream_abort_pd(ulpq, sid, mid, 0x1, gfp);
1068 }
1069
65f5e357
XL
1070 if (sin->pd_mode) {
1071 sin->pd_mode = 0;
1072
1073 mid = sin->mid;
1074 sctp_intl_stream_abort_pd(ulpq, sid, mid, 0, gfp);
1075 sctp_mid_skip(stream, in, sid, mid);
1076
1077 sctp_intl_reap_ordered(ulpq, sid);
1078 }
1079 }
1080
1081 /* intl abort pd happens only when all data needs to be cleaned */
1082 sctp_ulpq_flush(ulpq);
1083}
1084
8e0c3b73
XL
1085static inline int sctp_get_skip_pos(struct sctp_ifwdtsn_skip *skiplist,
1086 int nskips, __be16 stream, __u8 flags)
1087{
1088 int i;
1089
1090 for (i = 0; i < nskips; i++)
1091 if (skiplist[i].stream == stream &&
1092 skiplist[i].flags == flags)
1093 return i;
1094
1095 return i;
1096}
1097
1098#define SCTP_FTSN_U_BIT 0x1
1099static void sctp_generate_iftsn(struct sctp_outq *q, __u32 ctsn)
1100{
1101 struct sctp_ifwdtsn_skip ftsn_skip_arr[10];
1102 struct sctp_association *asoc = q->asoc;
1103 struct sctp_chunk *ftsn_chunk = NULL;
1104 struct list_head *lchunk, *temp;
1105 int nskips = 0, skip_pos;
1106 struct sctp_chunk *chunk;
1107 __u32 tsn;
1108
1109 if (!asoc->peer.prsctp_capable)
1110 return;
1111
1112 if (TSN_lt(asoc->adv_peer_ack_point, ctsn))
1113 asoc->adv_peer_ack_point = ctsn;
1114
1115 list_for_each_safe(lchunk, temp, &q->abandoned) {
1116 chunk = list_entry(lchunk, struct sctp_chunk, transmitted_list);
1117 tsn = ntohl(chunk->subh.data_hdr->tsn);
1118
1119 if (TSN_lte(tsn, ctsn)) {
1120 list_del_init(lchunk);
1121 sctp_chunk_free(chunk);
1122 } else if (TSN_lte(tsn, asoc->adv_peer_ack_point + 1)) {
1123 __be16 sid = chunk->subh.idata_hdr->stream;
1124 __be32 mid = chunk->subh.idata_hdr->mid;
1125 __u8 flags = 0;
1126
1127 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
1128 flags |= SCTP_FTSN_U_BIT;
1129
1130 asoc->adv_peer_ack_point = tsn;
1131 skip_pos = sctp_get_skip_pos(&ftsn_skip_arr[0], nskips,
1132 sid, flags);
1133 ftsn_skip_arr[skip_pos].stream = sid;
1134 ftsn_skip_arr[skip_pos].reserved = 0;
1135 ftsn_skip_arr[skip_pos].flags = flags;
1136 ftsn_skip_arr[skip_pos].mid = mid;
1137 if (skip_pos == nskips)
1138 nskips++;
1139 if (nskips == 10)
1140 break;
1141 } else {
1142 break;
1143 }
1144 }
1145
1146 if (asoc->adv_peer_ack_point > ctsn)
1147 ftsn_chunk = sctp_make_ifwdtsn(asoc, asoc->adv_peer_ack_point,
1148 nskips, &ftsn_skip_arr[0]);
1149
1150 if (ftsn_chunk) {
1151 list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
1152 SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
1153 }
1154}
1155
0fc2ea92
XL
1156#define _sctp_walk_ifwdtsn(pos, chunk, end) \
1157 for (pos = chunk->subh.ifwdtsn_hdr->skip; \
1158 (void *)pos < (void *)chunk->subh.ifwdtsn_hdr->skip + (end); pos++)
1159
1160#define sctp_walk_ifwdtsn(pos, ch) \
1161 _sctp_walk_ifwdtsn((pos), (ch), ntohs((ch)->chunk_hdr->length) - \
1162 sizeof(struct sctp_ifwdtsn_chunk))
1163
1164static bool sctp_validate_fwdtsn(struct sctp_chunk *chunk)
1165{
1166 struct sctp_fwdtsn_skip *skip;
1167 __u16 incnt;
1168
1169 if (chunk->chunk_hdr->type != SCTP_CID_FWD_TSN)
1170 return false;
1171
1172 incnt = chunk->asoc->stream.incnt;
1173 sctp_walk_fwdtsn(skip, chunk)
1174 if (ntohs(skip->stream) >= incnt)
1175 return false;
1176
1177 return true;
1178}
1179
1180static bool sctp_validate_iftsn(struct sctp_chunk *chunk)
1181{
1182 struct sctp_ifwdtsn_skip *skip;
1183 __u16 incnt;
1184
1185 if (chunk->chunk_hdr->type != SCTP_CID_I_FWD_TSN)
1186 return false;
1187
1188 incnt = chunk->asoc->stream.incnt;
1189 sctp_walk_ifwdtsn(skip, chunk)
1190 if (ntohs(skip->stream) >= incnt)
1191 return false;
1192
1193 return true;
1194}
1195
47b20a88
XL
1196static void sctp_report_fwdtsn(struct sctp_ulpq *ulpq, __u32 ftsn)
1197{
1198 /* Move the Cumulattive TSN Ack ahead. */
1199 sctp_tsnmap_skip(&ulpq->asoc->peer.tsn_map, ftsn);
1200 /* purge the fragmentation queue */
1201 sctp_ulpq_reasm_flushtsn(ulpq, ftsn);
1202 /* Abort any in progress partial delivery. */
1203 sctp_ulpq_abort_pd(ulpq, GFP_ATOMIC);
1204}
1205
1206static void sctp_intl_reasm_flushtsn(struct sctp_ulpq *ulpq, __u32 ftsn)
1207{
1208 struct sk_buff *pos, *tmp;
1209
1210 skb_queue_walk_safe(&ulpq->reasm, pos, tmp) {
1211 struct sctp_ulpevent *event = sctp_skb2event(pos);
1212 __u32 tsn = event->tsn;
1213
1214 if (TSN_lte(tsn, ftsn)) {
1215 __skb_unlink(pos, &ulpq->reasm);
1216 sctp_ulpevent_free(event);
1217 }
1218 }
1219
1220 skb_queue_walk_safe(&ulpq->reasm_uo, pos, tmp) {
1221 struct sctp_ulpevent *event = sctp_skb2event(pos);
1222 __u32 tsn = event->tsn;
1223
1224 if (TSN_lte(tsn, ftsn)) {
1225 __skb_unlink(pos, &ulpq->reasm_uo);
1226 sctp_ulpevent_free(event);
1227 }
1228 }
1229}
1230
1231static void sctp_report_iftsn(struct sctp_ulpq *ulpq, __u32 ftsn)
1232{
1233 /* Move the Cumulattive TSN Ack ahead. */
1234 sctp_tsnmap_skip(&ulpq->asoc->peer.tsn_map, ftsn);
1235 /* purge the fragmentation queue */
1236 sctp_intl_reasm_flushtsn(ulpq, ftsn);
1237 /* abort only when it's for all data */
1238 if (ftsn == sctp_tsnmap_get_max_tsn_seen(&ulpq->asoc->peer.tsn_map))
1239 sctp_intl_abort_pd(ulpq, GFP_ATOMIC);
1240}
1241
0c3f6f65
XL
1242static struct sctp_stream_interleave sctp_stream_interleave_0 = {
1243 .data_chunk_len = sizeof(struct sctp_data_chunk),
0fc2ea92 1244 .ftsn_chunk_len = sizeof(struct sctp_fwdtsn_chunk),
0c3f6f65
XL
1245 /* DATA process functions */
1246 .make_datafrag = sctp_make_datafrag_empty,
668c9beb 1247 .assign_number = sctp_chunk_assign_ssn,
9d4ceaf1 1248 .validate_data = sctp_validate_data,
bd4d627d 1249 .ulpevent_data = sctp_ulpq_tail_data,
9162e0ed 1250 .enqueue_event = sctp_ulpq_tail_event,
94014e8d 1251 .renege_events = sctp_ulpq_renege,
be4e0ce1 1252 .start_pd = sctp_ulpq_partial_delivery,
65f5e357 1253 .abort_pd = sctp_ulpq_abort_pd,
8e0c3b73
XL
1254 /* FORWARD-TSN process functions */
1255 .generate_ftsn = sctp_generate_fwdtsn,
0fc2ea92 1256 .validate_ftsn = sctp_validate_fwdtsn,
47b20a88 1257 .report_ftsn = sctp_report_fwdtsn,
0c3f6f65
XL
1258};
1259
1260static struct sctp_stream_interleave sctp_stream_interleave_1 = {
1261 .data_chunk_len = sizeof(struct sctp_idata_chunk),
0fc2ea92 1262 .ftsn_chunk_len = sizeof(struct sctp_ifwdtsn_chunk),
0c3f6f65
XL
1263 /* I-DATA process functions */
1264 .make_datafrag = sctp_make_idatafrag_empty,
668c9beb 1265 .assign_number = sctp_chunk_assign_mid,
9d4ceaf1 1266 .validate_data = sctp_validate_idata,
bd4d627d 1267 .ulpevent_data = sctp_ulpevent_idata,
9162e0ed 1268 .enqueue_event = sctp_enqueue_event,
94014e8d 1269 .renege_events = sctp_renege_events,
be4e0ce1 1270 .start_pd = sctp_intl_start_pd,
65f5e357 1271 .abort_pd = sctp_intl_abort_pd,
8e0c3b73
XL
1272 /* I-FORWARD-TSN process functions */
1273 .generate_ftsn = sctp_generate_iftsn,
0fc2ea92 1274 .validate_ftsn = sctp_validate_iftsn,
47b20a88 1275 .report_ftsn = sctp_report_iftsn,
0c3f6f65
XL
1276};
1277
1278void sctp_stream_interleave_init(struct sctp_stream *stream)
1279{
1280 struct sctp_association *asoc;
1281
1282 asoc = container_of(stream, struct sctp_association, stream);
1283 stream->si = asoc->intl_enable ? &sctp_stream_interleave_1
1284 : &sctp_stream_interleave_0;
1285}