1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 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: Nicola Baldo <nbaldo@cttc.es>
19  *         Budiarto Herman <budiarto.herman@magister.fi>
20  */
21 
22 
23 #include <ns3/core-module.h>
24 #include <ns3/network-module.h>
25 #include <ns3/mobility-module.h>
26 #include <ns3/lte-module.h>
27 #include <cmath>
28 
29 using namespace ns3;
30 
31 NS_LOG_COMPONENT_DEFINE ("LteRrcTest");
32 
33 /**
34  * \ingroup lte-test
35  * \ingroup tests
36  *
37  * \brief Test rrc connection establishment.
38  */
39 class LteRrcConnectionEstablishmentTestCase : public TestCase
40 {
41 public:
42   /**
43    *
44    *
45    * \param nUes number of UEs in the test
46    * \param nBearers number of bearers to be setup in each connection
47    * \param tConnBase connection time base value for all UEs in ms
48    * \param tConnIncrPerUe additional connection time increment for each UE index (0...nUes-1) in ms
49    * \param delayDiscStart expected duration to perform connection establishment in ms
50    * \param errorExpected if true, test case will wait a bit longer to accommodate for transmission error
51    * \param useIdealRrc If set to false, real RRC protocol model will be used
52    * \param admitRrcConnectionRequest If set to false, eNb will not allow UE connections
53    * \param description additional description of the test case
54    */
55   LteRrcConnectionEstablishmentTestCase (uint32_t nUes,
56                                          uint32_t nBearers,
57                                          uint32_t tConnBase,
58                                          uint32_t tConnIncrPerUe,
59                                          uint32_t delayDiscStart,
60                                          bool errorExpected,
61                                          bool useIdealRrc,
62                                          bool admitRrcConnectionRequest,
63                                          std::string description = "");
64 
65 protected:
66 
67   virtual void DoRun (void);
68   uint32_t m_nUes; ///< number of UEs in the test
69 
70   /**
71    * Build name string function
72    *
73    * \param nUes number of UEs in the test
74    * \param nBearers number of bearers to be setup in each connection
75    * \param tConnBase connection time base value for all UEs in ms
76    * \param tConnIncrPerUe additional connection time increment for each UE index (0...nUes-1) in ms
77    * \param delayDiscStart expected duration to perform connection establishment in ms
78    * \param useIdealRrc If set to false, real RRC protocol model will be used
79    * \param admitRrcConnectionRequest If set to false, eNb will not allow UE connections
80    * \param description additional description of the test case
81    * \returns the name string
82    */
83   static std::string BuildNameString (uint32_t nUes,
84                                       uint32_t nBearers,
85                                       uint32_t tConnBase,
86                                       uint32_t tConnIncrPerUe,
87                                       uint32_t delayDiscStart,
88                                       bool useIdealRrc,
89                                       bool admitRrcConnectionRequest,
90                                       std::string description = "");
91   /**
92    * Connect function
93    * \param ueDevice the UE device
94    * \param enbDevice the ENB device
95    */
96   void Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
97   /**
98    * Check connected function
99    * \param ueDevice the UE device
100    * \param enbDevice the ENB device
101    */
102   void CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
103   /**
104    * Check not connected function
105    * \param ueDevice the UE device
106    * \param enbDevice the ENB device
107    */
108   void CheckNotConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
109   /**
110    * Connection established callback function
111    * \param context the context string
112    * \param imsi the IMSI
113    * \param cellId the cell ID
114    * \param rnti the RNTI
115    */
116   void ConnectionEstablishedCallback (std::string context, uint64_t imsi,
117                                       uint16_t cellId, uint16_t rnti);
118   /**
119    * Connection timeout callback function
120    * \param context the context string
121    * \param imsi the IMSI
122    * \param cellId the cell ID
123    * \param rnti the RNTI
124    * \param connEstFailCount the T300 timer expiration counter value
125    */
126   void ConnectionTimeoutCallback (std::string context, uint64_t imsi,
127                                   uint16_t cellId, uint16_t rnti,
128                                   uint8_t connEstFailCount);
129 
130   uint32_t m_nBearers; ///< number of bearers to be setup in each connection
131   uint32_t m_tConnBase;  ///< connection time base value for all UEs in ms
132   uint32_t m_tConnIncrPerUe; ///< additional connection time increment for each UE index (0...nUes-1) in ms
133   uint32_t m_delayConnEnd;  ///< expected duration to perform connection establishment in ms
134   uint32_t m_delayDiscStart;  ///< delay between connection completed and disconnection request in ms
135   uint32_t m_delayDiscEnd; ///< expected duration to complete disconnection in ms
136   bool     m_useIdealRrc; ///< If set to false, real RRC protocol model will be used
137   bool     m_admitRrcConnectionRequest; ///< If set to false, eNb will not allow UE connections
138   Ptr<LteHelper> m_lteHelper; ///< LTE helper
139 
140   /// key: IMSI
141   std::map<uint64_t, bool> m_isConnectionEstablished;
142 };
143 
144 
145 std::string
BuildNameString(uint32_t nUes,uint32_t nBearers,uint32_t tConnBase,uint32_t tConnIncrPerUe,uint32_t delayDiscStart,bool useIdealRrc,bool admitRrcConnectionRequest,std::string description)146 LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUes,
147                                                         uint32_t nBearers,
148                                                         uint32_t tConnBase,
149                                                         uint32_t tConnIncrPerUe,
150                                                         uint32_t delayDiscStart,
151                                                         bool useIdealRrc,
152                                                         bool admitRrcConnectionRequest,
153                                                         std::string description)
154 {
155   std::ostringstream oss;
156   oss << "nUes=" << nUes
157       << ", nBearers=" << nBearers
158       << ", tConnBase=" << tConnBase
159       << ", tConnIncrPerUe=" << tConnIncrPerUe
160       << ", delayDiscStart=" << delayDiscStart;
161 
162   if (useIdealRrc)
163     {
164       oss << ", ideal RRC";
165     }
166   else
167     {
168       oss << ", real RRC";
169     }
170 
171   if (admitRrcConnectionRequest)
172     {
173       oss << ", admitRrcConnectionRequest = true";
174     }
175   else
176     {
177       oss << ", admitRrcConnectionRequest = false";
178     }
179 
180   if (!description.empty ())
181     {
182       oss << ", " << description;
183     }
184 
185   return oss.str ();
186 }
187 
LteRrcConnectionEstablishmentTestCase(uint32_t nUes,uint32_t nBearers,uint32_t tConnBase,uint32_t tConnIncrPerUe,uint32_t delayDiscStart,bool errorExpected,bool useIdealRrc,bool admitRrcConnectionRequest,std::string description)188 LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (
189     uint32_t nUes, uint32_t nBearers,
190     uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart,
191     bool errorExpected, bool useIdealRrc, bool admitRrcConnectionRequest,
192     std::string description)
193   : TestCase (BuildNameString (nUes, nBearers,
194                                tConnBase, tConnIncrPerUe, delayDiscStart,
195                                useIdealRrc, admitRrcConnectionRequest,
196                                description)),
197     m_nUes (nUes),
198     m_nBearers (nBearers),
199     m_tConnBase (tConnBase),
200     m_tConnIncrPerUe (tConnIncrPerUe),
201 
202     m_delayDiscStart (delayDiscStart),
203     m_delayDiscEnd (10),
204     m_useIdealRrc (useIdealRrc),
205     m_admitRrcConnectionRequest (admitRrcConnectionRequest)
206 {
207   NS_LOG_FUNCTION (this << GetName ());
208 
209   // see the description of d^e in the LTE testing docs
210   double dsi = 90;
211   double nRaAttempts = 0;
212   if (nUes <= 20)
213     {
214       nRaAttempts += 5;
215     }
216   else
217     {
218       NS_ASSERT (nUes <= 50);
219       nRaAttempts += 10;
220     }
221 
222   nRaAttempts += std::ceil (nUes / 4.0);
223   double dra = nRaAttempts * 7;
224   double dce = 10.0 + (2.0 * nUes) / 4.0;
225   if (errorExpected)
226     {
227       /*
228        * If transmission error happens, the UE has to repeat again from
229        * acquiring system information.
230        */
231       dce += dsi + dce;
232     }
233   double nCrs;
234   if (nUes <= 2)
235     {
236       nCrs = 0;
237     }
238   else if (nUes <= 5)
239     {
240       nCrs = 1;
241     }
242   else if (nUes <= 10)
243     {
244       nCrs = 2;
245     }
246   else if (nUes <= 20)
247     {
248       nCrs = 3;
249     }
250   else
251     {
252       nCrs = 4;
253     }
254   double dcr =  (10.0 + (2.0 * nUes) / 4.0) * (m_nBearers + nCrs);
255 
256   m_delayConnEnd = round (dsi + dra + dce + dcr);
257   NS_LOG_LOGIC (this << " " << GetName () << " dsi=" << dsi << " dra=" << dra << " dce=" << dce << " dcr=" << dcr << " m_delayConnEnd=" << m_delayConnEnd);
258 }
259 
260 void
DoRun()261 LteRrcConnectionEstablishmentTestCase::DoRun ()
262 {
263   NS_LOG_FUNCTION (this << GetName ());
264   Config::Reset ();
265 
266   if (m_nUes < 25)
267     {
268       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (40));
269     }
270   else if (m_nUes < 60)
271     {
272       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (80));
273     }
274   else if (m_nUes < 120)
275     {
276       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (160));
277     }
278   else
279     {
280       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (320));
281     }
282 
283   // normal code
284   m_lteHelper = CreateObject<LteHelper> ();
285   m_lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_useIdealRrc));
286 
287   NodeContainer enbNodes;
288   NodeContainer ueNodes;
289 
290 
291   enbNodes.Create (1);
292   ueNodes.Create (m_nUes);
293 
294   // the following positions all nodes at (0, 0, 0)
295   MobilityHelper mobility;
296   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
297   mobility.Install (enbNodes);
298   mobility.Install (ueNodes);
299 
300   int64_t stream = 1;
301   NetDeviceContainer enbDevs;
302   enbDevs = m_lteHelper->InstallEnbDevice (enbNodes);
303   stream += m_lteHelper->AssignStreams (enbDevs, stream);
304 
305   NetDeviceContainer ueDevs;
306   ueDevs = m_lteHelper->InstallUeDevice (ueNodes);
307   stream += m_lteHelper->AssignStreams (ueDevs, stream);
308 
309   // custom code used for testing purposes
310   // instead of lteHelper->Attach () and lteHelper->ActivateXxx
311 
312   // Set AdmitConnectionRequest attribute
313   for (NetDeviceContainer::Iterator it = enbDevs.Begin ();
314        it != enbDevs.End ();
315        ++it)
316     {
317       Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice> ()->GetRrc ();
318       enbRrc->SetAttribute ("AdmitRrcConnectionRequest",
319                             BooleanValue (m_admitRrcConnectionRequest));
320     }
321 
322 
323   uint32_t i = 0;
324   uint32_t tmax = 0;
325   for (NetDeviceContainer::Iterator it = ueDevs.Begin (); it != ueDevs.End (); ++it)
326     {
327       Ptr<NetDevice> ueDevice = *it;
328       Ptr<NetDevice> enbDevice = enbDevs.Get (0);
329       Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
330 
331       uint32_t tc = m_tConnBase + m_tConnIncrPerUe * i; // time connection start
332       uint32_t tcc = tc + m_delayConnEnd; // time check connection completed;
333       uint32_t td =  tcc + m_delayDiscStart; // time disconnect start
334       uint32_t tcd = td + m_delayDiscEnd; // time check disconnection completed
335       tmax = std::max (tmax, tcd);
336 
337       // trick to resolve overloading
338       //void (LteHelper::* overloadedAttachFunctionPointer) (Ptr<NetDevice>, Ptr<NetDevice>) = &LteHelper::Attach;
339       //Simulator::Schedule (MilliSeconds (tc), overloadedAttachFunctionPointer, lteHelper, *it, enbDevice);
340       Simulator::Schedule (MilliSeconds (tc), &LteRrcConnectionEstablishmentTestCase::Connect, this, ueDevice, enbDevice);
341 
342       Simulator::Schedule (MilliSeconds (tcc), &LteRrcConnectionEstablishmentTestCase::CheckConnected, this, *it, enbDevice);
343 
344       // disconnection not supported yet
345 
346       uint64_t imsi = ueLteDevice->GetImsi ();
347       m_isConnectionEstablished[imsi] = false;
348 
349       ++i;
350     }
351 
352   // Connect to trace sources in UEs
353   Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished",
354                    MakeCallback (&LteRrcConnectionEstablishmentTestCase::ConnectionEstablishedCallback,
355                                  this));
356   Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionTimeout",
357                    MakeCallback (&LteRrcConnectionEstablishmentTestCase::ConnectionTimeoutCallback,
358                                  this));
359 
360   Simulator::Stop (MilliSeconds (tmax + 1));
361 
362   Simulator::Run ();
363 
364   Simulator::Destroy ();
365 
366 }
367 
368 void
Connect(Ptr<NetDevice> ueDevice,Ptr<NetDevice> enbDevice)369 LteRrcConnectionEstablishmentTestCase::Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
370 {
371   NS_LOG_FUNCTION (this);
372   m_lteHelper->Attach (ueDevice, enbDevice);
373 
374   for (uint32_t b = 0; b < m_nBearers; ++b)
375     {
376       enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
377       EpsBearer bearer (q);
378       m_lteHelper->ActivateDataRadioBearer (ueDevice, bearer);
379     }
380 }
381 
382 void
CheckConnected(Ptr<NetDevice> ueDevice,Ptr<NetDevice> enbDevice)383 LteRrcConnectionEstablishmentTestCase::CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
384 {
385   Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
386   Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc ();
387   const uint64_t imsi = ueLteDevice->GetImsi ();
388   const uint16_t rnti = ueRrc->GetRnti ();
389   NS_LOG_FUNCTION (this << imsi << rnti);
390   NS_ASSERT_MSG (m_isConnectionEstablished.find (imsi) != m_isConnectionEstablished.end (),
391                  "Invalid IMSI " << imsi);
392 
393   if (!m_admitRrcConnectionRequest)
394     {
395       NS_TEST_ASSERT_MSG_EQ (m_isConnectionEstablished[imsi], false,
396                              "Connection with RNTI " << rnti << " should have been rejected");
397       return;
398     }
399 
400   /*
401    * Verifying UE state in UE RRC. Try to increase the test case duration if
402    * the following checks.
403    */
404   NS_TEST_ASSERT_MSG_EQ (m_isConnectionEstablished[imsi], true,
405                          "RNTI " << rnti << " fails to establish connection");
406   NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::CONNECTED_NORMALLY,
407                          "RNTI " << rnti << " is not at CONNECTED_NORMALLY state");
408 
409   // Verifying UE context state in eNodeB RRC.
410 
411   Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
412   Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc ();
413   const bool hasContext = enbRrc->HasUeManager (rnti);
414 
415   if (hasContext)
416     {
417       Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
418       NS_ASSERT (ueManager != 0);
419       NS_TEST_ASSERT_MSG_EQ (ueManager->GetState (),
420                              UeManager::CONNECTED_NORMALLY,
421                              "The context of RNTI " << rnti << " is in invalid state");
422     }
423   else
424     {
425        NS_LOG_WARN (this << " RNTI " << rnti << " thinks that it has"
426                          << " established connection but the eNodeB thinks"
427                          << " that the UE has failed on connection setup.");
428        /*
429         * The standard specifies that this case would exceed the maximum
430         * retransmission limit at UE RLC (SRB1), which will then trigger an RLF.
431         * However, this behaviour is not implemented yet.
432         */
433     }
434 
435   // Verifying other attributes on both sides.
436 
437   uint16_t ueCellId = ueRrc->GetCellId ();
438   uint16_t enbCellId = enbLteDevice->GetCellId ();
439   uint16_t ueImsi = ueLteDevice->GetImsi ();
440 
441   uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth ();
442   uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth ();
443   uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth ();
444   uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth ();
445   uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn ();
446   uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn ();
447   uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn ();
448   uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn ();
449 
450   NS_TEST_ASSERT_MSG_EQ (ueCellId, enbCellId, "inconsistent CellId");
451   NS_TEST_ASSERT_MSG_EQ (ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth");
452   NS_TEST_ASSERT_MSG_EQ (ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth");
453   NS_TEST_ASSERT_MSG_EQ (ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn");
454   NS_TEST_ASSERT_MSG_EQ (ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn");
455 
456   if (hasContext)
457     {
458       Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
459       NS_ASSERT (ueManager != 0);
460       UeManager::State state = ueManager->GetState ();
461       uint16_t enbImsi = ueManager->GetImsi ();
462       NS_TEST_ASSERT_MSG_EQ (ueImsi, enbImsi, "inconsistent Imsi");
463 
464       if (state == UeManager::CONNECTED_NORMALLY)
465         {
466           ObjectMapValue enbDataRadioBearerMapValue;
467           ueManager->GetAttribute ("DataRadioBearerMap", enbDataRadioBearerMapValue);
468           NS_TEST_ASSERT_MSG_EQ (enbDataRadioBearerMapValue.GetN (), m_nBearers, "wrong num bearers at eNB");
469           ObjectMapValue ueDataRadioBearerMapValue;
470           ueRrc->GetAttribute ("DataRadioBearerMap", ueDataRadioBearerMapValue);
471           NS_TEST_ASSERT_MSG_EQ (ueDataRadioBearerMapValue.GetN (), m_nBearers, "wrong num bearers at UE");
472 
473           ObjectMapValue::Iterator enbBearerIt = enbDataRadioBearerMapValue.Begin ();
474           ObjectMapValue::Iterator ueBearerIt = ueDataRadioBearerMapValue.Begin ();
475           while (enbBearerIt != enbDataRadioBearerMapValue.End ()
476                  && ueBearerIt != ueDataRadioBearerMapValue.End ())
477             {
478               Ptr<LteDataRadioBearerInfo> enbDrbInfo = enbBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
479               Ptr<LteDataRadioBearerInfo> ueDrbInfo = ueBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
480               //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer differs");
481               NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_epsBearerIdentity, (uint32_t) ueDrbInfo->m_epsBearerIdentity, "epsBearerIdentity differs");
482               NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_drbIdentity, (uint32_t) ueDrbInfo->m_drbIdentity, "drbIdentity differs");
483               //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig differs");
484               NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_logicalChannelIdentity, (uint32_t) ueDrbInfo->m_logicalChannelIdentity, "logicalChannelIdentity differs");
485               //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig, ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs");
486 
487               ++enbBearerIt;
488               ++ueBearerIt;
489             }
490 
491           NS_ASSERT_MSG (enbBearerIt == enbDataRadioBearerMapValue.End (), "too many bearers at eNB");
492           NS_ASSERT_MSG (ueBearerIt == ueDataRadioBearerMapValue.End (), "too many bearers at UE");
493         }
494     }
495 }
496 
497 void
CheckNotConnected(Ptr<NetDevice> ueDevice,Ptr<NetDevice> enbDevice)498 LteRrcConnectionEstablishmentTestCase::CheckNotConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
499 {
500   Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
501   Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc ();
502   const uint64_t imsi = ueLteDevice->GetImsi ();
503   const uint16_t rnti = ueRrc->GetRnti ();
504   NS_LOG_FUNCTION (this << imsi << rnti);
505   NS_ASSERT_MSG (m_isConnectionEstablished.find (imsi) != m_isConnectionEstablished.end (),
506                  "Invalid IMSI " << imsi);
507 
508   bool ueStateIsConnectedNormally = (LteUeRrc::CONNECTED_NORMALLY == ueRrc->GetState ());
509 
510   Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
511   Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc ();
512   const bool hasContext = enbRrc->HasUeManager (rnti);
513   bool contextStateIsConnectedNormally = false;
514   if (hasContext)
515     {
516       Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
517       NS_ASSERT (ueManager != 0);
518       contextStateIsConnectedNormally = (UeManager::CONNECTED_NORMALLY == ueManager->GetState ());
519     }
520   NS_TEST_ASSERT_MSG_EQ ((!m_isConnectionEstablished[imsi]
521                           || !ueStateIsConnectedNormally
522                           || !hasContext
523                           || !contextStateIsConnectedNormally),
524                          true,
525                          "it should not happen that connection is completed both at the UE and at the eNB side");
526 }
527 
528 void
ConnectionEstablishedCallback(std::string context,uint64_t imsi,uint16_t cellId,uint16_t rnti)529 LteRrcConnectionEstablishmentTestCase::ConnectionEstablishedCallback (
530     std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
531 {
532   NS_LOG_FUNCTION (this << imsi << cellId);
533   m_isConnectionEstablished[imsi] = true;
534 }
535 
536 
537 void
ConnectionTimeoutCallback(std::string context,uint64_t imsi,uint16_t cellId,uint16_t rnti,uint8_t connEstFailCount)538 LteRrcConnectionEstablishmentTestCase::ConnectionTimeoutCallback (
539     std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti,
540     uint8_t connEstFailCount)
541 {
542   NS_LOG_FUNCTION (this << imsi << cellId);
543 }
544 
545 
546 
547 /**
548  * \ingroup lte-test
549  * \ingroup tests
550  *
551  * \brief Lte Rrc Connection Establishment Error Test Case
552  */
553 class LteRrcConnectionEstablishmentErrorTestCase
554   : public LteRrcConnectionEstablishmentTestCase
555 {
556 public:
557   /**
558    *
559    *
560    * \param jumpAwayTime the time when all the UEs 'teleport' to a pre-defined
561    *                     high-interference position and stay there for 100 ms
562    * \param description additional description of the test case
563    */
564   LteRrcConnectionEstablishmentErrorTestCase (Time jumpAwayTime,
565                                               std::string description = "");
566 protected:
567   virtual void DoRun (void);
568 
569 private:
570   /// Jump away function
571   void JumpAway ();
572   /// Jump back function
573   void JumpBack ();
574 
575   Time m_jumpAwayTime; ///< jump away time
576   Ptr<MobilityModel> m_ueMobility; ///< UE mobility model
577 };
578 
579 
LteRrcConnectionEstablishmentErrorTestCase(Time jumpAwayTime,std::string description)580 LteRrcConnectionEstablishmentErrorTestCase::LteRrcConnectionEstablishmentErrorTestCase (
581   Time jumpAwayTime, std::string description)
582   : LteRrcConnectionEstablishmentTestCase (1, 1, 0, 0, 1, true, false, true,
583                                            description),
584     m_jumpAwayTime (jumpAwayTime)
585 {
586   NS_LOG_FUNCTION (this << GetName ());
587 }
588 
589 
590 void
DoRun()591 LteRrcConnectionEstablishmentErrorTestCase::DoRun ()
592 {
593   NS_LOG_FUNCTION (this << GetName ());
594   Config::Reset ();
595 
596   if (m_nUes < 25)
597     {
598       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (40));
599     }
600   else if (m_nUes < 60)
601     {
602       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (80));
603     }
604   else if (m_nUes < 120)
605     {
606       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (160));
607     }
608   else
609     {
610       Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (320));
611     }
612 
613   // normal code
614   m_lteHelper = CreateObject<LteHelper> ();
615   m_lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_useIdealRrc));
616 
617   NodeContainer enbNodes;
618   NodeContainer ueNodes;
619 
620 
621   enbNodes.Create (4);
622   ueNodes.Create (1);
623 
624   MobilityHelper mobility;
625   mobility.Install (ueNodes); // UE position at (0, 0, 0)
626   m_ueMobility = ueNodes.Get (0)->GetObject<MobilityModel> ();
627 
628   Ptr<ListPositionAllocator> enbPosition = CreateObject<ListPositionAllocator> ();
629   enbPosition->Add (Vector (0, 0, 0));
630   enbPosition->Add (Vector (100.0, 0, 0));
631   enbPosition->Add (Vector (0, 100.0, 0));
632   enbPosition->Add (Vector (100.0, 100.0, 0));
633   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
634   mobility.SetPositionAllocator (enbPosition);
635   mobility.Install (enbNodes);
636 
637   int64_t stream = 1;
638   NetDeviceContainer enbDevs;
639   enbDevs = m_lteHelper->InstallEnbDevice (enbNodes);
640   stream += m_lteHelper->AssignStreams (enbDevs, stream);
641 
642   NetDeviceContainer ueDevs;
643   ueDevs = m_lteHelper->InstallUeDevice (ueNodes);
644   stream += m_lteHelper->AssignStreams (ueDevs, stream);
645 
646   // custom code used for testing purposes
647   // instead of lteHelper->Attach () and lteHelper->ActivateXxx
648 
649   // Set AdmitConnectionRequest attribute
650   for (NetDeviceContainer::Iterator it = enbDevs.Begin ();
651        it != enbDevs.End ();
652        ++it)
653     {
654       Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice> ()->GetRrc ();
655       enbRrc->SetAttribute ("AdmitRrcConnectionRequest",
656                             BooleanValue (m_admitRrcConnectionRequest));
657     }
658 
659 
660   uint32_t i = 0;
661   uint32_t tmax = 0;
662   for (NetDeviceContainer::Iterator it = ueDevs.Begin (); it != ueDevs.End (); ++it)
663     {
664       Ptr<NetDevice> ueDevice = *it;
665       Ptr<NetDevice> enbDevice = enbDevs.Get (0);
666       Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
667 
668       uint32_t tc = m_tConnBase + m_tConnIncrPerUe * i; // time connection start
669       uint32_t tcc = tc + m_delayConnEnd; // time check connection completed;
670       uint32_t td =  tcc + m_delayDiscStart; // time disconnect start
671       uint32_t tcd = td + m_delayDiscEnd; // time check disconnection completed
672       tmax = std::max (tmax, tcd);
673 
674       // trick to resolve overloading
675       //void (LteHelper::* overloadedAttachFunctionPointer) (Ptr<NetDevice>, Ptr<NetDevice>) = &LteHelper::Attach;
676       //Simulator::Schedule (MilliSeconds (tc), overloadedAttachFunctionPointer, lteHelper, *it, enbDevice);
677       Simulator::Schedule (MilliSeconds (tc), &LteRrcConnectionEstablishmentErrorTestCase::Connect, this, ueDevice, enbDevice);
678 
679       // disconnection not supported yet
680 
681       uint64_t imsi = ueLteDevice->GetImsi ();
682       m_isConnectionEstablished[imsi] = false;
683 
684       ++i;
685     }
686 
687   // Connect to trace sources in UEs
688   Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished",
689                    MakeCallback (&LteRrcConnectionEstablishmentErrorTestCase::ConnectionEstablishedCallback,
690                                  this));
691   Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionTimeout",
692                    MakeCallback (&LteRrcConnectionEstablishmentErrorTestCase::ConnectionTimeoutCallback,
693                                  this));
694 
695 
696   Simulator::Schedule (m_jumpAwayTime,
697                        &LteRrcConnectionEstablishmentErrorTestCase::JumpAway,
698                        this);
699   Simulator::Schedule (m_jumpAwayTime + MilliSeconds (99),
700                        &LteRrcConnectionEstablishmentErrorTestCase::CheckNotConnected,
701                        this, ueDevs.Get (0), enbDevs.Get (0));
702   Simulator::Schedule (m_jumpAwayTime + MilliSeconds (100),
703                        &LteRrcConnectionEstablishmentErrorTestCase::JumpBack,
704                        this);
705 
706   Simulator::Stop (MilliSeconds (tmax + 1));
707 
708   Simulator::Run ();
709 
710   Simulator::Destroy ();
711 
712 }
713 
714 
715 void
JumpAway()716 LteRrcConnectionEstablishmentErrorTestCase::JumpAway ()
717 {
718   NS_LOG_FUNCTION (this);
719   // move to a really far away location so that transmission errors occur
720   m_ueMobility->SetPosition (Vector (100000.0, 100000.0, 0.0));
721 }
722 
723 
724 void
JumpBack()725 LteRrcConnectionEstablishmentErrorTestCase::JumpBack ()
726 {
727   NS_LOG_FUNCTION (this);
728   m_ueMobility->SetPosition (Vector (0.0, 0.0, 0.0));
729 }
730 
731 
732 /**
733  * \ingroup lte-test
734  * \ingroup tests
735  *
736  * \brief Lte Rrc Test Suite
737  */
738 class LteRrcTestSuite : public TestSuite
739 {
740 public:
741   LteRrcTestSuite ();
742 };
743 
744 
LteRrcTestSuite()745 LteRrcTestSuite::LteRrcTestSuite ()
746   : TestSuite ("lte-rrc", SYSTEM)
747 {
748 //  LogComponentEnableAll (LOG_PREFIX_ALL);
749 //  LogComponentEnable ("LteRrcTest", LOG_LEVEL_ALL);
750 //  LogComponentEnable ("LteEnbRrc", LOG_INFO);
751 //  LogComponentEnable ("LteUeRrc", LOG_INFO);
752 
753   NS_LOG_FUNCTION (this);
754 
755   for (uint32_t useIdealRrc = 0; useIdealRrc <= 1; ++useIdealRrc)
756     {
757       //         <----- all times in ms ----------------->
758 
759       //                                                     nUes      tConnBase            delayDiscStart         useIdealRrc
760       //                                                        nBearers       tConnIncrPerUe       errorExpected               admitRrcConnectionRequest
761       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     0,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
762       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     0,    100,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
763       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     1,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
764       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     1,    100,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
765       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     2,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
766       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     2,    100,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
767       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
768       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,          10,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
769       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,         100,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
770       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
771       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,          10,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
772       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,         100,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
773       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     2,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
774       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     2,     20,          10,           1, false, useIdealRrc, true), TestCase::QUICK);
775       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     2,     20,         100,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
776       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  3,     0,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
777       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,     0,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
778       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,     0,     20,         300,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
779       AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 20,     0,     10,           1,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
780       AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 50,     0,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
781 
782       // Test cases to check admitRrcConnectionRequest=false
783       //                                                     nUes      tConnBase            delayDiscStart         useIdealRrc
784       //                                                        nBearers       tConnIncrPerUe       errorExpected               admitRrcConnectionRequest
785       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     0,      0,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
786       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     2,    100,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
787       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
788       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,           0,           1, false, useIdealRrc, false), TestCase::QUICK);
789       AddTestCase (new LteRrcConnectionEstablishmentTestCase (  3,     0,     20,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
790     }
791 
792   // Test cases with transmission error
793   AddTestCase (new LteRrcConnectionEstablishmentErrorTestCase (
794                    Seconds (0.020214),
795                    "failure at RRC Connection Request"),
796                TestCase::QUICK);
797   AddTestCase (new LteRrcConnectionEstablishmentErrorTestCase (
798                    Seconds (0.025),
799                    "failure at RRC Connection Setup"),
800                TestCase::QUICK);
801   /*
802    * With RLF implementation we now do support the Idle mode,
803    * thus it solve Bug 1762 Comment #25.
804    */
805    AddTestCase (new LteRrcConnectionEstablishmentErrorTestCase (
806                     Seconds (0.030),
807                     "failure at RRC Connection Setup Complete"),
808                 TestCase::QUICK);
809 
810 }
811 
812 static LteRrcTestSuite g_lteRrcTestSuiteInstance;
813