^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* SCTP kernel implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) Copyright Red Hat Inc. 2017
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file is part of the SCTP kernel implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * These functions manipulate sctp stream queue/scheduling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Please send any bug reports or fixes you make to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * email addresched(es):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * lksctp developers <linux-sctp@vger.kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Written or modified by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/sctp/sctp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/sctp/sm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/sctp/stream_sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* Priority handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * RFC DRAFT ndata section 3.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static void sctp_sched_rr_unsched_all(struct sctp_stream *stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static void sctp_sched_rr_next_stream(struct sctp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct list_head *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) pos = stream->rr_next->rr_list.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (pos == &stream->rr_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) pos = pos->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) stream->rr_next = list_entry(pos, struct sctp_stream_out_ext, rr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void sctp_sched_rr_unsched(struct sctp_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct sctp_stream_out_ext *soute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (stream->rr_next == soute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* Try to move to the next stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) sctp_sched_rr_next_stream(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) list_del_init(&soute->rr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* If we have no other stream queued, clear next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (list_empty(&stream->rr_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) stream->rr_next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void sctp_sched_rr_sched(struct sctp_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct sctp_stream_out_ext *soute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!list_empty(&soute->rr_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Already scheduled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Schedule the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) list_add_tail(&soute->rr_list, &stream->rr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!stream->rr_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) stream->rr_next = soute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int sctp_sched_rr_set(struct sctp_stream *stream, __u16 sid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) __u16 prio, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static int sctp_sched_rr_get(struct sctp_stream *stream, __u16 sid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __u16 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int sctp_sched_rr_init(struct sctp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) INIT_LIST_HEAD(&stream->rr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) stream->rr_next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int sctp_sched_rr_init_sid(struct sctp_stream *stream, __u16 sid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) INIT_LIST_HEAD(&SCTP_SO(stream, sid)->ext->rr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void sctp_sched_rr_free(struct sctp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) sctp_sched_rr_unsched_all(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void sctp_sched_rr_enqueue(struct sctp_outq *q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct sctp_datamsg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct sctp_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct sctp_chunk *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) __u16 sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ch = list_first_entry(&msg->chunks, struct sctp_chunk, frag_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sid = sctp_chunk_stream_no(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) stream = &q->asoc->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) sctp_sched_rr_sched(stream, SCTP_SO(stream, sid)->ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static struct sctp_chunk *sctp_sched_rr_dequeue(struct sctp_outq *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct sctp_stream *stream = &q->asoc->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct sctp_stream_out_ext *soute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct sctp_chunk *ch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Bail out quickly if queue is empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (list_empty(&q->out_chunk_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Find which chunk is next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (stream->out_curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) soute = stream->out_curr->ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) soute = stream->rr_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ch = list_entry(soute->outq.next, struct sctp_chunk, stream_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) sctp_sched_dequeue_common(q, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void sctp_sched_rr_dequeue_done(struct sctp_outq *q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct sctp_chunk *ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct sctp_stream_out_ext *soute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) __u16 sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* Last chunk on that msg, move to the next stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) sid = sctp_chunk_stream_no(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) soute = SCTP_SO(&q->asoc->stream, sid)->ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) sctp_sched_rr_next_stream(&q->asoc->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (list_empty(&soute->outq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) sctp_sched_rr_unsched(&q->asoc->stream, soute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void sctp_sched_rr_sched_all(struct sctp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct sctp_association *asoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct sctp_stream_out_ext *soute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct sctp_chunk *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) asoc = container_of(stream, struct sctp_association, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) list_for_each_entry(ch, &asoc->outqueue.out_chunk_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) __u16 sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) sid = sctp_chunk_stream_no(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) soute = SCTP_SO(stream, sid)->ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (soute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) sctp_sched_rr_sched(stream, soute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static void sctp_sched_rr_unsched_all(struct sctp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct sctp_stream_out_ext *soute, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) list_for_each_entry_safe(soute, tmp, &stream->rr_list, rr_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) sctp_sched_rr_unsched(stream, soute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static struct sctp_sched_ops sctp_sched_rr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .set = sctp_sched_rr_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .get = sctp_sched_rr_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .init = sctp_sched_rr_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .init_sid = sctp_sched_rr_init_sid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .free = sctp_sched_rr_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .enqueue = sctp_sched_rr_enqueue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .dequeue = sctp_sched_rr_dequeue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .dequeue_done = sctp_sched_rr_dequeue_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .sched_all = sctp_sched_rr_sched_all,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .unsched_all = sctp_sched_rr_unsched_all,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) void sctp_sched_ops_rr_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) sctp_sched_ops_register(SCTP_SS_RR, &sctp_sched_rr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }