diff options
| author | Michio Honda <micchie@sfc.wide.ad.jp> | 2011-06-16 22:03:23 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-11-08 15:11:29 -0500 |
| commit | ddc4bbee6ef1ed20314be3888dd39ceefe233e79 (patch) | |
| tree | d52c0d7e64e83dd8f17fd0340c3c62402c7cd7ce | |
| parent | 8ce120f11898c921329a5f618d01dcc1e8e69cac (diff) | |
sctp: fasthandoff with ASCONF at mobile-node
Fast retransmission after changing the last address
with ASCONF negotiation
Signed-off-by: Michio Honda <micchie@sfc.wide.ad.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/net/sctp/structs.h | 1 | ||||
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 4 | ||||
| -rw-r--r-- | net/sctp/transport.c | 16 |
3 files changed, 20 insertions, 1 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index e90e7a9935dd..3382615bd710 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -1085,6 +1085,7 @@ void sctp_transport_burst_reset(struct sctp_transport *); | |||
| 1085 | unsigned long sctp_transport_timeout(struct sctp_transport *); | 1085 | unsigned long sctp_transport_timeout(struct sctp_transport *); |
| 1086 | void sctp_transport_reset(struct sctp_transport *); | 1086 | void sctp_transport_reset(struct sctp_transport *); |
| 1087 | void sctp_transport_update_pmtu(struct sctp_transport *, u32); | 1087 | void sctp_transport_update_pmtu(struct sctp_transport *, u32); |
| 1088 | void sctp_transport_immediate_rtx(struct sctp_transport *); | ||
| 1088 | 1089 | ||
| 1089 | 1090 | ||
| 1090 | /* This is the structure we use to queue packets as they come into | 1091 | /* This is the structure we use to queue packets as they come into |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 0121e0ab0351..a85eeeb55dd0 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -3400,8 +3400,10 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, | |||
| 3400 | asconf_len -= length; | 3400 | asconf_len -= length; |
| 3401 | } | 3401 | } |
| 3402 | 3402 | ||
| 3403 | if (no_err && asoc->src_out_of_asoc_ok) | 3403 | if (no_err && asoc->src_out_of_asoc_ok) { |
| 3404 | asoc->src_out_of_asoc_ok = 0; | 3404 | asoc->src_out_of_asoc_ok = 0; |
| 3405 | sctp_transport_immediate_rtx(asoc->peer.primary_path); | ||
| 3406 | } | ||
| 3405 | 3407 | ||
| 3406 | /* Free the cached last sent asconf chunk. */ | 3408 | /* Free the cached last sent asconf chunk. */ |
| 3407 | list_del_init(&asconf->transmitted_list); | 3409 | list_del_init(&asconf->transmitted_list); |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 394c57ca2f54..3889330b7b04 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -641,3 +641,19 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
| 641 | t->cacc.next_tsn_at_change = 0; | 641 | t->cacc.next_tsn_at_change = 0; |
| 642 | t->cacc.cacc_saw_newack = 0; | 642 | t->cacc.cacc_saw_newack = 0; |
| 643 | } | 643 | } |
| 644 | |||
| 645 | /* Schedule retransmission on the given transport */ | ||
| 646 | void sctp_transport_immediate_rtx(struct sctp_transport *t) | ||
| 647 | { | ||
| 648 | /* Stop pending T3_rtx_timer */ | ||
| 649 | if (timer_pending(&t->T3_rtx_timer)) { | ||
| 650 | (void)del_timer(&t->T3_rtx_timer); | ||
| 651 | sctp_transport_put(t); | ||
| 652 | } | ||
| 653 | sctp_retransmit(&t->asoc->outqueue, t, SCTP_RTXR_T3_RTX); | ||
| 654 | if (!timer_pending(&t->T3_rtx_timer)) { | ||
| 655 | if (!mod_timer(&t->T3_rtx_timer, jiffies + t->rto)) | ||
| 656 | sctp_transport_hold(t); | ||
| 657 | } | ||
| 658 | return; | ||
| 659 | } | ||
