1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Natale Patriciello <natale.patriciello@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  */
19 
20 #ifndef TCPCUBIC_H
21 #define TCPCUBIC_H
22 
23 #include "ns3/tcp-congestion-ops.h"
24 #include "ns3/tcp-socket-base.h"
25 
26 
27 namespace ns3 {
28 
29 /**
30  * \brief The Cubic Congestion Control Algorithm
31  *
32  * TCP Cubic is a protocol that enhances the fairness property
33  * of Bic while retaining its scalability and stability. The main feature is
34  * that the window growth function is defined in real time in order to be independent
35  * from the RTT. More specifically, the congestion window of Cubic is determined
36  * by a function of the elapsed time from the last window reduction.
37  *
38  * The Cubic code is quite similar to that of Bic.
39  * The main difference is located in the method Update, an edit
40  * necessary for satisfying the Cubic window growth, that can be tuned with
41  * the attribute C (the Cubic scaling factor).
42  *
43  * Following the Linux implementation, we included the Hybrid Slow Start,
44  * that effectively prevents the overshooting of slow start
45  * while maintaining a full utilization of the network. This new type of slow
46  * start can be disabled through the \Attribute{HyStart} attribute.
47  *
48  * CUBIC TCP is implemented and used by default in Linux kernels 2.6.19
49  * and above; this version follows the implementation in Linux 3.14, which
50  * slightly differ from the CUBIC paper. It also features HyStart.
51  *
52  * Home page:
53  *      http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
54  * The work starts from the implementation of CUBIC TCP in
55  * Sangtae Ha, Injong Rhee and Lisong Xu,
56  * "CUBIC: A New TCP-Friendly High-Speed TCP Variant"
57  * in ACM SIGOPS Operating System Review, July 2008.
58  * Available from:
59  *  http://netsrv.csc.ncsu.edu/export/cubic_a_new_tcp_2008.pdf
60  *
61  * CUBIC integrates a new slow start algorithm, called HyStart.
62  * The details of HyStart are presented in
63  *  Sangtae Ha and Injong Rhee,
64  *  "Taming the Elephants: New TCP Slow Start", NCSU TechReport 2008.
65  * Available from:
66  *  http://netsrv.csc.ncsu.edu/export/hystart_techreport_2008.pdf
67  *
68  * More information on this implementation: http://dl.acm.org/citation.cfm?id=2756518
69  */
70 class TcpCubic : public TcpCongestionOps
71 {
72 public:
73   /**
74    * \brief Get the type ID.
75    * \return the object TypeId
76    */
77   static TypeId GetTypeId (void);
78 
79   TcpCubic ();
80 
81   /**
82    * Copy constructor
83    * \param sock Socket to copy
84    */
85   TcpCubic (const TcpCubic& sock);
86 
87   virtual std::string GetName () const;
88   virtual void PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked, const Time& rtt);
89   virtual void IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
90   virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight);
91   virtual void CongestionStateSet (Ptr<TcpSocketState> tcb,
92                                    const TcpSocketState::TcpCongState_t newState);
93 
94   virtual Ptr<TcpCongestionOps> Fork ();
95 
96 private:
97   /**
98    * \brief Values to detect the Slow Start mode of HyStart
99    */
100   enum HybridSSDetectionMode
101   {
102     PACKET_TRAIN = 0x1, //!< Detection by trains of packet
103     DELAY        = 0x2  //!< Detection by delay value
104   };
105 
106   bool     m_fastConvergence;  //!< Enable or disable fast convergence algorithm
107   double   m_beta;             //!< Beta for cubic multiplicative increase
108 
109   bool     m_hystart;          //!< Enable or disable HyStart algorithm
110   int      m_hystartDetect;    //!< Detect way for HyStart algorithm \see HybridSSDetectionMode
111   uint32_t m_hystartLowWindow; //!< Lower bound cWnd for hybrid slow start (segments)
112   Time     m_hystartAckDelta;  //!< Spacing between ack's indicating train
113   Time     m_hystartDelayMin;  //!< Minimum time for hystart algorithm
114   Time     m_hystartDelayMax;  //!< Maximum time for hystart algorithm
115   uint8_t  m_hystartMinSamples; //!< Number of delay samples for detecting the increase of delay
116 
117   uint32_t m_initialCwnd;      //!< Initial cWnd
118   uint8_t  m_cntClamp;         //!< Modulo of the (avoided) float division for cWnd
119 
120   double   m_c;                //!< Cubic Scaling factor
121 
122   // Cubic parameters
123   uint32_t     m_cWndCnt;         //!<  cWnd integer-to-float counter
124   uint32_t     m_lastMaxCwnd;     //!<  Last maximum cWnd
125   uint32_t     m_bicOriginPoint;  //!<  Origin point of bic function
126   double       m_bicK;            //!<  Time to origin point from the beginning
127                                   //    of the current epoch (in s)
128   Time         m_delayMin;        //!<  Min delay
129   Time         m_epochStart;      //!<  Beginning of an epoch
130   bool         m_found;           //!<  The exit point is found?
131   Time         m_roundStart;      //!<  Beginning of each round
132   SequenceNumber32   m_endSeq;    //!<  End sequence of the round
133   Time         m_lastAck;         //!<  Last time when the ACK spacing is close
134   Time         m_cubicDelta;      //!<  Time to wait after recovery before update
135   Time         m_currRtt;         //!<  Current Rtt
136   uint32_t     m_sampleCnt;       //!<  Count of samples for HyStart
137 
138 private:
139   /**
140    * \brief Reset HyStart parameters
141    * \param tcb Transmission Control Block of the connection
142    */
143   void HystartReset (Ptr<const TcpSocketState> tcb);
144 
145   /**
146    * \brief Reset Cubic parameters
147    * \param tcb Transmission Control Block of the connection
148    */
149   void CubicReset (Ptr<const TcpSocketState> tcb);
150 
151   /**
152    * \brief Cubic window update after a new ack received
153    * \param tcb Transmission Control Block of the connection
154    * \returns the congestion window update counter
155    */
156   uint32_t Update (Ptr<TcpSocketState> tcb);
157 
158   /**
159    * \brief Update HyStart parameters
160    *
161    * \param tcb Transmission Control Block of the connection
162    * \param delay Delay for HyStart algorithm
163    */
164   void HystartUpdate (Ptr<TcpSocketState> tcb, const Time &delay);
165 
166   /**
167    * \brief Clamp time value in a range
168    *
169    * The returned value is t, clamped in a range specified
170    * by attributes (HystartDelayMin < t < HystartDelayMax)
171    *
172    * \param t Time value to clamp
173    * \return t itself if it is in range, otherwise the min or max
174    * value
175    */
176   Time HystartDelayThresh (const Time &t) const;
177 };
178 
179 } // namespace ns3
180 
181 #endif // TCPCUBIC_H
182