All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk
@ 2017-02-17  4:45 ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

Patch 3/7 and 4/7 are to implement receiver-side procedures for the
Outgoing and Incoming SSN Reset Request Parameter described in rfc6525
section 5.2.2 and 5.2.3

Patch 1/7 and 2/7 are ahead of them to define some apis.

Patch 5/7-7/7 are to add the process of reconf chunk event in rx path.

Note that with this patchset, asoc->reconf_enable has no chance yet to
be set, until the patch "sctp: add get and set sockopt for reconf_enable"
is applied in the future. As we can not just enable it when sctp is not
capable of processing reconf chunk yet.

v1->v2:
  - re-split the patchset and make sure it has no dead codes for review.
  - rename the titles of the commits and improve some changelogs.
  - drop __packed from some structures in patch 1/7.
  - fix some kbuild warnings in patch 3/7 by initializing str_p = NULL.
  - sctp_chunk_lookup_strreset_param changes to return sctp_paramhdr_t *
    and uses sctp_strreset_tsnreq to access request_seq in patch 3/7.
  - use __u<size> in uapi sctp.h in patch 1/7.
  - do str_list endian conversion when generating stream_reset_event in patch
    2/7.
  - remove str_list endian conversion, pass resp_seq param with network endian
    to lookup_strreset_param in 3/7.
  - move str_list endian conversion out of sctp_make_strreset_req, so that
    sctp_make_strreset_req can be used more conveniently to process inreq in
    patch 4/7.
  - remove sctp_merge_reconf_chunk and not support response with multiparam
    in patch 6/7.

Xin Long (7):
  sctp: add support for generating stream reconf resp chunk
  sctp: add support for generating stream ssn reset event notification
  sctp: implement receiver-side procedures for the Outgoing SSN Reset
    Request Parameter
  sctp: implement receiver-side procedures for the Incoming SSN Reset
    Request Parameter
  sctp: add a function to verify the sctp reconf chunk
  sctp: add reconf chunk process
  sctp: add reconf chunk event

 include/linux/sctp.h         |  24 ++++++
 include/net/sctp/constants.h |   3 +
 include/net/sctp/sm.h        |  21 +++++
 include/net/sctp/ulpevent.h  |   4 +
 include/uapi/linux/sctp.h    |  16 ++++
 net/sctp/sm_make_chunk.c     | 141 +++++++++++++++++++++++++++++++--
 net/sctp/sm_statefuns.c      |  54 +++++++++++++
 net/sctp/sm_statetable.c     |  30 +++++++
 net/sctp/stream.c            | 183 +++++++++++++++++++++++++++++++++++++++++++
 net/sctp/ulpevent.c          |  29 +++++++
 10 files changed, 498 insertions(+), 7 deletions(-)

-- 
2.1.0

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk
@ 2017-02-17  4:45 ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

Patch 3/7 and 4/7 are to implement receiver-side procedures for the
Outgoing and Incoming SSN Reset Request Parameter described in rfc6525
section 5.2.2 and 5.2.3

Patch 1/7 and 2/7 are ahead of them to define some apis.

Patch 5/7-7/7 are to add the process of reconf chunk event in rx path.

Note that with this patchset, asoc->reconf_enable has no chance yet to
be set, until the patch "sctp: add get and set sockopt for reconf_enable"
is applied in the future. As we can not just enable it when sctp is not
capable of processing reconf chunk yet.

v1->v2:
  - re-split the patchset and make sure it has no dead codes for review.
  - rename the titles of the commits and improve some changelogs.
  - drop __packed from some structures in patch 1/7.
  - fix some kbuild warnings in patch 3/7 by initializing str_p = NULL.
  - sctp_chunk_lookup_strreset_param changes to return sctp_paramhdr_t *
    and uses sctp_strreset_tsnreq to access request_seq in patch 3/7.
  - use __u<size> in uapi sctp.h in patch 1/7.
  - do str_list endian conversion when generating stream_reset_event in patch
    2/7.
  - remove str_list endian conversion, pass resp_seq param with network endian
    to lookup_strreset_param in 3/7.
  - move str_list endian conversion out of sctp_make_strreset_req, so that
    sctp_make_strreset_req can be used more conveniently to process inreq in
    patch 4/7.
  - remove sctp_merge_reconf_chunk and not support response with multiparam
    in patch 6/7.

Xin Long (7):
  sctp: add support for generating stream reconf resp chunk
  sctp: add support for generating stream ssn reset event notification
  sctp: implement receiver-side procedures for the Outgoing SSN Reset
    Request Parameter
  sctp: implement receiver-side procedures for the Incoming SSN Reset
    Request Parameter
  sctp: add a function to verify the sctp reconf chunk
  sctp: add reconf chunk process
  sctp: add reconf chunk event

 include/linux/sctp.h         |  24 ++++++
 include/net/sctp/constants.h |   3 +
 include/net/sctp/sm.h        |  21 +++++
 include/net/sctp/ulpevent.h  |   4 +
 include/uapi/linux/sctp.h    |  16 ++++
 net/sctp/sm_make_chunk.c     | 141 +++++++++++++++++++++++++++++++--
 net/sctp/sm_statefuns.c      |  54 +++++++++++++
 net/sctp/sm_statetable.c     |  30 +++++++
 net/sctp/stream.c            | 183 +++++++++++++++++++++++++++++++++++++++++++
 net/sctp/ulpevent.c          |  29 +++++++
 10 files changed, 498 insertions(+), 7 deletions(-)

-- 
2.1.0


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk
  2017-02-17  4:45 ` Xin Long
@ 2017-02-17  4:45   ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to define Re-configuration Response Parameter described
in rfc6525 section 4.4. As optional fields are only for SSN/TSN Reset
Request Parameter, it uses another function to make that.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/linux/sctp.h     | 24 ++++++++++++++++
 include/net/sctp/sm.h    |  7 +++++
 net/sctp/sm_make_chunk.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+)

diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index b055788..7a4804c 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -749,4 +749,28 @@ struct sctp_strreset_addstrm {
 	__u16 reserved;
 };
 
+enum {
+	SCTP_STRRESET_NOTHING_TO_DO	= 0x00,
+	SCTP_STRRESET_PERFORMED		= 0x01,
+	SCTP_STRRESET_DENIED		= 0x02,
+	SCTP_STRRESET_ERR_WRONG_SSN	= 0x03,
+	SCTP_STRRESET_ERR_IN_PROGRESS	= 0x04,
+	SCTP_STRRESET_ERR_BAD_SEQNO	= 0x05,
+	SCTP_STRRESET_IN_PROGRESS	= 0x06,
+};
+
+struct sctp_strreset_resp {
+	sctp_paramhdr_t param_hdr;
+	__u32 response_seq;
+	__u32 result;
+};
+
+struct sctp_strreset_resptsn {
+	sctp_paramhdr_t param_hdr;
+	__u32 response_seq;
+	__u32 result;
+	__u32 senders_next_tsn;
+	__u32 receivers_next_tsn;
+};
+
 #endif /* __LINUX_SCTP_H__ */
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 3675fde..8a85dd7 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -270,6 +270,13 @@ struct sctp_chunk *sctp_make_strreset_tsnreq(
 struct sctp_chunk *sctp_make_strreset_addstrm(
 				const struct sctp_association *asoc,
 				__u16 out, __u16 in);
+struct sctp_chunk *sctp_make_strreset_resp(
+				const struct sctp_association *asoc,
+				__u32 result, __u32 sn);
+struct sctp_chunk *sctp_make_strreset_tsnresp(
+				struct sctp_association *asoc,
+				__u32 result, __u32 sn,
+				__u32 sender_tsn, __u32 receiver_tsn);
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 7f8dbf2..9680c58 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3733,3 +3733,77 @@ struct sctp_chunk *sctp_make_strreset_addstrm(
 
 	return retval;
 }
+
+/* RE-CONFIG 4.4 (RESP)
+ *   0                   1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |     Parameter Type = 16       |      Parameter Length         |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |         Re-configuration Response Sequence Number             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                            Result                             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct sctp_chunk *sctp_make_strreset_resp(
+				const struct sctp_association *asoc,
+				__u32 result, __u32 sn)
+{
+	struct sctp_strreset_resp resp;
+	__u16 length = sizeof(resp);
+	struct sctp_chunk *retval;
+
+	retval = sctp_make_reconf(asoc, length);
+	if (!retval)
+		return NULL;
+
+	resp.param_hdr.type = SCTP_PARAM_RESET_RESPONSE;
+	resp.param_hdr.length = htons(length);
+	resp.response_seq = htonl(sn);
+	resp.result = htonl(result);
+
+	sctp_addto_chunk(retval, sizeof(resp), &resp);
+
+	return retval;
+}
+
+/* RE-CONFIG 4.4 OPTIONAL (TSNRESP)
+ *   0                   1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |     Parameter Type = 16       |      Parameter Length         |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |         Re-configuration Response Sequence Number             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                            Result                             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                   Sender's Next TSN (optional)                |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                  Receiver's Next TSN (optional)               |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct sctp_chunk *sctp_make_strreset_tsnresp(
+					struct sctp_association *asoc,
+					__u32 result, __u32 sn,
+					__u32 sender_tsn, __u32 receiver_tsn)
+{
+	struct sctp_strreset_resptsn tsnresp;
+	__u16 length = sizeof(tsnresp);
+	struct sctp_chunk *retval;
+
+	retval = sctp_make_reconf(asoc, length);
+	if (!retval)
+		return NULL;
+
+	tsnresp.param_hdr.type = SCTP_PARAM_RESET_RESPONSE;
+	tsnresp.param_hdr.length = htons(length);
+
+	tsnresp.response_seq = htonl(sn);
+	tsnresp.result = htonl(result);
+	tsnresp.senders_next_tsn = htonl(sender_tsn);
+	tsnresp.receivers_next_tsn = htonl(receiver_tsn);
+
+	sctp_addto_chunk(retval, sizeof(tsnresp), &tsnresp);
+
+	return retval;
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk
@ 2017-02-17  4:45   ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to define Re-configuration Response Parameter described
in rfc6525 section 4.4. As optional fields are only for SSN/TSN Reset
Request Parameter, it uses another function to make that.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/linux/sctp.h     | 24 ++++++++++++++++
 include/net/sctp/sm.h    |  7 +++++
 net/sctp/sm_make_chunk.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+)

diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index b055788..7a4804c 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -749,4 +749,28 @@ struct sctp_strreset_addstrm {
 	__u16 reserved;
 };
 
+enum {
+	SCTP_STRRESET_NOTHING_TO_DO	= 0x00,
+	SCTP_STRRESET_PERFORMED		= 0x01,
+	SCTP_STRRESET_DENIED		= 0x02,
+	SCTP_STRRESET_ERR_WRONG_SSN	= 0x03,
+	SCTP_STRRESET_ERR_IN_PROGRESS	= 0x04,
+	SCTP_STRRESET_ERR_BAD_SEQNO	= 0x05,
+	SCTP_STRRESET_IN_PROGRESS	= 0x06,
+};
+
+struct sctp_strreset_resp {
+	sctp_paramhdr_t param_hdr;
+	__u32 response_seq;
+	__u32 result;
+};
+
+struct sctp_strreset_resptsn {
+	sctp_paramhdr_t param_hdr;
+	__u32 response_seq;
+	__u32 result;
+	__u32 senders_next_tsn;
+	__u32 receivers_next_tsn;
+};
+
 #endif /* __LINUX_SCTP_H__ */
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 3675fde..8a85dd7 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -270,6 +270,13 @@ struct sctp_chunk *sctp_make_strreset_tsnreq(
 struct sctp_chunk *sctp_make_strreset_addstrm(
 				const struct sctp_association *asoc,
 				__u16 out, __u16 in);
+struct sctp_chunk *sctp_make_strreset_resp(
+				const struct sctp_association *asoc,
+				__u32 result, __u32 sn);
+struct sctp_chunk *sctp_make_strreset_tsnresp(
+				struct sctp_association *asoc,
+				__u32 result, __u32 sn,
+				__u32 sender_tsn, __u32 receiver_tsn);
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 7f8dbf2..9680c58 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3733,3 +3733,77 @@ struct sctp_chunk *sctp_make_strreset_addstrm(
 
 	return retval;
 }
+
+/* RE-CONFIG 4.4 (RESP)
+ *   0                   1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |     Parameter Type = 16       |      Parameter Length         |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |         Re-configuration Response Sequence Number             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                            Result                             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct sctp_chunk *sctp_make_strreset_resp(
+				const struct sctp_association *asoc,
+				__u32 result, __u32 sn)
+{
+	struct sctp_strreset_resp resp;
+	__u16 length = sizeof(resp);
+	struct sctp_chunk *retval;
+
+	retval = sctp_make_reconf(asoc, length);
+	if (!retval)
+		return NULL;
+
+	resp.param_hdr.type = SCTP_PARAM_RESET_RESPONSE;
+	resp.param_hdr.length = htons(length);
+	resp.response_seq = htonl(sn);
+	resp.result = htonl(result);
+
+	sctp_addto_chunk(retval, sizeof(resp), &resp);
+
+	return retval;
+}
+
+/* RE-CONFIG 4.4 OPTIONAL (TSNRESP)
+ *   0                   1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |     Parameter Type = 16       |      Parameter Length         |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |         Re-configuration Response Sequence Number             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                            Result                             |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                   Sender's Next TSN (optional)                |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                  Receiver's Next TSN (optional)               |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct sctp_chunk *sctp_make_strreset_tsnresp(
+					struct sctp_association *asoc,
+					__u32 result, __u32 sn,
+					__u32 sender_tsn, __u32 receiver_tsn)
+{
+	struct sctp_strreset_resptsn tsnresp;
+	__u16 length = sizeof(tsnresp);
+	struct sctp_chunk *retval;
+
+	retval = sctp_make_reconf(asoc, length);
+	if (!retval)
+		return NULL;
+
+	tsnresp.param_hdr.type = SCTP_PARAM_RESET_RESPONSE;
+	tsnresp.param_hdr.length = htons(length);
+
+	tsnresp.response_seq = htonl(sn);
+	tsnresp.result = htonl(result);
+	tsnresp.senders_next_tsn = htonl(sender_tsn);
+	tsnresp.receivers_next_tsn = htonl(receiver_tsn);
+
+	sctp_addto_chunk(retval, sizeof(tsnresp), &tsnresp);
+
+	return retval;
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 2/7] sctp: add support for generating stream ssn reset event notification
  2017-02-17  4:45   ` Xin Long
@ 2017-02-17  4:45     ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Stream Reset Event described in rfc6525
section 6.1.1.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/ulpevent.h |  4 ++++
 include/uapi/linux/sctp.h   | 16 ++++++++++++++++
 net/sctp/ulpevent.c         | 29 +++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 2c098cd..324b596 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -128,6 +128,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_authkey(
 struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 	const struct sctp_association *asoc, gfp_t gfp);
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
+	const struct sctp_association *asoc, __u16 flags,
+	__u16 stream_num, __u16 *stream_list, gfp_t gfp);
+
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *);
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index a91a9cc..d3ae381 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -490,6 +490,18 @@ struct sctp_sender_dry_event {
 	sctp_assoc_t sender_dry_assoc_id;
 };
 
+#define SCTP_STREAM_RESET_INCOMING_SSN	0x0001
+#define SCTP_STREAM_RESET_OUTGOING_SSN	0x0002
+#define SCTP_STREAM_RESET_DENIED	0x0004
+#define SCTP_STREAM_RESET_FAILED	0x0008
+struct sctp_stream_reset_event {
+	__u16 strreset_type;
+	__u16 strreset_flags;
+	__u32 strreset_length;
+	sctp_assoc_t strreset_assoc_id;
+	__u16 strreset_stream_list[];
+};
+
 /*
  * Described in Section 7.3
  *   Ancillary Data and Notification Interest Options
@@ -505,6 +517,7 @@ struct sctp_event_subscribe {
 	__u8 sctp_adaptation_layer_event;
 	__u8 sctp_authentication_event;
 	__u8 sctp_sender_dry_event;
+	__u8 sctp_stream_reset_event;
 };
 
 /*
@@ -529,6 +542,7 @@ union sctp_notification {
 	struct sctp_pdapi_event sn_pdapi_event;
 	struct sctp_authkey_event sn_authkey_event;
 	struct sctp_sender_dry_event sn_sender_dry_event;
+	struct sctp_stream_reset_event sn_strreset_event;
 };
 
 /* Section 5.3.1
@@ -556,6 +570,8 @@ enum sctp_sn_type {
 #define SCTP_AUTHENTICATION_INDICATION	SCTP_AUTHENTICATION_EVENT
 	SCTP_SENDER_DRY_EVENT,
 #define SCTP_SENDER_DRY_EVENT		SCTP_SENDER_DRY_EVENT
+	SCTP_STREAM_RESET_EVENT,
+#define SCTP_STREAM_RESET_EVENT		SCTP_STREAM_RESET_EVENT
 };
 
 /* Notification error codes used to fill up the error fields in some
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index bea0005..c8881bc5 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -854,6 +854,35 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 	return event;
 }
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
+	const struct sctp_association *asoc, __u16 flags, __u16 stream_num,
+	__u16 *stream_list, gfp_t gfp)
+{
+	struct sctp_stream_reset_event *sreset;
+	struct sctp_ulpevent *event;
+	struct sk_buff *skb;
+	int length, i;
+
+	length = sizeof(struct sctp_stream_reset_event) + 2 * stream_num;
+	event = sctp_ulpevent_new(length, MSG_NOTIFICATION, gfp);
+	if (!event)
+		return NULL;
+
+	skb = sctp_event2skb(event);
+	sreset = (struct sctp_stream_reset_event *)skb_put(skb, length);
+
+	sreset->strreset_type = SCTP_STREAM_RESET_EVENT;
+	sreset->strreset_flags = flags;
+	sreset->strreset_length = length;
+	sctp_ulpevent_set_owner(event, asoc);
+	sreset->strreset_assoc_id = sctp_assoc2id(asoc);
+
+	for (i = 0; i < stream_num; i++)
+		sreset->strreset_stream_list[i] = ntohs(stream_list[i]);
+
+	return event;
+}
+
 /* Return the notification type, assuming this is a notification
  * event.
  */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 2/7] sctp: add support for generating stream ssn reset event notification
@ 2017-02-17  4:45     ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Stream Reset Event described in rfc6525
section 6.1.1.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/ulpevent.h |  4 ++++
 include/uapi/linux/sctp.h   | 16 ++++++++++++++++
 net/sctp/ulpevent.c         | 29 +++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 2c098cd..324b596 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -128,6 +128,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_authkey(
 struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 	const struct sctp_association *asoc, gfp_t gfp);
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
+	const struct sctp_association *asoc, __u16 flags,
+	__u16 stream_num, __u16 *stream_list, gfp_t gfp);
+
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *);
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index a91a9cc..d3ae381 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -490,6 +490,18 @@ struct sctp_sender_dry_event {
 	sctp_assoc_t sender_dry_assoc_id;
 };
 
