A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lte-test-cell-selection.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 Budiarto Herman
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Budiarto Herman <budiarto.herman@magister.fi>
7 *
8 */
9
11
12#include <ns3/boolean.h>
13#include <ns3/double.h>
14#include <ns3/integer.h>
15#include <ns3/internet-stack-helper.h>
16#include <ns3/ipv4-address-helper.h>
17#include <ns3/ipv4-interface-container.h>
18#include <ns3/ipv4-static-routing-helper.h>
19#include <ns3/log.h>
20#include <ns3/lte-enb-net-device.h>
21#include <ns3/lte-helper.h>
22#include <ns3/lte-ue-net-device.h>
23#include <ns3/lte-ue-rrc.h>
24#include <ns3/mobility-helper.h>
25#include <ns3/net-device-container.h>
26#include <ns3/node-container.h>
27#include <ns3/point-to-point-epc-helper.h>
28#include <ns3/point-to-point-helper.h>
29#include <ns3/rng-seed-manager.h>
30#include <ns3/simulator.h>
31
32using namespace ns3;
33
34NS_LOG_COMPONENT_DEFINE("LteCellSelectionTest");
35
36/*
37 * This test suite sets up four cells (four eNBs) and six UEs. Two of the
38 * cells are CSG and two are non-CSG. The six UEs associate with cells
39 * based on their positions and random access procedures. The test checks
40 * that the UEs, at specirfic simulation times, are associated to expected
41 * cells. See the header Doxygen for more specific descriptions.
42 *
43 * The test conditions that are checked rely on the RA preamble values
44 * (randomly selected) being unique for the six UEs. For most values of
45 * random seed and run number, this will be the case, but certain values
46 * will cause a collision (same RA preamble drawn for two UEs). Therefore,
47 * this test fixes the RngSeed and RngRun values, and uses AssignStreams,
48 * to ensure that an RA preamble collision does not occur.
49 */
50
52 : TestSuite("lte-cell-selection", Type::SYSTEM)
53{
54 std::vector<LteCellSelectionTestCase::UeSetup_t> w;
55
56 // REAL RRC PROTOCOL
57
58 w = {
59 // x, y, csgMember, checkPoint, cell1, cell2
60 LteCellSelectionTestCase::UeSetup_t(0.0, 0.55, false, MilliSeconds(283), 1, 0),
61 LteCellSelectionTestCase::UeSetup_t(0.0, 0.45, false, MilliSeconds(283), 1, 0),
62 LteCellSelectionTestCase::UeSetup_t(0.5, 0.45, false, MilliSeconds(363), 1, 3),
63 LteCellSelectionTestCase::UeSetup_t(0.5, 0.0, true, MilliSeconds(283), 2, 4),
64 LteCellSelectionTestCase::UeSetup_t(1.0, 0.55, true, MilliSeconds(283), 3, 0),
65 LteCellSelectionTestCase::UeSetup_t(1.0, 0.45, true, MilliSeconds(283), 4, 0),
66 };
67
68 AddTestCase(new LteCellSelectionTestCase("EPC, real RRC", true, false, 60.0 /* isd */, w),
69 TestCase::Duration::QUICK);
70
71 // IDEAL RRC PROTOCOL
72
73 w = {
74 // x, y, csgMember, checkPoint, cell1, cell2
75 LteCellSelectionTestCase::UeSetup_t(0.0, 0.55, false, MilliSeconds(266), 1, 0),
76 LteCellSelectionTestCase::UeSetup_t(0.0, 0.45, false, MilliSeconds(266), 1, 0),
77 LteCellSelectionTestCase::UeSetup_t(0.5, 0.45, false, MilliSeconds(346), 1, 3),
78 LteCellSelectionTestCase::UeSetup_t(0.5, 0.0, true, MilliSeconds(266), 2, 4),
79 LteCellSelectionTestCase::UeSetup_t(1.0, 0.55, true, MilliSeconds(266), 3, 0),
80 LteCellSelectionTestCase::UeSetup_t(1.0, 0.45, true, MilliSeconds(266), 4, 0),
81 };
82
83 AddTestCase(new LteCellSelectionTestCase("EPC, ideal RRC", true, true, 60.0 /* isd */, w),
84 TestCase::Duration::QUICK);
85
86} // end of LteCellSelectionTestSuite::LteCellSelectionTestSuite ()
87
88/**
89 * \ingroup lte-test
90 * Static variable for test initialization
91 */
93
94/*
95 * Test Case
96 */
97
99 double relPosY,
100 bool isCsgMember,
101 Time checkPoint,
102 uint16_t expectedCellId1,
103 uint16_t expectedCellId2)
104 : position(Vector(relPosX, relPosY, 0.0)),
105 isCsgMember(isCsgMember),
106 checkPoint(checkPoint),
107 expectedCellId1(expectedCellId1),
108 expectedCellId2(expectedCellId2)
109{
110}
111
113 bool isEpcMode,
114 bool isIdealRrc,
115 double interSiteDistance,
116 std::vector<UeSetup_t> ueSetupList)
117 : TestCase(name),
118 m_isEpcMode(isEpcMode),
119 m_isIdealRrc(isIdealRrc),
120 m_interSiteDistance(interSiteDistance),
121 m_ueSetupList(ueSetupList)
122{
123 NS_LOG_FUNCTION(this << GetName());
125}
126
131
132void
134{
135 NS_LOG_FUNCTION(this << GetName());
136
137 // In ns-3 test suite operation, static variables persist across all
138 // tests (all test suites execute within a single ns-3 process).
139 // Therefore, to fix a seed and run number for a specific test, the
140 // current values of seed and run number should be saved and restored
141 // after the test is run.
142 uint32_t previousSeed = RngSeedManager::GetSeed();
143 uint64_t previousRun = RngSeedManager::GetRun();
144 // Values of 1 and 2 here will prevent RA preamble collisions
145 Config::SetGlobal("RngSeed", UintegerValue(1));
146 Config::SetGlobal("RngRun", UintegerValue(2));
147
149 lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
150 lteHelper->SetAttribute("UseIdealRrc", BooleanValue(m_isIdealRrc));
151
153
154 if (m_isEpcMode)
155 {
157 lteHelper->SetEpcHelper(epcHelper);
158 }
159
160 /*
161 * The topology is the following (the number on the node indicate the cell ID)
162 *
163 * [1] [3]
164 * non-CSG -- non-CSG
165 * | |
166 * | | 60 m
167 * | |
168 * [2] [4]
169 * CSG ------ CSG
170 * 60 m
171 */
172
173 // Create Nodes
174 NodeContainer enbNodes;
175 enbNodes.Create(4);
176 NodeContainer ueNodes;
177 auto nUe = static_cast<uint16_t>(m_ueSetupList.size());
178 ueNodes.Create(nUe);
179
180 // Assign nodes to position
182 // eNodeB
183 positionAlloc->Add(Vector(0.0, m_interSiteDistance, 0.0));
184 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
185 positionAlloc->Add(Vector(m_interSiteDistance, m_interSiteDistance, 0.0));
186 positionAlloc->Add(Vector(m_interSiteDistance, 0.0, 0.0));
187 // UE
188 std::vector<UeSetup_t>::const_iterator itSetup;
189 for (itSetup = m_ueSetupList.begin(); itSetup != m_ueSetupList.end(); itSetup++)
190 {
191 Vector uePos(m_interSiteDistance * itSetup->position.x,
192 m_interSiteDistance * itSetup->position.y,
193 m_interSiteDistance * itSetup->position.z);
194 NS_LOG_INFO("UE position " << uePos);
195 positionAlloc->Add(uePos);
196 }
197
198 MobilityHelper mobility;
199 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
200 mobility.SetPositionAllocator(positionAlloc);
201 mobility.Install(enbNodes);
202 mobility.Install(ueNodes);
203
204 // Create Devices and install them in the Nodes (eNB and UE)
205 int64_t stream = 1;
206 NetDeviceContainer enbDevs;
207
208 // cell ID 1 is a non-CSG cell
209 lteHelper->SetEnbDeviceAttribute("CsgId", UintegerValue(0));
210 lteHelper->SetEnbDeviceAttribute("CsgIndication", BooleanValue(false));
211 enbDevs.Add(lteHelper->InstallEnbDevice(enbNodes.Get(0)));
212
213 // cell ID 2 is a CSG cell
214 lteHelper->SetEnbDeviceAttribute("CsgId", UintegerValue(1));
215 lteHelper->SetEnbDeviceAttribute("CsgIndication", BooleanValue(true));
216 enbDevs.Add(lteHelper->InstallEnbDevice(enbNodes.Get(1)));
217
218 // cell ID 3 is a non-CSG cell
219 lteHelper->SetEnbDeviceAttribute("CsgId", UintegerValue(0));
220 lteHelper->SetEnbDeviceAttribute("CsgIndication", BooleanValue(false));
221 enbDevs.Add(lteHelper->InstallEnbDevice(enbNodes.Get(2)));
222
223 // cell ID 4 is a CSG cell
224 lteHelper->SetEnbDeviceAttribute("CsgId", UintegerValue(1));
225 lteHelper->SetEnbDeviceAttribute("CsgIndication", BooleanValue(true));
226 enbDevs.Add(lteHelper->InstallEnbDevice(enbNodes.Get(3)));
227
228 NetDeviceContainer ueDevs;
229 Time lastCheckPoint = MilliSeconds(0);
230 NS_ASSERT(m_ueSetupList.size() == ueNodes.GetN());
232 for (itSetup = m_ueSetupList.begin(), itNode = ueNodes.Begin();
233 itSetup != m_ueSetupList.end() || itNode != ueNodes.End();
234 itSetup++, itNode++)
235 {
236 if (itSetup->isCsgMember)
237 {
238 lteHelper->SetUeDeviceAttribute("CsgId", UintegerValue(1));
239 }
240 else
241 {
242 lteHelper->SetUeDeviceAttribute("CsgId", UintegerValue(0));
243 }
244
245 NetDeviceContainer devs = lteHelper->InstallUeDevice(*itNode);
246 Ptr<LteUeNetDevice> ueDev = devs.Get(0)->GetObject<LteUeNetDevice>();
247 NS_ASSERT(ueDev);
248 ueDevs.Add(devs);
249 Simulator::Schedule(itSetup->checkPoint,
251 this,
252 ueDev,
253 itSetup->expectedCellId1,
254 itSetup->expectedCellId2);
255
256 if (lastCheckPoint < itSetup->checkPoint)
257 {
258 lastCheckPoint = itSetup->checkPoint;
259 }
260 }
261
262 stream += lteHelper->AssignStreams(enbDevs, stream);
263 stream += lteHelper->AssignStreams(ueDevs, stream);
264
265 // Tests
266 NS_ASSERT(m_ueSetupList.size() == ueDevs.GetN());
268 for (itSetup = m_ueSetupList.begin(), itDev = ueDevs.Begin();
269 itSetup != m_ueSetupList.end() || itDev != ueDevs.End();
270 itSetup++, itDev++)
271 {
272 Ptr<LteUeNetDevice> ueDev = (*itDev)->GetObject<LteUeNetDevice>();
273 }
274
275 if (m_isEpcMode)
276 {
277 // Create P-GW node
278 Ptr<Node> pgw = epcHelper->GetPgwNode();
279
280 // Create a single RemoteHost
281 NodeContainer remoteHostContainer;
282 remoteHostContainer.Create(1);
283 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
284 InternetStackHelper internet;
285 internet.Install(remoteHostContainer);
286
287 // Create the Internet
289 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
290 p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
291 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
292 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
293 Ipv4AddressHelper ipv4h;
294 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
295 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
296
297 // Routing of the Internet Host (towards the LTE network)
298 Ipv4StaticRoutingHelper ipv4RoutingHelper;
299 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
300 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
301 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"),
302 Ipv4Mask("255.0.0.0"),
303 1);
304
305 // Install the IP stack on the UEs
306 internet.Install(ueNodes);
307 Ipv4InterfaceContainer ueIpIfaces;
308 ueIpIfaces = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevs));
309
310 // Assign IP address to UEs
311 for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
312 {
313 Ptr<Node> ueNode = ueNodes.Get(u);
314 // Set the default gateway for the UE
315 Ptr<Ipv4StaticRouting> ueStaticRouting =
316 ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>());
317 ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
318 }
319
320 } // end of if (m_isEpcMode)
321 else
322 {
323 NS_FATAL_ERROR("No support yet for LTE-only simulations");
324 }
325
326 // Connect to trace sources in UEs
327 Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/StateTransition",
330 "/NodeList/*/DeviceList/*/LteUeRrc/InitialCellSelectionEndOk",
333 "/NodeList/*/DeviceList/*/LteUeRrc/InitialCellSelectionEndError",
335 Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished",
337
338 // Enable Idle mode cell selection
339 lteHelper->Attach(ueDevs);
340
341 // Run simulation
342 Simulator::Stop(lastCheckPoint);
344
345 NS_LOG_INFO("Simulation ends");
347
348 // Restore the seed and run number that were in effect before this test
349 Config::SetGlobal("RngSeed", UintegerValue(previousSeed));
350 Config::SetGlobal("RngRun", UintegerValue(previousRun));
351
352} // end of void LteCellSelectionTestCase::DoRun ()
353
354void
356 uint16_t expectedCellId1,
357 uint16_t expectedCellId2)
358{
359 uint16_t actualCellId = ueDev->GetRrc()->GetCellId();
360
361 if (expectedCellId2 == 0)
362 {
363 NS_TEST_ASSERT_MSG_EQ(actualCellId,
364 expectedCellId1,
365 "IMSI " << ueDev->GetImsi() << " has attached to an unexpected cell");
366 }
367 else
368 {
369 bool pass = (actualCellId == expectedCellId1) || (actualCellId == expectedCellId2);
371 true,
372 "IMSI " << ueDev->GetImsi() << " has attached to an unexpected cell"
373 << " (actual: " << actualCellId << ","
374 << " expected: " << expectedCellId1 << " or "
375 << expectedCellId2 << ")");
376 }
377
378 if (expectedCellId1 > 0)
379 {
380 NS_TEST_ASSERT_MSG_EQ(m_lastState.at(static_cast<unsigned int>(ueDev->GetImsi() - 1)),
382 "UE " << ueDev->GetImsi() << " is not at CONNECTED_NORMALLY state");
383 }
384}
385
386void
388 uint64_t imsi,
389 uint16_t cellId,
390 uint16_t rnti,
391 LteUeRrc::State oldState,
392 LteUeRrc::State newState)
393{
394 NS_LOG_FUNCTION(this << imsi << cellId << rnti << oldState << newState);
395 m_lastState.at(static_cast<unsigned int>(imsi - 1)) = newState;
396}
397
398void
400 uint64_t imsi,
401 uint16_t cellId)
402{
403 NS_LOG_FUNCTION(this << imsi << cellId);
404}
405
406void
408 uint64_t imsi,
409 uint16_t cellId)
410{
411 NS_LOG_FUNCTION(this << imsi << cellId);
412}
413
414void
416 uint64_t imsi,
417 uint16_t cellId,
418 uint16_t rnti)
419{
420 NS_LOG_FUNCTION(this << imsi << cellId << rnti);
421}
Testing the initial cell selection procedure by UE at IDLE state in the beginning of simulation.
std::vector< UeSetup_t > m_ueSetupList
UE setup list.
void CheckPoint(Ptr< LteUeNetDevice > ueDev, uint16_t expectedCellId1, uint16_t expectedCellId2)
Verifies if the given UE is attached to either of the given two cells and in a CONNECTED_NORMALLY sta...
void InitialCellSelectionEndOkCallback(std::string context, uint64_t imsi, uint16_t cellId)
Initial cell selection end ok callback function.
std::vector< LteUeRrc::State > m_lastState
The current UE RRC state.
LteCellSelectionTestCase(std::string name, bool isEpcMode, bool isIdealRrc, double interSiteDistance, std::vector< UeSetup_t > ueSetupList)
Creates an instance of the initial cell selection test case.
void DoRun() override
Setup the simulation according to the configuration set by the class constructor, run it,...
bool m_isEpcMode
whether the LTE configuration in test is using EPC
double m_interSiteDistance
inter site distance
void ConnectionEstablishedCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
Connection established callback function.
void InitialCellSelectionEndErrorCallback(std::string context, uint64_t imsi, uint16_t cellId)
Initial cell selection end error callback function.
bool m_isIdealRrc
whether the LTE is configured to use ideal RRC
void StateTransitionCallback(std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, LteUeRrc::State oldState, LteUeRrc::State newState)
State transition callback function.
Test suite for executing the cell selection test cases in without-EPC and with-EPC scenarios.
Class for representing data rates.
Definition data-rate.h:78
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition ipv4.h:69
holds a vector of std::pair of Ptr<Ipv4> and interface index.
a class to represent an Ipv4 address mask
Helper class that adds ns3::Ipv4StaticRouting objects.
Ptr< Ipv4StaticRouting > GetStaticRouting(Ptr< Ipv4 > ipv4) const
Try and find the static routing protocol as either the main routing protocol or in the list of routin...
The LteUeNetDevice class implements the UE net device.
State
The states of the UE RRC entity.
Definition lte-ue-rrc.h:88
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
Iterator Begin() const
Get an iterator which refers to the first NetDevice in the container.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Iterator End() const
Get an iterator which indicates past-the-last NetDevice in the container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
Iterator End() const
Get an iterator which indicates past-the-last Node in the container.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Iterator Begin() const
Get an iterator which refers to the first Node in the container.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Build a set of PointToPointNetDevice objects.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
NetDeviceContainer Install(NodeContainer c)
Smart pointer class similar to boost::intrusive_ptr.
static uint64_t GetRun()
Get the current run number.
static uint32_t GetSeed()
Get the current seed value which will be used by all subsequently instantiated RandomVariableStream o...
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
std::string GetName() const
Definition test.cc:367
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
void SetGlobal(std::string name, const AttributeValue &value)
Definition config.cc:929
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:967
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
static LteCellSelectionTestSuite g_lteCellSelectionTestSuite
Static variable for test initialization.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
A set of input parameters for setting up a UE in the simulation.
UeSetup_t(double relPosX, double relPosY, bool isCsgMember, Time checkPoint, uint16_t expectedCellId1, uint16_t expectedCellId2)
UE test setup function.