Skip to content

Commit

Permalink
Merge branch 'sctp-stream-schedulers'
Browse files Browse the repository at this point in the history
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 <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 3, 2017
2 parents af14827 + ac1ed8b commit 2687330
Show file tree
Hide file tree
Showing 12 changed files with 1,347 additions and 77 deletions.
72 changes: 72 additions & 0 deletions include/net/sctp/stream_sched.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* SCTP kernel implementation
* (C) Copyright Red Hat Inc. 2017
*
* These are definitions used by the stream schedulers, defined in RFC
* draft ndata (https://tools.ietf.org/html/draft-ietf-tsvwg-sctp-ndata-11)
*
* This SCTP implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This SCTP implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
* Please send any bug reports or fixes you make to the
* email addresses:
* lksctp developers <linux-sctp@vger.kernel.org>
*
* Written or modified by:
* Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
*/

#ifndef __sctp_stream_sched_h__
#define __sctp_stream_sched_h__

struct sctp_sched_ops {
/* Property handling for a given stream */
int (*set)(struct sctp_stream *stream, __u16 sid, __u16 value,
gfp_t gfp);
int (*get)(struct sctp_stream *stream, __u16 sid, __u16 *value);

/* Init the specific scheduler */
int (*init)(struct sctp_stream *stream);
/* Init a stream */
int (*init_sid)(struct sctp_stream *stream, __u16 sid, gfp_t gfp);
/* Frees the entire thing */
void (*free)(struct sctp_stream *stream);

/* Enqueue a chunk */
void (*enqueue)(struct sctp_outq *q, struct sctp_datamsg *msg);
/* Dequeue a chunk */
struct sctp_chunk *(*dequeue)(struct sctp_outq *q);
/* Called only if the chunk fit the packet */
void (*dequeue_done)(struct sctp_outq *q, struct sctp_chunk *chunk);
/* Sched all chunks already enqueued */
void (*sched_all)(struct sctp_stream *steam);
/* Unched all chunks already enqueued */
void (*unsched_all)(struct sctp_stream *steam);
};

int sctp_sched_set_sched(struct sctp_association *asoc,
enum sctp_sched_type sched);
int sctp_sched_get_sched(struct sctp_association *asoc);
int sctp_sched_set_value(struct sctp_association *asoc, __u16 sid,
__u16 value, gfp_t gfp);
int sctp_sched_get_value(struct sctp_association *asoc, __u16 sid,
__u16 *value);
void sctp_sched_dequeue_done(struct sctp_outq *q, struct sctp_chunk *ch);

void sctp_sched_dequeue_common(struct sctp_outq *q, struct sctp_chunk *ch);
int sctp_sched_init_sid(struct sctp_stream *stream, __u16 sid, gfp_t gfp);
struct sctp_sched_ops *sctp_sched_ops_from_stream(struct sctp_stream *stream);

#endif /* __sctp_stream_sched_h__ */
63 changes: 59 additions & 4 deletions include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ struct sctp_sender_hb_info {

int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
gfp_t gfp);
int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid);
void sctp_stream_free(struct sctp_stream *stream);
void sctp_stream_clear(struct sctp_stream *stream);
void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);
Expand Down Expand Up @@ -529,8 +530,12 @@ struct sctp_chunk {
/* How many times this chunk have been sent, for prsctp RTX policy */
int sent_count;

/* This is our link to the per-transport transmitted list. */
struct list_head transmitted_list;
union {
/* This is our link to the per-transport transmitted list. */
struct list_head transmitted_list;
/* List in specific stream outq */
struct list_head stream_list;
};

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

static inline __u16 sctp_chunk_stream_no(struct sctp_chunk *ch)
{
return ntohs(ch->subh.data_hdr->stream);
}

enum {
SCTP_ADDR_NEW, /* new address added to assoc/ep */
SCTP_ADDR_SRC, /* address can be used as source */
Expand Down Expand Up @@ -1012,6 +1022,9 @@ struct sctp_outq {
/* Data pending that has never been transmitted. */
struct list_head out_chunk_list;

/* Stream scheduler being used */
struct sctp_sched_ops *sched;

unsigned int out_qlen; /* Total length of queued data chunks. */

/* Error of send failed, may used in SCTP_SEND_FAILED event. */
Expand Down Expand Up @@ -1315,11 +1328,37 @@ struct sctp_inithdr_host {
__u32 initial_tsn;
};

struct sctp_stream_priorities {
/* List of priorities scheduled */
struct list_head prio_sched;
/* List of streams scheduled */
struct list_head active;
/* The next stream stream in line */
struct sctp_stream_out_ext *next;
__u16 prio;
};

struct sctp_stream_out_ext {
__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
struct list_head outq; /* chunks enqueued by this stream */
union {
struct {
/* Scheduled streams list */
struct list_head prio_list;
struct sctp_stream_priorities *prio_head;
};
/* Fields used by RR scheduler */
struct {
struct list_head rr_list;
};
};
};

struct sctp_stream_out {
__u16 ssn;
__u8 state;
__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
struct sctp_stream_out_ext *ext;
};

struct sctp_stream_in {
Expand All @@ -1331,6 +1370,22 @@ struct sctp_stream {
struct sctp_stream_in *in;
__u16 outcnt;
__u16 incnt;
/* Current stream being sent, if any */
struct sctp_stream_out *out_curr;
union {
/* Fields used by priority scheduler */
struct {
/* List of priorities scheduled */
struct list_head prio_list;
};
/* Fields used by RR scheduler */
struct {
/* List of streams scheduled */
struct list_head rr_list;
/* The next stream stream in line */
struct sctp_stream_out_ext *rr_next;
};
};
};

#define SCTP_STREAM_CLOSED 0x00
Expand Down
16 changes: 16 additions & 0 deletions include/uapi/linux/sctp.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ typedef __s32 sctp_assoc_t;
#define SCTP_RESET_ASSOC 120
#define SCTP_ADD_STREAMS 121
#define SCTP_SOCKOPT_PEELOFF_FLAGS 122
#define SCTP_STREAM_SCHEDULER 123
#define SCTP_STREAM_SCHEDULER_VALUE 124

/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
Expand Down Expand Up @@ -814,6 +816,12 @@ struct sctp_assoc_value {
uint32_t assoc_value;
};

struct sctp_stream_value {
sctp_assoc_t assoc_id;
uint16_t stream_id;
uint16_t stream_value;
};

/*
* 7.2.2 Peer Address Information
*
Expand Down Expand Up @@ -1088,4 +1096,12 @@ struct sctp_add_streams {
uint16_t sas_outstrms;
};

/* SCTP Stream schedulers */
enum sctp_sched_type {
SCTP_SS_FCFS,
SCTP_SS_PRIO,
SCTP_SS_RR,
SCTP_SS_MAX = SCTP_SS_RR
};

#endif /* _UAPI_SCTP_H */
3 changes: 2 additions & 1 deletion net/sctp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
inqueue.o outqueue.o ulpqueue.o \
tsnmap.o bind_addr.o socket.o primitive.o \
output.o input.o debug.o stream.o auth.o \
offload.o
offload.o stream_sched.o stream_sched_prio.o \
stream_sched_rr.o

sctp_probe-y := probe.o

Expand Down
6 changes: 3 additions & 3 deletions net/sctp/chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,10 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)

if (chunk->sent_count) {
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
streamout->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
streamout->ext->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
} else {
chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
streamout->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
streamout->ext->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
}
return 1;
} else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
Expand All @@ -323,7 +323,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
&chunk->asoc->stream.out[chunk->sinfo.sinfo_stream];

chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
streamout->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
return 1;
} else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
chunk->msg->expires_at &&
Expand Down
Loading

0 comments on commit 2687330

Please sign in to comment.