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

sctp: add weighted fair queueing stream scheduler

As it says in rfc8260#section-3.6 about the weighted fair queueing
scheduler:

A Weighted Fair Queueing scheduler between the streams is used. The
weight is configurable per outgoing SCTP stream. This scheduler
considers the lengths of the messages of each stream and schedules
them in a specific way to use the capacity according to the given
weights. If the weight of stream S1 is n times the weight of stream
S2, the scheduler should assign to stream S1 n times the capacity it
assigns to stream S2. The details are implementation dependent.
Interleaving user messages allows for a better realization of the
capacity usage according to the given weights.

This patch adds Weighted Fair Queueing Scheduler actually based on
the code of Fair Capacity Scheduler by adding fc_weight into struct
sctp_stream_out_ext and taking it into account when sorting stream->
fc_list in sctp_sched_fc_sched() and sctp_sched_fc_dequeue_done().

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Xin Long and committed by
Paolo Abeni
42d452e7 4821a076

+51 -5
+1
include/net/sctp/stream_sched.h
··· 59 59 void sctp_sched_ops_prio_init(void); 60 60 void sctp_sched_ops_rr_init(void); 61 61 void sctp_sched_ops_fc_init(void); 62 + void sctp_sched_ops_wfq_init(void); 62 63 63 64 #endif /* __sctp_stream_sched_h__ */
+1
include/net/sctp/structs.h
··· 1432 1432 struct { 1433 1433 struct list_head fc_list; 1434 1434 __u32 fc_length; 1435 + __u16 fc_weight; 1435 1436 }; 1436 1437 }; 1437 1438 };
+2 -1
include/uapi/linux/sctp.h
··· 1212 1212 SCTP_SS_PRIO, 1213 1213 SCTP_SS_RR, 1214 1214 SCTP_SS_FC, 1215 - SCTP_SS_MAX = SCTP_SS_FC 1215 + SCTP_SS_WFQ, 1216 + SCTP_SS_MAX = SCTP_SS_WFQ 1216 1217 }; 1217 1218 1218 1219 /* Probe Interval socket option */
+1
net/sctp/stream_sched.c
··· 125 125 sctp_sched_ops_prio_init(); 126 126 sctp_sched_ops_rr_init(); 127 127 sctp_sched_ops_fc_init(); 128 + sctp_sched_ops_wfq_init(); 128 129 } 129 130 130 131 static void sctp_sched_free_sched(struct sctp_stream *stream)
+46 -4
net/sctp/stream_sched_fc.c
··· 19 19 #include <net/sctp/sm.h> 20 20 #include <net/sctp/stream_sched.h> 21 21 22 - /* Fair Capacity handling 23 - * RFC 8260 section 3.5 22 + /* Fair Capacity and Weighted Fair Queueing handling 23 + * RFC 8260 section 3.5 and 3.6 24 24 */ 25 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 + } 26 47 27 48 static int sctp_sched_fc_set(struct sctp_stream *stream, __u16 sid, 28 49 __u16 weight, gfp_t gfp) ··· 71 50 72 51 INIT_LIST_HEAD(&soute->fc_list); 73 52 soute->fc_length = 0; 53 + soute->fc_weight = 1; 74 54 75 55 return 0; 76 56 } ··· 89 67 return; 90 68 91 69 list_for_each_entry(pos, &stream->fc_list, fc_list) 92 - if (pos->fc_length >= soute->fc_length) 70 + if ((__u64)pos->fc_length * soute->fc_weight >= 71 + (__u64)soute->fc_length * pos->fc_weight) 93 72 break; 94 73 list_add_tail(&soute->fc_list, &pos->fc_list); 95 74 } ··· 160 137 161 138 pos = soute; 162 139 list_for_each_entry_continue(pos, &stream->fc_list, fc_list) 163 - if (pos->fc_length >= soute->fc_length) 140 + if ((__u64)pos->fc_length * soute->fc_weight >= 141 + (__u64)soute->fc_length * pos->fc_weight) 164 142 break; 165 143 list_move_tail(&soute->fc_list, &pos->fc_list); 166 144 } ··· 204 180 void sctp_sched_ops_fc_init(void) 205 181 { 206 182 sctp_sched_ops_register(SCTP_SS_FC, &sctp_sched_fc); 183 + } 184 + 185 + static struct sctp_sched_ops sctp_sched_wfq = { 186 + .set = sctp_sched_wfq_set, 187 + .get = sctp_sched_wfq_get, 188 + .init = sctp_sched_fc_init, 189 + .init_sid = sctp_sched_fc_init_sid, 190 + .free_sid = sctp_sched_fc_free_sid, 191 + .enqueue = sctp_sched_fc_enqueue, 192 + .dequeue = sctp_sched_fc_dequeue, 193 + .dequeue_done = sctp_sched_fc_dequeue_done, 194 + .sched_all = sctp_sched_fc_sched_all, 195 + .unsched_all = sctp_sched_fc_unsched_all, 196 + }; 197 + 198 + void sctp_sched_ops_wfq_init(void) 199 + { 200 + sctp_sched_ops_register(SCTP_SS_WFQ, &sctp_sched_wfq); 207 201 }