Skip to content

Commit 2687330

Browse files
committed
Merge branch 'sctp-stream-schedulers'
Marcelo Ricardo Leitner says: ==================== Introduce SCTP Stream Schedulers This patchset introduces the SCTP Stream Schedulers are defined by https://tools.ietf.org/html/draft-ietf-tsvwg-sctp-ndata-13 It provides 3 schedulers at the moment: FCFS, Priority and Round Robin. The other 3, Round Robin per packet, Fair Capacity and Weighted Fair Capacity will be added later. More specifically, WFQ is required by WebRTC Datachannels. The draft also defines the idata chunk, allowing a usermsg to be interrupted by another piece of idata from another stream. This patchset *doesn't* include it. It will be posted later by Xin Long. Its integration with this patchset is very simple and it basically only requires a tweak in sctp_sched_dequeue_done(), to ignore datamsg boundaries. The first 5 patches are a preparation for the next ones. The most relevant patches are the 4th and 6th ones. More details are available on each patch. v2: changelog update on patch 3 ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents af14827 + ac1ed8b commit 2687330

File tree

12 files changed

+1347
-77
lines changed

12 files changed

+1347
-77
lines changed

include/net/sctp/stream_sched.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* SCTP kernel implementation
2+
* (C) Copyright Red Hat Inc. 2017
3+
*
4+
* These are definitions used by the stream schedulers, defined in RFC
5+
* draft ndata (https://tools.ietf.org/html/draft-ietf-tsvwg-sctp-ndata-11)
6+
*
7+
* This SCTP implementation is free software;
8+
* you can redistribute it and/or modify it under the terms of
9+
* the GNU General Public License as published by
10+
* the Free Software Foundation; either version 2, or (at your option)
11+
* any later version.
12+
*
13+
* This SCTP implementation is distributed in the hope that it
14+
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
15+
* ************************
16+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17+
* See the GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with GNU CC; see the file COPYING. If not, see
21+
* <http://www.gnu.org/licenses/>.
22+
*
23+
* Please send any bug reports or fixes you make to the
24+
* email addresses:
25+
* lksctp developers <[email protected]>
26+
*
27+
* Written or modified by:
28+
* Marcelo Ricardo Leitner <[email protected]>
29+
*/
30+
31+
#ifndef __sctp_stream_sched_h__
32+
#define __sctp_stream_sched_h__
33+
34+
struct sctp_sched_ops {
35+
/* Property handling for a given stream */
36+
int (*set)(struct sctp_stream *stream, __u16 sid, __u16 value,
37+
gfp_t gfp);
38+
int (*get)(struct sctp_stream *stream, __u16 sid, __u16 *value);
39+
40+
/* Init the specific scheduler */
41+
int (*init)(struct sctp_stream *stream);
42+
/* Init a stream */
43+
int (*init_sid)(struct sctp_stream *stream, __u16 sid, gfp_t gfp);
44+
/* Frees the entire thing */
45+
void (*free)(struct sctp_stream *stream);
46+
47+
/* Enqueue a chunk */
48+
void (*enqueue)(struct sctp_outq *q, struct sctp_datamsg *msg);
49+
/* Dequeue a chunk */
50+
struct sctp_chunk *(*dequeue)(struct sctp_outq *q);
51+
/* Called only if the chunk fit the packet */
52+
void (*dequeue_done)(struct sctp_outq *q, struct sctp_chunk *chunk);
53+
/* Sched all chunks already enqueued */
54+
void (*sched_all)(struct sctp_stream *steam);
55+
/* Unched all chunks already enqueued */
56+
void (*unsched_all)(struct sctp_stream *steam);
57+
};
58+
59+
int sctp_sched_set_sched(struct sctp_association *asoc,
60+
enum sctp_sched_type sched);
61+
int sctp_sched_get_sched(struct sctp_association *asoc);
62+
int sctp_sched_set_value(struct sctp_association *asoc, __u16 sid,
63+
__u16 value, gfp_t gfp);
64+
int sctp_sched_get_value(struct sctp_association *asoc, __u16 sid,
65+
__u16 *value);
66+
void sctp_sched_dequeue_done(struct sctp_outq *q, struct sctp_chunk *ch);
67+
68+
void sctp_sched_dequeue_common(struct sctp_outq *q, struct sctp_chunk *ch);
69+
int sctp_sched_init_sid(struct sctp_stream *stream, __u16 sid, gfp_t gfp);
70+
struct sctp_sched_ops *sctp_sched_ops_from_stream(struct sctp_stream *stream);
71+
72+
#endif /* __sctp_stream_sched_h__ */

include/net/sctp/structs.h

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ struct sctp_sender_hb_info {
380380

381381
int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
382382
gfp_t gfp);
383+
int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid);
383384
void sctp_stream_free(struct sctp_stream *stream);
384385
void sctp_stream_clear(struct sctp_stream *stream);
385386
void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);
@@ -529,8 +530,12 @@ struct sctp_chunk {
529530
/* How many times this chunk have been sent, for prsctp RTX policy */
530531
int sent_count;
531532

532-
/* This is our link to the per-transport transmitted list. */
533-
struct list_head transmitted_list;
533+
union {
534+
/* This is our link to the per-transport transmitted list. */
535+
struct list_head transmitted_list;
536+
/* List in specific stream outq */
537+
struct list_head stream_list;
538+
};
534539

535540
/* This field is used by chunks that hold fragmented data.
536541
* For the first fragment this is the list that holds the rest of
@@ -640,6 +645,11 @@ void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
640645
union sctp_addr *);
641646
const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
642647

648+
static inline __u16 sctp_chunk_stream_no(struct sctp_chunk *ch)
649+
{
650+
return ntohs(ch->subh.data_hdr->stream);
651+
}
652+
643653
enum {
644654
SCTP_ADDR_NEW, /* new address added to assoc/ep */
645655
SCTP_ADDR_SRC, /* address can be used as source */
@@ -1012,6 +1022,9 @@ struct sctp_outq {
10121022
/* Data pending that has never been transmitted. */
10131023
struct list_head out_chunk_list;
10141024

1025+
/* Stream scheduler being used */
1026+
struct sctp_sched_ops *sched;
1027+
10151028
unsigned int out_qlen; /* Total length of queued data chunks. */
10161029

10171030
/* Error of send failed, may used in SCTP_SEND_FAILED event. */
@@ -1315,11 +1328,37 @@ struct sctp_inithdr_host {
13151328
__u32 initial_tsn;
13161329
};
13171330

1331+
struct sctp_stream_priorities {
1332+
/* List of priorities scheduled */
1333+
struct list_head prio_sched;
1334+
/* List of streams scheduled */
1335+
struct list_head active;
1336+
/* The next stream stream in line */
1337+
struct sctp_stream_out_ext *next;
1338+
__u16 prio;
1339+
};
1340+
1341+
struct sctp_stream_out_ext {
1342+
__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
1343+
__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
1344+
struct list_head outq; /* chunks enqueued by this stream */
1345+
union {
1346+
struct {
1347+
/* Scheduled streams list */
1348+
struct list_head prio_list;
1349+
struct sctp_stream_priorities *prio_head;
1350+
};
1351+
/* Fields used by RR scheduler */
1352+
struct {
1353+
struct list_head rr_list;
1354+
};
1355+
};
1356+
};
1357+
13181358
struct sctp_stream_out {
13191359
__u16 ssn;
13201360
__u8 state;
1321-
__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
1322-
__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
1361+
struct sctp_stream_out_ext *ext;
13231362
};
13241363

13251364
struct sctp_stream_in {
@@ -1331,6 +1370,22 @@ struct sctp_stream {
13311370
struct sctp_stream_in *in;
13321371
__u16 outcnt;
13331372
__u16 incnt;
1373+
/* Current stream being sent, if any */
1374+
struct sctp_stream_out *out_curr;
1375+
union {
1376+
/* Fields used by priority scheduler */
1377+
struct {
1378+
/* List of priorities scheduled */
1379+
struct list_head prio_list;
1380+
};
1381+
/* Fields used by RR scheduler */
1382+
struct {
1383+
/* List of streams scheduled */
1384+
struct list_head rr_list;
1385+
/* The next stream stream in line */
1386+
struct sctp_stream_out_ext *rr_next;
1387+
};
1388+
};
13341389
};
13351390

13361391
#define SCTP_STREAM_CLOSED 0x00

include/uapi/linux/sctp.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ typedef __s32 sctp_assoc_t;
122122
#define SCTP_RESET_ASSOC 120
123123
#define SCTP_ADD_STREAMS 121
124124
#define SCTP_SOCKOPT_PEELOFF_FLAGS 122
125+
#define SCTP_STREAM_SCHEDULER 123
126+
#define SCTP_STREAM_SCHEDULER_VALUE 124
125127

126128
/* PR-SCTP policies */
127129
#define SCTP_PR_SCTP_NONE 0x0000
@@ -814,6 +816,12 @@ struct sctp_assoc_value {
814816
uint32_t assoc_value;
815817
};
816818

819+
struct sctp_stream_value {
820+
sctp_assoc_t assoc_id;
821+
uint16_t stream_id;
822+
uint16_t stream_value;
823+
};
824+
817825
/*
818826
* 7.2.2 Peer Address Information
819827
*
@@ -1088,4 +1096,12 @@ struct sctp_add_streams {
10881096
uint16_t sas_outstrms;
10891097
};
10901098

1099+
/* SCTP Stream schedulers */
1100+
enum sctp_sched_type {
1101+
SCTP_SS_FCFS,
1102+
SCTP_SS_PRIO,
1103+
SCTP_SS_RR,
1104+
SCTP_SS_MAX = SCTP_SS_RR
1105+
};
1106+
10911107
#endif /* _UAPI_SCTP_H */

net/sctp/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
1212
inqueue.o outqueue.o ulpqueue.o \
1313
tsnmap.o bind_addr.o socket.o primitive.o \
1414
output.o input.o debug.o stream.o auth.o \
15-
offload.o
15+
offload.o stream_sched.o stream_sched_prio.o \
16+
stream_sched_rr.o
1617

1718
sctp_probe-y := probe.o
1819

net/sctp/chunk.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,10 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
311311

312312
if (chunk->sent_count) {
313313
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
314-
streamout->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
314+
streamout->ext->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
315315
} else {
316316
chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
317-
streamout->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
317+
streamout->ext->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
318318
}
319319
return 1;
320320
} else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
@@ -323,7 +323,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
323323
&chunk->asoc->stream.out[chunk->sinfo.sinfo_stream];
324324

325325
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
326-
streamout->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
326+
streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
327327
return 1;
328328
} else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
329329
chunk->msg->expires_at &&

0 commit comments

Comments
 (0)