ccc.cpp

00001 /*****************************************************************************
00002 Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are
00007 met:
00008 
00009 * Redistributions of source code must retain the above
00010   copyright notice, this list of conditions and the
00011   following disclaimer.
00012 
00013 * Redistributions in binary form must reproduce the
00014   above copyright notice, this list of conditions
00015   and the following disclaimer in the documentation
00016   and/or other materials provided with the distribution.
00017 
00018 * Neither the name of the University of Illinois
00019   nor the names of its contributors may be used to
00020   endorse or promote products derived from this
00021   software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00024 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
00025 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00026 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00027 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00028 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00029 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00030 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00031 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00032 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00033 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 *****************************************************************************/
00035 
00036 /*****************************************************************************
00037 written by
00038    Yunhong Gu, last updated 02/28/2012
00039 *****************************************************************************/
00040 
00041 
00042 #include "core.h"
00043 #include "ccc.h"
00044 #include <cmath>
00045 #include <cstring>
00046 
00047 CCC::CCC():
00048 m_iSYNInterval(CUDT::m_iSYNInterval),
00049 m_dPktSndPeriod(1.0),
00050 m_dCWndSize(16.0),
00051 m_iBandwidth(),
00052 m_dMaxCWndSize(),
00053 m_iMSS(),
00054 m_iSndCurrSeqNo(),
00055 m_iRcvRate(),
00056 m_iRTT(),
00057 m_pcParam(NULL),
00058 m_iPSize(0),
00059 m_UDT(),
00060 m_iACKPeriod(0),
00061 m_iACKInterval(0),
00062 m_bUserDefinedRTO(false),
00063 m_iRTO(-1),
00064 m_PerfInfo()
00065 {
00066 }
00067 
00068 CCC::~CCC()
00069 {
00070    delete [] m_pcParam;
00071 }
00072 
00073 void CCC::setACKTimer(int msINT)
00074 {
00075    m_iACKPeriod = msINT > m_iSYNInterval ? m_iSYNInterval : msINT;
00076 }
00077 
00078 void CCC::setACKInterval(int pktINT)
00079 {
00080    m_iACKInterval = pktINT;
00081 }
00082 
00083 void CCC::setRTO(int usRTO)
00084 {
00085    m_bUserDefinedRTO = true;
00086    m_iRTO = usRTO;
00087 }
00088 
00089 void CCC::sendCustomMsg(CPacket& pkt) const
00090 {
00091    CUDT* u = CUDT::getUDTHandle(m_UDT);
00092 
00093    if (NULL != u)
00094    {
00095       pkt.m_iID = u->m_PeerID;
00096       u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt);
00097    }
00098 }
00099 
00100 const CPerfMon* CCC::getPerfInfo()
00101 {
00102    try
00103    {
00104       CUDT* u = CUDT::getUDTHandle(m_UDT);
00105       if (NULL != u)
00106          u->sample(&m_PerfInfo, false);
00107    }
00108    catch (...)
00109    {
00110       return NULL;
00111    }
00112 
00113    return &m_PerfInfo;
00114 }
00115 
00116 void CCC::setMSS(int mss)
00117 {
00118    m_iMSS = mss;
00119 }
00120 
00121 void CCC::setBandwidth(int bw)
00122 {
00123    m_iBandwidth = bw;
00124 }
00125 
00126 void CCC::setSndCurrSeqNo(int32_t seqno)
00127 {
00128    m_iSndCurrSeqNo = seqno;
00129 }
00130 
00131 void CCC::setRcvRate(int rcvrate)
00132 {
00133    m_iRcvRate = rcvrate;
00134 }
00135 
00136 void CCC::setMaxCWndSize(int cwnd)
00137 {
00138    m_dMaxCWndSize = cwnd;
00139 }
00140 
00141 void CCC::setRTT(int rtt)
00142 {
00143    m_iRTT = rtt;
00144 }
00145 
00146 void CCC::setUserParam(const char* param, int size)
00147 {
00148    delete [] m_pcParam;
00149    m_pcParam = new char[size];
00150    memcpy(m_pcParam, param, size);
00151    m_iPSize = size;
00152 }
00153 
00154 //
00155 CUDTCC::CUDTCC():
00156 m_iRCInterval(),
00157 m_LastRCTime(),
00158 m_bSlowStart(),
00159 m_iLastAck(),
00160 m_bLoss(),
00161 m_iLastDecSeq(),
00162 m_dLastDecPeriod(),
00163 m_iNAKCount(),
00164 m_iDecRandom(),
00165 m_iAvgNAKNum(),
00166 m_iDecCount()
00167 {
00168 }
00169 
00170 void CUDTCC::init()
00171 {
00172    m_iRCInterval = m_iSYNInterval;
00173    m_LastRCTime = CTimer::getTime();
00174    setACKTimer(m_iRCInterval);
00175 
00176    m_bSlowStart = true;
00177    m_iLastAck = m_iSndCurrSeqNo;
00178    m_bLoss = false;
00179    m_iLastDecSeq = CSeqNo::decseq(m_iLastAck);
00180    m_dLastDecPeriod = 1;
00181    m_iAvgNAKNum = 0;
00182    m_iNAKCount = 0;
00183    m_iDecRandom = 1;
00184 
00185    m_dCWndSize = 16;
00186    m_dPktSndPeriod = 1;
00187 }
00188 
00189 void CUDTCC::onACK(int32_t ack)
00190 {
00191    int64_t B = 0;
00192    double inc = 0;
00193    // Note: 1/24/2012
00194    // The minimum increase parameter is increased from "1.0 / m_iMSS" to 0.01
00195    // because the original was too small and caused sending rate to stay at low level
00196    // for long time.
00197    const double min_inc = 0.01;
00198 
00199    uint64_t currtime = CTimer::getTime();
00200    if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval)
00201       return;
00202 
00203    m_LastRCTime = currtime;
00204 
00205    if (m_bSlowStart)
00206    {
00207       m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack);
00208       m_iLastAck = ack;
00209 
00210       if (m_dCWndSize > m_dMaxCWndSize)
00211       {
00212          m_bSlowStart = false;
00213          if (m_iRcvRate > 0)
00214             m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
00215          else
00216             m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
00217       }
00218    }
00219    else
00220       m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16;
00221 
00222    // During Slow Start, no rate increase
00223    if (m_bSlowStart)
00224       return;
00225 
00226    if (m_bLoss)
00227    {
00228       m_bLoss = false;
00229       return;
00230    }
00231 
00232    B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod);
00233    if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B))
00234       B = m_iBandwidth / 9;
00235    if (B <= 0)
00236       inc = min_inc;
00237    else
00238    {
00239       // inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS)
00240       // Beta = 1.5 * 10^(-6)
00241 
00242       inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS;
00243 
00244       if (inc < min_inc)
00245          inc = min_inc;
00246    }
00247 
00248    m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc + m_iRCInterval);
00249 }
00250 
00251 void CUDTCC::onLoss(const int32_t* losslist, int)
00252 {
00253    //Slow Start stopped, if it hasn't yet
00254    if (m_bSlowStart)
00255    {
00256       m_bSlowStart = false;
00257       if (m_iRcvRate > 0)
00258       {
00259          // Set the sending rate to the receiving rate.
00260          m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
00261          return;
00262       }
00263       // If no receiving rate is observed, we have to compute the sending
00264       // rate according to the current window size, and decrease it
00265       // using the method below.
00266       m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
00267    }
00268 
00269    m_bLoss = true;
00270 
00271    if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0)
00272    {
00273       m_dLastDecPeriod = m_dPktSndPeriod;
00274       m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
00275 
00276       m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125);
00277       m_iNAKCount = 1;
00278       m_iDecCount = 1;
00279 
00280       m_iLastDecSeq = m_iSndCurrSeqNo;
00281 
00282       // remove global synchronization using randomization
00283       srand(m_iLastDecSeq);
00284       m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX));
00285       if (m_iDecRandom < 1)
00286          m_iDecRandom = 1;
00287    }
00288    else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom)))
00289    {
00290       // 0.875^5 = 0.51, rate should not be decreased by more than half within a congestion period
00291       m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125);
00292       m_iLastDecSeq = m_iSndCurrSeqNo;
00293    }
00294 }
00295 
00296 void CUDTCC::onTimeout()
00297 {
00298    if (m_bSlowStart)
00299    {
00300       m_bSlowStart = false;
00301       if (m_iRcvRate > 0)
00302          m_dPktSndPeriod = 1000000.0 / m_iRcvRate;
00303       else
00304          m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval);
00305    }
00306    else
00307    {
00308       /*
00309       m_dLastDecPeriod = m_dPktSndPeriod;
00310       m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2);
00311       m_iLastDecSeq = m_iLastAck;
00312       */
00313    }
00314 }

Generated on 9 Feb 2013 for barchart-udt-core-2.2.2 by  doxygen 1.6.1