sctp-mfrHbAfterRto.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 by the Protocol Engineering Lab, U of Delaware
00003  * All rights reserved.
00004  *
00005  * Armando L. Caro Jr. <acaro@@cis,udel,edu>
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  *
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  *
00018  * 3. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00035 /* This extension combines MultipleFastRtx and HbAfterRto extensions.
00036  *
00037  * MultipleFastRtx extension implements the Caro Multiple Fast Retransmit
00038  * Algorithm. Caro's Algorithm introduces a fastRtxRecover state variable
00039  * per TSN in the send buffer. Any time a TSN is retransmitted, its
00040  * fastRtxRecover is set to the highest TSN outstanding at the time of
00041  * retransmit. That way, only missing reports triggered by TSNs beyond
00042  * fastRtxRecover may trigger yet another fast retransmit.
00043  *
00044  * HbAfterRto extension sends a heartbeat immediately after timeout
00045  * retransmission. The idea is to give the destinations a chance to get an
00046  * RTT measurement after their RTO is backed off. The hope is to avoid
00047  * unnecessarily large RTOs (especially on the alternate destinations).
00048  */
00049 
00050 #ifndef lint
00051 static const char rcsid[] =
00052 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/sctp/sctp-mfrHbAfterRto.cc,v 1.1 2005/10/07 06:14:37 tomh Exp $ (UD/PEL)";
00053 #endif
00054 
00055 #include "ip.h"
00056 #include "sctp-mfrHbAfterRto.h"
00057 #include "flags.h"
00058 #include "random.h"
00059 #include "template.h"
00060 
00061 #include "sctpDebug.h"
00062 
00063 #ifdef DMALLOC
00064 #include "dmalloc.h"
00065 #endif
00066 
00067 #define MIN(x,y)    (((x)<(y))?(x):(y))
00068 #define MAX(x,y)    (((x)>(y))?(x):(y))
00069 
00070 static class MfrHbAfterRtoSctpClass : public TclClass 
00071 { 
00072 public:
00073   MfrHbAfterRtoSctpClass() : TclClass("Agent/SCTP/MfrHbAfterRto") {}
00074   TclObject* create(int, const char*const*) 
00075   {
00076     return (new MfrHbAfterRtoSctpAgent());
00077   }
00078 } classSctpMfrHbAfterRto;
00079 
00080 MfrHbAfterRtoSctpAgent::MfrHbAfterRtoSctpAgent() : MultipleFastRtxSctpAgent()
00081 {
00082 }
00083 
00084 void MfrHbAfterRtoSctpAgent::delay_bind_init_all()
00085 {
00086   MultipleFastRtxSctpAgent::delay_bind_init_all();
00087 }
00088 
00089 int MfrHbAfterRtoSctpAgent::delay_bind_dispatch(const char *cpVarName, 
00090                         const char *cpLocalName, 
00091                         TclObject *opTracer)
00092 {
00093   return MultipleFastRtxSctpAgent::delay_bind_dispatch(cpVarName, 
00094                                cpLocalName, opTracer);
00095 }
00096 
00097 void MfrHbAfterRtoSctpAgent::Timeout(SctpChunkType_E eChunkType, 
00098                      SctpDest_S *spDest)
00099 {
00100   DBG_I(Timeout);
00101   DBG_PL(Timeout, "eChunkType=%s spDest=%p"), 
00102     (eChunkType == SCTP_CHUNK_DATA) ? "DATA" : "HEARTBEAT",
00103     spDest
00104     DBG_PR;
00105 
00106   double dCurrTime = Scheduler::instance().clock();
00107 
00108   DBG_PL(Timeout, "dCurrTime=%f"), dCurrTime DBG_PR;
00109 
00110   if(eChunkType == SCTP_CHUNK_DATA)
00111     {
00112       spDest->eRtxTimerIsRunning = FALSE;
00113       
00114       /* section 7.2.3 of rfc2960 (w/ implementor's guide)
00115        */
00116       if(spDest->iCwnd > 1 * (int) uiMaxDataSize)
00117     {
00118       spDest->iSsthresh = MAX(spDest->iCwnd/2, 
00119                   iInitialCwnd * (int) uiMaxDataSize);
00120       spDest->iCwnd = 1*uiMaxDataSize;
00121       spDest->iPartialBytesAcked = 0; // reset
00122       tiCwnd++; // trigger changes for trace to pick up
00123     }
00124 
00125       spDest->opCwndDegradeTimer->force_cancel();
00126 
00127       /* Cancel any pending RTT measurement on this destination. Stephan
00128        * Baucke suggested (2004-04-27) this action as a fix for the
00129        * following simple scenario:
00130        *
00131        * - Host A sends packets 1, 2 and 3 to host B, and choses 3 for
00132        *   an RTT measurement
00133        *
00134        * - Host B receives all packets correctly and sends ACK1, ACK2,
00135        *   and ACK3.
00136        *
00137        * - ACK2 and ACK3 are lost on the return path
00138        *
00139        * - Eventually a timeout fires for packet 2, and A retransmits 2
00140        *
00141        * - Upon receipt of 2, B sends a cumulative ACK3 (since it has
00142        *   received 2 & 3 before)
00143        *
00144        * - Since packet 3 has never been retransmitted, the SCTP code
00145        *   actually accepts the ACK for an RTT measurement, although it
00146        *   was sent in reply to the retransmission of 2, which results
00147        *   in a much too high RTT estimate. Since this case tends to
00148        *   happen in case of longer link interruptions, the error is
00149        *   often amplified by subsequent timer backoffs.
00150        */
00151       spDest->eRtoPending = FALSE; // cancel any pending RTT measurement
00152     }
00153 
00154   DBG_PL(Timeout, "was spDest->dRto=%f"), spDest->dRto DBG_PR;
00155   spDest->dRto *= 2;    // back off the timer
00156   if(spDest->dRto > dMaxRto)
00157     spDest->dRto = dMaxRto;
00158   tdRto++;              // trigger changes for trace to pick up
00159   DBG_PL(Timeout, "now spDest->dRto=%f"), spDest->dRto DBG_PR;
00160 
00161   spDest->iTimeoutCount++;
00162   spDest->iErrorCount++; // @@@ window probe timeouts should not be counted
00163   DBG_PL(Timeout, "now spDest->iErrorCount=%d"), spDest->iErrorCount DBG_PR;
00164 
00165   if(spDest->eStatus == SCTP_DEST_STATUS_ACTIVE)
00166     {  
00167       iAssocErrorCount++;
00168       DBG_PL(Timeout, "now iAssocErrorCount=%d"), iAssocErrorCount DBG_PR;
00169 
00170        // Path.Max.Retrans exceeded?
00171       if(spDest->iErrorCount > (int) uiPathMaxRetrans)
00172     {
00173       spDest->eStatus = SCTP_DEST_STATUS_INACTIVE;
00174       if(spDest == spNewTxDest)
00175         {
00176           spNewTxDest = GetNextDest(spDest);
00177           DBG_PL(Timeout, "failing over from %p to %p"),
00178         spDest, spNewTxDest DBG_PR;
00179         }
00180     }
00181       if(iAssocErrorCount > (int) uiAssociationMaxRetrans)
00182     {
00183       /* abruptly close the association!  (section 8.1)
00184        */
00185       DBG_PL(Timeout, "abruptly closing the association!") DBG_PR;
00186       Close();
00187       DBG_X(Timeout);
00188       return;
00189     }
00190     }
00191 
00192   // trace it!
00193   tiTimeoutCount++;
00194   tiErrorCount++;       
00195 
00196   if(spDest->iErrorCount > (int) uiChangePrimaryThresh &&
00197      spDest == spPrimaryDest)
00198     {
00199       spPrimaryDest = spNewTxDest;
00200       DBG_PL(Timeout, "changing primary from %p to %p"),
00201     spDest, spNewTxDest DBG_PR;
00202     }
00203 
00204   if(eChunkType == SCTP_CHUNK_DATA)
00205     {
00206       TimeoutRtx(spDest);
00207 
00208       // BEGIN -- HbAfterRto changes to this function
00209 
00210       /* If there is an active alternate destination, then send a HB
00211        * immediately to the destination which timed out.
00212        */
00213       if(GetNextDest(spDest) != spDest)
00214     SendHeartbeat(spDest);  
00215 
00216       // END -- HbAfterRto changes to this function
00217     }
00218   else if(eChunkType == SCTP_CHUNK_HB)
00219     {
00220       if(uiHeartbeatInterval != 0)
00221     SendHeartbeat(spDest);
00222     }
00223 
00224   DBG_X(Timeout);  
00225 }

Generated on Tue Mar 6 16:47:50 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6