sctp: implement assign_number for sctp_stream_interleave
assign_number is added as a member of sctp_stream_interleave, used to assign ssn for data or mid (message id) for idata, called in sctp_packet_append_data. sctp_chunk_assign_ssn is left as it is, and sctp_chunk_assign_mid is added for sctp_stream_interleave_1. This procedure is described in section 2.2.2 of RFC8260. All sizeof(struct sctp_data_chunk) in tx path is replaced with sctp_datachk_len, to make it right for idata as well. And also adjust sctp_chunk_is_data for SCTP_CID_I_DATA. After this patch, idata can be built and sent in tx path. Note that if sp strm_interleave is set, it has to wait_connect in sctp_sendmsg, as asoc intl_enable need to be known after 4 shake- hands, to decide if it should use data or idata later. data and idata can't be mixed to send in one asoc. Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
0c3f6f6554
commit
668c9beb90
@@ -57,16 +57,53 @@ static struct sctp_chunk *sctp_make_idatafrag_empty(
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void sctp_chunk_assign_mid(struct sctp_chunk *chunk)
|
||||
{
|
||||
struct sctp_stream *stream;
|
||||
struct sctp_chunk *lchunk;
|
||||
__u32 cfsn = 0;
|
||||
__u16 sid;
|
||||
|
||||
if (chunk->has_mid)
|
||||
return;
|
||||
|
||||
sid = sctp_chunk_stream_no(chunk);
|
||||
stream = &chunk->asoc->stream;
|
||||
|
||||
list_for_each_entry(lchunk, &chunk->msg->chunks, frag_list) {
|
||||
struct sctp_idatahdr *hdr;
|
||||
|
||||
lchunk->has_mid = 1;
|
||||
|
||||
if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
|
||||
continue;
|
||||
|
||||
hdr = lchunk->subh.idata_hdr;
|
||||
|
||||
if (lchunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG)
|
||||
hdr->ppid = lchunk->sinfo.sinfo_ppid;
|
||||
else
|
||||
hdr->fsn = htonl(cfsn++);
|
||||
|
||||
if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
|
||||
hdr->mid = htonl(sctp_mid_next(stream, out, sid));
|
||||
else
|
||||
hdr->mid = htonl(sctp_mid_peek(stream, out, sid));
|
||||
}
|
||||
}
|
||||
|
||||
static struct sctp_stream_interleave sctp_stream_interleave_0 = {
|
||||
.data_chunk_len = sizeof(struct sctp_data_chunk),
|
||||
/* DATA process functions */
|
||||
.make_datafrag = sctp_make_datafrag_empty,
|
||||
.assign_number = sctp_chunk_assign_ssn,
|
||||
};
|
||||
|
||||
static struct sctp_stream_interleave sctp_stream_interleave_1 = {
|
||||
.data_chunk_len = sizeof(struct sctp_idata_chunk),
|
||||
/* I-DATA process functions */
|
||||
.make_datafrag = sctp_make_idatafrag_empty,
|
||||
.assign_number = sctp_chunk_assign_mid,
|
||||
};
|
||||
|
||||
void sctp_stream_interleave_init(struct sctp_stream *stream)
|
||||
|
||||
Reference in New Issue
Block a user