+#define SCTP_STREAM_RESET_INCOMING_SSN	0x0001
+#define SCTP_STREAM_RESET_OUTGOING_SSN	0x0002
+#define SCTP_STREAM_RESET_DENIED	0x0004
+#define SCTP_STREAM_RESET_FAILED	0x0008
+struct sctp_stream_reset_event {
+	__u16 strreset_type;
+	__u16 strreset_flags;
+	__u32 strreset_length;
+	sctp_assoc_t strreset_assoc_id;
+	__u16 strreset_stream_list[];
+};
+
 /*
  * Described in Section 7.3
  *   Ancillary Data and Notification Interest Options
@@ -505,6 +517,7 @@ struct sctp_event_subscribe {
 	__u8 sctp_adaptation_layer_event;
 	__u8 sctp_authentication_event;
 	__u8 sctp_sender_dry_event;
+	__u8 sctp_stream_reset_event;
 };
 
 /*
@@ -529,6 +542,7 @@ union sctp_notification {
 	struct sctp_pdapi_event sn_pdapi_event;
 	struct sctp_authkey_event sn_authkey_event;
 	struct sctp_sender_dry_event sn_sender_dry_event;
+	struct sctp_stream_reset_event sn_strreset_event;
 };
 
 /* Section 5.3.1
@@ -556,6 +570,8 @@ enum sctp_sn_type {
 #define SCTP_AUTHENTICATION_INDICATION	SCTP_AUTHENTICATION_EVENT
 	SCTP_SENDER_DRY_EVENT,
 #define SCTP_SENDER_DRY_EVENT		SCTP_SENDER_DRY_EVENT
+	SCTP_STREAM_RESET_EVENT,
+#define SCTP_STREAM_RESET_EVENT		SCTP_STREAM_RESET_EVENT
 };
 
 /* Notification error codes used to fill up the error fields in some
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index bea0005..c8881bc5 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -854,6 +854,35 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 	return event;
 }
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
+	const struct sctp_association *asoc, __u16 flags, __u16 stream_num,
+	__u16 *stream_list, gfp_t gfp)
+{
+	struct sctp_stream_reset_event *sreset;
+	struct sctp_ulpevent *event;
+	struct sk_buff *skb;
+	int length, i;
+
+	length = sizeof(struct sctp_stream_reset_event) + 2 * stream_num;
+	event = sctp_ulpevent_new(length, MSG_NOTIFICATION, gfp);
+	if (!event)
+		return NULL;
+
+	skb = sctp_event2skb(event);
+	sreset = (struct sctp_stream_reset_event *)skb_put(skb, length);
+
+	sreset->strreset_type = SCTP_STREAM_RESET_EVENT;
+	sreset->strreset_flags = flags;
+	sreset->strreset_length = length;
+	sctp_ulpevent_set_owner(event, asoc);
+	sreset->strreset_assoc_id = sctp_assoc2id(asoc);
+
+	for (i = 0; i < stream_num; i++)
+		sreset->strreset_stream_list[i] = ntohs(stream_list[i]);
+
+	return event;
+}
+
 /* Return the notification type, assuming this is a notification
  * event.
  */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter
  2017-02-17  4:45     ` Xin Long
@ 2017-02-17  4:45       ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the Outgoing
SSN Reset Request Parameter described in rfc6525 section 5.2.2.

Note that some checks must be after request_seq check, as even those
checks fail, strreset_inseq still has to be increase by 1.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h |   6 +++
 net/sctp/stream.c     | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 8a85dd7..c0f9bea 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -280,6 +280,12 @@ struct sctp_chunk *sctp_make_strreset_tsnresp(
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
+/* Prototypes for stream-processing functions.  */
+struct sctp_chunk *sctp_process_strreset_outreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
+
 /* Prototypes for statetable processing. */
 
 int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype,
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index eb02490..531fcc4 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -294,3 +294,116 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 out:
 	return retval;
 }
+
+static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param(
+			struct sctp_association *asoc, __u32 resp_seq)
+{
+	struct sctp_chunk *chunk = asoc->strreset_chunk;
+	struct sctp_reconf_chunk *hdr;
+	union sctp_params param;
+
+	if (ntohl(resp_seq) != asoc->strreset_outseq || !chunk)
+		return NULL;
+
+	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
+	sctp_walk_params(param, hdr, params) {
+		/* sctp_strreset_tsnreq is actually the basic structure
+		 * of all stream reconf params, so it's safe to use it
+		 * to access request_seq.
+		 */
+		struct sctp_strreset_tsnreq *req = param.v;
+
+		if (req->request_seq == resp_seq)
+			return param.v;
+	}
+
+	return NULL;
+}
+
+struct sctp_chunk *sctp_process_strreset_outreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_outreq *outreq = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u16 i, nums, flags = 0, *str_p = NULL;
+	__u32 result = SCTP_STRRESET_DENIED;
+	__u32 request_seq;
+
+	request_seq = ntohl(outreq->request_seq);
+
+	if (ntohl(outreq->send_reset_at_tsn) >
+	    sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map)) {
+		result = SCTP_STRRESET_IN_PROGRESS;
+		goto out;
+	}
+
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq == asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	/* Check strreset_enable after inseq inc, as sender cannot tell
+	 * the peer doesn't enable strreset after receiving response with
+	 * result denied, as well as to keep consistent with bsd.
+	 */
+	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
+		goto out;
+
+	if (asoc->strreset_chunk) {
+		sctp_paramhdr_t *param_hdr;
+		struct sctp_transport *t;
+
+		param_hdr = sctp_chunk_lookup_strreset_param(
+					asoc, outreq->response_seq);
+		if (!param_hdr || param_hdr->type !=
+					SCTP_PARAM_RESET_IN_REQUEST) {
+			/* same process with outstanding isn't 0 */
+			result = SCTP_STRRESET_ERR_IN_PROGRESS;
+			goto out;
+		}
+
+		asoc->strreset_outstanding--;
+		asoc->strreset_outseq++;
+
+		if (!asoc->strreset_outstanding) {
+			t = asoc->strreset_chunk->transport;
+			if (del_timer(&t->reconf_timer))
+				sctp_transport_put(t);
+
+			sctp_chunk_put(asoc->strreset_chunk);
+			asoc->strreset_chunk = NULL;
+		}
+
+		flags = SCTP_STREAM_RESET_INCOMING_SSN;
+	}
+
+	nums = (ntohs(param.p->length) - sizeof(*outreq)) / 2;
+	if (nums) {
+		str_p = outreq->list_of_streams;
+		for (i = 0; i < nums; i++) {
+			if (ntohs(str_p[i]) >= stream->incnt) {
+				result = SCTP_STRRESET_ERR_WRONG_SSN;
+				goto out;
+			}
+		}
+
+		for (i = 0; i < nums; i++)
+			stream->in[ntohs(str_p[i])].ssn = 0;
+	} else {
+		for (i = 0; i < stream->incnt; i++)
+			stream->in[i].ssn = 0;
+	}
+
+	result = SCTP_STRRESET_PERFORMED;
+
+	*evp = sctp_ulpevent_make_stream_reset_event(asoc,
+		flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p,
+		GFP_ATOMIC);
+
+out:
+	return sctp_make_strreset_resp(asoc, result, request_seq);
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request P
@ 2017-02-17  4:45       ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the Outgoing
SSN Reset Request Parameter described in rfc6525 section 5.2.2.

Note that some checks must be after request_seq check, as even those
checks fail, strreset_inseq still has to be increase by 1.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h |   6 +++
 net/sctp/stream.c     | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 8a85dd7..c0f9bea 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -280,6 +280,12 @@ struct sctp_chunk *sctp_make_strreset_tsnresp(
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
+/* Prototypes for stream-processing functions.  */
+struct sctp_chunk *sctp_process_strreset_outreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
+
 /* Prototypes for statetable processing. */
 
 int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype,
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index eb02490..531fcc4 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -294,3 +294,116 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 out:
 	return retval;
 }
+
+static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param(
+			struct sctp_association *asoc, __u32 resp_seq)
+{
+	struct sctp_chunk *chunk = asoc->strreset_chunk;
+	struct sctp_reconf_chunk *hdr;
+	union sctp_params param;
+
+	if (ntohl(resp_seq) != asoc->strreset_outseq || !chunk)
+		return NULL;
+
+	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
+	sctp_walk_params(param, hdr, params) {
+		/* sctp_strreset_tsnreq is actually the basic structure
+		 * of all stream reconf params, so it's safe to use it
+		 * to access request_seq.
+		 */
+		struct sctp_strreset_tsnreq *req = param.v;
+
+		if (req->request_seq = resp_seq)
+			return param.v;
+	}
+
+	return NULL;
+}
+
+struct sctp_chunk *sctp_process_strreset_outreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_outreq *outreq = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u16 i, nums, flags = 0, *str_p = NULL;
+	__u32 result = SCTP_STRRESET_DENIED;
+	__u32 request_seq;
+
+	request_seq = ntohl(outreq->request_seq);
+
+	if (ntohl(outreq->send_reset_at_tsn) >
+	    sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map)) {
+		result = SCTP_STRRESET_IN_PROGRESS;
+		goto out;
+	}
+
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq = asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	/* Check strreset_enable after inseq inc, as sender cannot tell
+	 * the peer doesn't enable strreset after receiving response with
+	 * result denied, as well as to keep consistent with bsd.
+	 */
+	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
+		goto out;
+
+	if (asoc->strreset_chunk) {
+		sctp_paramhdr_t *param_hdr;
+		struct sctp_transport *t;
+
+		param_hdr = sctp_chunk_lookup_strreset_param(
+					asoc, outreq->response_seq);
+		if (!param_hdr || param_hdr->type !+					SCTP_PARAM_RESET_IN_REQUEST) {
+			/* same process with outstanding isn't 0 */
+			result = SCTP_STRRESET_ERR_IN_PROGRESS;
+			goto out;
+		}
+
+		asoc->strreset_outstanding--;
+		asoc->strreset_outseq++;
+
+		if (!asoc->strreset_outstanding) {
+			t = asoc->strreset_chunk->transport;
+			if (del_timer(&t->reconf_timer))
+				sctp_transport_put(t);
+
+			sctp_chunk_put(asoc->strreset_chunk);
+			asoc->strreset_chunk = NULL;
+		}
+
+		flags = SCTP_STREAM_RESET_INCOMING_SSN;
+	}
+
+	nums = (ntohs(param.p->length) - sizeof(*outreq)) / 2;
+	if (nums) {
+		str_p = outreq->list_of_streams;
+		for (i = 0; i < nums; i++) {
+			if (ntohs(str_p[i]) >= stream->incnt) {
+				result = SCTP_STRRESET_ERR_WRONG_SSN;
+				goto out;
+			}
+		}
+
+		for (i = 0; i < nums; i++)
+			stream->in[ntohs(str_p[i])].ssn = 0;
+	} else {
+		for (i = 0; i < stream->incnt; i++)
+			stream->in[i].ssn = 0;
+	}
+
+	result = SCTP_STRRESET_PERFORMED;
+
+	*evp = sctp_ulpevent_make_stream_reset_event(asoc,
+		flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p,
+		GFP_ATOMIC);
+
+out:
+	return sctp_make_strreset_resp(asoc, result, request_seq);
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming SSN Reset Request Parameter
  2017-02-17  4:45       ` [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request P Xin Long
@ 2017-02-17  4:45         ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the Incoming
SSN Reset Request Parameter described in rfc6525 section 5.2.3.

It's also to move str_list endian conversion out of sctp_make_strreset_req,
so that sctp_make_strreset_req can be used more conveniently to process
inreq.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h    |  4 +++
 net/sctp/sm_make_chunk.c |  8 +-----
 net/sctp/stream.c        | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index c0f9bea..f6a828d 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -285,6 +285,10 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_inreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 9680c58..60d9fdc 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3617,7 +3617,7 @@ struct sctp_chunk *sctp_make_strreset_req(
 	__u16 stream_len = stream_num * 2;
 	struct sctp_strreset_inreq inreq;
 	struct sctp_chunk *retval;
-	__u16 outlen, inlen, i;
+	__u16 outlen, inlen;
 
 	outlen = (sizeof(outreq) + stream_len) * out;
 	inlen = (sizeof(inreq) + stream_len) * in;
@@ -3626,9 +3626,6 @@ struct sctp_chunk *sctp_make_strreset_req(
 	if (!retval)
 		return NULL;
 
-	for (i = 0; i < stream_num; i++)
-		stream_list[i] = htons(stream_list[i]);
-
 	if (outlen) {
 		outreq.param_hdr.type = SCTP_PARAM_RESET_OUT_REQUEST;
 		outreq.param_hdr.length = htons(outlen);
@@ -3653,9 +3650,6 @@ struct sctp_chunk *sctp_make_strreset_req(
 			sctp_addto_chunk(retval, stream_len, stream_list);
 	}
 
-	for (i = 0; i < stream_num; i++)
-		stream_list[i] = ntohs(stream_list[i]);
-
 	return retval;
 }
 
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 531fcc4..1c6cc04 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -135,7 +135,14 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
 			if (str_list[i] >= stream->incnt)
 				goto out;
 
+	for (i = 0; i < str_nums; i++)
+		str_list[i] = htons(str_list[i]);
+
 	chunk = sctp_make_strreset_req(asoc, str_nums, str_list, out, in);
+
+	for (i = 0; i < str_nums; i++)
+		str_list[i] = ntohs(str_list[i]);
+
 	if (!chunk) {
 		retval = -ENOMEM;
 		goto out;
@@ -407,3 +414,66 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 out:
 	return sctp_make_strreset_resp(asoc, result, request_seq);
 }
+
+struct sctp_chunk *sctp_process_strreset_inreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_inreq *inreq = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	struct sctp_chunk *chunk = NULL;
+	__u16 i, nums, *str_p;
+	__u32 request_seq;
+
+	request_seq = ntohl(inreq->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq == asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
+		goto out;
+
+	if (asoc->strreset_outstanding) {
+		result = SCTP_STRRESET_ERR_IN_PROGRESS;
+		goto out;
+	}
+
+	nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2;
+	str_p = inreq->list_of_streams;
+	for (i = 0; i < nums; i++) {
+		if (ntohs(str_p[i]) >= stream->outcnt) {
+			result = SCTP_STRRESET_ERR_WRONG_SSN;
+			goto out;
+		}
+	}
+
+	chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0);
+	if (!chunk)
+		goto out;
+
+	if (nums)
+		for (i = 0; i < nums; i++)
+			stream->out[ntohs(str_p[i])].state =
+					       SCTP_STREAM_CLOSED;
+	else
+		for (i = 0; i < stream->outcnt; i++)
+			stream->out[i].state = SCTP_STREAM_CLOSED;
+
+	asoc->strreset_chunk = chunk;
+	asoc->strreset_outstanding = 1;
+	sctp_chunk_hold(asoc->strreset_chunk);
+
+	*evp = sctp_ulpevent_make_stream_reset_event(asoc,
+		SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
+
+out:
+	if (!chunk)
+		chunk =  sctp_make_strreset_resp(asoc, result, request_seq);
+
+	return chunk;
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming SSN Reset Request P
@ 2017-02-17  4:45         ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the Incoming
SSN Reset Request Parameter described in rfc6525 section 5.2.3.

It's also to move str_list endian conversion out of sctp_make_strreset_req,
so that sctp_make_strreset_req can be used more conveniently to process
inreq.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h    |  4 +++
 net/sctp/sm_make_chunk.c |  8 +-----
 net/sctp/stream.c        | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index c0f9bea..f6a828d 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -285,6 +285,10 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_inreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 9680c58..60d9fdc 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3617,7 +3617,7 @@ struct sctp_chunk *sctp_make_strreset_req(
 	__u16 stream_len = stream_num * 2;
 	struct sctp_strreset_inreq inreq;
 	struct sctp_chunk *retval;
-	__u16 outlen, inlen, i;
+	__u16 outlen, inlen;
 
 	outlen = (sizeof(outreq) + stream_len) * out;
 	inlen = (sizeof(inreq) + stream_len) * in;
@@ -3626,9 +3626,6 @@ struct sctp_chunk *sctp_make_strreset_req(
 	if (!retval)
 		return NULL;
 
-	for (i = 0; i < stream_num; i++)
-		stream_list[i] = htons(stream_list[i]);
-
 	if (outlen) {
 		outreq.param_hdr.type = SCTP_PARAM_RESET_OUT_REQUEST;
 		outreq.param_hdr.length = htons(outlen);
@@ -3653,9 +3650,6 @@ struct sctp_chunk *sctp_make_strreset_req(
 			sctp_addto_chunk(retval, stream_len, stream_list);
 	}
 
-	for (i = 0; i < stream_num; i++)
-		stream_list[i] = ntohs(stream_list[i]);
-
 	return retval;
 }
 
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 531fcc4..1c6cc04 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -135,7 +135,14 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
 			if (str_list[i] >= stream->incnt)
 				goto out;
 
+	for (i = 0; i < str_nums; i++)
+		str_list[i] = htons(str_list[i]);
+
 	chunk = sctp_make_strreset_req(asoc, str_nums, str_list, out, in);
+
+	for (i = 0; i < str_nums; i++)
+		str_list[i] = ntohs(str_list[i]);
+
 	if (!chunk) {
 		retval = -ENOMEM;
 		goto out;
@@ -407,3 +414,66 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 out:
 	return sctp_make_strreset_resp(asoc, result, request_seq);
 }
+
+struct sctp_chunk *sctp_process_strreset_inreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_inreq *inreq = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	struct sctp_chunk *chunk = NULL;
+	__u16 i, nums, *str_p;
+	__u32 request_seq;
+
+	request_seq = ntohl(inreq->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq = asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
+		goto out;
+
+	if (asoc->strreset_outstanding) {
+		result = SCTP_STRRESET_ERR_IN_PROGRESS;
+		goto out;
+	}
+
+	nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2;
+	str_p = inreq->list_of_streams;
+	for (i = 0; i < nums; i++) {
+		if (ntohs(str_p[i]) >= stream->outcnt) {
+			result = SCTP_STRRESET_ERR_WRONG_SSN;
+			goto out;
+		}
+	}
+
+	chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0);
+	if (!chunk)
+		goto out;
+
+	if (nums)
+		for (i = 0; i < nums; i++)
+			stream->out[ntohs(str_p[i])].state +					       SCTP_STREAM_CLOSED;
+	else
+		for (i = 0; i < stream->outcnt; i++)
+			stream->out[i].state = SCTP_STREAM_CLOSED;
+
+	asoc->strreset_chunk = chunk;
+	asoc->strreset_outstanding = 1;
+	sctp_chunk_hold(asoc->strreset_chunk);
+
+	*evp = sctp_ulpevent_make_stream_reset_event(asoc,
+		SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
+
+out:
+	if (!chunk)
+		chunk =  sctp_make_strreset_resp(asoc, result, request_seq);
+
+	return chunk;
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 5/7] sctp: add a function to verify the sctp reconf chunk
  2017-02-17  4:45         ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming SSN Reset Request P Xin Long
@ 2017-02-17  4:45           ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add a function sctp_verify_reconf to do some length
check and multi-params check for sctp stream reconf according to rfc6525
section 3.1.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h    |  3 +++
 net/sctp/sm_make_chunk.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index f6a828d..ca9fbfb 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -277,6 +277,9 @@ struct sctp_chunk *sctp_make_strreset_tsnresp(
 				struct sctp_association *asoc,
 				__u32 result, __u32 sn,
 				__u32 sender_tsn, __u32 receiver_tsn);
+bool sctp_verify_reconf(const struct sctp_association *asoc,
+			struct sctp_chunk *chunk,
+			struct sctp_paramhdr **errp);
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 60d9fdc..969a30c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3801,3 +3801,62 @@ struct sctp_chunk *sctp_make_strreset_tsnresp(
 
 	return retval;
 }
+
+bool sctp_verify_reconf(const struct sctp_association *asoc,
+			struct sctp_chunk *chunk,
+			struct sctp_paramhdr **errp)
+{
+	struct sctp_reconf_chunk *hdr;
+	union sctp_params param;
+	__u16 last = 0, cnt = 0;
+
+	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
+	sctp_walk_params(param, hdr, params) {
+		__u16 length = ntohs(param.p->length);
+
+		*errp = param.p;
+		if (cnt++ > 2)
+			return false;
+		switch (param.p->type) {
+		case SCTP_PARAM_RESET_OUT_REQUEST:
+			if (length < sizeof(struct sctp_strreset_outreq) ||
+			    (last && last != SCTP_PARAM_RESET_RESPONSE &&
+			     last != SCTP_PARAM_RESET_IN_REQUEST))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_IN_REQUEST:
+			if (length < sizeof(struct sctp_strreset_inreq) ||
+			    (last && last != SCTP_PARAM_RESET_OUT_REQUEST))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_RESPONSE:
+			if ((length != sizeof(struct sctp_strreset_resp) &&
+			     length != sizeof(struct sctp_strreset_resptsn)) ||
+			    (last && last != SCTP_PARAM_RESET_RESPONSE &&
+			     last != SCTP_PARAM_RESET_OUT_REQUEST))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_TSN_REQUEST:
+			if (length !=
+			    sizeof(struct sctp_strreset_tsnreq) || last)
+				return false;
+			break;
+		case SCTP_PARAM_RESET_ADD_IN_STREAMS:
+			if (length != sizeof(struct sctp_strreset_addstrm) ||
+			    (last && last != SCTP_PARAM_RESET_ADD_OUT_STREAMS))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_ADD_OUT_STREAMS:
+			if (length != sizeof(struct sctp_strreset_addstrm) ||
+			    (last && last != SCTP_PARAM_RESET_ADD_IN_STREAMS))
+				return false;
+			break;
+		default:
+			return false;
+		}
+
+		last = param.p->type;
+	}
+
+	return true;
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 5/7] sctp: add a function to verify the sctp reconf chunk
@ 2017-02-17  4:45           ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add a function sctp_verify_reconf to do some length
check and multi-params check for sctp stream reconf according to rfc6525
section 3.1.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h    |  3 +++
 net/sctp/sm_make_chunk.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index f6a828d..ca9fbfb 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -277,6 +277,9 @@ struct sctp_chunk *sctp_make_strreset_tsnresp(
 				struct sctp_association *asoc,
 				__u32 result, __u32 sn,
 				__u32 sender_tsn, __u32 receiver_tsn);
+bool sctp_verify_reconf(const struct sctp_association *asoc,
+			struct sctp_chunk *chunk,
+			struct sctp_paramhdr **errp);
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 60d9fdc..969a30c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3801,3 +3801,62 @@ struct sctp_chunk *sctp_make_strreset_tsnresp(
 
 	return retval;
 }
+
+bool sctp_verify_reconf(const struct sctp_association *asoc,
+			struct sctp_chunk *chunk,
+			struct sctp_paramhdr **errp)
+{
+	struct sctp_reconf_chunk *hdr;
+	union sctp_params param;
+	__u16 last = 0, cnt = 0;
+
+	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
+	sctp_walk_params(param, hdr, params) {
+		__u16 length = ntohs(param.p->length);
+
+		*errp = param.p;
+		if (cnt++ > 2)
+			return false;
+		switch (param.p->type) {
+		case SCTP_PARAM_RESET_OUT_REQUEST:
+			if (length < sizeof(struct sctp_strreset_outreq) ||
+			    (last && last != SCTP_PARAM_RESET_RESPONSE &&
+			     last != SCTP_PARAM_RESET_IN_REQUEST))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_IN_REQUEST:
+			if (length < sizeof(struct sctp_strreset_inreq) ||
+			    (last && last != SCTP_PARAM_RESET_OUT_REQUEST))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_RESPONSE:
+			if ((length != sizeof(struct sctp_strreset_resp) &&
+			     length != sizeof(struct sctp_strreset_resptsn)) ||
+			    (last && last != SCTP_PARAM_RESET_RESPONSE &&
+			     last != SCTP_PARAM_RESET_OUT_REQUEST))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_TSN_REQUEST:
+			if (length !+			    sizeof(struct sctp_strreset_tsnreq) || last)
+				return false;
+			break;
+		case SCTP_PARAM_RESET_ADD_IN_STREAMS:
+			if (length != sizeof(struct sctp_strreset_addstrm) ||
+			    (last && last != SCTP_PARAM_RESET_ADD_OUT_STREAMS))
+				return false;
+			break;
+		case SCTP_PARAM_RESET_ADD_OUT_STREAMS:
+			if (length != sizeof(struct sctp_strreset_addstrm) ||
+			    (last && last != SCTP_PARAM_RESET_ADD_IN_STREAMS))
+				return false;
+			break;
+		default:
+			return false;
+		}
+
+		last = param.p->type;
+	}
+
+	return true;
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 6/7] sctp: add reconf chunk process
  2017-02-17  4:45           ` Xin Long
@ 2017-02-17  4:45             ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add a function to process the incoming reconf chunk,
in which it verifies the chunk, and traverses the param and process
it with the right function one by one.

sctp_sf_do_reconf would be the process function of reconf chunk event.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  1 +
 net/sctp/sm_statefuns.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index ca9fbfb..b6f682e 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -135,6 +135,7 @@ sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
 sctp_state_fn_t sctp_sf_cookie_echoed_err;
 sctp_state_fn_t sctp_sf_do_asconf;
 sctp_state_fn_t sctp_sf_do_asconf_ack;
+sctp_state_fn_t sctp_sf_do_reconf;
 sctp_state_fn_t sctp_sf_do_9_2_reshutack;
 sctp_state_fn_t sctp_sf_eat_fwd_tsn;
 sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d8798dd..e03bb1a 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3834,6 +3834,60 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net,
 	return SCTP_DISPOSITION_DISCARD;
 }
 
+/* RE-CONFIG Section 5.2 Upon reception of an RECONF Chunk. */
+sctp_disposition_t sctp_sf_do_reconf(struct net *net,
+				     const struct sctp_endpoint *ep,
+				     const struct sctp_association *asoc,
+				     const sctp_subtype_t type, void *arg,
+				     sctp_cmd_seq_t *commands)
+{
+	struct sctp_paramhdr *err_param = NULL;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_reconf_chunk *hdr;
+	union sctp_params param;
+
+	if (!sctp_vtag_verify(chunk, asoc)) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
+				SCTP_NULL());
+		return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+	}
+
+	/* Make sure that the RECONF chunk has a valid length.  */
+	if (!sctp_chunk_length_valid(chunk, sizeof(*hdr)))
+		return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+						  commands);
+
+	if (!sctp_verify_reconf(asoc, chunk, &err_param))
+		return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
+						  (void *)err_param, commands);
+
+	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
+	sctp_walk_params(param, hdr, params) {
+		struct sctp_chunk *reply = NULL;
+		struct sctp_ulpevent *ev = NULL;
+
+		if (param.p->type == SCTP_PARAM_RESET_OUT_REQUEST)
+			reply = sctp_process_strreset_outreq(
+				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
+			reply = sctp_process_strreset_inreq(
+				(struct sctp_association *)asoc, param, &ev);
+		/* More handles for other types will be added here, by now it
+		 * just ignores other types.
+		 */
+
+		if (ev)
+			sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+					SCTP_ULPEVENT(ev));
+
+		if (reply)
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(reply));
+	}
+
+	return SCTP_DISPOSITION_CONSUME;
+}
+
 /*
  * PR-SCTP Section 3.6 Receiver Side Implementation of PR-SCTP
  *
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 6/7] sctp: add reconf chunk process
@ 2017-02-17  4:45             ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add a function to process the incoming reconf chunk,
in which it verifies the chunk, and traverses the param and process
it with the right function one by one.

sctp_sf_do_reconf would be the process function of reconf chunk event.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  1 +
 net/sctp/sm_statefuns.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index ca9fbfb..b6f682e 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -135,6 +135,7 @@ sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
 sctp_state_fn_t sctp_sf_cookie_echoed_err;
 sctp_state_fn_t sctp_sf_do_asconf;
 sctp_state_fn_t sctp_sf_do_asconf_ack;
+sctp_state_fn_t sctp_sf_do_reconf;
 sctp_state_fn_t sctp_sf_do_9_2_reshutack;
 sctp_state_fn_t sctp_sf_eat_fwd_tsn;
 sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d8798dd..e03bb1a 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3834,6 +3834,60 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net,
 	return SCTP_DISPOSITION_DISCARD;
 }
 
+/* RE-CONFIG Section 5.2 Upon reception of an RECONF Chunk. */
+sctp_disposition_t sctp_sf_do_reconf(struct net *net,
+				     const struct sctp_endpoint *ep,
+				     const struct sctp_association *asoc,
+				     const sctp_subtype_t type, void *arg,
+				     sctp_cmd_seq_t *commands)
+{
+	struct sctp_paramhdr *err_param = NULL;
+	struct sctp_chunk *chunk = arg;
+	struct sctp_reconf_chunk *hdr;
+	union sctp_params param;
+
+	if (!sctp_vtag_verify(chunk, asoc)) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
+				SCTP_NULL());
+		return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+	}
+
+	/* Make sure that the RECONF chunk has a valid length.  */
+	if (!sctp_chunk_length_valid(chunk, sizeof(*hdr)))
+		return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+						  commands);
+
+	if (!sctp_verify_reconf(asoc, chunk, &err_param))
+		return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
+						  (void *)err_param, commands);
+
+	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
+	sctp_walk_params(param, hdr, params) {
+		struct sctp_chunk *reply = NULL;
+		struct sctp_ulpevent *ev = NULL;
+
+		if (param.p->type = SCTP_PARAM_RESET_OUT_REQUEST)
+			reply = sctp_process_strreset_outreq(
+				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
+			reply = sctp_process_strreset_inreq(
+				(struct sctp_association *)asoc, param, &ev);
+		/* More handles for other types will be added here, by now it
+		 * just ignores other types.
+		 */
+
+		if (ev)
+			sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+					SCTP_ULPEVENT(ev));
+
+		if (reply)
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(reply));
+	}
+
+	return SCTP_DISPOSITION_CONSUME;
+}
+
 /*
  * PR-SCTP Section 3.6 Receiver Side Implementation of PR-SCTP
  *
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 7/7] sctp: add reconf chunk event
  2017-02-17  4:45             ` Xin Long
@ 2017-02-17  4:45               ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add reconf chunk event based on the sctp event
frame in rx path, it will call sctp_sf_do_reconf to process the
reconf chunk.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/constants.h |  3 +++
 net/sctp/sm_statetable.c     | 30 ++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 3567c97..b07a745 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -60,11 +60,14 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM };
 
 #define SCTP_NUM_PRSCTP_CHUNK_TYPES	1
 
+#define SCTP_NUM_RECONF_CHUNK_TYPES	1
+
 #define SCTP_NUM_AUTH_CHUNK_TYPES	1
 
 #define SCTP_NUM_CHUNK_TYPES		(SCTP_NUM_BASE_CHUNK_TYPES + \
 					 SCTP_NUM_ADDIP_CHUNK_TYPES +\
 					 SCTP_NUM_PRSCTP_CHUNK_TYPES +\
+					 SCTP_NUM_RECONF_CHUNK_TYPES +\
 					 SCTP_NUM_AUTH_CHUNK_TYPES)
 
 /* These are the different flavours of event.  */
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index b5438b4..419b18e 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -482,6 +482,32 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN
 	TYPE_SCTP_FWD_TSN,
 }; /*state_fn_t prsctp_chunk_event_table[][] */
 
+#define TYPE_SCTP_RECONF { \
+	/* SCTP_STATE_CLOSED */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_COOKIE_WAIT */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_COOKIE_ECHOED */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_ESTABLISHED */ \
+	TYPE_SCTP_FUNC(sctp_sf_do_reconf), \
+	/* SCTP_STATE_SHUTDOWN_PENDING */ \
+	TYPE_SCTP_FUNC(sctp_sf_do_reconf), \
+	/* SCTP_STATE_SHUTDOWN_SENT */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+} /* TYPE_SCTP_RECONF */
+
+/* The primary index for this table is the chunk type.
+ * The secondary index for this table is the state.
+ */
+static const sctp_sm_table_entry_t reconf_chunk_event_table[SCTP_NUM_RECONF_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+	TYPE_SCTP_RECONF,
+}; /*state_fn_t reconf_chunk_event_table[][] */
+
 #define TYPE_SCTP_AUTH { \
 	/* SCTP_STATE_CLOSED */ \
 	TYPE_SCTP_FUNC(sctp_sf_ootb), \
@@ -964,6 +990,10 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net,
 			return &addip_chunk_event_table[1][state];
 	}
 
+	if (net->sctp.reconf_enable)
+		if (cid == SCTP_CID_RECONF)
+			return &reconf_chunk_event_table[0][state];
+
 	if (net->sctp.auth_enable) {
 		if (cid == SCTP_CID_AUTH)
 			return &auth_chunk_event_table[0][state];
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 7/7] sctp: add reconf chunk event
@ 2017-02-17  4:45               ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-02-17  4:45 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add reconf chunk event based on the sctp event
frame in rx path, it will call sctp_sf_do_reconf to process the
reconf chunk.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/constants.h |  3 +++
 net/sctp/sm_statetable.c     | 30 ++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 3567c97..b07a745 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -60,11 +60,14 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM };
 
 #define SCTP_NUM_PRSCTP_CHUNK_TYPES	1
 
