Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b3b87077 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sctp-stream-interleave'



Xin Long says:

====================
sctp: Implement Stream Interleave: Interaction with Other SCTP Extensions

Stream Interleave would be implemented in two Parts:

   1. The I-DATA Chunk Supporting User Message Interleaving
   2. Interaction with Other SCTP Extensions

Overview in section 2.3 of RFC8260 for Part 2:

   The usage of the I-DATA chunk might interfere with other SCTP
   extensions.  Future SCTP extensions MUST describe if and how they
   interfere with the usage of I-DATA chunks.  For the SCTP extensions
   already defined when this document was published, the details are
   given in the following subsections.

As the 2nd part of Stream Interleave Implementation, this patchset mostly
adds the support for SCTP Partial Reliability Extension with I-FORWARD-TSN
chunk. Then adjusts stream scheduler and stream reconfig to make them work
properly with I-DATA chunks.

In the last patch, all stream interleave codes will be enabled by adding
sysctl to allow users to use this feature.

v1 -> v2:
  - removed the intl_enable check from sctp_chunk_event_lookup, as Marcelo's
    suggestion.
  - fixed a typo in changelog.
====================

Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 02477809 463118c3
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ enum sctp_cid {

	/* Use hex, as defined in ADDIP sec. 3.1 */
	SCTP_CID_ASCONF			= 0xC1,
	SCTP_CID_I_FWD_TSN		= 0xC2,
	SCTP_CID_ASCONF_ACK		= 0x80,
	SCTP_CID_RECONF			= 0x82,
}; /* enum */
@@ -616,6 +617,22 @@ struct sctp_fwdtsn_chunk {
	struct sctp_fwdtsn_hdr fwdtsn_hdr;
};

struct sctp_ifwdtsn_skip {
	__be16 stream;
	__u8 reserved;
	__u8 flags;
	__be32 mid;
};

struct sctp_ifwdtsn_hdr {
	__be32 new_cum_tsn;
	struct sctp_ifwdtsn_skip skip[0];
};

struct sctp_ifwdtsn_chunk {
	struct sctp_chunkhdr chunk_hdr;
	struct sctp_ifwdtsn_hdr fwdtsn_hdr;
};

/* ADDIP
 * Section 3.1.1 Address Configuration Change Chunk (ASCONF)
+3 −0
Original line number Diff line number Diff line
@@ -199,6 +199,9 @@ struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc,
				 const struct sctp_chunk *chunk);
struct sctp_chunk *sctp_make_idata(const struct sctp_association *asoc,
				   __u8 flags, int paylen, gfp_t gfp);
struct sctp_chunk *sctp_make_ifwdtsn(const struct sctp_association *asoc,
				     __u32 new_cum_tsn, size_t nstreams,
				     struct sctp_ifwdtsn_skip *skiplist);
struct sctp_chunk *sctp_make_datafrag_empty(const struct sctp_association *asoc,
					    const struct sctp_sndrcvinfo *sinfo,
					    int len, __u8 flags, gfp_t gfp);
+7 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@

struct sctp_stream_interleave {
	__u16	data_chunk_len;
	__u16	ftsn_chunk_len;
	/* (I-)DATA process */
	struct sctp_chunk *(*make_datafrag)(const struct sctp_association *asoc,
					    const struct sctp_sndrcvinfo *sinfo,
@@ -47,6 +48,12 @@ struct sctp_stream_interleave {
				 struct sctp_chunk *chunk, gfp_t gfp);
	void	(*start_pd)(struct sctp_ulpq *ulpq, gfp_t gfp);
	void	(*abort_pd)(struct sctp_ulpq *ulpq, gfp_t gfp);
	/* (I-)FORWARD-TSN process */
	void	(*generate_ftsn)(struct sctp_outq *q, __u32 ctsn);
	bool	(*validate_ftsn)(struct sctp_chunk *chunk);
	void	(*report_ftsn)(struct sctp_ulpq *ulpq, __u32 ftsn);
	void	(*handle_ftsn)(struct sctp_ulpq *ulpq,
			       struct sctp_chunk *chunk);
};

