Commit e418a672 authored by Sridhar Samudrala's avatar Sridhar Samudrala Committed by Sridhar Samudrala

[SCTP] Fix bugs in handling overlapping INIT and peer restart over a

multihomed association.
parent d3476cc6
...@@ -936,6 +936,9 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk) ...@@ -936,6 +936,9 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk)
void sctp_assoc_update(struct sctp_association *asoc, void sctp_assoc_update(struct sctp_association *asoc,
struct sctp_association *new) struct sctp_association *new)
{ {
struct sctp_transport *trans;
struct list_head *pos, *temp;
/* Copy in new parameters of peer. */ /* Copy in new parameters of peer. */
asoc->c = new->c; asoc->c = new->c;
asoc->peer.rwnd = new->peer.rwnd; asoc->peer.rwnd = new->peer.rwnd;
...@@ -944,20 +947,19 @@ void sctp_assoc_update(struct sctp_association *asoc, ...@@ -944,20 +947,19 @@ void sctp_assoc_update(struct sctp_association *asoc,
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE,
asoc->peer.i.initial_tsn); asoc->peer.i.initial_tsn);
/* FIXME: /* Remove any peer addresses not present in the new association. */
* Do we need to copy primary_path etc? list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
* trans = list_entry(pos, struct sctp_transport, transports);
* More explicitly, addresses may have been removed and if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr))
* this needs accounting for. sctp_assoc_del_peer(asoc, &trans->ipaddr);
*/ }
/* If the case is A (association restart), use /* If the case is A (association restart), use
* initial_tsn as next_tsn. If the case is B, use * initial_tsn as next_tsn. If the case is B, use
* current next_tsn in case data sent to peer * current next_tsn in case data sent to peer
* has been discarded and needs retransmission. * has been discarded and needs retransmission.
*/ */
if (sctp_state(asoc, ESTABLISHED)) { if (asoc->state >= SCTP_STATE_ESTABLISHED) {
asoc->next_tsn = new->next_tsn; asoc->next_tsn = new->next_tsn;
asoc->ctsn_ack_point = new->ctsn_ack_point; asoc->ctsn_ack_point = new->ctsn_ack_point;
asoc->adv_peer_ack_point = new->adv_peer_ack_point; asoc->adv_peer_ack_point = new->adv_peer_ack_point;
...@@ -968,6 +970,15 @@ void sctp_assoc_update(struct sctp_association *asoc, ...@@ -968,6 +970,15 @@ void sctp_assoc_update(struct sctp_association *asoc,
sctp_ssnmap_clear(asoc->ssnmap); sctp_ssnmap_clear(asoc->ssnmap);
} else { } else {
/* Add any peer addresses from the new association. */
list_for_each(pos, &new->peer.transport_addr_list) {
trans = list_entry(pos, struct sctp_transport,
transports);
if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
sctp_assoc_add_peer(asoc, &trans->ipaddr,
GFP_ATOMIC);
}
asoc->ctsn_ack_point = asoc->next_tsn - 1; asoc->ctsn_ack_point = asoc->next_tsn - 1;
asoc->adv_peer_ack_point = asoc->ctsn_ack_point; asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
if (!asoc->ssnmap) { if (!asoc->ssnmap) {
...@@ -976,7 +987,6 @@ void sctp_assoc_update(struct sctp_association *asoc, ...@@ -976,7 +987,6 @@ void sctp_assoc_update(struct sctp_association *asoc,
new->ssnmap = NULL; new->ssnmap = NULL;
} }
} }
} }
/* Update the retran path for sending a retransmitted packet. /* Update the retran path for sending a retransmitted packet.
......
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