+#define SCTP_NUM_RECONF_CHUNK_TYPES	1
+
 #define SCTP_NUM_AUTH_CHUNK_TYPES	1
 
 #define SCTP_NUM_CHUNK_TYPES		(SCTP_NUM_BASE_CHUNK_TYPES + \
 					 SCTP_NUM_ADDIP_CHUNK_TYPES +\
 					 SCTP_NUM_PRSCTP_CHUNK_TYPES +\
+					 SCTP_NUM_RECONF_CHUNK_TYPES +\
 					 SCTP_NUM_AUTH_CHUNK_TYPES)
 
 /* These are the different flavours of event.  */
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index b5438b4..419b18e 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -482,6 +482,32 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN
 	TYPE_SCTP_FWD_TSN,
 }; /*state_fn_t prsctp_chunk_event_table[][] */
 
+#define TYPE_SCTP_RECONF { \
+	/* SCTP_STATE_CLOSED */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_COOKIE_WAIT */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_COOKIE_ECHOED */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_ESTABLISHED */ \
+	TYPE_SCTP_FUNC(sctp_sf_do_reconf), \
+	/* SCTP_STATE_SHUTDOWN_PENDING */ \
+	TYPE_SCTP_FUNC(sctp_sf_do_reconf), \
+	/* SCTP_STATE_SHUTDOWN_SENT */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+	TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+} /* TYPE_SCTP_RECONF */
+
+/* The primary index for this table is the chunk type.
+ * The secondary index for this table is the state.
+ */
+static const sctp_sm_table_entry_t reconf_chunk_event_table[SCTP_NUM_RECONF_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+	TYPE_SCTP_RECONF,
+}; /*state_fn_t reconf_chunk_event_table[][] */
+
 #define TYPE_SCTP_AUTH { \
 	/* SCTP_STATE_CLOSED */ \
 	TYPE_SCTP_FUNC(sctp_sf_ootb), \
@@ -964,6 +990,10 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net,
 			return &addip_chunk_event_table[1][state];
 	}
 
+	if (net->sctp.reconf_enable)
+		if (cid = SCTP_CID_RECONF)
+			return &reconf_chunk_event_table[0][state];
+
 	if (net->sctp.auth_enable) {
 		if (cid = SCTP_CID_AUTH)
 			return &auth_chunk_event_table[0][state];
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk
  2017-02-17  4:45 ` Xin Long
@ 2017-02-19 23:18   ` David Miller
  -1 siblings, 0 replies; 50+ messages in thread
From: David Miller @ 2017-02-19 23:18 UTC (permalink / raw)
  To: lucien.xin; +Cc: netdev, linux-sctp, marcelo.leitner, nhorman, vyasevich

From: Xin Long <lucien.xin@gmail.com>
Date: Fri, 17 Feb 2017 12:45:36 +0800

> Patch 3/7 and 4/7 are to implement receiver-side procedures for the
> Outgoing and Incoming SSN Reset Request Parameter described in rfc6525
> section 5.2.2 and 5.2.3
> 
> Patch 1/7 and 2/7 are ahead of them to define some apis.
> 
> Patch 5/7-7/7 are to add the process of reconf chunk event in rx path.
> 
> Note that with this patchset, asoc->reconf_enable has no chance yet to
> be set, until the patch "sctp: add get and set sockopt for reconf_enable"
> is applied in the future. As we can not just enable it when sctp is not
> capable of processing reconf chunk yet.
 ...

Series applied, thanks.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request ch
@ 2017-02-19 23:18   ` David Miller
  0 siblings, 0 replies; 50+ messages in thread
From: David Miller @ 2017-02-19 23:18 UTC (permalink / raw)
  To: lucien.xin; +Cc: netdev, linux-sctp, marcelo.leitner, nhorman, vyasevich

From: Xin Long <lucien.xin@gmail.com>
Date: Fri, 17 Feb 2017 12:45:36 +0800

> Patch 3/7 and 4/7 are to implement receiver-side procedures for the
> Outgoing and Incoming SSN Reset Request Parameter described in rfc6525
> section 5.2.2 and 5.2.3
> 
> Patch 1/7 and 2/7 are ahead of them to define some apis.
> 
> Patch 5/7-7/7 are to add the process of reconf chunk event in rx path.
> 
> Note that with this patchset, asoc->reconf_enable has no chance yet to
> be set, until the patch "sctp: add get and set sockopt for reconf_enable"
> is applied in the future. As we can not just enable it when sctp is not
> capable of processing reconf chunk yet.
 ...

Series applied, thanks.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add streams and response
  2017-02-17  4:45 ` Xin Long
@ 2017-03-10  4:11 ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

Patch 2/7, 4/7, 5/7, 6/7 are to implement the process of asoc reset request,
add streams requests and all kinds of responses.

Patch 1/7 and 3/7 are ahead of 2/7 and 4/7 to add two event notification
for asoc reset and add streams.

Patch 7/7 is the last patch for implementing rfc6525 sctp stream reconf
to add sysctl and sockopt interface for users to enable sctp stream reconf.

After this patchset, sctp stream reconf will be able to work as rfc6525.

v1->v2:
  - put these into a smaller group.
  - rename the titles of the commits and improve some changelogs.
  - improve sctp_chunk_lookup_strreset_param and reuse it in patch 4/7.
  - process addstrm outreq as the ack of in addstrm inreq if strreset_chunk
    is not NULL in patch 4/7.
  - remove the stream alloc when sending addstrm inreq, and the process in
    peer will response it by sending a addstrm out request back in patch 5/7.
  - adjust the process of addstrm in resp to fit in the codes that only alloc
    streams through addstrm outreq in patch 6/7.

Xin Long (7):
  sctp: add support for generating assoc reset event notification
  sctp: implement receiver-side procedures for the SSN/TSN Reset Request
    Parameter
  sctp: add support for generating add stream change event notification
  sctp: implement receiver-side procedures for the Add Outgoing Streams
    Request Parameter
  sctp: implement receiver-side procedures for the Add Incoming Streams
    Request Parameter
  sctp: implement receiver-side procedures for the Reconf Response
    Parameter
  sctp: add get and set sockopt for reconf_enable

 include/net/sctp/sm.h       |  16 ++
 include/net/sctp/ulpevent.h |   8 +
 include/uapi/linux/sctp.h   |  31 ++++
 net/sctp/sm_statefuns.c     |  15 +-
 net/sctp/socket.c           |  81 +++++++++
 net/sctp/stream.c           | 396 +++++++++++++++++++++++++++++++++++++++++---
 net/sctp/sysctl.c           |   7 +
 net/sctp/ulpevent.c         |  56 +++++++
 8 files changed, 585 insertions(+), 25 deletions(-)

-- 
2.1.0

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add strea
@ 2017-03-10  4:11 ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

Patch 2/7, 4/7, 5/7, 6/7 are to implement the process of asoc reset request,
add streams requests and all kinds of responses.

Patch 1/7 and 3/7 are ahead of 2/7 and 4/7 to add two event notification
for asoc reset and add streams.

Patch 7/7 is the last patch for implementing rfc6525 sctp stream reconf
to add sysctl and sockopt interface for users to enable sctp stream reconf.

After this patchset, sctp stream reconf will be able to work as rfc6525.

v1->v2:
  - put these into a smaller group.
  - rename the titles of the commits and improve some changelogs.
  - improve sctp_chunk_lookup_strreset_param and reuse it in patch 4/7.
  - process addstrm outreq as the ack of in addstrm inreq if strreset_chunk
    is not NULL in patch 4/7.
  - remove the stream alloc when sending addstrm inreq, and the process in
    peer will response it by sending a addstrm out request back in patch 5/7.
  - adjust the process of addstrm in resp to fit in the codes that only alloc
    streams through addstrm outreq in patch 6/7.

Xin Long (7):
  sctp: add support for generating assoc reset event notification
  sctp: implement receiver-side procedures for the SSN/TSN Reset Request
    Parameter
  sctp: add support for generating add stream change event notification
  sctp: implement receiver-side procedures for the Add Outgoing Streams
    Request Parameter
  sctp: implement receiver-side procedures for the Add Incoming Streams
    Request Parameter
  sctp: implement receiver-side procedures for the Reconf Response
    Parameter
  sctp: add get and set sockopt for reconf_enable

 include/net/sctp/sm.h       |  16 ++
 include/net/sctp/ulpevent.h |   8 +
 include/uapi/linux/sctp.h   |  31 ++++
 net/sctp/sm_statefuns.c     |  15 +-
 net/sctp/socket.c           |  81 +++++++++
 net/sctp/stream.c           | 396 +++++++++++++++++++++++++++++++++++++++++---
 net/sctp/sysctl.c           |   7 +
 net/sctp/ulpevent.c         |  56 +++++++
 8 files changed, 585 insertions(+), 25 deletions(-)

-- 
2.1.0


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 1/7] sctp: add support for generating assoc reset event notification
  2017-03-10  4:11 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add strea Xin Long
@ 2017-03-10  4:11   ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Association Reset Event described in rfc6525
section 6.1.2.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/ulpevent.h |  4 ++++
 include/uapi/linux/sctp.h   | 15 +++++++++++++++
 net/sctp/ulpevent.c         | 28 ++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 324b596..2ab7ed4 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -132,6 +132,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
 	const struct sctp_association *asoc, __u16 flags,
 	__u16 stream_num, __u16 *stream_list, gfp_t gfp);
 
+struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
+	const struct sctp_association *asoc, __u16 flags,
+	 __u32 local_tsn, __u32 remote_tsn, gfp_t gfp);
+
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *);
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index d3ae381..7735829 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -502,6 +502,17 @@ struct sctp_stream_reset_event {
 	__u16 strreset_stream_list[];
 };
 
+#define SCTP_ASSOC_RESET_DENIED		0x0004
+#define SCTP_ASSOC_RESET_FAILED		0x0008
+struct sctp_assoc_reset_event {
+	__u16 assocreset_type;
+	__u16 assocreset_flags;
+	__u32 assocreset_length;
+	sctp_assoc_t assocreset_assoc_id;
+	__u32 assocreset_local_tsn;
+	__u32 assocreset_remote_tsn;
+};
+
 /*
  * Described in Section 7.3
  *   Ancillary Data and Notification Interest Options
@@ -518,6 +529,7 @@ struct sctp_event_subscribe {
 	__u8 sctp_authentication_event;
 	__u8 sctp_sender_dry_event;
 	__u8 sctp_stream_reset_event;
+	__u8 sctp_assoc_reset_event;
 };
 
 /*
@@ -543,6 +555,7 @@ union sctp_notification {
 	struct sctp_authkey_event sn_authkey_event;
 	struct sctp_sender_dry_event sn_sender_dry_event;
 	struct sctp_stream_reset_event sn_strreset_event;
+	struct sctp_assoc_reset_event sn_assocreset_event;
 };
 
 /* Section 5.3.1
@@ -572,6 +585,8 @@ enum sctp_sn_type {
 #define SCTP_SENDER_DRY_EVENT		SCTP_SENDER_DRY_EVENT
 	SCTP_STREAM_RESET_EVENT,
 #define SCTP_STREAM_RESET_EVENT		SCTP_STREAM_RESET_EVENT
+	SCTP_ASSOC_RESET_EVENT,
+#define SCTP_ASSOC_RESET_EVENT		SCTP_ASSOC_RESET_EVENT
 };
 
 /* Notification error codes used to fill up the error fields in some
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index c8881bc5..420d7f3 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -883,6 +883,34 @@ struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
 	return event;
 }
 
+struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
+	const struct sctp_association *asoc, __u16 flags, __u32 local_tsn,
+	__u32 remote_tsn, gfp_t gfp)
+{
+	struct sctp_assoc_reset_event *areset;
+	struct sctp_ulpevent *event;
+	struct sk_buff *skb;
+
+	event = sctp_ulpevent_new(sizeof(struct sctp_assoc_reset_event),
+				  MSG_NOTIFICATION, gfp);
+	if (!event)
+		return NULL;
+
+	skb = sctp_event2skb(event);
+	areset = (struct sctp_assoc_reset_event *)
+		skb_put(skb, sizeof(struct sctp_assoc_reset_event));
+
+	areset->assocreset_type = SCTP_ASSOC_RESET_EVENT;
+	areset->assocreset_flags = flags;
+	areset->assocreset_length = sizeof(struct sctp_assoc_reset_event);
+	sctp_ulpevent_set_owner(event, asoc);
+	areset->assocreset_assoc_id = sctp_assoc2id(asoc);
+	areset->assocreset_local_tsn = local_tsn;
+	areset->assocreset_remote_tsn = remote_tsn;
+
+	return event;
+}
+
 /* Return the notification type, assuming this is a notification
  * event.
  */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 1/7] sctp: add support for generating assoc reset event notification
@ 2017-03-10  4:11   ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Association Reset Event described in rfc6525
section 6.1.2.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/ulpevent.h |  4 ++++
 include/uapi/linux/sctp.h   | 15 +++++++++++++++
 net/sctp/ulpevent.c         | 28 ++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 324b596..2ab7ed4 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -132,6 +132,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
 	const struct sctp_association *asoc, __u16 flags,
 	__u16 stream_num, __u16 *stream_list, gfp_t gfp);
 
+struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
+	const struct sctp_association *asoc, __u16 flags,
+	 __u32 local_tsn, __u32 remote_tsn, gfp_t gfp);
+
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *);
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index d3ae381..7735829 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -502,6 +502,17 @@ struct sctp_stream_reset_event {
 	__u16 strreset_stream_list[];
 };
 
+#define SCTP_ASSOC_RESET_DENIED		0x0004
+#define SCTP_ASSOC_RESET_FAILED		0x0008
+struct sctp_assoc_reset_event {
+	__u16 assocreset_type;
+	__u16 assocreset_flags;
+	__u32 assocreset_length;
+	sctp_assoc_t assocreset_assoc_id;
+	__u32 assocreset_local_tsn;
+	__u32 assocreset_remote_tsn;
+};
+
 /*
  * Described in Section 7.3
  *   Ancillary Data and Notification Interest Options
@@ -518,6 +529,7 @@ struct sctp_event_subscribe {
 	__u8 sctp_authentication_event;
 	__u8 sctp_sender_dry_event;
 	__u8 sctp_stream_reset_event;
+	__u8 sctp_assoc_reset_event;
 };
 
 /*
@@ -543,6 +555,7 @@ union sctp_notification {
 	struct sctp_authkey_event sn_authkey_event;
 	struct sctp_sender_dry_event sn_sender_dry_event;
 	struct sctp_stream_reset_event sn_strreset_event;
+	struct sctp_assoc_reset_event sn_assocreset_event;
 };
 
 /* Section 5.3.1
@@ -572,6 +585,8 @@ enum sctp_sn_type {
 #define SCTP_SENDER_DRY_EVENT		SCTP_SENDER_DRY_EVENT
 	SCTP_STREAM_RESET_EVENT,
 #define SCTP_STREAM_RESET_EVENT		SCTP_STREAM_RESET_EVENT
+	SCTP_ASSOC_RESET_EVENT,
+#define SCTP_ASSOC_RESET_EVENT		SCTP_ASSOC_RESET_EVENT
 };
 
 /* Notification error codes used to fill up the error fields in some
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index c8881bc5..420d7f3 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -883,6 +883,34 @@ struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
 	return event;
 }
 
+struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
+	const struct sctp_association *asoc, __u16 flags, __u32 local_tsn,
+	__u32 remote_tsn, gfp_t gfp)
+{
+	struct sctp_assoc_reset_event *areset;
+	struct sctp_ulpevent *event;
+	struct sk_buff *skb;
+
+	event = sctp_ulpevent_new(sizeof(struct sctp_assoc_reset_event),
+				  MSG_NOTIFICATION, gfp);
+	if (!event)
+		return NULL;
+
+	skb = sctp_event2skb(event);
+	areset = (struct sctp_assoc_reset_event *)
+		skb_put(skb, sizeof(struct sctp_assoc_reset_event));
+
+	areset->assocreset_type = SCTP_ASSOC_RESET_EVENT;
+	areset->assocreset_flags = flags;
+	areset->assocreset_length = sizeof(struct sctp_assoc_reset_event);
+	sctp_ulpevent_set_owner(event, asoc);
+	areset->assocreset_assoc_id = sctp_assoc2id(asoc);
+	areset->assocreset_local_tsn = local_tsn;
+	areset->assocreset_remote_tsn = remote_tsn;
+
+	return event;
+}
+
 /* Return the notification type, assuming this is a notification
  * event.
  */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter
  2017-03-10  4:11   ` Xin Long
@ 2017-03-10  4:11     ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the SSN/TSN
Reset Request Parameter described in rfc6525 section 6.2.4.

The process is kind of complicate, it's wonth having some comments
from section 6.2.4 in the codes.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  4 +++
 net/sctp/sm_statefuns.c |  3 ++
 net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index b6f682e..2629d66 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_tsnreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index e03bb1a..6982064 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
 			reply = sctp_process_strreset_inreq(
 				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
+			reply = sctp_process_strreset_tsnreq(
+				(struct sctp_association *)asoc, param, &ev);
 		/* More handles for other types will be added here, by now it
 		 * just ignores other types.
 		 */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 1c6cc04..7e993b0 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 
 	return chunk;
 }
+
+struct sctp_chunk *sctp_process_strreset_tsnreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	__u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
+	struct sctp_strreset_tsnreq *tsnreq = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	__u32 request_seq;
+	__u16 i;
+
+	request_seq = ntohl(tsnreq->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq == asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
+		goto out;
+
+	if (asoc->strreset_outstanding) {
+		result = SCTP_STRRESET_ERR_IN_PROGRESS;
+		goto out;
+	}
+
+	/* G3: The same processing as though a SACK chunk with no gap report
+	 *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
+	 *     received MUST be performed.
+	 */
+	max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
+	sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
+	sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
+
+	/* G1: Compute an appropriate value for the Receiver's Next TSN -- the
+	 *     TSN that the peer should use to send the next DATA chunk.  The
+	 *     value SHOULD be the smallest TSN not acknowledged by the
+	 *     receiver of the request plus 2^31.
+	 */
+	init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
+	sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
+			 init_tsn, GFP_ATOMIC);
+
+	/* G4: The same processing as though a FWD-TSN chunk (as defined in
+	 *     [RFC3758]) with all streams affected and a new cumulative TSN
+	 *     ACK of the Receiver's Next TSN minus 1 were received MUST be
+	 *     performed.
+	 */
+	sctp_outq_free(&asoc->outqueue);
+
+	/* G2: Compute an appropriate value for the local endpoint's next TSN,
+	 *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
+	 *     chunk.  The value SHOULD be the highest TSN sent by the receiver
+	 *     of the request plus 1.
+	 */
+	next_tsn = asoc->next_tsn;
+	asoc->ctsn_ack_point = next_tsn - 1;
+	asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
+
+	/* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
+	 *      incoming and outgoing streams.
+	 */
+	for (i = 0; i < stream->outcnt; i++)
+		stream->out[i].ssn = 0;
+	for (i = 0; i < stream->incnt; i++)
+		stream->in[i].ssn = 0;
+
+	result = SCTP_STRRESET_PERFORMED;
+
+	*evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
+						    next_tsn, GFP_ATOMIC);
+
+out:
+	return sctp_make_strreset_tsnresp(asoc, result, request_seq,
+					  next_tsn, init_tsn);
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parame
@ 2017-03-10  4:11     ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the SSN/TSN
Reset Request Parameter described in rfc6525 section 6.2.4.

The process is kind of complicate, it's wonth having some comments
from section 6.2.4 in the codes.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  4 +++
 net/sctp/sm_statefuns.c |  3 ++
 net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index b6f682e..2629d66 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_tsnreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index e03bb1a..6982064 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
 			reply = sctp_process_strreset_inreq(
 				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
+			reply = sctp_process_strreset_tsnreq(
+				(struct sctp_association *)asoc, param, &ev);
 		/* More handles for other types will be added here, by now it
 		 * just ignores other types.
 		 */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 1c6cc04..7e993b0 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 
 	return chunk;
 }
+
+struct sctp_chunk *sctp_process_strreset_tsnreq(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	__u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
+	struct sctp_strreset_tsnreq *tsnreq = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	__u32 request_seq;
+	__u16 i;
+
+	request_seq = ntohl(tsnreq->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq = asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
+		goto out;
+
+	if (asoc->strreset_outstanding) {
+		result = SCTP_STRRESET_ERR_IN_PROGRESS;
+		goto out;
+	}
+
+	/* G3: The same processing as though a SACK chunk with no gap report
+	 *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
+	 *     received MUST be performed.
+	 */
+	max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
+	sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
+	sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
+
+	/* G1: Compute an appropriate value for the Receiver's Next TSN -- the
+	 *     TSN that the peer should use to send the next DATA chunk.  The
+	 *     value SHOULD be the smallest TSN not acknowledged by the
+	 *     receiver of the request plus 2^31.
+	 */
+	init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
+	sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
+			 init_tsn, GFP_ATOMIC);
+
+	/* G4: The same processing as though a FWD-TSN chunk (as defined in
+	 *     [RFC3758]) with all streams affected and a new cumulative TSN
+	 *     ACK of the Receiver's Next TSN minus 1 were received MUST be
+	 *     performed.
+	 */
+	sctp_outq_free(&asoc->outqueue);
+
+	/* G2: Compute an appropriate value for the local endpoint's next TSN,
+	 *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
+	 *     chunk.  The value SHOULD be the highest TSN sent by the receiver
+	 *     of the request plus 1.
+	 */
+	next_tsn = asoc->next_tsn;
+	asoc->ctsn_ack_point = next_tsn - 1;
+	asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
+
+	/* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
+	 *      incoming and outgoing streams.
+	 */
+	for (i = 0; i < stream->outcnt; i++)
+		stream->out[i].ssn = 0;
+	for (i = 0; i < stream->incnt; i++)
+		stream->in[i].ssn = 0;
+
+	result = SCTP_STRRESET_PERFORMED;
+
+	*evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
+						    next_tsn, GFP_ATOMIC);
+
+out:
+	return sctp_make_strreset_tsnresp(asoc, result, request_seq,
+					  next_tsn, init_tsn);
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 3/7] sctp: add support for generating add stream change event notification
  2017-03-10  4:11     ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parame Xin Long
@ 2017-03-10  4:11       ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Stream Change Event described in rfc6525
section 6.1.3.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/ulpevent.h |  4 ++++
 include/uapi/linux/sctp.h   | 15 +++++++++++++++
 net/sctp/ulpevent.c         | 28 ++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 2ab7ed4..1060494 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -136,6 +136,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
 	const struct sctp_association *asoc, __u16 flags,
 	 __u32 local_tsn, __u32 remote_tsn, gfp_t gfp);
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_change_event(
+	const struct sctp_association *asoc, __u16 flags,
+	__u32 strchange_instrms, __u32 strchange_outstrms, gfp_t gfp);
+
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *);
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 7735829..fd652e6 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -513,6 +513,17 @@ struct sctp_assoc_reset_event {
 	__u32 assocreset_remote_tsn;
 };
 
+#define SCTP_ASSOC_CHANGE_DENIED	0x0004
+#define SCTP_ASSOC_CHANGE_FAILED	0x0008
+struct sctp_stream_change_event {
+	__u16 strchange_type;
+	__u16 strchange_flags;
+	__u32 strchange_length;
+	sctp_assoc_t strchange_assoc_id;
+	__u16 strchange_instrms;
+	__u16 strchange_outstrms;
+};
+
 /*
  * Described in Section 7.3
  *   Ancillary Data and Notification Interest Options
@@ -530,6 +541,7 @@ struct sctp_event_subscribe {
 	__u8 sctp_sender_dry_event;
 	__u8 sctp_stream_reset_event;
 	__u8 sctp_assoc_reset_event;
+	__u8 sctp_stream_change_event;
 };
 
 /*
@@ -556,6 +568,7 @@ union sctp_notification {
 	struct sctp_sender_dry_event sn_sender_dry_event;
 	struct sctp_stream_reset_event sn_strreset_event;
 	struct sctp_assoc_reset_event sn_assocreset_event;
+	struct sctp_stream_change_event sn_strchange_event;
 };
 
 /* Section 5.3.1
@@ -587,6 +600,8 @@ enum sctp_sn_type {
 #define SCTP_STREAM_RESET_EVENT		SCTP_STREAM_RESET_EVENT
 	SCTP_ASSOC_RESET_EVENT,
 #define SCTP_ASSOC_RESET_EVENT		SCTP_ASSOC_RESET_EVENT
+	SCTP_STREAM_CHANGE_EVENT,
+#define SCTP_STREAM_CHANGE_EVENT	SCTP_STREAM_CHANGE_EVENT
 };
 
 /* Notification error codes used to fill up the error fields in some
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 420d7f3..ec2b3e0 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -911,6 +911,34 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
 	return event;
 }
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_change_event(
+	const struct sctp_association *asoc, __u16 flags,
+	__u32 strchange_instrms, __u32 strchange_outstrms, gfp_t gfp)
+{
+	struct sctp_stream_change_event *schange;
+	struct sctp_ulpevent *event;
+	struct sk_buff *skb;
+
+	event = sctp_ulpevent_new(sizeof(struct sctp_stream_change_event),
+				  MSG_NOTIFICATION, gfp);
+	if (!event)
+		return NULL;
+
+	skb = sctp_event2skb(event);
+	schange = (struct sctp_stream_change_event *)
+		skb_put(skb, sizeof(struct sctp_stream_change_event));
+
+	schange->strchange_type = SCTP_STREAM_CHANGE_EVENT;
+	schange->strchange_flags = flags;
+	schange->strchange_length = sizeof(struct sctp_stream_change_event);
+	sctp_ulpevent_set_owner(event, asoc);
+	schange->strchange_assoc_id = sctp_assoc2id(asoc);
+	schange->strchange_instrms = strchange_instrms;
+	schange->strchange_outstrms = strchange_outstrms;
+
+	return event;
+}
+
 /* Return the notification type, assuming this is a notification
  * event.
  */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 3/7] sctp: add support for generating add stream change event notification
@ 2017-03-10  4:11       ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Stream Change Event described in rfc6525
section 6.1.3.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/ulpevent.h |  4 ++++
 include/uapi/linux/sctp.h   | 15 +++++++++++++++
 net/sctp/ulpevent.c         | 28 ++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 2ab7ed4..1060494 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -136,6 +136,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
 	const struct sctp_association *asoc, __u16 flags,
 	 __u32 local_tsn, __u32 remote_tsn, gfp_t gfp);
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_change_event(
+	const struct sctp_association *asoc, __u16 flags,
+	__u32 strchange_instrms, __u32 strchange_outstrms, gfp_t gfp);
+
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *);
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 7735829..fd652e6 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -513,6 +513,17 @@ struct sctp_assoc_reset_event {
 	__u32 assocreset_remote_tsn;
 };
 
+#define SCTP_ASSOC_CHANGE_DENIED	0x0004
+#define SCTP_ASSOC_CHANGE_FAILED	0x0008
+struct sctp_stream_change_event {
+	__u16 strchange_type;
+	__u16 strchange_flags;
+	__u32 strchange_length;
+	sctp_assoc_t strchange_assoc_id;
+	__u16 strchange_instrms;
+	__u16 strchange_outstrms;
+};
+
 /*
  * Described in Section 7.3
  *   Ancillary Data and Notification Interest Options
@@ -530,6 +541,7 @@ struct sctp_event_subscribe {
 	__u8 sctp_sender_dry_event;
 	__u8 sctp_stream_reset_event;
 	__u8 sctp_assoc_reset_event;
+	__u8 sctp_stream_change_event;
 };
 
 /*
@@ -556,6 +568,7 @@ union sctp_notification {
 	struct sctp_sender_dry_event sn_sender_dry_event;
 	struct sctp_stream_reset_event sn_strreset_event;
 	struct sctp_assoc_reset_event sn_assocreset_event;
+	struct sctp_stream_change_event sn_strchange_event;
 };
 
 /* Section 5.3.1
@@ -587,6 +600,8 @@ enum sctp_sn_type {
 #define SCTP_STREAM_RESET_EVENT		SCTP_STREAM_RESET_EVENT
 	SCTP_ASSOC_RESET_EVENT,
 #define SCTP_ASSOC_RESET_EVENT		SCTP_ASSOC_RESET_EVENT
+	SCTP_STREAM_CHANGE_EVENT,
+#define SCTP_STREAM_CHANGE_EVENT	SCTP_STREAM_CHANGE_EVENT
 };
 
 /* Notification error codes used to fill up the error fields in some
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 420d7f3..ec2b3e0 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -911,6 +911,34 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
 	return event;
 }
 
+struct sctp_ulpevent *sctp_ulpevent_make_stream_change_event(
+	const struct sctp_association *asoc, __u16 flags,
+	__u32 strchange_instrms, __u32 strchange_outstrms, gfp_t gfp)
+{
+	struct sctp_stream_change_event *schange;
+	struct sctp_ulpevent *event;
+	struct sk_buff *skb;
+
+	event = sctp_ulpevent_new(sizeof(struct sctp_stream_change_event),
+				  MSG_NOTIFICATION, gfp);
+	if (!event)
+		return NULL;
+
+	skb = sctp_event2skb(event);
+	schange = (struct sctp_stream_change_event *)
+		skb_put(skb, sizeof(struct sctp_stream_change_event));
+
+	schange->strchange_type = SCTP_STREAM_CHANGE_EVENT;
+	schange->strchange_flags = flags;
+	schange->strchange_length = sizeof(struct sctp_stream_change_event);
+	sctp_ulpevent_set_owner(event, asoc);
+	schange->strchange_assoc_id = sctp_assoc2id(asoc);
+	schange->strchange_instrms = strchange_instrms;
+	schange->strchange_outstrms = strchange_outstrms;
+
+	return event;
+}
+
 /* Return the notification type, assuming this is a notification
  * event.
  */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Add Outgoing Streams Request Parameter
  2017-03-10  4:11       ` Xin Long
