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

Merge branch 'sctp-rfc7496-support'



Xin Long says:

====================
sctp: implement rfc7496 in sctp

This patchset implements "Additional Policies for the Partially Reliable
Stream Control Transmission Protocol Extension" described on RFC7496.

The Partially Reliable SCTP (PR-SCTP) extension defined in [RFC3758]
provides a generic method for senders to abandon user messages. The
decision to abandon a user message is sender side only, and the exact
condition is called a "PR-SCTP policy". This patchset implements 3
policies:

 1. Timed Reliability:  This allows the sender to specify a timeout for
    a user message after which the SCTP stack abandons the user message.

 2. Limited Retransmission Policy:  Allows limitation of the number of
    retransmissions.

 3. Priority Policy:  Allows removal of lower-priority messages if space
    for higher-priority messages is needed in the send buffer.

Patch 1-3 add some sockopts in sctp to set/get pr_sctp policy status.
Patch 4-6 implement these 3 policies one by one.
====================

Acked-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bac65c4b 8dbdf1f5
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -602,6 +602,16 @@ struct sctp_chunk {
	/* This needs to be recoverable for SCTP_SEND_FAILED events. */
	struct sctp_sndrcvinfo sinfo;

	/* We use this field to record param for prsctp policies,
	 * for TTL policy, it is the time_to_drop of this chunk,
	 * for RTX policy, it is the max_sent_count of this chunk,
	 * for PRIO policy, it is the priority of this chunk.
	 */
	unsigned long prsctp_param;

	/* How many times this chunk have been sent, for prsctp RTX policy */
	int sent_count;

	/* Which association does this belong to?  */
	struct sctp_association *asoc;

@@ -1074,6 +1084,8 @@ void sctp_retransmit(struct sctp_outq *, struct sctp_transport *,
		     sctp_retransmit_reason_t);
void sctp_retransmit_mark(struct sctp_outq *, struct sctp_transport *, __u8);
int sctp_outq_uncork(struct sctp_outq *, gfp_t gfp);
void sctp_prsctp_prune(struct sctp_association *asoc,
		       struct sctp_sndrcvinfo *sinfo, int msg_len);
/* Uncork and flush an outqueue.  */
static inline void sctp_outq_cork(struct sctp_outq *q)
{
@@ -1256,7 +1268,8 @@ struct sctp_endpoint {
	/* SCTP-AUTH: endpoint shared keys */
	struct list_head endpoint_shared_keys;
	__u16 active_key_id;
	__u8  auth_enable;
	__u8  auth_enable:1,
	      prsctp_enable:1;
};

/* Recover the outter endpoint structure. */
@@ -1848,9 +1861,15 @@ struct sctp_association {
	__u16 active_key_id;

	__u8 need_ecne:1,	/* Need to send an ECNE Chunk? */
	     temp:1;		/* Is it a temporary association? */
	     temp:1,		/* Is it a temporary association? */
	     prsctp_enable:1;

	struct sctp_priv_assoc_stats stats;

	int sent_cnt_removable;

	__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
	__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
};


+42 −0
Original line number Diff line number Diff line
@@ -112,6 +112,31 @@ typedef __s32 sctp_assoc_t;
#define SCTP_SOCKOPT_CONNECTX	110		/* CONNECTX requests. */
#define SCTP_SOCKOPT_CONNECTX3	111	/* CONNECTX requests (updated) */
#define SCTP_GET_ASSOC_STATS	112	/* Read only */
#define SCTP_PR_SUPPORTED	113
#define SCTP_DEFAULT_PRINFO	114
#define SCTP_PR_ASSOC_STATUS	115

/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE	0x0000
#define SCTP_PR_SCTP_TTL	0x0010
#define SCTP_PR_SCTP_RTX	0x0020
#define SCTP_PR_SCTP_PRIO	0x0030
#define SCTP_PR_SCTP_MAX	SCTP_PR_SCTP_PRIO
#define SCTP_PR_SCTP_MASK	0x0030

#define __SCTP_PR_INDEX(x)	((x >> 4) - 1)
#define SCTP_PR_INDEX(x)	__SCTP_PR_INDEX(SCTP_PR_SCTP_ ## x)

#define SCTP_PR_POLICY(x)	((x) & SCTP_PR_SCTP_MASK)
#define SCTP_PR_SET_POLICY(flags, x)	\
	do {				\
		flags &= ~SCTP_PR_SCTP_MASK;	\
		flags |= x;		\
	} while (0)

#define SCTP_PR_TTL_ENABLED(x)	(SCTP_PR_POLICY(x) == SCTP_PR_SCTP_TTL)
#define SCTP_PR_RTX_ENABLED(x)	(SCTP_PR_POLICY(x) == SCTP_PR_SCTP_RTX)
#define SCTP_PR_PRIO_ENABLED(x)	(SCTP_PR_POLICY(x) == SCTP_PR_SCTP_PRIO)

/* These are bit fields for msghdr->msg_flags.  See section 5.1.  */
/* On user space Linux, these live in <bits/socket.h> as an enum.  */
@@ -902,4 +927,21 @@ struct sctp_paddrthlds {
	__u16 spt_pathpfthld;
};

/*
 * Socket Option for Getting the Association/Stream-Specific PR-SCTP Status
 */
struct sctp_prstatus {
	sctp_assoc_t sprstat_assoc_id;
	__u16 sprstat_sid;
	__u16 sprstat_policy;
	__u64 sprstat_abandoned_unsent;
	__u64 sprstat_abandoned_sent;
};

struct sctp_default_prinfo {
	sctp_assoc_t pr_assoc_id;
	__u32 pr_value;
	__u16 pr_policy;
};

#endif /* _UAPI_SCTP_H */
+1 −0
Original line number Diff line number Diff line
@@ -268,6 +268,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
		goto fail_init;

	asoc->active_key_id = ep->active_key_id;
	asoc->prsctp_enable = ep->prsctp_enable;

	/* Save the hmacs and chunks list into this association */
	if (ep->auth_hmacs_list)
+22 −3
Original line number Diff line number Diff line
@@ -335,6 +335,8 @@ errout:
/* Check whether this message has expired. */
int sctp_chunk_abandoned(struct sctp_chunk *chunk)
{
	if (!chunk->asoc->prsctp_enable ||
	    !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) {
		struct sctp_datamsg *msg = chunk->msg;

		if (!msg->can_abandon)
@@ -346,6 +348,23 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
		return 0;
	}

	if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
	    time_after(jiffies, chunk->prsctp_param)) {
		if (chunk->sent_count)
			chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
		else
			chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
		return 1;
	} else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
		   chunk->sent_count > chunk->prsctp_param) {
		chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
		return 1;
	}
	/* PRIO policy is processed by sendmsg, not here */

	return 0;
}

/* This chunk (and consequently entire message) has failed in its sending. */
void sctp_chunk_fail(struct sctp_chunk *chunk, int error)
{
+1 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
	 */
	ep->auth_hmacs_list = auth_hmacs;
	ep->auth_chunk_list = auth_chunks;
	ep->prsctp_enable = net->sctp.prsctp_enable;

	return ep;

Loading