diff options
-rw-r--r-- | include/net/sctp/user.h | 1 | ||||
-rw-r--r-- | net/sctp/chunk.c | 15 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 7 |
3 files changed, 22 insertions, 1 deletions
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index be2334aaf52e..50b2431405f2 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
@@ -206,6 +206,7 @@ enum sctp_sinfo_flags { | |||
206 | SCTP_UNORDERED = 1, /* Send/receive message unordered. */ | 206 | SCTP_UNORDERED = 1, /* Send/receive message unordered. */ |
207 | SCTP_ADDR_OVER = 2, /* Override the primary destination. */ | 207 | SCTP_ADDR_OVER = 2, /* Override the primary destination. */ |
208 | SCTP_ABORT=4, /* Send an ABORT message to the peer. */ | 208 | SCTP_ABORT=4, /* Send an ABORT message to the peer. */ |
209 | SCTP_SACK_IMMEDIATELY = 8, /* SACK should be sent without delay */ | ||
209 | SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */ | 210 | SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */ |
210 | }; | 211 | }; |
211 | 212 | ||
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index acf7c4d128f7..8e4320040f05 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -263,9 +263,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
263 | if (0 == i) | 263 | if (0 == i) |
264 | frag |= SCTP_DATA_FIRST_FRAG; | 264 | frag |= SCTP_DATA_FIRST_FRAG; |
265 | 265 | ||
266 | if ((i == (whole - 1)) && !over) | 266 | if ((i == (whole - 1)) && !over) { |
267 | frag |= SCTP_DATA_LAST_FRAG; | 267 | frag |= SCTP_DATA_LAST_FRAG; |
268 | 268 | ||
269 | /* The application requests to set the I-bit of the | ||
270 | * last DATA chunk of a user message when providing | ||
271 | * the user message to the SCTP implementation. | ||
272 | */ | ||
273 | if ((sinfo->sinfo_flags & SCTP_EOF) || | ||
274 | (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY)) | ||
275 | frag |= SCTP_DATA_SACK_IMM; | ||
276 | } | ||
277 | |||
269 | chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); | 278 | chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); |
270 | 279 | ||
271 | if (!chunk) | 280 | if (!chunk) |
@@ -297,6 +306,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
297 | else | 306 | else |
298 | frag = SCTP_DATA_LAST_FRAG; | 307 | frag = SCTP_DATA_LAST_FRAG; |
299 | 308 | ||
309 | if ((sinfo->sinfo_flags & SCTP_EOF) || | ||
310 | (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY)) | ||
311 | frag |= SCTP_DATA_SACK_IMM; | ||
312 | |||
300 | chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); | 313 | chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); |
301 | 314 | ||
302 | if (!chunk) | 315 | if (!chunk) |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index c9f20e28521b..5732661c87d3 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -1011,6 +1011,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
1011 | break; | 1011 | break; |
1012 | 1012 | ||
1013 | case SCTP_XMIT_OK: | 1013 | case SCTP_XMIT_OK: |
1014 | /* The sender is in the SHUTDOWN-PENDING state, | ||
1015 | * The sender MAY set the I-bit in the DATA | ||
1016 | * chunk header. | ||
1017 | */ | ||
1018 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) | ||
1019 | chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM; | ||
1020 | |||
1014 | break; | 1021 | break; |
1015 | 1022 | ||
1016 | default: | 1023 | default: |