@ 2017-03-10  4:11         ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Receiver-Side Procedures for the Add Outgoing
Streams Request Parameter described in section 5.2.5.

It is also to improve sctp_chunk_lookup_strreset_param, so that it
can be used for processing addstrm_out request.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  4 +++
 net/sctp/sm_statefuns.c |  3 ++
 net/sctp/stream.c       | 89 +++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 86 insertions(+), 10 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 2629d66..93ae50b 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -297,6 +297,10 @@ struct sctp_chunk *sctp_process_strreset_tsnreq(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_addstrm_out(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 6982064..881122b 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3875,6 +3875,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
 			reply = sctp_process_strreset_tsnreq(
 				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS)
+			reply = sctp_process_strreset_addstrm_out(
+				(struct sctp_association *)asoc, param, &ev);
 		/* More handles for other types will be added here, by now it
 		 * just ignores other types.
 		 */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 7e993b0..df2794d 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -303,13 +303,14 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 }
 
 static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param(
-			struct sctp_association *asoc, __u32 resp_seq)
+			struct sctp_association *asoc, __u32 resp_seq,
+			__be16 type)
 {
 	struct sctp_chunk *chunk = asoc->strreset_chunk;
 	struct sctp_reconf_chunk *hdr;
 	union sctp_params param;
 
-	if (ntohl(resp_seq) != asoc->strreset_outseq || !chunk)
+	if (!chunk)
 		return NULL;
 
 	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
@@ -320,7 +321,8 @@ static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param(
 		 */
 		struct sctp_strreset_tsnreq *req = param.v;
 
-		if (req->request_seq == resp_seq)
+		if ((!resp_seq || req->request_seq == resp_seq) &&
+		    (!type || type == req->param_hdr.type))
 			return param.v;
 	}
 
@@ -361,13 +363,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 		goto out;
 
 	if (asoc->strreset_chunk) {
-		sctp_paramhdr_t *param_hdr;
-		struct sctp_transport *t;
-
-		param_hdr = sctp_chunk_lookup_strreset_param(
-					asoc, outreq->response_seq);
-		if (!param_hdr || param_hdr->type !=
-					SCTP_PARAM_RESET_IN_REQUEST) {
+		if (!sctp_chunk_lookup_strreset_param(
+				asoc, outreq->response_seq,
+				SCTP_PARAM_RESET_IN_REQUEST)) {
 			/* same process with outstanding isn't 0 */
 			result = SCTP_STRRESET_ERR_IN_PROGRESS;
 			goto out;
@@ -377,6 +375,8 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 		asoc->strreset_outseq++;
 
 		if (!asoc->strreset_outstanding) {
+			struct sctp_transport *t;
+
 			t = asoc->strreset_chunk->transport;
 			if (del_timer(&t->reconf_timer))
 				sctp_transport_put(t);
@@ -556,3 +556,72 @@ struct sctp_chunk *sctp_process_strreset_tsnreq(
 	return sctp_make_strreset_tsnresp(asoc, result, request_seq,
 					  next_tsn, init_tsn);
 }
+
+struct sctp_chunk *sctp_process_strreset_addstrm_out(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_addstrm *addstrm = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	struct sctp_stream_in *streamin;
+	__u32 request_seq, incnt;
+	__u16 in;
+
+	request_seq = ntohl(addstrm->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq == asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
+		goto out;
+
+	if (asoc->strreset_chunk) {
+		if (!sctp_chunk_lookup_strreset_param(
+			asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
+			/* same process with outstanding isn't 0 */
+			result = SCTP_STRRESET_ERR_IN_PROGRESS;
+			goto out;
+		}
+
+		asoc->strreset_outstanding--;
+		asoc->strreset_outseq++;
+
+		if (!asoc->strreset_outstanding) {
+			struct sctp_transport *t;
+
+			t = asoc->strreset_chunk->transport;
+			if (del_timer(&t->reconf_timer))
+				sctp_transport_put(t);
+
+			sctp_chunk_put(asoc->strreset_chunk);
+			asoc->strreset_chunk = NULL;
+		}
+	}
+
+	in = ntohs(addstrm->number_of_streams);
+	incnt = stream->incnt + in;
+	if (!in || incnt > SCTP_MAX_STREAM)
+		goto out;
+
+	streamin = krealloc(stream->in, incnt * sizeof(*streamin),
+			    GFP_ATOMIC);
+	if (!streamin)
+		goto out;
+
+	memset(streamin + stream->incnt, 0, in * sizeof(*streamin));
+	stream->in = streamin;
+	stream->incnt = incnt;
+
+	result = SCTP_STRRESET_PERFORMED;
+
+	*evp = sctp_ulpevent_make_stream_change_event(asoc,
+		0, ntohs(addstrm->number_of_streams), 0, GFP_ATOMIC);
+
+out:
+	return sctp_make_strreset_resp(asoc, result, request_seq);
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Add Outgoing Streams Request
@ 2017-03-10  4:11         ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to add Receiver-Side Procedures for the Add Outgoing
Streams Request Parameter described in section 5.2.5.

It is also to improve sctp_chunk_lookup_strreset_param, so that it
can be used for processing addstrm_out request.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  4 +++
 net/sctp/sm_statefuns.c |  3 ++
 net/sctp/stream.c       | 89 +++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 86 insertions(+), 10 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 2629d66..93ae50b 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -297,6 +297,10 @@ struct sctp_chunk *sctp_process_strreset_tsnreq(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_addstrm_out(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 6982064..881122b 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3875,6 +3875,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
 			reply = sctp_process_strreset_tsnreq(
 				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type = SCTP_PARAM_RESET_ADD_OUT_STREAMS)
+			reply = sctp_process_strreset_addstrm_out(
+				(struct sctp_association *)asoc, param, &ev);
 		/* More handles for other types will be added here, by now it
 		 * just ignores other types.
 		 */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 7e993b0..df2794d 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -303,13 +303,14 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 }
 
 static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param(
-			struct sctp_association *asoc, __u32 resp_seq)
+			struct sctp_association *asoc, __u32 resp_seq,
+			__be16 type)
 {
 	struct sctp_chunk *chunk = asoc->strreset_chunk;
 	struct sctp_reconf_chunk *hdr;
 	union sctp_params param;
 
-	if (ntohl(resp_seq) != asoc->strreset_outseq || !chunk)
+	if (!chunk)
 		return NULL;
 
 	hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
@@ -320,7 +321,8 @@ static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param(
 		 */
 		struct sctp_strreset_tsnreq *req = param.v;
 
-		if (req->request_seq = resp_seq)
+		if ((!resp_seq || req->request_seq = resp_seq) &&
+		    (!type || type = req->param_hdr.type))
 			return param.v;
 	}
 
@@ -361,13 +363,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 		goto out;
 
 	if (asoc->strreset_chunk) {
-		sctp_paramhdr_t *param_hdr;
-		struct sctp_transport *t;
-
-		param_hdr = sctp_chunk_lookup_strreset_param(
-					asoc, outreq->response_seq);
-		if (!param_hdr || param_hdr->type !-					SCTP_PARAM_RESET_IN_REQUEST) {
+		if (!sctp_chunk_lookup_strreset_param(
+				asoc, outreq->response_seq,
+				SCTP_PARAM_RESET_IN_REQUEST)) {
 			/* same process with outstanding isn't 0 */
 			result = SCTP_STRRESET_ERR_IN_PROGRESS;
 			goto out;
@@ -377,6 +375,8 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 		asoc->strreset_outseq++;
 
 		if (!asoc->strreset_outstanding) {
+			struct sctp_transport *t;
+
 			t = asoc->strreset_chunk->transport;
 			if (del_timer(&t->reconf_timer))
 				sctp_transport_put(t);
@@ -556,3 +556,72 @@ struct sctp_chunk *sctp_process_strreset_tsnreq(
 	return sctp_make_strreset_tsnresp(asoc, result, request_seq,
 					  next_tsn, init_tsn);
 }
+
+struct sctp_chunk *sctp_process_strreset_addstrm_out(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_addstrm *addstrm = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	struct sctp_stream_in *streamin;
+	__u32 request_seq, incnt;
+	__u16 in;
+
+	request_seq = ntohl(addstrm->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq = asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
+		goto out;
+
+	if (asoc->strreset_chunk) {
+		if (!sctp_chunk_lookup_strreset_param(
+			asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
+			/* same process with outstanding isn't 0 */
+			result = SCTP_STRRESET_ERR_IN_PROGRESS;
+			goto out;
+		}
+
+		asoc->strreset_outstanding--;
+		asoc->strreset_outseq++;
+
+		if (!asoc->strreset_outstanding) {
+			struct sctp_transport *t;
+
+			t = asoc->strreset_chunk->transport;
+			if (del_timer(&t->reconf_timer))
+				sctp_transport_put(t);
+
+			sctp_chunk_put(asoc->strreset_chunk);
+			asoc->strreset_chunk = NULL;
+		}
+	}
+
+	in = ntohs(addstrm->number_of_streams);
+	incnt = stream->incnt + in;
+	if (!in || incnt > SCTP_MAX_STREAM)
+		goto out;
+
+	streamin = krealloc(stream->in, incnt * sizeof(*streamin),
+			    GFP_ATOMIC);
+	if (!streamin)
+		goto out;
+
+	memset(streamin + stream->incnt, 0, in * sizeof(*streamin));
+	stream->in = streamin;
+	stream->incnt = incnt;
+
+	result = SCTP_STRRESET_PERFORMED;
+
+	*evp = sctp_ulpevent_make_stream_change_event(asoc,
+		0, ntohs(addstrm->number_of_streams), 0, GFP_ATOMIC);
+
+out:
+	return sctp_make_strreset_resp(asoc, result, request_seq);
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 5/7] sctp: implement receiver-side procedures for the Add Incoming Streams Request Parameter
  2017-03-10  4:11         ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Add Outgoing Streams Request Xin Long
@ 2017-03-10  4:11           ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the Add Incoming
Streams Request Parameter described in rfc6525 section 5.2.6.

It is also to fix that it shouldn't have add streams when sending addstrm
in request, as the process in peer will handle it by sending a addstrm out
request back.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  4 +++
 net/sctp/sm_statefuns.c |  3 ++
 net/sctp/stream.c       | 74 +++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 69 insertions(+), 12 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 93ae50b..e0d9825 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -301,6 +301,10 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_addstrm_in(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 881122b..a8687a7 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3878,6 +3878,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS)
 			reply = sctp_process_strreset_addstrm_out(
 				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type == SCTP_PARAM_RESET_ADD_IN_STREAMS)
+			reply = sctp_process_strreset_addstrm_in(
+				(struct sctp_association *)asoc, param, &ev);
 		/* More handles for other types will be added here, by now it
 		 * just ignores other types.
 		 */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index df2794d..1c925db 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -267,18 +267,6 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 		stream->out = streamout;
 	}
 
-	if (in) {
-		struct sctp_stream_in *streamin;
-
-		streamin = krealloc(stream->in, incnt * sizeof(*streamin),
-				    GFP_KERNEL);
-		if (!streamin)
-			goto out;
-
-		memset(streamin + stream->incnt, 0, in * sizeof(*streamin));
-		stream->in = streamin;
-	}
-
 	chunk = sctp_make_strreset_addstrm(asoc, out, in);
 	if (!chunk)
 		goto out;
@@ -625,3 +613,65 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 out:
 	return sctp_make_strreset_resp(asoc, result, request_seq);
 }
+
+struct sctp_chunk *sctp_process_strreset_addstrm_in(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_addstrm *addstrm = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	struct sctp_stream_out *streamout;
+	struct sctp_chunk *chunk = NULL;
+	__u32 request_seq, outcnt;
+	__u16 out;
+
+	request_seq = ntohl(addstrm->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq == asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
+		goto out;
+
+	if (asoc->strreset_outstanding) {
+		result = SCTP_STRRESET_ERR_IN_PROGRESS;
+		goto out;
+	}
+
+	out = ntohs(addstrm->number_of_streams);
+	outcnt = stream->outcnt + out;
+	if (!out || outcnt > SCTP_MAX_STREAM)
+		goto out;
+
+	streamout = krealloc(stream->out, outcnt * sizeof(*streamout),
+			     GFP_ATOMIC);
+	if (!streamout)
+		goto out;
+
+	memset(streamout + stream->outcnt, 0, out * sizeof(*streamout));
+	stream->out = streamout;
+
+	chunk = sctp_make_strreset_addstrm(asoc, out, 0);
+	if (!chunk)
+		goto out;
+
+	asoc->strreset_chunk = chunk;
+	asoc->strreset_outstanding = 1;
+	sctp_chunk_hold(asoc->strreset_chunk);
+
+	stream->outcnt = outcnt;
+
+	*evp = sctp_ulpevent_make_stream_change_event(asoc,
+		0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC);
+
+out:
+	if (!chunk)
+		chunk = sctp_make_strreset_resp(asoc, result, request_seq);
+
+	return chunk;
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 5/7] sctp: implement receiver-side procedures for the Add Incoming Streams Request
@ 2017-03-10  4:11           ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the Add Incoming
Streams Request Parameter described in rfc6525 section 5.2.6.

It is also to fix that it shouldn't have add streams when sending addstrm
in request, as the process in peer will handle it by sending a addstrm out
request back.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |  4 +++
 net/sctp/sm_statefuns.c |  3 ++
 net/sctp/stream.c       | 74 +++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 69 insertions(+), 12 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 93ae50b..e0d9825 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -301,6 +301,10 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_addstrm_in(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 881122b..a8687a7 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3878,6 +3878,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type = SCTP_PARAM_RESET_ADD_OUT_STREAMS)
 			reply = sctp_process_strreset_addstrm_out(
 				(struct sctp_association *)asoc, param, &ev);
+		else if (param.p->type = SCTP_PARAM_RESET_ADD_IN_STREAMS)
+			reply = sctp_process_strreset_addstrm_in(
+				(struct sctp_association *)asoc, param, &ev);
 		/* More handles for other types will be added here, by now it
 		 * just ignores other types.
 		 */
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index df2794d..1c925db 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -267,18 +267,6 @@ int sctp_send_add_streams(struct sctp_association *asoc,
 		stream->out = streamout;
 	}
 
-	if (in) {
-		struct sctp_stream_in *streamin;
-
-		streamin = krealloc(stream->in, incnt * sizeof(*streamin),
-				    GFP_KERNEL);
-		if (!streamin)
-			goto out;
-
-		memset(streamin + stream->incnt, 0, in * sizeof(*streamin));
-		stream->in = streamin;
-	}
-
 	chunk = sctp_make_strreset_addstrm(asoc, out, in);
 	if (!chunk)
 		goto out;
@@ -625,3 +613,65 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 out:
 	return sctp_make_strreset_resp(asoc, result, request_seq);
 }
+
+struct sctp_chunk *sctp_process_strreset_addstrm_in(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_addstrm *addstrm = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	__u32 result = SCTP_STRRESET_DENIED;
+	struct sctp_stream_out *streamout;
+	struct sctp_chunk *chunk = NULL;
+	__u32 request_seq, outcnt;
+	__u16 out;
+
+	request_seq = ntohl(addstrm->request_seq);
+	if (request_seq > asoc->strreset_inseq) {
+		result = SCTP_STRRESET_ERR_BAD_SEQNO;
+		goto out;
+	} else if (request_seq = asoc->strreset_inseq) {
+		asoc->strreset_inseq++;
+	}
+
+	if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
+		goto out;
+
+	if (asoc->strreset_outstanding) {
+		result = SCTP_STRRESET_ERR_IN_PROGRESS;
+		goto out;
+	}
+
+	out = ntohs(addstrm->number_of_streams);
+	outcnt = stream->outcnt + out;
+	if (!out || outcnt > SCTP_MAX_STREAM)
+		goto out;
+
+	streamout = krealloc(stream->out, outcnt * sizeof(*streamout),
+			     GFP_ATOMIC);
+	if (!streamout)
+		goto out;
+
+	memset(streamout + stream->outcnt, 0, out * sizeof(*streamout));
+	stream->out = streamout;
+
+	chunk = sctp_make_strreset_addstrm(asoc, out, 0);
+	if (!chunk)
+		goto out;
+
+	asoc->strreset_chunk = chunk;
+	asoc->strreset_outstanding = 1;
+	sctp_chunk_hold(asoc->strreset_chunk);
+
+	stream->outcnt = outcnt;
+
+	*evp = sctp_ulpevent_make_stream_change_event(asoc,
+		0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC);
+
+out:
+	if (!chunk)
+		chunk = sctp_make_strreset_resp(asoc, result, request_seq);
+
+	return chunk;
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 6/7] sctp: implement receiver-side procedures for the Reconf Response Parameter
  2017-03-10  4:11           ` [PATCHv2 net-next 5/7] sctp: implement receiver-side procedures for the Add Incoming Streams Request Xin Long
@ 2017-03-10  4:11             ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the
Re-configuration Response Parameter in rfc6525 section 5.2.7.

sctp_process_strreset_resp would process the response for any
kind of reconf request, and the stream reconf is applied only
when the response result is success.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |   4 ++
 net/sctp/sm_statefuns.c |   6 +-
 net/sctp/stream.c       | 154 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index e0d9825..47113f2 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -305,6 +305,10 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_resp(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index a8687a7..ab1374f 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3881,9 +3881,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type == SCTP_PARAM_RESET_ADD_IN_STREAMS)
 			reply = sctp_process_strreset_addstrm_in(
 				(struct sctp_association *)asoc, param, &ev);
-		/* More handles for other types will be added here, by now it
-		 * just ignores other types.
-		 */
+		else if (param.p->type == SCTP_PARAM_RESET_RESPONSE)
+			reply = sctp_process_strreset_resp(
+				(struct sctp_association *)asoc, param, &ev);
 
 		if (ev)
 			sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 1c925db..961d0a1 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -675,3 +675,157 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 
 	return chunk;
 }
+
+struct sctp_chunk *sctp_process_strreset_resp(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_resp *resp = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	struct sctp_transport *t;
+	__u16 i, nums, flags = 0;
+	sctp_paramhdr_t *req;
+	__u32 result;
+
+	req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0);
+	if (!req)
+		return NULL;
+
+	result = ntohl(resp->result);
+	if (result != SCTP_STRRESET_PERFORMED) {
+		/* if in progress, do nothing but retransmit */
+		if (result == SCTP_STRRESET_IN_PROGRESS)
+			return NULL;
+		else if (result == SCTP_STRRESET_DENIED)
+			flags = SCTP_STREAM_RESET_DENIED;
+		else
+			flags = SCTP_STREAM_RESET_FAILED;
+	}
+
+	if (req->type == SCTP_PARAM_RESET_OUT_REQUEST) {
+		struct sctp_strreset_outreq *outreq;
+		__u16 *str_p = NULL;
+
+		outreq = (struct sctp_strreset_outreq *)req;
+		nums = (ntohs(outreq->param_hdr.length) - sizeof(*outreq)) / 2;
+
+		if (result == SCTP_STRRESET_PERFORMED) {
+			if (nums) {
+				str_p = outreq->list_of_streams;
+				for (i = 0; i < nums; i++)
+					stream->out[ntohs(str_p[i])].ssn = 0;
+			} else {
+				for (i = 0; i < stream->outcnt; i++)
+					stream->out[i].ssn = 0;
+			}
+
+			flags = SCTP_STREAM_RESET_OUTGOING_SSN;
+		}
+
+		for (i = 0; i < stream->outcnt; i++)
+			stream->out[i].state = SCTP_STREAM_OPEN;
+
+		*evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
+			nums, str_p, GFP_ATOMIC);
+	} else if (req->type == SCTP_PARAM_RESET_IN_REQUEST) {
+		struct sctp_strreset_inreq *inreq;
+		__u16 *str_p = NULL;
+
+		/* if the result is performed, it's impossible for inreq */
+		if (result == SCTP_STRRESET_PERFORMED)
+			return NULL;
+
+		inreq = (struct sctp_strreset_inreq *)req;
+		nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / 2;
+
+		str_p = inreq->list_of_streams;
+		*evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
+			nums, str_p, GFP_ATOMIC);
+	} else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
+		struct sctp_strreset_resptsn *resptsn;
+		__u32 stsn, rtsn;
+
+		/* check for resptsn, as sctp_verify_reconf didn't do it*/
+		if (ntohs(param.p->length) != sizeof(*resptsn))
+			return NULL;
+
+		resptsn = (struct sctp_strreset_resptsn *)resp;
+		stsn = ntohl(resptsn->senders_next_tsn);
+		rtsn = ntohl(resptsn->receivers_next_tsn);
+
+		if (result == SCTP_STRRESET_PERFORMED) {
+			__u32 mtsn = sctp_tsnmap_get_max_tsn_seen(
+						&asoc->peer.tsn_map);
+
+			sctp_ulpq_reasm_flushtsn(&asoc->ulpq, mtsn);
+			sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
+
+			sctp_tsnmap_init(&asoc->peer.tsn_map,
+					 SCTP_TSN_MAP_INITIAL,
+					 stsn, GFP_ATOMIC);
+
+			sctp_outq_free(&asoc->outqueue);
+
+			asoc->next_tsn = rtsn;
+			asoc->ctsn_ack_point = asoc->next_tsn - 1;
+			asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
+
+			for (i = 0; i < stream->outcnt; i++)
+				stream->out[i].ssn = 0;
+			for (i = 0; i < stream->incnt; i++)
+				stream->in[i].ssn = 0;
+		}
+
+		for (i = 0; i < stream->outcnt; i++)
+			stream->out[i].state = SCTP_STREAM_OPEN;
+
+		*evp = sctp_ulpevent_make_assoc_reset_event(asoc, flags,
+			stsn, rtsn, GFP_ATOMIC);
+	} else if (req->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) {
+		struct sctp_strreset_addstrm *addstrm;
+		__u16 number;
+
+		addstrm = (struct sctp_strreset_addstrm *)req;
+		nums = ntohs(addstrm->number_of_streams);
+		number = stream->outcnt - nums;
+
+		if (result == SCTP_STRRESET_PERFORMED)
+			for (i = number; i < stream->outcnt; i++)
+				stream->out[i].state = SCTP_STREAM_OPEN;
+		else
+			stream->outcnt = number;
+
+		*evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
+			0, nums, GFP_ATOMIC);
+	} else if (req->type == SCTP_PARAM_RESET_ADD_IN_STREAMS) {
+		struct sctp_strreset_addstrm *addstrm;
+
+		/* if the result is performed, it's impossible for addstrm in
+		 * request.
+		 */
+		if (result == SCTP_STRRESET_PERFORMED)
+			return NULL;
+
+		addstrm = (struct sctp_strreset_addstrm *)req;
+		nums = ntohs(addstrm->number_of_streams);
+
+		*evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
+			nums, 0, GFP_ATOMIC);
+	}
+
+	asoc->strreset_outstanding--;
+	asoc->strreset_outseq++;
+
+	/* remove everything for this reconf request */
+	if (!asoc->strreset_outstanding) {
+		t = asoc->strreset_chunk->transport;
+		if (del_timer(&t->reconf_timer))
+			sctp_transport_put(t);
+
+		sctp_chunk_put(asoc->strreset_chunk);
+		asoc->strreset_chunk = NULL;
+	}
+
+	return NULL;
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 6/7] sctp: implement receiver-side procedures for the Reconf Response Parameter
@ 2017-03-10  4:11             ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patch is to implement Receiver-Side Procedures for the
Re-configuration Response Parameter in rfc6525 section 5.2.7.

sctp_process_strreset_resp would process the response for any
kind of reconf request, and the stream reconf is applied only
when the response result is success.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/net/sctp/sm.h   |   4 ++
 net/sctp/sm_statefuns.c |   6 +-
 net/sctp/stream.c       | 154 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index e0d9825..47113f2 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -305,6 +305,10 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 				struct sctp_association *asoc,
 				union sctp_params param,
 				struct sctp_ulpevent **evp);
+struct sctp_chunk *sctp_process_strreset_resp(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp);
 
 /* Prototypes for statetable processing. */
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index a8687a7..ab1374f 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3881,9 +3881,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
 		else if (param.p->type = SCTP_PARAM_RESET_ADD_IN_STREAMS)
 			reply = sctp_process_strreset_addstrm_in(
 				(struct sctp_association *)asoc, param, &ev);
-		/* More handles for other types will be added here, by now it
-		 * just ignores other types.
-		 */
+		else if (param.p->type = SCTP_PARAM_RESET_RESPONSE)
+			reply = sctp_process_strreset_resp(
+				(struct sctp_association *)asoc, param, &ev);
 
 		if (ev)
 			sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 1c925db..961d0a1 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -675,3 +675,157 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 
 	return chunk;
 }
+
+struct sctp_chunk *sctp_process_strreset_resp(
+				struct sctp_association *asoc,
+				union sctp_params param,
+				struct sctp_ulpevent **evp)
+{
+	struct sctp_strreset_resp *resp = param.v;
+	struct sctp_stream *stream = asoc->stream;
+	struct sctp_transport *t;
+	__u16 i, nums, flags = 0;
+	sctp_paramhdr_t *req;
+	__u32 result;
+
+	req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0);
+	if (!req)
+		return NULL;
+
+	result = ntohl(resp->result);
+	if (result != SCTP_STRRESET_PERFORMED) {
+		/* if in progress, do nothing but retransmit */
+		if (result = SCTP_STRRESET_IN_PROGRESS)
+			return NULL;
+		else if (result = SCTP_STRRESET_DENIED)
+			flags = SCTP_STREAM_RESET_DENIED;
+		else
+			flags = SCTP_STREAM_RESET_FAILED;
+	}
+
+	if (req->type = SCTP_PARAM_RESET_OUT_REQUEST) {
+		struct sctp_strreset_outreq *outreq;
+		__u16 *str_p = NULL;
+
+		outreq = (struct sctp_strreset_outreq *)req;
+		nums = (ntohs(outreq->param_hdr.length) - sizeof(*outreq)) / 2;
+
+		if (result = SCTP_STRRESET_PERFORMED) {
+			if (nums) {
+				str_p = outreq->list_of_streams;
+				for (i = 0; i < nums; i++)
+					stream->out[ntohs(str_p[i])].ssn = 0;
+			} else {
+				for (i = 0; i < stream->outcnt; i++)
+					stream->out[i].ssn = 0;
+			}
+
+			flags = SCTP_STREAM_RESET_OUTGOING_SSN;
+		}
+
+		for (i = 0; i < stream->outcnt; i++)
+			stream->out[i].state = SCTP_STREAM_OPEN;
+
+		*evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
+			nums, str_p, GFP_ATOMIC);
+	} else if (req->type = SCTP_PARAM_RESET_IN_REQUEST) {
+		struct sctp_strreset_inreq *inreq;
+		__u16 *str_p = NULL;
+
+		/* if the result is performed, it's impossible for inreq */
+		if (result = SCTP_STRRESET_PERFORMED)
+			return NULL;
+
+		inreq = (struct sctp_strreset_inreq *)req;
+		nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / 2;
+
+		str_p = inreq->list_of_streams;
+		*evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
+			nums, str_p, GFP_ATOMIC);
+	} else if (req->type = SCTP_PARAM_RESET_TSN_REQUEST) {
+		struct sctp_strreset_resptsn *resptsn;
+		__u32 stsn, rtsn;
+
+		/* check for resptsn, as sctp_verify_reconf didn't do it*/
+		if (ntohs(param.p->length) != sizeof(*resptsn))
+			return NULL;
+
+		resptsn = (struct sctp_strreset_resptsn *)resp;
+		stsn = ntohl(resptsn->senders_next_tsn);
+		rtsn = ntohl(resptsn->receivers_next_tsn);
+
+		if (result = SCTP_STRRESET_PERFORMED) {
+			__u32 mtsn = sctp_tsnmap_get_max_tsn_seen(
+						&asoc->peer.tsn_map);
+
+			sctp_ulpq_reasm_flushtsn(&asoc->ulpq, mtsn);
+			sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
+
+			sctp_tsnmap_init(&asoc->peer.tsn_map,
+					 SCTP_TSN_MAP_INITIAL,
+					 stsn, GFP_ATOMIC);
+
+			sctp_outq_free(&asoc->outqueue);
+
+			asoc->next_tsn = rtsn;
+			asoc->ctsn_ack_point = asoc->next_tsn - 1;
+			asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
+
+			for (i = 0; i < stream->outcnt; i++)
+				stream->out[i].ssn = 0;
+			for (i = 0; i < stream->incnt; i++)
+				stream->in[i].ssn = 0;
+		}
+
+		for (i = 0; i < stream->outcnt; i++)
+			stream->out[i].state = SCTP_STREAM_OPEN;
+
+		*evp = sctp_ulpevent_make_assoc_reset_event(asoc, flags,
+			stsn, rtsn, GFP_ATOMIC);
+	} else if (req->type = SCTP_PARAM_RESET_ADD_OUT_STREAMS) {
+		struct sctp_strreset_addstrm *addstrm;
+		__u16 number;
+
+		addstrm = (struct sctp_strreset_addstrm *)req;
+		nums = ntohs(addstrm->number_of_streams);
+		number = stream->outcnt - nums;
+
+		if (result = SCTP_STRRESET_PERFORMED)
+			for (i = number; i < stream->outcnt; i++)
+				stream->out[i].state = SCTP_STREAM_OPEN;
+		else
+			stream->outcnt = number;
+
+		*evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
+			0, nums, GFP_ATOMIC);
+	} else if (req->type = SCTP_PARAM_RESET_ADD_IN_STREAMS) {
+		struct sctp_strreset_addstrm *addstrm;
+
+		/* if the result is performed, it's impossible for addstrm in
+		 * request.
+		 */
+		if (result = SCTP_STRRESET_PERFORMED)
+			return NULL;
+
+		addstrm = (struct sctp_strreset_addstrm *)req;
+		nums = ntohs(addstrm->number_of_streams);
+
+		*evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
+			nums, 0, GFP_ATOMIC);
+	}
+
+	asoc->strreset_outstanding--;
+	asoc->strreset_outseq++;
+
+	/* remove everything for this reconf request */
+	if (!asoc->strreset_outstanding) {
+		t = asoc->strreset_chunk->transport;
+		if (del_timer(&t->reconf_timer))
+			sctp_transport_put(t);
+
+		sctp_chunk_put(asoc->strreset_chunk);
+		asoc->strreset_chunk = NULL;
+	}
+
+	return NULL;
+}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 7/7] sctp: add get and set sockopt for reconf_enable
  2017-03-10  4:11             ` Xin Long
@ 2017-03-10  4:11               ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patchset is to add SCTP_RECONFIG_SUPPORTED sockopt, it would
set and get asoc reconf_enable value when asoc_id is set, or it
would set and get ep reconf_enalbe value if asoc_id is 0.

It is also to add sysctl interface for users to set the default
value for reconf_enable.

After this patch, stream reconf will work.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/uapi/linux/sctp.h |  1 +
 net/sctp/socket.c         | 81 +++++++++++++++++++++++++++++++++++++++++++++++
 net/sctp/sysctl.c         |  7 ++++
 3 files changed, 89 insertions(+)

diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index fd652e6..7212870 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -115,6 +115,7 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_PR_SUPPORTED	113
 #define SCTP_DEFAULT_PRINFO	114
 #define SCTP_PR_ASSOC_STATUS	115
+#define SCTP_RECONFIG_SUPPORTED	117
 #define SCTP_ENABLE_STREAM_RESET	118
 #define SCTP_RESET_STREAMS	119
 #define SCTP_RESET_ASSOC	120
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6f0a9be..24e28cf 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3758,6 +3758,39 @@ static int sctp_setsockopt_default_prinfo(struct sock *sk,
 	return retval;
 }
 
+static int sctp_setsockopt_reconfig_supported(struct sock *sk,
+					      char __user *optval,
+					      unsigned int optlen)
+{
+	struct sctp_assoc_value params;
+	struct sctp_association *asoc;
+	int retval = -EINVAL;
+
+	if (optlen != sizeof(params))
+		goto out;
+
+	if (copy_from_user(&params, optval, optlen)) {
+		retval = -EFAULT;
+		goto out;
+	}
+
+	asoc = sctp_id2assoc(sk, params.assoc_id);
+	if (asoc) {
+		asoc->reconf_enable = !!params.assoc_value;
+	} else if (!params.assoc_id) {
+		struct sctp_sock *sp = sctp_sk(sk);
+
+		sp->ep->reconf_enable = !!params.assoc_value;
+	} else {
+		goto out;
+	}
+
+	retval = 0;
+
+out:
+	return retval;
+}
+
 static int sctp_setsockopt_enable_strreset(struct sock *sk,
 					   char __user *optval,
 					   unsigned int optlen)
@@ -4038,6 +4071,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
 	case SCTP_DEFAULT_PRINFO:
 		retval = sctp_setsockopt_default_prinfo(sk, optval, optlen);
 		break;
+	case SCTP_RECONFIG_SUPPORTED:
+		retval = sctp_setsockopt_reconfig_supported(sk, optval, optlen);
+		break;
 	case SCTP_ENABLE_STREAM_RESET:
 		retval = sctp_setsockopt_enable_strreset(sk, optval, optlen);
 		break;
@@ -6540,6 +6576,47 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
 	return retval;
 }
 
+static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len,
+					      char __user *optval,
+					      int __user *optlen)
+{
+	struct sctp_assoc_value params;
+	struct sctp_association *asoc;
+	int retval = -EFAULT;
+
+	if (len < sizeof(params)) {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	len = sizeof(params);
+	if (copy_from_user(&params, optval, len))
+		goto out;
+
+	asoc = sctp_id2assoc(sk, params.assoc_id);
+	if (asoc) {
+		params.assoc_value = asoc->reconf_enable;
+	} else if (!params.assoc_id) {
+		struct sctp_sock *sp = sctp_sk(sk);
+
+		params.assoc_value = sp->ep->reconf_enable;
+	} else {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	if (put_user(len, optlen))
+		goto out;
+
+	if (copy_to_user(optval, &params, len))
+		goto out;
+
+	retval = 0;
+
+out:
+	return retval;
+}
+
 static int sctp_getsockopt_enable_strreset(struct sock *sk, int len,
 					   char __user *optval,
 					   int __user *optlen)
@@ -6748,6 +6825,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
 		retval = sctp_getsockopt_pr_assocstatus(sk, len, optval,
 							optlen);
 		break;
+	case SCTP_RECONFIG_SUPPORTED:
+		retval = sctp_getsockopt_reconfig_supported(sk, len, optval,
+							    optlen);
+		break;
 	case SCTP_ENABLE_STREAM_RESET:
 		retval = sctp_getsockopt_enable_strreset(sk, len, optval,
 							 optlen);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index daf8554..0e732f6 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -275,6 +275,13 @@ static struct ctl_table sctp_net_table[] = {
 		.proc_handler	= proc_dointvec,
 	},
 	{
+		.procname	= "reconf_enable",
+		.data		= &init_net.sctp.reconf_enable,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
 		.procname	= "auth_enable",
 		.data		= &init_net.sctp.auth_enable,
 		.maxlen		= sizeof(int),
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCHv2 net-next 7/7] sctp: add get and set sockopt for reconf_enable
@ 2017-03-10  4:11               ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:11 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

This patchset is to add SCTP_RECONFIG_SUPPORTED sockopt, it would
set and get asoc reconf_enable value when asoc_id is set, or it
would set and get ep reconf_enalbe value if asoc_id is 0.

It is also to add sysctl interface for users to set the default
value for reconf_enable.

After this patch, stream reconf will work.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 include/uapi/linux/sctp.h |  1 +
 net/sctp/socket.c         | 81 +++++++++++++++++++++++++++++++++++++++++++++++
 net/sctp/sysctl.c         |  7 ++++
 3 files changed, 89 insertions(+)

diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index fd652e6..7212870 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -115,6 +115,7 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_PR_SUPPORTED	113
 #define SCTP_DEFAULT_PRINFO	114
 #define SCTP_PR_ASSOC_STATUS	115
+#define SCTP_RECONFIG_SUPPORTED	117
 #define SCTP_ENABLE_STREAM_RESET	118
 #define SCTP_RESET_STREAMS	119
 #define SCTP_RESET_ASSOC	120
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6f0a9be..24e28cf 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3758,6 +3758,39 @@ static int sctp_setsockopt_default_prinfo(struct sock *sk,
 	return retval;
 }
 
+static int sctp_setsockopt_reconfig_supported(struct sock *sk,
+					      char __user *optval,
+					      unsigned int optlen)
+{
+	struct sctp_assoc_value params;
+	struct sctp_association *asoc;
+	int retval = -EINVAL;
+
+	if (optlen != sizeof(params))
+		goto out;
+
+	if (copy_from_user(&params, optval, optlen)) {
+		retval = -EFAULT;
+		goto out;
+	}
+
+	asoc = sctp_id2assoc(sk, params.assoc_id);
+	if (asoc) {
+		asoc->reconf_enable = !!params.assoc_value;
+	} else if (!params.assoc_id) {
+		struct sctp_sock *sp = sctp_sk(sk);
+
+		sp->ep->reconf_enable = !!params.assoc_value;
+	} else {
+		goto out;
+	}
+
+	retval = 0;
+
+out:
+	return retval;
+}
+
 static int sctp_setsockopt_enable_strreset(struct sock *sk,
 					   char __user *optval,
 					   unsigned int optlen)
@@ -4038,6 +4071,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
 	case SCTP_DEFAULT_PRINFO:
 		retval = sctp_setsockopt_default_prinfo(sk, optval, optlen);
 		break;
+	case SCTP_RECONFIG_SUPPORTED:
+		retval = sctp_setsockopt_reconfig_supported(sk, optval, optlen);
+		break;
 	case SCTP_ENABLE_STREAM_RESET:
 		retval = sctp_setsockopt_enable_strreset(sk, optval, optlen);
 		break;
@@ -6540,6 +6576,47 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
 	return retval;
 }
 
+static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len,
+					      char __user *optval,
+					      int __user *optlen)
+{
+	struct sctp_assoc_value params;
+	struct sctp_association *asoc;
+	int retval = -EFAULT;
+
+	if (len < sizeof(params)) {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	len = sizeof(params);
+	if (copy_from_user(&params, optval, len))
+		goto out;
+
+	asoc = sctp_id2assoc(sk, params.assoc_id);
+	if (asoc) {
+		params.assoc_value = asoc->reconf_enable;
+	} else if (!params.assoc_id) {
+		struct sctp_sock *sp = sctp_sk(sk);
+
+		params.assoc_value = sp->ep->reconf_enable;
+	} else {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	if (put_user(len, optlen))
+		goto out;
+
+	if (copy_to_user(optval, &params, len))
+		goto out;
+
+	retval = 0;
+
+out:
+	return retval;
+}
+
 static int sctp_getsockopt_enable_strreset(struct sock *sk, int len,
 					   char __user *optval,
 					   int __user *optlen)
@@ -6748,6 +6825,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
 		retval = sctp_getsockopt_pr_assocstatus(sk, len, optval,
 							optlen);
 		break;
+	case SCTP_RECONFIG_SUPPORTED:
+		retval = sctp_getsockopt_reconfig_supported(sk, len, optval,
+							    optlen);
+		break;
 	case SCTP_ENABLE_STREAM_RESET:
 		retval = sctp_getsockopt_enable_strreset(sk, len, optval,
 							 optlen);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index daf8554..0e732f6 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -275,6 +275,13 @@ static struct ctl_table sctp_net_table[] = {
 		.proc_handler	= proc_dointvec,
 	},
 	{
+		.procname	= "reconf_enable",
+		.data		= &init_net.sctp.reconf_enable,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
 		.procname	= "auth_enable",
 		.data		= &init_net.sctp.auth_enable,
 		.maxlen		= sizeof(int),
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add streams and response
  2017-03-10  4:11 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add strea Xin Long
@ 2017-03-10  4:17   ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:17 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

[-- Attachment #1: Type: text/plain, Size: 692 bytes --]

On Fri, Mar 10, 2017 at 12:11 PM, Xin Long <lucien.xin@gmail.com> wrote:
> Patch 2/7, 4/7, 5/7, 6/7 are to implement the process of asoc reset request,
> add streams requests and all kinds of responses.
>
> Patch 1/7 and 3/7 are ahead of 2/7 and 4/7 to add two event notification
> for asoc reset and add streams.
>
> Patch 7/7 is the last patch for implementing rfc6525 sctp stream reconf
> to add sysctl and sockopt interface for users to enable sctp stream reconf.
>
> After this patchset, sctp stream reconf will be able to work as rfc6525.

Attachments are the scripts I used to do tests for all patchsets,
including the scripts on bsd side when doing some interactivity
tests with bsd.

[-- Attachment #2: reconf_bsd_v2.tar.gz --]
[-- Type: application/x-gzip, Size: 2985 bytes --]

[-- Attachment #3: reconf_linux_v2.tar.gz --]
[-- Type: application/x-gzip, Size: 4934 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add s
@ 2017-03-10  4:17   ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-10  4:17 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem

[-- Attachment #1: Type: text/plain, Size: 692 bytes --]

On Fri, Mar 10, 2017 at 12:11 PM, Xin Long <lucien.xin@gmail.com> wrote:
> Patch 2/7, 4/7, 5/7, 6/7 are to implement the process of asoc reset request,
> add streams requests and all kinds of responses.
>
> Patch 1/7 and 3/7 are ahead of 2/7 and 4/7 to add two event notification
> for asoc reset and add streams.
>
> Patch 7/7 is the last patch for implementing rfc6525 sctp stream reconf
> to add sysctl and sockopt interface for users to enable sctp stream reconf.
>
> After this patchset, sctp stream reconf will be able to work as rfc6525.

Attachments are the scripts I used to do tests for all patchsets,
including the scripts on bsd side when doing some interactivity
tests with bsd.

[-- Attachment #2: reconf_bsd_v2.tar.gz --]
[-- Type: application/x-gzip, Size: 2985 bytes --]

[-- Attachment #3: reconf_linux_v2.tar.gz --]
[-- Type: application/x-gzip, Size: 4934 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add streams and response
  2017-03-10  4:11 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add strea Xin Long
@ 2017-03-13  6:22   ` David Miller
  -1 siblings, 0 replies; 50+ messages in thread
From: David Miller @ 2017-03-13  6:22 UTC (permalink / raw)
  To: lucien.xin; +Cc: netdev, linux-sctp, marcelo.leitner, nhorman, vyasevich

From: Xin Long <lucien.xin@gmail.com>
Date: Fri, 10 Mar 2017 12:11:05 +0800

> Patch 2/7, 4/7, 5/7, 6/7 are to implement the process of asoc reset request,
> add streams requests and all kinds of responses.
> 
> Patch 1/7 and 3/7 are ahead of 2/7 and 4/7 to add two event notification
> for asoc reset and add streams.
> 
> Patch 7/7 is the last patch for implementing rfc6525 sctp stream reconf
> to add sysctl and sockopt interface for users to enable sctp stream reconf.
> 
> After this patchset, sctp stream reconf will be able to work as rfc6525.
> 
> v1->v2:
>   - put these into a smaller group.
>   - rename the titles of the commits and improve some changelogs.
>   - improve sctp_chunk_lookup_strreset_param and reuse it in patch 4/7.
>   - process addstrm outreq as the ack of in addstrm inreq if strreset_chunk
>     is not NULL in patch 4/7.
>   - remove the stream alloc when sending addstrm inreq, and the process in
>     peer will response it by sending a addstrm out request back in patch 5/7.
>   - adjust the process of addstrm in resp to fit in the codes that only alloc
>     streams through addstrm outreq in patch 6/7.

Series applied, thanks.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add s
@ 2017-03-13  6:22   ` David Miller
  0 siblings, 0 replies; 50+ messages in thread
From: David Miller @ 2017-03-13  6:22 UTC (permalink / raw)
  To: lucien.xin; +Cc: netdev, linux-sctp, marcelo.leitner, nhorman, vyasevich

From: Xin Long <lucien.xin@gmail.com>
Date: Fri, 10 Mar 2017 12:11:05 +0800

> Patch 2/7, 4/7, 5/7, 6/7 are to implement the process of asoc reset request,
> add streams requests and all kinds of responses.
> 
> Patch 1/7 and 3/7 are ahead of 2/7 and 4/7 to add two event notification
> for asoc reset and add streams.
> 
> Patch 7/7 is the last patch for implementing rfc6525 sctp stream reconf
> to add sysctl and sockopt interface for users to enable sctp stream reconf.
> 
> After this patchset, sctp stream reconf will be able to work as rfc6525.
> 
> v1->v2:
>   - put these into a smaller group.
>   - rename the titles of the commits and improve some changelogs.
>   - improve sctp_chunk_lookup_strreset_param and reuse it in patch 4/7.
>   - process addstrm outreq as the ack of in addstrm inreq if strreset_chunk
>     is not NULL in patch 4/7.
>   - remove the stream alloc when sending addstrm inreq, and the process in
>     peer will response it by sending a addstrm out request back in patch 5/7.
>   - adjust the process of addstrm in resp to fit in the codes that only alloc
>     streams through addstrm outreq in patch 6/7.

Series applied, thanks.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter
  2017-03-10  4:11     ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parame Xin Long
@ 2017-03-20 18:04       ` Marcelo Ricardo Leitner
  -1 siblings, 0 replies; 50+ messages in thread
From: Marcelo Ricardo Leitner @ 2017-03-20 18:04 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
> This patch is to implement Receiver-Side Procedures for the SSN/TSN
> Reset Request Parameter described in rfc6525 section 6.2.4.
> 
> The process is kind of complicate, it's wonth having some comments
> from section 6.2.4 in the codes.
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  include/net/sctp/sm.h   |  4 +++
>  net/sctp/sm_statefuns.c |  3 ++
>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 86 insertions(+)
> 
> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
> index b6f682e..2629d66 100644
> --- a/include/net/sctp/sm.h
> +++ b/include/net/sctp/sm.h
> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>  				struct sctp_association *asoc,
>  				union sctp_params param,
>  				struct sctp_ulpevent **evp);
> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> +				struct sctp_association *asoc,
> +				union sctp_params param,
> +				struct sctp_ulpevent **evp);
>  
>  /* Prototypes for statetable processing. */
>  
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index e03bb1a..6982064 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>  		else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
>  			reply = sctp_process_strreset_inreq(
>  				(struct sctp_association *)asoc, param, &ev);
> +		else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
> +			reply = sctp_process_strreset_tsnreq(
> +				(struct sctp_association *)asoc, param, &ev);
>  		/* More handles for other types will be added here, by now it
>  		 * just ignores other types.
>  		 */
> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
> index 1c6cc04..7e993b0 100644
> --- a/net/sctp/stream.c
> +++ b/net/sctp/stream.c
> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>  
>  	return chunk;
>  }
> +
> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> +				struct sctp_association *asoc,
> +				union sctp_params param,
> +				struct sctp_ulpevent **evp)
> +{
> +	__u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
> +	struct sctp_strreset_tsnreq *tsnreq = param.v;
> +	struct sctp_stream *stream = asoc->stream;
> +	__u32 result = SCTP_STRRESET_DENIED;
> +	__u32 request_seq;
> +	__u16 i;
> +
> +	request_seq = ntohl(tsnreq->request_seq);
> +	if (request_seq > asoc->strreset_inseq) {
> +		result = SCTP_STRRESET_ERR_BAD_SEQNO;
> +		goto out;
> +	} else if (request_seq == asoc->strreset_inseq) {
> +		asoc->strreset_inseq++;
> +	}

I guess I already asked this, but.. why request_seq <
asoc->strreset_inseq is allowed?

> +
> +	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
> +		goto out;
> +
> +	if (asoc->strreset_outstanding) {
> +		result = SCTP_STRRESET_ERR_IN_PROGRESS;
> +		goto out;
> +	}
> +
> +	/* G3: The same processing as though a SACK chunk with no gap report
> +	 *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
> +	 *     received MUST be performed.
> +	 */
> +	max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
> +	sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
> +	sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
> +
> +	/* G1: Compute an appropriate value for the Receiver's Next TSN -- the
> +	 *     TSN that the peer should use to send the next DATA chunk.  The
> +	 *     value SHOULD be the smallest TSN not acknowledged by the
> +	 *     receiver of the request plus 2^31.
> +	 */
> +	init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
> +	sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
> +			 init_tsn, GFP_ATOMIC);
> +
> +	/* G4: The same processing as though a FWD-TSN chunk (as defined in
> +	 *     [RFC3758]) with all streams affected and a new cumulative TSN
> +	 *     ACK of the Receiver's Next TSN minus 1 were received MUST be
> +	 *     performed.
> +	 */
> +	sctp_outq_free(&asoc->outqueue);
> +
> +	/* G2: Compute an appropriate value for the local endpoint's next TSN,
> +	 *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
> +	 *     chunk.  The value SHOULD be the highest TSN sent by the receiver
> +	 *     of the request plus 1.
> +	 */
> +	next_tsn = asoc->next_tsn;
> +	asoc->ctsn_ack_point = next_tsn - 1;
> +	asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
> +
> +	/* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
> +	 *      incoming and outgoing streams.
> +	 */
> +	for (i = 0; i < stream->outcnt; i++)
> +		stream->out[i].ssn = 0;
> +	for (i = 0; i < stream->incnt; i++)
> +		stream->in[i].ssn = 0;
> +
> +	result = SCTP_STRRESET_PERFORMED;
> +
> +	*evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
> +						    next_tsn, GFP_ATOMIC);
> +
> +out:
> +	return sctp_make_strreset_tsnresp(asoc, result, request_seq,
> +					  next_tsn, init_tsn);
> +}
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa
@ 2017-03-20 18:04       ` Marcelo Ricardo Leitner
  0 siblings, 0 replies; 50+ messages in thread
From: Marcelo Ricardo Leitner @ 2017-03-20 18:04 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
> This patch is to implement Receiver-Side Procedures for the SSN/TSN
> Reset Request Parameter described in rfc6525 section 6.2.4.
> 
> The process is kind of complicate, it's wonth having some comments
> from section 6.2.4 in the codes.
> 
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  include/net/sctp/sm.h   |  4 +++
>  net/sctp/sm_statefuns.c |  3 ++
>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 86 insertions(+)
> 
> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
> index b6f682e..2629d66 100644
> --- a/include/net/sctp/sm.h
> +++ b/include/net/sctp/sm.h
> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>  				struct sctp_association *asoc,
>  				union sctp_params param,
>  				struct sctp_ulpevent **evp);
> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> +				struct sctp_association *asoc,
> +				union sctp_params param,
> +				struct sctp_ulpevent **evp);
>  
>  /* Prototypes for statetable processing. */
>  
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index e03bb1a..6982064 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>  		else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
>  			reply = sctp_process_strreset_inreq(
>  				(struct sctp_association *)asoc, param, &ev);
> +		else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
> +			reply = sctp_process_strreset_tsnreq(
> +				(struct sctp_association *)asoc, param, &ev);
>  		/* More handles for other types will be added here, by now it
>  		 * just ignores other types.
>  		 */
> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
> index 1c6cc04..7e993b0 100644
> --- a/net/sctp/stream.c
> +++ b/net/sctp/stream.c
> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>  
>  	return chunk;
>  }
> +
> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> +				struct sctp_association *asoc,
> +				union sctp_params param,
> +				struct sctp_ulpevent **evp)
> +{
> +	__u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
> +	struct sctp_strreset_tsnreq *tsnreq = param.v;
> +	struct sctp_stream *stream = asoc->stream;
> +	__u32 result = SCTP_STRRESET_DENIED;
> +	__u32 request_seq;
> +	__u16 i;
> +
> +	request_seq = ntohl(tsnreq->request_seq);
> +	if (request_seq > asoc->strreset_inseq) {
> +		result = SCTP_STRRESET_ERR_BAD_SEQNO;
> +		goto out;
> +	} else if (request_seq = asoc->strreset_inseq) {
> +		asoc->strreset_inseq++;
> +	}

I guess I already asked this, but.. why request_seq <
asoc->strreset_inseq is allowed?

> +
> +	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
> +		goto out;
> +
> +	if (asoc->strreset_outstanding) {
> +		result = SCTP_STRRESET_ERR_IN_PROGRESS;
> +		goto out;
> +	}
> +
> +	/* G3: The same processing as though a SACK chunk with no gap report
> +	 *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
> +	 *     received MUST be performed.
> +	 */
> +	max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
> +	sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
> +	sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
> +
> +	/* G1: Compute an appropriate value for the Receiver's Next TSN -- the
> +	 *     TSN that the peer should use to send the next DATA chunk.  The
> +	 *     value SHOULD be the smallest TSN not acknowledged by the
> +	 *     receiver of the request plus 2^31.
> +	 */
> +	init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
> +	sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
> +			 init_tsn, GFP_ATOMIC);
> +
> +	/* G4: The same processing as though a FWD-TSN chunk (as defined in
> +	 *     [RFC3758]) with all streams affected and a new cumulative TSN
> +	 *     ACK of the Receiver's Next TSN minus 1 were received MUST be
> +	 *     performed.
> +	 */
> +	sctp_outq_free(&asoc->outqueue);
> +
> +	/* G2: Compute an appropriate value for the local endpoint's next TSN,
> +	 *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
> +	 *     chunk.  The value SHOULD be the highest TSN sent by the receiver
> +	 *     of the request plus 1.
> +	 */
> +	next_tsn = asoc->next_tsn;
> +	asoc->ctsn_ack_point = next_tsn - 1;
> +	asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
> +
> +	/* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
> +	 *      incoming and outgoing streams.
> +	 */
> +	for (i = 0; i < stream->outcnt; i++)
> +		stream->out[i].ssn = 0;
> +	for (i = 0; i < stream->incnt; i++)
> +		stream->in[i].ssn = 0;
> +
> +	result = SCTP_STRRESET_PERFORMED;
> +
> +	*evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
> +						    next_tsn, GFP_ATOMIC);
> +
> +out:
> +	return sctp_make_strreset_tsnresp(asoc, result, request_seq,
> +					  next_tsn, init_tsn);
> +}
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter
  2017-03-20 18:04       ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Marcelo Ricardo Leitner
@ 2017-03-21  5:44         ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-21  5:44 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
>> This patch is to implement Receiver-Side Procedures for the SSN/TSN
>> Reset Request Parameter described in rfc6525 section 6.2.4.
>>
>> The process is kind of complicate, it's wonth having some comments
>> from section 6.2.4 in the codes.
>>
>> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>> ---
>>  include/net/sctp/sm.h   |  4 +++
>>  net/sctp/sm_statefuns.c |  3 ++
>>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 86 insertions(+)
>>
>> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
>> index b6f682e..2629d66 100644
>> --- a/include/net/sctp/sm.h
>> +++ b/include/net/sctp/sm.h
>> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>>                               struct sctp_association *asoc,
>>                               union sctp_params param,
>>                               struct sctp_ulpevent **evp);
>> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> +                             struct sctp_association *asoc,
>> +                             union sctp_params param,
>> +                             struct sctp_ulpevent **evp);
>>
>>  /* Prototypes for statetable processing. */
>>
>> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
>> index e03bb1a..6982064 100644
>> --- a/net/sctp/sm_statefuns.c
>> +++ b/net/sctp/sm_statefuns.c
>> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>>               else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
>>                       reply = sctp_process_strreset_inreq(
>>                               (struct sctp_association *)asoc, param, &ev);
>> +             else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
>> +                     reply = sctp_process_strreset_tsnreq(
>> +                             (struct sctp_association *)asoc, param, &ev);
>>               /* More handles for other types will be added here, by now it
>>                * just ignores other types.
>>                */
>> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
>> index 1c6cc04..7e993b0 100644
>> --- a/net/sctp/stream.c
>> +++ b/net/sctp/stream.c
>> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>>
>>       return chunk;
>>  }
>> +
>> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> +                             struct sctp_association *asoc,
>> +                             union sctp_params param,
>> +                             struct sctp_ulpevent **evp)
>> +{
>> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
>> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
>> +     struct sctp_stream *stream = asoc->stream;
>> +     __u32 result = SCTP_STRRESET_DENIED;
>> +     __u32 request_seq;
>> +     __u16 i;
>> +
>> +     request_seq = ntohl(tsnreq->request_seq);
>> +     if (request_seq > asoc->strreset_inseq) {
>> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> +             goto out;
>> +     } else if (request_seq == asoc->strreset_inseq) {
>> +             asoc->strreset_inseq++;
>> +     }
>
> I guess I already asked this, but.. why request_seq <
> asoc->strreset_inseq is allowed?
we can not just ignore or response with ERR.
rfc6525#section-5.2.1:

   ... If the received RE-CONFIG chunk contains at least
   one request and based on the analysis of the Re-configuration Request
   Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
   retransmission), the same RE-CONFIG chunk MUST to be sent back in
   response, as it was earlier.


>
>> +
>> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
>> +             goto out;
>> +
>> +     if (asoc->strreset_outstanding) {
>> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
>> +             goto out;
>> +     }
>> +
>> +     /* G3: The same processing as though a SACK chunk with no gap report
>> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
>> +      *     received MUST be performed.
>> +      */
>> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
>> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
>> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
>> +
>> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
>> +      *     TSN that the peer should use to send the next DATA chunk.  The
>> +      *     value SHOULD be the smallest TSN not acknowledged by the
>> +      *     receiver of the request plus 2^31.
>> +      */
>> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
>> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
>> +                      init_tsn, GFP_ATOMIC);
>> +
>> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
>> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
>> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
>> +      *     performed.
>> +      */
>> +     sctp_outq_free(&asoc->outqueue);
>> +
>> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
>> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
>> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
>> +      *     of the request plus 1.
>> +      */
>> +     next_tsn = asoc->next_tsn;
>> +     asoc->ctsn_ack_point = next_tsn - 1;
>> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
>> +
>> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
>> +      *      incoming and outgoing streams.
>> +      */
>> +     for (i = 0; i < stream->outcnt; i++)
>> +             stream->out[i].ssn = 0;
>> +     for (i = 0; i < stream->incnt; i++)
>> +             stream->in[i].ssn = 0;
>> +
>> +     result = SCTP_STRRESET_PERFORMED;
>> +
>> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
>> +                                                 next_tsn, GFP_ATOMIC);
>> +
>> +out:
>> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
>> +                                       next_tsn, init_tsn);
>> +}
>> --
>> 2.1.0
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa
@ 2017-03-21  5:44         ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-21  5:44 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
>> This patch is to implement Receiver-Side Procedures for the SSN/TSN
>> Reset Request Parameter described in rfc6525 section 6.2.4.
>>
>> The process is kind of complicate, it's wonth having some comments
>> from section 6.2.4 in the codes.
>>
>> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>> ---
>>  include/net/sctp/sm.h   |  4 +++
>>  net/sctp/sm_statefuns.c |  3 ++
>>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 86 insertions(+)
>>
>> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
>> index b6f682e..2629d66 100644
>> --- a/include/net/sctp/sm.h
>> +++ b/include/net/sctp/sm.h
>> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>>                               struct sctp_association *asoc,
>>                               union sctp_params param,
>>                               struct sctp_ulpevent **evp);
>> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> +                             struct sctp_association *asoc,
>> +                             union sctp_params param,
>> +                             struct sctp_ulpevent **evp);
>>
>>  /* Prototypes for statetable processing. */
>>
>> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
>> index e03bb1a..6982064 100644
>> --- a/net/sctp/sm_statefuns.c
>> +++ b/net/sctp/sm_statefuns.c
>> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>>               else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
>>                       reply = sctp_process_strreset_inreq(
>>                               (struct sctp_association *)asoc, param, &ev);
>> +             else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
>> +                     reply = sctp_process_strreset_tsnreq(
>> +                             (struct sctp_association *)asoc, param, &ev);
>>               /* More handles for other types will be added here, by now it
>>                * just ignores other types.
>>                */
>> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
>> index 1c6cc04..7e993b0 100644
>> --- a/net/sctp/stream.c
>> +++ b/net/sctp/stream.c
>> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>>
>>       return chunk;
>>  }
>> +
>> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> +                             struct sctp_association *asoc,
>> +                             union sctp_params param,
>> +                             struct sctp_ulpevent **evp)
>> +{
>> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
>> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
>> +     struct sctp_stream *stream = asoc->stream;
>> +     __u32 result = SCTP_STRRESET_DENIED;
>> +     __u32 request_seq;
>> +     __u16 i;
>> +
>> +     request_seq = ntohl(tsnreq->request_seq);
>> +     if (request_seq > asoc->strreset_inseq) {
>> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> +             goto out;
>> +     } else if (request_seq = asoc->strreset_inseq) {
>> +             asoc->strreset_inseq++;
>> +     }
>
> I guess I already asked this, but.. why request_seq <
> asoc->strreset_inseq is allowed?
we can not just ignore or response with ERR.
rfc6525#section-5.2.1:

   ... If the received RE-CONFIG chunk contains at least
   one request and based on the analysis of the Re-configuration Request
   Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
   retransmission), the same RE-CONFIG chunk MUST to be sent back in
   response, as it was earlier.


>
>> +
>> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
>> +             goto out;
>> +
>> +     if (asoc->strreset_outstanding) {
>> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
>> +             goto out;
>> +     }
>> +
>> +     /* G3: The same processing as though a SACK chunk with no gap report
>> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
>> +      *     received MUST be performed.
>> +      */
>> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
>> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
>> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
>> +
>> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
>> +      *     TSN that the peer should use to send the next DATA chunk.  The
>> +      *     value SHOULD be the smallest TSN not acknowledged by the
>> +      *     receiver of the request plus 2^31.
>> +      */
>> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
>> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
>> +                      init_tsn, GFP_ATOMIC);
>> +
>> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
>> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
>> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
>> +      *     performed.
>> +      */
>> +     sctp_outq_free(&asoc->outqueue);
>> +
>> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
>> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
>> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
>> +      *     of the request plus 1.
>> +      */
>> +     next_tsn = asoc->next_tsn;
>> +     asoc->ctsn_ack_point = next_tsn - 1;
>> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
>> +
>> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
>> +      *      incoming and outgoing streams.
>> +      */
>> +     for (i = 0; i < stream->outcnt; i++)
>> +             stream->out[i].ssn = 0;
>> +     for (i = 0; i < stream->incnt; i++)
>> +             stream->in[i].ssn = 0;
>> +
>> +     result = SCTP_STRRESET_PERFORMED;
>> +
>> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
>> +                                                 next_tsn, GFP_ATOMIC);
>> +
>> +out:
>> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
>> +                                       next_tsn, init_tsn);
>> +}
>> --
>> 2.1.0
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter
  2017-03-21  5:44         ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Xin Long