void sctp_stream_interleave_init(struct sctp_stream *stream);
+12 −0
Original line number Diff line number Diff line
@@ -599,6 +599,7 @@ struct sctp_chunk {
		struct sctp_fwdtsn_hdr *fwdtsn_hdr;
		struct sctp_authhdr *auth_hdr;
		struct sctp_idatahdr *idata_hdr;
		struct sctp_ifwdtsn_hdr *ifwdtsn_hdr;
	} subh;

	__u8 *chunk_end;
@@ -1099,6 +1100,7 @@ void sctp_retransmit_mark(struct sctp_outq *, struct sctp_transport *, __u8);
void sctp_outq_uncork(struct sctp_outq *, gfp_t gfp);
void sctp_prsctp_prune(struct sctp_association *asoc,
		       struct sctp_sndrcvinfo *sinfo, int msg_len);
void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);
/* Uncork and flush an outqueue.  */
static inline void sctp_outq_cork(struct sctp_outq *q)
{
@@ -1441,6 +1443,16 @@ static inline __u16 sctp_datahdr_len(const struct sctp_stream *stream)
	return stream->si->data_chunk_len - sizeof(struct sctp_chunkhdr);
}

static inline __u16 sctp_ftsnchk_len(const struct sctp_stream *stream)
{
	return stream->si->ftsn_chunk_len;
}

static inline __u16 sctp_ftsnhdr_len(const struct sctp_stream *stream)
{
	return stream->si->ftsn_chunk_len - sizeof(struct sctp_chunkhdr);
}

/* SCTP_GET_ASSOC_STATS counters */
struct sctp_priv_assoc_stats {
	/* Maximum observed rto in the association during subsequent
+6 −6
Original line number Diff line number Diff line
@@ -67,8 +67,6 @@ static void sctp_mark_missing(struct sctp_outq *q,
			      __u32 highest_new_tsn,
			      int count_of_newacks);

static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);

static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp);

/* Add data to the front of the queue. */
@@ -591,7 +589,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
	 * following the procedures outlined in C1 - C5.
	 */
	if (reason == SCTP_RTXR_T3_RTX)
		sctp_generate_fwdtsn(q, q->asoc->ctsn_ack_point);
		q->asoc->stream.si->generate_ftsn(q, q->asoc->ctsn_ack_point);

	/* Flush the queues only on timeout, since fast_rtx is only
	 * triggered during sack processing and the queue
@@ -942,6 +940,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
		case SCTP_CID_ECN_ECNE:
		case SCTP_CID_ASCONF:
		case SCTP_CID_FWD_TSN:
		case SCTP_CID_I_FWD_TSN:
		case SCTP_CID_RECONF:
			status = sctp_packet_transmit_chunk(packet, chunk,
							    one_packet, gfp);
@@ -956,7 +955,8 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
			 * sender MUST assure that at least one T3-rtx
			 * timer is running.
			 */
			if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
			if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN ||
			    chunk->chunk_hdr->type == SCTP_CID_I_FWD_TSN) {
				sctp_transport_reset_t3_rtx(transport);
				transport->last_time_sent = jiffies;
			}
@@ -1372,7 +1372,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)

	asoc->peer.rwnd = sack_a_rwnd;

	sctp_generate_fwdtsn(q, sack_ctsn);
	asoc->stream.si->generate_ftsn(q, sack_ctsn);

	pr_debug("%s: sack cumulative tsn ack:0x%x\n", __func__, sack_ctsn);
	pr_debug("%s: cumulative tsn ack of assoc:%p is 0x%x, "
@@ -1795,7 +1795,7 @@ static inline int sctp_get_skip_pos(struct sctp_fwdtsn_skip *skiplist,
}

/* Create and add a fwdtsn chunk to the outq's control queue if needed. */
static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
{
	struct sctp_association *asoc = q->asoc;
	struct sctp_chunk *ftsn_chunk = NULL;
Loading