summaryrefslogtreecommitdiffstats
path: root/net/sctp/associola.c
diff options
context:
space:
mode:
authorSridhar Samudrala <sri@us.ibm.com>2006-07-21 14:48:50 -0700
committerDavid S. Miller <davem@davemloft.net>2006-07-21 14:48:50 -0700
commitad8fec1720e000ba2384de6408076a60fc92a981 (patch)
tree52fd2f7af583b95db6db369c6b3ea3d6adc26d69 /net/sctp/associola.c
parentcfdeef3282705a4b872d3559c4e7d2561251363c (diff)
downloadlinux-ad8fec1720e000ba2384de6408076a60fc92a981.tar.bz2
[SCTP]: Verify all the paths to a peer via heartbeat before using them.
This patch implements Path Initialization procedure as described in Sec 2.36 of RFC4460. Signed-off-by: Sridhar Samudrala <sri@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r--net/sctp/associola.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 9d05e13e92f6..27329ce9c311 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -441,7 +441,8 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
/* If the primary path is changing, assume that the
* user wants to use this new path.
*/
- if (transport->state != SCTP_INACTIVE)
+ if ((transport->state == SCTP_ACTIVE) ||
+ (transport->state == SCTP_UNKNOWN))
asoc->peer.active_path = transport;
/*
@@ -532,11 +533,11 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
port = addr->v4.sin_port;
SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
- " port: %d state:%s\n",
+ " port: %d state:%d\n",
asoc,
addr,
addr->v4.sin_port,
- peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
+ peer_state);
/* Set the port if it has not been set yet. */
if (0 == asoc->peer.port)
@@ -545,9 +546,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Check to see if this is a duplicate. */
peer = sctp_assoc_lookup_paddr(asoc, addr);
if (peer) {
- if (peer_state == SCTP_ACTIVE &&
- peer->state == SCTP_UNKNOWN)
- peer->state = SCTP_ACTIVE;
+ if (peer->state == SCTP_UNKNOWN) {
+ if (peer_state == SCTP_ACTIVE)
+ peer->state = SCTP_ACTIVE;
+ if (peer_state == SCTP_UNCONFIRMED)
+ peer->state = SCTP_UNCONFIRMED;
+ }
return peer;
}
@@ -739,7 +743,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport, transports);
- if (t->state == SCTP_INACTIVE)
+ if ((t->state == SCTP_INACTIVE) ||
+ (t->state == SCTP_UNCONFIRMED))
continue;
if (!first || t->last_time_heard > first->last_time_heard) {
second = first;
@@ -759,7 +764,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
* [If the primary is active but not most recent, bump the most
* recently used transport.]
*/
- if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
+ if (((asoc->peer.primary_path->state == SCTP_ACTIVE) ||
+ (asoc->peer.primary_path->state == SCTP_UNKNOWN)) &&
first != asoc->peer.primary_path) {
second = first;
first = asoc->peer.primary_path;
@@ -1054,7 +1060,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
transports);
if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
sctp_assoc_add_peer(asoc, &trans->ipaddr,
- GFP_ATOMIC, SCTP_ACTIVE);
+ GFP_ATOMIC, trans->state);
}
asoc->ctsn_ack_point = asoc->next_tsn - 1;
@@ -1094,7 +1100,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
/* Try to find an active transport. */
- if (t->state != SCTP_INACTIVE) {
+ if ((t->state == SCTP_ACTIVE) ||
+ (t->state == SCTP_UNKNOWN)) {
break;
} else {
/* Keep track of the next transport in case