@ 2017-03-24 23:52           ` Marcelo Ricardo Leitner
  -1 siblings, 0 replies; 50+ messages in thread
From: Marcelo Ricardo Leitner @ 2017-03-24 23:52 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
> >> Reset Request Parameter described in rfc6525 section 6.2.4.
> >>
> >> The process is kind of complicate, it's wonth having some comments
> >> from section 6.2.4 in the codes.
> >>
> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> >> ---
> >>  include/net/sctp/sm.h   |  4 +++
> >>  net/sctp/sm_statefuns.c |  3 ++
> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 86 insertions(+)
> >>
> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
> >> index b6f682e..2629d66 100644
> >> --- a/include/net/sctp/sm.h
> >> +++ b/include/net/sctp/sm.h
> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >>                               struct sctp_association *asoc,
> >>                               union sctp_params param,
> >>                               struct sctp_ulpevent **evp);
> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> +                             struct sctp_association *asoc,
> >> +                             union sctp_params param,
> >> +                             struct sctp_ulpevent **evp);
> >>
> >>  /* Prototypes for statetable processing. */
> >>
> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> >> index e03bb1a..6982064 100644
> >> --- a/net/sctp/sm_statefuns.c
> >> +++ b/net/sctp/sm_statefuns.c
> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
> >>               else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
> >>                       reply = sctp_process_strreset_inreq(
> >>                               (struct sctp_association *)asoc, param, &ev);
> >> +             else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
> >> +                     reply = sctp_process_strreset_tsnreq(
> >> +                             (struct sctp_association *)asoc, param, &ev);
> >>               /* More handles for other types will be added here, by now it
> >>                * just ignores other types.
> >>                */
> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
> >> index 1c6cc04..7e993b0 100644
> >> --- a/net/sctp/stream.c
> >> +++ b/net/sctp/stream.c
> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >>
> >>       return chunk;
> >>  }
> >> +
> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> +                             struct sctp_association *asoc,
> >> +                             union sctp_params param,
> >> +                             struct sctp_ulpevent **evp)
> >> +{
> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
> >> +     struct sctp_stream *stream = asoc->stream;
> >> +     __u32 result = SCTP_STRRESET_DENIED;
> >> +     __u32 request_seq;
> >> +     __u16 i;
> >> +
> >> +     request_seq = ntohl(tsnreq->request_seq);
> >> +     if (request_seq > asoc->strreset_inseq) {
> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> >> +             goto out;
> >> +     } else if (request_seq == asoc->strreset_inseq) {
> >> +             asoc->strreset_inseq++;
> >> +     }
> >
> > I guess I already asked this, but.. why request_seq <
> > asoc->strreset_inseq is allowed?
> we can not just ignore or response with ERR.
> rfc6525#section-5.2.1:
> 
>    ... If the received RE-CONFIG chunk contains at least
>    one request and based on the analysis of the Re-configuration Request
>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
                                  ^^^^^^^^^^^^^
>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
>    response, as it was earlier.

That means we should only re-process that *last* reconf request, and not
just any old one. My understanding is that we need something like:
+     } else if (request_seq < asoc->strreset_inseq-1) {
+             result = SCTP_STRRESET_ERR_BAD_SEQNO;
+             goto out;
+     }

And then this makes it evident that we have to handle request_seq as
serial numbers (like TSNs are handled).


> 
> 
> >
> >> +
> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
> >> +             goto out;
> >> +
> >> +     if (asoc->strreset_outstanding) {
> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* G3: The same processing as though a SACK chunk with no gap report
> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
> >> +      *     received MUST be performed.
> >> +      */
> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
> >> +
> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
> >> +      *     receiver of the request plus 2^31.
> >> +      */
> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
> >> +                      init_tsn, GFP_ATOMIC);
> >> +
> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
> >> +      *     performed.
> >> +      */
> >> +     sctp_outq_free(&asoc->outqueue);
> >> +
> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
> >> +      *     of the request plus 1.
> >> +      */
> >> +     next_tsn = asoc->next_tsn;
> >> +     asoc->ctsn_ack_point = next_tsn - 1;
> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
> >> +
> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
> >> +      *      incoming and outgoing streams.
> >> +      */
> >> +     for (i = 0; i < stream->outcnt; i++)
> >> +             stream->out[i].ssn = 0;
> >> +     for (i = 0; i < stream->incnt; i++)
> >> +             stream->in[i].ssn = 0;
> >> +
> >> +     result = SCTP_STRRESET_PERFORMED;
> >> +
> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
> >> +                                                 next_tsn, GFP_ATOMIC);
> >> +
> >> +out:
> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
> >> +                                       next_tsn, init_tsn);
> >> +}
> >> --
> >> 2.1.0
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa
@ 2017-03-24 23:52           ` Marcelo Ricardo Leitner
  0 siblings, 0 replies; 50+ messages in thread
