diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2009-05-12 09:52:51 -0400 |
---|---|---|
committer | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-06-03 09:14:46 -0400 |
commit | 9919b455fc00c995ef8141848bdc0709ce50bf36 (patch) | |
tree | ec700e8a9fe3dd9f1ed841e22f96c06476d484fb | |
parent | d48e074dfdada552fa53f5eab807540f352e0d5d (diff) |
sctp: fix to choose alternate destination when retransmit ASCONF chunk
RFC 5061 Section 5.1 ASCONF Chunk Procedures said:
B4) Re-transmit the ASCONF Chunk last sent and if possible choose an
alternate destination address (please refer to [RFC4960],
Section 6.4.1). An endpoint MUST NOT add new parameters to this
chunk; it MUST be the same (including its Sequence Number) as
the last ASCONF sent. An endpoint MAY, however, bundle an
additional ASCONF with new ASCONF parameters with the next
Sequence Number. For details, see Section 5.5.
This patch fix to choose an alternate destination address when
re-transmit the ASCONF chunk, with some dup codes cleanup.
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
-rw-r--r-- | include/net/sctp/structs.h | 6 | ||||
-rw-r--r-- | net/sctp/associola.c | 42 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 8 |
3 files changed, 14 insertions, 42 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 23f08fe1d50a..edfcacf3250e 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -1939,10 +1939,8 @@ void sctp_association_free(struct sctp_association *); | |||
1939 | void sctp_association_put(struct sctp_association *); | 1939 | void sctp_association_put(struct sctp_association *); |
1940 | void sctp_association_hold(struct sctp_association *); | 1940 | void sctp_association_hold(struct sctp_association *); |
1941 | 1941 | ||
1942 | struct sctp_transport *sctp_assoc_choose_init_transport( | 1942 | struct sctp_transport *sctp_assoc_choose_alter_transport( |
1943 | struct sctp_association *); | 1943 | struct sctp_association *, struct sctp_transport *); |
1944 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( | ||
1945 | struct sctp_association *); | ||
1946 | void sctp_assoc_update_retran_path(struct sctp_association *); | 1944 | void sctp_assoc_update_retran_path(struct sctp_association *); |
1947 | struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, | 1945 | struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, |
1948 | const union sctp_addr *); | 1946 | const union sctp_addr *); |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8d3aef9d0615..39f5166ae7af 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -1284,49 +1284,21 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1284 | ntohs(t->ipaddr.v4.sin_port)); | 1284 | ntohs(t->ipaddr.v4.sin_port)); |
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | /* Choose the transport for sending a INIT packet. */ | 1287 | /* Choose the transport for sending retransmit packet. */ |
1288 | struct sctp_transport *sctp_assoc_choose_init_transport( | 1288 | struct sctp_transport *sctp_assoc_choose_alter_transport( |
1289 | struct sctp_association *asoc) | 1289 | struct sctp_association *asoc, struct sctp_transport *last_sent_to) |
1290 | { | 1290 | { |
1291 | struct sctp_transport *t; | 1291 | /* If this is the first time packet is sent, use the active path, |
1292 | 1292 | * else use the retran path. If the last packet was sent over the | |
1293 | /* Use the retran path. If the last INIT was sent over the | ||
1294 | * retran path, update the retran path and use it. | 1293 | * retran path, update the retran path and use it. |
1295 | */ | 1294 | */ |
1296 | if (!asoc->init_last_sent_to) { | 1295 | if (!last_sent_to) |
1297 | t = asoc->peer.active_path; | ||
1298 | } else { | ||
1299 | if (asoc->init_last_sent_to == asoc->peer.retran_path) | ||
1300 | sctp_assoc_update_retran_path(asoc); | ||
1301 | t = asoc->peer.retran_path; | ||
1302 | } | ||
1303 | |||
1304 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
1305 | " %p addr: ", | ||
1306 | " port: %d\n", | ||
1307 | asoc, | ||
1308 | (&t->ipaddr), | ||
1309 | ntohs(t->ipaddr.v4.sin_port)); | ||
1310 | |||
1311 | return t; | ||
1312 | } | ||
1313 | |||
1314 | /* Choose the transport for sending a SHUTDOWN packet. */ | ||
1315 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( | ||
1316 | struct sctp_association *asoc) | ||
1317 | { | ||
1318 | /* If this is the first time SHUTDOWN is sent, use the active path, | ||
1319 | * else use the retran path. If the last SHUTDOWN was sent over the | ||
1320 | * retran path, update the retran path and use it. | ||
1321 | */ | ||
1322 | if (!asoc->shutdown_last_sent_to) | ||
1323 | return asoc->peer.active_path; | 1296 | return asoc->peer.active_path; |
1324 | else { | 1297 | else { |
1325 | if (asoc->shutdown_last_sent_to == asoc->peer.retran_path) | 1298 | if (last_sent_to == asoc->peer.retran_path) |
1326 | sctp_assoc_update_retran_path(asoc); | 1299 | sctp_assoc_update_retran_path(asoc); |
1327 | return asoc->peer.retran_path; | 1300 | return asoc->peer.retran_path; |
1328 | } | 1301 | } |
1329 | |||
1330 | } | 1302 | } |
1331 | 1303 | ||
1332 | /* Update the association's pmtu and frag_point by going through all the | 1304 | /* Update the association's pmtu and frag_point by going through all the |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index e2020eb2c8ca..86426aac1600 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -686,7 +686,8 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, | |||
686 | { | 686 | { |
687 | struct sctp_transport *t; | 687 | struct sctp_transport *t; |
688 | 688 | ||
689 | t = sctp_assoc_choose_shutdown_transport(asoc); | 689 | t = sctp_assoc_choose_alter_transport(asoc, |
690 | asoc->shutdown_last_sent_to); | ||
690 | asoc->shutdown_last_sent_to = t; | 691 | asoc->shutdown_last_sent_to = t; |
691 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; | 692 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; |
692 | chunk->transport = t; | 693 | chunk->transport = t; |
@@ -777,7 +778,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, | |||
777 | { | 778 | { |
778 | struct sctp_transport *t; | 779 | struct sctp_transport *t; |
779 | 780 | ||
780 | t = asoc->peer.active_path; | 781 | t = sctp_assoc_choose_alter_transport(asoc, chunk->transport); |
781 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; | 782 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; |
782 | chunk->transport = t; | 783 | chunk->transport = t; |
783 | } | 784 | } |
@@ -1379,7 +1380,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1379 | 1380 | ||
1380 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: | 1381 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: |
1381 | chunk = cmd->obj.ptr; | 1382 | chunk = cmd->obj.ptr; |
1382 | t = sctp_assoc_choose_init_transport(asoc); | 1383 | t = sctp_assoc_choose_alter_transport(asoc, |
1384 | asoc->init_last_sent_to); | ||
1383 | asoc->init_last_sent_to = t; | 1385 | asoc->init_last_sent_to = t; |
1384 | chunk->transport = t; | 1386 | chunk->transport = t; |
1385 | t->init_sent_count++; | 1387 | t->init_sent_count++; |