5G-LENA nr-v3.0-32-g83aee33
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
system-scheduler-test.cc
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// SPDX-License-Identifier: GPL-2.0-only
6
8
9#include <ns3/antenna-module.h>
10#include <ns3/applications-module.h>
11#include <ns3/config.h>
12#include <ns3/internet-module.h>
13#include <ns3/nr-module.h>
14#include <ns3/packet.h>
15#include <ns3/point-to-point-helper.h>
16#include <ns3/pointer.h>
17#include <ns3/simulator.h>
18#include <ns3/uinteger.h>
19
20namespace ns3
21{
22
23void
24SystemSchedulerTest::CountPkts([[maybe_unused]] Ptr<const Packet> pkt)
25{
26 m_packets++;
27 if (m_packets == m_limit)
28 {
29 Simulator::Stop();
30 }
31}
32
34 uint32_t usersPerBeamNum,
35 uint32_t numOfBeams,
36 uint32_t numerology,
37 double bw1,
38 bool isDownlnk,
39 bool isUplink,
40 const std::string& schedulerType)
41 : TestCase(name)
42{
43 m_numerology = numerology;
44 m_bw1 = bw1;
45 m_isDownlink = isDownlnk;
46 m_isUplink = isUplink;
47 m_usersPerBeamNum = usersPerBeamNum;
48 NS_ABORT_MSG_UNLESS(numOfBeams <= 4,
49 "Test program is designed to support up to 4 beams per gNB");
50 m_numOfBeams = numOfBeams;
51 m_schedulerType = schedulerType;
52 m_name = name;
53}
54
55// This destructor does nothing but we include it as a reminder that
56// the test case should clean up after itself
60
61void
62SystemSchedulerTest::DoRun()
63{
64 NS_ABORT_IF(!m_isUplink && !m_isDownlink);
65
66 // set simulation time and mobility
67 Time simTime = MilliSeconds(800);
68 Time udpAppStartTimeDl = MilliSeconds(400);
69 Time udpAppStartTimeUl = MilliSeconds(400);
70 Time udpAppStopTimeDl = MilliSeconds(800); // Let's give 0.4s for the traffic
71 Time udpAppStopTimeUl = MilliSeconds(800); // Let's give 0.4s for the traffic
72 uint16_t gNbNum = 1;
73 uint32_t packetSize = 100;
74 uint32_t maxPackets = 400;
75 DataRate udpRate = DataRate("320kbps"); // 400 packets of 800 bits
76
77 Config::SetDefault("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue(999999999));
78 Config::SetDefault("ns3::LteRlcUm::ReorderingTimer", TimeValue(Seconds(1)));
79 Config::SetDefault("ns3::EpsBearer::Release", UintegerValue(15));
80
81 Config::SetDefault(
82 "ns3::NrUePhy::EnableUplinkPowerControl",
83 BooleanValue(
84 false)); // scheduler tests are designed to expect the maximum transmit power, maximum
85 // MCS, thus uplink power control is not compatible, because it will adjust
86
87 // create base stations and mobile terminals
88 NodeContainer gNbNodes;
89 NodeContainer ueNodes;
90 MobilityHelper mobility;
91
92 double gNbHeight = 10;
93 double ueHeight = 1.5;
94 gNbNodes.Create(gNbNum);
95 ueNodes.Create(m_usersPerBeamNum * m_numOfBeams * gNbNum);
96
97 Ptr<ListPositionAllocator> apPositionAlloc = CreateObject<ListPositionAllocator>();
98 Ptr<ListPositionAllocator> staPositionAlloc = CreateObject<ListPositionAllocator>();
99
100 double gNbx = 0;
101 double gNby = 0;
102
103 for (uint32_t gNb = 0; gNb < gNbNum; gNb++)
104 {
105 apPositionAlloc->Add(Vector(gNbx, gNby, gNbHeight));
106
107 for (uint32_t beam = 1; beam <= m_numOfBeams; beam++)
108 {
109 for (uint32_t uePerBeamIndex = 0; uePerBeamIndex < m_usersPerBeamNum; uePerBeamIndex++)
110 {
111 if (beam == 1)
112 {
113 staPositionAlloc->Add(Vector(gNbx + 1 + 0.1 * uePerBeamIndex,
114 gNby + 10 + 0.1 * uePerBeamIndex,
115 ueHeight));
116 }
117 else if (beam == 2)
118 {
119 staPositionAlloc->Add(Vector(gNbx + 10 + 0.1 * uePerBeamIndex,
120 gNby - 1 + 0.1 * uePerBeamIndex,
121 ueHeight));
122 }
123 else if (beam == 3)
124 {
125 staPositionAlloc->Add(Vector(gNbx - 1 + 0.1 * uePerBeamIndex,
126 gNby - 10 + 0.1 * uePerBeamIndex,
127 ueHeight));
128 }
129 else if (beam == 4)
130 {
131 staPositionAlloc->Add(Vector(gNbx - 10 + 0.1 * uePerBeamIndex,
132 gNby + 1 + 0.1 * uePerBeamIndex,
133 ueHeight));
134 }
135 }
136 }
137
138 // position of next gNB and its UE is shiftened for 20, 20
139 gNbx += 1;
140 gNby += 1;
141 }
142 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
143 mobility.SetPositionAllocator(apPositionAlloc);
144 mobility.Install(gNbNodes);
145 mobility.SetPositionAllocator(staPositionAlloc);
146 mobility.Install(ueNodes);
147
148 // setup the mmWave simulation
149 Ptr<NrPointToPointEpcHelper> epcHelper = CreateObject<NrPointToPointEpcHelper>();
150
151 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
152 idealBeamformingHelper->SetAttribute("BeamformingMethod",
153 TypeIdValue(CellScanBeamforming::GetTypeId()));
154 idealBeamformingHelper->SetBeamformingAlgorithmAttribute("BeamSearchAngleStep",
155 DoubleValue(10.0));
156
157 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
158 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
159
160 // set the number of antenna elements of UE
161 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(2));
162 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(4));
163 nrHelper->SetUeAntennaAttribute("AntennaElement",
164 PointerValue(CreateObject<IsotropicAntennaModel>()));
165
166 // UE transmit power
167 nrHelper->SetUePhyAttribute("TxPower", DoubleValue(20.0));
168
169 // set the number of antenna elements of gNbs
170 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(4));
171 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
172 nrHelper->SetGnbAntennaAttribute("AntennaElement",
173 PointerValue(CreateObject<ThreeGppAntennaModel>()));
174
175 // gNB transmit power
176 nrHelper->SetGnbPhyAttribute("TxPower", DoubleValue(44.0));
177
178 // gNB numerology
179 nrHelper->SetGnbPhyAttribute("Numerology", UintegerValue(m_numerology));
180
181 // Set the scheduler type
182 nrHelper->SetSchedulerTypeId(TypeId::LookupByName(m_schedulerType));
183 Config::SetDefault("ns3::NrAmc::ErrorModelType",
184 TypeIdValue(TypeId::LookupByName("ns3::NrEesmCcT1")));
185 nrHelper->SetSchedulerAttribute("FixedMcsDl", BooleanValue(true));
186 nrHelper->SetSchedulerAttribute("FixedMcsUl", BooleanValue(true));
187 nrHelper->SetSchedulerAttribute("StartingMcsDl", UintegerValue(28));
188 nrHelper->SetSchedulerAttribute("StartingMcsUl", UintegerValue(28));
189
190 nrHelper->SetEpcHelper(epcHelper);
191
192 /*
193 * Spectrum division. We create two operational bands, each of them containing
194 * one component carrier, and each CC containing a single bandwidth part
195 * centered at the frequency specified by the input parameters.
196 * Each spectrum part length is, as well, specified by the input parameters.
197 * Both operational bands will use the StreetCanyon channel modeling.
198 */
200 CcBwpCreator ccBwpCreator;
201 double centralFrequency = 28e9;
202 double bandwidth = m_bw1;
203 const uint8_t numCcPerBand = 1;
205 CcBwpCreator::SimpleOperationBandConf bandConf(centralFrequency,
206 bandwidth,
207 numCcPerBand,
208 scenario);
209
210 // By using the configuration created, it is time to make the operation bands
211 OperationBandInfo band = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
212
213 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(MilliSeconds(0)));
214
215 // Shadowing
216 nrHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
217
218 /*
219 * Initialize channel and pathloss, plus other things inside band1. If needed,
220 * the band configuration can be done manually, but we leave it for more
221 * sophisticated examples. For the moment, this method will take care
222 * of all the spectrum initialization needs.
223 */
224 nrHelper->InitializeOperationBand(&band);
225 allBwps = CcBwpCreator::GetAllBwps({band});
226
227 uint32_t bwpIdForLowLat = 0;
228 // gNb routing between Bearer and bandwidh part
229 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB",
230 UintegerValue(bwpIdForLowLat));
231 // UE routing between Bearer and bandwidh part
232 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdForLowLat));
233
234 // install mmWave net devices
235 NetDeviceContainer gNbNetDevs = nrHelper->InstallGnbDevice(gNbNodes, allBwps);
236 NetDeviceContainer ueNetDevs = nrHelper->InstallUeDevice(ueNodes, allBwps);
237
238 int64_t randomStream = 1;
239 randomStream += nrHelper->AssignStreams(gNbNetDevs, randomStream);
240 randomStream += nrHelper->AssignStreams(ueNetDevs, randomStream);
241
242 for (auto it = gNbNetDevs.Begin(); it != gNbNetDevs.End(); ++it)
243 {
244 DynamicCast<NrGnbNetDevice>(*it)->UpdateConfig();
245 }
246
247 for (auto it = ueNetDevs.Begin(); it != ueNetDevs.End(); ++it)
248 {
249 DynamicCast<NrUeNetDevice>(*it)->UpdateConfig();
250 }
251
252 // create the internet and install the IP stack on the UEs
253 // get SGW/PGW and create a single RemoteHost
254 Ptr<Node> pgw = epcHelper->GetPgwNode();
255 NodeContainer remoteHostContainer;
256 remoteHostContainer.Create(1);
257 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
258 InternetStackHelper internet;
259 internet.Install(remoteHostContainer);
260 // connect a remoteHost to pgw. Setup routing too
261 PointToPointHelper p2ph;
262 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
263 p2ph.SetDeviceAttribute("Mtu", UintegerValue(2500));
264 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.000)));
265 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
266 Ipv4AddressHelper ipv4h;
267 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
268 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
269 // in this container, interface 0 is the pgw, 1 is the remoteHost
270 Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress(1);
271
272 Ipv4StaticRoutingHelper ipv4RoutingHelper;
273 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
274 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
275 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
276 internet.Install(ueNodes);
277 Ipv4InterfaceContainer ueIpIface;
278 ueIpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDevs));
279
280 // Set the default gateway for the UEs
281 for (uint32_t j = 0; j < ueNodes.GetN(); ++j)
282 {
283 Ptr<Ipv4StaticRouting> ueStaticRouting =
284 ipv4RoutingHelper.GetStaticRouting(ueNodes.Get(j)->GetObject<Ipv4>());
285 ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
286 }
287
288 // attach UEs to the closest eNB
289 nrHelper->AttachToClosestEnb(ueNetDevs, gNbNetDevs);
290
291 // assign IP address to UEs, and install UDP downlink applications
292 uint16_t dlPort = 1234;
293 uint16_t ulPort = 2000;
294 ApplicationContainer clientAppsDl;
295 ApplicationContainer serverAppsDl;
296 ApplicationContainer clientAppsUl;
297 ApplicationContainer serverAppsUl;
298 // ObjectMapValue objectMapValue;
299
300 Time udpInterval = NanoSeconds(1);
301
302 if (m_isUplink)
303 {
304 UdpServerHelper ulPacketSinkHelper(ulPort);
305 serverAppsUl.Add(ulPacketSinkHelper.Install(remoteHost));
306
307 // configure here UDP traffic flows
308 for (uint32_t j = 0; j < ueNodes.GetN(); ++j)
309 {
310 UdpClientHelper ulClient(remoteHostAddr, ulPort);
311 ulClient.SetAttribute("MaxPackets", UintegerValue(maxPackets));
312 ulClient.SetAttribute("PacketSize", UintegerValue(packetSize));
313 ulClient.SetAttribute(
314 "Interval",
315 TimeValue(udpInterval)); // we try to saturate, we just need to measure during a
316 // short time, how much traffic can handle each BWP
317 clientAppsUl.Add(ulClient.Install(ueNodes.Get(j)));
318
319 Ptr<EpcTft> tft = Create<EpcTft>();
320 EpcTft::PacketFilter ulpf;
321 ulpf.remotePortStart = ulPort;
322 ulpf.remotePortEnd = ulPort;
323 ulpf.direction = EpcTft::UPLINK;
324 tft->Add(ulpf);
325
326 EpsBearer bearer(EpsBearer::NGBR_LOW_LAT_EMBB);
327 nrHelper->ActivateDedicatedEpsBearer(ueNetDevs.Get(j), bearer, tft);
328 }
329
330 serverAppsUl.Start(udpAppStartTimeUl);
331 clientAppsUl.Start(udpAppStartTimeUl);
332 serverAppsUl.Stop(udpAppStopTimeUl);
333 clientAppsUl.Stop(udpAppStopTimeUl);
334 }
335
336 if (m_isDownlink)
337 {
338 UdpServerHelper dlPacketSinkHelper(dlPort);
339 serverAppsDl.Add(dlPacketSinkHelper.Install(ueNodes));
340
341 // configure here UDP traffic flows
342 for (uint32_t j = 0; j < ueNodes.GetN(); ++j)
343 {
344 UdpClientHelper dlClient(ueIpIface.GetAddress(j), dlPort);
345 dlClient.SetAttribute("MaxPackets", UintegerValue(maxPackets));
346 dlClient.SetAttribute("PacketSize", UintegerValue(packetSize));
347 dlClient.SetAttribute(
348 "Interval",
349 TimeValue(udpInterval)); // we try to saturate, we just need to measure during a
350 // short time, how much traffic can handle each BWP
351 clientAppsDl.Add(dlClient.Install(remoteHost));
352
353 Ptr<EpcTft> tft = Create<EpcTft>();
354 EpcTft::PacketFilter dlpf;
355 dlpf.localPortStart = dlPort;
356 dlpf.localPortEnd = dlPort;
357 dlpf.direction = EpcTft::DOWNLINK;
358 tft->Add(dlpf);
359
360 EpsBearer bearer(EpsBearer::NGBR_LOW_LAT_EMBB);
361 nrHelper->ActivateDedicatedEpsBearer(ueNetDevs.Get(j), bearer, tft);
362 }
363 // start UDP server and client apps
364 serverAppsDl.Start(udpAppStartTimeDl);
365 clientAppsDl.Start(udpAppStartTimeDl);
366 serverAppsDl.Stop(udpAppStopTimeDl);
367 clientAppsDl.Stop(udpAppStopTimeDl);
368 }
369
370 m_limit = ueNodes.GetN() * maxPackets * ((m_isUplink && m_isDownlink) ? 2 : 1);
371
372 for (auto it = serverAppsDl.Begin(); it != serverAppsDl.End(); ++it)
373 {
374 (*it)->TraceConnectWithoutContext("Rx",
375 MakeCallback(&SystemSchedulerTest::CountPkts, this));
376 }
377
378 for (auto it = serverAppsUl.Begin(); it != serverAppsUl.End(); ++it)
379 {
380 (*it)->TraceConnectWithoutContext("Rx",
381 MakeCallback(&SystemSchedulerTest::CountPkts, this));
382 }
383
384 // nrHelper->EnableTraces();
385 Simulator::Stop(simTime);
386 Simulator::Run();
387
388 double dataRecvDl = 0;
389 double dataRecvUl = 0;
390
391 if (m_isDownlink)
392 {
393 for (uint32_t i = 0; i < serverAppsDl.GetN(); i++)
394 {
395 Ptr<UdpServer> serverApp = serverAppsDl.Get(i)->GetObject<UdpServer>();
396 double data = (serverApp->GetReceived() * packetSize * 8);
397 dataRecvDl += data;
398 }
399 }
400 if (m_isUplink)
401 {
402 for (uint32_t i = 0; i < serverAppsUl.GetN(); i++)
403 {
404 Ptr<UdpServer> serverApp = serverAppsUl.Get(i)->GetObject<UdpServer>();
405 double data = (serverApp->GetReceived() * packetSize * 8);
406 dataRecvUl += data;
407 }
408 }
409
410 double expectedBitRate =
411 udpRate.GetBitRate() * ueNodes.GetN() * ((m_isUplink && m_isDownlink) ? 2 : 1);
412 NS_TEST_ASSERT_MSG_EQ_TOL(dataRecvDl + dataRecvUl,
413 expectedBitRate,
414 expectedBitRate * 0.05,
415 "Wrong total DL + UL throughput");
416
417 Simulator::Destroy();
418}
419
420} // namespace ns3
static BandwidthPartInfoPtrVector GetAllBwps(const std::vector< std::reference_wrapper< OperationBandInfo > > &operationBands)
Get all the BWP pointers from the specified vector of operation bands.
static TypeId GetTypeId()
Get the type id.
SystemSchedulerTest(const std::string &name, uint32_t usersPerNumOfBeams, uint32_t numOfBeams, uint32_t numerology, double bw1, bool isDownlink, bool isUplink, const std::string &schedulerType)
SystemSchedulerTest is a test constructor which is used to initialise the test parameters.
~SystemSchedulerTest() override
~SystemSchedulerTest
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Scenario
Different types for the propagation loss model of this bandwidth part.
@ UMi_StreetCanyon_LoS
UMi_StreetCanyon where all the nodes will be in Line-of-Sight.
This test case checks if the throughput obtained per UE is as expected for the specified scheduling l...