From: Marcelo Ricardo Leitner @ 2017-03-24 23:52 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
> >> Reset Request Parameter described in rfc6525 section 6.2.4.
> >>
> >> The process is kind of complicate, it's wonth having some comments
> >> from section 6.2.4 in the codes.
> >>
> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> >> ---
> >>  include/net/sctp/sm.h   |  4 +++
> >>  net/sctp/sm_statefuns.c |  3 ++
> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 86 insertions(+)
> >>
> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
> >> index b6f682e..2629d66 100644
> >> --- a/include/net/sctp/sm.h
> >> +++ b/include/net/sctp/sm.h
> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >>                               struct sctp_association *asoc,
> >>                               union sctp_params param,
> >>                               struct sctp_ulpevent **evp);
> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> +                             struct sctp_association *asoc,
> >> +                             union sctp_params param,
> >> +                             struct sctp_ulpevent **evp);
> >>
> >>  /* Prototypes for statetable processing. */
> >>
> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> >> index e03bb1a..6982064 100644
> >> --- a/net/sctp/sm_statefuns.c
> >> +++ b/net/sctp/sm_statefuns.c
> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
> >>               else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
> >>                       reply = sctp_process_strreset_inreq(
> >>                               (struct sctp_association *)asoc, param, &ev);
> >> +             else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
> >> +                     reply = sctp_process_strreset_tsnreq(
> >> +                             (struct sctp_association *)asoc, param, &ev);
> >>               /* More handles for other types will be added here, by now it
> >>                * just ignores other types.
> >>                */
> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
> >> index 1c6cc04..7e993b0 100644
> >> --- a/net/sctp/stream.c
> >> +++ b/net/sctp/stream.c
> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >>
> >>       return chunk;
> >>  }
> >> +
> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> +                             struct sctp_association *asoc,
> >> +                             union sctp_params param,
> >> +                             struct sctp_ulpevent **evp)
> >> +{
> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
> >> +     struct sctp_stream *stream = asoc->stream;
> >> +     __u32 result = SCTP_STRRESET_DENIED;
> >> +     __u32 request_seq;
> >> +     __u16 i;
> >> +
> >> +     request_seq = ntohl(tsnreq->request_seq);
> >> +     if (request_seq > asoc->strreset_inseq) {
> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> >> +             goto out;
> >> +     } else if (request_seq = asoc->strreset_inseq) {
> >> +             asoc->strreset_inseq++;
> >> +     }
> >
> > I guess I already asked this, but.. why request_seq <
> > asoc->strreset_inseq is allowed?
> we can not just ignore or response with ERR.
> rfc6525#section-5.2.1:
> 
>    ... If the received RE-CONFIG chunk contains at least
>    one request and based on the analysis of the Re-configuration Request
>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
                                  ^^^^^^^^^^^^^
>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
>    response, as it was earlier.

That means we should only re-process that *last* reconf request, and not
just any old one. My understanding is that we need something like:
+     } else if (request_seq < asoc->strreset_inseq-1) {
+             result = SCTP_STRRESET_ERR_BAD_SEQNO;
+             goto out;
+     }

