aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_sideeffect.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
-rw-r--r--net/sctp/sm_sideeffect.c56
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 */
950static 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;
1600nomem: 1640nomem:
1601 error = -ENOMEM; 1641 error = -ENOMEM;