Lines Matching +full:ulp +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (c) 1999-2000 Cisco, Inc.
5 * Copyright (c) 1999-2001 Motorola, Inc.
10 * This abstraction carries sctp events to the ULP (sockets).
14 * lksctp developers <linux-sctp@vger.kernel.org>
40 /* Initialize a ULP queue from a block of memory. */
44 memset(ulpq, 0, sizeof(struct sctp_ulpq)); in sctp_ulpq_init()
46 ulpq->asoc = asoc; in sctp_ulpq_init()
47 skb_queue_head_init(&ulpq->reasm); in sctp_ulpq_init()
48 skb_queue_head_init(&ulpq->reasm_uo); in sctp_ulpq_init()
49 skb_queue_head_init(&ulpq->lobby); in sctp_ulpq_init()
50 ulpq->pd_mode = 0; in sctp_ulpq_init()
62 while ((skb = __skb_dequeue(&ulpq->lobby)) != NULL) { in sctp_ulpq_flush()
67 while ((skb = __skb_dequeue(&ulpq->reasm)) != NULL) { in sctp_ulpq_flush()
72 while ((skb = __skb_dequeue(&ulpq->reasm_uo)) != NULL) { in sctp_ulpq_flush()
90 int event_eor = 0; in sctp_ulpq_tail_data()
93 event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp); in sctp_ulpq_tail_data()
95 return -ENOMEM; in sctp_ulpq_tail_data()
97 event->ssn = ntohs(chunk->subh.data_hdr->ssn); in sctp_ulpq_tail_data()
98 event->ppid = chunk->subh.data_hdr->ppid; in sctp_ulpq_tail_data()
109 if (event->msg_flags & MSG_EOR) in sctp_ulpq_tail_data()
113 /* Send event to the ULP. 'event' is the sctp_ulpevent for in sctp_ulpq_tail_data()
117 event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0; in sctp_ulpq_tail_data()
124 /* Add a new event for propagation to the ULP. */
132 if (atomic_dec_and_test(&sp->pd_mode)) { in sctp_clear_pd()
136 if (!skb_queue_empty(&sp->pd_lobby)) { in sctp_clear_pd()
137 skb_queue_splice_tail_init(&sp->pd_lobby, in sctp_clear_pd()
138 &sk->sk_receive_queue); in sctp_clear_pd()
147 if (!skb_queue_empty(&sp->pd_lobby) && asoc) { in sctp_clear_pd()
151 sctp_skb_for_each(skb, &sp->pd_lobby, tmp) { in sctp_clear_pd()
153 if (event->asoc == asoc) { in sctp_clear_pd()
154 __skb_unlink(skb, &sp->pd_lobby); in sctp_clear_pd()
155 __skb_queue_tail(&sk->sk_receive_queue, in sctp_clear_pd()
162 return 0; in sctp_clear_pd()
168 struct sctp_sock *sp = sctp_sk(ulpq->asoc->base.sk); in sctp_ulpq_set_pd()
170 atomic_inc(&sp->pd_mode); in sctp_ulpq_set_pd()
171 ulpq->pd_mode = 1; in sctp_ulpq_set_pd()
177 ulpq->pd_mode = 0; in sctp_ulpq_clear_pd()
179 return sctp_clear_pd(ulpq->asoc->base.sk, ulpq->asoc); in sctp_ulpq_clear_pd()
184 struct sock *sk = ulpq->asoc->base.sk; in sctp_ulpq_tail_event()
189 int clear_pd = 0; in sctp_ulpq_tail_event()
197 if (sk->sk_shutdown & RCV_SHUTDOWN && in sctp_ulpq_tail_event()
198 (sk->sk_shutdown & SEND_SHUTDOWN || in sctp_ulpq_tail_event()
207 if (!sctp_ulpevent_is_enabled(event, ulpq->asoc->subscribe)) in sctp_ulpq_tail_event()
215 if (atomic_read(&sp->pd_mode) == 0) { in sctp_ulpq_tail_event()
216 queue = &sk->sk_receive_queue; in sctp_ulpq_tail_event()
218 if (ulpq->pd_mode) { in sctp_ulpq_tail_event()
224 if ((event->msg_flags & MSG_NOTIFICATION) || in sctp_ulpq_tail_event()
226 (event->msg_flags & SCTP_DATA_FRAG_MASK))) in sctp_ulpq_tail_event()
227 queue = &sp->pd_lobby; in sctp_ulpq_tail_event()
229 clear_pd = event->msg_flags & MSG_EOR; in sctp_ulpq_tail_event()
230 queue = &sk->sk_receive_queue; in sctp_ulpq_tail_event()
238 if (sp->frag_interleave) in sctp_ulpq_tail_event()
239 queue = &sk->sk_receive_queue; in sctp_ulpq_tail_event()
241 queue = &sp->pd_lobby; in sctp_ulpq_tail_event()
254 if (queue == &sk->sk_receive_queue && !sp->data_ready_signalled) { in sctp_ulpq_tail_event()
256 sp->data_ready_signalled = 1; in sctp_ulpq_tail_event()
257 sk->sk_data_ready(sk); in sctp_ulpq_tail_event()
267 return 0; in sctp_ulpq_tail_event()
280 tsn = event->tsn; in sctp_ulpq_store_reasm()
283 pos = skb_peek_tail(&ulpq->reasm); in sctp_ulpq_store_reasm()
285 __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event)); in sctp_ulpq_store_reasm()
291 ctsn = cevent->tsn; in sctp_ulpq_store_reasm()
293 __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event)); in sctp_ulpq_store_reasm()
298 skb_queue_walk(&ulpq->reasm, pos) { in sctp_ulpq_store_reasm()
300 ctsn = cevent->tsn; in sctp_ulpq_store_reasm()
307 __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event)); in sctp_ulpq_store_reasm()
313 * This routine creates a re-assembled skb given the first and last skb's
314 * as stored in the reassembly queue. The skb's may be non-linear if the sctp
327 struct sk_buff *list = skb_shinfo(f_frag)->frag_list; in sctp_make_reassembled_event()
333 pos = f_frag->next; in sctp_make_reassembled_event()
336 for (last = list; list; last = list, list = list->next) in sctp_make_reassembled_event()
343 last->next = pos; in sctp_make_reassembled_event()
355 sctp_skb_set_owner_r(new, f_frag->sk); in sctp_make_reassembled_event()
357 skb_shinfo(new)->frag_list = pos; in sctp_make_reassembled_event()
359 skb_shinfo(f_frag)->frag_list = pos; in sctp_make_reassembled_event()
365 /* if we did unshare, then free the old skb and re-assign */ in sctp_make_reassembled_event()
373 pnext = pos->next; in sctp_make_reassembled_event()
376 f_frag->len += pos->len; in sctp_make_reassembled_event()
377 f_frag->data_len += pos->len; in sctp_make_reassembled_event()
385 pos->next = pnext; in sctp_make_reassembled_event()
408 size_t pd_len = 0; in sctp_ulpq_retrieve_reassembled()
412 /* Initialized to 0 just to avoid compiler warning message. Will in sctp_ulpq_retrieve_reassembled()
416 next_tsn = 0; in sctp_ulpq_retrieve_reassembled()
431 skb_queue_walk(&ulpq->reasm, pos) { in sctp_ulpq_retrieve_reassembled()
433 ctsn = cevent->tsn; in sctp_ulpq_retrieve_reassembled()
435 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { in sctp_ulpq_retrieve_reassembled()
441 if (skb_queue_is_first(&ulpq->reasm, pos)) { in sctp_ulpq_retrieve_reassembled()
444 pd_len = pos->len; in sctp_ulpq_retrieve_reassembled()
448 pd_len = 0; in sctp_ulpq_retrieve_reassembled()
460 pd_len += pos->len; in sctp_ulpq_retrieve_reassembled()
475 asoc = ulpq->asoc; in sctp_ulpq_retrieve_reassembled()
482 if (!sctp_sk(asoc->base.sk)->frag_interleave && in sctp_ulpq_retrieve_reassembled()
483 atomic_read(&sctp_sk(asoc->base.sk)->pd_mode)) in sctp_ulpq_retrieve_reassembled()
487 pd_point = sctp_sk(asoc->base.sk)->pd_point; in sctp_ulpq_retrieve_reassembled()
489 retval = sctp_make_reassembled_event(asoc->base.net, in sctp_ulpq_retrieve_reassembled()
490 &ulpq->reasm, in sctp_ulpq_retrieve_reassembled()
499 retval = sctp_make_reassembled_event(ulpq->asoc->base.net, in sctp_ulpq_retrieve_reassembled()
500 &ulpq->reasm, first_frag, pos); in sctp_ulpq_retrieve_reassembled()
502 retval->msg_flags |= MSG_EOR; in sctp_ulpq_retrieve_reassembled()
520 if (skb_queue_empty(&ulpq->reasm)) in sctp_ulpq_retrieve_partial()
525 next_tsn = 0; in sctp_ulpq_retrieve_partial()
526 is_last = 0; in sctp_ulpq_retrieve_partial()
528 skb_queue_walk(&ulpq->reasm, pos) { in sctp_ulpq_retrieve_partial()
530 ctsn = cevent->tsn; in sctp_ulpq_retrieve_partial()
532 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { in sctp_ulpq_retrieve_partial()
565 retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm, in sctp_ulpq_retrieve_partial()
568 retval->msg_flags |= MSG_EOR; in sctp_ulpq_retrieve_partial()
583 if (SCTP_DATA_NOT_FRAG == (event->msg_flags & SCTP_DATA_FRAG_MASK)) { in sctp_ulpq_reasm()
584 event->msg_flags |= MSG_EOR; in sctp_ulpq_reasm()
589 if (!ulpq->pd_mode) in sctp_ulpq_reasm()
597 ctsn = event->tsn; in sctp_ulpq_reasm()
598 ctsnap = sctp_tsnmap_get_ctsn(&ulpq->asoc->peer.tsn_map); in sctp_ulpq_reasm()
619 if (skb_queue_empty(&ulpq->reasm)) in sctp_ulpq_retrieve_first()
624 next_tsn = 0; in sctp_ulpq_retrieve_first()
626 skb_queue_walk(&ulpq->reasm, pos) { in sctp_ulpq_retrieve_first()
628 ctsn = cevent->tsn; in sctp_ulpq_retrieve_first()
630 switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { in sctp_ulpq_retrieve_first()
666 retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm, in sctp_ulpq_retrieve_first()
678 * take cautions in updating its re-assembly queue. The receiver MUST
691 if (skb_queue_empty(&ulpq->reasm)) in sctp_ulpq_reasm_flushtsn()
694 skb_queue_walk_safe(&ulpq->reasm, pos, tmp) { in sctp_ulpq_reasm_flushtsn()
696 tsn = event->tsn; in sctp_ulpq_reasm_flushtsn()
704 __skb_unlink(pos, &ulpq->reasm); in sctp_ulpq_reasm_flushtsn()
720 if (skb_queue_empty(&ulpq->reasm)) in sctp_ulpq_reasm_drain()
730 if (event->msg_flags & MSG_EOR) in sctp_ulpq_reasm_drain()
733 /* Send event to the ULP. 'event' is the in sctp_ulpq_reasm_drain()
754 sid = event->stream; in sctp_ulpq_retrieve_ordered()
755 stream = &ulpq->asoc->stream; in sctp_ulpq_retrieve_ordered()
757 event_list = (struct sk_buff_head *) sctp_event2skb(event)->prev; in sctp_ulpq_retrieve_ordered()
760 sctp_skb_for_each(pos, &ulpq->lobby, tmp) { in sctp_ulpq_retrieve_ordered()
761 cevent = (struct sctp_ulpevent *) pos->cb; in sctp_ulpq_retrieve_ordered()
762 csid = cevent->stream; in sctp_ulpq_retrieve_ordered()
763 cssn = cevent->ssn; in sctp_ulpq_retrieve_ordered()
779 __skb_unlink(pos, &ulpq->lobby); in sctp_ulpq_retrieve_ordered()
795 pos = skb_peek_tail(&ulpq->lobby); in sctp_ulpq_store_ordered()
797 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event)); in sctp_ulpq_store_ordered()
801 sid = event->stream; in sctp_ulpq_store_ordered()
802 ssn = event->ssn; in sctp_ulpq_store_ordered()
804 cevent = (struct sctp_ulpevent *) pos->cb; in sctp_ulpq_store_ordered()
805 csid = cevent->stream; in sctp_ulpq_store_ordered()
806 cssn = cevent->ssn; in sctp_ulpq_store_ordered()
808 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event)); in sctp_ulpq_store_ordered()
813 __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event)); in sctp_ulpq_store_ordered()
820 skb_queue_walk(&ulpq->lobby, pos) { in sctp_ulpq_store_ordered()
821 cevent = (struct sctp_ulpevent *) pos->cb; in sctp_ulpq_store_ordered()
822 csid = cevent->stream; in sctp_ulpq_store_ordered()
823 cssn = cevent->ssn; in sctp_ulpq_store_ordered()
833 __skb_queue_before(&ulpq->lobby, pos, sctp_event2skb(event)); in sctp_ulpq_store_ordered()
843 if (event->msg_flags & SCTP_DATA_UNORDERED) in sctp_ulpq_order()
847 sid = event->stream; in sctp_ulpq_order()
848 ssn = event->ssn; in sctp_ulpq_order()
849 stream = &ulpq->asoc->stream; in sctp_ulpq_order()
881 struct sk_buff_head *lobby = &ulpq->lobby; in sctp_ulpq_reap_ordered()
884 stream = &ulpq->asoc->stream; in sctp_ulpq_reap_ordered()
890 cevent = (struct sctp_ulpevent *) pos->cb; in sctp_ulpq_reap_ordered()
891 csid = cevent->stream; in sctp_ulpq_reap_ordered()
892 cssn = cevent->ssn; in sctp_ulpq_reap_ordered()
919 cevent = (struct sctp_ulpevent *) pos->cb; in sctp_ulpq_reap_ordered()
920 csid = cevent->stream; in sctp_ulpq_reap_ordered()
921 cssn = cevent->ssn; in sctp_ulpq_reap_ordered()
931 /* Send event to the ULP. 'event' is the sctp_ulpevent for in sctp_ulpq_reap_ordered()
949 stream = &ulpq->asoc->stream; in sctp_ulpq_skip()
967 __u16 freed = 0; in sctp_ulpq_renege_list()
973 tsnmap = &ulpq->asoc->peer.tsn_map; in sctp_ulpq_renege_list()
977 tsn = event->tsn; in sctp_ulpq_renege_list()
988 flist = skb_shinfo(skb)->frag_list; in sctp_ulpq_renege_list()
989 for (last = flist; flist; flist = flist->next) { in sctp_ulpq_renege_list()
994 last_tsn = sctp_skb2event(last)->tsn; in sctp_ulpq_renege_list()
1015 return sctp_ulpq_renege_list(ulpq, &ulpq->lobby, needed); in sctp_ulpq_renege_order()
1021 return sctp_ulpq_renege_list(ulpq, &ulpq->reasm, needed); in sctp_ulpq_renege_frags()
1034 asoc = ulpq->asoc; in sctp_ulpq_partial_delivery()
1035 sp = sctp_sk(asoc->base.sk); in sctp_ulpq_partial_delivery()
1040 if (ulpq->pd_mode) in sctp_ulpq_partial_delivery()
1046 skb = skb_peek(&asoc->ulpq.reasm); in sctp_ulpq_partial_delivery()
1048 ctsn = sctp_skb2event(skb)->tsn; in sctp_ulpq_partial_delivery()
1049 if (!TSN_lte(ctsn, sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map))) in sctp_ulpq_partial_delivery()
1058 if (sp->frag_interleave || atomic_read(&sp->pd_mode) == 0) { in sctp_ulpq_partial_delivery()
1061 /* Send event to the ULP. */ in sctp_ulpq_partial_delivery()
1078 struct sctp_association *asoc = ulpq->asoc; in sctp_ulpq_renege()
1079 __u32 freed = 0; in sctp_ulpq_renege()
1082 needed = ntohs(chunk->chunk_hdr->length) - in sctp_ulpq_renege()
1085 if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) { in sctp_ulpq_renege()
1088 freed += sctp_ulpq_renege_frags(ulpq, needed - freed); in sctp_ulpq_renege()
1091 if (sk_rmem_schedule(asoc->base.sk, chunk->skb, needed) && in sctp_ulpq_renege()
1098 if (retval <= 0) in sctp_ulpq_renege()
1104 sk_mem_reclaim(asoc->base.sk); in sctp_ulpq_renege()
1118 if (!ulpq->pd_mode) in sctp_ulpq_abort_pd()
1121 sk = ulpq->asoc->base.sk; in sctp_ulpq_abort_pd()
1123 if (sctp_ulpevent_type_enabled(ulpq->asoc->subscribe, in sctp_ulpq_abort_pd()
1125 ev = sctp_ulpevent_make_pdapi(ulpq->asoc, in sctp_ulpq_abort_pd()
1127 0, 0, 0, gfp); in sctp_ulpq_abort_pd()
1129 __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev)); in sctp_ulpq_abort_pd()
1132 if ((sctp_ulpq_clear_pd(ulpq) || ev) && !sp->data_ready_signalled) { in sctp_ulpq_abort_pd()
1133 sp->data_ready_signalled = 1; in sctp_ulpq_abort_pd()
1134 sk->sk_data_ready(sk); in sctp_ulpq_abort_pd()