aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/command.h1
-rw-r--r--include/net/sctp/constants.h1
-rw-r--r--include/net/sctp/sctp.h1
-rw-r--r--include/net/sctp/structs.h5
-rw-r--r--net/sctp/outqueue.c33
-rw-r--r--net/sctp/sm_sideeffect.c10
-rw-r--r--net/sctp/sm_statefuns.c2
-rw-r--r--net/sctp/transport.c5
8 files changed, 36 insertions, 22 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index b8733364557f..c1f797673571 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -103,6 +103,7 @@ typedef enum {
103 SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */ 103 SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */
104 SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */ 104 SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
105 SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */ 105 SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */
106 SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */
106 SCTP_CMD_LAST 107 SCTP_CMD_LAST
107} sctp_verb_t; 108} sctp_verb_t;
108 109
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index da8354e8e33c..73fbdf6a24f8 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -407,6 +407,7 @@ typedef enum {
407 SCTP_RTXR_T3_RTX, 407 SCTP_RTXR_T3_RTX,
408 SCTP_RTXR_FAST_RTX, 408 SCTP_RTXR_FAST_RTX,
409 SCTP_RTXR_PMTUD, 409 SCTP_RTXR_PMTUD,
410 SCTP_RTXR_T1_RTX,
410} sctp_retransmit_reason_t; 411} sctp_retransmit_reason_t;
411 412
412/* Reasons to lower cwnd. */ 413/* Reasons to lower cwnd. */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 93eb708609e7..70827305f501 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -267,6 +267,7 @@ enum
267 SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS, 267 SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS,
268 SCTP_MIB_DELAY_SACK_EXPIREDS, 268 SCTP_MIB_DELAY_SACK_EXPIREDS,
269 SCTP_MIB_AUTOCLOSE_EXPIREDS, 269 SCTP_MIB_AUTOCLOSE_EXPIREDS,
270 SCTP_MIB_T1_RETRANSMITS,
270 SCTP_MIB_T3_RETRANSMITS, 271 SCTP_MIB_T3_RETRANSMITS,
271 SCTP_MIB_PMTUD_RETRANSMITS, 272 SCTP_MIB_PMTUD_RETRANSMITS,
272 SCTP_MIB_FAST_RETRANSMITS, 273 SCTP_MIB_FAST_RETRANSMITS,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ef892e00c833..482c2aab3d67 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -873,10 +873,11 @@ struct sctp_transport {
873 * address list derived from the INIT or INIT ACK chunk, a 873 * address list derived from the INIT or INIT ACK chunk, a
874 * number of data elements needs to be maintained including: 874 * number of data elements needs to be maintained including:
875 */ 875 */
876 __u32 rtt; /* This is the most recent RTT. */
877
878 /* RTO : The current retransmission timeout value. */ 876 /* RTO : The current retransmission timeout value. */
879 unsigned long rto; 877 unsigned long rto;
878 unsigned long last_rto;
879
880 __u32 rtt; /* This is the most recent RTT. */
880 881
881 /* RTTVAR : The current RTT variation. */ 882 /* RTTVAR : The current RTT variation. */
882 __u32 rttvar; 883 __u32 rttvar;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index e315c6c756ca..99a3db5d5fae 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -382,7 +382,7 @@ static void sctp_insert_list(struct list_head *head, struct list_head *new)
382/* Mark all the eligible packets on a transport for retransmission. */ 382/* Mark all the eligible packets on a transport for retransmission. */
383void sctp_retransmit_mark(struct sctp_outq *q, 383void sctp_retransmit_mark(struct sctp_outq *q,
384 struct sctp_transport *transport, 384 struct sctp_transport *transport,
385 __u8 fast_retransmit) 385 __u8 reason)
386{ 386{
387 struct list_head *lchunk, *ltemp; 387 struct list_head *lchunk, *ltemp;
388 struct sctp_chunk *chunk; 388 struct sctp_chunk *chunk;
@@ -412,20 +412,20 @@ void sctp_retransmit_mark(struct sctp_outq *q,
412 continue; 412 continue;
413 } 413 }
414 414
415 /* If we are doing retransmission due to a fast retransmit, 415 /* If we are doing retransmission due to a timeout or pmtu
416 * only the chunk's that are marked for fast retransmit 416 * discovery, only the chunks that are not yet acked should
417 * should be added to the retransmit queue. If we are doing 417 * be added to the retransmit queue.
418 * retransmission due to a timeout or pmtu discovery, only the
419 * chunks that are not yet acked should be added to the
420 * retransmit queue.
421 */ 418 */
422 if ((fast_retransmit && (chunk->fast_retransmit > 0)) || 419 if ((reason == SCTP_RTXR_FAST_RTX &&
423 (!fast_retransmit && !chunk->tsn_gap_acked)) { 420 (chunk->fast_retransmit > 0)) ||
421 (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) {
424 /* If this chunk was sent less then 1 rto ago, do not 422 /* If this chunk was sent less then 1 rto ago, do not
425 * retransmit this chunk, but give the peer time 423 * retransmit this chunk, but give the peer time
426 * to acknowlege it. 424 * to acknowlege it. Do this only when
425 * retransmitting due to T3 timeout.
427 */ 426 */
428 if ((jiffies - chunk->sent_at) < transport->rto) 427 if (reason == SCTP_RTXR_T3_RTX &&
428 (jiffies - chunk->sent_at) < transport->last_rto)
429 continue; 429 continue;
430 430
431 /* RFC 2960 6.2.1 Processing a Received SACK 431 /* RFC 2960 6.2.1 Processing a Received SACK
@@ -467,10 +467,10 @@ void sctp_retransmit_mark(struct sctp_outq *q,
467 } 467 }
468 } 468 }
469 469
470 SCTP_DEBUG_PRINTK("%s: transport: %p, fast_retransmit: %d, " 470 SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, "
471 "cwnd: %d, ssthresh: %d, flight_size: %d, " 471 "cwnd: %d, ssthresh: %d, flight_size: %d, "
472 "pba: %d\n", __FUNCTION__, 472 "pba: %d\n", __FUNCTION__,
473 transport, fast_retransmit, 473 transport, reason,
474 transport->cwnd, transport->ssthresh, 474 transport->cwnd, transport->ssthresh,
475 transport->flight_size, 475 transport->flight_size,
476 transport->partial_bytes_acked); 476 transport->partial_bytes_acked);
@@ -484,7 +484,6 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
484 sctp_retransmit_reason_t reason) 484 sctp_retransmit_reason_t reason)
485{ 485{
486 int error = 0; 486 int error = 0;
487 __u8 fast_retransmit = 0;
488 487
489 switch(reason) { 488 switch(reason) {
490 case SCTP_RTXR_T3_RTX: 489 case SCTP_RTXR_T3_RTX:
@@ -499,16 +498,18 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
499 case SCTP_RTXR_FAST_RTX: 498 case SCTP_RTXR_FAST_RTX:
500 SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); 499 SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
501 sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); 500 sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
502 fast_retransmit = 1;
503 break; 501 break;
504 case SCTP_RTXR_PMTUD: 502 case SCTP_RTXR_PMTUD:
505 SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); 503 SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
506 break; 504 break;
505 case SCTP_RTXR_T1_RTX:
506 SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
507 break;
507 default: 508 default:
508 BUG(); 509 BUG();
509 } 510 }
510 511
511 sctp_retransmit_mark(q, transport, fast_retransmit); 512 sctp_retransmit_mark(q, transport, reason);
512 513
513 /* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination, 514 /* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination,
514 * the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by 515 * the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index bbdc938da86f..78d1a8a49bd0 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -453,6 +453,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
453 * maximum value discussed in rule C7 above (RTO.max) may be 453 * maximum value discussed in rule C7 above (RTO.max) may be
454 * used to provide an upper bound to this doubling operation. 454 * used to provide an upper bound to this doubling operation.
455 */ 455 */
456 transport->last_rto = transport->rto;
456 transport->rto = min((transport->rto * 2), transport->asoc->rto_max); 457 transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
457} 458}
458 459
@@ -1267,6 +1268,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1267 sctp_ootb_pkt_free(packet); 1268 sctp_ootb_pkt_free(packet);
1268 break; 1269 break;
1269 1270
1271 case SCTP_CMD_T1_RETRAN:
1272 /* Mark a transport for retransmission. */
1273 sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
1274 SCTP_RTXR_T1_RTX);
1275 break;
1276
1270 case SCTP_CMD_RETRAN: 1277 case SCTP_CMD_RETRAN:
1271 /* Mark a transport for retransmission. */ 1278 /* Mark a transport for retransmission. */
1272 sctp_retransmit(&asoc->outqueue, cmd->obj.transport, 1279 sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
@@ -1393,7 +1400,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1393 list_for_each(pos, &asoc->peer.transport_addr_list) { 1400 list_for_each(pos, &asoc->peer.transport_addr_list) {
1394 t = list_entry(pos, struct sctp_transport, 1401 t = list_entry(pos, struct sctp_transport,
1395 transports); 1402 transports);
1396 sctp_retransmit_mark(&asoc->outqueue, t, 0); 1403 sctp_retransmit_mark(&asoc->outqueue, t,
1404 SCTP_RTXR_T1_RTX);
1397 } 1405 }
1398 1406
1399 sctp_add_cmd_sf(commands, 1407 sctp_add_cmd_sf(commands,
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f01b408508ff..a66075a70f29 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2305,7 +2305,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
2305 /* If we've sent any data bundled with COOKIE-ECHO we will need to 2305 /* If we've sent any data bundled with COOKIE-ECHO we will need to
2306 * resend 2306 * resend
2307 */ 2307 */
2308 sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, 2308 sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
2309 SCTP_TRANSPORT(asoc->peer.primary_path)); 2309 SCTP_TRANSPORT(asoc->peer.primary_path));
2310 2310
2311 /* Cast away the const modifier, as we want to just 2311 /* Cast away the const modifier, as we want to just
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 5f467c914f80..d55ce83a020b 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -74,8 +74,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
74 * given destination transport address, set RTO to the protocol 74 * given destination transport address, set RTO to the protocol
75 * parameter 'RTO.Initial'. 75 * parameter 'RTO.Initial'.
76 */ 76 */
77 peer->last_rto = peer->rto = msecs_to_jiffies(sctp_rto_initial);
77 peer->rtt = 0; 78 peer->rtt = 0;
78 peer->rto = msecs_to_jiffies(sctp_rto_initial);
79 peer->rttvar = 0; 79 peer->rttvar = 0;
80 peer->srtt = 0; 80 peer->srtt = 0;
81 peer->rto_pending = 0; 81 peer->rto_pending = 0;
@@ -385,6 +385,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
385 tp->rto = tp->asoc->rto_max; 385 tp->rto = tp->asoc->rto_max;
386 386
387 tp->rtt = rtt; 387 tp->rtt = rtt;
388 tp->last_rto = tp->rto;
388 389
389 /* Reset rto_pending so that a new RTT measurement is started when a 390 /* Reset rto_pending so that a new RTT measurement is started when a
390 * new data chunk is sent. 391 * new data chunk is sent.
@@ -578,7 +579,7 @@ void sctp_transport_reset(struct sctp_transport *t)
578 */ 579 */
579 t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); 580 t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
580 t->ssthresh = asoc->peer.i.a_rwnd; 581 t->ssthresh = asoc->peer.i.a_rwnd;
581 t->rto = asoc->rto_initial; 582 t->last_rto = t->rto = asoc->rto_initial;
582 t->rtt = 0; 583 t->rtt = 0;
583 t->srtt = 0; 584 t->srtt = 0;
584 t->rttvar = 0; 585 t->rttvar = 0;