aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/outqueue.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2009-09-04 18:21:00 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2009-09-04 18:21:00 -0400
commit31b02e1549406efa346534acad956a42bc3f28c4 (patch)
tree3acc807275810eb2efdc5fc2744bdfc3528488c2 /net/sctp/outqueue.c
parentf68b2e05f326971cd76c65aa91a1a41771dd7485 (diff)
sctp: Failover transmitted list on transport delete
Add-IP feature allows users to delete an active transport. If that transport has chunks in flight, those chunks need to be moved to another transport or association may get into unrecoverable state. Reported-by: Rafael Laufer <rlaufer@cisco.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Diffstat (limited to 'net/sctp/outqueue.c')
-rw-r--r--net/sctp/outqueue.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index d765fc53e74d..c9f20e28521b 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -406,8 +406,9 @@ void sctp_retransmit_mark(struct sctp_outq *q,
406 * not be retransmitted 406 * not be retransmitted
407 */ 407 */
408 if (!chunk->tsn_gap_acked) { 408 if (!chunk->tsn_gap_acked) {
409 chunk->transport->flight_size -= 409 if (chunk->transport)
410 sctp_data_size(chunk); 410 chunk->transport->flight_size -=
411 sctp_data_size(chunk);
411 q->outstanding_bytes -= sctp_data_size(chunk); 412 q->outstanding_bytes -= sctp_data_size(chunk);
412 q->asoc->peer.rwnd += (sctp_data_size(chunk) + 413 q->asoc->peer.rwnd += (sctp_data_size(chunk) +
413 sizeof(struct sk_buff)); 414 sizeof(struct sk_buff));
@@ -443,7 +444,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
443 q->asoc->peer.rwnd += (sctp_data_size(chunk) + 444 q->asoc->peer.rwnd += (sctp_data_size(chunk) +
444 sizeof(struct sk_buff)); 445 sizeof(struct sk_buff));
445 q->outstanding_bytes -= sctp_data_size(chunk); 446 q->outstanding_bytes -= sctp_data_size(chunk);
446 transport->flight_size -= sctp_data_size(chunk); 447 if (chunk->transport)
448 transport->flight_size -= sctp_data_size(chunk);
447 449
448 /* sctpimpguide-05 Section 2.8.2 450 /* sctpimpguide-05 Section 2.8.2
449 * M5) If a T3-rtx timer expires, the 451 * M5) If a T3-rtx timer expires, the
@@ -1310,6 +1312,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1310 __u32 rtt; 1312 __u32 rtt;
1311 __u8 restart_timer = 0; 1313 __u8 restart_timer = 0;
1312 int bytes_acked = 0; 1314 int bytes_acked = 0;
1315 int migrate_bytes = 0;
1313 1316
1314 /* These state variables are for coherent debug output. --xguo */ 1317 /* These state variables are for coherent debug output. --xguo */
1315 1318
@@ -1343,8 +1346,9 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1343 * considering it as 'outstanding'. 1346 * considering it as 'outstanding'.
1344 */ 1347 */
1345 if (!tchunk->tsn_gap_acked) { 1348 if (!tchunk->tsn_gap_acked) {
1346 tchunk->transport->flight_size -= 1349 if (tchunk->transport)
1347 sctp_data_size(tchunk); 1350 tchunk->transport->flight_size -=
1351 sctp_data_size(tchunk);
1348 q->outstanding_bytes -= sctp_data_size(tchunk); 1352 q->outstanding_bytes -= sctp_data_size(tchunk);
1349 } 1353 }
1350 continue; 1354 continue;
@@ -1378,6 +1382,20 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1378 rtt); 1382 rtt);
1379 } 1383 }
1380 } 1384 }
1385
1386 /* If the chunk hasn't been marked as ACKED,
1387 * mark it and account bytes_acked if the
1388 * chunk had a valid transport (it will not
1389 * have a transport if ASCONF had deleted it
1390 * while DATA was outstanding).
1391 */
1392 if (!tchunk->tsn_gap_acked) {
1393 tchunk->tsn_gap_acked = 1;
1394 bytes_acked += sctp_data_size(tchunk);
1395 if (!tchunk->transport)
1396 migrate_bytes += sctp_data_size(tchunk);
1397 }
1398
1381 if (TSN_lte(tsn, sack_ctsn)) { 1399 if (TSN_lte(tsn, sack_ctsn)) {
1382 /* RFC 2960 6.3.2 Retransmission Timer Rules 1400 /* RFC 2960 6.3.2 Retransmission Timer Rules
1383 * 1401 *
@@ -1391,8 +1409,6 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1391 restart_timer = 1; 1409 restart_timer = 1;
1392 1410
1393 if (!tchunk->tsn_gap_acked) { 1411 if (!tchunk->tsn_gap_acked) {
1394 tchunk->tsn_gap_acked = 1;
1395 bytes_acked += sctp_data_size(tchunk);
1396 /* 1412 /*
1397 * SFR-CACC algorithm: 1413 * SFR-CACC algorithm:
1398 * 2) If the SACK contains gap acks 1414 * 2) If the SACK contains gap acks
@@ -1432,10 +1448,6 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1432 * older than that newly acknowledged DATA 1448 * older than that newly acknowledged DATA
1433 * chunk, are qualified as 'Stray DATA chunks'. 1449 * chunk, are qualified as 'Stray DATA chunks'.
1434 */ 1450 */
1435 if (!tchunk->tsn_gap_acked) {
1436 tchunk->tsn_gap_acked = 1;
1437 bytes_acked += sctp_data_size(tchunk);
1438 }
1439 list_add_tail(lchunk, &tlist); 1451 list_add_tail(lchunk, &tlist);
1440 } 1452 }
1441 1453
@@ -1491,7 +1503,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1491 tsn); 1503 tsn);
1492 tchunk->tsn_gap_acked = 0; 1504 tchunk->tsn_gap_acked = 0;
1493 1505
1494 bytes_acked -= sctp_data_size(tchunk); 1506 if (tchunk->transport)
1507 bytes_acked -= sctp_data_size(tchunk);
1495 1508
1496 /* RFC 2960 6.3.2 Retransmission Timer Rules 1509 /* RFC 2960 6.3.2 Retransmission Timer Rules
1497 * 1510 *
@@ -1561,6 +1574,14 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1561#endif /* SCTP_DEBUG */ 1574#endif /* SCTP_DEBUG */
1562 if (transport) { 1575 if (transport) {
1563 if (bytes_acked) { 1576 if (bytes_acked) {
1577 /* We may have counted DATA that was migrated
1578 * to this transport due to DEL-IP operation.
1579 * Subtract those bytes, since the were never
1580 * send on this transport and shouldn't be
1581 * credited to this transport.
1582 */
1583 bytes_acked -= migrate_bytes;
1584
1564 /* 8.2. When an outstanding TSN is acknowledged, 1585 /* 8.2. When an outstanding TSN is acknowledged,
1565 * the endpoint shall clear the error counter of 1586 * the endpoint shall clear the error counter of
1566 * the destination transport address to which the 1587 * the destination transport address to which the
@@ -1589,7 +1610,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1589 transport->flight_size -= bytes_acked; 1610 transport->flight_size -= bytes_acked;
1590 if (transport->flight_size == 0) 1611 if (transport->flight_size == 0)
1591 transport->partial_bytes_acked = 0; 1612 transport->partial_bytes_acked = 0;
1592 q->outstanding_bytes -= bytes_acked; 1613 q->outstanding_bytes -= bytes_acked + migrate_bytes;
1593 } else { 1614 } else {
1594 /* RFC 2960 6.1, sctpimpguide-06 2.15.2 1615 /* RFC 2960 6.1, sctpimpguide-06 2.15.2
1595 * When a sender is doing zero window probing, it 1616 * When a sender is doing zero window probing, it