Skip to content

Commit

Permalink
[SCTP]: Reset some transport and association variables on restart
Browse files Browse the repository at this point in the history
If the association has been restarted, we need to reset the
transport congestion variables as well as accumulated error
counts and CACC variables.  If we do not, the association
will use the wrong values and may terminate prematurely.

This was found with a scenario where the peer restarted
the association when lksctp was in the last HB timeout for
its association.  The restart happened, but the error counts
have not been reset and when the timeout occurred, a newly
restarted association was terminated due to excessive
retransmits.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vlad Yasevich authored and David S. Miller committed Mar 20, 2007
1 parent fb78525 commit 749bf92
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,7 @@ void sctp_transport_update_rto(struct sctp_transport *, __u32);
void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
unsigned long sctp_transport_timeout(struct sctp_transport *);
void sctp_transport_reset(struct sctp_transport *);


/* This is the structure we use to queue packets as they come into
Expand Down
9 changes: 9 additions & 0 deletions net/sctp/associola.c
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,9 @@ void sctp_assoc_update(struct sctp_association *asoc,
trans = list_entry(pos, struct sctp_transport, transports);
if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr))
sctp_assoc_del_peer(asoc, &trans->ipaddr);

if (asoc->state >= SCTP_STATE_ESTABLISHED)
sctp_transport_reset(trans);
}

/* If the case is A (association restart), use
Expand All @@ -1069,6 +1072,12 @@ void sctp_assoc_update(struct sctp_association *asoc,
*/
sctp_ulpq_flush(&asoc->ulpq);

/* reset the overall association error count so
* that the restarted association doesn't get torn
* down on the next retransmission timer.
*/
asoc->overall_error_count = 0;

} else {
/* Add any peer addresses from the new association. */
list_for_each(pos, &new->peer.transport_addr_list) {
Expand Down
32 changes: 32 additions & 0 deletions net/sctp/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,3 +526,35 @@ unsigned long sctp_transport_timeout(struct sctp_transport *t)
timeout += jiffies;
return timeout;
}

/* Reset transport variables to their initial values */
void sctp_transport_reset(struct sctp_transport *t)
{
struct sctp_association *asoc = t->asoc;

/* RFC 2960 (bis), Section 5.2.4
* All the congestion control parameters (e.g., cwnd, ssthresh)
* related to this peer MUST be reset to their initial values
* (see Section 6.2.1)
*/
t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
t->ssthresh = SCTP_DEFAULT_MAXWINDOW;
t->rto = asoc->rto_initial;
t->rtt = 0;
t->srtt = 0;
t->rttvar = 0;

/* Reset these additional varibles so that we have a clean
* slate.
*/
t->partial_bytes_acked = 0;
t->flight_size = 0;
t->error_count = 0;
t->rto_pending = 0;

/* Initialize the state information for SFR-CACC */
t->cacc.changeover_active = 0;
t->cacc.cycling_changeover = 0;
t->cacc.next_tsn_at_change = 0;
t->cacc.cacc_saw_newack = 0;
}

0 comments on commit 749bf92

Please sign in to comment.