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