1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
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  * Author: Zoraze Ali <zoraze.ali@cttc.es>
19  *
20  */
21 
22 #include <ns3/object.h>
23 #include <ns3/log.h>
24 #include <ns3/test.h>
25 #include <ns3/simulator.h>
26 #include <ns3/ptr.h>
27 #include <ns3/constant-position-mobility-model.h>
28 #include <ns3/node-container.h>
29 #include <ns3/mobility-helper.h>
30 #include <ns3/net-device-container.h>
31 #include <ns3/lte-ue-rrc.h>
32 #include <ns3/lte-helper.h>
33 #include <ns3/lte-spectrum-value-helper.h>
34 #include <ns3/callback.h>
35 
36 using namespace ns3;
37 
38 /**
39  * This test suite verifies following two things:
40  *
41  *  1. When CA is enabled and UE carriers configuration is different than the default one,
42  *     we check that the UE is configured properly once it receives
43  *     RRC Connection Reconfiguration message from eNB.
44  *
45  *  2. A user can configure 2 or more eNBs and UEs with different configuration parameters,
46  *     i.e, each eNB and UE can have different EARFCN and Bandwidths and a UE connects to
47  *     an eNB with similar DL EARFCN.
48  *     Here we check it with CA enabled but the end results will be the same if CA is not
49  *     enabled and we have more than one eNBs and UEs with different configurations.
50  *
51  * Since we do not need EPC to test the configuration, this test only simulates
52  * the LTE radio access with RLC SM.
53  *
54  * Test 1 tests that the UE is configured properly after receiving RRC Connection
55  * Reconfiguration message from the eNB, which will overwrite UE default configuration
56  * done in LteHelper for the sake of creating PHY and MAC instances equal to the number
57  * of component carriers.
58  *
59  * Test 2 tests that in a simulation scenario every eNB or UE can be configured with
60  * different EARFCNs and Bandwidths. This will check that the eNBs and UEs configuration
61  * is not static, as reported in BUG 2840.
62  */
63 
64 /// ConfigToCheck structure
65 struct ConfigToCheck
66 {
67   uint16_t m_dlBandwidth; ///< Downlink bandwidth
68   uint16_t m_ulBandwidth; ///< Uplink bandwidth
69   uint32_t m_dlEarfcn; ///< Downlink EARFCN
70   uint32_t m_ulEarfcn; ///< Uplink EARFCN
71 };
72 
73 NS_LOG_COMPONENT_DEFINE ("TestCarrierAggregationConfig");
74 
75 /**
76  * \ingroup lte-test
77  * \ingroup tests
78  *
79  * \brief Carrier aggregation configuration test case.
80  */
81 class CarrierAggregationConfigTestCase : public TestCase
82 {
83 public:
84   /**
85    * Constructor
86    *
87    * \param numberOfNodes Total Number of eNBs and UEs
88    * \param numberOfComponentCarriers  Total number of component carriers
89    * \param configToCheck Vector containing all the configurations to check
90    * \param simulationDuration Duration of the simulation
91    */
CarrierAggregationConfigTestCase(uint32_t numberOfNodes,uint16_t numberOfComponentCarriers,std::vector<ConfigToCheck> configToCheck,Time simulationDuration)92   CarrierAggregationConfigTestCase (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration)
93     : TestCase (BuildNameString (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration)),
94       m_numberOfNodes(numberOfNodes),
95       m_numberOfComponentCarriers(numberOfComponentCarriers),
96       m_configToCheck(configToCheck),
97       m_simulationDuration (simulationDuration)
98   {
99     m_connectionCounter = 0.0;
100   }
101 
102 private:
103   virtual void DoRun (void);
104 
105   /**
106    * Build name string function
107    *
108    * \param numberOfNodes Total Number of eNBs and UEs
109    * \param numberOfComponentCarriers  Total number of component carriers
110    * \param configToCheck Vector containing all the configurations to check
111    * \param simulationDuration Duration of the simulation
112    * \returns the name string
113    */
114   std::string BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration);
115   /**
116    * Evaluate function
117    *
118    * \param context The context
119    * \param ueRrc Pointer to the UE RRC
120    * \param sCellToAddModList List of the configuration parameters for secondary cell
121    */
122   void Evaluate (std::string context, Ptr<LteUeRrc> ueRrc, std::list<LteRrcSap::SCellToAddMod> sCellToAddModList);
123   /**
124    * Equally spaced component carriers function
125    *
126    * \return Vector of maps containing the per component carrier configuration
127    */
128   std::vector<std::map<uint16_t, ConfigToCheck> > EquallySpacedCcs ();
129 
130   uint32_t m_numberOfNodes; ///< Numer of nodes
131   uint16_t m_numberOfComponentCarriers; ///< Number of component carriers
132   std::vector<ConfigToCheck> m_configToCheck; ///< Vector containing all the configurations to check
133   uint32_t m_connectionCounter; ///< Connection counter
134   Time m_simulationDuration; ///< Simulation duration
135   std::vector<std::map<uint16_t, ConfigToCheck> > m_configToCheckContainer; ///< Vector of maps containing the per component carrier configuration
136 };
137 
138 std::string
BuildNameString(uint32_t numberOfNodes,uint16_t numberOfComponentCarriers,std::vector<ConfigToCheck> configToCheck,Time simulationDuration)139 CarrierAggregationConfigTestCase::BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration)
140 {
141   std::ostringstream oss;
142   oss << " nodes " << numberOfNodes << " carriers " << numberOfComponentCarriers
143       << " configurations " << configToCheck.size ()
144       << " duration " << simulationDuration;
145   return oss.str ();
146 }
147 
148 std::vector<std::map<uint16_t, ConfigToCheck> >
EquallySpacedCcs()149 CarrierAggregationConfigTestCase::EquallySpacedCcs ()
150 {
151   std::vector<std::map<uint16_t, ConfigToCheck> > configToCheckContainer;
152 
153   for (auto &it: m_configToCheck)
154     {
155       std::map<uint16_t, ConfigToCheck> ccmap;
156       uint32_t ulEarfcn = it.m_ulEarfcn;
157       uint32_t dlEarfcn = it.m_dlEarfcn;
158       uint32_t maxBandwidthRb = std::max<uint32_t> (it.m_ulBandwidth, it.m_dlBandwidth);
159 
160       // Convert bandwidth from RBs to kHz
161       uint32_t maxBandwidthKhz = LteSpectrumValueHelper::GetChannelBandwidth (maxBandwidthRb) / 1e3;
162 
163       for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
164         {
165           // Make sure we stay within the same band.
166           if (LteSpectrumValueHelper::GetUplinkCarrierBand (ulEarfcn) !=
167               LteSpectrumValueHelper::GetUplinkCarrierBand (it.m_ulEarfcn)
168            || LteSpectrumValueHelper::GetDownlinkCarrierBand (dlEarfcn) !=
169               LteSpectrumValueHelper::GetDownlinkCarrierBand (it.m_dlEarfcn))
170             {
171               NS_FATAL_ERROR ("Band is not wide enough to allocate " << m_numberOfComponentCarriers << " CCs");
172             }
173 
174       ConfigToCheck cc;
175       cc.m_dlBandwidth = it.m_dlBandwidth;
176       cc.m_dlEarfcn = dlEarfcn;
177       cc.m_ulBandwidth = it.m_ulBandwidth;
178       cc.m_ulEarfcn = ulEarfcn;
179 
180       ccmap.insert (std::pair<uint16_t, ConfigToCheck> (i, cc));
181 
182       NS_LOG_INFO ("UL BW: " << it.m_ulBandwidth <<
183                    ", DL BW: " << it.m_dlBandwidth <<
184                    ", UL Earfcn: " << ulEarfcn <<
185                    ", DL Earfcn: " << dlEarfcn);
186 
187       // The spacing between the center frequencies of two contiguous CCs should be multiple of 300 kHz.
188       // Round spacing up to 300 kHz.
189       uint32_t frequencyShift = 300 * (1 + (maxBandwidthKhz - 1) / 300);
190 
191       // Unit of EARFCN corresponds to 100kHz.
192       uint32_t earfcnShift = frequencyShift / 100;
193       ulEarfcn += earfcnShift;
194       dlEarfcn += earfcnShift;
195     }
196 
197     configToCheckContainer.push_back (ccmap);
198   }
199 
200   return configToCheckContainer;
201 }
202 
203 void
Evaluate(std::string context,Ptr<LteUeRrc> ueRrc,std::list<LteRrcSap::SCellToAddMod> sCellToAddModList)204 CarrierAggregationConfigTestCase::Evaluate (std::string context, Ptr<LteUeRrc> ueRrc, std::list<LteRrcSap::SCellToAddMod> sCellToAddModList)
205 {
206   NS_LOG_INFO ("Secondary carriers configured");
207 
208   uint16_t cellId = ueRrc->GetCellId ();
209   NS_LOG_INFO ("cellId " << cellId);
210   NS_LOG_INFO ("m_configToCheckContainer size " << m_configToCheckContainer.size ());
211 
212   ++m_connectionCounter;
213 
214   std::map<uint16_t, ConfigToCheck> configToCheckMap;
215 
216   if (cellId == 1)
217     {
218       configToCheckMap = m_configToCheckContainer[cellId-1];
219     }
220   else
221     {
222       uint16_t n1 = std::max(cellId, m_numberOfComponentCarriers);
223       uint16_t n2 = std::min(cellId, m_numberOfComponentCarriers);
224       configToCheckMap = m_configToCheckContainer[n1-n2];
225     }
226 
227   NS_LOG_INFO ("PCarrier - UL BW: " << static_cast<uint16_t> (ueRrc->GetUlBandwidth ()) <<
228                ", DL BW: " << static_cast<uint16_t> (ueRrc->GetDlBandwidth ()) <<
229                ", UL Earfcn: " << ueRrc->GetUlEarfcn () <<
230                ", DL Earfcn: " << ueRrc->GetDlEarfcn ());
231 
232   for (auto scell: sCellToAddModList)
233     {
234       NS_LOG_INFO ("SCarrier - UL BW: " << static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth)<<
235                    ", DL BW: " << static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth) <<
236                    ", UL Earfcn: " << scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq <<
237                    ", DL Earfcn: " << scell.cellIdentification.dlCarrierFreq);
238     }
239 
240   ConfigToCheck pCConfig = configToCheckMap[0]; // Primary Carrier
241   ConfigToCheck sCConfig; // Secondary Carriers
242 
243   NS_TEST_ASSERT_MSG_EQ (pCConfig.m_dlBandwidth, static_cast<uint16_t> (ueRrc->GetDlBandwidth ()),
244                          "Primary Carrier DL bandwidth configuration failed");
245   NS_TEST_ASSERT_MSG_EQ (pCConfig.m_ulBandwidth, static_cast<uint16_t> (ueRrc->GetUlBandwidth ()),
246                          "Primary Carrier UL bandwidth configuration failed");
247   NS_TEST_ASSERT_MSG_EQ (pCConfig.m_dlEarfcn, ueRrc->GetDlEarfcn (),
248                          "Primary Carrier DL EARFCN configuration failed");
249   NS_TEST_ASSERT_MSG_EQ (pCConfig.m_ulEarfcn, ueRrc->GetUlEarfcn (),
250                          "Primary Carrier UL EARFCN configuration failed");
251 
252   uint32_t ConfigToCheckMapIndex = 1;
253 
254   for (auto scell: sCellToAddModList)
255     {
256       sCConfig = configToCheckMap[ConfigToCheckMapIndex];
257 
258       NS_TEST_ASSERT_MSG_EQ (sCConfig.m_dlBandwidth, static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth),
259                              "Secondary Carrier DL bandwidth configuration failed");
260       NS_TEST_ASSERT_MSG_EQ (sCConfig.m_ulBandwidth, static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth),
261                              "Secondary Carrier UL bandwidth configuration failed");
262       NS_TEST_ASSERT_MSG_EQ (sCConfig.m_dlEarfcn, scell.cellIdentification.dlCarrierFreq,
263                              "Secondary Carrier DL EARFCN configuration failed");
264       NS_TEST_ASSERT_MSG_EQ (sCConfig.m_ulEarfcn, scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq,
265                              "Secondary Carrier UL EARFCN configuration failed");
266       ConfigToCheckMapIndex++;
267     }
268 }
269 
270 void
DoRun()271 CarrierAggregationConfigTestCase::DoRun ()
272 {
273   Config::SetDefault ("ns3::LteHelper::UseCa", BooleanValue (true));
274   Config::SetDefault ("ns3::LteHelper::NumberOfComponentCarriers", UintegerValue (m_numberOfComponentCarriers));
275   Config::SetDefault ("ns3::LteHelper::EnbComponentCarrierManager", StringValue ("ns3::RrComponentCarrierManager"));
276 
277   int64_t stream = 1;
278 
279   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
280 
281   // Create Nodes: eNodeB and UE
282   NodeContainer enbNodes;
283   NodeContainer ueNodes;
284   enbNodes.Create (m_numberOfNodes);
285   ueNodes.Create (m_numberOfNodes);
286 
287   uint32_t totalNumberOfNodes = enbNodes.GetN () + ueNodes.GetN ();
288 
289   // Install Mobility Model
290   Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
291   for (uint16_t i = 0; i < totalNumberOfNodes; i++)
292     {
293       positionAlloc->Add (Vector (2 * i, 0, 0));
294     }
295 
296   MobilityHelper mobility;
297   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
298   mobility.SetPositionAllocator (positionAlloc);
299 
300   for (uint32_t n = 0; n < m_numberOfNodes; ++n)
301     {
302       mobility.Install (enbNodes.Get (n));
303       mobility.Install (ueNodes.Get (n));
304     }
305 
306   ConfigToCheck configuration;
307   NetDeviceContainer enbDevs;
308   NetDeviceContainer ueDevs;
309 
310   // Set bandwidth, EARFCN and install nodes (eNB and UE)
311   for (uint32_t i = 0; i < m_configToCheck.size (); ++i)
312     {
313       configuration = m_configToCheck[i];
314 
315       lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (configuration.m_dlBandwidth));
316       lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (configuration.m_ulBandwidth));
317       lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (configuration.m_dlEarfcn));
318       lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (configuration.m_ulEarfcn));
319       lteHelper->SetUeDeviceAttribute ("DlEarfcn", UintegerValue (configuration.m_dlEarfcn));
320       enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (i)));
321       lteHelper->AssignStreams (enbDevs, stream);
322       ueDevs.Add (lteHelper->InstallUeDevice (ueNodes.Get (i)));
323       lteHelper->AssignStreams (ueDevs, stream);
324     }
325 
326   // Calculate the DlBandwidth, UlBandwidth, DlEarfcn and UlEarfcn to which the values from UE RRC would be compared
327   m_configToCheckContainer = EquallySpacedCcs ();
328 
329   // Attach a UE to an eNB
330   for(uint32_t k = 0; k < m_numberOfNodes; ++k)
331     {
332       lteHelper->Attach (ueDevs.Get (k), enbDevs.Get (k));
333     }
334 
335    // Activate a data radio bearer
336   enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
337   EpsBearer bearer (q);
338   lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
339 
340   Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/SCarrierConfigured",
341                    MakeCallback (&CarrierAggregationConfigTestCase::Evaluate, this));
342 
343   Simulator::Stop (m_simulationDuration);
344   Simulator::Run ();
345 
346   NS_TEST_ASSERT_MSG_EQ (m_connectionCounter, ueNodes.GetN (), "Not all the UEs were connected");
347 
348   Simulator::Destroy ();
349 }
350 
351 /**
352  * \ingroup lte-test
353  * \ingroup tests
354  *
355  * \brief Carrier aggregation configuration test suite.
356  */
357 class CarrierAggregationConfigTestSuite : public TestSuite
358 {
359 public:
360   CarrierAggregationConfigTestSuite ();
361 };
362 
CarrierAggregationConfigTestSuite()363 CarrierAggregationConfigTestSuite::CarrierAggregationConfigTestSuite ()
364   : TestSuite ("lte-carrier-aggregation-configuration", SYSTEM)
365 {
366   std::vector<ConfigToCheck> configToCheck;
367 
368   // Test1 with 1 eNB and 1 UE.
369   // We put a configuration different than the default configuration done in LteHelper for the sake of
370   // creating PHY and MAC instances equal to the number of component carriers.
371 
372   ConfigToCheck configToCheckTest1;
373   configToCheckTest1.m_dlBandwidth = 50;
374   configToCheckTest1.m_ulBandwidth = 50;
375   configToCheckTest1.m_dlEarfcn = 300;
376   configToCheckTest1.m_ulEarfcn = 300+18000;
377   configToCheck.push_back (configToCheckTest1);
378   uint32_t numberOfNodes = 1;
379   uint16_t numberOfComponentCarriers = 2;
380   Time simulationDuration = Seconds (1);
381 
382   AddTestCase (new CarrierAggregationConfigTestCase (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration), TestCase::QUICK);
383 
384 //   configToCheck.erase(configToCheck.begin(), configToCheck.end());
385   configToCheck.clear ();
386 
387   // Test2 with 2 eNBs and 2 UEs.
388   // We decrease the bandwidth so not to exceed maximum band bandwidth of 20 MHz
389 
390   configToCheckTest1.m_dlBandwidth = 25;
391   configToCheckTest1.m_ulBandwidth = 25;
392   configToCheckTest1.m_dlEarfcn = 300;
393   configToCheckTest1.m_ulEarfcn = 300+18000;
394   configToCheck.push_back (configToCheckTest1);
395 
396   ConfigToCheck configToCheckTest2;
397   configToCheckTest2.m_dlBandwidth = 25;
398   configToCheckTest2.m_ulBandwidth = 25;
399   configToCheckTest2.m_dlEarfcn = 502;
400   configToCheckTest2.m_ulEarfcn = 502+18000;
401   configToCheck.push_back (configToCheckTest2);
402   numberOfNodes = 2;
403   simulationDuration = Seconds (2);
404 
405   AddTestCase (new CarrierAggregationConfigTestCase (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration), TestCase::QUICK);
406 }
407 
408 static CarrierAggregationConfigTestSuite g_carrierAggregationConfigTestSuite;
409