aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_sideeffect.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2012-07-21 03:56:07 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-22 15:13:46 -0400
commit5aa93bcf66f4af094d6f11096e81d5501a0b4ba5 (patch)
tree7bcf045fcae31a7e367e7eb1e0568b3702a25018 /net/sctp/sm_sideeffect.c
parente3906486f616da7cc086a3ba06c0df4e5a48b4ab (diff)
sctp: Implement quick failover draft from tsvwg
I've seen several attempts recently made to do quick failover of sctp transports by reducing various retransmit timers and counters. While its possible to implement a faster failover on multihomed sctp associations, its not particularly robust, in that it can lead to unneeded retransmits, as well as false connection failures due to intermittent latency on a network. Instead, lets implement the new ietf quick failover draft found here: http://tools.ietf.org/html/draft-nishida-tsvwg-sctp-failover-05 This will let the sctp stack identify transports that have had a small number of errors, and avoid using them quickly until their reliability can be re-established. I've tested this out on two virt guests connected via multiple isolated virt networks and believe its in compliance with the above draft and works well. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> CC: Vlad Yasevich <vyasevich@gmail.com> CC: Sridhar Samudrala <sri@us.ibm.com> CC: "David S. Miller" <davem@davemloft.net> CC: linux-sctp@vger.kernel.org CC: joe@perches.com Acked-by: Vlad Yasevich <vyasevich@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
-rw-r--r--net/sctp/sm_sideeffect.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 8716da1a8592..fe99628e1257 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -76,6 +76,8 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
76 sctp_cmd_seq_t *commands, 76 sctp_cmd_seq_t *commands,
77 gfp_t gfp); 77 gfp_t gfp);
78 78
79static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
80 struct sctp_transport *t);
79/******************************************************************** 81/********************************************************************
80 * Helper functions 82 * Helper functions
81 ********************************************************************/ 83 ********************************************************************/
@@ -470,7 +472,8 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = {
470 * notification SHOULD be sent to the upper layer. 472 * notification SHOULD be sent to the upper layer.
471 * 473 *
472 */ 474 */
473static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, 475static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
476 struct sctp_association *asoc,
474 struct sctp_transport *transport, 477 struct sctp_transport *transport,
475 int is_hb) 478 int is_hb)
476{ 479{
@@ -495,6 +498,23 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
495 transport->error_count++; 498 transport->error_count++;
496 } 499 }
497 500
501 /* If the transport error count is greater than the pf_retrans
502 * threshold, and less than pathmaxrtx, then mark this transport
503 * as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1,
504 * point 1
505 */
506 if ((transport->state != SCTP_PF) &&
507 (asoc->pf_retrans < transport->pathmaxrxt) &&
508 (transport->error_count > asoc->pf_retrans)) {
509
510 sctp_assoc_control_transport(asoc, transport,
511 SCTP_TRANSPORT_PF,
512 0);
513
514 /* Update the hb timer to resend a heartbeat every rto */
515 sctp_cmd_hb_timer_update(commands, transport);
516 }
517
498 if (transport->state != SCTP_INACTIVE && 518 if (transport->state != SCTP_INACTIVE &&
499 (transport->error_count > transport->pathmaxrxt)) { 519 (transport->error_count > transport->pathmaxrxt)) {
500 SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", 520 SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
@@ -699,6 +719,10 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
699 SCTP_HEARTBEAT_SUCCESS); 719 SCTP_HEARTBEAT_SUCCESS);
700 } 720 }
701 721
722 if (t->state == SCTP_PF)
723 sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
724 SCTP_HEARTBEAT_SUCCESS);
725
702 /* The receiver of the HEARTBEAT ACK should also perform an 726 /* The receiver of the HEARTBEAT ACK should also perform an
703 * RTT measurement for that destination transport address 727 * RTT measurement for that destination transport address
704 * using the time value carried in the HEARTBEAT ACK chunk. 728 * using the time value carried in the HEARTBEAT ACK chunk.
@@ -1565,8 +1589,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1565 1589
1566 case SCTP_CMD_STRIKE: 1590 case SCTP_CMD_STRIKE:
1567 /* Mark one strike against a transport. */ 1591 /* Mark one strike against a transport. */
1568 sctp_do_8_2_transport_strike(asoc, cmd->obj.transport, 1592 sctp_do_8_2_transport_strike(commands, asoc,
1569 0); 1593 cmd->obj.transport, 0);
1570 break; 1594 break;
1571 1595
1572 case SCTP_CMD_TRANSPORT_IDLE: 1596 case SCTP_CMD_TRANSPORT_IDLE:
@@ -1576,7 +1600,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1576 1600
1577 case SCTP_CMD_TRANSPORT_HB_SENT: 1601 case SCTP_CMD_TRANSPORT_HB_SENT:
1578 t = cmd->obj.transport; 1602 t = cmd->obj.transport;
1579 sctp_do_8_2_transport_strike(asoc, t, 1); 1603 sctp_do_8_2_transport_strike(commands, asoc,
1604 t, 1);
1580 t->hb_sent = 1; 1605 t->hb_sent = 1;
1581 break; 1606 break;
1582 1607