aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2009-08-26 09:36:25 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2009-09-04 18:20:58 -0400
commitb9f8478682445c2a3e0b87718a0563ef543ad94e (patch)
tree9bc0351c0a329a0780c6f2f7291e9207727de686
parentd71a09ed555e52299b5d3ad8945bdf84f65423a6 (diff)
sctp: Fix error count increments that were results of HEARTBEATS
SCTP RFC 4960 states that unacknowledged HEARTBEATS count as errors agains a given transport or endpoint. As such, we should increment the error counts for only for unacknowledged HB, otherwise we detect failure too soon. This goes for both the overall error count and the path error count. Now, there is a difference in how the detection is done between the two. The path error detection is done after the increment, so to detect it properly, we actually need to exceed the path threshold. The overall error detection is done _BEFORE_ the increment. Thus to detect the failure, it's enough for the error count to match the threshold. This is why all the state functions use '>=' to detect failure, while path detection uses '>'. Thanks goes to Chunbo Luo <chunbo.luo@windriver.com> who first proposed patches to fix this issue and made me re-read the spec and the code to figure out how this cruft really works. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
-rw-r--r--net/sctp/sm_sideeffect.c20
-rw-r--r--net/sctp/sm_statefuns.c2
2 files changed, 17 insertions, 5 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 238adf7978e9..694f7491731d 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,
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 7fb08a694917..45b8bcafd827 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -971,7 +971,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
971{ 971{
972 struct sctp_transport *transport = (struct sctp_transport *) arg; 972 struct sctp_transport *transport = (struct sctp_transport *) arg;
973 973
974 if (asoc->overall_error_count > asoc->max_retrans) { 974 if (asoc->overall_error_count >= asoc->max_retrans) {
975 sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 975 sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
976 SCTP_ERROR(ETIMEDOUT)); 976 SCTP_ERROR(ETIMEDOUT));
977 /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 977 /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */