[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>
This commit is contained in:
committed by
David S. Miller
parent
cfdeef3282
commit
ad8fec1720
@ -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
|
||||
|
Reference in New Issue
Block a user