Skip to content

Commit 668c9be

Browse files
lxindavem330
authored andcommitted
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 <[email protected]> Acked-by: Marcelo Ricardo Leitner <[email protected]> Acked-by: Neil Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0c3f6f6 commit 668c9be

File tree

9 files changed

+83
-14
lines changed

9 files changed

+83
-14
lines changed

include/net/sctp/constants.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,13 @@ SCTP_SUBTYPE_CONSTRUCTOR(OTHER, enum sctp_event_other, other)
145145
SCTP_SUBTYPE_CONSTRUCTOR(PRIMITIVE, enum sctp_event_primitive, primitive)
146146

147147

148-
#define sctp_chunk_is_data(a) (a->chunk_hdr->type == SCTP_CID_DATA)
148+
#define sctp_chunk_is_data(a) (a->chunk_hdr->type == SCTP_CID_DATA || \
149+
a->chunk_hdr->type == SCTP_CID_I_DATA)
149150

150151
/* Calculate the actual data size in a data chunk */
151-
#define SCTP_DATA_SNDSIZE(c) ((int)((unsigned long)(c->chunk_end)\
152-
- (unsigned long)(c->chunk_hdr)\
153-
- sizeof(struct sctp_data_chunk)))
152+
#define SCTP_DATA_SNDSIZE(c) ((int)((unsigned long)(c->chunk_end) - \
153+
(unsigned long)(c->chunk_hdr) - \
154+
sctp_datachk_len(&c->asoc->stream)))
154155

155156
/* Internal error codes */
156157
enum sctp_ierror {

include/net/sctp/sctp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,13 +444,13 @@ static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
444444
int frag = pmtu;
445445

446446
frag -= sp->pf->af->net_header_len;
447-
frag -= sizeof(struct sctphdr) + sizeof(struct sctp_data_chunk);
447+
frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
448448

449449
if (asoc->user_frag)
450450
frag = min_t(int, frag, asoc->user_frag);
451451

452452
frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN -
453-
sizeof(struct sctp_data_chunk)));
453+
sctp_datachk_len(&asoc->stream)));
454454

455455
return frag;
456456
}

include/net/sctp/sm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
343343
__u16 size;
344344

345345
size = ntohs(chunk->chunk_hdr->length);
346-
size -= sizeof(struct sctp_data_chunk);
346+
size -= sctp_datahdr_len(&chunk->asoc->stream);
347347

348348
return size;
349349
}

include/net/sctp/stream_interleave.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct sctp_stream_interleave {
3737
struct sctp_chunk *(*make_datafrag)(const struct sctp_association *asoc,
3838
const struct sctp_sndrcvinfo *sinfo,
3939
int len, __u8 flags, gfp_t gfp);
40+
void (*assign_number)(struct sctp_chunk *chunk);
4041
};
4142

4243
void sctp_stream_interleave_init(struct sctp_stream *stream);

include/net/sctp/structs.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,18 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);
399399
#define sctp_ssn_skip(stream, type, sid, ssn) \
400400
((stream)->type[sid].ssn = ssn + 1)
401401

402+
/* What is the current MID number for this stream? */
403+
#define sctp_mid_peek(stream, type, sid) \
404+
((stream)->type[sid].mid)
405+
406+
/* Return the next MID number for this stream. */
407+
#define sctp_mid_next(stream, type, sid) \
408+
((stream)->type[sid].mid++)
409+
410+
/* Skip over this mid and all below. */
411+
#define sctp_mid_skip(stream, type, sid, mid) \
412+
((stream)->type[sid].mid = mid + 1)
413+
402414
/*
403415
* Pointers to address related SCTP functions.
404416
* (i.e. things that depend on the address family.)
@@ -623,6 +635,7 @@ struct sctp_chunk {
623635
__u16 rtt_in_progress:1, /* This chunk used for RTT calc? */
624636
has_tsn:1, /* Does this chunk have a TSN yet? */
625637
has_ssn:1, /* Does this chunk have a SSN yet? */
638+
#define has_mid has_ssn
626639
singleton:1, /* Only chunk in the packet? */
627640
end_of_packet:1, /* Last chunk in the packet? */
628641
ecn_ce_done:1, /* Have we processed the ECN CE bit? */
@@ -1360,7 +1373,10 @@ struct sctp_stream_out_ext {
13601373
};
13611374

13621375
struct sctp_stream_out {
1363-
__u16 ssn;
1376+
union {
1377+
__u32 mid;
1378+
__u16 ssn;
1379+
};
13641380
__u8 state;
13651381
struct sctp_stream_out_ext *ext;
13661382
};

