diff options
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
-rw-r--r-- | net/sctp/sm_sideeffect.c | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 86426aac1600..8674d4919556 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -440,14 +440,26 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
440 | /* The check for association's overall error counter exceeding the | 440 | /* The check for association's overall error counter exceeding the |
441 | * threshold is done in the state function. | 441 | * threshold is done in the state function. |
442 | */ | 442 | */ |
443 | /* When probing UNCONFIRMED addresses, the association overall | 443 | /* We are here due to a timer expiration. If the timer was |
444 | * error count is NOT incremented | 444 | * not a HEARTBEAT, then normal error tracking is done. |
445 | * If the timer was a heartbeat, we only increment error counts | ||
446 | * when we already have an outstanding HEARTBEAT that has not | ||
447 | * been acknowledged. | ||
448 | * Additionaly, some tranport states inhibit error increments. | ||
445 | */ | 449 | */ |
446 | if (transport->state != SCTP_UNCONFIRMED) | 450 | if (!is_hb) { |
447 | asoc->overall_error_count++; | 451 | asoc->overall_error_count++; |
452 | if (transport->state != SCTP_INACTIVE) | ||
453 | transport->error_count++; | ||
454 | } else if (transport->hb_sent) { | ||
455 | if (transport->state != SCTP_UNCONFIRMED) | ||
456 | asoc->overall_error_count++; | ||
457 | if (transport->state != SCTP_INACTIVE) | ||
458 | transport->error_count++; | ||
459 | } | ||
448 | 460 | ||
449 | if (transport->state != SCTP_INACTIVE && | 461 | if (transport->state != SCTP_INACTIVE && |
450 | (transport->error_count++ >= transport->pathmaxrxt)) { | 462 | (transport->error_count > transport->pathmaxrxt)) { |
451 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", | 463 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", |
452 | " transport IP: port:%d failed.\n", | 464 | " transport IP: port:%d failed.\n", |
453 | asoc, | 465 | asoc, |
@@ -931,6 +943,27 @@ static void sctp_cmd_t1_timer_update(struct sctp_association *asoc, | |||
931 | 943 | ||
932 | } | 944 | } |
933 | 945 | ||
946 | /* Send the whole message, chunk by chunk, to the outqueue. | ||
947 | * This way the whole message is queued up and bundling if | ||
948 | * encouraged for small fragments. | ||
949 | */ | ||
950 | static int sctp_cmd_send_msg(struct sctp_association *asoc, | ||
951 | struct sctp_datamsg *msg) | ||
952 | { | ||
953 | struct sctp_chunk *chunk; | ||
954 | int error = 0; | ||
955 | |||
956 | list_for_each_entry(chunk, &msg->chunks, frag_list) { | ||
957 | error = sctp_outq_tail(&asoc->outqueue, chunk); | ||
958 | if (error) | ||
959 | break; | ||
960 | } | ||
961 | |||
962 | return error; | ||
963 | } | ||
964 | |||
965 | |||
966 | |||
934 | /* These three macros allow us to pull the debugging code out of the | 967 | /* These three macros allow us to pull the debugging code out of the |
935 | * main flow of sctp_do_sm() to keep attention focused on the real | 968 | * main flow of sctp_do_sm() to keep attention focused on the real |
936 | * functionality there. | 969 | * functionality there. |
@@ -1500,7 +1533,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1500 | case SCTP_CMD_PROCESS_CTSN: | 1533 | case SCTP_CMD_PROCESS_CTSN: |
1501 | /* Dummy up a SACK for processing. */ | 1534 | /* Dummy up a SACK for processing. */ |
1502 | sackh.cum_tsn_ack = cmd->obj.be32; | 1535 | sackh.cum_tsn_ack = cmd->obj.be32; |
1503 | sackh.a_rwnd = 0; | 1536 | sackh.a_rwnd = asoc->peer.rwnd + |
1537 | asoc->outqueue.outstanding_bytes; | ||
1504 | sackh.num_gap_ack_blocks = 0; | 1538 | sackh.num_gap_ack_blocks = 0; |
1505 | sackh.num_dup_tsns = 0; | 1539 | sackh.num_dup_tsns = 0; |
1506 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, | 1540 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, |
@@ -1575,7 +1609,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1575 | case SCTP_CMD_UPDATE_INITTAG: | 1609 | case SCTP_CMD_UPDATE_INITTAG: |
1576 | asoc->peer.i.init_tag = cmd->obj.u32; | 1610 | asoc->peer.i.init_tag = cmd->obj.u32; |
1577 | break; | 1611 | break; |
1578 | 1612 | case SCTP_CMD_SEND_MSG: | |
1613 | if (!asoc->outqueue.cork) { | ||
1614 | sctp_outq_cork(&asoc->outqueue); | ||
1615 | local_cork = 1; | ||
1616 | } | ||
1617 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); | ||
1618 | break; | ||
1579 | default: | 1619 | default: |
1580 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1620 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1581 | cmd->verb, cmd->obj.ptr); | 1621 | cmd->verb, cmd->obj.ptr); |
@@ -1593,9 +1633,9 @@ out: | |||
1593 | */ | 1633 | */ |
1594 | if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) { | 1634 | if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) { |
1595 | if (chunk->end_of_packet || chunk->singleton) | 1635 | if (chunk->end_of_packet || chunk->singleton) |
1596 | sctp_outq_uncork(&asoc->outqueue); | 1636 | error = sctp_outq_uncork(&asoc->outqueue); |
1597 | } else if (local_cork) | 1637 | } else if (local_cork) |
1598 | sctp_outq_uncork(&asoc->outqueue); | 1638 | error = sctp_outq_uncork(&asoc->outqueue); |
1599 | return error; | 1639 | return error; |
1600 | nomem: | 1640 | nomem: |
1601 | error = -ENOMEM; | 1641 | error = -ENOMEM; |