aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2009-05-12 09:52:51 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2009-06-03 09:14:46 -0400
commit9919b455fc00c995ef8141848bdc0709ce50bf36 (patch)
treeec700e8a9fe3dd9f1ed841e22f96c06476d484fb
parentd48e074dfdada552fa53f5eab807540f352e0d5d (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.h6
-rw-r--r--net/sctp/associola.c42
-rw-r--r--net/sctp/sm_sideeffect.c8
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 *);
1939void sctp_association_put(struct sctp_association *); 1939void sctp_association_put(struct sctp_association *);
1940void sctp_association_hold(struct sctp_association *); 1940void sctp_association_hold(struct sctp_association *);
1941 1941
1942struct sctp_transport *sctp_assoc_choose_init_transport( 1942struct sctp_transport *sctp_assoc_choose_alter_transport(
1943 struct sctp_association *); 1943 struct sctp_association *, struct sctp_transport *);
1944struct sctp_transport *sctp_assoc_choose_shutdown_transport(
1945 struct sctp_association *);
1946void sctp_assoc_update_retran_path(struct sctp_association *); 1944void sctp_assoc_update_retran_path(struct sctp_association *);
1947struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, 1945struct 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. */
1288struct sctp_transport *sctp_assoc_choose_init_transport( 1288struct 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. */
1315struct 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++;