diff options
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
| -rw-r--r-- | net/sctp/sm_sideeffect.c | 22 | 
1 files changed, 19 insertions, 3 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 534c2e5feb0..167c880cf8d 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,  	/* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of the  	 * HEARTBEAT should clear the error counter of the destination  	 * transport address to which the HEARTBEAT was sent. -	 * The association's overall error count is also cleared.  	 */  	t->error_count = 0; -	t->asoc->overall_error_count = 0; + +	/* +	 * Although RFC4960 specifies that the overall error count must +	 * be cleared when a HEARTBEAT ACK is received, we make an +	 * exception while in SHUTDOWN PENDING. If the peer keeps its +	 * window shut forever, we may never be able to transmit our +	 * outstanding data and rely on the retransmission limit be reached +	 * to shutdown the association. +	 */ +	if (t->asoc->state != SCTP_STATE_SHUTDOWN_PENDING) +		t->asoc->overall_error_count = 0;  	/* Clear the hb_sent flag to signal that we had a good  	 * acknowledgement. @@ -1201,7 +1210,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,  	int local_cork = 0;  	if (SCTP_EVENT_T_TIMEOUT != event_type) -		chunk = (struct sctp_chunk *) event_arg; +		chunk = event_arg;  	/* Note:  This whole file is a huge candidate for rework.  	 * For example, each command could either have its own handler, so @@ -1437,6 +1446,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,  			sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr);  			break; +		case SCTP_CMD_TIMER_START_ONCE: +			timer = &asoc->timers[cmd->obj.to]; + +			if (timer_pending(timer)) +				break; +			/* fall through */ +  		case SCTP_CMD_TIMER_START:  			timer = &asoc->timers[cmd->obj.to];  			timeout = asoc->timeouts[cmd->obj.to];  |