diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/outqueue.c | 20 | ||||
-rw-r--r-- | net/sctp/protocol.c | 11 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 20 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 32 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 36 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 16 |
7 files changed, 106 insertions, 31 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index edc753297a49..a6d27bf563a5 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -1595,6 +1595,8 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1595 | #endif /* SCTP_DEBUG */ | 1595 | #endif /* SCTP_DEBUG */ |
1596 | if (transport) { | 1596 | if (transport) { |
1597 | if (bytes_acked) { | 1597 | if (bytes_acked) { |
1598 | struct sctp_association *asoc = transport->asoc; | ||
1599 | |||
1598 | /* We may have counted DATA that was migrated | 1600 | /* We may have counted DATA that was migrated |
1599 | * to this transport due to DEL-IP operation. | 1601 | * to this transport due to DEL-IP operation. |
1600 | * Subtract those bytes, since the were never | 1602 | * Subtract those bytes, since the were never |
@@ -1613,6 +1615,17 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1613 | transport->error_count = 0; | 1615 | transport->error_count = 0; |
1614 | transport->asoc->overall_error_count = 0; | 1616 | transport->asoc->overall_error_count = 0; |
1615 | 1617 | ||
1618 | /* | ||
1619 | * While in SHUTDOWN PENDING, we may have started | ||
1620 | * the T5 shutdown guard timer after reaching the | ||
1621 | * retransmission limit. Stop that timer as soon | ||
1622 | * as the receiver acknowledged any data. | ||
1623 | */ | ||
1624 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING && | ||
1625 | del_timer(&asoc->timers | ||
1626 | [SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD])) | ||
1627 | sctp_association_put(asoc); | ||
1628 | |||
1616 | /* Mark the destination transport address as | 1629 | /* Mark the destination transport address as |
1617 | * active if it is not so marked. | 1630 | * active if it is not so marked. |
1618 | */ | 1631 | */ |
@@ -1642,10 +1655,15 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1642 | * A sender is doing zero window probing when the | 1655 | * A sender is doing zero window probing when the |
1643 | * receiver's advertised window is zero, and there is | 1656 | * receiver's advertised window is zero, and there is |
1644 | * only one data chunk in flight to the receiver. | 1657 | * only one data chunk in flight to the receiver. |
1658 | * | ||
1659 | * Allow the association to timeout while in SHUTDOWN | ||
1660 | * PENDING or SHUTDOWN RECEIVED in case the receiver | ||
1661 | * stays in zero window mode forever. | ||
1645 | */ | 1662 | */ |
1646 | if (!q->asoc->peer.rwnd && | 1663 | if (!q->asoc->peer.rwnd && |
1647 | !list_empty(&tlist) && | 1664 | !list_empty(&tlist) && |
1648 | (sack_ctsn+2 == q->asoc->next_tsn)) { | 1665 | (sack_ctsn+2 == q->asoc->next_tsn) && |
1666 | q->asoc->state < SCTP_STATE_SHUTDOWN_PENDING) { | ||
1649 | SCTP_DEBUG_PRINTK("%s: SACK received for zero " | 1667 | SCTP_DEBUG_PRINTK("%s: SACK received for zero " |
1650 | "window probe: %u\n", | 1668 | "window probe: %u\n", |
1651 | __func__, sack_ctsn); | 1669 | __func__, sack_ctsn); |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index ab5ded2c58de..91784f44a2e2 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1199,7 +1199,6 @@ SCTP_STATIC __init int sctp_init(void) | |||
1199 | int status = -EINVAL; | 1199 | int status = -EINVAL; |
1200 | unsigned long goal; | 1200 | unsigned long goal; |
1201 | unsigned long limit; | 1201 | unsigned long limit; |
1202 | unsigned long nr_pages; | ||
1203 | int max_share; | 1202 | int max_share; |
1204 | int order; | 1203 | int order; |
1205 | 1204 | ||
@@ -1289,15 +1288,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1289 | /* Initialize handle used for association ids. */ | 1288 | /* Initialize handle used for association ids. */ |
1290 | idr_init(&sctp_assocs_id); | 1289 | idr_init(&sctp_assocs_id); |
1291 | 1290 | ||
1292 | /* Set the pressure threshold to be a fraction of global memory that | 1291 | limit = nr_free_buffer_pages() / 8; |
1293 | * is up to 1/2 at 256 MB, decreasing toward zero with the amount of | ||
1294 | * memory, with a floor of 128 pages. | ||
1295 | * Note this initializes the data in sctpv6_prot too | ||
1296 | * Unabashedly stolen from tcp_init | ||
1297 | */ | ||
1298 | nr_pages = totalram_pages - totalhigh_pages; | ||
1299 | limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); | ||
1300 | limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); | ||
1301 | limit = max(limit, 128UL); | 1292 | limit = max(limit, 128UL); |
1302 | sysctl_sctp_mem[0] = limit / 4 * 3; | 1293 | sysctl_sctp_mem[0] = limit / 4 * 3; |
1303 | sysctl_sctp_mem[1] = limit; | 1294 | sysctl_sctp_mem[1] = limit; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 1b2bb6487342..167c880cf8da 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -670,10 +670,19 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
670 | /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of the | 670 | /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of the |
671 | * HEARTBEAT should clear the error counter of the destination | 671 | * HEARTBEAT should clear the error counter of the destination |
672 | * transport address to which the HEARTBEAT was sent. | 672 | * transport address to which the HEARTBEAT was sent. |
673 | * The association's overall error count is also cleared. | ||
674 | */ | 673 | */ |
675 | t->error_count = 0; | 674 | t->error_count = 0; |
676 | t->asoc->overall_error_count = 0; | 675 | |
676 | /* | ||
677 | * Although RFC4960 specifies that the overall error count must | ||
678 | * be cleared when a HEARTBEAT ACK is received, we make an | ||
679 | * exception while in SHUTDOWN PENDING. If the peer keeps its | ||
680 | * window shut forever, we may never be able to transmit our | ||
681 | * outstanding data and rely on the retransmission limit be reached | ||
682 | * to shutdown the association. | ||
683 | */ | ||
684 | if (t->asoc->state != SCTP_STATE_SHUTDOWN_PENDING) | ||
685 | t->asoc->overall_error_count = 0; | ||
677 | 686 | ||
678 | /* Clear the hb_sent flag to signal that we had a good | 687 | /* Clear the hb_sent flag to signal that we had a good |
679 | * acknowledgement. | 688 | * acknowledgement. |
@@ -1437,6 +1446,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1437 | sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr); | 1446 | sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr); |
1438 | break; | 1447 | break; |
1439 | 1448 | ||
1449 | case SCTP_CMD_TIMER_START_ONCE: | ||
1450 | timer = &asoc->timers[cmd->obj.to]; | ||
1451 | |||
1452 | if (timer_pending(timer)) | ||
1453 | break; | ||
1454 | /* fall through */ | ||
1455 | |||
1440 | case SCTP_CMD_TIMER_START: | 1456 | case SCTP_CMD_TIMER_START: |
1441 | timer = &asoc->timers[cmd->obj.to]; | 1457 | timer = &asoc->timers[cmd->obj.to]; |
1442 | timeout = asoc->timeouts[cmd->obj.to]; | 1458 | timeout = asoc->timeouts[cmd->obj.to]; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 7d00b1777c63..49b847b00f99 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -5155,7 +5155,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | |||
5155 | * The sender of the SHUTDOWN MAY also start an overall guard timer | 5155 | * The sender of the SHUTDOWN MAY also start an overall guard timer |
5156 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | 5156 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. |
5157 | */ | 5157 | */ |
5158 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 5158 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
5159 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 5159 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
5160 | 5160 | ||
5161 | if (asoc->autoclose) | 5161 | if (asoc->autoclose) |
@@ -5300,14 +5300,28 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
5300 | SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS); | 5300 | SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS); |
5301 | 5301 | ||
5302 | if (asoc->overall_error_count >= asoc->max_retrans) { | 5302 | if (asoc->overall_error_count >= asoc->max_retrans) { |
5303 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | 5303 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { |
5304 | SCTP_ERROR(ETIMEDOUT)); | 5304 | /* |
5305 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 5305 | * We are here likely because the receiver had its rwnd |
5306 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5306 | * closed for a while and we have not been able to |
5307 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5307 | * transmit the locally queued data within the maximum |
5308 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5308 | * retransmission attempts limit. Start the T5 |
5309 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 5309 | * shutdown guard timer to give the receiver one last |
5310 | return SCTP_DISPOSITION_DELETE_TCB; | 5310 | * chance and some additional time to recover before |
5311 | * aborting. | ||
5312 | */ | ||
5313 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START_ONCE, | ||
5314 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
5315 | } else { | ||
5316 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
5317 | SCTP_ERROR(ETIMEDOUT)); | ||
5318 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | ||
5319 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | ||
5320 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | ||
5321 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
5322 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
5323 | return SCTP_DISPOSITION_DELETE_TCB; | ||
5324 | } | ||
5311 | } | 5325 | } |
5312 | 5326 | ||
5313 | /* E1) For the destination address for which the timer | 5327 | /* E1) For the destination address for which the timer |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 0338dc6fdc9d..7c211a7f90f4 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -827,7 +827,7 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
827 | /* SCTP_STATE_ESTABLISHED */ \ | 827 | /* SCTP_STATE_ESTABLISHED */ \ |
828 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 828 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
829 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 829 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
830 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 830 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ |
831 | /* SCTP_STATE_SHUTDOWN_SENT */ \ | 831 | /* SCTP_STATE_SHUTDOWN_SENT */ \ |
832 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ | 832 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ |
833 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ | 833 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 1c6aec1f9ec4..836aa63ee121 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1454,6 +1454,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1454 | struct sctp_endpoint *ep; | 1454 | struct sctp_endpoint *ep; |
1455 | struct sctp_association *asoc; | 1455 | struct sctp_association *asoc; |
1456 | struct list_head *pos, *temp; | 1456 | struct list_head *pos, *temp; |
1457 | unsigned int data_was_unread; | ||
1457 | 1458 | ||
1458 | SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); | 1459 | SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); |
1459 | 1460 | ||
@@ -1463,6 +1464,10 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1463 | 1464 | ||
1464 | ep = sctp_sk(sk)->ep; | 1465 | ep = sctp_sk(sk)->ep; |
1465 | 1466 | ||
1467 | /* Clean up any skbs sitting on the receive queue. */ | ||
1468 | data_was_unread = sctp_queue_purge_ulpevents(&sk->sk_receive_queue); | ||
1469 | data_was_unread += sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby); | ||
1470 | |||
1466 | /* Walk all associations on an endpoint. */ | 1471 | /* Walk all associations on an endpoint. */ |
1467 | list_for_each_safe(pos, temp, &ep->asocs) { | 1472 | list_for_each_safe(pos, temp, &ep->asocs) { |
1468 | asoc = list_entry(pos, struct sctp_association, asocs); | 1473 | asoc = list_entry(pos, struct sctp_association, asocs); |
@@ -1480,7 +1485,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1480 | } | 1485 | } |
1481 | } | 1486 | } |
1482 | 1487 | ||
1483 | if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { | 1488 | if (data_was_unread || !skb_queue_empty(&asoc->ulpq.lobby) || |
1489 | !skb_queue_empty(&asoc->ulpq.reasm) || | ||
1490 | (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)) { | ||
1484 | struct sctp_chunk *chunk; | 1491 | struct sctp_chunk *chunk; |
1485 | 1492 | ||
1486 | chunk = sctp_make_abort_user(asoc, NULL, 0); | 1493 | chunk = sctp_make_abort_user(asoc, NULL, 0); |
@@ -1490,10 +1497,6 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1490 | sctp_primitive_SHUTDOWN(asoc, NULL); | 1497 | sctp_primitive_SHUTDOWN(asoc, NULL); |
1491 | } | 1498 | } |
1492 | 1499 | ||
1493 | /* Clean up any skbs sitting on the receive queue. */ | ||
1494 | sctp_queue_purge_ulpevents(&sk->sk_receive_queue); | ||
1495 | sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby); | ||
1496 | |||
1497 | /* On a TCP-style socket, block for at most linger_time if set. */ | 1500 | /* On a TCP-style socket, block for at most linger_time if set. */ |
1498 | if (sctp_style(sk, TCP) && timeout) | 1501 | if (sctp_style(sk, TCP) && timeout) |
1499 | sctp_wait_for_close(sk, timeout); | 1502 | sctp_wait_for_close(sk, timeout); |
@@ -2143,10 +2146,33 @@ static int sctp_setsockopt_disable_fragments(struct sock *sk, | |||
2143 | static int sctp_setsockopt_events(struct sock *sk, char __user *optval, | 2146 | static int sctp_setsockopt_events(struct sock *sk, char __user *optval, |
2144 | unsigned int optlen) | 2147 | unsigned int optlen) |
2145 | { | 2148 | { |
2149 | struct sctp_association *asoc; | ||
2150 | struct sctp_ulpevent *event; | ||
2151 | |||
2146 | if (optlen > sizeof(struct sctp_event_subscribe)) | 2152 | if (optlen > sizeof(struct sctp_event_subscribe)) |
2147 | return -EINVAL; | 2153 | return -EINVAL; |
2148 | if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) | 2154 | if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) |
2149 | return -EFAULT; | 2155 | return -EFAULT; |
2156 | |||
2157 | /* | ||
2158 | * At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, | ||
2159 | * if there is no data to be sent or retransmit, the stack will | ||
2160 | * immediately send up this notification. | ||
2161 | */ | ||
2162 | if (sctp_ulpevent_type_enabled(SCTP_SENDER_DRY_EVENT, | ||
2163 | &sctp_sk(sk)->subscribe)) { | ||
2164 | asoc = sctp_id2assoc(sk, 0); | ||
2165 | |||
2166 | if (asoc && sctp_outq_is_empty(&asoc->outqueue)) { | ||
2167 | event = sctp_ulpevent_make_sender_dry_event(asoc, | ||
2168 | GFP_ATOMIC); | ||
2169 | if (!event) | ||
2170 | return -ENOMEM; | ||
2171 | |||
2172 | sctp_ulpq_tail_event(&asoc->ulpq, event); | ||
2173 | } | ||
2174 | } | ||
2175 | |||
2150 | return 0; | 2176 | return 0; |
2151 | } | 2177 | } |
2152 | 2178 | ||
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index e70e5fc87890..8a84017834c2 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -1081,9 +1081,19 @@ void sctp_ulpevent_free(struct sctp_ulpevent *event) | |||
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | /* Purge the skb lists holding ulpevents. */ | 1083 | /* Purge the skb lists holding ulpevents. */ |
1084 | void sctp_queue_purge_ulpevents(struct sk_buff_head *list) | 1084 | unsigned int sctp_queue_purge_ulpevents(struct sk_buff_head *list) |
1085 | { | 1085 | { |
1086 | struct sk_buff *skb; | 1086 | struct sk_buff *skb; |
1087 | while ((skb = skb_dequeue(list)) != NULL) | 1087 | unsigned int data_unread = 0; |
1088 | sctp_ulpevent_free(sctp_skb2event(skb)); | 1088 | |
1089 | while ((skb = skb_dequeue(list)) != NULL) { | ||
1090 | struct sctp_ulpevent *event = sctp_skb2event(skb); | ||
1091 | |||
1092 | if (!sctp_ulpevent_is_notification(event)) | ||
1093 | data_unread += skb->len; | ||
1094 | |||
1095 | sctp_ulpevent_free(event); | ||
1096 | } | ||
1097 | |||
1098 | return data_unread; | ||
1089 | } | 1099 | } |