aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_sideeffect.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
-rw-r--r--net/sctp/sm_sideeffect.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 23a9f1a95b7d..9732c797e8ed 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -190,20 +190,28 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
190 * unacknowledged DATA chunk. ... 190 * unacknowledged DATA chunk. ...
191 */ 191 */
192 if (!asoc->peer.sack_needed) { 192 if (!asoc->peer.sack_needed) {
193 /* We will need a SACK for the next packet. */ 193 asoc->peer.sack_cnt++;
194 asoc->peer.sack_needed = 1;
195 194
196 /* Set the SACK delay timeout based on the 195 /* Set the SACK delay timeout based on the
197 * SACK delay for the last transport 196 * SACK delay for the last transport
198 * data was received from, or the default 197 * data was received from, or the default
199 * for the association. 198 * for the association.
200 */ 199 */
201 if (trans) 200 if (trans) {
201 /* We will need a SACK for the next packet. */
202 if (asoc->peer.sack_cnt >= trans->sackfreq - 1)
203 asoc->peer.sack_needed = 1;
204
202 asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = 205 asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
203 trans->sackdelay; 206 trans->sackdelay;
204 else 207 } else {
208 /* We will need a SACK for the next packet. */
209 if (asoc->peer.sack_cnt >= asoc->sackfreq - 1)
210 asoc->peer.sack_needed = 1;
211
205 asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = 212 asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
206 asoc->sackdelay; 213 asoc->sackdelay;
214 }
207 215
208 /* Restart the SACK timer. */ 216 /* Restart the SACK timer. */
209 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 217 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
@@ -216,6 +224,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
216 goto nomem; 224 goto nomem;
217 225
218 asoc->peer.sack_needed = 0; 226 asoc->peer.sack_needed = 0;
227 asoc->peer.sack_cnt = 0;
219 228
220 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack)); 229 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack));
221 230
@@ -655,7 +664,7 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
655 struct sctp_association *asoc, 664 struct sctp_association *asoc,
656 struct sctp_sackhdr *sackh) 665 struct sctp_sackhdr *sackh)
657{ 666{
658 int err; 667 int err = 0;
659 668
660 if (sctp_outq_sack(&asoc->outqueue, sackh)) { 669 if (sctp_outq_sack(&asoc->outqueue, sackh)) {
661 /* There are no more TSNs awaiting SACK. */ 670 /* There are no more TSNs awaiting SACK. */
@@ -663,11 +672,6 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
663 SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), 672 SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN),
664 asoc->state, asoc->ep, asoc, NULL, 673 asoc->state, asoc->ep, asoc, NULL,
665 GFP_ATOMIC); 674 GFP_ATOMIC);
666 } else {
667 /* Windows may have opened, so we need
668 * to check if we have DATA to transmit
669 */
670 err = sctp_outq_flush(&asoc->outqueue, 0);
671 } 675 }
672 676
673 return err; 677 return err;
@@ -1472,8 +1476,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1472 break; 1476 break;
1473 1477
1474 case SCTP_CMD_DISCARD_PACKET: 1478 case SCTP_CMD_DISCARD_PACKET:
1475 /* We need to discard the whole packet. */ 1479 /* We need to discard the whole packet.
1480 * Uncork the queue since there might be
1481 * responses pending
1482 */
1476 chunk->pdiscard = 1; 1483 chunk->pdiscard = 1;
1484 if (asoc) {
1485 sctp_outq_uncork(&asoc->outqueue);
1486 local_cork = 0;
1487 }
1477 break; 1488 break;
1478 1489
1479 case SCTP_CMD_RTO_PENDING: 1490 case SCTP_CMD_RTO_PENDING:
@@ -1544,8 +1555,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1544 } 1555 }
1545 1556
1546out: 1557out:
1547 if (local_cork) 1558 /* If this is in response to a received chunk, wait until
1548 sctp_outq_uncork(&asoc->outqueue); 1559 * we are done with the packet to open the queue so that we don't
1560 * send multiple packets in response to a single request.
1561 */
1562 if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) {
1563 if (chunk->end_of_packet || chunk->singleton)
1564 sctp_outq_uncork(&asoc->outqueue);
1565 } else if (local_cork)
1566 sctp_outq_uncork(&asoc->outqueue);
1549 return error; 1567 return error;
1550nomem: 1568nomem:
1551 error = -ENOMEM; 1569 error = -ENOMEM;