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

Commit 7f9d68ac authored by Xin Long's avatar Xin Long Committed by David S. Miller
Browse files

sctp: implement sender-side procedures for SSN Reset Request Parameter



This patch is to implement sender-side procedures for the Outgoing
and Incoming SSN Reset Request Parameter described in rfc6525 section
5.1.2 and 5.1.3.

It is also add sockopt SCTP_RESET_STREAMS in rfc6525 section 6.3.2
for users.

Note that the new asoc member strreset_outstanding is to make sure
only one reconf request chunk on the fly as rfc6525 section 5.1.1
demands.

Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9fb657ae
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -193,6 +193,12 @@ void sctp_remaddr_proc_exit(struct net *net);
 */
int sctp_offload_init(void);

/*
 * sctp/stream.c
 */
int sctp_send_reset_streams(struct sctp_association *asoc,
			    struct sctp_reset_streams *params);

/*
 * Module global variables
 */
+1 −0
Original line number Diff line number Diff line
@@ -1875,6 +1875,7 @@ struct sctp_association {
	     reconf_enable:1;

	__u8 strreset_enable;
	__u8 strreset_outstanding; /* request param count on the fly */

	__u32 strreset_outseq; /* Update after receiving response */
	__u32 strreset_inseq; /* Update after receiving request */
+11 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_DEFAULT_PRINFO	114
#define SCTP_PR_ASSOC_STATUS	115
#define SCTP_ENABLE_STREAM_RESET	118
#define SCTP_RESET_STREAMS	119

/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE	0x0000
@@ -145,6 +146,9 @@ typedef __s32 sctp_assoc_t;
#define SCTP_ENABLE_CHANGE_ASSOC_REQ	0x04
#define SCTP_ENABLE_STRRESET_MASK	0x07

#define SCTP_STREAM_RESET_INCOMING	0x01
#define SCTP_STREAM_RESET_OUTGOING	0x02

/* 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.  */
enum sctp_msg_flags {
@@ -1015,4 +1019,11 @@ struct sctp_info {
	__u32	__reserved3;
};

struct sctp_reset_streams {
	sctp_assoc_t srs_assoc_id;
	uint16_t srs_flags;
	uint16_t srs_number_streams;	/* 0 == ALL */
	uint16_t srs_stream_list[];	/* list if srs_num_streams is not 0 */
};

#endif /* _UAPI_SCTP_H */
+23 −10
Original line number Diff line number Diff line
@@ -915,12 +915,15 @@ 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_RECONF:
			status = sctp_packet_transmit_chunk(packet, chunk,
							    one_packet, gfp);
			if (status  != SCTP_XMIT_OK) {
				/* put the chunk back */
				list_add(&chunk->list, &q->control_chunk_list);
			} else {
				break;
			}

			asoc->stats.octrlchunks++;
			/* PR-SCTP C5) If a FORWARD TSN is sent, the
			 * sender MUST assure that at least one T3-rtx
@@ -930,7 +933,10 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
				sctp_transport_reset_t3_rtx(transport);
				transport->last_time_sent = jiffies;
			}
			}

			if (chunk == asoc->strreset_chunk)
				sctp_transport_reset_reconf_timer(transport);

			break;

		default:
@@ -1016,6 +1022,8 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)

		/* Finally, transmit new packets.  */
		while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
			__u32 sid = ntohs(chunk->subh.data_hdr->stream);

			/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
			 * stream identifier.
			 */
@@ -1038,6 +1046,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
				continue;
			}

			if (asoc->stream->out[sid].state == SCTP_STREAM_CLOSED) {
				sctp_outq_head_data(q, chunk);
				goto sctp_flush_out;
			}

			/* If there is a specified transport, use it.
			 * Otherwise, we want to use the active path.
			 */
+29 −0
Original line number Diff line number Diff line
@@ -3786,6 +3786,32 @@ static int sctp_setsockopt_enable_strreset(struct sock *sk,
	return retval;
}

static int sctp_setsockopt_reset_streams(struct sock *sk,
					 char __user *optval,
					 unsigned int optlen)
{
	struct sctp_reset_streams *params;
	struct sctp_association *asoc;
	int retval = -EINVAL;

	if (optlen < sizeof(struct sctp_reset_streams))
		return -EINVAL;

	params = memdup_user(optval, optlen);
	if (IS_ERR(params))
		return PTR_ERR(params);

	asoc = sctp_id2assoc(sk, params->srs_assoc_id);
	if (!asoc)
		goto out;

	retval = sctp_send_reset_streams(asoc, params);

out:
	kfree(params);
	return retval;
}

/* API 6.2 setsockopt(), getsockopt()
 *
 * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3955,6 +3981,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
	case SCTP_ENABLE_STREAM_RESET:
		retval = sctp_setsockopt_enable_strreset(sk, optval, optlen);
		break;
	case SCTP_RESET_STREAMS:
		retval = sctp_setsockopt_reset_streams(sk, optval, optlen);
		break;
	default:
		retval = -ENOPROTOOPT;
		break;
Loading