net/sctp/output.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ static enum sctp_xmit __sctp_packet_append_chunk(struct sctp_packet *packet,
313313
/* We believe that this chunk is OK to add to the packet */
314314
switch (chunk->chunk_hdr->type) {
315315
case SCTP_CID_DATA:
316+
case SCTP_CID_I_DATA:
316317
/* Account for the data being in the packet */
317318
sctp_packet_append_data(packet, chunk);
318319
/* Disallow SACK bundling after DATA. */
@@ -724,7 +725,7 @@ static enum sctp_xmit sctp_packet_can_append_data(struct sctp_packet *packet,
724725
* or delay in hopes of bundling a full sized packet.
725726
*/
726727
if (chunk->skb->len + q->out_qlen > transport->pathmtu -
727-
packet->overhead - sizeof(struct sctp_data_chunk) - 4)
728+
packet->overhead - sctp_datachk_len(&chunk->asoc->stream) - 4)
728729
/* Enough data queued to fill a packet */
729730
return SCTP_XMIT_OK;
730731

@@ -759,7 +760,7 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
759760

760761
asoc->peer.rwnd = rwnd;
761762
sctp_chunk_assign_tsn(chunk);
762-
sctp_chunk_assign_ssn(chunk);
763+
asoc->stream.si->assign_number(chunk);
763764
}
764765

765766
static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,

net/sctp/socket.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,7 +2002,20 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
20022002
if (err < 0)
20032003
goto out_free;
20042004

2005-
wait_connect = true;
2005+
/* If stream interleave is enabled, wait_connect has to be
2006+
* done earlier than data enqueue, as it needs to make data
2007+
* or idata according to asoc->intl_enable which is set
2008+
* after connection is done.
2009+
*/
2010+
if (sctp_sk(asoc->base.sk)->strm_interleave) {
2011+
timeo = sock_sndtimeo(sk, 0);
2012+
err = sctp_wait_for_connect(asoc, &timeo);
2013+
if (err)
2014+
goto out_unlock;
2015+
} else {
2016+
wait_connect = true;
2017+
}
2018+
20062019
pr_debug("%s: we associated primitively\n", __func__);
20072020
}
20082021

@@ -3180,7 +3193,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
31803193
if (val == 0) {
31813194
val = asoc->pathmtu - sp->pf->af->net_header_len;
31823195
val -= sizeof(struct sctphdr) +
3183-
sizeof(struct sctp_data_chunk);
3196+
sctp_datachk_len(&asoc->stream);
31843197
}
31853198
asoc->user_frag = val;
31863199
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);

net/sctp/stream_interleave.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,53 @@ static struct sctp_chunk *sctp_make_idatafrag_empty(
5757
return retval;
5858
}
5959

60+
static void sctp_chunk_assign_mid(struct sctp_chunk *chunk)
61+
{
62+
struct sctp_stream *stream;
63+
struct sctp_chunk *lchunk;
64+
__u32 cfsn = 0;
65+
__u16 sid;
66+
67+
if (chunk->has_mid)
68+
return;
69+
70+
sid = sctp_chunk_stream_no(chunk);
71+
stream = &chunk->asoc->stream;
72+
73+
list_for_each_entry(lchunk, &chunk->msg->chunks, frag_list) {
74+
struct sctp_idatahdr *hdr;
75+
76+
lchunk->has_mid = 1;
77+
78+
if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
79+
continue;
80+
81+
hdr = lchunk->subh.idata_hdr;
82+
83+
if (lchunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG)
84+
hdr->ppid = lchunk->sinfo.sinfo_ppid;
85+
else
86+
hdr->fsn = htonl(cfsn++);
87+
88+
if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
89+
hdr->mid = htonl(sctp_mid_next(stream, out, sid));
90+
else
91+
hdr->mid = htonl(sctp_mid_peek(stream, out, sid));
92+
}
93+
}
94+
6095
static struct sctp_stream_interleave sctp_stream_interleave_0 = {
6196
.data_chunk_len = sizeof(struct sctp_data_chunk),
6297
/* DATA process functions */
6398
.make_datafrag = sctp_make_datafrag_empty,
99+
.assign_number = sctp_chunk_assign_ssn,
64100
};
65101

66102
static struct sctp_stream_interleave sctp_stream_interleave_1 = {
67103
.data_chunk_len = sizeof(struct sctp_idata_chunk),
68104
/* I-DATA process functions */
69105
.make_datafrag = sctp_make_idatafrag_empty,
106+
.assign_number = sctp_chunk_assign_mid,
70107
};
71108

72109
void sctp_stream_interleave_init(struct sctp_stream *stream)

net/sctp/ulpevent.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
443443
goto fail;
444444

445445
/* Pull off the common chunk header and DATA header. */
446-
skb_pull(skb, sizeof(struct sctp_data_chunk));
447-
len -= sizeof(struct sctp_data_chunk);
446+
skb_pull(skb, sctp_datachk_len(&asoc->stream));
447+
len -= sctp_datachk_len(&asoc->stream);
448448

449449
/* Embed the event fields inside the cloned skb. */
450450
event = sctp_skb2event(skb);

0 commit comments

Comments
 (0)