diff options
Diffstat (limited to 'net/sctp/outqueue.c')
-rw-r--r-- | net/sctp/outqueue.c | 214 |
1 files changed, 49 insertions, 165 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index be35e2dbcc9a..ef9e2bbc0f2f 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -299,10 +299,10 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
299 | struct net *net = sock_net(q->asoc->base.sk); | 299 | struct net *net = sock_net(q->asoc->base.sk); |
300 | int error = 0; | 300 | int error = 0; |
301 | 301 | ||
302 | SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n", | 302 | pr_debug("%s: outq:%p, chunk:%p[%s]\n", __func__, q, chunk, |
303 | q, chunk, chunk && chunk->chunk_hdr ? | 303 | chunk && chunk->chunk_hdr ? |
304 | sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) | 304 | sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : |
305 | : "Illegal Chunk"); | 305 | "illegal chunk"); |
306 | 306 | ||
307 | /* If it is data, queue it up, otherwise, send it | 307 | /* If it is data, queue it up, otherwise, send it |
308 | * immediately. | 308 | * immediately. |
@@ -328,10 +328,10 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
328 | break; | 328 | break; |
329 | 329 | ||
330 | default: | 330 | default: |
331 | SCTP_DEBUG_PRINTK("outqueueing (%p, %p[%s])\n", | 331 | pr_debug("%s: outqueueing: outq:%p, chunk:%p[%s])\n", |
332 | q, chunk, chunk && chunk->chunk_hdr ? | 332 | __func__, q, chunk, chunk && chunk->chunk_hdr ? |
333 | sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) | 333 | sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : |
334 | : "Illegal Chunk"); | 334 | "illegal chunk"); |
335 | 335 | ||
336 | sctp_outq_tail_data(q, chunk); | 336 | sctp_outq_tail_data(q, chunk); |
337 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) | 337 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) |
@@ -460,14 +460,10 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
460 | } | 460 | } |
461 | } | 461 | } |
462 | 462 | ||
463 | SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, " | 463 | pr_debug("%s: transport:%p, reason:%d, cwnd:%d, ssthresh:%d, " |
464 | "cwnd: %d, ssthresh: %d, flight_size: %d, " | 464 | "flight_size:%d, pba:%d\n", __func__, transport, reason, |
465 | "pba: %d\n", __func__, | 465 | transport->cwnd, transport->ssthresh, transport->flight_size, |
466 | transport, reason, | 466 | transport->partial_bytes_acked); |
467 | transport->cwnd, transport->ssthresh, | ||
468 | transport->flight_size, | ||
469 | transport->partial_bytes_acked); | ||
470 | |||
471 | } | 467 | } |
472 | 468 | ||
473 | /* Mark all the eligible packets on a transport for retransmission and force | 469 | /* Mark all the eligible packets on a transport for retransmission and force |
@@ -1014,19 +1010,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
1014 | sctp_transport_burst_limited(transport); | 1010 | sctp_transport_burst_limited(transport); |
1015 | } | 1011 | } |
1016 | 1012 | ||
1017 | SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ", | 1013 | pr_debug("%s: outq:%p, chunk:%p[%s], tx-tsn:0x%x skb->head:%p " |
1018 | q, chunk, | 1014 | "skb->users:%d\n", |
1019 | chunk && chunk->chunk_hdr ? | 1015 | __func__, q, chunk, chunk && chunk->chunk_hdr ? |
1020 | sctp_cname(SCTP_ST_CHUNK( | 1016 | sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : |
1021 | chunk->chunk_hdr->type)) | 1017 | "illegal chunk", ntohl(chunk->subh.data_hdr->tsn), |
1022 | : "Illegal Chunk"); | 1018 | chunk->skb ? chunk->skb->head : NULL, chunk->skb ? |
1023 | 1019 | atomic_read(&chunk->skb->users) : -1); | |
1024 | SCTP_DEBUG_PRINTK("TX TSN 0x%x skb->head " | ||
1025 | "%p skb->users %d.\n", | ||
1026 | ntohl(chunk->subh.data_hdr->tsn), | ||
1027 | chunk->skb ?chunk->skb->head : NULL, | ||
1028 | chunk->skb ? | ||
1029 | atomic_read(&chunk->skb->users) : -1); | ||
1030 | 1020 | ||
1031 | /* Add the chunk to the packet. */ | 1021 | /* Add the chunk to the packet. */ |
1032 | status = sctp_packet_transmit_chunk(packet, chunk, 0); | 1022 | status = sctp_packet_transmit_chunk(packet, chunk, 0); |
@@ -1038,10 +1028,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
1038 | /* We could not append this chunk, so put | 1028 | /* We could not append this chunk, so put |
1039 | * the chunk back on the output queue. | 1029 | * the chunk back on the output queue. |
1040 | */ | 1030 | */ |
1041 | SCTP_DEBUG_PRINTK("sctp_outq_flush: could " | 1031 | pr_debug("%s: could not transmit tsn:0x%x, status:%d\n", |
1042 | "not transmit TSN: 0x%x, status: %d\n", | 1032 | __func__, ntohl(chunk->subh.data_hdr->tsn), |
1043 | ntohl(chunk->subh.data_hdr->tsn), | 1033 | status); |
1044 | status); | 1034 | |
1045 | sctp_outq_head_data(q, chunk); | 1035 | sctp_outq_head_data(q, chunk); |
1046 | goto sctp_flush_out; | 1036 | goto sctp_flush_out; |
1047 | break; | 1037 | break; |
@@ -1284,11 +1274,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
1284 | 1274 | ||
1285 | sctp_generate_fwdtsn(q, sack_ctsn); | 1275 | sctp_generate_fwdtsn(q, sack_ctsn); |
1286 | 1276 | ||
1287 | SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n", | 1277 | pr_debug("%s: sack cumulative tsn ack:0x%x\n", __func__, sack_ctsn); |
1288 | __func__, sack_ctsn); | 1278 | pr_debug("%s: cumulative tsn ack of assoc:%p is 0x%x, " |
1289 | SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association, " | 1279 | "advertised peer ack point:0x%x\n", __func__, asoc, ctsn, |
1290 | "%p is 0x%x. Adv peer ack point: 0x%x\n", | 1280 | asoc->adv_peer_ack_point); |
1291 | __func__, asoc, ctsn, asoc->adv_peer_ack_point); | ||
1292 | 1281 | ||
1293 | /* See if all chunks are acked. | 1282 | /* See if all chunks are acked. |
1294 | * Make sure the empty queue handler will get run later. | 1283 | * Make sure the empty queue handler will get run later. |
@@ -1304,7 +1293,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
1304 | goto finish; | 1293 | goto finish; |
1305 | } | 1294 | } |
1306 | 1295 | ||
1307 | SCTP_DEBUG_PRINTK("sack queue is empty.\n"); | 1296 | pr_debug("%s: sack queue is empty\n", __func__); |
1308 | finish: | 1297 | finish: |
1309 | return q->empty; | 1298 | return q->empty; |
1310 | } | 1299 | } |
@@ -1345,21 +1334,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1345 | __u8 restart_timer = 0; | 1334 | __u8 restart_timer = 0; |
1346 | int bytes_acked = 0; | 1335 | int bytes_acked = 0; |
1347 | int migrate_bytes = 0; | 1336 | int migrate_bytes = 0; |
1348 | 1337 | bool forward_progress = false; | |
1349 | /* These state variables are for coherent debug output. --xguo */ | ||
1350 | |||
1351 | #if SCTP_DEBUG | ||
1352 | __u32 dbg_ack_tsn = 0; /* An ACKed TSN range starts here... */ | ||
1353 | __u32 dbg_last_ack_tsn = 0; /* ...and finishes here. */ | ||
1354 | __u32 dbg_kept_tsn = 0; /* An un-ACKed range starts here... */ | ||
1355 | __u32 dbg_last_kept_tsn = 0; /* ...and finishes here. */ | ||
1356 | |||
1357 | /* 0 : The last TSN was ACKed. | ||
1358 | * 1 : The last TSN was NOT ACKed (i.e. KEPT). | ||
1359 | * -1: We need to initialize. | ||
1360 | */ | ||
1361 | int dbg_prt_state = -1; | ||
1362 | #endif /* SCTP_DEBUG */ | ||
1363 | 1338 | ||
1364 | sack_ctsn = ntohl(sack->cum_tsn_ack); | 1339 | sack_ctsn = ntohl(sack->cum_tsn_ack); |
1365 | 1340 | ||
@@ -1426,6 +1401,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1426 | bytes_acked += sctp_data_size(tchunk); | 1401 | bytes_acked += sctp_data_size(tchunk); |
1427 | if (!tchunk->transport) | 1402 | if (!tchunk->transport) |
1428 | migrate_bytes += sctp_data_size(tchunk); | 1403 | migrate_bytes += sctp_data_size(tchunk); |
1404 | forward_progress = true; | ||
1429 | } | 1405 | } |
1430 | 1406 | ||
1431 | if (TSN_lte(tsn, sack_ctsn)) { | 1407 | if (TSN_lte(tsn, sack_ctsn)) { |
@@ -1439,6 +1415,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1439 | * current RTO. | 1415 | * current RTO. |
1440 | */ | 1416 | */ |
1441 | restart_timer = 1; | 1417 | restart_timer = 1; |
1418 | forward_progress = true; | ||
1442 | 1419 | ||
1443 | if (!tchunk->tsn_gap_acked) { | 1420 | if (!tchunk->tsn_gap_acked) { |
1444 | /* | 1421 | /* |
@@ -1482,57 +1459,11 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1482 | */ | 1459 | */ |
1483 | list_add_tail(lchunk, &tlist); | 1460 | list_add_tail(lchunk, &tlist); |
1484 | } | 1461 | } |
1485 | |||
1486 | #if SCTP_DEBUG | ||
1487 | switch (dbg_prt_state) { | ||
1488 | case 0: /* last TSN was ACKed */ | ||
1489 | if (dbg_last_ack_tsn + 1 == tsn) { | ||
1490 | /* This TSN belongs to the | ||
1491 | * current ACK range. | ||
1492 | */ | ||
1493 | break; | ||
1494 | } | ||
1495 | |||
1496 | if (dbg_last_ack_tsn != dbg_ack_tsn) { | ||
1497 | /* Display the end of the | ||
1498 | * current range. | ||
1499 | */ | ||
1500 | SCTP_DEBUG_PRINTK_CONT("-%08x", | ||
1501 | dbg_last_ack_tsn); | ||
1502 | } | ||
1503 | |||
1504 | /* Start a new range. */ | ||
1505 | SCTP_DEBUG_PRINTK_CONT(",%08x", tsn); | ||
1506 | dbg_ack_tsn = tsn; | ||
1507 | break; | ||
1508 | |||
1509 | case 1: /* The last TSN was NOT ACKed. */ | ||
1510 | if (dbg_last_kept_tsn != dbg_kept_tsn) { | ||
1511 | /* Display the end of current range. */ | ||
1512 | SCTP_DEBUG_PRINTK_CONT("-%08x", | ||
1513 | dbg_last_kept_tsn); | ||
1514 | } | ||
1515 | |||
1516 | SCTP_DEBUG_PRINTK_CONT("\n"); | ||
1517 | |||
1518 | /* FALL THROUGH... */ | ||
1519 | default: | ||
1520 | /* This is the first-ever TSN we examined. */ | ||
1521 | /* Start a new range of ACK-ed TSNs. */ | ||
1522 | SCTP_DEBUG_PRINTK("ACKed: %08x", tsn); | ||
1523 | dbg_prt_state = 0; | ||
1524 | dbg_ack_tsn = tsn; | ||
1525 | } | ||
1526 | |||
1527 | dbg_last_ack_tsn = tsn; | ||
1528 | #endif /* SCTP_DEBUG */ | ||
1529 | |||
1530 | } else { | 1462 | } else { |
1531 | if (tchunk->tsn_gap_acked) { | 1463 | if (tchunk->tsn_gap_acked) { |
1532 | SCTP_DEBUG_PRINTK("%s: Receiver reneged on " | 1464 | pr_debug("%s: receiver reneged on data TSN:0x%x\n", |
1533 | "data TSN: 0x%x\n", | 1465 | __func__, tsn); |
1534 | __func__, | 1466 | |
1535 | tsn); | ||
1536 | tchunk->tsn_gap_acked = 0; | 1467 | tchunk->tsn_gap_acked = 0; |
1537 | 1468 | ||
1538 | if (tchunk->transport) | 1469 | if (tchunk->transport) |
@@ -1551,59 +1482,9 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1551 | } | 1482 | } |
1552 | 1483 | ||
1553 | list_add_tail(lchunk, &tlist); | 1484 | list_add_tail(lchunk, &tlist); |
1554 | |||
1555 | #if SCTP_DEBUG | ||
1556 | /* See the above comments on ACK-ed TSNs. */ | ||
1557 | switch (dbg_prt_state) { | ||
1558 | case 1: | ||
1559 | if (dbg_last_kept_tsn + 1 == tsn) | ||
1560 | break; | ||
1561 | |||
1562 | if (dbg_last_kept_tsn != dbg_kept_tsn) | ||
1563 | SCTP_DEBUG_PRINTK_CONT("-%08x", | ||
1564 | dbg_last_kept_tsn); | ||
1565 | |||
1566 | SCTP_DEBUG_PRINTK_CONT(",%08x", tsn); | ||
1567 | dbg_kept_tsn = tsn; | ||
1568 | break; | ||
1569 | |||
1570 | case 0: | ||
1571 | if (dbg_last_ack_tsn != dbg_ack_tsn) | ||
1572 | SCTP_DEBUG_PRINTK_CONT("-%08x", | ||
1573 | dbg_last_ack_tsn); | ||
1574 | SCTP_DEBUG_PRINTK_CONT("\n"); | ||
1575 | |||
1576 | /* FALL THROUGH... */ | ||
1577 | default: | ||
1578 | SCTP_DEBUG_PRINTK("KEPT: %08x",tsn); | ||
1579 | dbg_prt_state = 1; | ||
1580 | dbg_kept_tsn = tsn; | ||
1581 | } | ||
1582 | |||
1583 | dbg_last_kept_tsn = tsn; | ||
1584 | #endif /* SCTP_DEBUG */ | ||
1585 | } | 1485 | } |
1586 | } | 1486 | } |
1587 | 1487 | ||
1588 | #if SCTP_DEBUG | ||
1589 | /* Finish off the last range, displaying its ending TSN. */ | ||
1590 | switch (dbg_prt_state) { | ||
1591 | case 0: | ||
1592 | if (dbg_last_ack_tsn != dbg_ack_tsn) { | ||
1593 | SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_ack_tsn); | ||
1594 | } else { | ||
1595 | SCTP_DEBUG_PRINTK_CONT("\n"); | ||
1596 | } | ||
1597 | break; | ||
1598 | |||
1599 | case 1: | ||
1600 | if (dbg_last_kept_tsn != dbg_kept_tsn) { | ||
1601 | SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_kept_tsn); | ||
1602 | } else { | ||
1603 | SCTP_DEBUG_PRINTK_CONT("\n"); | ||
1604 | } | ||
1605 | } | ||
1606 | #endif /* SCTP_DEBUG */ | ||
1607 | if (transport) { | 1488 | if (transport) { |
1608 | if (bytes_acked) { | 1489 | if (bytes_acked) { |
1609 | struct sctp_association *asoc = transport->asoc; | 1490 | struct sctp_association *asoc = transport->asoc; |
@@ -1625,6 +1506,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1625 | */ | 1506 | */ |
1626 | transport->error_count = 0; | 1507 | transport->error_count = 0; |
1627 | transport->asoc->overall_error_count = 0; | 1508 | transport->asoc->overall_error_count = 0; |
1509 | forward_progress = true; | ||
1628 | 1510 | ||
1629 | /* | 1511 | /* |
1630 | * While in SHUTDOWN PENDING, we may have started | 1512 | * While in SHUTDOWN PENDING, we may have started |
@@ -1676,9 +1558,9 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1676 | !list_empty(&tlist) && | 1558 | !list_empty(&tlist) && |
1677 | (sack_ctsn+2 == q->asoc->next_tsn) && | 1559 | (sack_ctsn+2 == q->asoc->next_tsn) && |
1678 | q->asoc->state < SCTP_STATE_SHUTDOWN_PENDING) { | 1560 | q->asoc->state < SCTP_STATE_SHUTDOWN_PENDING) { |
1679 | SCTP_DEBUG_PRINTK("%s: SACK received for zero " | 1561 | pr_debug("%s: sack received for zero window " |
1680 | "window probe: %u\n", | 1562 | "probe:%u\n", __func__, sack_ctsn); |
1681 | __func__, sack_ctsn); | 1563 | |
1682 | q->asoc->overall_error_count = 0; | 1564 | q->asoc->overall_error_count = 0; |
1683 | transport->error_count = 0; | 1565 | transport->error_count = 0; |
1684 | } | 1566 | } |
@@ -1698,6 +1580,11 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1698 | jiffies + transport->rto)) | 1580 | jiffies + transport->rto)) |
1699 | sctp_transport_hold(transport); | 1581 | sctp_transport_hold(transport); |
1700 | } | 1582 | } |
1583 | |||
1584 | if (forward_progress) { | ||
1585 | if (transport->dst) | ||
1586 | dst_confirm(transport->dst); | ||
1587 | } | ||
1701 | } | 1588 | } |
1702 | 1589 | ||
1703 | list_splice(&tlist, transmitted_queue); | 1590 | list_splice(&tlist, transmitted_queue); |
@@ -1739,10 +1626,8 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1739 | count_of_newacks, tsn)) { | 1626 | count_of_newacks, tsn)) { |
1740 | chunk->tsn_missing_report++; | 1627 | chunk->tsn_missing_report++; |
1741 | 1628 | ||
1742 | SCTP_DEBUG_PRINTK( | 1629 | pr_debug("%s: tsn:0x%x missing counter:%d\n", |
1743 | "%s: TSN 0x%x missing counter: %d\n", | 1630 | __func__, tsn, chunk->tsn_missing_report); |
1744 | __func__, tsn, | ||
1745 | chunk->tsn_missing_report); | ||
1746 | } | 1631 | } |
1747 | } | 1632 | } |
1748 | /* | 1633 | /* |
@@ -1762,11 +1647,10 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1762 | if (do_fast_retransmit) | 1647 | if (do_fast_retransmit) |
1763 | sctp_retransmit(q, transport, SCTP_RTXR_FAST_RTX); | 1648 | sctp_retransmit(q, transport, SCTP_RTXR_FAST_RTX); |
1764 | 1649 | ||
1765 | SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, " | 1650 | pr_debug("%s: transport:%p, cwnd:%d, ssthresh:%d, " |
1766 | "ssthresh: %d, flight_size: %d, pba: %d\n", | 1651 | "flight_size:%d, pba:%d\n", __func__, transport, |
1767 | __func__, transport, transport->cwnd, | 1652 | transport->cwnd, transport->ssthresh, |
1768 | transport->ssthresh, transport->flight_size, | 1653 | transport->flight_size, transport->partial_bytes_acked); |
1769 | transport->partial_bytes_acked); | ||
1770 | } | 1654 | } |
1771 | } | 1655 | } |
1772 | 1656 | ||