sctp-hbAfterRto.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 /* HbAfterRto extension sends a heartbeat immediately after timeout
00036  * retransmission. The idea is to give the destinations a chance to get an
00037  * RTT measurement after their RTO is backed off. The hope is to avoid
00038  * unnecessarily large RTOs (especially on the alternate destinations).
00039  */
00040 
00041 #ifndef lint
00042 static const char rcsid[] =
00043 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/sctp/sctp-hbAfterRto.cc,v 1.3 2005/10/07 05:58:29 tomh Exp $ (UD/PEL)";
00044 #endif
00045 
00046 #include "ip.h"
00047 #include "sctp-hbAfterRto.h"
00048 #include "flags.h"
00049 #include "random.h"
00050 #include "template.h"
00051 
00052 #include "sctpDebug.h"
00053 
00054 #ifdef DMALLOC
00055 #include "dmalloc.h"
00056 #endif
00057 
00058 #define MIN(x,y)    (((x)<(y))?(x):(y))
00059 #define MAX(x,y)    (((x)>(y))?(x):(y))
00060 
00061 static class HbAfterRtoSctpClass : public TclClass 
00062 { 
00063 public:
00064   HbAfterRtoSctpClass() : TclClass("Agent/SCTP/HbAfterRto") {}
00065   TclObject* create(int, const char*const*) 
00066   {
00067     return (new HbAfterRtoSctpAgent());
00068   }
00069 } classSctpHbAfterRto;
00070 
00071 HbAfterRtoSctpAgent::HbAfterRtoSctpAgent() : SctpAgent()
00072 {
00073 }
00074 
00075 void HbAfterRtoSctpAgent::delay_bind_init_all()
00076 {
00077   SctpAgent::delay_bind_init_all();
00078 }
00079 
00080 int HbAfterRtoSctpAgent::delay_bind_dispatch(const char *cpVarName, 
00081                       const char *cpLocalName, 
00082                       TclObject *opTracer)
00083 {
00084   return SctpAgent::delay_bind_dispatch(cpVarName, cpLocalName, opTracer);
00085 }
00086 
00087 void HbAfterRtoSctpAgent::Timeout(SctpChunkType_E eChunkType, 
00088                   SctpDest_S *spDest)
00089 {
00090   DBG_I(Timeout);
00091   DBG_PL(Timeout, "eChunkType=%s spDest=%p"), 
00092     (eChunkType == SCTP_CHUNK_DATA) ? "DATA" : "HEARTBEAT",
00093     spDest
00094     DBG_PR;
00095 
00096   double dCurrTime = Scheduler::instance().clock();
00097 
00098   DBG_PL(Timeout, "dCurrTime=%f"), dCurrTime DBG_PR;
00099 
00100   if(eChunkType == SCTP_CHUNK_DATA)
00101     {
00102       spDest->eRtxTimerIsRunning = FALSE;
00103       
00104       /* section 7.2.3 of rfc2960 (w/ implementor's guide)
00105        */
00106       if(spDest->iCwnd > 1 * (int) uiMaxDataSize)
00107     {
00108       spDest->iSsthresh = MAX(spDest->iCwnd/2, 
00109                   iInitialCwnd * (int) uiMaxDataSize);
00110       spDest->iCwnd = 1*uiMaxDataSize;
00111       spDest->iPartialBytesAcked = 0; // reset
00112       tiCwnd++; // trigger changes for trace to pick up
00113     }
00114 
00115       spDest->opCwndDegradeTimer->force_cancel();
00116 
00117       /* Cancel any pending RTT measurement on this destination. Stephan
00118        * Baucke suggested (2004-04-27) this action as a fix for the
00119        * following simple scenario:
00120        *
00121        * - Host A sends packets 1, 2 and 3 to host B, and choses 3 for
00122        *   an RTT measurement
00123        *
00124        * - Host B receives all packets correctly and sends ACK1, ACK2,
00125        *   and ACK3.
00126        *
00127        * - ACK2 and ACK3 are lost on the return path
00128        *
00129        * - Eventually a timeout fires for packet 2, and A retransmits 2
00130        *
00131        * - Upon receipt of 2, B sends a cumulative ACK3 (since it has
00132        *   received 2 & 3 before)
00133        *
00134        * - Since packet 3 has never been retransmitted, the SCTP code
00135        *   actually accepts the ACK for an RTT measurement, although it
00136        *   was sent in reply to the retransmission of 2, which results
00137        *   in a much too high RTT estimate. Since this case tends to
00138        *   happen in case of longer link interruptions, the error is
00139        *   often amplified by subsequent timer backoffs.
00140        */
00141       spDest->eRtoPending = FALSE; // cancel any pending RTT measurement
00142     }
00143 
00144   DBG_PL(Timeout, "was spDest->dRto=%f"), spDest->dRto DBG_PR;
00145   spDest->dRto *= 2;    // back off the timer
00146   if(spDest->dRto > dMaxRto)
00147     spDest->dRto = dMaxRto;
00148   tdRto++;              // trigger changes for trace to pick up
00149   DBG_PL(Timeout, "now spDest->dRto=%f"), spDest->dRto DBG_PR;
00150 
00151   spDest->iTimeoutCount++;
00152   spDest->iErrorCount++; // @@@ window probe timeouts should not be counted
00153   DBG_PL(Timeout, "now spDest->iErrorCount=%d"), spDest->iErrorCount DBG_PR;
00154 
00155   if(spDest->eStatus == SCTP_DEST_STATUS_ACTIVE)
00156     {  
00157       iAssocErrorCount++;
00158       DBG_PL(Timeout, "now iAssocErrorCount=%d"), iAssocErrorCount DBG_PR;
00159 
00160       // Path.Max.Retrans exceeded?
00161       if(spDest->iErrorCount > (int) uiPathMaxRetrans) 
00162     {
00163       spDest->eStatus = SCTP_DEST_STATUS_INACTIVE;
00164       if(spDest == spNewTxDest)
00165         {
00166           spNewTxDest = GetNextDest(spDest);
00167           DBG_PL(Timeout, "failing over from %p to %p"),
00168         spDest, spNewTxDest DBG_PR;
00169         }
00170     }
00171       if(iAssocErrorCount > (int) uiAssociationMaxRetrans)
00172     {
00173       /* abruptly close the association!  (section 8.1)
00174        */
00175       DBG_PL(Timeout, "abruptly closing the association!") DBG_PR;
00176       Close();
00177       DBG_X(Timeout);
00178       return;
00179     }
00180     }
00181 
00182   // trace it!
00183   tiTimeoutCount++;
00184   tiErrorCount++;       
00185 
00186   if(spDest->iErrorCount > (int) uiChangePrimaryThresh &&
00187      spDest == spPrimaryDest)
00188     {
00189       spPrimaryDest = spNewTxDest;
00190       DBG_PL(Timeout, "changing primary from %p to %p"),
00191     spDest, spNewTxDest DBG_PR;
00192     }
00193 
00194   if(eChunkType == SCTP_CHUNK_DATA)
00195     {
00196       TimeoutRtx(spDest);
00197 
00198       // BEGIN -- HbAfterRto changes to this function
00199 
00200       /* If there is an active alternate destination, then send a HB
00201        * immediately to the destination which timed out.
00202        */
00203       if(GetNextDest(spDest) != spDest)
00204     SendHeartbeat(spDest);  
00205 
00206       // END -- HbAfterRto changes to this function
00207     }
00208   else if(eChunkType == SCTP_CHUNK_HB)
00209     {
00210       if(uiHeartbeatInterval != 0)
00211     SendHeartbeat(spDest);
00212     }
00213 
00214   DBG_X(Timeout);  
00215 }

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