window.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 01/22/2011
00039 *****************************************************************************/
00040 
00041 #include <cmath>
00042 #include "common.h"
00043 #include "window.h"
00044 #include <algorithm>
00045 
00046 using namespace std;
00047 
00048 CACKWindow::CACKWindow(int size):
00049 m_piACKSeqNo(NULL),
00050 m_piACK(NULL),
00051 m_pTimeStamp(NULL),
00052 m_iSize(size),
00053 m_iHead(0),
00054 m_iTail(0)
00055 {
00056    m_piACKSeqNo = new int32_t[m_iSize];
00057    m_piACK = new int32_t[m_iSize];
00058    m_pTimeStamp = new uint64_t[m_iSize];
00059 
00060    m_piACKSeqNo[0] = -1;
00061 }
00062 
00063 CACKWindow::~CACKWindow()
00064 {
00065    delete [] m_piACKSeqNo;
00066    delete [] m_piACK;
00067    delete [] m_pTimeStamp;
00068 }
00069 
00070 void CACKWindow::store(int32_t seq, int32_t ack)
00071 {
00072    m_piACKSeqNo[m_iHead] = seq;
00073    m_piACK[m_iHead] = ack;
00074    m_pTimeStamp[m_iHead] = CTimer::getTime();
00075 
00076    m_iHead = (m_iHead + 1) % m_iSize;
00077 
00078    // overwrite the oldest ACK since it is not likely to be acknowledged
00079    if (m_iHead == m_iTail)
00080       m_iTail = (m_iTail + 1) % m_iSize;
00081 }
00082 
00083 int CACKWindow::acknowledge(int32_t seq, int32_t& ack)
00084 {
00085    if (m_iHead >= m_iTail)
00086    {
00087       // Head has not exceeded the physical boundary of the window
00088 
00089       for (int i = m_iTail, n = m_iHead; i < n; ++ i)
00090       {
00091          // looking for indentical ACK Seq. No.
00092          if (seq == m_piACKSeqNo[i])
00093          {
00094             // return the Data ACK it carried
00095             ack = m_piACK[i];
00096 
00097             // calculate RTT
00098             int rtt = int(CTimer::getTime() - m_pTimeStamp[i]);
00099 
00100             if (i + 1 == m_iHead)
00101             {
00102                m_iTail = m_iHead = 0;
00103                m_piACKSeqNo[0] = -1;
00104             }
00105             else
00106                m_iTail = (i + 1) % m_iSize;
00107 
00108             return rtt;
00109          }
00110       }
00111 
00112       // Bad input, the ACK node has been overwritten
00113       return -1;
00114    }
00115 
00116    // Head has exceeded the physical window boundary, so it is behind tail
00117    for (int j = m_iTail, n = m_iHead + m_iSize; j < n; ++ j)
00118    {
00119       // looking for indentical ACK seq. no.
00120       if (seq == m_piACKSeqNo[j % m_iSize])
00121       {
00122          // return Data ACK
00123          j %= m_iSize;
00124          ack = m_piACK[j];
00125 
00126          // calculate RTT
00127          int rtt = int(CTimer::getTime() - m_pTimeStamp[j]);
00128 
00129          if (j == m_iHead)
00130          {
00131             m_iTail = m_iHead = 0;
00132             m_piACKSeqNo[0] = -1;
00133          }
00134          else
00135             m_iTail = (j + 1) % m_iSize;
00136 
00137          return rtt;
00138       }
00139    }
00140 
00141    // bad input, the ACK node has been overwritten
00142    return -1;
00143 }
00144 
00146 
00147 CPktTimeWindow::CPktTimeWindow(int asize, int psize):
00148 m_iAWSize(asize),
00149 m_piPktWindow(NULL),
00150 m_iPktWindowPtr(0),
00151 m_iPWSize(psize),
00152 m_piProbeWindow(NULL),
00153 m_iProbeWindowPtr(0),
00154 m_iLastSentTime(0),
00155 m_iMinPktSndInt(1000000),
00156 m_LastArrTime(),
00157 m_CurrArrTime(),
00158 m_ProbeTime()
00159 {
00160    m_piPktWindow = new int[m_iAWSize];
00161    m_piPktReplica = new int[m_iAWSize];
00162    m_piProbeWindow = new int[m_iPWSize];
00163    m_piProbeReplica = new int[m_iPWSize];
00164 
00165    m_LastArrTime = CTimer::getTime();
00166 
00167    for (int i = 0; i < m_iAWSize; ++ i)
00168       m_piPktWindow[i] = 1000000;
00169 
00170    for (int k = 0; k < m_iPWSize; ++ k)
00171       m_piProbeWindow[k] = 1000;
00172 }
00173 
00174 CPktTimeWindow::~CPktTimeWindow()
00175 {
00176    delete [] m_piPktWindow;
00177    delete [] m_piPktReplica;
00178    delete [] m_piProbeWindow;
00179    delete [] m_piProbeReplica;
00180 }
00181 
00182 int CPktTimeWindow::getMinPktSndInt() const
00183 {
00184    return m_iMinPktSndInt;
00185 }
00186 
00187 int CPktTimeWindow::getPktRcvSpeed() const
00188 {
00189    // get median value, but cannot change the original value order in the window
00190    std::copy(m_piPktWindow, m_piPktWindow + m_iAWSize - 1, m_piPktReplica);
00191    std::nth_element(m_piPktReplica, m_piPktReplica + (m_iAWSize / 2), m_piPktReplica + m_iAWSize - 1);
00192    int median = m_piPktReplica[m_iAWSize / 2];
00193 
00194    int count = 0;
00195    int sum = 0;
00196    int upper = median << 3;
00197    int lower = median >> 3;
00198 
00199    // median filtering
00200    int* p = m_piPktWindow;
00201    for (int i = 0, n = m_iAWSize; i < n; ++ i)
00202    {
00203       if ((*p < upper) && (*p > lower))
00204       {
00205          ++ count;
00206          sum += *p;
00207       }
00208       ++ p;
00209    }
00210 
00211    // claculate speed, or return 0 if not enough valid value
00212    if (count > (m_iAWSize >> 1))
00213       return (int)ceil(1000000.0 / (sum / count));
00214    else
00215       return 0;
00216 }
00217 
00218 int CPktTimeWindow::getBandwidth() const
00219 {
00220    // get median value, but cannot change the original value order in the window
00221    std::copy(m_piProbeWindow, m_piProbeWindow + m_iPWSize - 1, m_piProbeReplica);
00222    std::nth_element(m_piProbeReplica, m_piProbeReplica + (m_iPWSize / 2), m_piProbeReplica + m_iPWSize - 1);
00223    int median = m_piProbeReplica[m_iPWSize / 2];
00224 
00225    int count = 1;
00226    int sum = median;
00227    int upper = median << 3;
00228    int lower = median >> 3;
00229 
00230    // median filtering
00231    int* p = m_piProbeWindow;
00232    for (int i = 0, n = m_iPWSize; i < n; ++ i)
00233    {
00234       if ((*p < upper) && (*p > lower))
00235       {
00236          ++ count;
00237          sum += *p;
00238       }
00239       ++ p;
00240    }
00241 
00242    return (int)ceil(1000000.0 / (double(sum) / double(count)));
00243 }
00244 
00245 void CPktTimeWindow::onPktSent(int currtime)
00246 {
00247    int interval = currtime - m_iLastSentTime;
00248 
00249    if ((interval < m_iMinPktSndInt) && (interval > 0))
00250       m_iMinPktSndInt = interval;
00251 
00252    m_iLastSentTime = currtime;
00253 }
00254 
00255 void CPktTimeWindow::onPktArrival()
00256 {
00257    m_CurrArrTime = CTimer::getTime();
00258 
00259    // record the packet interval between the current and the last one
00260    *(m_piPktWindow + m_iPktWindowPtr) = int(m_CurrArrTime - m_LastArrTime);
00261 
00262    // the window is logically circular
00263    ++ m_iPktWindowPtr;
00264    if (m_iPktWindowPtr == m_iAWSize)
00265       m_iPktWindowPtr = 0;
00266 
00267    // remember last packet arrival time
00268    m_LastArrTime = m_CurrArrTime;
00269 }
00270 
00271 void CPktTimeWindow::probe1Arrival()
00272 {
00273    m_ProbeTime = CTimer::getTime();
00274 }
00275 
00276 void CPktTimeWindow::probe2Arrival()
00277 {
00278    m_CurrArrTime = CTimer::getTime();
00279 
00280    // record the probing packets interval
00281    *(m_piProbeWindow + m_iProbeWindowPtr) = int(m_CurrArrTime - m_ProbeTime);
00282    // the window is logically circular
00283    ++ m_iProbeWindowPtr;
00284    if (m_iProbeWindowPtr == m_iPWSize)
00285       m_iProbeWindowPtr = 0;
00286 }

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