5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-multi-flow-qos-sched.cc
Go to the documentation of this file.
1// Copyright (c) 2022 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
23#include "ns3/antenna-module.h"
24#include "ns3/applications-module.h"
25#include "ns3/buildings-module.h"
26#include "ns3/config-store-module.h"
27#include "ns3/core-module.h"
28#include "ns3/flow-monitor-module.h"
29#include "ns3/internet-apps-module.h"
30#include "ns3/internet-module.h"
31#include "ns3/mobility-module.h"
32#include "ns3/nr-module.h"
33#include "ns3/point-to-point-module.h"
34
35using namespace ns3;
36
37NS_LOG_COMPONENT_DEFINE("CttcNrSimpleQosSched");
38
39int
40main(int argc, char* argv[])
41{
42 /*
43 * Variables that represent the parameters we will accept as input by the
44 * command line. Each of them is initialized with a default value, and
45 * possibly overridden below when command-line arguments are parsed.
46 */
47 // Scenario parameters (that we will use inside this script):
48 uint16_t gNbNum = 1;
49 uint16_t ueNumPergNb = 2;
50 bool logging = false;
51
52 // Simulation parameters. Please don't use double to indicate seconds; use
53 // ns-3 Time values which use integers to avoid portability issues.
54 Time simTime = MilliSeconds(1000);
55 Time udpAppStartTime = MilliSeconds(400);
56
57 // NR parameters. We will take the input from the command line, and then we
58 // will pass them inside the NR module.
59 uint16_t numerology = 0;
60 double centralFrequency = 4e9;
61 double bandwidth = 10e6;
62 double totalTxPower = 43;
63
64 bool enableOfdma = false;
65 std::string schedulerType = "PF";
66 bool enableQoSLcScheduler = false;
67
68 uint8_t priorityTrafficScenario = 0; // default is saturation
69
70 uint16_t mcsTable = 2;
71
72 bool enablePdcpDiscarding = false;
73 uint32_t discardTimerMs = 0;
74
75 bool enableNrHelperTraces = false;
76 bool enableQosTrafficTraces = true;
77 // Where we will store the output files.
78 std::string simTag = "default";
79 std::string outputDir = "./";
80
81 /*
82 * From here, we instruct the ns3::CommandLine class of all the input parameters
83 * that we may accept as input, as well as their description, and the storage
84 * variable.
85 */
86 CommandLine cmd;
87
88 cmd.AddValue("gNbNum", "The number of gNbs in multiple-ue topology", gNbNum);
89 cmd.AddValue("ueNumPergNb", "The number of UE per gNb in multiple-ue topology", ueNumPergNb);
90 cmd.AddValue("logging", "Enable logging", logging);
91 cmd.AddValue("priorityTrafficScenario",
92 "The traffic scenario for the case of priority. Can be 0: saturation"
93 "or 1: medium-load",
94 priorityTrafficScenario);
95 cmd.AddValue("simTime", "Simulation time", simTime);
96 cmd.AddValue("numerology", "The numerology to be used", numerology);
97 cmd.AddValue("centralFrequency", "The system frequency to be used", centralFrequency);
98 cmd.AddValue("bandwidth", "The system bandwidth to be used", bandwidth);
99 cmd.AddValue("totalTxPower",
100 "total tx power that will be proportionally assigned to"
101 " bands, CCs and bandwidth parts depending on each BWP bandwidth ",
102 totalTxPower);
103 cmd.AddValue("simTag",
104 "tag to be appended to output filenames to distinguish simulation campaigns",
105 simTag);
106 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
107 cmd.AddValue("enableOfdma",
108 "If set to true it enables Ofdma scheduler. Default value is false (Tdma)",
109 enableOfdma);
110 cmd.AddValue("schedulerType",
111 "PF: Proportional Fair (default), RR: Round-Robin, Qos",
112 schedulerType);
113 cmd.AddValue("enableQoSLcScheduler",
114 "If set to true, it enables the QoS LC scheduler. Default is RR (false)",
115 enableQoSLcScheduler);
116 cmd.AddValue("enableNrHelperTraces",
117 "If true, it enables the generation of the NrHelper traces, otherwise"
118 "NrHelper traces will not be generated. Default value is false",
119 enableNrHelperTraces);
120 cmd.AddValue("enableQosTrafficTraces",
121 "If true, it enables the generation of the the Delay and Throughput"
122 "traces, otherwise these traces will not be generated. Default value is true",
123 enableQosTrafficTraces);
124 cmd.AddValue("enablePdcpDiscarding",
125 "Whether to enable PDCP TX discarding",
126 enablePdcpDiscarding);
127 cmd.AddValue("discardTimerMs",
128 "Discard timer value in milliseconds to use for all the flows",
129 discardTimerMs);
130
131 cmd.Parse(argc, argv);
132
133 // enable logging or not
134 if (logging)
135 {
136 LogLevel logLevel1 =
137 (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_LEVEL_INFO);
138 LogComponentEnable("NrMacSchedulerNs3", logLevel1);
139 LogComponentEnable("NrMacSchedulerTdma", logLevel1);
140 }
141
142 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
143 Config::SetDefault("ns3::NrRlcUm::EnablePdcpDiscarding", BooleanValue(enablePdcpDiscarding));
144 Config::SetDefault("ns3::NrRlcUm::DiscardTimerMs", UintegerValue(discardTimerMs));
145
146 /*
147 * Create the scenario. In our examples, we heavily use helpers that setup
148 * the gnbs and ue following a pre-defined pattern. Please have a look at the
149 * GridScenarioHelper documentation to see how the nodes will be distributed.
150 */
151 int64_t randomStream = 1;
152
153 GridScenarioHelper gridScenario;
154 gridScenario.SetRows(1);
155 gridScenario.SetColumns(gNbNum);
156 gridScenario.SetHorizontalBsDistance(5.0);
157 gridScenario.SetVerticalBsDistance(5.0);
158 gridScenario.SetBsHeight(1.5);
159 gridScenario.SetUtHeight(1.5);
160 // must be set before BS number
161 gridScenario.SetSectorization(GridScenarioHelper::SINGLE);
162 gridScenario.SetBsNumber(gNbNum);
163 gridScenario.SetUtNumber(ueNumPergNb * gNbNum);
164 gridScenario.SetScenarioHeight(3); // Create a 3x3 scenario where the UE will
165 gridScenario.SetScenarioLength(3); // be distributed.
166 randomStream += gridScenario.AssignStreams(randomStream);
167 gridScenario.CreateScenario();
168
169 uint32_t udpPacketSize1;
170 uint32_t udpPacketSize2;
171 uint32_t lambda1 = 1000;
172 uint32_t lambda2 = 1000;
173
174 if (priorityTrafficScenario == 0) // saturation
175 {
176 udpPacketSize1 = 3000;
177 udpPacketSize2 = 3000;
178 }
179 else if (priorityTrafficScenario == 1) // medium-load
180 {
181 udpPacketSize1 = 3000;
182 udpPacketSize2 = 1252;
183 }
184 else
185 {
186 NS_ABORT_MSG("The priorityTrafficScenario chosen is not correct. "
187 "Please choose among 0: saturation and 1: medium-load");
188 }
189
190 /*
191 * Create two different NodeContainer for the different traffic type.
192 * In ueLowLat we will put the UEs that will receive low-latency traffic,
193 * while in ueVoice we will put the UEs that will receive the voice traffic.
194 */
195 NodeContainer ue1flowContainer;
196 NodeContainer ue2flowsContainer;
197
198 for (uint32_t j = 0; j < gridScenario.GetUserTerminals().GetN(); ++j)
199 {
200 Ptr<Node> ue = gridScenario.GetUserTerminals().Get(j);
201
202 j % 2 == 0 ? ue1flowContainer.Add(ue) : ue2flowsContainer.Add(ue);
203 }
204
205 if (priorityTrafficScenario == 1)
206 {
207 lambda1 = 1000 / ue1flowContainer.GetN();
208 lambda2 = 1000 / ue2flowsContainer.GetN();
209 }
210
211 // setup the nr simulation
212 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
213 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
214 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
215
216 // Put the pointers inside nrHelper
217 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
218 nrHelper->SetEpcHelper(nrEpcHelper);
219 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
220
221 std::stringstream scheduler;
222 std::string subType;
223
224 subType = !enableOfdma ? "Tdma" : "Ofdma";
225 scheduler << "ns3::NrMacScheduler" << subType << schedulerType;
226 std::cout << "Scheduler: " << scheduler.str() << std::endl;
227 nrHelper->SetSchedulerTypeId(TypeId::LookupByName(scheduler.str()));
228
229 if (enableQoSLcScheduler)
230 {
231 nrHelper->SetSchedulerAttribute("SchedLcAlgorithmType",
232 TypeIdValue(NrMacSchedulerLcQos::GetTypeId()));
233 }
234
235 // Error Model: gNB and UE with same spectrum error model.
236 std::string errorModel = "ns3::NrEesmIrT" + std::to_string(mcsTable);
237 nrHelper->SetDlErrorModel(errorModel);
238 nrHelper->SetUlErrorModel(errorModel);
239
240 // Both DL and UL AMC will have the same model behind.
241 nrHelper->SetGnbDlAmcAttribute("AmcModel", EnumValue(NrAmc::ErrorModel));
242 nrHelper->SetGnbUlAmcAttribute("AmcModel", EnumValue(NrAmc::ErrorModel));
243
244 // Beamforming method
245 idealBeamformingHelper->SetAttribute("BeamformingMethod",
246 TypeIdValue(DirectPathBeamforming::GetTypeId()));
247
248 // Antennas for all the UEs
249 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(1));
250 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(1));
251 nrHelper->SetUeAntennaAttribute("AntennaElement",
252 PointerValue(CreateObject<IsotropicAntennaModel>()));
253
254 // Antennas for all the gNbs
255 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(1));
256 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(1));
257 nrHelper->SetGnbAntennaAttribute("AntennaElement",
258 PointerValue(CreateObject<IsotropicAntennaModel>()));
259
260 /*
261 * Setup the configuration of the spectrum. One operation band is deployed
262 * with 1 component carrier (CC), automatically generated by the ccBwpManager
263 */
265 CcBwpCreator ccBwpCreator;
267 const uint8_t numOfCcs = 1;
268
269 /*
270 * The configured spectrum division for TDD is:
271 *
272 * |----Band1----|
273 * |-----CC1-----|
274 * |-----BWP1----|
275 */
276
277 // Create the configuration for the CcBwpHelper. SimpleOperationBandConf creates
278 // a single BWP per CC
279 CcBwpCreator::SimpleOperationBandConf bandConf(centralFrequency, bandwidth, numOfCcs);
280
281 bandConf.m_numBwp = 1;
282 // By using the configuration created, it is time to make the operation band
283 band = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
284 // Create the channel helper for the spectrum configuration
285 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
286 // Set the spectrum channel
287 channelHelper->ConfigureFactories("UMi", "LOS", "ThreeGpp");
288 // Set shadowing and update period
289 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
290 // Set and create the channel for the band with only the propagation model
291 channelHelper->AssignChannelsToBands({band}, NrChannelHelper::INIT_PROPAGATION);
292 allBwps = CcBwpCreator::GetAllBwps({band});
293
294 double x = pow(10, totalTxPower / 10);
295
296 Packet::EnableChecking();
297 Packet::EnablePrinting();
298
299 uint32_t bwpIdUe1 = 0;
300 uint32_t bwpIdUe2Flow1 = 0;
301 uint32_t bwpIdUe2Flow2 = 0;
302
303 // gNb routing between Bearer and bandwidh part
304 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdUe1));
305 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdUe2Flow1));
306 nrHelper->SetGnbBwpManagerAlgorithmAttribute("DGBR_INTER_SERV_87",
307 UintegerValue(bwpIdUe2Flow2));
308
309 // Ue routing between Bearer and bandwidth part
310 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdUe1));
311 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdUe2Flow1));
312 nrHelper->SetUeBwpManagerAlgorithmAttribute("DGBR_INTER_SERV_87", UintegerValue(bwpIdUe2Flow2));
313
314 /*
315 * We have configured the attributes we needed. Now, install and get the pointers
316 * to the NetDevices, which contains all the NR stack:
317 */
318 NetDeviceContainer gnbNetDev =
319 nrHelper->InstallGnbDevice(gridScenario.GetBaseStations(), allBwps);
320 NetDeviceContainer ue1flowNetDev = nrHelper->InstallUeDevice(ue1flowContainer, allBwps);
321 NetDeviceContainer ue2flowsNetDev = nrHelper->InstallUeDevice(ue2flowsContainer, allBwps);
322
323 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
324 randomStream += nrHelper->AssignStreams(ue1flowNetDev, randomStream);
325 randomStream += nrHelper->AssignStreams(ue2flowsNetDev, randomStream);
326
327 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("Numerology", UintegerValue(numerology));
328 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("TxPower", DoubleValue(10 * log10(x)));
329
330 // create the internet and install the IP stack on the UEs
331 // get SGW/PGW and create a single RemoteHost
332 auto [remoteHost, remoteHostIpv4Address] =
333 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
334
335 InternetStackHelper internet;
336
337 internet.Install(gridScenario.GetUserTerminals());
338
339 Ipv4InterfaceContainer ue1FlowIpIface;
340 Ipv4InterfaceContainer ue2FlowsIpIface;
341 ue1FlowIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ue1flowNetDev));
342 ue2FlowsIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ue2flowsNetDev));
343
344 // attach UEs to the closest gNB
345 nrHelper->AttachToClosestGnb(ue1flowNetDev, gnbNetDev);
346 nrHelper->AttachToClosestGnb(ue2flowsNetDev, gnbNetDev);
347
348 /*
349 * Traffic part. Install two kind of traffic: low-latency and voice, each
350 * identified by a particular source port.
351 */
352 uint16_t dlPortUe1flow = 1234;
353 uint16_t dlPortUe2flowsNgbr = 1235;
354 uint16_t dlPortUe2flowsDcGbr = 1236;
355
356 ApplicationContainer serverApps;
357
358 // The sink will always listen to the specified ports
359 UdpServerHelper dlPacketSinkUe1flow(dlPortUe1flow);
360 UdpServerHelper dlPacketSinkUe2flowsNgbr(dlPortUe2flowsNgbr);
361 UdpServerHelper dlPacketSinkUe2flowsDcGgbr(dlPortUe2flowsDcGbr);
362
363 // The server, that is the application which is listening, is installed in the UE
364 serverApps.Add(dlPacketSinkUe1flow.Install(ue1flowContainer));
365 serverApps.Add(dlPacketSinkUe2flowsNgbr.Install(ue2flowsContainer));
366 serverApps.Add(dlPacketSinkUe2flowsDcGgbr.Install(ue2flowsContainer));
367
368 /*
369 * Configure attributes for the different generators, using user-provided
370 * parameters for generating a CBR traffic
371 *
372 * UE with 1 flow configuration and object creation:
373 */
374 /******************************************************************************/
375 UdpClientHelper dlClientUe1flow;
376 dlClientUe1flow.SetAttribute("RemotePort", UintegerValue(dlPortUe1flow));
377 dlClientUe1flow.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
378 dlClientUe1flow.SetAttribute("PacketSize", UintegerValue(udpPacketSize1));
379 dlClientUe1flow.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambda1)));
380
381 // The bearer that will carry UE with 1 flow Non GBR traffic
383
384 // The filter for the UE with 1 flow Non GBR traffic
385 Ptr<NrEpcTft> ue1flowTft = Create<NrEpcTft>();
386 NrEpcTft::PacketFilter dlpfUe1flow;
387 dlpfUe1flow.localPortStart = dlPortUe1flow;
388 dlpfUe1flow.localPortEnd = dlPortUe1flow;
389 ue1flowTft->Add(dlpfUe1flow);
390 /******************************************************************************/
391
392 /******************************************************************************/
393 // UE with 2 Flows Non GBR configuration and object creation:
394 UdpClientHelper dlClientUe2flowsNgbr;
395 dlClientUe2flowsNgbr.SetAttribute("RemotePort", UintegerValue(dlPortUe2flowsNgbr));
396 dlClientUe2flowsNgbr.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
397 dlClientUe2flowsNgbr.SetAttribute("PacketSize", UintegerValue(udpPacketSize1));
398 dlClientUe2flowsNgbr.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambda1)));
399
400 // NrGbrQosInformation qosInfoInterServ2;
401 // qosInfoInterServ2.gbrDl = 6e6; // Downlink GBR
402
403 // The bearer that will carry UE with 2 Flows Non GBR traffic
404 NrEpsBearer ue2flowsNgbrBearer(NrEpsBearer::NGBR_LOW_LAT_EMBB); // qosInfoInterServ2);
405
406 // The filter for the UE with 2 Flows Non GBR traffic
407 Ptr<NrEpcTft> ue2flowsNgbrTft = Create<NrEpcTft>();
408 NrEpcTft::PacketFilter dlpfUe2flowsNgbr;
409 dlpfUe2flowsNgbr.localPortStart = dlPortUe2flowsNgbr;
410 dlpfUe2flowsNgbr.localPortEnd = dlPortUe2flowsNgbr;
411 ue2flowsNgbrTft->Add(dlpfUe2flowsNgbr);
412 /******************************************************************************/
413
414 /******************************************************************************/
415 UdpClientHelper dlClientUe2flowsDcGbr;
416 dlClientUe2flowsDcGbr.SetAttribute("RemotePort", UintegerValue(dlPortUe2flowsDcGbr));
417 dlClientUe2flowsDcGbr.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
418 dlClientUe2flowsDcGbr.SetAttribute("PacketSize", UintegerValue(udpPacketSize2));
419 dlClientUe2flowsDcGbr.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambda2)));
420
421 NrGbrQosInformation qosUe2flowsDcGbr;
422 qosUe2flowsDcGbr.gbrDl = 5e6; // Downlink GBR
423
424 // The bearer that will carry Ue 2 Flows DC GBR traffic
425 NrEpsBearer ue2flowsDcGbrBearer(NrEpsBearer::DGBR_INTER_SERV_87, qosUe2flowsDcGbr);
426
427 // The filter for the 2 Flows DC GBR traffic
428 Ptr<NrEpcTft> ue2FlowsDcGbrTft = Create<NrEpcTft>();
429 NrEpcTft::PacketFilter dlpfUe2flowsDcGbr;
430 dlpfUe2flowsDcGbr.localPortStart = dlPortUe2flowsDcGbr;
431 dlpfUe2flowsDcGbr.localPortEnd = dlPortUe2flowsDcGbr;
432 ue2FlowsDcGbrTft->Add(dlpfUe2flowsDcGbr);
433 /******************************************************************************/
434
435 // Install the applications
436 ApplicationContainer clientApps;
437
438 for (uint32_t i = 0; i < ue1flowContainer.GetN(); ++i)
439 {
440 Ptr<NetDevice> ueDevice = ue1flowNetDev.Get(i);
441 Address ueAddress = ue1FlowIpIface.GetAddress(i);
442
443 // The client, who is transmitting, is installed in the remote host,
444 // with destination address set to the address of the UE
445 dlClientUe1flow.SetAttribute("RemoteAddress", AddressValue(ueAddress));
446 clientApps.Add(dlClientUe1flow.Install(remoteHost));
447
448 // Activate a dedicated bearer for the traffic type
449 nrHelper->ActivateDedicatedEpsBearer(ueDevice, ue1flowBearer, ue1flowTft);
450 }
451
452 for (uint32_t i = 0; i < ue2flowsContainer.GetN(); ++i)
453 {
454 Ptr<NetDevice> ueDevice = ue2flowsNetDev.Get(i);
455 Address ueAddress = ue2FlowsIpIface.GetAddress(i);
456
457 // The client, who is transmitting, is installed in the remote host,
458 // with destination address set to the address of the UE
459 dlClientUe2flowsNgbr.SetAttribute("RemoteAddress", AddressValue(ueAddress));
460 clientApps.Add(dlClientUe2flowsNgbr.Install(remoteHost));
461
462 // Activate a dedicated bearer for the traffic type
463 nrHelper->ActivateDedicatedEpsBearer(ueDevice, ue2flowsNgbrBearer, ue2flowsNgbrTft);
464 }
465
466 for (uint32_t i = 0; i < ue2flowsContainer.GetN(); ++i)
467 {
468 Ptr<NetDevice> ueDevice = ue2flowsNetDev.Get(i);
469 Address ueAddress = ue2FlowsIpIface.GetAddress(i);
470
471 // The client, who is transmitting, is installed in the remote host,
472 // with destination address set to the address of the UE
473 dlClientUe2flowsDcGbr.SetAttribute("RemoteAddress", AddressValue(ueAddress));
474 clientApps.Add(dlClientUe2flowsDcGbr.Install(remoteHost));
475
476 // Activate a dedicated bearer for the traffic type
477 nrHelper->ActivateDedicatedEpsBearer(ueDevice, ue2flowsDcGbrBearer, ue2FlowsDcGbrTft);
478 }
479
480 // start UDP server and client apps
481 serverApps.Start(udpAppStartTime);
482 clientApps.Start(udpAppStartTime);
483 serverApps.Stop(simTime);
484 clientApps.Stop(simTime);
485
486 // enable the traces provided by the nr module
487 if (enableNrHelperTraces)
488 {
489 nrHelper->EnableTraces();
490 }
491
492 FlowMonitorHelper flowmonHelper;
493 NodeContainer endpointNodes;
494 endpointNodes.Add(remoteHost);
495 endpointNodes.Add(gridScenario.GetUserTerminals());
496
497 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
498 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.001));
499 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
500 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
501
502 Simulator::Stop(simTime);
503 Simulator::Run();
504
505 double averageFlowThroughput = 0.0;
506 double averageFlowDelay = 0.0;
507
508 std::ofstream delayFile;
509 std::ofstream throughputFile;
510
511 std::ostringstream delayFileName;
512 std::ostringstream throughputFileName;
513
514 std::string lcSced;
515 lcSced = enableQoSLcScheduler ? "LcQos" : "LcRR";
516
517 if (simTag.empty())
518 {
519 delayFileName << "Delay"
520 << "_" << schedulerType.c_str() << "_" << lcSced.c_str() << ".txt";
521
522 throughputFileName << "Throughput"
523 << "_" << schedulerType.c_str() << "_" << lcSced.c_str() << ".txt";
524 }
525 else
526 {
527 delayFileName << outputDir << "Delay" << simTag << std::string(".txt").c_str();
528 throughputFileName << outputDir << "Throughput" << simTag << std::string(".txt").c_str();
529 }
530
531 if (enableQosTrafficTraces)
532 {
533 delayFile.open(delayFileName.str());
534 delayFile.setf(std::ios_base::fixed);
535
536 if (!delayFile.is_open())
537 {
538 NS_ABORT_MSG("Can't open file " << delayFileName.str());
539 }
540 delayFile << "source_address"
541 << "\t"
542 << "source_port"
543 << "\t"
544 << "dest_address"
545 << "\t"
546 << "dest_port"
547 << "\t"
548 << "delay"
549 << "\n";
550
551 throughputFile.open(throughputFileName.str());
552 throughputFile.setf(std::ios_base::fixed);
553
554 if (!throughputFile.is_open())
555 {
556 NS_ABORT_MSG("Can't open file " << throughputFileName.str());
557 }
558
559 throughputFile << "source_port"
560 << "\t"
561 << "dest_port"
562 << "\t"
563 << "Throughput"
564 << "\t"
565 << "Delay"
566 << "\n";
567 }
568
569 /*
570 * To check what was installed in the memory, i.e., BWPs of gNB Device, and its configuration.
571 * Example is: Node 1 -> Device 0 -> BandwidthPartMap -> {0,1} BWPs -> NrGnbPhy -> Numerology,
572 GtkConfigStore config;
573 config.ConfigureAttributes ();
574 */
575
576 // Print per-flow statistics
577 monitor->CheckForLostPackets();
578 Ptr<Ipv4FlowClassifier> classifier =
579 DynamicCast<Ipv4FlowClassifier>(flowmonHelper.GetClassifier());
580 FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
581
582 std::ofstream outFile;
583 std::string filename = outputDir + "/" + simTag;
584 outFile.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
585 if (!outFile.is_open())
586 {
587 std::cerr << "Can't open file " << filename << std::endl;
588 return 1;
589 }
590
591 outFile.setf(std::ios_base::fixed);
592
593 double flowDuration = (simTime - udpAppStartTime).GetSeconds();
594 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
595 i != stats.end();
596 ++i)
597 {
598 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
599
600 if (enableQosTrafficTraces)
601 {
602 for (uint32_t j = 0; j < i->second.delayHistogram.GetNBins(); j++)
603 {
604 Histogram h = i->second.delayHistogram;
605 if (h.GetBinCount(j))
606 {
607 for (uint32_t k = 0; k < h.GetBinCount(j); k++)
608 {
609 delayFile << t.sourceAddress << "\t" << t.sourcePort << "\t"
610 << t.destinationAddress << "\t" << t.destinationPort << "\t"
611 << h.GetBinStart(j) << "\n";
612 }
613 }
614 }
615 }
616
617 std::stringstream protoStream;
618 protoStream << (uint16_t)t.protocol;
619 if (t.protocol == 6)
620 {
621 protoStream.str("TCP");
622 }
623 if (t.protocol == 17)
624 {
625 protoStream.str("UDP");
626 }
627 outFile << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
628 << t.destinationAddress << ":" << t.destinationPort << ") proto "
629 << protoStream.str() << "\n";
630 outFile << " Tx Packets: " << i->second.txPackets << "\n";
631 outFile << " Tx Bytes: " << i->second.txBytes << "\n";
632 outFile << " TxOffered: " << i->second.txBytes * 8.0 / flowDuration / 1000.0 / 1000.0
633 << " Mbps\n";
634 outFile << " Rx Bytes: " << i->second.rxBytes << "\n";
635 if (i->second.rxPackets > 0)
636 {
637 // Measure the duration of the flow from receiver's perspective
638 averageFlowThroughput += i->second.rxBytes * 8.0 / flowDuration / 1000 / 1000;
639 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
640
641 double throughput = i->second.rxBytes * 8.0 / flowDuration / 1000 / 1000;
642 double delay = 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
643
644 outFile << " Throughput: " << i->second.rxBytes * 8.0 / flowDuration / 1000 / 1000
645 << " Mbps\n";
646 outFile << " Mean delay: "
647 << 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets << " ms\n";
648 // outFile << " Mean upt: " << i->second.uptSum / i->second.rxPackets / 1000/1000 << "
649 // Mbps \n";
650 outFile << " Mean jitter: "
651 << 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets << " ms\n";
652
653 if (enableQosTrafficTraces)
654 {
655 throughputFile << t.sourcePort << "\t" << t.destinationPort << "\t" << throughput
656 << "\t" << delay << std::endl;
657 }
658 }
659 else
660 {
661 outFile << " Throughput: 0 Mbps\n";
662 outFile << " Mean delay: 0 ms\n";
663 outFile << " Mean jitter: 0 ms\n";
664
665 if (enableQosTrafficTraces)
666 {
667 throughputFile << t.sourcePort << "\t" << t.destinationPort << "\t" << 0 << "\t"
668 << 0 << std::endl;
669 }
670 }
671 outFile << " Rx Packets: " << i->second.rxPackets << "\n";
672 }
673
674 outFile << "\n\n Mean flow throughput: " << averageFlowThroughput / stats.size() << "\n";
675 outFile << " Mean flow delay: " << averageFlowDelay / stats.size() << "\n";
676
677 outFile.close();
678
679 std::ifstream f(filename.c_str());
680
681 if (f.is_open())
682 {
683 std::cout << f.rdbuf();
684 }
685
686 Simulator::Destroy();
687 return 0;
688}
Manages the correct creation of operation bands, component carriers and bandwidth parts.
OperationBandInfo CreateOperationBandContiguousCc(const SimpleOperationBandConf &conf)
Create an operation band with the CC specified.
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.
The GridScenarioHelper class.
void SetRows(uint32_t r)
SetRows.
void SetHorizontalBsDistance(double d)
SetHorizontalBsDistance.
void SetVerticalBsDistance(double d)
SetVerticalBsDistance.
void CreateScenario() override
Create the scenario, with the configured parameter.
int64_t AssignStreams(int64_t stream)
void SetColumns(uint32_t c)
SetColumns.
const NodeContainer & GetUserTerminals() const
Get the list of user nodes.
void SetBsNumber(std::size_t n)
Set the number of base stations.
void SetUtNumber(std::size_t n)
Set the number of UT/UE.
const NodeContainer & GetBaseStations() const
Get the list of gnb/base station nodes.
@ ErrorModel
Error Model version (can use different error models, see NrErrorModel)
Definition nr-amc.h:81
@ INIT_PROPAGATION
Initialize the propagation loss model.
This class contains the specification of EPS Bearers.
@ NGBR_LOW_LAT_EMBB
Non-GBR Low Latency eMBB applications.
@ DGBR_INTER_SERV_87
Delay-Critical GBR Interactive Service - Motion tracking data (TS 23.501)
static TypeId GetTypeId()
Get the type ID.
void SetBsHeight(double h)
SetGnbHeight.
void SetUtHeight(double h)
SetUeHeight.
void SetSectorization(SiteSectorizationType numSectors)
Sets the number of sectors of every site.
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
uint16_t localPortStart
start of the port number range of the UE
Definition nr-epc-tft.h:118
uint16_t localPortEnd
end of the port number range of the UE
Definition nr-epc-tft.h:119
Operation band information structure.