Commit 506ab679 authored by Jon Grimm's avatar Jon Grimm Committed by Jon Grimm

[SCTP] Add SFR-CACC support. (Ardelle.Fan)

Submitted by Ardelle Fan.  Implementation of Split Fast Retransmit -
Changeover Aware Congestion Control.  Certain conditions involving
multihoming changover can result in TCP-unfriendliness.  This
implements the IETF proposed method of dealing with this corner
case.
parent d1256358
...@@ -804,9 +804,6 @@ struct sctp_transport { ...@@ -804,9 +804,6 @@ struct sctp_transport {
*/ */
int max_retrans; int max_retrans;
/* We use this name for debugging output... */
char *debug_name;
/* Per : A timer used by each destination. /* Per : A timer used by each destination.
* Destination : * Destination :
* Timer : * Timer :
...@@ -832,6 +829,35 @@ struct sctp_transport { ...@@ -832,6 +829,35 @@ struct sctp_transport {
struct list_head send_ready; struct list_head send_ready;
int malloced; /* Is this structure kfree()able? */ int malloced; /* Is this structure kfree()able? */
/* State information saved for SFR_CACC algorithm. The key
* idea in SFR_CACC is to maintain state at the sender on a
* per-destination basis when a changeover happens.
* char changeover_active;
* char cycling_changeover;
* __u32 next_tsn_at_change;
* char cacc_saw_newack;
*/
struct {
/* An unsigned integer, which stores the next TSN to be
* used by the sender, at the moment of changeover.
*/
__u32 next_tsn_at_change;
/* A flag which indicates the occurrence of a changeover */
char changeover_active;
/* A glag which indicates whether the change of primary is
* the first switch to this destination address during an
* active switch.
*/
char cycling_changeover;
/* A temporary flag, which is used during the processing of
* a SACK to estimate the causative TSN(s)'s group.
*/
char cacc_saw_newack;
} cacc;
}; };
struct sctp_transport *sctp_transport_new(const union sctp_addr *, int); struct sctp_transport *sctp_transport_new(const union sctp_addr *, int);
......
...@@ -256,7 +256,7 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc, ...@@ -256,7 +256,7 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
sctp_packet_transmit_chunk, sctp_packet_transmit_chunk,
sctp_packet_transmit); sctp_packet_transmit);
if (NULL == sctp_ulpq_init(&asoc->ulpq, asoc)) if (!sctp_ulpq_init(&asoc->ulpq, asoc))
goto fail_init; goto fail_init;
/* Set up the tsn tracking. */ /* Set up the tsn tracking. */
...@@ -266,7 +266,6 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc, ...@@ -266,7 +266,6 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
asoc->need_ecne = 0; asoc->need_ecne = 0;
asoc->debug_name = "unnamedasoc";
asoc->eyecatcher = SCTP_ASSOC_EYECATCHER; asoc->eyecatcher = SCTP_ASSOC_EYECATCHER;
/* Assume that peer would support both address types unless we are /* Assume that peer would support both address types unless we are
...@@ -380,6 +379,30 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, ...@@ -380,6 +379,30 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
*/ */
if (transport->active) if (transport->active)
asoc->peer.active_path = transport; asoc->peer.active_path = transport;
/*
* SFR-CACC algorithm:
* Upon the receipt of a request to change the primary
* destination address, on the data structure for the new
* primary destination, the sender MUST do the following:
*
* 1) If CHANGEOVER_ACTIVE is set, then there was a switch
* to this destination address earlier. The sender MUST set
* CYCLING_CHANGEOVER to indicate that this switch is a
* double switch to the same destination address.
*/
if (transport->cacc.changeover_active)
transport->cacc.cycling_changeover = 1;
/* 2) The sender MUST set CHANGEOVER_ACTIVE to indicate that
* a changeover has occurred.
*/
transport->cacc.changeover_active = 1;
/* 3) The sender MUST store the next TSN to be sent in
* next_tsn_at_change.
*/
transport->cacc.next_tsn_at_change = asoc->next_tsn;
} }
/* Add a transport address to an association. */ /* Add a transport address to an association. */
...@@ -479,7 +502,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, ...@@ -479,7 +502,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
/* If we do not yet have a primary path, set one. */ /* If we do not yet have a primary path, set one. */
if (NULL == asoc->peer.primary_path) { if (!asoc->peer.primary_path) {
sctp_assoc_set_primary(asoc, peer); sctp_assoc_set_primary(asoc, peer);
asoc->peer.retran_path = peer; asoc->peer.retran_path = peer;
} }
...@@ -592,7 +615,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, ...@@ -592,7 +615,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
/* If we failed to find a usable transport, just camp on the /* If we failed to find a usable transport, just camp on the
* primary, even if it is inactive. * primary, even if it is inactive.
*/ */
if (NULL == first) { if (!first) {
first = asoc->peer.primary_path; first = asoc->peer.primary_path;
second = asoc->peer.primary_path; second = asoc->peer.primary_path;
} }
......
This diff is collapsed.
...@@ -116,8 +116,6 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, ...@@ -116,8 +116,6 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->error_threshold = 0; peer->error_threshold = 0;
peer->error_count = 0; peer->error_count = 0;
peer->debug_name = "unnamedtransport";
INIT_LIST_HEAD(&peer->transmitted); INIT_LIST_HEAD(&peer->transmitted);
INIT_LIST_HEAD(&peer->send_ready); INIT_LIST_HEAD(&peer->send_ready);
INIT_LIST_HEAD(&peer->transports); INIT_LIST_HEAD(&peer->transports);
...@@ -137,6 +135,13 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, ...@@ -137,6 +135,13 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->dead = 0; peer->dead = 0;
peer->malloced = 0; peer->malloced = 0;
/* Initialize the state information for SFR-CACC */
peer->cacc.changeover_active = 0;
peer->cacc.cycling_changeover = 0;
peer->cacc.next_tsn_at_change = 0;
peer->cacc.cacc_saw_newack = 0;
return peer; return peer;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment