* [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf @ 2017-01-01 11:20 Xin Long 2017-01-01 11:20 ` [PATCH net-next 01/27] sctp: add stream arrays in asoc Xin Long ` (2 more replies) 0 siblings, 3 replies; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patchset is to implement sctp stream reconf described in rfc6525. Patch 1-3 add per stream information in sctp asoc. Patch 4-8 make the chunk with different reconf params. (Section 3-4) Patch 9-12 add reconf timer, primitive and enable option. Patch 13-25 implement the procedures on both sender and receiver sides (Section 5) add sockopts and event for users (Section 6) Patch 26-27 add reconf event, activate the sctp stream reconf process. Xin Long (27): sctp: add stream arrays in asoc sctp: replace ssnmap with asoc stream arrays sctp: remove asoc ssnmap and ssnmap.c sctp: add rfc6525 section 3.1 sctp: add rfc6525 section 4.1-4.2 sctp: add rfc6525 section 4.3 sctp: add rfc6525 section 4.4 sctp: add rfc6525 section 4.5-4.6 sctp: add stream reconf timer sctp: add stream reconf primitive sctp: add reconf_enable in asoc ep and netns sctp: add get and set sockopt for reconf_enable sctp: add rfc6525 section 6.3.1 sctp: add rfc6525 section 5.1.2-5.1.3 and 6.3.2 sctp: add rfc6525 section 5.1.4 and 6.3.3 sctp: add rfc6525 section 5.1.5-5.1.6 and 6.3.4 sctp: add rfc6525 section 6.1.1 sctp: add rfc6525 section 6.1.2 sctp: add rfc6525 section 6.1.3 sctp: add rfc6525 section 5.2.2 sctp: add rfc6525 section 5.2.3 sctp: add rfc6525 section 5.2.4 sctp: add rfc6525 section 5.2.5 sctp: add rfc6525 section 5.2.6 sctp: add rfc6525 section 5.2.7 sctp: add sctp reconf chunk process sctp: add reconf chunk event include/linux/sctp.h | 68 ++++++ include/net/netns/sctp.h | 3 + include/net/sctp/constants.h | 7 +- include/net/sctp/sctp.h | 3 +- include/net/sctp/sm.h | 54 ++++- include/net/sctp/structs.h | 91 ++++--- include/net/sctp/ulpevent.h | 12 + include/uapi/linux/sctp.h | 93 ++++++- net/sctp/Makefile | 4 +- net/sctp/associola.c | 29 ++- net/sctp/endpointola.c | 1 + net/sctp/objcnt.c | 2 - net/sctp/outqueue.c | 33 ++- net/sctp/primitive.c | 3 + net/sctp/sm_make_chunk.c | 403 ++++++++++++++++++++++++++++++- net/sctp/sm_sideeffect.c | 32 +++ net/sctp/sm_statefuns.c | 112 ++++++++- net/sctp/sm_statetable.c | 70 ++++++ net/sctp/socket.c | 433 +++++++++++++++++++++++++++++++++ net/sctp/ssnmap.c | 125 ---------- net/sctp/stream.c | 563 +++++++++++++++++++++++++++++++++++++++++++ net/sctp/sysctl.c | 7 + net/sctp/transport.c | 17 +- net/sctp/ulpevent.c | 86 +++++++ net/sctp/ulpqueue.c | 33 +-- 25 files changed, 2043 insertions(+), 241 deletions(-) delete mode 100644 net/sctp/ssnmap.c create mode 100644 net/sctp/stream.c -- 2.1.0 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH net-next 01/27] sctp: add stream arrays in asoc 2017-01-01 11:20 [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 02/27] sctp: replace ssnmap with asoc stream arrays Xin Long 2017-01-01 11:32 ` [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf Xin Long 2017-01-01 16:30 ` David Miller 2 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add streamout and streamin arrays in asoc, initialize them in sctp_process_init and free them in sctp_association_free. Stream arrays are used to replace ssnmap to save more stream things in the next patch. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/structs.h | 18 ++++++++++++++++++ net/sctp/associola.c | 19 +++++++++++++++++++ net/sctp/sm_make_chunk.c | 17 ++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 87d56cc..549f17d 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1331,6 +1331,18 @@ struct sctp_inithdr_host { __u32 initial_tsn; }; +struct sctp_stream_out { + __u16 ssn; + __u8 state; +}; + +struct sctp_stream_in { + __u16 ssn; +}; + +#define SCTP_STREAM_CLOSED 0x00 +#define SCTP_STREAM_OPEN 0x01 + /* SCTP_GET_ASSOC_STATS counters */ struct sctp_priv_assoc_stats { /* Maximum observed rto in the association during subsequent @@ -1879,6 +1891,12 @@ struct sctp_association { temp:1, /* Is it a temporary association? */ prsctp_enable:1; + /* stream arrays */ + struct sctp_stream_out *streamout; + struct sctp_stream_in *streamin; + __u16 streamoutcnt; + __u16 streamincnt; + struct sctp_priv_assoc_stats stats; int sent_cnt_removable; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index d3cc30c..290ec4d 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -361,6 +361,10 @@ void sctp_association_free(struct sctp_association *asoc) /* Free ssnmap storage. */ sctp_ssnmap_free(asoc->ssnmap); + /* Free stream information. */ + kfree(asoc->streamout); + kfree(asoc->streamin); + /* Clean up the bound address list. */ sctp_bind_addr_free(&asoc->base.bind_addr); @@ -1130,6 +1134,8 @@ void sctp_assoc_update(struct sctp_association *asoc, * has been discarded and needs retransmission. */ if (asoc->state >= SCTP_STATE_ESTABLISHED) { + int i; + asoc->next_tsn = new->next_tsn; asoc->ctsn_ack_point = new->ctsn_ack_point; asoc->adv_peer_ack_point = new->adv_peer_ack_point; @@ -1139,6 +1145,12 @@ void sctp_assoc_update(struct sctp_association *asoc, */ sctp_ssnmap_clear(asoc->ssnmap); + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[i].ssn = 0; + + for (i = 0; i < asoc->streamincnt; i++) + asoc->streamin[i].ssn = 0; + /* Flush the ULP reassembly and ordered queue. * Any data there will now be stale and will * cause problems. @@ -1168,6 +1180,13 @@ void sctp_assoc_update(struct sctp_association *asoc, new->ssnmap = NULL; } + if (!asoc->streamin && !asoc->streamout) { + asoc->streamout = new->streamout; + asoc->streamin = new->streamin; + new->streamout = NULL; + new->streamin = NULL; + } + if (!asoc->assoc_id) { /* get a new association id since we don't have one * yet. diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9e9690b..eeadeef 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2442,13 +2442,28 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, * association. */ if (!asoc->temp) { - int error; + int error, i; + + asoc->streamoutcnt = asoc->c.sinit_num_ostreams; + asoc->streamincnt = asoc->c.sinit_max_instreams; asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, asoc->c.sinit_num_ostreams, gfp); if (!asoc->ssnmap) goto clean_up; + asoc->streamout = kcalloc(asoc->streamoutcnt, + sizeof(*asoc->streamout), gfp); + if (!asoc->streamout) + goto clean_up; + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[i].state = SCTP_STREAM_OPEN; + + asoc->streamin = kcalloc(asoc->streamincnt, + sizeof(*asoc->streamin), gfp); + if (!asoc->streamin) + goto clean_up; + error = sctp_assoc_set_id(asoc, gfp); if (error) goto clean_up; -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 02/27] sctp: replace ssnmap with asoc stream arrays 2017-01-01 11:20 ` [PATCH net-next 01/27] sctp: add stream arrays in asoc Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 03/27] sctp: remove asoc ssnmap and ssnmap.c Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem Stream arrays are used to save per stream information, which includes ssn for each stream already. This patch is to replace ssnmap with asoc stream arrays. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/structs.h | 19 ++++++------------- net/sctp/associola.c | 10 ---------- net/sctp/sm_make_chunk.c | 11 ++--------- net/sctp/sm_statefuns.c | 3 +-- net/sctp/ulpqueue.c | 33 +++++++++++---------------------- 5 files changed, 20 insertions(+), 56 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 549f17d..f81c321 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -407,23 +407,16 @@ void sctp_ssnmap_free(struct sctp_ssnmap *map); void sctp_ssnmap_clear(struct sctp_ssnmap *map); /* What is the current SSN number for this stream? */ -static inline __u16 sctp_ssn_peek(struct sctp_stream *stream, __u16 id) -{ - return stream->ssn[id]; -} +#define sctp_ssn_peek(asoc, type, sid) \ + ((asoc)->stream##type[sid].ssn) /* Return the next SSN number for this stream. */ -static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) -{ - return stream->ssn[id]++; -} +#define sctp_ssn_next(asoc, type, sid) \ + ((asoc)->stream##type[sid].ssn++) /* Skip over this ssn and all below. */ -static inline void sctp_ssn_skip(struct sctp_stream *stream, __u16 id, - __u16 ssn) -{ - stream->ssn[id] = ssn+1; -} +#define sctp_ssn_skip(asoc, type, sid, ssn) \ + ((asoc)->stream##type[sid].ssn = ssn + 1) /* * Pointers to address related SCTP functions. diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 290ec4d..ea03270 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -358,9 +358,6 @@ void sctp_association_free(struct sctp_association *asoc) sctp_tsnmap_free(&asoc->peer.tsn_map); - /* Free ssnmap storage. */ - sctp_ssnmap_free(asoc->ssnmap); - /* Free stream information. */ kfree(asoc->streamout); kfree(asoc->streamin); @@ -1143,8 +1140,6 @@ void sctp_assoc_update(struct sctp_association *asoc, /* Reinitialize SSN for both local streams * and peer's streams. */ - sctp_ssnmap_clear(asoc->ssnmap); - for (i = 0; i < asoc->streamoutcnt; i++) asoc->streamout[i].ssn = 0; @@ -1174,11 +1169,6 @@ void sctp_assoc_update(struct sctp_association *asoc, asoc->ctsn_ack_point = asoc->next_tsn - 1; asoc->adv_peer_ack_point = asoc->ctsn_ack_point; - if (!asoc->ssnmap) { - /* Move the ssnmap. */ - asoc->ssnmap = new->ssnmap; - new->ssnmap = NULL; - } if (!asoc->streamin && !asoc->streamout) { asoc->streamout = new->streamout; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index eeadeef..78cbd1b 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1527,7 +1527,6 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) { struct sctp_datamsg *msg; struct sctp_chunk *lchunk; - struct sctp_stream *stream; __u16 ssn; __u16 sid; @@ -1536,7 +1535,6 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) /* All fragments will be on the same stream */ sid = ntohs(chunk->subh.data_hdr->stream); - stream = &chunk->asoc->ssnmap->out; /* Now assign the sequence number to the entire message. * All fragments must have the same stream sequence number. @@ -1547,9 +1545,9 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) ssn = 0; } else { if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG) - ssn = sctp_ssn_next(stream, sid); + ssn = sctp_ssn_next(chunk->asoc, out, sid); else - ssn = sctp_ssn_peek(stream, sid); + ssn = sctp_ssn_peek(chunk->asoc, out, sid); } lchunk->subh.data_hdr->ssn = htons(ssn); @@ -2447,11 +2445,6 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, asoc->streamoutcnt = asoc->c.sinit_num_ostreams; asoc->streamincnt = asoc->c.sinit_max_instreams; - asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, - asoc->c.sinit_num_ostreams, gfp); - if (!asoc->ssnmap) - goto clean_up; - asoc->streamout = kcalloc(asoc->streamoutcnt, sizeof(*asoc->streamout), gfp); if (!asoc->streamout) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 3382ef2..8a130a7 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -6274,9 +6274,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, * and is invalid. */ ssn = ntohs(data_hdr->ssn); - if (ordered && SSN_lt(ssn, sctp_ssn_peek(&asoc->ssnmap->in, sid))) { + if (ordered && SSN_lt(ssn, sctp_ssn_peek(asoc, in, sid))) return SCTP_IERROR_PROTO_VIOLATION; - } /* Send the data up to the user. Note: Schedule the * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 84d0fda..0d8bf26 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -760,11 +760,9 @@ static void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, struct sk_buff_head *event_list; struct sk_buff *pos, *tmp; struct sctp_ulpevent *cevent; - struct sctp_stream *in; __u16 sid, csid, cssn; sid = event->stream; - in = &ulpq->asoc->ssnmap->in; event_list = (struct sk_buff_head *) sctp_event2skb(event)->prev; @@ -782,11 +780,11 @@ static void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, if (csid < sid) continue; - if (cssn != sctp_ssn_peek(in, sid)) + if (cssn != sctp_ssn_peek(ulpq->asoc, in, sid)) break; - /* Found it, so mark in the ssnmap. */ - sctp_ssn_next(in, sid); + /* Found it, so mark in stream array. */ + sctp_ssn_next(ulpq->asoc, in, sid); __skb_unlink(pos, &ulpq->lobby); @@ -849,7 +847,6 @@ static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) { __u16 sid, ssn; - struct sctp_stream *in; /* Check if this message needs ordering. */ if (SCTP_DATA_UNORDERED & event->msg_flags) @@ -858,10 +855,9 @@ static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, /* Note: The stream ID must be verified before this routine. */ sid = event->stream; ssn = event->ssn; - in = &ulpq->asoc->ssnmap->in; /* Is this the expected SSN for this stream ID? */ - if (ssn != sctp_ssn_peek(in, sid)) { + if (ssn != sctp_ssn_peek(ulpq->asoc, in, sid)) { /* We've received something out of order, so find where it * needs to be placed. We order by stream and then by SSN. */ @@ -870,7 +866,7 @@ static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, } /* Mark that the next chunk has been found. */ - sctp_ssn_next(in, sid); + sctp_ssn_next(ulpq->asoc, in, sid); /* Go find any other chunks that were waiting for * ordering. @@ -888,13 +884,10 @@ static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) struct sk_buff *pos, *tmp; struct sctp_ulpevent *cevent; struct sctp_ulpevent *event; - struct sctp_stream *in; struct sk_buff_head temp; struct sk_buff_head *lobby = &ulpq->lobby; __u16 csid, cssn; - in = &ulpq->asoc->ssnmap->in; - /* We are holding the chunks by stream, by SSN. */ skb_queue_head_init(&temp); event = NULL; @@ -912,7 +905,7 @@ static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) continue; /* see if this ssn has been marked by skipping */ - if (!SSN_lt(cssn, sctp_ssn_peek(in, csid))) + if (!SSN_lt(cssn, sctp_ssn_peek(ulpq->asoc, in, csid))) break; __skb_unlink(pos, lobby); @@ -932,8 +925,9 @@ static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) csid = cevent->stream; cssn = cevent->ssn; - if (csid == sid && cssn == sctp_ssn_peek(in, csid)) { - sctp_ssn_next(in, csid); + if (csid == sid && + cssn == sctp_ssn_peek(ulpq->asoc, in, csid)) { + sctp_ssn_next(ulpq->asoc, in, csid); __skb_unlink(pos, lobby); __skb_queue_tail(&temp, pos); event = sctp_skb2event(pos); @@ -955,17 +949,12 @@ static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) */ void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn) { - struct sctp_stream *in; - - /* Note: The stream ID must be verified before this routine. */ - in = &ulpq->asoc->ssnmap->in; - /* Is this an old SSN? If so ignore. */ - if (SSN_lt(ssn, sctp_ssn_peek(in, sid))) + if (SSN_lt(ssn, sctp_ssn_peek(ulpq->asoc, in, sid))) return; /* Mark that we are no longer expecting this SSN or lower. */ - sctp_ssn_skip(in, sid, ssn); + sctp_ssn_skip(ulpq->asoc, in, sid, ssn); /* Go find any other chunks that were waiting for * ordering and deliver them if needed. -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 03/27] sctp: remove asoc ssnmap and ssnmap.c 2017-01-01 11:20 ` [PATCH net-next 02/27] sctp: replace ssnmap with asoc stream arrays Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 04/27] sctp: add rfc6525 section 3.1 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem Since asoc stream arrays has replaced ssnmap, ssnmap is not used any more, this patch is to remove asoc ssnmap and ssnmap.c. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sctp.h | 1 - include/net/sctp/structs.h | 33 ------------ net/sctp/Makefile | 3 +- net/sctp/objcnt.c | 2 - net/sctp/ssnmap.c | 125 --------------------------------------------- 5 files changed, 1 insertion(+), 163 deletions(-) delete mode 100644 net/sctp/ssnmap.c diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index d8833a8..598d938 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -283,7 +283,6 @@ extern atomic_t sctp_dbg_objcnt_chunk; extern atomic_t sctp_dbg_objcnt_bind_addr; extern atomic_t sctp_dbg_objcnt_bind_bucket; extern atomic_t sctp_dbg_objcnt_addr; -extern atomic_t sctp_dbg_objcnt_ssnmap; extern atomic_t sctp_dbg_objcnt_datamsg; extern atomic_t sctp_dbg_objcnt_keys; diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index f81c321..9075d61 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -82,7 +82,6 @@ struct sctp_outq; struct sctp_bind_addr; struct sctp_ulpq; struct sctp_ep_common; -struct sctp_ssnmap; struct crypto_shash; @@ -377,35 +376,6 @@ typedef struct sctp_sender_hb_info { __u64 hb_nonce; } __packed sctp_sender_hb_info_t; -/* - * RFC 2960 1.3.2 Sequenced Delivery within Streams - * - * The term "stream" is used in SCTP to refer to a sequence of user - * messages that are to be delivered to the upper-layer protocol in - * order with respect to other messages within the same stream. This is - * in contrast to its usage in TCP, where it refers to a sequence of - * bytes (in this document a byte is assumed to be eight bits). - * ... - * - * This is the structure we use to track both our outbound and inbound - * SSN, or Stream Sequence Numbers. - */ - -struct sctp_stream { - __u16 *ssn; - unsigned int len; -}; - -struct sctp_ssnmap { - struct sctp_stream in; - struct sctp_stream out; -}; - -struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, - gfp_t gfp); -void sctp_ssnmap_free(struct sctp_ssnmap *map); -void sctp_ssnmap_clear(struct sctp_ssnmap *map); - /* What is the current SSN number for this stream? */ #define sctp_ssn_peek(asoc, type, sid) \ ((asoc)->stream##type[sid].ssn) @@ -1751,9 +1721,6 @@ struct sctp_association { /* Default receive parameters */ __u32 default_rcv_context; - /* This tracks outbound ssn for a given stream. */ - struct sctp_ssnmap *ssnmap; - /* All outbound chunks go through this structure. */ struct sctp_outq outqueue; diff --git a/net/sctp/Makefile b/net/sctp/Makefile index 6c4f749..48bfc74 100644 --- a/net/sctp/Makefile +++ b/net/sctp/Makefile @@ -11,8 +11,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ transport.o chunk.o sm_make_chunk.o ulpevent.o \ inqueue.o outqueue.o ulpqueue.o \ tsnmap.o bind_addr.o socket.o primitive.o \ - output.o input.o debug.o ssnmap.o auth.o \ - offload.o + output.o input.o debug.o auth.o offload.o sctp_probe-y := probe.o diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c index 40e7fac..105ac33 100644 --- a/net/sctp/objcnt.c +++ b/net/sctp/objcnt.c @@ -51,7 +51,6 @@ SCTP_DBG_OBJCNT(bind_addr); SCTP_DBG_OBJCNT(bind_bucket); SCTP_DBG_OBJCNT(chunk); SCTP_DBG_OBJCNT(addr); -SCTP_DBG_OBJCNT(ssnmap); SCTP_DBG_OBJCNT(datamsg); SCTP_DBG_OBJCNT(keys); @@ -67,7 +66,6 @@ static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = { SCTP_DBG_OBJCNT_ENTRY(bind_addr), SCTP_DBG_OBJCNT_ENTRY(bind_bucket), SCTP_DBG_OBJCNT_ENTRY(addr), - SCTP_DBG_OBJCNT_ENTRY(ssnmap), SCTP_DBG_OBJCNT_ENTRY(datamsg), SCTP_DBG_OBJCNT_ENTRY(keys), }; diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c deleted file mode 100644 index b9c8521..0000000 --- a/net/sctp/ssnmap.c +++ /dev/null @@ -1,125 +0,0 @@ -/* SCTP kernel implementation - * Copyright (c) 2003 International Business Machines, Corp. - * - * This file is part of the SCTP kernel implementation - * - * These functions manipulate sctp SSN tracker. - * - * This SCTP implementation is free software; - * you can redistribute it and/or modify it under the terms of - * the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This SCTP implementation is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied - * ************************ - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU CC; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/>. - * - * Please send any bug reports or fixes you make to the - * email address(es): - * lksctp developers <linux-sctp@vger.kernel.org> - * - * Written or modified by: - * Jon Grimm <jgrimm@us.ibm.com> - */ - -#include <linux/types.h> -#include <linux/slab.h> -#include <net/sctp/sctp.h> -#include <net/sctp/sm.h> - -static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, - __u16 out); - -/* Storage size needed for map includes 2 headers and then the - * specific needs of in or out streams. - */ -static inline size_t sctp_ssnmap_size(__u16 in, __u16 out) -{ - return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16); -} - - -/* Create a new sctp_ssnmap. - * Allocate room to store at least 'len' contiguous TSNs. - */ -struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, - gfp_t gfp) -{ - struct sctp_ssnmap *retval; - int size; - - size = sctp_ssnmap_size(in, out); - if (size <= KMALLOC_MAX_SIZE) - retval = kmalloc(size, gfp); - else - retval = (struct sctp_ssnmap *) - __get_free_pages(gfp, get_order(size)); - if (!retval) - goto fail; - - if (!sctp_ssnmap_init(retval, in, out)) - goto fail_map; - - SCTP_DBG_OBJCNT_INC(ssnmap); - - return retval; - -fail_map: - if (size <= KMALLOC_MAX_SIZE) - kfree(retval); - else - free_pages((unsigned long)retval, get_order(size)); -fail: - return NULL; -} - - -/* Initialize a block of memory as a ssnmap. */ -static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, - __u16 out) -{ - memset(map, 0x00, sctp_ssnmap_size(in, out)); - - /* Start 'in' stream just after the map header. */ - map->in.ssn = (__u16 *)&map[1]; - map->in.len = in; - - /* Start 'out' stream just after 'in'. */ - map->out.ssn = &map->in.ssn[in]; - map->out.len = out; - - return map; -} - -/* Clear out the ssnmap streams. */ -void sctp_ssnmap_clear(struct sctp_ssnmap *map) -{ - size_t size; - - size = (map->in.len + map->out.len) * sizeof(__u16); - memset(map->in.ssn, 0x00, size); -} - -/* Dispose of a ssnmap. */ -void sctp_ssnmap_free(struct sctp_ssnmap *map) -{ - int size; - - if (unlikely(!map)) - return; - - size = sctp_ssnmap_size(map->in.len, map->out.len); - if (size <= KMALLOC_MAX_SIZE) - kfree(map); - else - free_pages((unsigned long)map, get_order(size)); - - SCTP_DBG_OBJCNT_DEC(ssnmap); -} -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 04/27] sctp: add rfc6525 section 3.1 2017-01-01 11:20 ` [PATCH net-next 03/27] sctp: remove asoc ssnmap and ssnmap.c Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 05/27] sctp: add rfc6525 section 4.1-4.2 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to define the reconf chunk as the section 3.1 descibes. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/linux/sctp.h | 6 ++++++ net/sctp/sm_make_chunk.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/linux/sctp.h b/include/linux/sctp.h index fcb4c36..cdc3b05 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -108,6 +108,7 @@ typedef enum { /* Use hex, as defined in ADDIP sec. 3.1 */ SCTP_CID_ASCONF = 0xC1, SCTP_CID_ASCONF_ACK = 0x80, + SCTP_CID_RECONF = 0x82, } sctp_cid_t; /* enum */ @@ -710,4 +711,9 @@ struct sctp_infox { struct sctp_association *asoc; }; +struct sctp_reconf_chunk { + sctp_chunkhdr_t chunk_hdr; + __u8 params[0]; +} __packed; + #endif /* __LINUX_SCTP_H__ */ diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 78cbd1b..258d55a 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3534,3 +3534,36 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, return retval; } + +/* RE-CONFIG 3.1 (RE-CONFIG chunk) + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type = 130 | Chunk Flags | Chunk Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * \ \ + * / Re-configuration Parameter / + * \ \ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * \ \ + * / Re-configuration Parameter (optional) / + * \ \ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +static struct sctp_chunk *sctp_make_reconf( + const struct sctp_association *asoc, + int length) +{ + struct sctp_reconf_chunk *reconf; + struct sctp_chunk *retval; + + retval = sctp_make_control(asoc, SCTP_CID_RECONF, 0, length, + GFP_ATOMIC); + if (!retval) + return NULL; + + reconf = (struct sctp_reconf_chunk *)retval->chunk_hdr; + retval->param_hdr.v = reconf->params; + + return retval; +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 05/27] sctp: add rfc6525 section 4.1-4.2 2017-01-01 11:20 ` [PATCH net-next 04/27] sctp: add rfc6525 section 3.1 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 06/27] sctp: add rfc6525 section 4.3 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add asoc strreset_outseq and strreset_inseq for saving the reconf request sequence, initialize them when create assoc and process init, and also to define Incoming and Outgoing SSN Reset Request Parameter described in section 4.1 and 4.2, As they can be in one same chunk as section 3.1-3 describes, it makes them in one function. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/linux/sctp.h | 26 ++++++++++++++ include/net/sctp/sm.h | 5 ++- include/net/sctp/structs.h | 3 ++ net/sctp/associola.c | 1 + net/sctp/sm_make_chunk.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) diff --git a/include/linux/sctp.h b/include/linux/sctp.h index cdc3b05..d5da19c 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -200,6 +200,13 @@ typedef enum { SCTP_PARAM_SUCCESS_REPORT = cpu_to_be16(0xc005), SCTP_PARAM_ADAPTATION_LAYER_IND = cpu_to_be16(0xc006), + /* RE-CONFIG. Section 4 */ + SCTP_PARAM_RESET_OUT_REQUEST = cpu_to_be16(0x000d), + SCTP_PARAM_RESET_IN_REQUEST = cpu_to_be16(0x000e), + SCTP_PARAM_RESET_TSN_REQUEST = cpu_to_be16(0x000f), + SCTP_PARAM_RESET_RESPONSE = cpu_to_be16(0x0010), + SCTP_PARAM_RESET_ADD_OUT_STREAMS = cpu_to_be16(0x0011), + SCTP_PARAM_RESET_ADD_IN_STREAMS = cpu_to_be16(0x0012), } sctp_param_t; /* enum */ @@ -716,4 +723,23 @@ struct sctp_reconf_chunk { __u8 params[0]; } __packed; +struct sctp_strreset_req { + sctp_paramhdr_t param_hdr; + __u32 request_seq; +} __packed; + +struct sctp_strreset_outreq { + sctp_paramhdr_t param_hdr; + __u32 request_seq; + __u32 response_seq; + __u32 send_reset_at_tsn; + __u16 list_of_streams[0]; +} __packed; + +struct sctp_strreset_inreq { + sctp_paramhdr_t param_hdr; + __u32 request_seq; + __u16 list_of_streams[0]; +} __packed; + #endif /* __LINUX_SCTP_H__ */ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index ca6c971..3462cb0 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -259,7 +259,10 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, __u32 new_cum_tsn, size_t nstreams, struct sctp_fwdtsn_skip *skiplist); struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc); - +struct sctp_chunk *sctp_make_strreset_req( + const struct sctp_association *asoc, + __u16 stream_num, __u16 *stream_list, + bool out, bool in); void sctp_chunk_assign_tsn(struct sctp_chunk *); void sctp_chunk_assign_ssn(struct sctp_chunk *); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 9075d61..09616f1 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1857,6 +1857,9 @@ struct sctp_association { __u16 streamoutcnt; __u16 streamincnt; + __u32 strreset_outseq; /* Update after receiving response */ + __u32 strreset_inseq; /* Update after receiving request */ + struct sctp_priv_assoc_stats stats; int sent_cnt_removable; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ea03270..74949da 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -207,6 +207,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a * association to the same value as the initial TSN. */ asoc->addip_serial = asoc->c.initial_tsn; + asoc->strreset_outseq = asoc->c.initial_tsn; INIT_LIST_HEAD(&asoc->addip_chunk_list); INIT_LIST_HEAD(&asoc->asconf_ack_list); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 258d55a..6420714 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1842,6 +1842,7 @@ struct sctp_association *sctp_unpack_cookie( retval->next_tsn = retval->c.initial_tsn; retval->ctsn_ack_point = retval->next_tsn - 1; retval->addip_serial = retval->c.initial_tsn; + retval->strreset_outseq = retval->c.initial_tsn; retval->adv_peer_ack_point = retval->ctsn_ack_point; retval->peer.prsctp_capable = retval->c.prsctp_capable; retval->peer.adaptation_ind = retval->c.adaptation_ind; @@ -2385,6 +2386,8 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, asoc->peer.i.initial_tsn = ntohl(peer_init->init_hdr.initial_tsn); + asoc->strreset_inseq = asoc->peer.i.initial_tsn; + /* Apply the upper bounds for output streams based on peer's * number of inbound streams. */ @@ -3567,3 +3570,88 @@ static struct sctp_chunk *sctp_make_reconf( return retval; } + +/* RE-CONFIG 4.1 (STREAM OUT RESET) + * 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 = 13 | Parameter Length = 16 + 2 * N | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Re-configuration Request Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Re-configuration Response Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sender's Last Assigned TSN | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Stream Number 1 (optional) | Stream Number 2 (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * / ...... / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Stream Number N-1 (optional) | Stream Number N (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * RE-CONFIG 4.2 (STREAM IN RESET) + * 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 = 14 | Parameter Length = 8 + 2 * N | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Re-configuration Request Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Stream Number 1 (optional) | Stream Number 2 (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * / ...... / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Stream Number N-1 (optional) | Stream Number N (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct sctp_chunk *sctp_make_strreset_req( + const struct sctp_association *asoc, + __u16 stream_num, __u16 *stream_list, + bool out, bool in) +{ + struct sctp_strreset_outreq outreq; + __u16 stream_size = stream_num * 2; + struct sctp_strreset_inreq inreq; + struct sctp_chunk *retval; + __u16 osize, isize, i; + + osize = (sizeof(outreq) + stream_size) * out; + isize = (sizeof(inreq) + stream_size) * in; + + retval = sctp_make_reconf(asoc, osize + isize); + if (!retval) + return NULL; + + for (i = 0; i < stream_num; i++) + stream_list[i] = htons(stream_list[i]); + + if (osize) { + outreq.param_hdr.type = SCTP_PARAM_RESET_OUT_REQUEST; + outreq.param_hdr.length = htons(osize); + outreq.request_seq = htonl(asoc->strreset_outseq); + outreq.response_seq = htonl(asoc->strreset_inseq - 1); + outreq.send_reset_at_tsn = htonl(asoc->next_tsn - 1); + + sctp_addto_chunk(retval, sizeof(outreq), &outreq); + + if (stream_size) + sctp_addto_chunk(retval, stream_size, stream_list); + } + + if (isize) { + inreq.param_hdr.type = SCTP_PARAM_RESET_IN_REQUEST; + inreq.param_hdr.length = htons(isize); + inreq.request_seq = htonl(asoc->strreset_outseq + out); + + sctp_addto_chunk(retval, sizeof(inreq), &inreq); + + if (stream_size) + sctp_addto_chunk(retval, stream_size, stream_list); + } + + for (i = 0; i < stream_num; i++) + stream_list[i] = ntohs(stream_list[i]); + + return retval; +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 06/27] sctp: add rfc6525 section 4.3 2017-01-01 11:20 ` [PATCH net-next 05/27] sctp: add rfc6525 section 4.1-4.2 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 07/27] sctp: add rfc6525 section 4.4 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to define SSN/TSN Reset Request Parameter described in section 4.3. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/linux/sctp.h | 5 +++++ include/net/sctp/sm.h | 2 ++ net/sctp/sm_make_chunk.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/include/linux/sctp.h b/include/linux/sctp.h index d5da19c..cc4c74d 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -742,4 +742,9 @@ struct sctp_strreset_inreq { __u16 list_of_streams[0]; } __packed; +struct sctp_strreset_tsnreq { + sctp_paramhdr_t param_hdr; + __u32 request_seq; +} __packed; + #endif /* __LINUX_SCTP_H__ */ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 3462cb0..c658700 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -263,6 +263,8 @@ struct sctp_chunk *sctp_make_strreset_req( const struct sctp_association *asoc, __u16 stream_num, __u16 *stream_list, bool out, bool in); +struct sctp_chunk *sctp_make_strreset_tsnreq( + const struct sctp_association *asoc); 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 6420714..4b29965 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3655,3 +3655,32 @@ struct sctp_chunk *sctp_make_strreset_req( return retval; } + +/* RE-CONFIG 4.3 (SSN/TSN RESET ALL) + * 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 = 15 | Parameter Length = 8 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Re-configuration Request Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct sctp_chunk *sctp_make_strreset_tsnreq( + const struct sctp_association *asoc) +{ + struct sctp_strreset_tsnreq tsnreq; + __u16 length = sizeof(tsnreq); + struct sctp_chunk *retval; + + retval = sctp_make_reconf(asoc, length); + if (!retval) + return NULL; + + tsnreq.param_hdr.type = SCTP_PARAM_RESET_TSN_REQUEST; + tsnreq.param_hdr.length = htons(length); + tsnreq.request_seq = htonl(asoc->strreset_outseq); + + sctp_addto_chunk(retval, sizeof(tsnreq), &tsnreq); + + return retval; +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 07/27] sctp: add rfc6525 section 4.4 2017-01-01 11:20 ` [PATCH net-next 06/27] sctp: add rfc6525 section 4.3 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 08/27] sctp: add rfc6525 section 4.5-4.6 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to define Re-configuration Response Parameter described in 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 cc4c74d..c4fcc7d 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -747,4 +747,28 @@ struct sctp_strreset_tsnreq { __u32 request_seq; } __packed; +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; +} __packed; + +struct sctp_strreset_resptsn { + sctp_paramhdr_t param_hdr; + __u32 response_seq; + __u32 result; + __u32 senders_next_tsn; + __u32 receivers_next_tsn; +} __packed; + #endif /* __LINUX_SCTP_H__ */ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index c658700..013d69f 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -265,6 +265,13 @@ struct sctp_chunk *sctp_make_strreset_req( bool out, bool in); struct sctp_chunk *sctp_make_strreset_tsnreq( const struct sctp_association *asoc); +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 4b29965..e779a0f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3684,3 +3684,77 @@ struct sctp_chunk *sctp_make_strreset_tsnreq( 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] 37+ messages in thread
* [PATCH net-next 08/27] sctp: add rfc6525 section 4.5-4.6 2017-01-01 11:20 ` [PATCH net-next 07/27] sctp: add rfc6525 section 4.4 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 09/27] sctp: add stream reconf timer Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to define Add Incoming/Outgoing Streams Request Parameter described in section 4.5 and 4.6. They can be in one same chunk trunk as section 3.1-7 describes, so make them in one function. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/linux/sctp.h | 7 +++++++ include/net/sctp/sm.h | 3 +++ net/sctp/sm_make_chunk.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/include/linux/sctp.h b/include/linux/sctp.h index c4fcc7d..3a9f234 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -771,4 +771,11 @@ struct sctp_strreset_resptsn { __u32 receivers_next_tsn; } __packed; +struct sctp_strreset_addstrm { + sctp_paramhdr_t param_hdr; + __u32 request_seq; + __u16 number_of_streams; + __u16 reserved; +} __packed; + #endif /* __LINUX_SCTP_H__ */ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 013d69f..35986d0 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -272,6 +272,9 @@ struct sctp_chunk *sctp_make_strreset_tsnresp( struct sctp_association *asoc, __u32 result, __u32 sn, __u32 sender_tsn, __u32 receiver_tsn); +struct sctp_chunk *sctp_make_strreset_addstrm( + const struct sctp_association *asoc, + __u16 out, __u16 in); 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 e779a0f..102e816 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3758,3 +3758,49 @@ struct sctp_chunk *sctp_make_strreset_tsnresp( return retval; } + +/* RE-CONFIG 4.5/4.6 (ADD STREAM) + * 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 = 17 | Parameter Length = 12 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Re-configuration Request Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Number of new streams | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct sctp_chunk *sctp_make_strreset_addstrm( + const struct sctp_association *asoc, + __u16 out, __u16 in) +{ + struct sctp_strreset_addstrm addstrm; + __u16 size = sizeof(addstrm); + struct sctp_chunk *retval; + + retval = sctp_make_reconf(asoc, (!!out + !!in) * size); + if (!retval) + return NULL; + + if (out) { + addstrm.param_hdr.type = SCTP_PARAM_RESET_ADD_OUT_STREAMS; + addstrm.param_hdr.length = htons(size); + addstrm.number_of_streams = htons(out); + addstrm.request_seq = htonl(asoc->strreset_outseq); + addstrm.reserved = 0; + + sctp_addto_chunk(retval, size, &addstrm); + } + + if (in) { + addstrm.param_hdr.type = SCTP_PARAM_RESET_ADD_IN_STREAMS; + addstrm.param_hdr.length = htons(size); + addstrm.number_of_streams = htons(in); + addstrm.request_seq = htonl(asoc->strreset_outseq + !!out); + addstrm.reserved = 0; + + sctp_addto_chunk(retval, size, &addstrm); + } + + return retval; +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 09/27] sctp: add stream reconf timer 2017-01-01 11:20 ` [PATCH net-next 08/27] sctp: add rfc6525 section 4.5-4.6 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 10/27] sctp: add stream reconf primitive Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add a per transport timer based on sctp timer frame for stream reconf chunk retransmission. It would start after sending a reconf request chunk, and stop after receiving the response chunk. If the timer expires, besides retransmitting the reconf request chunk, it would also do the same thing with data RTO timer. like to increase the appropriate error counts, and perform threshold management, possibly destroying the asoc if sctp retransmission thresholds are exceeded, just as section 5.1.1 describes. This patch is also to add asoc strreset_chunk, it is used to save the reconf request chunk, so that it can be retransmitted, and to check if the response is really for this request by comparing the information inside with the response chunk as well. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/constants.h | 1 + include/net/sctp/sm.h | 2 ++ include/net/sctp/structs.h | 6 ++++++ net/sctp/associola.c | 3 +++ net/sctp/sm_sideeffect.c | 32 ++++++++++++++++++++++++++++++++ net/sctp/sm_statefuns.c | 28 ++++++++++++++++++++++++++++ net/sctp/sm_statetable.c | 20 ++++++++++++++++++++ net/sctp/transport.c | 17 +++++++++++++++-- 8 files changed, 107 insertions(+), 2 deletions(-) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 5b847e4..8307c86 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -90,6 +90,7 @@ typedef enum { SCTP_EVENT_TIMEOUT_T4_RTO, SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD, SCTP_EVENT_TIMEOUT_HEARTBEAT, + SCTP_EVENT_TIMEOUT_RECONF, SCTP_EVENT_TIMEOUT_SACK, SCTP_EVENT_TIMEOUT_AUTOCLOSE, } sctp_event_timeout_t; diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 35986d0..2ab0a8a 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -167,6 +167,7 @@ sctp_state_fn_t sctp_sf_cookie_wait_icmp_abort; /* Prototypes for timeout event state functions. */ sctp_state_fn_t sctp_sf_do_6_3_3_rtx; +sctp_state_fn_t sctp_sf_send_reconf; sctp_state_fn_t sctp_sf_do_6_2_sack; sctp_state_fn_t sctp_sf_autoclose_timer_expire; @@ -290,6 +291,7 @@ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype, /* 2nd level prototypes */ void sctp_generate_t3_rtx_event(unsigned long peer); void sctp_generate_heartbeat_event(unsigned long peer); +void sctp_generate_reconf_event(unsigned long peer); void sctp_generate_proto_unreach_event(unsigned long peer); void sctp_ootb_pkt_free(struct sctp_packet *); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 09616f1..bb18990 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -873,6 +873,9 @@ struct sctp_transport { /* Timer to handle ICMP proto unreachable envets */ struct timer_list proto_unreach_timer; + /* Timer to handler reconf chunk rtx */ + struct timer_list reconf_timer; + /* Since we're using per-destination retransmission timers * (see above), we're also using per-destination "transmitted" * queues. This probably ought to be a private struct @@ -931,6 +934,7 @@ void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk); void sctp_transport_free(struct sctp_transport *); void sctp_transport_reset_t3_rtx(struct sctp_transport *); void sctp_transport_reset_hb_timer(struct sctp_transport *); +void sctp_transport_reset_reconf_timer(struct sctp_transport *transport); int sctp_transport_hold(struct sctp_transport *); void sctp_transport_put(struct sctp_transport *); void sctp_transport_update_rto(struct sctp_transport *, __u32); @@ -1860,6 +1864,8 @@ struct sctp_association { __u32 strreset_outseq; /* Update after receiving response */ __u32 strreset_inseq; /* Update after receiving request */ + struct sctp_chunk *strreset_chunk; /* save request chunk */ + struct sctp_priv_assoc_stats stats; int sent_cnt_removable; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 74949da..7acfdad 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -363,6 +363,9 @@ void sctp_association_free(struct sctp_association *asoc) kfree(asoc->streamout); kfree(asoc->streamin); + if (asoc->strreset_chunk) + sctp_chunk_free(asoc->strreset_chunk); + /* Clean up the bound address list. */ sctp_bind_addr_free(&asoc->base.bind_addr); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index c345bf1..a455271 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -436,6 +436,37 @@ void sctp_generate_proto_unreach_event(unsigned long data) sctp_association_put(asoc); } + /* Handle the timeout of the RE-CONFIG timer. */ +void sctp_generate_reconf_event(unsigned long data) +{ + struct sctp_transport *transport = (struct sctp_transport *)data; + struct sctp_association *asoc = transport->asoc; + struct sock *sk = asoc->base.sk; + struct net *net = sock_net(sk); + int error = 0; + + bh_lock_sock(sk); + if (sock_owned_by_user(sk)) { + pr_debug("%s: sock is busy\n", __func__); + + /* Try again later. */ + if (!mod_timer(&transport->reconf_timer, jiffies + (HZ / 20))) + sctp_transport_hold(transport); + goto out_unlock; + } + + error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, + SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_RECONF), + asoc->state, asoc->ep, asoc, + transport, GFP_ATOMIC); + + if (error) + sk->sk_err = -error; + +out_unlock: + bh_unlock_sock(sk); + sctp_transport_put(transport); +} /* Inject a SACK Timeout event into the state machine. */ static void sctp_generate_sack_event(unsigned long data) @@ -453,6 +484,7 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = { sctp_generate_t4_rto_event, sctp_generate_t5_shutdown_guard_event, NULL, + NULL, sctp_generate_sack_event, sctp_generate_autoclose_event, }; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8a130a7..b6828dc 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1021,6 +1021,34 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(struct net *net, return SCTP_DISPOSITION_CONSUME; } +/* resend asoc strreset_chunk. */ +sctp_disposition_t sctp_sf_send_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_transport *transport = arg; + + if (asoc->overall_error_count >= asoc->max_retrans) { + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); + /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_PERR(SCTP_ERROR_NO_ERROR)); + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); + return SCTP_DISPOSITION_DELETE_TCB; + } + + sctp_chunk_hold(asoc->strreset_chunk); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(asoc->strreset_chunk)); + sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); + + return SCTP_DISPOSITION_CONSUME; +} + /* * Process an heartbeat request. * diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index a987d54..3da521a 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -888,6 +888,25 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ } +#define TYPE_SCTP_EVENT_TIMEOUT_RECONF { \ + /* SCTP_STATE_CLOSED */ \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ + /* SCTP_STATE_COOKIE_WAIT */ \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ + /* SCTP_STATE_COOKIE_ECHOED */ \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ + /* SCTP_STATE_ESTABLISHED */ \ + TYPE_SCTP_FUNC(sctp_sf_send_reconf), \ + /* SCTP_STATE_SHUTDOWN_PENDING */ \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ + /* SCTP_STATE_SHUTDOWN_SENT */ \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ +} + static const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = { TYPE_SCTP_EVENT_TIMEOUT_NONE, TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE, @@ -897,6 +916,7 @@ static const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][S TYPE_SCTP_EVENT_TIMEOUT_T4_RTO, TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD, TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT, + TYPE_SCTP_EVENT_TIMEOUT_RECONF, TYPE_SCTP_EVENT_TIMEOUT_SACK, TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE, }; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index a1652ab..baa1ac0 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -88,9 +88,11 @@ static struct sctp_transport *sctp_transport_init(struct net *net, INIT_LIST_HEAD(&peer->transports); setup_timer(&peer->T3_rtx_timer, sctp_generate_t3_rtx_event, - (unsigned long)peer); + (unsigned long)peer); setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, - (unsigned long)peer); + (unsigned long)peer); + setup_timer(&peer->reconf_timer, sctp_generate_reconf_event, + (unsigned long)peer); setup_timer(&peer->proto_unreach_timer, sctp_generate_proto_unreach_event, (unsigned long)peer); @@ -144,6 +146,9 @@ void sctp_transport_free(struct sctp_transport *transport) if (del_timer(&transport->T3_rtx_timer)) sctp_transport_put(transport); + if (del_timer(&transport->reconf_timer)) + sctp_transport_put(transport); + /* Delete the ICMP proto unreachable timer if it's active. */ if (del_timer(&transport->proto_unreach_timer)) sctp_association_put(transport->asoc); @@ -211,6 +216,14 @@ void sctp_transport_reset_hb_timer(struct sctp_transport *transport) sctp_transport_hold(transport); } +void sctp_transport_reset_reconf_timer(struct sctp_transport *transport) +{ + if (!timer_pending(&transport->reconf_timer)) + if (!mod_timer(&transport->reconf_timer, + jiffies + transport->rto)) + sctp_transport_hold(transport); +} + /* This transport has been assigned to an association. * Initialize fields from the association or from the sock itself. * Register the reference count in the association. -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 10/27] sctp: add stream reconf primitive 2017-01-01 11:20 ` [PATCH net-next 09/27] sctp: add stream reconf timer Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 11/27] sctp: add reconf_enable in asoc ep and netns Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add a primitive based on sctp primitive frame for sending stream reconf request. It works as the other primitives, and create a SCTP_CMD_REPLY command to send the request chunk out. sctp_primitive_RECONF would be the api to send a reconf request chunk. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/constants.h | 3 ++- include/net/sctp/sctp.h | 2 ++ include/net/sctp/sm.h | 1 + net/sctp/primitive.c | 3 +++ net/sctp/sm_statefuns.c | 13 +++++++++++++ net/sctp/sm_statetable.c | 20 ++++++++++++++++++++ 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 8307c86..3567c97 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -114,9 +114,10 @@ typedef enum { SCTP_PRIMITIVE_SEND, SCTP_PRIMITIVE_REQUESTHEARTBEAT, SCTP_PRIMITIVE_ASCONF, + SCTP_PRIMITIVE_RECONF, } sctp_event_primitive_t; -#define SCTP_EVENT_PRIMITIVE_MAX SCTP_PRIMITIVE_ASCONF +#define SCTP_EVENT_PRIMITIVE_MAX SCTP_PRIMITIVE_RECONF #define SCTP_NUM_PRIMITIVE_TYPES (SCTP_EVENT_PRIMITIVE_MAX + 1) /* We define here a utility type for manipulating subtypes. diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 598d938..bc0e049 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -141,6 +141,8 @@ int sctp_primitive_ABORT(struct net *, struct sctp_association *, void *arg); int sctp_primitive_SEND(struct net *, struct sctp_association *, void *arg); int sctp_primitive_REQUESTHEARTBEAT(struct net *, struct sctp_association *, void *arg); int sctp_primitive_ASCONF(struct net *, struct sctp_association *, void *arg); +int sctp_primitive_RECONF(struct net *net, struct sctp_association *asoc, + void *arg); /* * sctp/input.c diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 2ab0a8a..bcca913 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -157,6 +157,7 @@ sctp_state_fn_t sctp_sf_error_shutdown; sctp_state_fn_t sctp_sf_ignore_primitive; sctp_state_fn_t sctp_sf_do_prm_requestheartbeat; sctp_state_fn_t sctp_sf_do_prm_asconf; +sctp_state_fn_t sctp_sf_do_prm_reconf; /* Prototypes for other event state functions. */ sctp_state_fn_t sctp_sf_do_no_pending_tsn; diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index ab8d9f9..f0553a0 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -211,3 +211,6 @@ DECLARE_PRIMITIVE(REQUESTHEARTBEAT); */ DECLARE_PRIMITIVE(ASCONF); + +/* RE-CONFIG 5.1 */ +DECLARE_PRIMITIVE(RECONF); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index b6828dc..c06b134 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5185,6 +5185,19 @@ sctp_disposition_t sctp_sf_do_prm_asconf(struct net *net, return SCTP_DISPOSITION_CONSUME; } +/* RE-CONFIG Section 5.1 RECONF Chunk Procedures */ +sctp_disposition_t sctp_sf_do_prm_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_chunk *chunk = arg; + + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); + return SCTP_DISPOSITION_CONSUME; +} + /* * Ignore the primitive event * diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 3da521a..b5438b4 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -643,6 +643,25 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ } /* TYPE_SCTP_PRIMITIVE_ASCONF */ +#define TYPE_SCTP_PRIMITIVE_RECONF { \ + /* SCTP_STATE_CLOSED */ \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ + /* SCTP_STATE_COOKIE_WAIT */ \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ + /* SCTP_STATE_COOKIE_ECHOED */ \ + TYPE_SCTP_FUNC(sctp_sf_error_closed), \ + /* SCTP_STATE_ESTABLISHED */ \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_reconf), \ + /* SCTP_STATE_SHUTDOWN_PENDING */ \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_reconf), \ + /* SCTP_STATE_SHUTDOWN_SENT */ \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_reconf), \ + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ + TYPE_SCTP_FUNC(sctp_sf_do_prm_reconf), \ + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ + TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ +} /* TYPE_SCTP_PRIMITIVE_RECONF */ + /* The primary index for this table is the primitive type. * The secondary index for this table is the state. */ @@ -653,6 +672,7 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE TYPE_SCTP_PRIMITIVE_SEND, TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT, TYPE_SCTP_PRIMITIVE_ASCONF, + TYPE_SCTP_PRIMITIVE_RECONF, }; #define TYPE_SCTP_OTHER_NO_PENDING_TSN { \ -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 11/27] sctp: add reconf_enable in asoc ep and netns 2017-01-01 11:20 ` [PATCH net-next 10/27] sctp: add stream reconf primitive Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 12/27] sctp: add get and set sockopt for reconf_enable Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add reconf_enable field in all of asoc ep and netns to indicate if they support stream reset. When initializing, asoc reconf_enable get the default value from ep reconf_enable which is from netns netns reconf_enable by default. It is also to add reconf_capable in asoc peer part to know if peer supports reconf_enable, the value is set if ext params have reconf chunk support when processing init chunk, just as rfc6525 section 5.1.1 demands. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/netns/sctp.h | 3 +++ include/net/sctp/structs.h | 7 +++++-- net/sctp/associola.c | 1 + net/sctp/endpointola.c | 1 + net/sctp/sm_make_chunk.c | 15 +++++++++++++++ net/sctp/sysctl.c | 7 +++++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h index c501d67..b7871d0 100644 --- a/include/net/netns/sctp.h +++ b/include/net/netns/sctp.h @@ -118,6 +118,9 @@ struct netns_sctp { /* Flag to indicate if PR-SCTP is enabled. */ int prsctp_enable; + /* Flag to indicate if PR-CONFIG is enabled. */ + int reconf_enable; + /* Flag to idicate if SCTP-AUTH is enabled */ int auth_enable; diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index bb18990..7c46398 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1251,7 +1251,8 @@ struct sctp_endpoint { struct list_head endpoint_shared_keys; __u16 active_key_id; __u8 auth_enable:1, - prsctp_enable:1; + prsctp_enable:1, + reconf_enable:1; }; /* Recover the outter endpoint structure. */ @@ -1497,6 +1498,7 @@ struct sctp_association { hostname_address:1, /* Peer understands DNS addresses? */ asconf_capable:1, /* Does peer support ADDIP? */ prsctp_capable:1, /* Can peer do PR-SCTP? */ + reconf_capable:1, /* Can peer do RE-CONFIG? */ auth_capable:1; /* Is peer doing SCTP-AUTH? */ /* sack_needed : This flag indicates if the next received @@ -1853,7 +1855,8 @@ struct sctp_association { __u8 need_ecne:1, /* Need to send an ECNE Chunk? */ temp:1, /* Is it a temporary association? */ - prsctp_enable:1; + prsctp_enable:1, + reconf_enable:1; /* stream arrays */ struct sctp_stream_out *streamout; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 7acfdad..ab43cb6 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -270,6 +270,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a asoc->active_key_id = ep->active_key_id; asoc->prsctp_enable = ep->prsctp_enable; + asoc->reconf_enable = ep->reconf_enable; /* Save the hmacs and chunks list into this association */ if (ep->auth_hmacs_list) diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 410ddc1..8c58923 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -164,6 +164,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, ep->auth_hmacs_list = auth_hmacs; ep->auth_chunk_list = auth_chunks; ep->prsctp_enable = net->sctp.prsctp_enable; + ep->reconf_enable = net->sctp.reconf_enable; return ep; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 102e816..f1efba6 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -270,6 +270,11 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, num_ext += 2; } + if (asoc->reconf_enable) { + extensions[num_ext] = SCTP_CID_RECONF; + num_ext += 1; + } + if (sp->adaptation_ind) chunksize += sizeof(aiparam); @@ -434,6 +439,11 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, num_ext += 2; } + if (asoc->peer.reconf_capable) { + extensions[num_ext] = SCTP_CID_RECONF; + num_ext += 1; + } + if (sp->adaptation_ind) chunksize += sizeof(aiparam); @@ -2010,6 +2020,11 @@ static void sctp_process_ext_param(struct sctp_association *asoc, for (i = 0; i < num_ext; i++) { switch (param.ext->chunks[i]) { + case SCTP_CID_RECONF: + if (asoc->reconf_enable && + !asoc->peer.reconf_capable) + asoc->peer.reconf_capable = 1; + break; case SCTP_CID_FWD_TSN: if (asoc->prsctp_enable && !asoc->peer.prsctp_capable) asoc->peer.prsctp_capable = 1; 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] 37+ messages in thread
* [PATCH net-next 12/27] sctp: add get and set sockopt for reconf_enable 2017-01-01 11:20 ` [PATCH net-next 11/27] sctp: add reconf_enable in asoc ep and netns Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 13/27] sctp: add rfc6525 section 6.3.1 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, 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. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/uapi/linux/sctp.h | 1 + net/sctp/socket.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index a406adc..4d3b621 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 /* PR-SCTP policies */ #define SCTP_PR_SCTP_NONE 0x0000 diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 318c678..e946bc2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3751,6 +3751,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(¶ms, 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; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -3917,6 +3950,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; default: retval = -ENOPROTOOPT; break; @@ -6401,6 +6437,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(¶ms, 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, ¶ms, len)) + goto out; + + retval = 0; + +out: + return retval; +} + static int sctp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -6568,6 +6645,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; default: retval = -ENOPROTOOPT; break; -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 13/27] sctp: add rfc6525 section 6.3.1 2017-01-01 11:20 ` [PATCH net-next 12/27] sctp: add get and set sockopt for reconf_enable Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 14/27] sctp: add rfc6525 section 5.1.2-5.1.3 and 6.3.2 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add sockopt SCTP_ENABLE_STREAM_RESET to set strreset_enable to indicate which reconf request type it supports, which is described in section 6.3.1. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/structs.h | 4 +++ include/uapi/linux/sctp.h | 7 ++++ net/sctp/associola.c | 1 + net/sctp/socket.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 7c46398..56282a3 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1253,6 +1253,8 @@ struct sctp_endpoint { __u8 auth_enable:1, prsctp_enable:1, reconf_enable:1; + + __u8 strreset_enable; }; /* Recover the outter endpoint structure. */ @@ -1858,6 +1860,8 @@ struct sctp_association { prsctp_enable:1, reconf_enable:1; + __u8 strreset_enable; + /* stream arrays */ struct sctp_stream_out *streamout; struct sctp_stream_in *streamin; diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index 4d3b621..950d76a 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -116,6 +116,7 @@ typedef __s32 sctp_assoc_t; #define SCTP_DEFAULT_PRINFO 114 #define SCTP_PR_ASSOC_STATUS 115 #define SCTP_RECONFIG_SUPPORTED 117 +#define SCTP_ENABLE_STREAM_RESET 118 /* PR-SCTP policies */ #define SCTP_PR_SCTP_NONE 0x0000 @@ -139,6 +140,12 @@ typedef __s32 sctp_assoc_t; #define SCTP_PR_RTX_ENABLED(x) (SCTP_PR_POLICY(x) == SCTP_PR_SCTP_RTX) #define SCTP_PR_PRIO_ENABLED(x) (SCTP_PR_POLICY(x) == SCTP_PR_SCTP_PRIO) +/* For enable stream reset */ +#define SCTP_ENABLE_RESET_STREAM_REQ 0x01 +#define SCTP_ENABLE_RESET_ASSOC_REQ 0x02 +#define SCTP_ENABLE_CHANGE_ASSOC_REQ 0x04 +#define SCTP_ENABLE_STRRESET_MASK 0x07 + /* These are bit fields for msghdr->msg_flags. See section 5.1. */ /* On user space Linux, these live in <bits/socket.h> as an enum. */ enum sctp_msg_flags { diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ab43cb6..44b8690 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -271,6 +271,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a asoc->active_key_id = ep->active_key_id; asoc->prsctp_enable = ep->prsctp_enable; asoc->reconf_enable = ep->reconf_enable; + asoc->strreset_enable = ep->strreset_enable; /* Save the hmacs and chunks list into this association */ if (ep->auth_hmacs_list) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e946bc2..3cae585 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3784,6 +3784,42 @@ static int sctp_setsockopt_reconfig_supported(struct sock *sk, return retval; } +static int sctp_setsockopt_enable_strreset(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(¶ms, optval, optlen)) { + retval = -EFAULT; + goto out; + } + + if (params.assoc_value & (~SCTP_ENABLE_STRRESET_MASK)) + goto out; + + asoc = sctp_id2assoc(sk, params.assoc_id); + if (asoc) { + asoc->strreset_enable = params.assoc_value; + } else if (!params.assoc_id) { + struct sctp_sock *sp = sctp_sk(sk); + + sp->ep->strreset_enable = params.assoc_value; + } else { + goto out; + } + + retval = 0; + +out: + return retval; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -3953,6 +3989,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, 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; default: retval = -ENOPROTOOPT; break; @@ -6478,6 +6517,47 @@ static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len, return retval; } +static int sctp_getsockopt_enable_strreset(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(¶ms, optval, len)) + goto out; + + asoc = sctp_id2assoc(sk, params.assoc_id); + if (asoc) { + params.assoc_value = asoc->strreset_enable; + } else if (!params.assoc_id) { + struct sctp_sock *sp = sctp_sk(sk); + + params.assoc_value = sp->ep->strreset_enable; + } else { + retval = -EINVAL; + goto out; + } + + if (put_user(len, optlen)) + goto out; + + if (copy_to_user(optval, ¶ms, len)) + goto out; + + retval = 0; + +out: + return retval; +} + static int sctp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -6649,6 +6729,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, retval = sctp_getsockopt_reconfig_supported(sk, len, optval, optlen); break; + case SCTP_ENABLE_STREAM_RESET: + retval = sctp_getsockopt_enable_strreset(sk, len, optval, + optlen); + break; default: retval = -ENOPROTOOPT; break; -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 14/27] sctp: add rfc6525 section 5.1.2-5.1.3 and 6.3.2 2017-01-01 11:20 ` [PATCH net-next 13/27] sctp: add rfc6525 section 6.3.1 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 15/27] sctp: add rfc6525 section 5.1.4 and 6.3.3 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement sender-side procedures for the Outgoing and Incoming SSN Reset Request Parameter described in section 5.1.2 and 5.1.3. It is also add sockopt SCTP_RESET_STREAMS in section 6.3.2 for users. Note that the new asoc member strreset_outstanding is to make sure only one reconf request chunk on the fly as section 5.1.1 demands. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 11 ++++++ net/sctp/outqueue.c | 33 +++++++++++----- net/sctp/socket.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 10 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 56282a3..ce8985f 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1861,6 +1861,7 @@ struct sctp_association { reconf_enable:1; __u8 strreset_enable; + __u8 strreset_outstanding; /* request param count on the fly */ /* stream arrays */ struct sctp_stream_out *streamout; diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index 950d76a..1f4518b 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -117,6 +117,7 @@ typedef __s32 sctp_assoc_t; #define SCTP_PR_ASSOC_STATUS 115 #define SCTP_RECONFIG_SUPPORTED 117 #define SCTP_ENABLE_STREAM_RESET 118 +#define SCTP_RESET_STREAMS 119 /* PR-SCTP policies */ #define SCTP_PR_SCTP_NONE 0x0000 @@ -146,6 +147,9 @@ typedef __s32 sctp_assoc_t; #define SCTP_ENABLE_CHANGE_ASSOC_REQ 0x04 #define SCTP_ENABLE_STRRESET_MASK 0x07 +#define SCTP_STREAM_RESET_INCOMING 0x01 +#define SCTP_STREAM_RESET_OUTGOING 0x02 + /* These are bit fields for msghdr->msg_flags. See section 5.1. */ /* On user space Linux, these live in <bits/socket.h> as an enum. */ enum sctp_msg_flags { @@ -1016,4 +1020,11 @@ struct sctp_info { __u32 __reserved3; }; +struct sctp_reset_streams { + sctp_assoc_t srs_assoc_id; + uint16_t srs_flags; + uint16_t srs_number_streams; /* 0 == ALL */ + uint16_t srs_stream_list[]; /* list if srs_num_streams is not 0 */ +}; + #endif /* _UAPI_SCTP_H */ diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index e540826..5d668c9 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -915,22 +915,28 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) case SCTP_CID_ECN_ECNE: case SCTP_CID_ASCONF: case SCTP_CID_FWD_TSN: + case SCTP_CID_RECONF: status = sctp_packet_transmit_chunk(packet, chunk, one_packet, gfp); if (status != SCTP_XMIT_OK) { /* put the chunk back */ list_add(&chunk->list, &q->control_chunk_list); - } else { - asoc->stats.octrlchunks++; - /* PR-SCTP C5) If a FORWARD TSN is sent, the - * sender MUST assure that at least one T3-rtx - * timer is running. - */ - if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) { - sctp_transport_reset_t3_rtx(transport); - transport->last_time_sent = jiffies; - } + break; + } + + asoc->stats.octrlchunks++; + /* PR-SCTP C5) If a FORWARD TSN is sent, the + * sender MUST assure that at least one T3-rtx + * timer is running. + */ + if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) { + sctp_transport_reset_t3_rtx(transport); + transport->last_time_sent = jiffies; } + + if (chunk == asoc->strreset_chunk) + sctp_transport_reset_reconf_timer(transport); + break; default: @@ -1016,6 +1022,8 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) /* Finally, transmit new packets. */ while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { + __u32 sid = ntohs(chunk->subh.data_hdr->stream); + /* RFC 2960 6.5 Every DATA chunk MUST carry a valid * stream identifier. */ @@ -1038,6 +1046,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) continue; } + if (asoc->streamout[sid].state == SCTP_STREAM_CLOSED) { + sctp_outq_head_data(q, chunk); + goto sctp_flush_out; + } + /* If there is a specified transport, use it. * Otherwise, we want to use the active path. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3cae585..e62872c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -434,6 +434,19 @@ static int sctp_send_asconf(struct sctp_association *asoc, return retval; } +static int sctp_send_reconf(struct sctp_association *asoc, + struct sctp_chunk *chunk) +{ + struct net *net = sock_net(asoc->base.sk); + int retval = 0; + + retval = sctp_primitive_RECONF(net, asoc, chunk); + if (retval) + sctp_chunk_free(chunk); + + return retval; +} + /* Add a list of addresses as bind addresses to local endpoint or * association. * @@ -3820,6 +3833,87 @@ static int sctp_setsockopt_enable_strreset(struct sock *sk, return retval; } +static int sctp_setsockopt_reset_streams(struct sock *sk, + char __user *optval, + unsigned int optlen) +{ + struct sctp_reset_streams *params; + struct sctp_association *asoc; + struct sctp_chunk *chunk = NULL; + __u16 i, str_nums, *str_list; + int retval = -EINVAL; + bool out, in; + + if (optlen < sizeof(struct sctp_reset_streams)) + return -EINVAL; + + params = memdup_user(optval, optlen); + if (IS_ERR(params)) { + retval = PTR_ERR(params); + goto out; + } + + asoc = sctp_id2assoc(sk, params->srs_assoc_id); + if (!asoc) + goto out; + + if (!asoc->peer.reconf_capable || + !(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) { + retval = -ENOPROTOOPT; + goto out; + } + + if (asoc->strreset_outstanding) { + retval = -EINPROGRESS; + goto out; + } + + out = params->srs_flags & SCTP_STREAM_RESET_OUTGOING; + in = params->srs_flags & SCTP_STREAM_RESET_INCOMING; + if (!out && !in) + goto out; + + str_nums = params->srs_number_streams; + str_list = params->srs_stream_list; + if (out && str_nums) + for (i = 0; i < str_nums; i++) + if (str_list[i] >= asoc->streamoutcnt) + goto out; + + if (in && str_nums) + for (i = 0; i < str_nums; i++) + if (str_list[i] >= asoc->streamincnt) + goto out; + + chunk = sctp_make_strreset_req(asoc, str_nums, str_list, out, in); + if (!chunk) + goto out; + + if (out) { + if (str_nums) + for (i = 0; i < str_nums; i++) + asoc->streamout[str_list[i]].state = + SCTP_STREAM_CLOSED; + else + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[i].state = SCTP_STREAM_CLOSED; + } + + asoc->strreset_outstanding = out + in; + asoc->strreset_chunk = chunk; + sctp_chunk_hold(asoc->strreset_chunk); + + retval = sctp_send_reconf(asoc, chunk); + if (retval) { + sctp_chunk_put(asoc->strreset_chunk); + asoc->strreset_chunk = NULL; + } + +out: + kfree(params); + return retval; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -3992,6 +4086,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_ENABLE_STREAM_RESET: retval = sctp_setsockopt_enable_strreset(sk, optval, optlen); break; + case SCTP_RESET_STREAMS: + retval = sctp_setsockopt_reset_streams(sk, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 15/27] sctp: add rfc6525 section 5.1.4 and 6.3.3 2017-01-01 11:20 ` [PATCH net-next 14/27] sctp: add rfc6525 section 5.1.2-5.1.3 and 6.3.2 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 16/27] sctp: add rfc6525 section 5.1.5-5.1.6 and 6.3.4 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement Sender-Side Procedures for the SSN/TSN Reset Request Parameter descibed in section 5.1.4. It is also to add sockopt SCTP_RESET_ASSOC in section 6.3.3 for users. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/uapi/linux/sctp.h | 1 + net/sctp/socket.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index 1f4518b..c1c77c8 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -118,6 +118,7 @@ typedef __s32 sctp_assoc_t; #define SCTP_RECONFIG_SUPPORTED 117 #define SCTP_ENABLE_STREAM_RESET 118 #define SCTP_RESET_STREAMS 119 +#define SCTP_RESET_ASSOC 120 /* PR-SCTP policies */ #define SCTP_PR_SCTP_NONE 0x0000 diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e62872c..bcefc55 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3914,6 +3914,60 @@ static int sctp_setsockopt_reset_streams(struct sock *sk, return retval; } +static int sctp_setsockopt_reset_assoc(struct sock *sk, + char __user *optval, + unsigned int optlen) +{ + struct sctp_association *asoc; + struct sctp_chunk *chunk = NULL; + sctp_assoc_t associd; + int retval = -EINVAL; + __u16 i; + + if (optlen != sizeof(associd)) + goto out; + + if (copy_from_user(&associd, optval, optlen)) { + retval = -EFAULT; + goto out; + } + + asoc = sctp_id2assoc(sk, associd); + if (!asoc) + goto out; + + if (!asoc->peer.reconf_capable || + !(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) { + retval = -ENOPROTOOPT; + goto out; + } + + if (asoc->strreset_outstanding) { + retval = -EINPROGRESS; + goto out; + } + + chunk = sctp_make_strreset_tsnreq(asoc); + if (!chunk) + goto out; + + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[i].state = SCTP_STREAM_CLOSED; + + asoc->strreset_outstanding = 1; + asoc->strreset_chunk = chunk; + sctp_chunk_hold(asoc->strreset_chunk); + + retval = sctp_send_reconf(asoc, chunk); + if (retval) { + sctp_chunk_put(asoc->strreset_chunk); + asoc->strreset_chunk = NULL; + } + +out: + return retval; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -4089,6 +4143,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_RESET_STREAMS: retval = sctp_setsockopt_reset_streams(sk, optval, optlen); break; + case SCTP_RESET_ASSOC: + retval = sctp_setsockopt_reset_assoc(sk, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 16/27] sctp: add rfc6525 section 5.1.5-5.1.6 and 6.3.4 2017-01-01 11:20 ` [PATCH net-next 15/27] sctp: add rfc6525 section 5.1.4 and 6.3.3 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 17/27] sctp: add rfc6525 section 6.1.1 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement Sender-Side Procedures for the Add Outgoing and Incoming Streams Request Parameter described in 5.1.5-5.1.6. It is also to add sockopt SCTP_ADD_STREAMS in section 6.3.4 for users. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/uapi/linux/sctp.h | 7 +++ net/sctp/socket.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index c1c77c8..4401a40 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -119,6 +119,7 @@ typedef __s32 sctp_assoc_t; #define SCTP_ENABLE_STREAM_RESET 118 #define SCTP_RESET_STREAMS 119 #define SCTP_RESET_ASSOC 120 +#define SCTP_ADD_STREAMS 121 /* PR-SCTP policies */ #define SCTP_PR_SCTP_NONE 0x0000 @@ -1028,4 +1029,10 @@ struct sctp_reset_streams { uint16_t srs_stream_list[]; /* list if srs_num_streams is not 0 */ }; +struct sctp_add_streams { + sctp_assoc_t sas_assoc_id; + uint16_t sas_instrms; + uint16_t sas_outstrms; +}; + #endif /* _UAPI_SCTP_H */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index bcefc55..a4e8aac 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3968,6 +3968,117 @@ static int sctp_setsockopt_reset_assoc(struct sock *sk, return retval; } +static int sctp_setsockopt_add_streams(struct sock *sk, + char __user *optval, + unsigned int optlen) +{ + struct sctp_association *asoc; + struct sctp_chunk *chunk = NULL; + struct sctp_add_streams params; + int retval = -EINVAL; + __u16 out, in; + + if (optlen != sizeof(params)) + goto out; + + if (copy_from_user(¶ms, optval, optlen)) { + retval = -EFAULT; + goto out; + } + + asoc = sctp_id2assoc(sk, params.sas_assoc_id); + if (!asoc) + goto out; + + if (!asoc->peer.reconf_capable || + !(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { + retval = -ENOPROTOOPT; + goto out; + } + + if (asoc->strreset_outstanding) { + retval = -EINPROGRESS; + goto out; + } + + out = params.sas_outstrms; + in = params.sas_instrms; + + if (!out && !in) + goto out; + + if (out) { + __u16 nums = asoc->streamoutcnt + out; + + /* Check for overflow, can't use nums here */ + if (asoc->streamoutcnt + out > SCTP_MAX_STREAM) + goto out; + + /* Use ksize to check if stream array really needs to realloc */ + if (ksize(asoc->streamout) / sizeof(*asoc->streamout) < nums) { + struct sctp_stream_out *streamout; + + streamout = kcalloc(nums, sizeof(*streamout), + GFP_KERNEL); + if (!streamout) { + retval = -ENOMEM; + goto out; + } + + memcpy(streamout, asoc->streamout, + sizeof(*streamout) * asoc->streamoutcnt); + + kfree(asoc->streamout); + asoc->streamout = streamout; + } + + asoc->streamoutcnt = nums; + } + + if (in) { + __u16 nums = asoc->streamincnt + in; + + if (asoc->streamincnt + in > SCTP_MAX_STREAM) + goto out; + + if (ksize(asoc->streamin) / sizeof(*asoc->streamin) < nums) { + struct sctp_stream_in *streamin; + + streamin = kcalloc(nums, sizeof(*streamin), + GFP_KERNEL); + if (!streamin) { + retval = -ENOMEM; + goto out; + } + + memcpy(streamin, asoc->streamin, + sizeof(*streamin) * asoc->streamincnt); + + kfree(asoc->streamin); + asoc->streamin = streamin; + } + + asoc->streamincnt = nums; + } + + chunk = sctp_make_strreset_addstrm(asoc, out, in); + if (!chunk) + goto out; + + asoc->strreset_outstanding = !!out + !!in; + asoc->strreset_chunk = chunk; + sctp_chunk_hold(asoc->strreset_chunk); + + retval = sctp_send_reconf(asoc, chunk); + if (retval) { + sctp_chunk_put(asoc->strreset_chunk); + asoc->strreset_chunk = NULL; + } + +out: + return retval; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -4146,6 +4257,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_RESET_ASSOC: retval = sctp_setsockopt_reset_assoc(sk, optval, optlen); break; + case SCTP_ADD_STREAMS: + retval = sctp_setsockopt_add_streams(sk, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 17/27] sctp: add rfc6525 section 6.1.1 2017-01-01 11:20 ` [PATCH net-next 16/27] sctp: add rfc6525 section 5.1.5-5.1.6 and 6.3.4 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 18/27] sctp: add rfc6525 section 6.1.2 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add Stream Reset Event described in section 6.1.1. It's added earlier here so that the codes for other sections could invoked them. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/ulpevent.h | 4 ++++ include/uapi/linux/sctp.h | 36 ++++++++++++++++++++++++++---------- net/sctp/ulpevent.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 10 deletions(-) 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 4401a40..97b8a96 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -491,21 +491,34 @@ 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 { + uint16_t strreset_type; + uint16_t strreset_flags; + uint32_t strreset_length; + sctp_assoc_t strreset_assoc_id; + uint16_t strreset_stream_list[]; +}; + /* * Described in Section 7.3 * Ancillary Data and Notification Interest Options */ struct sctp_event_subscribe { - __u8 sctp_data_io_event; - __u8 sctp_association_event; - __u8 sctp_address_event; - __u8 sctp_send_failure_event; - __u8 sctp_peer_error_event; - __u8 sctp_shutdown_event; - __u8 sctp_partial_delivery_event; - __u8 sctp_adaptation_layer_event; - __u8 sctp_authentication_event; - __u8 sctp_sender_dry_event; + uint8_t sctp_data_io_event; + uint8_t sctp_association_event; + uint8_t sctp_address_event; + uint8_t sctp_send_failure_event; + uint8_t sctp_peer_error_event; + uint8_t sctp_shutdown_event; + uint8_t sctp_partial_delivery_event; + uint8_t sctp_adaptation_layer_event; + uint8_t sctp_authentication_event; + uint8_t sctp_sender_dry_event; + uint8_t sctp_stream_reset_event; }; /* @@ -530,6 +543,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 @@ -557,6 +571,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..490d573 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -854,6 +854,36 @@ 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; + + event = sctp_ulpevent_new(sizeof(struct sctp_stream_reset_event) + + 2 * stream_num, MSG_NOTIFICATION, gfp); + if (!event) + return NULL; + + skb = sctp_event2skb(event); + sreset = (struct sctp_stream_reset_event *)skb_put(skb, + sizeof(struct sctp_stream_reset_event) + 2 * stream_num); + + sreset->strreset_type = SCTP_STREAM_RESET_EVENT; + sreset->strreset_flags = flags; + sreset->strreset_length = sizeof(struct sctp_stream_reset_event); + sctp_ulpevent_set_owner(event, asoc); + sreset->strreset_assoc_id = sctp_assoc2id(asoc); + + if (stream_num) + memcpy(sreset->strreset_stream_list, stream_list, + 2 * stream_num); + + return event; +} + /* Return the notification type, assuming this is a notification * event. */ -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 18/27] sctp: add rfc6525 section 6.1.2 2017-01-01 11:20 ` [PATCH net-next 17/27] sctp: add rfc6525 section 6.1.1 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 19/27] sctp: add rfc6525 section 6.1.3 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add Association Reset Event described in 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 97b8a96..9da165a 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -503,6 +503,17 @@ struct sctp_stream_reset_event { uint16_t strreset_stream_list[]; }; +#define SCTP_ASSOC_RESET_DENIED 0x0004 +#define SCTP_ASSOC_RESET_FAILED 0x0008 +struct sctp_assoc_reset_event { + uint16_t assocreset_type; + uint16_t assocreset_flags; + uint32_t assocreset_length; + sctp_assoc_t assocreset_assoc_id; + uint32_t assocreset_local_tsn; + uint32_t assocreset_remote_tsn; +}; + /* * Described in Section 7.3 * Ancillary Data and Notification Interest Options @@ -519,6 +530,7 @@ struct sctp_event_subscribe { uint8_t sctp_authentication_event; uint8_t sctp_sender_dry_event; uint8_t sctp_stream_reset_event; + uint8_t sctp_assoc_reset_event; }; /* @@ -544,6 +556,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 @@ -573,6 +586,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 490d573..5492cd7 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -884,6 +884,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] 37+ messages in thread
* [PATCH net-next 19/27] sctp: add rfc6525 section 6.1.3 2017-01-01 11:20 ` [PATCH net-next 18/27] sctp: add rfc6525 section 6.1.2 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add Stream Change Event described in 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 9da165a..90a8e2c 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -514,6 +514,17 @@ struct sctp_assoc_reset_event { uint32_t assocreset_remote_tsn; }; +#define SCTP_ASSOC_CHANGE_DENIED 0x0004 +#define SCTP_ASSOC_CHANGE_FAILED 0x0008 +struct sctp_stream_change_event { + uint16_t strchange_type; + uint16_t strchange_flags; + uint32_t strchange_length; + sctp_assoc_t strchange_assoc_id; + uint16_t strchange_instrms; + uint16_t strchange_outstrms; +}; + /* * Described in Section 7.3 * Ancillary Data and Notification Interest Options @@ -531,6 +542,7 @@ struct sctp_event_subscribe { uint8_t sctp_sender_dry_event; uint8_t sctp_stream_reset_event; uint8_t sctp_assoc_reset_event; + uint8_t sctp_stream_change_event; }; /* @@ -557,6 +569,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 @@ -588,6 +601,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 5492cd7..c56460f 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -912,6 +912,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] 37+ messages in thread
* [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 2017-01-01 11:20 ` [PATCH net-next 19/27] sctp: add rfc6525 section 6.1.3 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 21/27] sctp: add rfc6525 section 5.2.3 Xin Long 2017-01-01 12:02 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 kbuild test robot 0 siblings, 2 replies; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement Receiver-Side Procedures for the Outgoing SSN Reset Request Parameter described in 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/Makefile | 3 +- net/sctp/stream.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 net/sctp/stream.c diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index bcca913..1833215 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -280,6 +280,12 @@ struct sctp_chunk *sctp_make_strreset_addstrm( 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/Makefile b/net/sctp/Makefile index 48bfc74..02d8d01 100644 --- a/net/sctp/Makefile +++ b/net/sctp/Makefile @@ -11,7 +11,8 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ transport.o chunk.o sm_make_chunk.o ulpevent.o \ inqueue.o outqueue.o ulpqueue.o \ tsnmap.o bind_addr.o socket.o primitive.o \ - output.o input.o debug.o auth.o offload.o + output.o input.o debug.o auth.o offload.o \ + stream.o sctp_probe-y := probe.o diff --git a/net/sctp/stream.c b/net/sctp/stream.c new file mode 100644 index 0000000..1d5b795 --- /dev/null +++ b/net/sctp/stream.c @@ -0,0 +1,146 @@ +/* SCTP kernel implementation + * (C) Copyright IBM Corp. 2001, 2004 + * Copyright (c) 1999-2000 Cisco, Inc. + * Copyright (c) 1999-2001 Motorola, Inc. + * Copyright (c) 2001 Intel Corp. + * + * This file is part of the SCTP kernel implementation + * + * These functions manipulate sctp tsn mapping array. + * + * This SCTP implementation is free software; + * you can redistribute it and/or modify it under the terms of + * the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This SCTP implementation is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * ************************ + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU CC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + * Please send any bug reports or fixes you make to the + * email address(es): + * lksctp developers <linux-sctp@vger.kernel.org> + * + * Written or modified by: + * Xin Long <lucien.xin@gmail.com> + */ + +#include <net/sctp/sctp.h> +#include <net/sctp/sm.h> + +static struct sctp_strreset_req *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 (resp_seq != asoc->strreset_outseq || !chunk) + return NULL; + + hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr; + sctp_walk_params(param, hdr, params) { + struct sctp_strreset_req *req = param.v; + + if (ntohl(req->request_seq) == resp_seq) + return req; + } + + 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; + __u32 result = SCTP_STRRESET_DENIED; + __u16 i, nums, *str_p, flags = 0; + __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) { + struct sctp_strreset_req *inreq; + struct sctp_transport *t; + + inreq = sctp_chunk_lookup_strreset_param( + asoc, ntohl(outreq->response_seq)); + if (!inreq || inreq->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++) { + str_p[i] = ntohs(str_p[i]); + if (str_p[i] >= asoc->streamincnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; + goto out; + } + } + + str_p = outreq->list_of_streams; + for (i = 0; i < nums; i++, str_p++) + asoc->streamin[*str_p].ssn = 0; + } else { + for (i = 0; i < asoc->streamincnt; i++) + asoc->streamin[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] 37+ messages in thread
* [PATCH net-next 21/27] sctp: add rfc6525 section 5.2.3 2017-01-01 11:20 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 Xin Long 2017-01-01 12:02 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 kbuild test robot 1 sibling, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement Receiver-Side Procedures for the Incoming SSN Reset Request Parameter described in section 5.2.3. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 4 ++++ net/sctp/stream.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 1833215..180d017 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/stream.c b/net/sctp/stream.c index 1d5b795..3053d06 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -144,3 +144,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; + __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++) { + str_p[i] = ntohs(str_p[i]); + if (str_p[i] >= asoc->streamoutcnt) { + 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++) + asoc->streamout[str_p[i]].state = + SCTP_STREAM_CLOSED; + else + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[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] 37+ messages in thread
* [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 2017-01-01 11:20 ` [PATCH net-next 21/27] sctp: add rfc6525 section 5.2.3 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 23/27] sctp: add rfc6525 section 5.2.5 Xin Long 2017-01-01 12:14 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 kbuild test robot 0 siblings, 2 replies; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement Receiver-Side Procedures for the SSN/TSN Reset Request Parameter described in section 6.2.4. The process is kinda complicate, it's wonth having 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/stream.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 180d017..e1b2509 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -289,6 +289,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/stream.c b/net/sctp/stream.c index 3053d06..fce4317 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -207,3 +207,79 @@ 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) +{ + struct sctp_strreset_tsnreq *tsnreq = param.v; + __u32 request_seq, initial_tsn, max_tsn_seen; + __u32 result = SCTP_STRRESET_DENIED; + __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. + */ + initial_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31); + sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, + initial_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. + */ + asoc->ctsn_ack_point = asoc->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 < asoc->streamoutcnt; i++) + asoc->streamout[i].ssn = 0; + for (i = 0; i < asoc->streamincnt; i++) + asoc->streamin[i].ssn = 0; + + result = SCTP_STRRESET_PERFORMED; + + *evp = sctp_ulpevent_make_assoc_reset_event(asoc, + 0, initial_tsn, asoc->next_tsn, GFP_ATOMIC); + +out: + return sctp_make_strreset_tsnresp(asoc, result, request_seq, + asoc->next_tsn, initial_tsn); +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 23/27] sctp: add rfc6525 section 5.2.5 2017-01-01 11:20 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 24/27] sctp: add rfc6525 section 5.2.6 Xin Long 2017-01-01 12:14 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 kbuild test robot 1 sibling, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add Receiver-Side Procedures for the Add Outgoing Streams Request Parameter described in section 5.2.5. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 4 ++++ net/sctp/stream.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index e1b2509..5624b52 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -293,6 +293,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/stream.c b/net/sctp/stream.c index fce4317..b51a037 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -283,3 +283,59 @@ struct sctp_chunk *sctp_process_strreset_tsnreq( return sctp_make_strreset_tsnresp(asoc, result, request_seq, asoc->next_tsn, initial_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; + __u32 result = SCTP_STRRESET_DENIED; + __u32 request_seq; + __u16 nums; + + 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; + } + + nums = ntohs(addstrm->number_of_streams); + if (!nums || nums + asoc->streamincnt > SCTP_MAX_STREAM) + goto out; + + nums = nums + asoc->streamincnt; + if (ksize(asoc->streamin) / sizeof(*asoc->streamin) < nums) { + struct sctp_stream_in *streamin; + + streamin = kcalloc(nums, sizeof(*streamin), GFP_ATOMIC); + if (!streamin) + goto out; + + memcpy(streamin, asoc->streamin, + sizeof(*streamin) * asoc->streamincnt); + + kfree(asoc->streamin); + asoc->streamin = streamin; + } + + asoc->streamincnt = nums; + + 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] 37+ messages in thread
* [PATCH net-next 24/27] sctp: add rfc6525 section 5.2.6 2017-01-01 11:20 ` [PATCH net-next 23/27] sctp: add rfc6525 section 5.2.5 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 25/27] sctp: add rfc6525 section 5.2.7 Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement Receiver-Side Procedures for the Add Incoming Streams Request Parameter described in section 5.2.6. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 4 ++++ net/sctp/stream.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 5624b52..b8ca767 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -297,6 +297,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/stream.c b/net/sctp/stream.c index b51a037..a2b248b 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -339,3 +339,62 @@ 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; + __u32 result = SCTP_STRRESET_DENIED; + __u32 request_seq; + __u16 i, nums; + + 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; + } + + nums = ntohs(addstrm->number_of_streams); + if (!nums || nums + asoc->streamoutcnt > SCTP_MAX_STREAM) + goto out; + + nums = nums + asoc->streamoutcnt; + if (ksize(asoc->streamout) / sizeof(*asoc->streamout) < nums) { + struct sctp_stream_out *streamout; + + streamout = kcalloc(nums, sizeof(*streamout), GFP_ATOMIC); + if (!streamout) + goto out; + + memcpy(streamout, asoc->streamout, + sizeof(*streamout) * asoc->streamoutcnt); + + kfree(asoc->streamout); + asoc->streamout = streamout; + } + + for (i = asoc->streamoutcnt; i < nums; i++) + asoc->streamout[i].state = SCTP_STREAM_OPEN; + + asoc->streamoutcnt = nums; + + result = SCTP_STRRESET_PERFORMED; + + *evp = sctp_ulpevent_make_stream_change_event(asoc, + 0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC); + +out: + return sctp_make_strreset_resp(asoc, result, request_seq); +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH net-next 25/27] sctp: add rfc6525 section 5.2.7 2017-01-01 11:20 ` [PATCH net-next 24/27] sctp: add rfc6525 section 5.2.6 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 26/27] sctp: add sctp reconf chunk process Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to implement Receiver-Side Procedures for the Re-configuration Response Parameter in 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/stream.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index b8ca767..7c2f956 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -301,6 +301,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/stream.c b/net/sctp/stream.c index a2b248b..ae64de2 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -398,3 +398,166 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in( out: return sctp_make_strreset_resp(asoc, result, request_seq); } + +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_strreset_req *req; + struct sctp_transport *t; + __u16 i, nums, flags = 0; + __u32 result; + + req = sctp_chunk_lookup_strreset_param( + asoc, ntohl(resp->response_seq)); + 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->param_hdr.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 (nums) { + str_p = outreq->list_of_streams; + for (i = 0; i < nums; i++) + str_p[i] = ntohs(str_p[i]); + } + + if (result == SCTP_STRRESET_PERFORMED) { + if (nums) { + str_p = outreq->list_of_streams; + for (i = 0; i < nums; i++, str_p++) + asoc->streamout[*str_p].ssn = 0; + } else { + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[i].ssn = 0; + } + + flags = SCTP_STREAM_RESET_OUTGOING_SSN; + } + + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[i].state = SCTP_STREAM_OPEN; + + *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, + nums, str_p, GFP_ATOMIC); + } else if (req->param_hdr.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; + + if (nums) { + str_p = inreq->list_of_streams; + for (i = 0; i < nums; i++) + str_p[i] = ntohs(str_p[i]); + } + + str_p = inreq->list_of_streams; + *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, + nums, str_p, GFP_ATOMIC); + } else if (req->param_hdr.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 < asoc->streamoutcnt; i++) + asoc->streamout[i].ssn = 0; + for (i = 0; i < asoc->streamincnt; i++) + asoc->streamin[i].ssn = 0; + } + + for (i = 0; i < asoc->streamoutcnt; i++) + asoc->streamout[i].state = SCTP_STREAM_OPEN; + + *evp = sctp_ulpevent_make_assoc_reset_event(asoc, flags, + stsn, rtsn, GFP_ATOMIC); + } else if (req->param_hdr.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 = asoc->streamoutcnt - nums; + + if (result == SCTP_STRRESET_PERFORMED) + for (i = number; i < asoc->streamoutcnt; i++) + asoc->streamout[i].state = SCTP_STREAM_OPEN; + else + asoc->streamoutcnt = number; + + *evp = sctp_ulpevent_make_stream_change_event(asoc, flags, + 0, nums, GFP_ATOMIC); + } else if (req->param_hdr.type == SCTP_PARAM_RESET_ADD_IN_STREAMS) { + struct sctp_strreset_addstrm *addstrm; + + addstrm = (struct sctp_strreset_addstrm *)req; + nums = ntohs(addstrm->number_of_streams); + + if (result != SCTP_STRRESET_PERFORMED) + asoc->streamincnt = asoc->streamincnt - nums; + + *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] 37+ messages in thread
* [PATCH net-next 26/27] sctp: add sctp reconf chunk process 2017-01-01 11:20 ` [PATCH net-next 25/27] sctp: add rfc6525 section 5.2.7 Xin Long @ 2017-01-01 11:20 ` Xin Long 2017-01-01 11:20 ` [PATCH net-next 27/27] sctp: add reconf chunk event Xin Long 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, 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. Note that to support multi-params in response chunk, it also adds a function sctp_merge_reconf_chunk to merge two reconf chunk into one. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 8 +++++ net/sctp/sm_make_chunk.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ net/sctp/sm_statefuns.c | 68 +++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 7c2f956..17984eb 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; @@ -277,6 +278,13 @@ struct sctp_chunk *sctp_make_strreset_tsnresp( struct sctp_chunk *sctp_make_strreset_addstrm( const struct sctp_association *asoc, __u16 out, __u16 in); +struct sctp_chunk *sctp_merge_reconf_chunk( + struct sctp_association *asoc, + struct sctp_chunk *last, + struct sctp_chunk *reply); +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 f1efba6..74c3fee 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3819,3 +3819,97 @@ struct sctp_chunk *sctp_make_strreset_addstrm( return retval; } + +struct sctp_chunk *sctp_merge_reconf_chunk( + struct sctp_association *asoc, + struct sctp_chunk *last, + struct sctp_chunk *reply) +{ + struct sctp_chunk *retval = NULL; + __u16 lsize, rsize; + + if (!reply) + return last; + + rsize = ntohs(reply->param_hdr.p->length); + lsize = ntohs(last->param_hdr.p->length); + + retval = sctp_make_reconf(asoc, lsize + rsize); + if (!retval) + goto out; + + sctp_addto_chunk(retval, lsize, last->param_hdr.v); + sctp_addto_chunk(retval, rsize, reply->param_hdr.v); + +out: + if (asoc->strreset_chunk) { + sctp_chunk_put(asoc->strreset_chunk); + asoc->strreset_chunk = retval; + if (asoc->strreset_chunk) + sctp_chunk_hold(asoc->strreset_chunk); + } + + sctp_chunk_free(reply); + sctp_chunk_free(last); + + 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; +} diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index c06b134..4b05bd5 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -3834,6 +3834,74 @@ 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 *reply = NULL; + struct sctp_chunk *last = 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_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); + 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); + else if (param.p->type == SCTP_PARAM_RESET_ADD_IN_STREAMS) + reply = sctp_process_strreset_addstrm_in( + (struct sctp_association *)asoc, param, &ev); + 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, + SCTP_ULPEVENT(ev)); + + if (last) + reply = sctp_merge_reconf_chunk( + (struct sctp_association *)asoc, last, reply); + last = reply; + } + + 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] 37+ messages in thread
* [PATCH net-next 27/27] sctp: add reconf chunk event 2017-01-01 11:20 ` [PATCH net-next 26/27] sctp: add sctp reconf chunk process Xin Long @ 2017-01-01 11:20 ` Xin Long 0 siblings, 0 replies; 37+ messages in thread From: Xin Long @ 2017-01-01 11:20 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem This patch is to add reconf chunk event based on the sctp event frame, after which, the reconf chunk process would be activated. 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] 37+ messages in thread
* Re: [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 2017-01-01 11:20 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 Xin Long 2017-01-01 11:20 ` [PATCH net-next 23/27] sctp: add rfc6525 section 5.2.5 Xin Long @ 2017-01-01 12:14 ` kbuild test robot 2017-01-01 13:26 ` Xin Long 1 sibling, 1 reply; 37+ messages in thread From: kbuild test robot @ 2017-01-01 12:14 UTC (permalink / raw) To: Xin Long Cc: kbuild-all, network dev, linux-sctp, Marcelo Ricardo Leitner, Neil Horman, davem [-- Attachment #1: Type: text/plain, Size: 7074 bytes --] Hi Xin, [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/Xin-Long/sctp-implement-rfc6525-sctp-stream-reconf/20170101-192844 config: x86_64-randconfig-x015-201701 (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 Note: it may well be a FALSE warning. FWIW you are at least aware of it now. http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings All warnings (new ones prefixed by >>): net/sctp/stream.c: In function 'sctp_process_strreset_outreq': net/sctp/stream.c:140:9: warning: 'str_p' may be used uninitialized in this function [-Wmaybe-uninitialized] *evp = sctp_ulpevent_make_stream_reset_event(asoc, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GFP_ATOMIC); ~~~~~~~~~~~ net/sctp/stream.c: In function 'sctp_process_strreset_tsnreq': >> net/sctp/stream.c:283:9: warning: 'initial_tsn' may be used uninitialized in this function [-Wmaybe-uninitialized] return sctp_make_strreset_tsnresp(asoc, result, request_seq, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ asoc->next_tsn, initial_tsn); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vim +/initial_tsn +283 net/sctp/stream.c 134 for (i = 0; i < asoc->streamincnt; i++) 135 asoc->streamin[i].ssn = 0; 136 } 137 138 result = SCTP_STRRESET_PERFORMED; 139 > 140 *evp = sctp_ulpevent_make_stream_reset_event(asoc, 141 flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, 142 GFP_ATOMIC); 143 144 out: 145 return sctp_make_strreset_resp(asoc, result, request_seq); 146 } 147 148 struct sctp_chunk *sctp_process_strreset_inreq( 149 struct sctp_association *asoc, 150 union sctp_params param, 151 struct sctp_ulpevent **evp) 152 { 153 struct sctp_strreset_inreq *inreq = param.v; 154 __u32 result = SCTP_STRRESET_DENIED; 155 struct sctp_chunk *chunk = NULL; 156 __u16 i, nums, *str_p; 157 __u32 request_seq; 158 159 request_seq = ntohl(inreq->request_seq); 160 if (request_seq > asoc->strreset_inseq) { 161 result = SCTP_STRRESET_ERR_BAD_SEQNO; 162 goto out; 163 } else if (request_seq == asoc->strreset_inseq) { 164 asoc->strreset_inseq++; 165 } 166 167 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) 168 goto out; 169 170 if (asoc->strreset_outstanding) { 171 result = SCTP_STRRESET_ERR_IN_PROGRESS; 172 goto out; 173 } 174 175 nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2; 176 str_p = inreq->list_of_streams; 177 for (i = 0; i < nums; i++) { 178 str_p[i] = ntohs(str_p[i]); 179 if (str_p[i] >= asoc->streamoutcnt) { 180 result = SCTP_STRRESET_ERR_WRONG_SSN; 181 goto out; 182 } 183 } 184 185 chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); 186 if (!chunk) 187 goto out; 188 189 if (nums) 190 for (i = 0; i < nums; i++) 191 asoc->streamout[str_p[i]].state = 192 SCTP_STREAM_CLOSED; 193 else 194 for (i = 0; i < asoc->streamoutcnt; i++) 195 asoc->streamout[i].state = SCTP_STREAM_CLOSED; 196 197 asoc->strreset_chunk = chunk; 198 asoc->strreset_outstanding = 1; 199 sctp_chunk_hold(asoc->strreset_chunk); 200 201 *evp = sctp_ulpevent_make_stream_reset_event(asoc, 202 SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC); 203 204 out: 205 if (!chunk) 206 chunk = sctp_make_strreset_resp(asoc, result, request_seq); 207 208 return chunk; 209 } 210 211 struct sctp_chunk *sctp_process_strreset_tsnreq( 212 struct sctp_association *asoc, 213 union sctp_params param, 214 struct sctp_ulpevent **evp) 215 { 216 struct sctp_strreset_tsnreq *tsnreq = param.v; 217 __u32 request_seq, initial_tsn, max_tsn_seen; 218 __u32 result = SCTP_STRRESET_DENIED; 219 __u16 i; 220 221 request_seq = ntohl(tsnreq->request_seq); 222 if (request_seq > asoc->strreset_inseq) { 223 result = SCTP_STRRESET_ERR_BAD_SEQNO; 224 goto out; 225 } else if (request_seq == asoc->strreset_inseq) { 226 asoc->strreset_inseq++; 227 } 228 229 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) 230 goto out; 231 232 if (asoc->strreset_outstanding) { 233 result = SCTP_STRRESET_ERR_IN_PROGRESS; 234 goto out; 235 } 236 237 /* G3: The same processing as though a SACK chunk with no gap report 238 * and a cumulative TSN ACK of the Sender's Next TSN minus 1 were 239 * received MUST be performed. 240 */ 241 max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map); 242 sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen); 243 sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); 244 245 /* G1: Compute an appropriate value for the Receiver's Next TSN -- the 246 * TSN that the peer should use to send the next DATA chunk. The 247 * value SHOULD be the smallest TSN not acknowledged by the 248 * receiver of the request plus 2^31. 249 */ 250 initial_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31); 251 sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, 252 initial_tsn, GFP_ATOMIC); 253 254 /* G4: The same processing as though a FWD-TSN chunk (as defined in 255 * [RFC3758]) with all streams affected and a new cumulative TSN 256 * ACK of the Receiver's Next TSN minus 1 were received MUST be 257 * performed. 258 */ 259 sctp_outq_free(&asoc->outqueue); 260 261 /* G2: Compute an appropriate value for the local endpoint's next TSN, 262 * i.e., the next TSN assigned by the receiver of the SSN/TSN reset 263 * chunk. The value SHOULD be the highest TSN sent by the receiver 264 * of the request plus 1. 265 */ 266 asoc->ctsn_ack_point = asoc->next_tsn - 1; 267 asoc->adv_peer_ack_point = asoc->ctsn_ack_point; 268 269 /* G5: The next expected and outgoing SSNs MUST be reset to 0 for all 270 * incoming and outgoing streams. 271 */ 272 for (i = 0; i < asoc->streamoutcnt; i++) 273 asoc->streamout[i].ssn = 0; 274 for (i = 0; i < asoc->streamincnt; i++) 275 asoc->streamin[i].ssn = 0; 276 277 result = SCTP_STRRESET_PERFORMED; 278 279 *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 280 0, initial_tsn, asoc->next_tsn, GFP_ATOMIC); 281 282 out: > 283 return sctp_make_strreset_tsnresp(asoc, result, request_seq, 284 asoc->next_tsn, initial_tsn); 285 } --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 25803 bytes --] ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 2017-01-01 12:14 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 kbuild test robot @ 2017-01-01 13:26 ` Xin Long 2017-01-01 16:32 ` David Miller 0 siblings, 1 reply; 37+ messages in thread From: Xin Long @ 2017-01-01 13:26 UTC (permalink / raw) To: kbuild test robot Cc: kbuild-all, network dev, linux-sctp, Marcelo Ricardo Leitner, Neil Horman, davem On Sun, Jan 1, 2017 at 8:14 PM, kbuild test robot <lkp@intel.com> wrote: > Hi Xin, > > [auto build test WARNING on net-next/master] > > url: https://github.com/0day-ci/linux/commits/Xin-Long/sctp-implement-rfc6525-sctp-stream-reconf/20170101-192844 > config: x86_64-randconfig-x015-201701 (attached as .config) > compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 > reproduce: > # save the attached .config to linux build tree > make ARCH=x86_64 > > Note: it may well be a FALSE warning. FWIW you are at least aware of it now. > http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings > > All warnings (new ones prefixed by >>): > > net/sctp/stream.c: In function 'sctp_process_strreset_outreq': > net/sctp/stream.c:140:9: warning: 'str_p' may be used uninitialized in this function [-Wmaybe-uninitialized] > *evp = sctp_ulpevent_make_stream_reset_event(asoc, > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > GFP_ATOMIC); > ~~~~~~~~~~~ > net/sctp/stream.c: In function 'sctp_process_strreset_tsnreq': >>> net/sctp/stream.c:283:9: warning: 'initial_tsn' may be used uninitialized in this function [-Wmaybe-uninitialized] > return sctp_make_strreset_tsnresp(asoc, result, request_seq, > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > asoc->next_tsn, initial_tsn); > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As only when the result is not performed, initial_tsn variables is uninitialized, peer side would ignore this value, so here is also safe. > > vim +/initial_tsn +283 net/sctp/stream.c > > 134 for (i = 0; i < asoc->streamincnt; i++) > 135 asoc->streamin[i].ssn = 0; > 136 } > 137 > 138 result = SCTP_STRRESET_PERFORMED; > 139 > > 140 *evp = sctp_ulpevent_make_stream_reset_event(asoc, > 141 flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, > 142 GFP_ATOMIC); > 143 > 144 out: > 145 return sctp_make_strreset_resp(asoc, result, request_seq); > 146 } > 147 > 148 struct sctp_chunk *sctp_process_strreset_inreq( > 149 struct sctp_association *asoc, > 150 union sctp_params param, > 151 struct sctp_ulpevent **evp) > 152 { > 153 struct sctp_strreset_inreq *inreq = param.v; > 154 __u32 result = SCTP_STRRESET_DENIED; > 155 struct sctp_chunk *chunk = NULL; > 156 __u16 i, nums, *str_p; > 157 __u32 request_seq; > 158 > 159 request_seq = ntohl(inreq->request_seq); > 160 if (request_seq > asoc->strreset_inseq) { > 161 result = SCTP_STRRESET_ERR_BAD_SEQNO; > 162 goto out; > 163 } else if (request_seq == asoc->strreset_inseq) { > 164 asoc->strreset_inseq++; > 165 } > 166 > 167 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) > 168 goto out; > 169 > 170 if (asoc->strreset_outstanding) { > 171 result = SCTP_STRRESET_ERR_IN_PROGRESS; > 172 goto out; > 173 } > 174 > 175 nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2; > 176 str_p = inreq->list_of_streams; > 177 for (i = 0; i < nums; i++) { > 178 str_p[i] = ntohs(str_p[i]); > 179 if (str_p[i] >= asoc->streamoutcnt) { > 180 result = SCTP_STRRESET_ERR_WRONG_SSN; > 181 goto out; > 182 } > 183 } > 184 > 185 chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); > 186 if (!chunk) > 187 goto out; > 188 > 189 if (nums) > 190 for (i = 0; i < nums; i++) > 191 asoc->streamout[str_p[i]].state = > 192 SCTP_STREAM_CLOSED; > 193 else > 194 for (i = 0; i < asoc->streamoutcnt; i++) > 195 asoc->streamout[i].state = SCTP_STREAM_CLOSED; > 196 > 197 asoc->strreset_chunk = chunk; > 198 asoc->strreset_outstanding = 1; > 199 sctp_chunk_hold(asoc->strreset_chunk); > 200 > 201 *evp = sctp_ulpevent_make_stream_reset_event(asoc, > 202 SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC); > 203 > 204 out: > 205 if (!chunk) > 206 chunk = sctp_make_strreset_resp(asoc, result, request_seq); > 207 > 208 return chunk; > 209 } > 210 > 211 struct sctp_chunk *sctp_process_strreset_tsnreq( > 212 struct sctp_association *asoc, > 213 union sctp_params param, > 214 struct sctp_ulpevent **evp) > 215 { > 216 struct sctp_strreset_tsnreq *tsnreq = param.v; > 217 __u32 request_seq, initial_tsn, max_tsn_seen; > 218 __u32 result = SCTP_STRRESET_DENIED; > 219 __u16 i; > 220 > 221 request_seq = ntohl(tsnreq->request_seq); > 222 if (request_seq > asoc->strreset_inseq) { > 223 result = SCTP_STRRESET_ERR_BAD_SEQNO; > 224 goto out; > 225 } else if (request_seq == asoc->strreset_inseq) { > 226 asoc->strreset_inseq++; > 227 } > 228 > 229 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) > 230 goto out; > 231 > 232 if (asoc->strreset_outstanding) { > 233 result = SCTP_STRRESET_ERR_IN_PROGRESS; > 234 goto out; > 235 } > 236 > 237 /* G3: The same processing as though a SACK chunk with no gap report > 238 * and a cumulative TSN ACK of the Sender's Next TSN minus 1 were > 239 * received MUST be performed. > 240 */ > 241 max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map); > 242 sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen); > 243 sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); > 244 > 245 /* G1: Compute an appropriate value for the Receiver's Next TSN -- the > 246 * TSN that the peer should use to send the next DATA chunk. The > 247 * value SHOULD be the smallest TSN not acknowledged by the > 248 * receiver of the request plus 2^31. > 249 */ > 250 initial_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31); > 251 sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, > 252 initial_tsn, GFP_ATOMIC); > 253 > 254 /* G4: The same processing as though a FWD-TSN chunk (as defined in > 255 * [RFC3758]) with all streams affected and a new cumulative TSN > 256 * ACK of the Receiver's Next TSN minus 1 were received MUST be > 257 * performed. > 258 */ > 259 sctp_outq_free(&asoc->outqueue); > 260 > 261 /* G2: Compute an appropriate value for the local endpoint's next TSN, > 262 * i.e., the next TSN assigned by the receiver of the SSN/TSN reset > 263 * chunk. The value SHOULD be the highest TSN sent by the receiver > 264 * of the request plus 1. > 265 */ > 266 asoc->ctsn_ack_point = asoc->next_tsn - 1; > 267 asoc->adv_peer_ack_point = asoc->ctsn_ack_point; > 268 > 269 /* G5: The next expected and outgoing SSNs MUST be reset to 0 for all > 270 * incoming and outgoing streams. > 271 */ > 272 for (i = 0; i < asoc->streamoutcnt; i++) > 273 asoc->streamout[i].ssn = 0; > 274 for (i = 0; i < asoc->streamincnt; i++) > 275 asoc->streamin[i].ssn = 0; > 276 > 277 result = SCTP_STRRESET_PERFORMED; > 278 > 279 *evp = sctp_ulpevent_make_assoc_reset_event(asoc, > 280 0, initial_tsn, asoc->next_tsn, GFP_ATOMIC); > 281 > 282 out: > > 283 return sctp_make_strreset_tsnresp(asoc, result, request_seq, > 284 asoc->next_tsn, initial_tsn); > 285 } > > --- > 0-DAY kernel test infrastructure Open Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 2017-01-01 13:26 ` Xin Long @ 2017-01-01 16:32 ` David Miller 2017-01-02 13:43 ` Xin Long 0 siblings, 1 reply; 37+ messages in thread From: David Miller @ 2017-01-01 16:32 UTC (permalink / raw) To: lucien.xin; +Cc: lkp, kbuild-all, netdev, linux-sctp, marcelo.leitner, nhorman From: Xin Long <lucien.xin@gmail.com> Date: Sun, 1 Jan 2017 21:26:47 +0800 > As only when the result is not performed, initial_tsn variables is > uninitialized, peer side would ignore this value, so here is also > safe. It doesn't matter if it is "safe" or not, you must fix all of the warnings reported by kbuild before your patches will be considered for applying. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 2017-01-01 16:32 ` David Miller @ 2017-01-02 13:43 ` Xin Long 0 siblings, 0 replies; 37+ messages in thread From: Xin Long @ 2017-01-02 13:43 UTC (permalink / raw) To: David Miller Cc: kbuild test robot, kbuild-all, network dev, linux-sctp, Marcelo Ricardo Leitner, Neil Horman On Mon, Jan 2, 2017 at 12:32 AM, David Miller <davem@davemloft.net> wrote: > From: Xin Long <lucien.xin@gmail.com> > Date: Sun, 1 Jan 2017 21:26:47 +0800 > >> As only when the result is not performed, initial_tsn variables is >> uninitialized, peer side would ignore this value, so here is also >> safe. > > It doesn't matter if it is "safe" or not, you must fix all of the > warnings reported by kbuild before your patches will be considered > for applying. will fix it in next post. thanks ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 2017-01-01 11:20 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 Xin Long 2017-01-01 11:20 ` [PATCH net-next 21/27] sctp: add rfc6525 section 5.2.3 Xin Long @ 2017-01-01 12:02 ` kbuild test robot 2017-01-01 13:23 ` Xin Long 1 sibling, 1 reply; 37+ messages in thread From: kbuild test robot @ 2017-01-01 12:02 UTC (permalink / raw) To: Xin Long Cc: kbuild-all, network dev, linux-sctp, Marcelo Ricardo Leitner, Neil Horman, davem [-- Attachment #1: Type: text/plain, Size: 1876 bytes --] Hi Xin, [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/Xin-Long/sctp-implement-rfc6525-sctp-stream-reconf/20170101-192844 config: x86_64-randconfig-x015-201701 (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 Note: it may well be a FALSE warning. FWIW you are at least aware of it now. http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings All warnings (new ones prefixed by >>): net/sctp/stream.c: In function 'sctp_process_strreset_outreq': >> net/sctp/stream.c:140:9: warning: 'str_p' may be used uninitialized in this function [-Wmaybe-uninitialized] *evp = sctp_ulpevent_make_stream_reset_event(asoc, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GFP_ATOMIC); ~~~~~~~~~~~ vim +/str_p +140 net/sctp/stream.c 124 if (str_p[i] >= asoc->streamincnt) { 125 result = SCTP_STRRESET_ERR_WRONG_SSN; 126 goto out; 127 } 128 } 129 130 str_p = outreq->list_of_streams; 131 for (i = 0; i < nums; i++, str_p++) 132 asoc->streamin[*str_p].ssn = 0; 133 } else { 134 for (i = 0; i < asoc->streamincnt; i++) 135 asoc->streamin[i].ssn = 0; 136 } 137 138 result = SCTP_STRRESET_PERFORMED; 139 > 140 *evp = sctp_ulpevent_make_stream_reset_event(asoc, 141 flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, 142 GFP_ATOMIC); 143 144 out: 145 return sctp_make_strreset_resp(asoc, result, request_seq); 146 } --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 25803 bytes --] ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 2017-01-01 12:02 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 kbuild test robot @ 2017-01-01 13:23 ` Xin Long 0 siblings, 0 replies; 37+ messages in thread From: Xin Long @ 2017-01-01 13:23 UTC (permalink / raw) To: kbuild test robot Cc: kbuild-all, network dev, linux-sctp, Marcelo Ricardo Leitner, Neil Horman, davem On Sun, Jan 1, 2017 at 8:02 PM, kbuild test robot <lkp@intel.com> wrote: > Hi Xin, > > [auto build test WARNING on net-next/master] > > url: https://github.com/0day-ci/linux/commits/Xin-Long/sctp-implement-rfc6525-sctp-stream-reconf/20170101-192844 > config: x86_64-randconfig-x015-201701 (attached as .config) > compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 > reproduce: > # save the attached .config to linux build tree > make ARCH=x86_64 > > Note: it may well be a FALSE warning. FWIW you are at least aware of it now. > http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings > > All warnings (new ones prefixed by >>): > > net/sctp/stream.c: In function 'sctp_process_strreset_outreq': >>> net/sctp/stream.c:140:9: warning: 'str_p' may be used uninitialized in this function [-Wmaybe-uninitialized] > *evp = sctp_ulpevent_make_stream_reset_event(asoc, > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > GFP_ATOMIC); > ~~~~~~~~~~~ > This warning is actually safe, as only when nums is NULL, str_p is uninitialized, and in sctp_ulpevent_make_stream_reset_event(), if nums is null, str_p wouldn't be really used. > vim +/str_p +140 net/sctp/stream.c > > 124 if (str_p[i] >= asoc->streamincnt) { > 125 result = SCTP_STRRESET_ERR_WRONG_SSN; > 126 goto out; > 127 } > 128 } > 129 > 130 str_p = outreq->list_of_streams; > 131 for (i = 0; i < nums; i++, str_p++) > 132 asoc->streamin[*str_p].ssn = 0; > 133 } else { > 134 for (i = 0; i < asoc->streamincnt; i++) > 135 asoc->streamin[i].ssn = 0; > 136 } > 137 > 138 result = SCTP_STRRESET_PERFORMED; > 139 > > 140 *evp = sctp_ulpevent_make_stream_reset_event(asoc, > 141 flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, > 142 GFP_ATOMIC); > 143 > 144 out: > 145 return sctp_make_strreset_resp(asoc, result, request_seq); > 146 } > > --- > 0-DAY kernel test infrastructure Open Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf 2017-01-01 11:20 [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf Xin Long 2017-01-01 11:20 ` [PATCH net-next 01/27] sctp: add stream arrays in asoc Xin Long @ 2017-01-01 11:32 ` Xin Long 2017-01-01 16:30 ` David Miller 2 siblings, 0 replies; 37+ messages in thread From: Xin Long @ 2017-01-01 11:32 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem [-- Attachment #1: Type: text/plain, Size: 3101 bytes --] On Sun, Jan 1, 2017 at 7:20 PM, Xin Long <lucien.xin@gmail.com> wrote: > This patchset is to implement sctp stream reconf described in rfc6525. > > Patch 1-3 add per stream information in sctp asoc. > Patch 4-8 make the chunk with different reconf params. (Section 3-4) > Patch 9-12 add reconf timer, primitive and enable option. > Patch 13-25 implement the procedures on both sender and receiver sides (Section 5) > add sockopts and event for users (Section 6) > Patch 26-27 add reconf event, activate the sctp stream reconf process. > Attachments are the scripts I used to do tests for this patchset. including the scripts on bsd side when doing some interactivity tests with bsd. > Xin Long (27): > sctp: add stream arrays in asoc > sctp: replace ssnmap with asoc stream arrays > sctp: remove asoc ssnmap and ssnmap.c > sctp: add rfc6525 section 3.1 > sctp: add rfc6525 section 4.1-4.2 > sctp: add rfc6525 section 4.3 > sctp: add rfc6525 section 4.4 > sctp: add rfc6525 section 4.5-4.6 > sctp: add stream reconf timer > sctp: add stream reconf primitive > sctp: add reconf_enable in asoc ep and netns > sctp: add get and set sockopt for reconf_enable > sctp: add rfc6525 section 6.3.1 > sctp: add rfc6525 section 5.1.2-5.1.3 and 6.3.2 > sctp: add rfc6525 section 5.1.4 and 6.3.3 > sctp: add rfc6525 section 5.1.5-5.1.6 and 6.3.4 > sctp: add rfc6525 section 6.1.1 > sctp: add rfc6525 section 6.1.2 > sctp: add rfc6525 section 6.1.3 > sctp: add rfc6525 section 5.2.2 > sctp: add rfc6525 section 5.2.3 > sctp: add rfc6525 section 5.2.4 > sctp: add rfc6525 section 5.2.5 > sctp: add rfc6525 section 5.2.6 > sctp: add rfc6525 section 5.2.7 > sctp: add sctp reconf chunk process > sctp: add reconf chunk event > > include/linux/sctp.h | 68 ++++++ > include/net/netns/sctp.h | 3 + > include/net/sctp/constants.h | 7 +- > include/net/sctp/sctp.h | 3 +- > include/net/sctp/sm.h | 54 ++++- > include/net/sctp/structs.h | 91 ++++--- > include/net/sctp/ulpevent.h | 12 + > include/uapi/linux/sctp.h | 93 ++++++- > net/sctp/Makefile | 4 +- > net/sctp/associola.c | 29 ++- > net/sctp/endpointola.c | 1 + > net/sctp/objcnt.c | 2 - > net/sctp/outqueue.c | 33 ++- > net/sctp/primitive.c | 3 + > net/sctp/sm_make_chunk.c | 403 ++++++++++++++++++++++++++++++- > net/sctp/sm_sideeffect.c | 32 +++ > net/sctp/sm_statefuns.c | 112 ++++++++- > net/sctp/sm_statetable.c | 70 ++++++ > net/sctp/socket.c | 433 +++++++++++++++++++++++++++++++++ > net/sctp/ssnmap.c | 125 ---------- > net/sctp/stream.c | 563 +++++++++++++++++++++++++++++++++++++++++++ > net/sctp/sysctl.c | 7 + > net/sctp/transport.c | 17 +- > net/sctp/ulpevent.c | 86 +++++++ > net/sctp/ulpqueue.c | 33 +-- > 25 files changed, 2043 insertions(+), 241 deletions(-) > delete mode 100644 net/sctp/ssnmap.c > create mode 100644 net/sctp/stream.c > > -- > 2.1.0 > [-- 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] 37+ messages in thread
* Re: [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf 2017-01-01 11:20 [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf Xin Long 2017-01-01 11:20 ` [PATCH net-next 01/27] sctp: add stream arrays in asoc Xin Long 2017-01-01 11:32 ` [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf Xin Long @ 2017-01-01 16:30 ` David Miller 2017-01-02 13:42 ` Xin Long 2 siblings, 1 reply; 37+ messages in thread From: David Miller @ 2017-01-01 16:30 UTC (permalink / raw) To: lucien.xin; +Cc: netdev, linux-sctp, marcelo.leitner, nhorman I'm sorry but this is way too many patches to submit at one time. Split your series into smaller, more reasonably sized, groups of changes. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf 2017-01-01 16:30 ` David Miller @ 2017-01-02 13:42 ` Xin Long 0 siblings, 0 replies; 37+ messages in thread From: Xin Long @ 2017-01-02 13:42 UTC (permalink / raw) To: David Miller Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, Neil Horman On Mon, Jan 2, 2017 at 12:30 AM, David Miller <davem@davemloft.net> wrote: > > I'm sorry but this is way too many patches to submit at one time. > > Split your series into smaller, more reasonably sized, groups > of changes. okay, will split and repost ^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2017-01-02 13:43 UTC | newest] Thread overview: 37+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-01-01 11:20 [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf Xin Long 2017-01-01 11:20 ` [PATCH net-next 01/27] sctp: add stream arrays in asoc Xin Long 2017-01-01 11:20 ` [PATCH net-next 02/27] sctp: replace ssnmap with asoc stream arrays Xin Long 2017-01-01 11:20 ` [PATCH net-next 03/27] sctp: remove asoc ssnmap and ssnmap.c Xin Long 2017-01-01 11:20 ` [PATCH net-next 04/27] sctp: add rfc6525 section 3.1 Xin Long 2017-01-01 11:20 ` [PATCH net-next 05/27] sctp: add rfc6525 section 4.1-4.2 Xin Long 2017-01-01 11:20 ` [PATCH net-next 06/27] sctp: add rfc6525 section 4.3 Xin Long 2017-01-01 11:20 ` [PATCH net-next 07/27] sctp: add rfc6525 section 4.4 Xin Long 2017-01-01 11:20 ` [PATCH net-next 08/27] sctp: add rfc6525 section 4.5-4.6 Xin Long 2017-01-01 11:20 ` [PATCH net-next 09/27] sctp: add stream reconf timer Xin Long 2017-01-01 11:20 ` [PATCH net-next 10/27] sctp: add stream reconf primitive Xin Long 2017-01-01 11:20 ` [PATCH net-next 11/27] sctp: add reconf_enable in asoc ep and netns Xin Long 2017-01-01 11:20 ` [PATCH net-next 12/27] sctp: add get and set sockopt for reconf_enable Xin Long 2017-01-01 11:20 ` [PATCH net-next 13/27] sctp: add rfc6525 section 6.3.1 Xin Long 2017-01-01 11:20 ` [PATCH net-next 14/27] sctp: add rfc6525 section 5.1.2-5.1.3 and 6.3.2 Xin Long 2017-01-01 11:20 ` [PATCH net-next 15/27] sctp: add rfc6525 section 5.1.4 and 6.3.3 Xin Long 2017-01-01 11:20 ` [PATCH net-next 16/27] sctp: add rfc6525 section 5.1.5-5.1.6 and 6.3.4 Xin Long 2017-01-01 11:20 ` [PATCH net-next 17/27] sctp: add rfc6525 section 6.1.1 Xin Long 2017-01-01 11:20 ` [PATCH net-next 18/27] sctp: add rfc6525 section 6.1.2 Xin Long 2017-01-01 11:20 ` [PATCH net-next 19/27] sctp: add rfc6525 section 6.1.3 Xin Long 2017-01-01 11:20 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 Xin Long 2017-01-01 11:20 ` [PATCH net-next 21/27] sctp: add rfc6525 section 5.2.3 Xin Long 2017-01-01 11:20 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 Xin Long 2017-01-01 11:20 ` [PATCH net-next 23/27] sctp: add rfc6525 section 5.2.5 Xin Long 2017-01-01 11:20 ` [PATCH net-next 24/27] sctp: add rfc6525 section 5.2.6 Xin Long 2017-01-01 11:20 ` [PATCH net-next 25/27] sctp: add rfc6525 section 5.2.7 Xin Long 2017-01-01 11:20 ` [PATCH net-next 26/27] sctp: add sctp reconf chunk process Xin Long 2017-01-01 11:20 ` [PATCH net-next 27/27] sctp: add reconf chunk event Xin Long 2017-01-01 12:14 ` [PATCH net-next 22/27] sctp: add rfc6525 section 5.2.4 kbuild test robot 2017-01-01 13:26 ` Xin Long 2017-01-01 16:32 ` David Miller 2017-01-02 13:43 ` Xin Long 2017-01-01 12:02 ` [PATCH net-next 20/27] sctp: add rfc6525 section 5.2.2 kbuild test robot 2017-01-01 13:23 ` Xin Long 2017-01-01 11:32 ` [PATCH net-next 00/27] sctp: implement rfc6525 sctp stream reconf Xin Long 2017-01-01 16:30 ` David Miller 2017-01-02 13:42 ` Xin Long
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).