Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'sctp-add-another-two-stream-schedulers'

Xin Long says:

====================
sctp: add another two stream schedulers

All SCTP stream schedulers are defined in rfc8260#section-3,
First-Come First-Served, Round-Robin and Priority-Based
Schedulers are already added in kernel.

This patchset adds another two schedulers: Fair Capacity
Scheduler and Weighted Fair Queueing Scheduler.

Note that the left one "Round-Robin Scheduler per Packet"
Scheduler is not implemented by this patch, as it's still
intrusive to be added in the current SCTP kernel code.
====================

Link: https://lore.kernel.org/r/cover.1678224012.git.lucien.xin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+242 -2
+2
include/net/sctp/stream_sched.h
··· 58 58 struct sctp_sched_ops *sched_ops); 59 59 void sctp_sched_ops_prio_init(void); 60 60 void sctp_sched_ops_rr_init(void); 61 + void sctp_sched_ops_fc_init(void); 62 + void sctp_sched_ops_wfq_init(void); 61 63 62 64 #endif /* __sctp_stream_sched_h__ */
+8
include/net/sctp/structs.h
··· 1429 1429 struct { 1430 1430 struct list_head rr_list; 1431 1431 }; 1432 + struct { 1433 + struct list_head fc_list; 1434 + __u32 fc_length; 1435 + __u16 fc_weight; 1436 + }; 1432 1437 }; 1433 1438 }; 1434 1439 ··· 1479 1474 struct list_head rr_list; 1480 1475 /* The next stream in line */ 1481 1476 struct sctp_stream_out_ext *rr_next; 1477 + }; 1478 + struct { 1479 + struct list_head fc_list; 1482 1480 }; 1483 1481 }; 1484 1482 struct sctp_stream_interleave *si;
+3 -1
include/uapi/linux/sctp.h
··· 1211 1211 SCTP_SS_DEFAULT = SCTP_SS_FCFS, 1212 1212 SCTP_SS_PRIO, 1213 1213 SCTP_SS_RR, 1214 - SCTP_SS_MAX = SCTP_SS_RR 1214 + SCTP_SS_FC, 1215 + SCTP_SS_WFQ, 1216 + SCTP_SS_MAX = SCTP_SS_WFQ 1215 1217 }; 1216 1218 1217 1219 /* Probe Interval socket option */
+2 -1
net/sctp/Makefile
··· 13 13 tsnmap.o bind_addr.o socket.o primitive.o \ 14 14 output.o input.o debug.o stream.o auth.o \ 15 15 offload.o stream_sched.o stream_sched_prio.o \ 16 - stream_sched_rr.o stream_interleave.o 16 + stream_sched_rr.o stream_sched_fc.o \ 17 + stream_interleave.o 17 18 18 19 sctp_diag-y := diag.o 19 20
+2
net/sctp/stream_sched.c
··· 124 124 sctp_sched_ops_fcfs_init(); 125 125 sctp_sched_ops_prio_init(); 126 126 sctp_sched_ops_rr_init(); 127 + sctp_sched_ops_fc_init(); 128 + sctp_sched_ops_wfq_init(); 127 129 } 128 130 129 131 static void sctp_sched_free_sched(struct sctp_stream *stream)
+225
net/sctp/stream_sched_fc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* SCTP kernel implementation 3 + * (C) Copyright Red Hat Inc. 2022 4 + * 5 + * This file is part of the SCTP kernel implementation 6 + * 7 + * These functions manipulate sctp stream queue/scheduling. 8 + * 9 + * Please send any bug reports or fixes you make to the 10 + * email addresched(es): 11 + * lksctp developers <linux-sctp@vger.kernel.org> 12 + * 13 + * Written or modified by: 14 + * Xin Long <lucien.xin@gmail.com> 15 + */ 16 + 17 + #include <linux/list.h> 18 + #include <net/sctp/sctp.h> 19 + #include <net/sctp/sm.h> 20 + #include <net/sctp/stream_sched.h> 21 + 22 + /* Fair Capacity and Weighted Fair Queueing handling 23 + * RFC 8260 section 3.5 and 3.6 24 + */ 25 + static void sctp_sched_fc_unsched_all(struct sctp_stream *stream); 26 + 27 + static int sctp_sched_wfq_set(struct sctp_stream *stream, __u16 sid, 28 + __u16 weight, gfp_t gfp) 29 + { 30 + struct sctp_stream_out_ext *soute = SCTP_SO(stream, sid)->ext; 31 + 32 + if (!weight) 33 + return -EINVAL; 34 + 35 + soute->fc_weight = weight; 36 + return 0; 37 + } 38 + 39 + static int sctp_sched_wfq_get(struct sctp_stream *stream, __u16 sid, 40 + __u16 *value) 41 + { 42 + struct sctp_stream_out_ext *soute = SCTP_SO(stream, sid)->ext; 43 + 44 + *value = soute->fc_weight; 45 + return 0; 46 + } 47 + 48 + static int sctp_sched_fc_set(struct sctp_stream *stream, __u16 sid, 49 + __u16 weight, gfp_t gfp) 50 + { 51 + return 0; 52 + } 53 + 54 + static int sctp_sched_fc_get(struct sctp_stream *stream, __u16 sid, 55 + __u16 *value) 56 + { 57 + return 0; 58 + } 59 + 60 + static int sctp_sched_fc_init(struct sctp_stream *stream) 61 + { 62 + INIT_LIST_HEAD(&stream->fc_list); 63 + 64 + return 0; 65 + } 66 + 67 + static int sctp_sched_fc_init_sid(struct sctp_stream *stream, __u16 sid, 68 + gfp_t gfp) 69 + { 70 + struct sctp_stream_out_ext *soute = SCTP_SO(stream, sid)->ext; 71 + 72 + INIT_LIST_HEAD(&soute->fc_list); 73 + soute->fc_length = 0; 74 + soute->fc_weight = 1; 75 + 76 + return 0; 77 + } 78 + 79 + static void sctp_sched_fc_free_sid(struct sctp_stream *stream, __u16 sid) 80 + { 81 + } 82 + 83 + static void sctp_sched_fc_sched(struct sctp_stream *stream, 84 + struct sctp_stream_out_ext *soute) 85 + { 86 + struct sctp_stream_out_ext *pos; 87 + 88 + if (!list_empty(&soute->fc_list)) 89 + return; 90 + 91 + list_for_each_entry(pos, &stream->fc_list, fc_list) 92 + if ((__u64)pos->fc_length * soute->fc_weight >= 93 + (__u64)soute->fc_length * pos->fc_weight) 94 + break; 95 + list_add_tail(&soute->fc_list, &pos->fc_list); 96 + } 97 + 98 + static void sctp_sched_fc_enqueue(struct sctp_outq *q, 99 + struct sctp_datamsg *msg) 100 + { 101 + struct sctp_stream *stream; 102 + struct sctp_chunk *ch; 103 + __u16 sid; 104 + 105 + ch = list_first_entry(&msg->chunks, struct sctp_chunk, frag_list); 106 + sid = sctp_chunk_stream_no(ch); 107 + stream = &q->asoc->stream; 108 + sctp_sched_fc_sched(stream, SCTP_SO(stream, sid)->ext); 109 + } 110 + 111 + static struct sctp_chunk *sctp_sched_fc_dequeue(struct sctp_outq *q) 112 + { 113 + struct sctp_stream *stream = &q->asoc->stream; 114 + struct sctp_stream_out_ext *soute; 115 + struct sctp_chunk *ch; 116 + 117 + /* Bail out quickly if queue is empty */ 118 + if (list_empty(&q->out_chunk_list)) 119 + return NULL; 120 + 121 + /* Find which chunk is next */ 122 + if (stream->out_curr) 123 + soute = stream->out_curr->ext; 124 + else 125 + soute = list_entry(stream->fc_list.next, struct sctp_stream_out_ext, fc_list); 126 + ch = list_entry(soute->outq.next, struct sctp_chunk, stream_list); 127 + 128 + sctp_sched_dequeue_common(q, ch); 129 + return ch; 130 + } 131 + 132 + static void sctp_sched_fc_dequeue_done(struct sctp_outq *q, 133 + struct sctp_chunk *ch) 134 + { 135 + struct sctp_stream *stream = &q->asoc->stream; 136 + struct sctp_stream_out_ext *soute, *pos; 137 + __u16 sid, i; 138 + 139 + sid = sctp_chunk_stream_no(ch); 140 + soute = SCTP_SO(stream, sid)->ext; 141 + /* reduce all fc_lengths by U32_MAX / 4 if the current fc_length overflows. */ 142 + if (soute->fc_length > U32_MAX - ch->skb->len) { 143 + for (i = 0; i < stream->outcnt; i++) { 144 + pos = SCTP_SO(stream, i)->ext; 145 + if (!pos) 146 + continue; 147 + if (pos->fc_length <= (U32_MAX >> 2)) { 148 + pos->fc_length = 0; 149 + continue; 150 + } 151 + pos->fc_length -= (U32_MAX >> 2); 152 + } 153 + } 154 + soute->fc_length += ch->skb->len; 155 + 156 + if (list_empty(&soute->outq)) { 157 + list_del_init(&soute->fc_list); 158 + return; 159 + } 160 + 161 + pos = soute; 162 + list_for_each_entry_continue(pos, &stream->fc_list, fc_list) 163 + if ((__u64)pos->fc_length * soute->fc_weight >= 164 + (__u64)soute->fc_length * pos->fc_weight) 165 + break; 166 + list_move_tail(&soute->fc_list, &pos->fc_list); 167 + } 168 + 169 + static void sctp_sched_fc_sched_all(struct sctp_stream *stream) 170 + { 171 + struct sctp_association *asoc; 172 + struct sctp_chunk *ch; 173 + 174 + asoc = container_of(stream, struct sctp_association, stream); 175 + list_for_each_entry(ch, &asoc->outqueue.out_chunk_list, list) { 176 + __u16 sid = sctp_chunk_stream_no(ch); 177 + 178 + if (SCTP_SO(stream, sid)->ext) 179 + sctp_sched_fc_sched(stream, SCTP_SO(stream, sid)->ext); 180 + } 181 + } 182 + 183 + static void sctp_sched_fc_unsched_all(struct sctp_stream *stream) 184 + { 185 + struct sctp_stream_out_ext *soute, *tmp; 186 + 187 + list_for_each_entry_safe(soute, tmp, &stream->fc_list, fc_list) 188 + list_del_init(&soute->fc_list); 189 + } 190 + 191 + static struct sctp_sched_ops sctp_sched_fc = { 192 + .set = sctp_sched_fc_set, 193 + .get = sctp_sched_fc_get, 194 + .init = sctp_sched_fc_init, 195 + .init_sid = sctp_sched_fc_init_sid, 196 + .free_sid = sctp_sched_fc_free_sid, 197 + .enqueue = sctp_sched_fc_enqueue, 198 + .dequeue = sctp_sched_fc_dequeue, 199 + .dequeue_done = sctp_sched_fc_dequeue_done, 200 + .sched_all = sctp_sched_fc_sched_all, 201 + .unsched_all = sctp_sched_fc_unsched_all, 202 + }; 203 + 204 + void sctp_sched_ops_fc_init(void) 205 + { 206 + sctp_sched_ops_register(SCTP_SS_FC, &sctp_sched_fc); 207 + } 208 + 209 + static struct sctp_sched_ops sctp_sched_wfq = { 210 + .set = sctp_sched_wfq_set, 211 + .get = sctp_sched_wfq_get, 212 + .init = sctp_sched_fc_init, 213 + .init_sid = sctp_sched_fc_init_sid, 214 + .free_sid = sctp_sched_fc_free_sid, 215 + .enqueue = sctp_sched_fc_enqueue, 216 + .dequeue = sctp_sched_fc_dequeue, 217 + .dequeue_done = sctp_sched_fc_dequeue_done, 218 + .sched_all = sctp_sched_fc_sched_all, 219 + .unsched_all = sctp_sched_fc_unsched_all, 220 + }; 221 + 222 + void sctp_sched_ops_wfq_init(void) 223 + { 224 + sctp_sched_ops_register(SCTP_SS_WFQ, &sctp_sched_wfq); 225 + }