And then this makes it evident that we have to handle request_seq as
serial numbers (like TSNs are handled).


> 
> 
> >
> >> +
> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
> >> +             goto out;
> >> +
> >> +     if (asoc->strreset_outstanding) {
> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
> >> +             goto out;
> >> +     }
> >> +
> >> +     /* G3: The same processing as though a SACK chunk with no gap report
> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
> >> +      *     received MUST be performed.
> >> +      */
> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
> >> +
> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
> >> +      *     receiver of the request plus 2^31.
> >> +      */
> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
> >> +                      init_tsn, GFP_ATOMIC);
> >> +
> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
> >> +      *     performed.
> >> +      */
> >> +     sctp_outq_free(&asoc->outqueue);
> >> +
> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
> >> +      *     of the request plus 1.
> >> +      */
> >> +     next_tsn = asoc->next_tsn;
> >> +     asoc->ctsn_ack_point = next_tsn - 1;
> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
> >> +
> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
> >> +      *      incoming and outgoing streams.
> >> +      */
> >> +     for (i = 0; i < stream->outcnt; i++)
> >> +             stream->out[i].ssn = 0;
> >> +     for (i = 0; i < stream->incnt; i++)
> >> +             stream->in[i].ssn = 0;
> >> +
> >> +     result = SCTP_STRRESET_PERFORMED;
> >> +
> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
> >> +                                                 next_tsn, GFP_ATOMIC);
> >> +
> >> +out:
> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
> >> +                                       next_tsn, init_tsn);
> >> +}
> >> --
> >> 2.1.0
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter
  2017-03-24 23:52           ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Marcelo Ricardo Leitner
@ 2017-03-27  4:48             ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-27  4:48 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Sat, Mar 25, 2017 at 7:52 AM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
>> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
>> <marcelo.leitner@gmail.com> wrote:
>> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
>> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
>> >> Reset Request Parameter described in rfc6525 section 6.2.4.
>> >>
>> >> The process is kind of complicate, it's wonth having some comments
>> >> from section 6.2.4 in the codes.
>> >>
>> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>> >> ---
>> >>  include/net/sctp/sm.h   |  4 +++
>> >>  net/sctp/sm_statefuns.c |  3 ++
>> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>> >>  3 files changed, 86 insertions(+)
>> >>
>> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
>> >> index b6f682e..2629d66 100644
>> >> --- a/include/net/sctp/sm.h
>> >> +++ b/include/net/sctp/sm.h
>> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >>                               struct sctp_association *asoc,
>> >>                               union sctp_params param,
>> >>                               struct sctp_ulpevent **evp);
>> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> +                             struct sctp_association *asoc,
>> >> +                             union sctp_params param,
>> >> +                             struct sctp_ulpevent **evp);
>> >>
>> >>  /* Prototypes for statetable processing. */
>> >>
>> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
>> >> index e03bb1a..6982064 100644
>> >> --- a/net/sctp/sm_statefuns.c
>> >> +++ b/net/sctp/sm_statefuns.c
>> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>> >>               else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
>> >>                       reply = sctp_process_strreset_inreq(
>> >>                               (struct sctp_association *)asoc, param, &ev);
>> >> +             else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
>> >> +                     reply = sctp_process_strreset_tsnreq(
>> >> +                             (struct sctp_association *)asoc, param, &ev);
>> >>               /* More handles for other types will be added here, by now it
>> >>                * just ignores other types.
>> >>                */
>> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
>> >> index 1c6cc04..7e993b0 100644
>> >> --- a/net/sctp/stream.c
>> >> +++ b/net/sctp/stream.c
>> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >>
>> >>       return chunk;
>> >>  }
>> >> +
>> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> +                             struct sctp_association *asoc,
>> >> +                             union sctp_params param,
>> >> +                             struct sctp_ulpevent **evp)
>> >> +{
>> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
>> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
>> >> +     struct sctp_stream *stream = asoc->stream;
>> >> +     __u32 result = SCTP_STRRESET_DENIED;
>> >> +     __u32 request_seq;
>> >> +     __u16 i;
>> >> +
>> >> +     request_seq = ntohl(tsnreq->request_seq);
>> >> +     if (request_seq > asoc->strreset_inseq) {
>> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> >> +             goto out;
>> >> +     } else if (request_seq == asoc->strreset_inseq) {
>> >> +             asoc->strreset_inseq++;
>> >> +     }
>> >
>> > I guess I already asked this, but.. why request_seq <
>> > asoc->strreset_inseq is allowed?
>> we can not just ignore or response with ERR.
>> rfc6525#section-5.2.1:
>>
>>    ... If the received RE-CONFIG chunk contains at least
>>    one request and based on the analysis of the Re-configuration Request
>>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
>                                   ^^^^^^^^^^^^^
>>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
>>    response, as it was earlier.
>
> That means we should only re-process that *last* reconf request, and not
> just any old one. My understanding is that we need something like:
> +     } else if (request_seq < asoc->strreset_inseq-1) {
> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> +             goto out;
> +     }
>
> And then this makes it evident that we have to handle request_seq as
> serial numbers (like TSNs are handled).
Got you.

Here is actually also a replay attack. If a duplicate request happens:

In  sender side, If the request is not yet acked, it will just process the
response as usual. If It's acked already, It will drop the duplicate
response as no matched asoc->strreset_chunk any more. It's safe.

But in receiver side. It will process stream/asoc again when receiving
a duplicate request. If receiver side has processed some data chunks
and tsn/ssn have been increased before this.  we shouldn't process
this request, but only send back a response with the original result.
The problem is that we didn't save the result of last request.


>
>
>>
>>
>> >
>> >> +
>> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
>> >> +             goto out;
>> >> +
>> >> +     if (asoc->strreset_outstanding) {
>> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* G3: The same processing as though a SACK chunk with no gap report
>> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
>> >> +      *     received MUST be performed.
>> >> +      */
>> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
>> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
>> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
>> >> +
>> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
>> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
>> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
>> >> +      *     receiver of the request plus 2^31.
>> >> +      */
>> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
>> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
>> >> +                      init_tsn, GFP_ATOMIC);
>> >> +
>> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
>> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
>> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
>> >> +      *     performed.
>> >> +      */
>> >> +     sctp_outq_free(&asoc->outqueue);
>> >> +
>> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
>> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
>> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
>> >> +      *     of the request plus 1.
>> >> +      */
>> >> +     next_tsn = asoc->next_tsn;
>> >> +     asoc->ctsn_ack_point = next_tsn - 1;
>> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
>> >> +
>> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
>> >> +      *      incoming and outgoing streams.
>> >> +      */
>> >> +     for (i = 0; i < stream->outcnt; i++)
>> >> +             stream->out[i].ssn = 0;
>> >> +     for (i = 0; i < stream->incnt; i++)
>> >> +             stream->in[i].ssn = 0;
>> >> +
>> >> +     result = SCTP_STRRESET_PERFORMED;
>> >> +
>> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
>> >> +                                                 next_tsn, GFP_ATOMIC);
>> >> +
>> >> +out:
>> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
>> >> +                                       next_tsn, init_tsn);
>> >> +}
>> >> --
>> >> 2.1.0
>> >>
>> >> --
>> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> >> the body of a message to majordomo@vger.kernel.org
>> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa
@ 2017-03-27  4:48             ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-27  4:48 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Sat, Mar 25, 2017 at 7:52 AM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
>> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
>> <marcelo.leitner@gmail.com> wrote:
>> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
>> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
>> >> Reset Request Parameter described in rfc6525 section 6.2.4.
>> >>
>> >> The process is kind of complicate, it's wonth having some comments
>> >> from section 6.2.4 in the codes.
>> >>
>> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>> >> ---
>> >>  include/net/sctp/sm.h   |  4 +++
>> >>  net/sctp/sm_statefuns.c |  3 ++
>> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>> >>  3 files changed, 86 insertions(+)
>> >>
>> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
>> >> index b6f682e..2629d66 100644
>> >> --- a/include/net/sctp/sm.h
>> >> +++ b/include/net/sctp/sm.h
>> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >>                               struct sctp_association *asoc,
>> >>                               union sctp_params param,
>> >>                               struct sctp_ulpevent **evp);
>> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> +                             struct sctp_association *asoc,
>> >> +                             union sctp_params param,
>> >> +                             struct sctp_ulpevent **evp);
>> >>
>> >>  /* Prototypes for statetable processing. */
>> >>
>> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
>> >> index e03bb1a..6982064 100644
>> >> --- a/net/sctp/sm_statefuns.c
>> >> +++ b/net/sctp/sm_statefuns.c
>> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>> >>               else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
>> >>                       reply = sctp_process_strreset_inreq(
>> >>                               (struct sctp_association *)asoc, param, &ev);
>> >> +             else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
>> >> +                     reply = sctp_process_strreset_tsnreq(
>> >> +                             (struct sctp_association *)asoc, param, &ev);
>> >>               /* More handles for other types will be added here, by now it
>> >>                * just ignores other types.
>> >>                */
>> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
>> >> index 1c6cc04..7e993b0 100644
>> >> --- a/net/sctp/stream.c
>> >> +++ b/net/sctp/stream.c
>> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >>
>> >>       return chunk;
>> >>  }
>> >> +
>> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> +                             struct sctp_association *asoc,
>> >> +                             union sctp_params param,
>> >> +                             struct sctp_ulpevent **evp)
>> >> +{
>> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
>> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
>> >> +     struct sctp_stream *stream = asoc->stream;
>> >> +     __u32 result = SCTP_STRRESET_DENIED;
>> >> +     __u32 request_seq;
>> >> +     __u16 i;
>> >> +
>> >> +     request_seq = ntohl(tsnreq->request_seq);
>> >> +     if (request_seq > asoc->strreset_inseq) {
>> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> >> +             goto out;
>> >> +     } else if (request_seq = asoc->strreset_inseq) {
>> >> +             asoc->strreset_inseq++;
>> >> +     }
>> >
>> > I guess I already asked this, but.. why request_seq <
>> > asoc->strreset_inseq is allowed?
>> we can not just ignore or response with ERR.
>> rfc6525#section-5.2.1:
>>
>>    ... If the received RE-CONFIG chunk contains at least
>>    one request and based on the analysis of the Re-configuration Request
>>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
>                                   ^^^^^^^^^^^^^
>>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
>>    response, as it was earlier.
>
> That means we should only re-process that *last* reconf request, and not
> just any old one. My understanding is that we need something like:
> +     } else if (request_seq < asoc->strreset_inseq-1) {
> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> +             goto out;
> +     }
>
> And then this makes it evident that we have to handle request_seq as
> serial numbers (like TSNs are handled).
Got you.

Here is actually also a replay attack. If a duplicate request happens:

In  sender side, If the request is not yet acked, it will just process the
response as usual. If It's acked already, It will drop the duplicate
response as no matched asoc->strreset_chunk any more. It's safe.

But in receiver side. It will process stream/asoc again when receiving
a duplicate request. If receiver side has processed some data chunks
and tsn/ssn have been increased before this.  we shouldn't process
this request, but only send back a response with the original result.
The problem is that we didn't save the result of last request.


>
>
>>
>>
>> >
>> >> +
>> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
>> >> +             goto out;
>> >> +
>> >> +     if (asoc->strreset_outstanding) {
>> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     /* G3: The same processing as though a SACK chunk with no gap report
>> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
>> >> +      *     received MUST be performed.
>> >> +      */
>> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
>> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
>> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
>> >> +
>> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
>> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
>> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
>> >> +      *     receiver of the request plus 2^31.
>> >> +      */
>> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
>> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
>> >> +                      init_tsn, GFP_ATOMIC);
>> >> +
>> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
>> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
>> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
>> >> +      *     performed.
>> >> +      */
>> >> +     sctp_outq_free(&asoc->outqueue);
>> >> +
>> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
>> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
>> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
>> >> +      *     of the request plus 1.
>> >> +      */
>> >> +     next_tsn = asoc->next_tsn;
>> >> +     asoc->ctsn_ack_point = next_tsn - 1;
>> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
>> >> +
>> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
>> >> +      *      incoming and outgoing streams.
>> >> +      */
>> >> +     for (i = 0; i < stream->outcnt; i++)
>> >> +             stream->out[i].ssn = 0;
>> >> +     for (i = 0; i < stream->incnt; i++)
>> >> +             stream->in[i].ssn = 0;
>> >> +
>> >> +     result = SCTP_STRRESET_PERFORMED;
>> >> +
>> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
>> >> +                                                 next_tsn, GFP_ATOMIC);
>> >> +
>> >> +out:
>> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
>> >> +                                       next_tsn, init_tsn);
>> >> +}
>> >> --
>> >> 2.1.0
>> >>
>> >> --
>> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> >> the body of a message to majordomo@vger.kernel.org
>> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter
  2017-03-27  4:48             ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Xin Long
@ 2017-03-27 14:16               ` Marcelo Ricardo Leitner
  -1 siblings, 0 replies; 50+ messages in thread
From: Marcelo Ricardo Leitner @ 2017-03-27 14:16 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Mon, Mar 27, 2017 at 12:48:31PM +0800, Xin Long wrote:
> On Sat, Mar 25, 2017 at 7:52 AM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
> >> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
> >> <marcelo.leitner@gmail.com> wrote:
> >> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
> >> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
> >> >> Reset Request Parameter described in rfc6525 section 6.2.4.
> >> >>
> >> >> The process is kind of complicate, it's wonth having some comments
> >> >> from section 6.2.4 in the codes.
> >> >>
> >> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> >> >> ---
> >> >>  include/net/sctp/sm.h   |  4 +++
> >> >>  net/sctp/sm_statefuns.c |  3 ++
> >> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
> >> >>  3 files changed, 86 insertions(+)
> >> >>
> >> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
> >> >> index b6f682e..2629d66 100644
> >> >> --- a/include/net/sctp/sm.h
> >> >> +++ b/include/net/sctp/sm.h
> >> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >> >>                               struct sctp_association *asoc,
> >> >>                               union sctp_params param,
> >> >>                               struct sctp_ulpevent **evp);
> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> >> +                             struct sctp_association *asoc,
> >> >> +                             union sctp_params param,
> >> >> +                             struct sctp_ulpevent **evp);
> >> >>
> >> >>  /* Prototypes for statetable processing. */
> >> >>
> >> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> >> >> index e03bb1a..6982064 100644
> >> >> --- a/net/sctp/sm_statefuns.c
> >> >> +++ b/net/sctp/sm_statefuns.c
> >> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
> >> >>               else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
> >> >>                       reply = sctp_process_strreset_inreq(
> >> >>                               (struct sctp_association *)asoc, param, &ev);
> >> >> +             else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
> >> >> +                     reply = sctp_process_strreset_tsnreq(
> >> >> +                             (struct sctp_association *)asoc, param, &ev);
> >> >>               /* More handles for other types will be added here, by now it
> >> >>                * just ignores other types.
> >> >>                */
> >> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
> >> >> index 1c6cc04..7e993b0 100644
> >> >> --- a/net/sctp/stream.c
> >> >> +++ b/net/sctp/stream.c
> >> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >> >>
> >> >>       return chunk;
> >> >>  }
> >> >> +
> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> >> +                             struct sctp_association *asoc,
> >> >> +                             union sctp_params param,
> >> >> +                             struct sctp_ulpevent **evp)
> >> >> +{
> >> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
> >> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
> >> >> +     struct sctp_stream *stream = asoc->stream;
> >> >> +     __u32 result = SCTP_STRRESET_DENIED;
> >> >> +     __u32 request_seq;
> >> >> +     __u16 i;
> >> >> +
> >> >> +     request_seq = ntohl(tsnreq->request_seq);
> >> >> +     if (request_seq > asoc->strreset_inseq) {
> >> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> >> >> +             goto out;
> >> >> +     } else if (request_seq == asoc->strreset_inseq) {
> >> >> +             asoc->strreset_inseq++;
> >> >> +     }
> >> >
> >> > I guess I already asked this, but.. why request_seq <
> >> > asoc->strreset_inseq is allowed?
> >> we can not just ignore or response with ERR.
> >> rfc6525#section-5.2.1:
> >>
> >>    ... If the received RE-CONFIG chunk contains at least
> >>    one request and based on the analysis of the Re-configuration Request
> >>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
> >                                   ^^^^^^^^^^^^^
> >>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
> >>    response, as it was earlier.
> >
> > That means we should only re-process that *last* reconf request, and not
> > just any old one. My understanding is that we need something like:
> > +     } else if (request_seq < asoc->strreset_inseq-1) {
> > +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> > +             goto out;
> > +     }
> >
> > And then this makes it evident that we have to handle request_seq as
> > serial numbers (like TSNs are handled).
> Got you.
> 
> Here is actually also a replay attack. If a duplicate request happens:

Yep.

> 
> In  sender side, If the request is not yet acked, it will just process the
> response as usual. If It's acked already, It will drop the duplicate
> response as no matched asoc->strreset_chunk any more. It's safe.
> 
> But in receiver side. It will process stream/asoc again when receiving
> a duplicate request. If receiver side has processed some data chunks
> and tsn/ssn have been increased before this.  we shouldn't process
> this request, but only send back a response with the original result.
> The problem is that we didn't save the result of last request.

Sender will stop sending DATA while the reset is happening. We probably
can use the "first DATA" as a trigger to then free the response chunk in
receiver, or the next request (as it can't have 2 requests at the same,
issuing the 2nd one means it got the ack for the previous one),
whichever happens first.

> 
> 
> >
> >
> >>
> >>
> >> >
> >> >> +
> >> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
> >> >> +             goto out;
> >> >> +
> >> >> +     if (asoc->strreset_outstanding) {
> >> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
> >> >> +             goto out;
> >> >> +     }
> >> >> +
> >> >> +     /* G3: The same processing as though a SACK chunk with no gap report
> >> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
> >> >> +      *     received MUST be performed.
> >> >> +      */
> >> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
> >> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
> >> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
> >> >> +
> >> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
> >> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
> >> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
> >> >> +      *     receiver of the request plus 2^31.
> >> >> +      */
> >> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
> >> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
> >> >> +                      init_tsn, GFP_ATOMIC);
> >> >> +
> >> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
> >> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
> >> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
> >> >> +      *     performed.
> >> >> +      */
> >> >> +     sctp_outq_free(&asoc->outqueue);
> >> >> +
> >> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
> >> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
> >> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
> >> >> +      *     of the request plus 1.
> >> >> +      */
> >> >> +     next_tsn = asoc->next_tsn;
> >> >> +     asoc->ctsn_ack_point = next_tsn - 1;
> >> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
> >> >> +
> >> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
> >> >> +      *      incoming and outgoing streams.
> >> >> +      */
> >> >> +     for (i = 0; i < stream->outcnt; i++)
> >> >> +             stream->out[i].ssn = 0;
> >> >> +     for (i = 0; i < stream->incnt; i++)
> >> >> +             stream->in[i].ssn = 0;
> >> >> +
> >> >> +     result = SCTP_STRRESET_PERFORMED;
> >> >> +
> >> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
> >> >> +                                                 next_tsn, GFP_ATOMIC);
> >> >> +
> >> >> +out:
> >> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
> >> >> +                                       next_tsn, init_tsn);
> >> >> +}
> >> >> --
> >> >> 2.1.0
> >> >>
> >> >> --
> >> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> >> >> the body of a message to majordomo@vger.kernel.org
> >> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa
@ 2017-03-27 14:16               ` Marcelo Ricardo Leitner
  0 siblings, 0 replies; 50+ messages in thread
From: Marcelo Ricardo Leitner @ 2017-03-27 14:16 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Mon, Mar 27, 2017 at 12:48:31PM +0800, Xin Long wrote:
> On Sat, Mar 25, 2017 at 7:52 AM, Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> > On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
> >> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
> >> <marcelo.leitner@gmail.com> wrote:
> >> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
> >> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
> >> >> Reset Request Parameter described in rfc6525 section 6.2.4.
> >> >>
> >> >> The process is kind of complicate, it's wonth having some comments
> >> >> from section 6.2.4 in the codes.
> >> >>
> >> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> >> >> ---
> >> >>  include/net/sctp/sm.h   |  4 +++
> >> >>  net/sctp/sm_statefuns.c |  3 ++
> >> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
> >> >>  3 files changed, 86 insertions(+)
> >> >>
> >> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
> >> >> index b6f682e..2629d66 100644
> >> >> --- a/include/net/sctp/sm.h
> >> >> +++ b/include/net/sctp/sm.h
> >> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >> >>                               struct sctp_association *asoc,
> >> >>                               union sctp_params param,
> >> >>                               struct sctp_ulpevent **evp);
> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> >> +                             struct sctp_association *asoc,
> >> >> +                             union sctp_params param,
> >> >> +                             struct sctp_ulpevent **evp);
> >> >>
> >> >>  /* Prototypes for statetable processing. */
> >> >>
> >> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> >> >> index e03bb1a..6982064 100644
> >> >> --- a/net/sctp/sm_statefuns.c
> >> >> +++ b/net/sctp/sm_statefuns.c
> >> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
> >> >>               else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
> >> >>                       reply = sctp_process_strreset_inreq(
> >> >>                               (struct sctp_association *)asoc, param, &ev);
> >> >> +             else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
> >> >> +                     reply = sctp_process_strreset_tsnreq(
> >> >> +                             (struct sctp_association *)asoc, param, &ev);
> >> >>               /* More handles for other types will be added here, by now it
> >> >>                * just ignores other types.
> >> >>                */
> >> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
> >> >> index 1c6cc04..7e993b0 100644
> >> >> --- a/net/sctp/stream.c
> >> >> +++ b/net/sctp/stream.c
> >> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
> >> >>
> >> >>       return chunk;
> >> >>  }
> >> >> +
> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
> >> >> +                             struct sctp_association *asoc,
> >> >> +                             union sctp_params param,
> >> >> +                             struct sctp_ulpevent **evp)
> >> >> +{
> >> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
> >> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
> >> >> +     struct sctp_stream *stream = asoc->stream;
> >> >> +     __u32 result = SCTP_STRRESET_DENIED;
> >> >> +     __u32 request_seq;
> >> >> +     __u16 i;
> >> >> +
> >> >> +     request_seq = ntohl(tsnreq->request_seq);
> >> >> +     if (request_seq > asoc->strreset_inseq) {
> >> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> >> >> +             goto out;
> >> >> +     } else if (request_seq = asoc->strreset_inseq) {
> >> >> +             asoc->strreset_inseq++;
> >> >> +     }
> >> >
> >> > I guess I already asked this, but.. why request_seq <
> >> > asoc->strreset_inseq is allowed?
> >> we can not just ignore or response with ERR.
> >> rfc6525#section-5.2.1:
> >>
> >>    ... If the received RE-CONFIG chunk contains at least
> >>    one request and based on the analysis of the Re-configuration Request
> >>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
> >                                   ^^^^^^^^^^^^^
> >>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
> >>    response, as it was earlier.
> >
> > That means we should only re-process that *last* reconf request, and not
> > just any old one. My understanding is that we need something like:
> > +     } else if (request_seq < asoc->strreset_inseq-1) {
> > +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
> > +             goto out;
> > +     }
> >
> > And then this makes it evident that we have to handle request_seq as
> > serial numbers (like TSNs are handled).
> Got you.
> 
> Here is actually also a replay attack. If a duplicate request happens:

