1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2013 Budiarto Herman
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: Budiarto Herman <budiarto.herman@magister.fi>
19 *
20 */
21
22 #include "lte-test-cell-selection.h"
23
24 #include <ns3/simulator.h>
25 #include <ns3/log.h>
26 #include <ns3/boolean.h>
27 #include <ns3/double.h>
28 #include <ns3/integer.h>
29
30 #include <ns3/mobility-helper.h>
31 #include <ns3/lte-helper.h>
32 #include <ns3/point-to-point-epc-helper.h>
33 #include <ns3/internet-stack-helper.h>
34 #include <ns3/point-to-point-helper.h>
35 #include <ns3/ipv4-address-helper.h>
36 #include <ns3/ipv4-static-routing-helper.h>
37
38 #include <ns3/node-container.h>
39 #include <ns3/net-device-container.h>
40 #include <ns3/ipv4-interface-container.h>
41
42 #include <ns3/lte-ue-net-device.h>
43 #include <ns3/lte-ue-rrc.h>
44 #include <ns3/lte-enb-net-device.h>
45
46 using namespace ns3;
47
48 NS_LOG_COMPONENT_DEFINE ("LteCellSelectionTest");
49
50 /*
51 * Test Suite
52 */
53
54
LteCellSelectionTestSuite()55 LteCellSelectionTestSuite::LteCellSelectionTestSuite ()
56 : TestSuite ("lte-cell-selection", SYSTEM)
57 {
58 std::vector<LteCellSelectionTestCase::UeSetup_t> w;
59
60 // REAL RRC PROTOCOL
61
62 w.clear ();
63 // x y csgMember
64 // checkPoint cell1, cell2
65 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.0, 0.55, false,
66 MilliSeconds (283), 1, 0));
67 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.0, 0.45, false,
68 MilliSeconds (283), 1, 0));
69 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.5, 0.45, false,
70 MilliSeconds (363), 1, 3));
71 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.5, 0.0, true,
72 MilliSeconds (283), 2, 4));
73 w.push_back (LteCellSelectionTestCase::UeSetup_t (1.0, 0.55, true,
74 MilliSeconds (283), 3, 0));
75 w.push_back (LteCellSelectionTestCase::UeSetup_t (1.0, 0.45, true,
76 MilliSeconds (283), 4, 0));
77
78 AddTestCase (new LteCellSelectionTestCase ("EPC, real RRC, RngNum=1",
79 true, false, 60.0, w, 1),
80 // isd rngrun
81 TestCase::QUICK);
82
83 // IDEAL RRC PROTOCOL
84
85 w.clear ();
86 // x y csgMember
87 // checkPoint cell1, cell2
88 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.0, 0.55, false,
89 MilliSeconds (266), 1, 0));
90 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.0, 0.45, false,
91 MilliSeconds (266), 1, 0));
92 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.5, 0.45, false,
93 MilliSeconds (346), 1, 3));
94 w.push_back (LteCellSelectionTestCase::UeSetup_t (0.5, 0.0, true,
95 MilliSeconds (266), 2, 4));
96 w.push_back (LteCellSelectionTestCase::UeSetup_t (1.0, 0.55, true,
97 MilliSeconds (266), 3, 0));
98 w.push_back (LteCellSelectionTestCase::UeSetup_t (1.0, 0.45, true,
99 MilliSeconds (266), 4, 0));
100
101 AddTestCase (new LteCellSelectionTestCase ("EPC, ideal RRC, RngNum=1",
102 true, true, 60.0, w, 1),
103 // isd rngrun
104 TestCase::QUICK);
105
106 } // end of LteCellSelectionTestSuite::LteCellSelectionTestSuite ()
107
108
109 static LteCellSelectionTestSuite g_lteCellSelectionTestSuite;
110
111
112
113 /*
114 * Test Case
115 */
116
117
UeSetup_t(double relPosX,double relPosY,bool isCsgMember,Time checkPoint,uint16_t expectedCellId1,uint16_t expectedCellId2)118 LteCellSelectionTestCase::UeSetup_t::UeSetup_t (
119 double relPosX, double relPosY, bool isCsgMember, Time checkPoint,
120 uint16_t expectedCellId1, uint16_t expectedCellId2)
121 : position (Vector (relPosX, relPosY, 0.0)),
122 isCsgMember (isCsgMember),
123 checkPoint (checkPoint),
124 expectedCellId1 (expectedCellId1),
125 expectedCellId2 (expectedCellId2)
126 {
127 }
128
129
LteCellSelectionTestCase(std::string name,bool isEpcMode,bool isIdealRrc,double interSiteDistance,std::vector<UeSetup_t> ueSetupList,uint64_t rngRun)130 LteCellSelectionTestCase::LteCellSelectionTestCase (
131 std::string name, bool isEpcMode, bool isIdealRrc,
132 double interSiteDistance,
133 std::vector<UeSetup_t> ueSetupList, uint64_t rngRun)
134 : TestCase (name),
135 m_isEpcMode (isEpcMode),
136 m_isIdealRrc (isIdealRrc),
137 m_interSiteDistance (interSiteDistance),
138 m_ueSetupList (ueSetupList),
139 m_rngRun (rngRun)
140 {
141 NS_LOG_FUNCTION (this << GetName ());
142 m_lastState.resize (m_ueSetupList.size (), LteUeRrc::NUM_STATES);
143 }
144
145
~LteCellSelectionTestCase()146 LteCellSelectionTestCase::~LteCellSelectionTestCase ()
147 {
148 NS_LOG_FUNCTION (this << GetName ());
149 }
150
151
152 void
DoRun()153 LteCellSelectionTestCase::DoRun ()
154 {
155 NS_LOG_FUNCTION (this << GetName ());
156
157 Config::SetGlobal ("RngRun", UintegerValue (m_rngRun));
158
159 Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
160 lteHelper->SetAttribute ("PathlossModel",
161 StringValue ("ns3::FriisSpectrumPropagationLossModel"));
162 lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_isIdealRrc));
163
164 Ptr<PointToPointEpcHelper> epcHelper;
165
166 if (m_isEpcMode)
167 {
168 epcHelper = CreateObject<PointToPointEpcHelper> ();
169 lteHelper->SetEpcHelper (epcHelper);
170 }
171
172 /*
173 * The topology is the following (the number on the node indicate the cell ID)
174 *
175 * [1] [3]
176 * non-CSG -- non-CSG
177 * | |
178 * | | 60 m
179 * | |
180 * [2] [4]
181 * CSG ------ CSG
182 * 60 m
183 */
184
185 // Create Nodes
186 NodeContainer enbNodes;
187 enbNodes.Create (4);
188 NodeContainer ueNodes;
189 uint16_t nUe = static_cast<uint16_t> (m_ueSetupList.size ());
190 ueNodes.Create (nUe);
191
192 // Assign nodes to position
193 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
194 // eNodeB
195 positionAlloc->Add (Vector ( 0.0, m_interSiteDistance, 0.0));
196 positionAlloc->Add (Vector ( 0.0, 0.0, 0.0));
197 positionAlloc->Add (Vector (m_interSiteDistance, m_interSiteDistance, 0.0));
198 positionAlloc->Add (Vector (m_interSiteDistance, 0.0, 0.0));
199 // UE
200 std::vector<UeSetup_t>::const_iterator itSetup;
201 for (itSetup = m_ueSetupList.begin ();
202 itSetup != m_ueSetupList.end (); itSetup++)
203 {
204 Vector uePos (m_interSiteDistance * itSetup->position.x,
205 m_interSiteDistance * itSetup->position.y,
206 m_interSiteDistance * itSetup->position.z);
207 NS_LOG_INFO ("UE position " << uePos);
208 positionAlloc->Add (uePos);
209 }
210
211 MobilityHelper mobility;
212 mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
213 mobility.SetPositionAllocator (positionAlloc);
214 mobility.Install (enbNodes);
215 mobility.Install (ueNodes);
216
217 // Create Devices and install them in the Nodes (eNB and UE)
218 int64_t stream = 1;
219 NetDeviceContainer enbDevs;
220
221 // cell ID 1 is a non-CSG cell
222 lteHelper->SetEnbDeviceAttribute ("CsgId", UintegerValue (0));
223 lteHelper->SetEnbDeviceAttribute ("CsgIndication", BooleanValue (false));
224 enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
225
226 // cell ID 2 is a CSG cell
227 lteHelper->SetEnbDeviceAttribute ("CsgId", UintegerValue (1));
228 lteHelper->SetEnbDeviceAttribute ("CsgIndication", BooleanValue (true));
229 enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
230
231 // cell ID 3 is a non-CSG cell
232 lteHelper->SetEnbDeviceAttribute ("CsgId", UintegerValue (0));
233 lteHelper->SetEnbDeviceAttribute ("CsgIndication", BooleanValue (false));
234 enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (2)));
235
236 // cell ID 4 is a CSG cell
237 lteHelper->SetEnbDeviceAttribute ("CsgId", UintegerValue (1));
238 lteHelper->SetEnbDeviceAttribute ("CsgIndication", BooleanValue (true));
239 enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (3)));
240
241 NetDeviceContainer ueDevs;
242 Time lastCheckPoint = MilliSeconds (0);
243 NS_ASSERT (m_ueSetupList.size () == ueNodes.GetN ());
244 NodeContainer::Iterator itNode;
245 for (itSetup = m_ueSetupList.begin (), itNode = ueNodes.Begin ();
246 itSetup != m_ueSetupList.end () || itNode != ueNodes.End ();
247 itSetup++, itNode++)
248 {
249 if (itSetup->isCsgMember)
250 {
251 lteHelper->SetUeDeviceAttribute ("CsgId", UintegerValue (1));
252 }
253 else
254 {
255 lteHelper->SetUeDeviceAttribute ("CsgId", UintegerValue (0));
256 }
257
258 NetDeviceContainer devs = lteHelper->InstallUeDevice (*itNode);
259 Ptr<LteUeNetDevice> ueDev = devs.Get (0)->GetObject<LteUeNetDevice> ();
260 NS_ASSERT (ueDev != 0);
261 ueDevs.Add (devs);
262 Simulator::Schedule (itSetup->checkPoint,
263 &LteCellSelectionTestCase::CheckPoint,
264 this, ueDev,
265 itSetup->expectedCellId1, itSetup->expectedCellId2);
266
267 if (lastCheckPoint < itSetup->checkPoint)
268 {
269 lastCheckPoint = itSetup->checkPoint;
270 }
271 }
272
273 stream += lteHelper->AssignStreams (enbDevs, stream);
274 stream += lteHelper->AssignStreams (ueDevs, stream);
275
276 // Tests
277 NS_ASSERT (m_ueSetupList.size () == ueDevs.GetN ());
278 NetDeviceContainer::Iterator itDev;
279 for (itSetup = m_ueSetupList.begin (), itDev = ueDevs.Begin ();
280 itSetup != m_ueSetupList.end () || itDev != ueDevs.End ();
281 itSetup++, itDev++)
282 {
283 Ptr<LteUeNetDevice> ueDev = (*itDev)->GetObject<LteUeNetDevice> ();
284 }
285
286 if (m_isEpcMode)
287 {
288 // Create P-GW node
289 Ptr<Node> pgw = epcHelper->GetPgwNode ();
290
291 // Create a single RemoteHost
292 NodeContainer remoteHostContainer;
293 remoteHostContainer.Create (1);
294 Ptr<Node> remoteHost = remoteHostContainer.Get (0);
295 InternetStackHelper internet;
296 internet.Install (remoteHostContainer);
297
298 // Create the Internet
299 PointToPointHelper p2ph;
300 p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
301 p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
302 p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
303 NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
304 Ipv4AddressHelper ipv4h;
305 ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
306 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
307
308 // Routing of the Internet Host (towards the LTE network)
309 Ipv4StaticRoutingHelper ipv4RoutingHelper;
310 Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
311 remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
312
313 // Install the IP stack on the UEs
314 internet.Install (ueNodes);
315 Ipv4InterfaceContainer ueIpIfaces;
316 ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevs));
317
318 // Assign IP address to UEs
319 for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
320 {
321 Ptr<Node> ueNode = ueNodes.Get (u);
322 // Set the default gateway for the UE
323 Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
324 ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
325 }
326
327 } // end of if (m_isEpcMode)
328 else
329 {
330 NS_FATAL_ERROR ("No support yet for LTE-only simulations");
331 }
332
333 // Connect to trace sources in UEs
334 Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/StateTransition",
335 MakeCallback (&LteCellSelectionTestCase::StateTransitionCallback,
336 this));
337 Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/InitialCellSelectionEndOk",
338 MakeCallback (&LteCellSelectionTestCase::InitialCellSelectionEndOkCallback,
339 this));
340 Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/InitialCellSelectionEndError",
341 MakeCallback (&LteCellSelectionTestCase::InitialCellSelectionEndErrorCallback,
342 this));
343 Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished",
344 MakeCallback (&LteCellSelectionTestCase::ConnectionEstablishedCallback,
345 this));
346
347 // Enable Idle mode cell selection
348 lteHelper->Attach (ueDevs);
349
350 // Run simulation
351 Simulator::Stop (lastCheckPoint);
352 Simulator::Run ();
353
354 NS_LOG_INFO ("Simulation ends");
355 Simulator::Destroy ();
356
357 } // end of void LteCellSelectionTestCase::DoRun ()
358
359
360 void
CheckPoint(Ptr<LteUeNetDevice> ueDev,uint16_t expectedCellId1,uint16_t expectedCellId2)361 LteCellSelectionTestCase::CheckPoint (Ptr<LteUeNetDevice> ueDev,
362 uint16_t expectedCellId1,
363 uint16_t expectedCellId2)
364 {
365 uint16_t actualCellId = ueDev->GetRrc ()->GetCellId ();
366
367 if (expectedCellId2 == 0)
368 {
369 NS_TEST_ASSERT_MSG_EQ (actualCellId, expectedCellId1,
370 "IMSI " << ueDev->GetImsi ()
371 << " has attached to an unexpected cell");
372 }
373 else
374 {
375 bool pass = (actualCellId == expectedCellId1) ||
376 (actualCellId == expectedCellId2);
377 NS_TEST_ASSERT_MSG_EQ (pass, true,
378 "IMSI " << ueDev->GetImsi ()
379 << " has attached to an unexpected cell"
380 << " (actual: " << actualCellId << ","
381 << " expected: " << expectedCellId1
382 << " or " << expectedCellId2 << ")");
383 }
384
385 if (expectedCellId1 > 0)
386 {
387 NS_TEST_ASSERT_MSG_EQ (m_lastState.at (static_cast<unsigned int>(ueDev->GetImsi () - 1)),
388 LteUeRrc::CONNECTED_NORMALLY,
389 "UE " << ueDev->GetImsi ()
390 << " is not at CONNECTED_NORMALLY state");
391 }
392 }
393
394
395 void
StateTransitionCallback(std::string context,uint64_t imsi,uint16_t cellId,uint16_t rnti,LteUeRrc::State oldState,LteUeRrc::State newState)396 LteCellSelectionTestCase::StateTransitionCallback (
397 std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti,
398 LteUeRrc::State oldState, LteUeRrc::State newState)
399 {
400 NS_LOG_FUNCTION (this << imsi << cellId << rnti << oldState << newState);
401 m_lastState.at (static_cast<unsigned int>(imsi - 1)) = newState;
402 }
403
404
405 void
InitialCellSelectionEndOkCallback(std::string context,uint64_t imsi,uint16_t cellId)406 LteCellSelectionTestCase::InitialCellSelectionEndOkCallback (
407 std::string context, uint64_t imsi, uint16_t cellId)
408 {
409 NS_LOG_FUNCTION (this << imsi << cellId);
410 }
411
412
413 void
InitialCellSelectionEndErrorCallback(std::string context,uint64_t imsi,uint16_t cellId)414 LteCellSelectionTestCase::InitialCellSelectionEndErrorCallback (
415 std::string context, uint64_t imsi, uint16_t cellId)
416 {
417 NS_LOG_FUNCTION (this << imsi << cellId);
418 }
419
420
421 void
ConnectionEstablishedCallback(std::string context,uint64_t imsi,uint16_t cellId,uint16_t rnti)422 LteCellSelectionTestCase::ConnectionEstablishedCallback (
423 std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
424 {
425 NS_LOG_FUNCTION (this << imsi << cellId << rnti);
426 }
427