sctp: fasthandoff with ASCONF at mobile-node
authorMichio Honda <micchie@sfc.wide.ad.jp>
Fri, 17 Jun 2011 02:03:23 +0000 (11:03 +0900)
committerDavid S. Miller <davem@davemloft.net>
Tue, 8 Nov 2011 20:11:29 +0000 (15:11 -0500)
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>
include/net/sctp/structs.h
net/sctp/sm_make_chunk.c
net/sctp/transport.c

index e90e7a9935ddc5c70c8e920487bc1196c2cc49e2..3382615bd7104156b7b7ef1dfe3765b5fe80a066 100644 (file)
@@ -1085,6 +1085,7 @@ void sctp_transport_burst_reset(struct sctp_transport *);
 unsigned long sctp_transport_timeout(struct sctp_transport *);
 void sctp_transport_reset(struct sctp_transport *);
 void sctp_transport_update_pmtu(struct sctp_transport *, u32);
+void sctp_transport_immediate_rtx(struct sctp_transport *);
 
 
 /* This is the structure we use to queue packets as they come into
index 0121e0ab035167d468c2976f17f210b2cb98a083..a85eeeb55dd0022e009895c53a6d8593929b7691 100644 (file)
@@ -3400,8 +3400,10 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
                asconf_len -= length;
        }
 
-       if (no_err && asoc->src_out_of_asoc_ok)
+       if (no_err && asoc->src_out_of_asoc_ok) {
                asoc->src_out_of_asoc_ok = 0;
+               sctp_transport_immediate_rtx(asoc->peer.primary_path);
+       }
 
        /* Free the cached last sent asconf chunk. */
        list_del_init(&asconf->transmitted_list);
index 394c57ca2f54210e4060654fb72f1937aee3bc75..3889330b7b04c06f33338be44bbf4effcf518827 100644 (file)
@@ -641,3 +641,19 @@ void sctp_transport_reset(struct sctp_transport *t)
        t->cacc.next_tsn_at_change = 0;
        t->cacc.cacc_saw_newack = 0;
 }
+
+/* Schedule retransmission on the given transport */
+void sctp_transport_immediate_rtx(struct sctp_transport *t)
+{
+       /* Stop pending T3_rtx_timer */
+       if (timer_pending(&t->T3_rtx_timer)) {
+               (void)del_timer(&t->T3_rtx_timer);
+               sctp_transport_put(t);
+       }
+       sctp_retransmit(&t->asoc->outqueue, t, SCTP_RTXR_T3_RTX);
+       if (!timer_pending(&t->T3_rtx_timer)) {
+               if (!mod_timer(&t->T3_rtx_timer, jiffies + t->rto))
+                       sctp_transport_hold(t);
+       }
+       return;
+}