diff options
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r-- | net/sctp/associola.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index b4cd2b71953f..024c3ebd9661 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -474,6 +474,15 @@ static void sctp_association_destroy(struct sctp_association *asoc) | |||
474 | void sctp_assoc_set_primary(struct sctp_association *asoc, | 474 | void sctp_assoc_set_primary(struct sctp_association *asoc, |
475 | struct sctp_transport *transport) | 475 | struct sctp_transport *transport) |
476 | { | 476 | { |
477 | int changeover = 0; | ||
478 | |||
479 | /* it's a changeover only if we already have a primary path | ||
480 | * that we are changing | ||
481 | */ | ||
482 | if (asoc->peer.primary_path != NULL && | ||
483 | asoc->peer.primary_path != transport) | ||
484 | changeover = 1 ; | ||
485 | |||
477 | asoc->peer.primary_path = transport; | 486 | asoc->peer.primary_path = transport; |
478 | 487 | ||
479 | /* Set a default msg_name for events. */ | 488 | /* Set a default msg_name for events. */ |
@@ -499,12 +508,12 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
499 | * double switch to the same destination address. | 508 | * double switch to the same destination address. |
500 | */ | 509 | */ |
501 | if (transport->cacc.changeover_active) | 510 | if (transport->cacc.changeover_active) |
502 | transport->cacc.cycling_changeover = 1; | 511 | transport->cacc.cycling_changeover = changeover; |
503 | 512 | ||
504 | /* 2) The sender MUST set CHANGEOVER_ACTIVE to indicate that | 513 | /* 2) The sender MUST set CHANGEOVER_ACTIVE to indicate that |
505 | * a changeover has occurred. | 514 | * a changeover has occurred. |
506 | */ | 515 | */ |
507 | transport->cacc.changeover_active = 1; | 516 | transport->cacc.changeover_active = changeover; |
508 | 517 | ||
509 | /* 3) The sender MUST store the next TSN to be sent in | 518 | /* 3) The sender MUST store the next TSN to be sent in |
510 | * next_tsn_at_change. | 519 | * next_tsn_at_change. |
@@ -1203,6 +1212,9 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1203 | struct list_head *head = &asoc->peer.transport_addr_list; | 1212 | struct list_head *head = &asoc->peer.transport_addr_list; |
1204 | struct list_head *pos; | 1213 | struct list_head *pos; |
1205 | 1214 | ||
1215 | if (asoc->peer.transport_count == 1) | ||
1216 | return; | ||
1217 | |||
1206 | /* Find the next transport in a round-robin fashion. */ | 1218 | /* Find the next transport in a round-robin fashion. */ |
1207 | t = asoc->peer.retran_path; | 1219 | t = asoc->peer.retran_path; |
1208 | pos = &t->transports; | 1220 | pos = &t->transports; |
@@ -1217,6 +1229,15 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1217 | 1229 | ||
1218 | t = list_entry(pos, struct sctp_transport, transports); | 1230 | t = list_entry(pos, struct sctp_transport, transports); |
1219 | 1231 | ||
1232 | /* We have exhausted the list, but didn't find any | ||
1233 | * other active transports. If so, use the next | ||
1234 | * transport. | ||
1235 | */ | ||
1236 | if (t == asoc->peer.retran_path) { | ||
1237 | t = next; | ||
1238 | break; | ||
1239 | } | ||
1240 | |||
1220 | /* Try to find an active transport. */ | 1241 | /* Try to find an active transport. */ |
1221 | 1242 | ||
1222 | if ((t->state == SCTP_ACTIVE) || | 1243 | if ((t->state == SCTP_ACTIVE) || |
@@ -1229,15 +1250,6 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1229 | if (!next) | 1250 | if (!next) |
1230 | next = t; | 1251 | next = t; |
1231 | } | 1252 | } |
1232 | |||
1233 | /* We have exhausted the list, but didn't find any | ||
1234 | * other active transports. If so, use the next | ||
1235 | * transport. | ||
1236 | */ | ||
1237 | if (t == asoc->peer.retran_path) { | ||
1238 | t = next; | ||
1239 | break; | ||
1240 | } | ||
1241 | } | 1253 | } |
1242 | 1254 | ||
1243 | asoc->peer.retran_path = t; | 1255 | asoc->peer.retran_path = t; |