Yep.

> 
> In  sender side, If the request is not yet acked, it will just process the
> response as usual. If It's acked already, It will drop the duplicate
> response as no matched asoc->strreset_chunk any more. It's safe.
> 
> But in receiver side. It will process stream/asoc again when receiving
> a duplicate request. If receiver side has processed some data chunks
> and tsn/ssn have been increased before this.  we shouldn't process
> this request, but only send back a response with the original result.
> The problem is that we didn't save the result of last request.

Sender will stop sending DATA while the reset is happening. We probably
can use the "first DATA" as a trigger to then free the response chunk in
receiver, or the next request (as it can't have 2 requests at the same,
issuing the 2nd one means it got the ack for the previous one),
whichever happens first.

> 
> 
> >
> >
> >>
> >>
> >> >
> >> >> +
> >> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
> >> >> +             goto out;
> >> >> +
> >> >> +     if (asoc->strreset_outstanding) {
> >> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
> >> >> +             goto out;
> >> >> +     }
> >> >> +
> >> >> +     /* G3: The same processing as though a SACK chunk with no gap report
> >> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
> >> >> +      *     received MUST be performed.
> >> >> +      */
> >> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
> >> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
> >> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
> >> >> +
> >> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
> >> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
> >> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
> >> >> +      *     receiver of the request plus 2^31.
> >> >> +      */
> >> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
> >> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
> >> >> +                      init_tsn, GFP_ATOMIC);
> >> >> +
> >> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
> >> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
> >> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
> >> >> +      *     performed.
> >> >> +      */
> >> >> +     sctp_outq_free(&asoc->outqueue);
> >> >> +
> >> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
> >> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
> >> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
> >> >> +      *     of the request plus 1.
> >> >> +      */
> >> >> +     next_tsn = asoc->next_tsn;
> >> >> +     asoc->ctsn_ack_point = next_tsn - 1;
> >> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
> >> >> +
> >> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
> >> >> +      *      incoming and outgoing streams.
> >> >> +      */
> >> >> +     for (i = 0; i < stream->outcnt; i++)
> >> >> +             stream->out[i].ssn = 0;
> >> >> +     for (i = 0; i < stream->incnt; i++)
> >> >> +             stream->in[i].ssn = 0;
> >> >> +
> >> >> +     result = SCTP_STRRESET_PERFORMED;
> >> >> +
> >> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
> >> >> +                                                 next_tsn, GFP_ATOMIC);
> >> >> +
> >> >> +out:
> >> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
> >> >> +                                       next_tsn, init_tsn);
> >> >> +}
> >> >> --
> >> >> 2.1.0
> >> >>
> >> >> --
> >> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> >> >> the body of a message to majordomo@vger.kernel.org
> >> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter
  2017-03-27 14:16               ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Marcelo Ricardo Leitner
@ 2017-03-27 15:50                 ` Xin Long
  -1 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-27 15:50 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Mon, Mar 27, 2017 at 10:16 PM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Mon, Mar 27, 2017 at 12:48:31PM +0800, Xin Long wrote:
>> On Sat, Mar 25, 2017 at 7:52 AM, Marcelo Ricardo Leitner
>> <marcelo.leitner@gmail.com> wrote:
>> > On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
>> >> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
>> >> <marcelo.leitner@gmail.com> wrote:
>> >> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
>> >> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
>> >> >> Reset Request Parameter described in rfc6525 section 6.2.4.
>> >> >>
>> >> >> The process is kind of complicate, it's wonth having some comments
>> >> >> from section 6.2.4 in the codes.
>> >> >>
>> >> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>> >> >> ---
>> >> >>  include/net/sctp/sm.h   |  4 +++
>> >> >>  net/sctp/sm_statefuns.c |  3 ++
>> >> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>> >> >>  3 files changed, 86 insertions(+)
>> >> >>
>> >> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
>> >> >> index b6f682e..2629d66 100644
>> >> >> --- a/include/net/sctp/sm.h
>> >> >> +++ b/include/net/sctp/sm.h
>> >> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >> >>                               struct sctp_association *asoc,
>> >> >>                               union sctp_params param,
>> >> >>                               struct sctp_ulpevent **evp);
>> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> >> +                             struct sctp_association *asoc,
>> >> >> +                             union sctp_params param,
>> >> >> +                             struct sctp_ulpevent **evp);
>> >> >>
>> >> >>  /* Prototypes for statetable processing. */
>> >> >>
>> >> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
>> >> >> index e03bb1a..6982064 100644
>> >> >> --- a/net/sctp/sm_statefuns.c
>> >> >> +++ b/net/sctp/sm_statefuns.c
>> >> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>> >> >>               else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST)
>> >> >>                       reply = sctp_process_strreset_inreq(
>> >> >>                               (struct sctp_association *)asoc, param, &ev);
>> >> >> +             else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST)
>> >> >> +                     reply = sctp_process_strreset_tsnreq(
>> >> >> +                             (struct sctp_association *)asoc, param, &ev);
>> >> >>               /* More handles for other types will be added here, by now it
>> >> >>                * just ignores other types.
>> >> >>                */
>> >> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
>> >> >> index 1c6cc04..7e993b0 100644
>> >> >> --- a/net/sctp/stream.c
>> >> >> +++ b/net/sctp/stream.c
>> >> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >> >>
>> >> >>       return chunk;
>> >> >>  }
>> >> >> +
>> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> >> +                             struct sctp_association *asoc,
>> >> >> +                             union sctp_params param,
>> >> >> +                             struct sctp_ulpevent **evp)
>> >> >> +{
>> >> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
>> >> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
>> >> >> +     struct sctp_stream *stream = asoc->stream;
>> >> >> +     __u32 result = SCTP_STRRESET_DENIED;
>> >> >> +     __u32 request_seq;
>> >> >> +     __u16 i;
>> >> >> +
>> >> >> +     request_seq = ntohl(tsnreq->request_seq);
>> >> >> +     if (request_seq > asoc->strreset_inseq) {
>> >> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> >> >> +             goto out;
>> >> >> +     } else if (request_seq == asoc->strreset_inseq) {
>> >> >> +             asoc->strreset_inseq++;
>> >> >> +     }
>> >> >
>> >> > I guess I already asked this, but.. why request_seq <
>> >> > asoc->strreset_inseq is allowed?
>> >> we can not just ignore or response with ERR.
>> >> rfc6525#section-5.2.1:
>> >>
>> >>    ... If the received RE-CONFIG chunk contains at least
>> >>    one request and based on the analysis of the Re-configuration Request
>> >>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
>> >                                   ^^^^^^^^^^^^^
>> >>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
>> >>    response, as it was earlier.
>> >
>> > That means we should only re-process that *last* reconf request, and not
>> > just any old one. My understanding is that we need something like:
>> > +     } else if (request_seq < asoc->strreset_inseq-1) {
>> > +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> > +             goto out;
>> > +     }
>> >
>> > And then this makes it evident that we have to handle request_seq as
>> > serial numbers (like TSNs are handled).
>> Got you.
>>
>> Here is actually also a replay attack. If a duplicate request happens:
>
> Yep.
>
>>
>> In  sender side, If the request is not yet acked, it will just process the
>> response as usual. If It's acked already, It will drop the duplicate
>> response as no matched asoc->strreset_chunk any more. It's safe.
>>
>> But in receiver side. It will process stream/asoc again when receiving
>> a duplicate request. If receiver side has processed some data chunks
>> and tsn/ssn have been increased before this.  we shouldn't process
>> this request, but only send back a response with the original result.
>> The problem is that we didn't save the result of last request.
>
> Sender will stop sending DATA while the reset is happening. We probably
> can use the "first DATA" as a trigger to then free the response chunk in
> receiver, or the next request (as it can't have 2 requests at the same,
> issuing the 2nd one means it got the ack for the previous one),
> whichever happens first.
for the next request, just check (request_seq == asoc->strreset_inseq-1)
as you said above.

as for the "first DATA", maybe check (the right instreams' ssn == 0)
(this issue not only exists on this patch (resetassoc),
 but also on addstrm/resetstream).

Thanks.

>
>>
>>
>> >
>> >
>> >>
>> >>
>> >> >
>> >> >> +
>> >> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
>> >> >> +             goto out;
>> >> >> +
>> >> >> +     if (asoc->strreset_outstanding) {
>> >> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
>> >> >> +             goto out;
>> >> >> +     }
>> >> >> +
>> >> >> +     /* G3: The same processing as though a SACK chunk with no gap report
>> >> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
>> >> >> +      *     received MUST be performed.
>> >> >> +      */
>> >> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
>> >> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
>> >> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
>> >> >> +
>> >> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
>> >> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
>> >> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
>> >> >> +      *     receiver of the request plus 2^31.
>> >> >> +      */
>> >> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
>> >> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
>> >> >> +                      init_tsn, GFP_ATOMIC);
>> >> >> +
>> >> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
>> >> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
>> >> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
>> >> >> +      *     performed.
>> >> >> +      */
>> >> >> +     sctp_outq_free(&asoc->outqueue);
>> >> >> +
>> >> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
>> >> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
>> >> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
>> >> >> +      *     of the request plus 1.
>> >> >> +      */
>> >> >> +     next_tsn = asoc->next_tsn;
>> >> >> +     asoc->ctsn_ack_point = next_tsn - 1;
>> >> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
>> >> >> +
>> >> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
>> >> >> +      *      incoming and outgoing streams.
>> >> >> +      */
>> >> >> +     for (i = 0; i < stream->outcnt; i++)
>> >> >> +             stream->out[i].ssn = 0;
>> >> >> +     for (i = 0; i < stream->incnt; i++)
>> >> >> +             stream->in[i].ssn = 0;
>> >> >> +
>> >> >> +     result = SCTP_STRRESET_PERFORMED;
>> >> >> +
>> >> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
>> >> >> +                                                 next_tsn, GFP_ATOMIC);
>> >> >> +
>> >> >> +out:
>> >> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
>> >> >> +                                       next_tsn, init_tsn);
>> >> >> +}
>> >> >> --
>> >> >> 2.1.0
>> >> >>
>> >> >> --
>> >> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> >> >> the body of a message to majordomo@vger.kernel.org
>> >> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >> >>
>> >> --
>> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> >> the body of a message to majordomo@vger.kernel.org
>> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa
@ 2017-03-27 15:50                 ` Xin Long
  0 siblings, 0 replies; 50+ messages in thread
From: Xin Long @ 2017-03-27 15:50 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner
  Cc: network dev, linux-sctp, Neil Horman, Vlad Yasevich, davem

On Mon, Mar 27, 2017 at 10:16 PM, Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
> On Mon, Mar 27, 2017 at 12:48:31PM +0800, Xin Long wrote:
>> On Sat, Mar 25, 2017 at 7:52 AM, Marcelo Ricardo Leitner
>> <marcelo.leitner@gmail.com> wrote:
>> > On Tue, Mar 21, 2017 at 01:44:32PM +0800, Xin Long wrote:
>> >> On Tue, Mar 21, 2017 at 2:04 AM, Marcelo Ricardo Leitner
>> >> <marcelo.leitner@gmail.com> wrote:
>> >> > On Fri, Mar 10, 2017 at 12:11:07PM +0800, Xin Long wrote:
>> >> >> This patch is to implement Receiver-Side Procedures for the SSN/TSN
>> >> >> Reset Request Parameter described in rfc6525 section 6.2.4.
>> >> >>
>> >> >> The process is kind of complicate, it's wonth having some comments
>> >> >> from section 6.2.4 in the codes.
>> >> >>
>> >> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
>> >> >> ---
>> >> >>  include/net/sctp/sm.h   |  4 +++
>> >> >>  net/sctp/sm_statefuns.c |  3 ++
>> >> >>  net/sctp/stream.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
>> >> >>  3 files changed, 86 insertions(+)
>> >> >>
>> >> >> diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
>> >> >> index b6f682e..2629d66 100644
>> >> >> --- a/include/net/sctp/sm.h
>> >> >> +++ b/include/net/sctp/sm.h
>> >> >> @@ -293,6 +293,10 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >> >>                               struct sctp_association *asoc,
>> >> >>                               union sctp_params param,
>> >> >>                               struct sctp_ulpevent **evp);
>> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> >> +                             struct sctp_association *asoc,
>> >> >> +                             union sctp_params param,
>> >> >> +                             struct sctp_ulpevent **evp);
>> >> >>
>> >> >>  /* Prototypes for statetable processing. */
>> >> >>
>> >> >> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
>> >> >> index e03bb1a..6982064 100644
>> >> >> --- a/net/sctp/sm_statefuns.c
>> >> >> +++ b/net/sctp/sm_statefuns.c
>> >> >> @@ -3872,6 +3872,9 @@ sctp_disposition_t sctp_sf_do_reconf(struct net *net,
>> >> >>               else if (param.p->type = SCTP_PARAM_RESET_IN_REQUEST)
>> >> >>                       reply = sctp_process_strreset_inreq(
>> >> >>                               (struct sctp_association *)asoc, param, &ev);
>> >> >> +             else if (param.p->type = SCTP_PARAM_RESET_TSN_REQUEST)
>> >> >> +                     reply = sctp_process_strreset_tsnreq(
>> >> >> +                             (struct sctp_association *)asoc, param, &ev);
>> >> >>               /* More handles for other types will be added here, by now it
>> >> >>                * just ignores other types.
>> >> >>                */
>> >> >> diff --git a/net/sctp/stream.c b/net/sctp/stream.c
>> >> >> index 1c6cc04..7e993b0 100644
>> >> >> --- a/net/sctp/stream.c
>> >> >> +++ b/net/sctp/stream.c
>> >> >> @@ -477,3 +477,82 @@ struct sctp_chunk *sctp_process_strreset_inreq(
>> >> >>
>> >> >>       return chunk;
>> >> >>  }
>> >> >> +
>> >> >> +struct sctp_chunk *sctp_process_strreset_tsnreq(
>> >> >> +                             struct sctp_association *asoc,
>> >> >> +                             union sctp_params param,
>> >> >> +                             struct sctp_ulpevent **evp)
>> >> >> +{
>> >> >> +     __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
>> >> >> +     struct sctp_strreset_tsnreq *tsnreq = param.v;
>> >> >> +     struct sctp_stream *stream = asoc->stream;
>> >> >> +     __u32 result = SCTP_STRRESET_DENIED;
>> >> >> +     __u32 request_seq;
>> >> >> +     __u16 i;
>> >> >> +
>> >> >> +     request_seq = ntohl(tsnreq->request_seq);
>> >> >> +     if (request_seq > asoc->strreset_inseq) {
>> >> >> +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> >> >> +             goto out;
>> >> >> +     } else if (request_seq = asoc->strreset_inseq) {
>> >> >> +             asoc->strreset_inseq++;
>> >> >> +     }
>> >> >
>> >> > I guess I already asked this, but.. why request_seq <
>> >> > asoc->strreset_inseq is allowed?
>> >> we can not just ignore or response with ERR.
>> >> rfc6525#section-5.2.1:
>> >>
>> >>    ... If the received RE-CONFIG chunk contains at least
>> >>    one request and based on the analysis of the Re-configuration Request
>> >>    Sequence Numbers this is the last received RE-CONFIG chunk (i.e., a
>> >                                   ^^^^^^^^^^^^^
>> >>    retransmission), the same RE-CONFIG chunk MUST to be sent back in
>> >>    response, as it was earlier.
>> >
>> > That means we should only re-process that *last* reconf request, and not
>> > just any old one. My understanding is that we need something like:
>> > +     } else if (request_seq < asoc->strreset_inseq-1) {
>> > +             result = SCTP_STRRESET_ERR_BAD_SEQNO;
>> > +             goto out;
>> > +     }
>> >
>> > And then this makes it evident that we have to handle request_seq as
>> > serial numbers (like TSNs are handled).
>> Got you.
>>
>> Here is actually also a replay attack. If a duplicate request happens:
>
> Yep.
>
>>
>> In  sender side, If the request is not yet acked, it will just process the
>> response as usual. If It's acked already, It will drop the duplicate
>> response as no matched asoc->strreset_chunk any more. It's safe.
>>
>> But in receiver side. It will process stream/asoc again when receiving
>> a duplicate request. If receiver side has processed some data chunks
>> and tsn/ssn have been increased before this.  we shouldn't process
>> this request, but only send back a response with the original result.
>> The problem is that we didn't save the result of last request.
>
> Sender will stop sending DATA while the reset is happening. We probably
> can use the "first DATA" as a trigger to then free the response chunk in
> receiver, or the next request (as it can't have 2 requests at the same,
> issuing the 2nd one means it got the ack for the previous one),
> whichever happens first.
for the next request, just check (request_seq = asoc->strreset_inseq-1)
as you said above.

as for the "first DATA", maybe check (the right instreams' ssn = 0)
(this issue not only exists on this patch (resetassoc),
 but also on addstrm/resetstream).

Thanks.

>
>>
>>
>> >
>> >
>> >>
>> >>
>> >> >
>> >> >> +
>> >> >> +     if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
>> >> >> +             goto out;
>> >> >> +
>> >> >> +     if (asoc->strreset_outstanding) {
>> >> >> +             result = SCTP_STRRESET_ERR_IN_PROGRESS;
>> >> >> +             goto out;
>> >> >> +     }
>> >> >> +
>> >> >> +     /* G3: The same processing as though a SACK chunk with no gap report
>> >> >> +      *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
>> >> >> +      *     received MUST be performed.
>> >> >> +      */
>> >> >> +     max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
>> >> >> +     sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen);
>> >> >> +     sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
>> >> >> +
>> >> >> +     /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
>> >> >> +      *     TSN that the peer should use to send the next DATA chunk.  The
>> >> >> +      *     value SHOULD be the smallest TSN not acknowledged by the
>> >> >> +      *     receiver of the request plus 2^31.
>> >> >> +      */
>> >> >> +     init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
>> >> >> +     sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
>> >> >> +                      init_tsn, GFP_ATOMIC);
>> >> >> +
>> >> >> +     /* G4: The same processing as though a FWD-TSN chunk (as defined in
>> >> >> +      *     [RFC3758]) with all streams affected and a new cumulative TSN
>> >> >> +      *     ACK of the Receiver's Next TSN minus 1 were received MUST be
>> >> >> +      *     performed.
>> >> >> +      */
>> >> >> +     sctp_outq_free(&asoc->outqueue);
>> >> >> +
>> >> >> +     /* G2: Compute an appropriate value for the local endpoint's next TSN,
>> >> >> +      *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
>> >> >> +      *     chunk.  The value SHOULD be the highest TSN sent by the receiver
>> >> >> +      *     of the request plus 1.
>> >> >> +      */
>> >> >> +     next_tsn = asoc->next_tsn;
>> >> >> +     asoc->ctsn_ack_point = next_tsn - 1;
>> >> >> +     asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
>> >> >> +
>> >> >> +     /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
>> >> >> +      *      incoming and outgoing streams.
>> >> >> +      */
>> >> >> +     for (i = 0; i < stream->outcnt; i++)
>> >> >> +             stream->out[i].ssn = 0;
>> >> >> +     for (i = 0; i < stream->incnt; i++)
>> >> >> +             stream->in[i].ssn = 0;
>> >> >> +
>> >> >> +     result = SCTP_STRRESET_PERFORMED;
>> >> >> +
>> >> >> +     *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
>> >> >> +                                                 next_tsn, GFP_ATOMIC);
>> >> >> +
>> >> >> +out:
>> >> >> +     return sctp_make_strreset_tsnresp(asoc, result, request_seq,
>> >> >> +                                       next_tsn, init_tsn);
>> >> >> +}
>> >> >> --
>> >> >> 2.1.0
>> >> >>
>> >> >> --
>> >> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> >> >> the body of a message to majordomo@vger.kernel.org
>> >> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >> >>
>> >> --
>> >> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> >> the body of a message to majordomo@vger.kernel.org
>> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2017-03-27 15:50 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-10  4:11 [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add streams and response Xin Long
2017-03-10  4:11 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add strea Xin Long
2017-03-10  4:11 ` [PATCHv2 net-next 1/7] sctp: add support for generating assoc reset event notification Xin Long
2017-03-10  4:11   ` Xin Long
2017-03-10  4:11   ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter Xin Long
2017-03-10  4:11     ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parame Xin Long
2017-03-10  4:11     ` [PATCHv2 net-next 3/7] sctp: add support for generating add stream change event notification Xin Long
2017-03-10  4:11       ` Xin Long
2017-03-10  4:11       ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Add Outgoing Streams Request Parameter Xin Long
2017-03-10  4:11         ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Add Outgoing Streams Request Xin Long
2017-03-10  4:11         ` [PATCHv2 net-next 5/7] sctp: implement receiver-side procedures for the Add Incoming Streams Request Parameter Xin Long
2017-03-10  4:11           ` [PATCHv2 net-next 5/7] sctp: implement receiver-side procedures for the Add Incoming Streams Request Xin Long
2017-03-10  4:11           ` [PATCHv2 net-next 6/7] sctp: implement receiver-side procedures for the Reconf Response Parameter Xin Long
2017-03-10  4:11             ` Xin Long
2017-03-10  4:11             ` [PATCHv2 net-next 7/7] sctp: add get and set sockopt for reconf_enable Xin Long
2017-03-10  4:11               ` Xin Long
2017-03-20 18:04     ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter Marcelo Ricardo Leitner
2017-03-20 18:04       ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Marcelo Ricardo Leitner
2017-03-21  5:44       ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter Xin Long
2017-03-21  5:44         ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Xin Long
2017-03-24 23:52         ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter Marcelo Ricardo Leitner
2017-03-24 23:52           ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Marcelo Ricardo Leitner
2017-03-27  4:48           ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter Xin Long
2017-03-27  4:48             ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Xin Long
2017-03-27 14:16             ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter Marcelo Ricardo Leitner
2017-03-27 14:16               ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Marcelo Ricardo Leitner
2017-03-27 15:50               ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Parameter Xin Long
2017-03-27 15:50                 ` [PATCHv2 net-next 2/7] sctp: implement receiver-side procedures for the SSN/TSN Reset Request Pa Xin Long
2017-03-10  4:17 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add streams and response Xin Long
2017-03-10  4:17   ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add s Xin Long
2017-03-13  6:22 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add streams and response David Miller
2017-03-13  6:22   ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf asoc reset and add s David Miller
  -- strict thread matches above, loose matches on Subject: below --
2017-02-17  4:45 [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk Xin Long
2017-02-17  4:45 ` Xin Long
2017-02-17  4:45 ` [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk Xin Long
2017-02-17  4:45   ` Xin Long
2017-02-17  4:45   ` [PATCHv2 net-next 2/7] sctp: add support for generating stream ssn reset event notification Xin Long
2017-02-17  4:45     ` Xin Long
2017-02-17  4:45     ` [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter Xin Long
2017-02-17  4:45       ` [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request P Xin Long
2017-02-17  4:45       ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming SSN Reset Request Parameter Xin Long
2017-02-17  4:45         ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming SSN Reset Request P Xin Long
2017-02-17  4:45         ` [PATCHv2 net-next 5/7] sctp: add a function to verify the sctp reconf chunk Xin Long
2017-02-17  4:45           ` Xin Long
2017-02-17  4:45           ` [PATCHv2 net-next 6/7] sctp: add reconf chunk process Xin Long
2017-02-17  4:45             ` Xin Long
2017-02-17  4:45             ` [PATCHv2 net-next 7/7] sctp: add reconf chunk event Xin Long
2017-02-17  4:45               ` Xin Long
2017-02-19 23:18 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk David Miller
2017-02-19 23:18   ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request ch David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.