1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015 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 #ifndef TCPCONGESTIONOPS_H
20 #define TCPCONGESTIONOPS_H
21 
22 #include "tcp-rate-ops.h"
23 #include "tcp-socket-state.h"
24 
25 namespace ns3 {
26 
27 /**
28  * \ingroup tcp
29  * \defgroup congestionOps Congestion Control Algorithms.
30  *
31  * The various congestion control algorithms, also known as "TCP flavors".
32  */
33 
34 /**
35  * \ingroup congestionOps
36  *
37  * \brief Congestion control abstract class
38  *
39  * The design is inspired by what Linux v4.0 does (but it has been
40  * in place for years). The congestion control is split from the main
41  * socket code, and it is a pluggable component. An interface has been defined;
42  * variables are maintained in the TcpSocketState class, while subclasses of
43  * TcpCongestionOps operate over an instance of that class.
44  *
45  * Only three methods have been implemented right now; however, Linux has many others,
46  * which can be added later in ns-3.
47  *
48  * \see IncreaseWindow
49  * \see PktsAcked
50  */
51 class TcpCongestionOps : public Object
52 {
53 public:
54   /**
55    * \brief Get the type ID.
56    * \return the object TypeId
57    */
58   static TypeId GetTypeId (void);
59 
60   TcpCongestionOps ();
61 
62   /**
63    * \brief Copy constructor.
64    * \param other object to copy.
65    */
66   TcpCongestionOps (const TcpCongestionOps &other);
67 
68   virtual ~TcpCongestionOps ();
69 
70   /**
71    * \brief Get the name of the congestion control algorithm
72    *
73    * \return A string identifying the name
74    */
75   virtual std::string GetName () const = 0;
76 
77   /**
78    * \brief Set configuration required by congestion control algorithm
79    *
80    * \param tcb internal congestion state
81    */
Init(Ptr<TcpSocketState> tcb)82   virtual void Init (Ptr<TcpSocketState> tcb)
83     {
84       NS_UNUSED (tcb);
85     }
86 
87   /**
88    * \brief Get the slow start threshold after a loss event
89    *
90    * Is guaranteed that the congestion control state (\p TcpAckState_t) is
91    * changed BEFORE the invocation of this method.
92    * The implementator should return the slow start threshold (and not change
93    * it directly) because, in the future, the TCP implementation may require to
94    * instantly recover from a loss event (e.g. when there is a network with an high
95    * reordering factor).
96    *
97    * \param tcb internal congestion state
98    * \param bytesInFlight total bytes in flight
99    * \return Slow start threshold
100    */
101   virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb,
102                                 uint32_t bytesInFlight) = 0;
103 
104   /**
105    * \brief Congestion avoidance algorithm implementation
106    *
107    * Mimic the function \pname{cong_avoid} in Linux. New segments have been ACKed,
108    * and the congestion control duty is to update the window.
109    *
110    * The function is allowed to change directly cWnd and/or ssThresh.
111    *
112    * \param tcb internal congestion state
113    * \param segmentsAcked count of segments acked
114    */
115   virtual void IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
116 
117   /**
118    * \brief Timing information on received ACK
119    *
120    * The function is called every time an ACK is received (only one time
121    * also for cumulative ACKs) and contains timing information. It is
122    * optional (congestion controls need not implement it) and the default
123    * implementation does nothing.
124    *
125    * \param tcb internal congestion state
126    * \param segmentsAcked count of segments acked
127    * \param rtt last rtt
128    */
129   virtual void PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
130                           const Time& rtt);
131 
132   /**
133    * \brief Trigger events/calculations specific to a congestion state
134    *
135    * This function mimics the notification function \pname{set_state} in Linux.
136    * The function does not change the congestion state in the tcb; it notifies
137    * the congestion control algorithm that this state is about to be changed.
138    * The tcb->m_congState variable must be separately set; for example:
139    *
140    * \code
141    *   m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY);
142    *   m_tcb->m_congState = TcpSocketState::CA_RECOVERY;
143    * \endcode
144    *
145    * \param tcb internal congestion state
146    * \param newState new congestion state to which the TCP is going to switch
147    */
148   virtual void CongestionStateSet (Ptr<TcpSocketState> tcb,
149                                    const TcpSocketState::TcpCongState_t newState);
150 
151   /**
152    * \brief Trigger events/calculations on occurrence of congestion window event
153    *
154    * This function mimics the function \pname{cwnd_event} in Linux.
155    * The function is called in case of congestion window events.
156    *
157    * \param tcb internal congestion state
158    * \param event the event which triggered this function
159    */
160   virtual void CwndEvent (Ptr<TcpSocketState> tcb,
161                           const TcpSocketState::TcpCAEvent_t event);
162 
163   /**
164    * \brief Returns true when Congestion Control Algorithm implements CongControl
165    *
166    * \return true if CC implements CongControl function
167    *
168    * This function is the equivalent in C++ of the C checks that are used
169    * in the Linux kernel to see if an optional function has been defined.
170    * Since CongControl is optional, not all congestion controls have it. But,
171    * from the perspective of TcpSocketBase, the behavior is different if
172    * CongControl is present. Therefore, this check should return true for any
173    * congestion controls that implements the CongControl optional function.
174    */
175   virtual bool HasCongControl () const;
176 
177   /**
178    * \brief Called when packets are delivered to update cwnd and pacing rate
179    *
180    * This function mimics the function cong_control in Linux. It is allowed to
181    * change directly cWnd and pacing rate.
182    *
183    * \param tcb internal congestion state
184    * \param rc Rate information for the connection
185    * \param rs Rate sample (over a period of time) information
186    */
187   virtual void CongControl (Ptr<TcpSocketState> tcb,
188                             const TcpRateOps::TcpRateConnection &rc,
189                             const TcpRateOps::TcpRateSample &rs);
190 
191   // Present in Linux but not in ns-3 yet:
192   /* call when ack arrives (optional) */
193   //     void (*in_ack_event)(struct sock *sk, u32 flags);
194   /* new value of cwnd after loss (optional) */
195   //     u32  (*undo_cwnd)(struct sock *sk);
196   /* hook for packet ack accounting (optional) */
197   //     void (*pkts_acked)(struct sock *sk, u32 ext, int *attr, union tcp_cc_info *info);
198 
199   /**
200    * \brief Copy the congestion control algorithm across sockets
201    *
202    * \return a pointer of the copied object
203    */
204   virtual Ptr<TcpCongestionOps> Fork () = 0;
205 };
206 
207 /**
208  * \brief The NewReno implementation
209  *
210  * New Reno introduces partial ACKs inside the well-established Reno algorithm.
211  * This and other modifications are described in RFC 6582.
212  *
213  * \see IncreaseWindow
214  */
215 class TcpNewReno : public TcpCongestionOps
216 {
217 public:
218   /**
219    * \brief Get the type ID.
220    * \return the object TypeId
221    */
222   static TypeId GetTypeId (void);
223 
224   TcpNewReno ();
225 
226   /**
227    * \brief Copy constructor.
228    * \param sock object to copy.
229    */
230   TcpNewReno (const TcpNewReno& sock);
231 
232   ~TcpNewReno ();
233 
234   std::string GetName () const;
235 
236   virtual void IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
237   virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb,
238                                 uint32_t bytesInFlight);
239   virtual Ptr<TcpCongestionOps> Fork ();
240 
241 protected:
242   virtual uint32_t SlowStart (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
243   virtual void CongestionAvoidance (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
244 };
245 
246 } // namespace ns3
247 
248 #endif // TCPCONGESTIONOPS_H
249