1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018 NITK Surathkal
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  * Authors: Vivek Jain <jain.vivek.anand@gmail.com>
19  *          Viyom Mittal <viyommittal@gmail.com>
20  *          Mohit P. Tahiliani <tahiliani@nitk.edu.in>
21  *
22  */
23 
24 #include "ns3/test.h"
25 #include "ns3/log.h"
26 #include "ns3/tcp-congestion-ops.h"
27 #include "ns3/tcp-socket-base.h"
28 #include "ns3/tcp-bbr.h"
29 
30 namespace ns3 {
31 
32 NS_LOG_COMPONENT_DEFINE ("TcpBbrTestSuite");
33 
34 /**
35  * \brief Testing whether BBR enables pacing
36  */
37 class TcpBbrPacingEnableTest : public TestCase
38 {
39 public:
40   /**
41    * \brief constructor
42    * \param pacing pacing configuration
43    * \param name description of the test
44    */
45   TcpBbrPacingEnableTest (bool pacing, const std::string &name);
46 
47 private:
48   virtual void DoRun (void);
49   /**
50    * \brief Execute the test.
51    */
52   void ExecuteTest (void);
53   bool m_pacing; //!< Initial pacing configuration.
54 };
55 
TcpBbrPacingEnableTest(bool pacing,const std::string & name)56 TcpBbrPacingEnableTest::TcpBbrPacingEnableTest (bool pacing, const std::string &name)
57   : TestCase (name),
58     m_pacing (pacing)
59 {}
60 
61 void
DoRun()62 TcpBbrPacingEnableTest::DoRun ()
63 {
64   Simulator::Schedule (Seconds (0.0), &TcpBbrPacingEnableTest::ExecuteTest, this);
65   Simulator::Run ();
66   Simulator::Destroy ();
67 }
68 
69 void
ExecuteTest()70 TcpBbrPacingEnableTest::ExecuteTest ()
71 {
72   Ptr<TcpSocketState> state = CreateObject <TcpSocketState> ();
73   state->m_pacing = m_pacing;
74 
75   Ptr<TcpBbr> cong = CreateObject <TcpBbr> ();
76 
77   cong->CongestionStateSet (state, TcpSocketState::CA_OPEN);
78 
79   NS_TEST_ASSERT_MSG_EQ (state->m_pacing, true,
80                          "BBR has not updated pacing value");
81 }
82 
83 /**
84  * \brief Tests whether BBR sets correct value of pacing and cwnd gain based on different state.
85  */
86 class TcpBbrCheckGainValuesTest : public TestCase
87 {
88 public:
89   /**
90    * \brief constructor
91    * \param state BBR state/mode under test
92    * \param highGain value of pacing and cwnd gain
93    * \param name description of the test
94    */
95   TcpBbrCheckGainValuesTest (TcpBbr::BbrMode_t state, double highGain, const std::string &name);
96 
97 private:
98   virtual void DoRun (void);
99   /**
100    * \brief Execute the test.
101    */
102   void ExecuteTest (void);
103   TcpBbr::BbrMode_t m_mode; //!< BBR mode under test
104   double m_highGain;        //!< Value of BBR high gain
105 };
106 
TcpBbrCheckGainValuesTest(TcpBbr::BbrMode_t state,double highGain,const std::string & name)107 TcpBbrCheckGainValuesTest::TcpBbrCheckGainValuesTest (TcpBbr::BbrMode_t state,
108                                                       double highGain, const std::string &name)
109   : TestCase (name),
110     m_mode (state),
111     m_highGain (highGain)
112 {}
113 
114 void
DoRun()115 TcpBbrCheckGainValuesTest::DoRun ()
116 {
117   Simulator::Schedule (Seconds (0.0), &TcpBbrCheckGainValuesTest::ExecuteTest, this);
118   Simulator::Run ();
119   Simulator::Destroy ();
120 }
121 
122 void
ExecuteTest()123 TcpBbrCheckGainValuesTest::ExecuteTest ()
124 {
125   Ptr<TcpBbr> cong = CreateObject <TcpBbr> ();
126   cong->SetAttribute ("HighGain", DoubleValue (m_highGain));
127   double actualPacingGain, actualCwndGain, desiredPacingGain = m_highGain, desiredCwndGain = m_highGain;
128   TcpBbr::BbrMode_t desiredMode = TcpBbr::BBR_STARTUP;
129   switch (m_mode)
130     {
131       case TcpBbr::BBR_STARTUP:
132         cong->EnterStartup ();
133         desiredPacingGain = m_highGain;
134         desiredCwndGain  = m_highGain;
135         actualPacingGain = cong->GetPacingGain ();
136         actualCwndGain = cong->GetCwndGain ();
137         desiredMode = TcpBbr::BBR_STARTUP;
138         break;
139       case TcpBbr::BBR_DRAIN:
140         cong->EnterDrain ();
141         desiredPacingGain = 1 / m_highGain;
142         desiredCwndGain  = m_highGain;
143         desiredMode = TcpBbr::BBR_DRAIN;
144         break;
145       case TcpBbr::BBR_PROBE_BW:
146         cong->EnterProbeBW ();
147         // The value of desiredPacingGain is sensitive to the setting of random
148         // variable stream. The value of 1.25 has been used in this test with a
149         // stream value of 4 (default for TCP BBR). Note that if the stream value
150         // is changed, this test might fail because when BBR enters the PROBE_BW
151         // phase, the value of actualPacingGain is chosen randomly from 1.25,
152         // 0.75, 1, 1, 1, 1, 1, 1.
153         desiredPacingGain = 1.25;
154         desiredCwndGain  = 2;
155         desiredMode = TcpBbr::BBR_PROBE_BW;
156         break;
157       case TcpBbr::BBR_PROBE_RTT:
158         cong->EnterProbeRTT ();
159         desiredPacingGain = 1;
160         desiredCwndGain  = 1;
161         desiredMode = TcpBbr::BBR_PROBE_RTT;
162         break;
163       default:
164         NS_ASSERT (false);
165     }
166 
167   actualPacingGain = cong->GetPacingGain ();
168   actualCwndGain = cong->GetCwndGain ();
169   NS_TEST_ASSERT_MSG_EQ (m_mode, desiredMode, "BBR has not entered into desired state");
170   NS_TEST_ASSERT_MSG_EQ (actualPacingGain, desiredPacingGain, "BBR has not updated into desired pacing gain");
171   NS_TEST_ASSERT_MSG_EQ (actualCwndGain, desiredCwndGain, "BBR has not updated into desired cwnd gain");
172 }
173 
174 /**
175  * \ingroup internet-test
176  * \ingroup tests
177  *
178  * \brief TCP BBR TestSuite
179  */
180 class TcpBbrTestSuite : public TestSuite
181 {
182 public:
183   /**
184    * \brief constructor
185    */
TcpBbrTestSuite()186   TcpBbrTestSuite () : TestSuite ("tcp-bbr-test", UNIT)
187   {
188     AddTestCase (new TcpBbrPacingEnableTest (true, "BBR must keep pacing feature on"), TestCase::QUICK);
189 
190     AddTestCase (new TcpBbrPacingEnableTest (false, "BBR must turn on pacing feature"), TestCase::QUICK);
191 
192     AddTestCase (new TcpBbrCheckGainValuesTest (TcpBbr::BBR_STARTUP, 4, "BBR should enter to STARTUP phase and set cwnd and pacing gain accordingly"), TestCase::QUICK);
193 
194     AddTestCase (new TcpBbrCheckGainValuesTest (TcpBbr::BBR_DRAIN, 4, "BBR should enter to DRAIN phase and set cwnd and pacing gain accordingly"), TestCase::QUICK);
195 
196     AddTestCase (new TcpBbrCheckGainValuesTest (TcpBbr::BBR_PROBE_BW, 4, "BBR should enter to BBR_PROBE_BW phase and set cwnd and pacing gain accordingly"), TestCase::QUICK);
197 
198     AddTestCase (new TcpBbrCheckGainValuesTest (TcpBbr::BBR_PROBE_RTT, 4, "BBR should enter to BBR_PROBE_RTT phase and set cwnd and pacing gain accordingly"), TestCase::QUICK);
199   }
200 };
201 
202 static TcpBbrTestSuite g_tcpBbrTest; //!< static variable for test initialization
203 }
204