aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/user.h1
-rw-r--r--net/sctp/chunk.c15
-rw-r--r--net/sctp/outqueue.c7
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: