summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-09-08 22:00:26 +0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2008-10-01 19:34:16 +0400
commit96cd0d3d710e64c55e034b77052d7ac46f094759 (patch)
tree5b068bd865e07232574698a0404dacd1f218f54c
parent8190f89dfd09dae0c117fb0745f5a820bd19a5a4 (diff)
downloadlinux-96cd0d3d710e64c55e034b77052d7ac46f094759.tar.xz
sctp: enable cookie-echo retransmission transport switch
This patch enables cookie-echo retransmission transport switch feature. If COOKIE-ECHO retransmission happens, it will be sent to the address other than the one last sent to. Signed-off-by: Gui Jianfeng <guijianfeng@cn.fujitsu.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
-rw-r--r--net/sctp/sm_sideeffect.c78
-rw-r--r--net/sctp/sm_statefuns.c2
2 files changed, 46 insertions, 34 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 9732c797e8ed..13d9eea5cf1a 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -889,6 +889,35 @@ static void sctp_cmd_adaptation_ind(sctp_cmd_seq_t *commands,
sctp_ulpq_tail_event(&asoc->ulpq, ev);
}
+
+static void sctp_cmd_t1_timer_update(struct sctp_association *asoc,
+ sctp_event_timeout_t timer,
+ char *name)
+{
+ struct sctp_transport *t;
+
+ t = asoc->init_last_sent_to;
+ asoc->init_err_counter++;
+
+ if (t->init_sent_count > (asoc->init_cycle + 1)) {
+ asoc->timeouts[timer] *= 2;
+ if (asoc->timeouts[timer] > asoc->max_init_timeo) {
+ asoc->timeouts[timer] = asoc->max_init_timeo;
+ }
+ asoc->init_cycle++;
+ SCTP_DEBUG_PRINTK(
+ "T1 %s Timeout adjustment"
+ " init_err_counter: %d"
+ " cycle: %d"
+ " timeout: %ld\n",
+ name,
+ asoc->init_err_counter,
+ asoc->init_cycle,
+ asoc->timeouts[timer]);
+ }
+
+}
+
/* These three macros allow us to pull the debugging code out of the
* main flow of sctp_do_sm() to keep attention focused on the real
* functionality there.
@@ -1196,6 +1225,11 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(cmd->obj.ptr));
+ if (new_obj->transport) {
+ new_obj->transport->init_sent_count++;
+ asoc->init_last_sent_to = new_obj->transport;
+ }
+
/* FIXME - Eventually come up with a cleaner way to
* enabling COOKIE-ECHO + DATA bundling during
* multihoming stale cookie scenarios, the following
@@ -1345,26 +1379,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* all transports have been tried at the current
* timeout.
*/
- t = asoc->init_last_sent_to;
- asoc->init_err_counter++;
-
- if (t->init_sent_count > (asoc->init_cycle + 1)) {
- asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2;
- if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] >
- asoc->max_init_timeo) {
- asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
- asoc->max_init_timeo;
- }
- asoc->init_cycle++;
- SCTP_DEBUG_PRINTK(
- "T1 INIT Timeout adjustment"
- " init_err_counter: %d"
- " cycle: %d"
- " timeout: %ld\n",
- asoc->init_err_counter,
- asoc->init_cycle,
- asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
- }
+ sctp_cmd_t1_timer_update(asoc,
+ SCTP_EVENT_TIMEOUT_T1_INIT,
+ "INIT");
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
@@ -1377,20 +1394,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* all transports have been tried at the current
* timeout.
*/
- asoc->init_err_counter++;
-
- asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2;
- if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] >
- asoc->max_init_timeo) {
- asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
- asoc->max_init_timeo;
- }
- SCTP_DEBUG_PRINTK(
- "T1 COOKIE Timeout adjustment"
- " init_err_counter: %d"
- " timeout: %ld\n",
- asoc->init_err_counter,
- asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
+ sctp_cmd_t1_timer_update(asoc,
+ SCTP_EVENT_TIMEOUT_T1_COOKIE,
+ "COOKIE");
/* If we've sent any data bundled with
* COOKIE-ECHO we need to resend.
@@ -1422,6 +1428,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_INIT_COUNTER_RESET:
asoc->init_err_counter = 0;
asoc->init_cycle = 0;
+ list_for_each_entry(t, &asoc->peer.transport_addr_list,
+ transports) {
+ t->init_sent_count = 0;
+ }
break;
case SCTP_CMD_REPORT_DUP:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 81dfaee49b71..ea3a34cbe470 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -5307,6 +5307,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
if (!repl)
return SCTP_DISPOSITION_NOMEM;
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+ SCTP_CHUNK(repl));
/* Issue a sideeffect to do the needed accounting. */
sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));