5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-demo.cc
Go to the documentation of this file.
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
31// NOLINTBEGIN
32// clang-format off
33
41// clang-format on
42// NOLINTEND
43
44/*
45 * Include part. Often, you will have to include the headers for an entire module;
46 * do that by including the name of the module you need with the suffix "-module.h".
47 */
48
49#include "ns3/antenna-module.h"
50#include "ns3/applications-module.h"
51#include "ns3/buildings-module.h"
52#include "ns3/config-store-module.h"
53#include "ns3/core-module.h"
54#include "ns3/flow-monitor-module.h"
55#include "ns3/internet-apps-module.h"
56#include "ns3/internet-module.h"
57#include "ns3/mobility-module.h"
58#include "ns3/nr-module.h"
59#include "ns3/point-to-point-module.h"
60
61/*
62 * Use, always, the namespace ns3. All the NR classes are inside such namespace.
63 */
64using namespace ns3;
65
66/*
67 * With this line, we will be able to see the logs of the file by enabling the
68 * component "CttcNrDemo".
69 * Further information on how logging works can be found in the ns-3 documentation [3].
70 */
71NS_LOG_COMPONENT_DEFINE("CttcNrDemo");
72
73int
74main(int argc, char* argv[])
75{
76 /*
77 * Variables that represent the parameters we will accept as input by the
78 * command line. Each of them is initialized with a default value, and
79 * possibly overridden below when command-line arguments are parsed.
80 */
81 // Scenario parameters (that we will use inside this script):
82 uint16_t gNbNum = 1;
83 uint16_t ueNumPergNb = 2;
84 bool logging = false;
85 bool doubleOperationalBand = true;
86
87 // Traffic parameters (that we will use inside this script):
88 uint32_t udpPacketSizeULL = 100;
89 uint32_t udpPacketSizeBe = 1252;
90 uint32_t lambdaULL = 10000;
91 uint32_t lambdaBe = 10000;
92
93 // Simulation parameters. Please don't use double to indicate seconds; use
94 // ns-3 Time values which use integers to avoid portability issues.
95 Time simTime = MilliSeconds(1000);
96 Time udpAppStartTime = MilliSeconds(400);
97
98 // NR parameters (Reference: 3GPP TR 38.901 V17.0.0 (Release 17)
99 // Table 7.8-1 for the power and BW).
100 // In this example the BW has been split into two BWPs
101 // We will take the input from the command line, and then we
102 // will pass them inside the NR module.
103 uint16_t numerologyBwp1 = 4;
104 double centralFrequencyBand1 = 28e9;
105 double bandwidthBand1 = 50e6;
106 uint16_t numerologyBwp2 = 2;
107 double centralFrequencyBand2 = 28.2e9;
108 double bandwidthBand2 = 50e6;
109 double totalTxPower = 35;
110
111 // Where we will store the output files.
112 std::string simTag = "default";
113 std::string outputDir = "./";
114
115 /*
116 * From here, we instruct the ns3::CommandLine class of all the input parameters
117 * that we may accept as input, as well as their description, and the storage
118 * variable.
119 */
120 CommandLine cmd(__FILE__);
121
122 cmd.AddValue("gNbNum", "The number of gNbs in multiple-ue topology", gNbNum);
123 cmd.AddValue("ueNumPergNb", "The number of UE per gNb in multiple-ue topology", ueNumPergNb);
124 cmd.AddValue("logging", "Enable logging", logging);
125 cmd.AddValue("doubleOperationalBand",
126 "If true, simulate two operational bands with one CC for each band,"
127 "and each CC will have 1 BWP that spans the entire CC.",
128 doubleOperationalBand);
129 cmd.AddValue("packetSizeUll",
130 "packet size in bytes to be used by ultra low latency traffic",
131 udpPacketSizeULL);
132 cmd.AddValue("packetSizeBe",
133 "packet size in bytes to be used by best effort traffic",
134 udpPacketSizeBe);
135 cmd.AddValue("lambdaUll",
136 "Number of UDP packets in one second for ultra low latency traffic",
137 lambdaULL);
138 cmd.AddValue("lambdaBe",
139 "Number of UDP packets in one second for best effort traffic",
140 lambdaBe);
141 cmd.AddValue("simTime", "Simulation time", simTime);
142 cmd.AddValue("numerologyBwp1", "The numerology to be used in bandwidth part 1", numerologyBwp1);
143 cmd.AddValue("centralFrequencyBand1",
144 "The system frequency to be used in band 1",
145 centralFrequencyBand1);
146 cmd.AddValue("bandwidthBand1", "The system bandwidth to be used in band 1", bandwidthBand1);
147 cmd.AddValue("numerologyBwp2", "The numerology to be used in bandwidth part 2", numerologyBwp2);
148 cmd.AddValue("centralFrequencyBand2",
149 "The system frequency to be used in band 2",
150 centralFrequencyBand2);
151 cmd.AddValue("bandwidthBand2", "The system bandwidth to be used in band 2", bandwidthBand2);
152 cmd.AddValue("totalTxPower",
153 "total tx power that will be proportionally assigned to"
154 " bands, CCs and bandwidth parts depending on each BWP bandwidth ",
155 totalTxPower);
156 cmd.AddValue("simTag",
157 "tag to be appended to output filenames to distinguish simulation campaigns",
158 simTag);
159 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
160
161 // Parse the command line
162 cmd.Parse(argc, argv);
163
164 /*
165 * Check if the frequency is in the allowed range.
166 * If you need to add other checks, here is the best position to put them.
167 */
168 NS_ABORT_IF(centralFrequencyBand1 < 0.5e9 && centralFrequencyBand1 > 100e9);
169 NS_ABORT_IF(centralFrequencyBand2 < 0.5e9 && centralFrequencyBand2 > 100e9);
170
171 /*
172 * If the logging variable is set to true, enable the log of some components
173 * through the code. The same effect can be obtained through the use
174 * of the NS_LOG environment variable:
175 *
176 * export NS_LOG="UdpClient=level_info|prefix_time|prefix_func|prefix_node:UdpServer=..."
177 *
178 * Usually, the environment variable way is preferred, as it is more customizable,
179 * and more expressive.
180 */
181 if (logging)
182 {
183 LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
184 LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
185 LogComponentEnable("NrPdcp", LOG_LEVEL_INFO);
186 }
187
188 /*
189 * In general, attributes for the NR module are typically configured in NrHelper. However, some
190 * attributes need to be configured globally through the Config::SetDefault() method. Below is
191 * an example: if you want to make the RLC buffer very large, you can pass a very large integer
192 * here.
193 */
194 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
195
196 /*
197 * Create the scenario. In our examples, we heavily use helpers that setup
198 * the gnbs and ue following a pre-defined pattern. Please have a look at the
199 * GridScenarioHelper documentation to see how the nodes will be distributed.
200 */
201 int64_t randomStream = 1;
202 GridScenarioHelper gridScenario;
203 gridScenario.SetRows(1);
204 gridScenario.SetColumns(gNbNum);
205 // All units below are in meters
206 gridScenario.SetHorizontalBsDistance(10.0);
207 gridScenario.SetVerticalBsDistance(10.0);
208 gridScenario.SetBsHeight(10);
209 gridScenario.SetUtHeight(1.5);
210 // must be set before BS number
211 gridScenario.SetSectorization(GridScenarioHelper::SINGLE);
212 gridScenario.SetBsNumber(gNbNum);
213 gridScenario.SetUtNumber(ueNumPergNb * gNbNum);
214 gridScenario.SetScenarioHeight(3); // Create a 3x3 scenario where the UE will
215 gridScenario.SetScenarioLength(3); // be distributed.
216 randomStream += gridScenario.AssignStreams(randomStream);
217 gridScenario.CreateScenario();
218
219 /*
220 * Create two different NodeContainer for the different traffic type.
221 * In ueLowLat we will put the UEs that will receive low-latency traffic,
222 * while in ueVoice we will put the UEs that will receive the voice traffic.
223 */
224 NodeContainer ueLowLatContainer;
225 NodeContainer ueVoiceContainer;
226
227 for (uint32_t j = 0; j < gridScenario.GetUserTerminals().GetN(); ++j)
228 {
229 Ptr<Node> ue = gridScenario.GetUserTerminals().Get(j);
230 if (j % 2 == 0)
231 {
232 ueLowLatContainer.Add(ue);
233 }
234 else
235 {
236 ueVoiceContainer.Add(ue);
237 }
238 }
239
240 /*
241 * TODO: Add a print, or a plot, that shows the scenario.
242 */
243 NS_LOG_INFO("Creating " << gridScenario.GetUserTerminals().GetN() << " user terminals and "
244 << gridScenario.GetBaseStations().GetN() << " gNBs");
245
246 /*
247 * Setup the NR module. We create the various helpers needed for the
248 * NR simulation:
249 * - nrEpcHelper, which will setup the core network
250 * - IdealBeamformingHelper, which takes care of the beamforming part
251 * - NrHelper, which takes care of creating and connecting the various
252 * part of the NR stack
253 * - NrChannelHelper, which takes care of the spectrum channel
254 */
255 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
256 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
257 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
258
259 // Put the pointers inside nrHelper
260 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
261 nrHelper->SetEpcHelper(nrEpcHelper);
262
263 /*
264 * Spectrum division. We create two operational bands, each of them containing
265 * one component carrier, and each CC containing a single bandwidth part
266 * centered at the frequency specified by the input parameters.
267 * Each spectrum part length is, as well, specified by the input parameters.
268 * Both operational bands will use the StreetCanyon channel modeling.
269 */
271 CcBwpCreator ccBwpCreator;
272 const uint8_t numCcPerBand = 1; // in this example, both bands have a single CC
273
274 // Create the configuration for the CcBwpHelper. SimpleOperationBandConf creates
275 // a single BWP per CC
276 CcBwpCreator::SimpleOperationBandConf bandConf1(centralFrequencyBand1,
277 bandwidthBand1,
278 numCcPerBand);
279
280 // Create the band and install the channel into it
281 OperationBandInfo band1 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf1);
282 // Set the channel for the band
283 CcBwpCreator::SimpleOperationBandConf bandConf2(centralFrequencyBand2,
284 bandwidthBand2,
285 numCcPerBand);
286 OperationBandInfo band2 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf2);
287
288 /*
289 * The configured spectrum division is:
290 * ------------Band1--------------|--------------Band2-----------------
291 * ------------CC1----------------|--------------CC2-------------------
292 * ------------BWP1---------------|--------------BWP2------------------
293 */
294
295 /*
296 * Start to account for the bandwidth used by the example, as well as
297 * the total power that has to be divided among the BWPs.
298 */
299 double x = pow(10, totalTxPower / 10);
300 double totalBandwidth = bandwidthBand1;
306 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
307 channelHelper->ConfigureFactories("UMi", "Default", "ThreeGpp");
312 channelHelper->SetChannelConditionModelAttribute("UpdatePeriod", TimeValue(MilliSeconds(0)));
313 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
314 /*
315 * if not single band simulation, initialize and setup power in the second band.
316 * Install channel and pathloss, plus other things inside single or both bands.
317 */
318 if (doubleOperationalBand)
319 {
320 channelHelper->AssignChannelsToBands({band1, band2});
321 totalBandwidth += bandwidthBand2;
322 allBwps = CcBwpCreator::GetAllBwps({band1, band2});
323 }
324 else
325 {
326 channelHelper->AssignChannelsToBands({band1});
327 allBwps = CcBwpCreator::GetAllBwps({band1});
328 }
329
330 /*
331 * allBwps contains all the spectrum configuration needed for the nrHelper.
332 *
333 * Now, we can setup the attributes. We can have three kind of attributes:
334 * (i) parameters that are valid for all the bandwidth parts and applies to
335 * all nodes, (ii) parameters that are valid for all the bandwidth parts
336 * and applies to some node only, and (iii) parameters that are different for
337 * every bandwidth parts. The approach is:
338 *
339 * - for (i): Configure the attribute through the helper, and then install;
340 * - for (ii): Configure the attribute through the helper, and then install
341 * for the first set of nodes. Then, change the attribute through the helper,
342 * and install again;
343 * - for (iii): Install, and then configure the attributes by retrieving
344 * the pointer needed, and calling "SetAttribute" on top of such pointer.
345 *
346 */
347
348 Packet::EnableChecking();
349 Packet::EnablePrinting();
350
351 /*
352 * Case (i): Attributes valid for all the nodes
353 */
354 // Beamforming method
355 idealBeamformingHelper->SetAttribute("BeamformingMethod",
356 TypeIdValue(DirectPathBeamforming::GetTypeId()));
357
358 // Core latency
359 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
360
361 // Antennas for all the UEs
362 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(2));
363 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(4));
364 nrHelper->SetUeAntennaAttribute("AntennaElement",
365 PointerValue(CreateObject<IsotropicAntennaModel>()));
366
367 // Antennas for all the gNbs
368 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(4));
369 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
370 nrHelper->SetGnbAntennaAttribute("AntennaElement",
371 PointerValue(CreateObject<IsotropicAntennaModel>()));
372
373 uint32_t bwpIdForLowLat = 0;
374 uint32_t bwpIdForVoice = 0;
375 if (doubleOperationalBand)
376 {
377 bwpIdForVoice = 1;
378 bwpIdForLowLat = 0;
379 }
380
381 // gNb routing between Bearer and bandwidh part
382 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB",
383 UintegerValue(bwpIdForLowLat));
384 nrHelper->SetGnbBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
385
386 // Ue routing between Bearer and bandwidth part
387 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdForLowLat));
388 nrHelper->SetUeBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
389
390 /*
391 * We miss many other parameters. By default, not configuring them is equivalent
392 * to use the default values. Please, have a look at the documentation to see
393 * what are the default values for all the attributes you are not seeing here.
394 */
395
396 /*
397 * Case (ii): Attributes valid for a subset of the nodes
398 */
399
400 // NOT PRESENT IN THIS SIMPLE EXAMPLE
401
402 /*
403 * We have configured the attributes we needed. Now, install and get the pointers
404 * to the NetDevices, which contains all the NR stack:
405 */
406
407 NetDeviceContainer gnbNetDev =
408 nrHelper->InstallGnbDevice(gridScenario.GetBaseStations(), allBwps);
409 NetDeviceContainer ueLowLatNetDev = nrHelper->InstallUeDevice(ueLowLatContainer, allBwps);
410 NetDeviceContainer ueVoiceNetDev = nrHelper->InstallUeDevice(ueVoiceContainer, allBwps);
411
412 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
413 randomStream += nrHelper->AssignStreams(ueLowLatNetDev, randomStream);
414 randomStream += nrHelper->AssignStreams(ueVoiceNetDev, randomStream);
415 /*
416 * Case (iii): Go node for node and change the attributes we have to setup
417 * per-node.
418 */
419
420 // Get the first netdevice (gnbNetDev.Get (0)) and the first bandwidth part (0)
421 // and set the attribute.
422 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)
423 ->SetAttribute("Numerology", UintegerValue(numerologyBwp1));
424 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)
425 ->SetAttribute("TxPower", DoubleValue(10 * log10((bandwidthBand1 / totalBandwidth) * x)));
426
427 if (doubleOperationalBand)
428 {
429 // Get the first netdevice (gnbNetDev.Get (0)) and the second bandwidth part (1)
430 // and set the attribute.
431 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)
432 ->SetAttribute("Numerology", UintegerValue(numerologyBwp2));
433 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)
434 ->SetTxPower(10 * log10((bandwidthBand2 / totalBandwidth) * x));
435 }
436
437 // From here, it is standard NS3. In the future, we will create helpers
438 // for this part as well.
439
440 auto [remoteHost, remoteHostIpv4Address] =
441 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
442
443 InternetStackHelper internet;
444
445 internet.Install(gridScenario.GetUserTerminals());
446
447 Ipv4InterfaceContainer ueLowLatIpIface =
448 nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueLowLatNetDev));
449 Ipv4InterfaceContainer ueVoiceIpIface =
450 nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVoiceNetDev));
451
452 // attach UEs to the closest gNB
453 nrHelper->AttachToClosestGnb(ueLowLatNetDev, gnbNetDev);
454 nrHelper->AttachToClosestGnb(ueVoiceNetDev, gnbNetDev);
455
456 /*
457 * Traffic part. Install two kind of traffic: low-latency and voice, each
458 * identified by a particular source port.
459 */
460 uint16_t dlPortLowLat = 1234;
461 uint16_t dlPortVoice = 1235;
462
463 ApplicationContainer serverApps;
464
465 // The sink will always listen to the specified ports
466 UdpServerHelper dlPacketSinkLowLat(dlPortLowLat);
467 UdpServerHelper dlPacketSinkVoice(dlPortVoice);
468
469 // The server, that is the application which is listening, is installed in the UE
470 serverApps.Add(dlPacketSinkLowLat.Install(ueLowLatContainer));
471 serverApps.Add(dlPacketSinkVoice.Install(ueVoiceContainer));
472
473 /*
474 * Configure attributes for the different generators, using user-provided
475 * parameters for generating a CBR traffic
476 *
477 * Low-Latency configuration and object creation:
478 */
479 UdpClientHelper dlClientLowLat;
480 dlClientLowLat.SetAttribute("RemotePort", UintegerValue(dlPortLowLat));
481 dlClientLowLat.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
482 dlClientLowLat.SetAttribute("PacketSize", UintegerValue(udpPacketSizeULL));
483 dlClientLowLat.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaULL)));
484
485 // The bearer that will carry low latency traffic
487
488 // The filter for the low-latency traffic
489 Ptr<NrEpcTft> lowLatTft = Create<NrEpcTft>();
490 NrEpcTft::PacketFilter dlpfLowLat;
491 dlpfLowLat.localPortStart = dlPortLowLat;
492 dlpfLowLat.localPortEnd = dlPortLowLat;
493 lowLatTft->Add(dlpfLowLat);
494
495 // Voice configuration and object creation:
496 UdpClientHelper dlClientVoice;
497 dlClientVoice.SetAttribute("RemotePort", UintegerValue(dlPortVoice));
498 dlClientVoice.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
499 dlClientVoice.SetAttribute("PacketSize", UintegerValue(udpPacketSizeBe));
500 dlClientVoice.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaBe)));
501
502 // The bearer that will carry voice traffic
504
505 // The filter for the voice traffic
506 Ptr<NrEpcTft> voiceTft = Create<NrEpcTft>();
507 NrEpcTft::PacketFilter dlpfVoice;
508 dlpfVoice.localPortStart = dlPortVoice;
509 dlpfVoice.localPortEnd = dlPortVoice;
510 voiceTft->Add(dlpfVoice);
511
512 /*
513 * Let's install the applications!
514 */
515 ApplicationContainer clientApps;
516
517 for (uint32_t i = 0; i < ueLowLatContainer.GetN(); ++i)
518 {
519 Ptr<Node> ue = ueLowLatContainer.Get(i);
520 Ptr<NetDevice> ueDevice = ueLowLatNetDev.Get(i);
521 Address ueAddress = ueLowLatIpIface.GetAddress(i);
522
523 // The client, who is transmitting, is installed in the remote host,
524 // with destination address set to the address of the UE
525 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(ueAddress));
526 clientApps.Add(dlClientLowLat.Install(remoteHost));
527
528 // Activate a dedicated bearer for the traffic type
529 nrHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
530 }
531
532 for (uint32_t i = 0; i < ueVoiceContainer.GetN(); ++i)
533 {
534 Ptr<Node> ue = ueVoiceContainer.Get(i);
535 Ptr<NetDevice> ueDevice = ueVoiceNetDev.Get(i);
536 Address ueAddress = ueVoiceIpIface.GetAddress(i);
537
538 // The client, who is transmitting, is installed in the remote host,
539 // with destination address set to the address of the UE
540 dlClientVoice.SetAttribute("RemoteAddress", AddressValue(ueAddress));
541 clientApps.Add(dlClientVoice.Install(remoteHost));
542
543 // Activate a dedicated bearer for the traffic type
544 nrHelper->ActivateDedicatedEpsBearer(ueDevice, voiceBearer, voiceTft);
545 }
546
547 // start UDP server and client apps
548 serverApps.Start(udpAppStartTime);
549 clientApps.Start(udpAppStartTime);
550 serverApps.Stop(simTime);
551 clientApps.Stop(simTime);
552
553 // enable the traces provided by the nr module
554 // nrHelper->EnableTraces();
555
556 FlowMonitorHelper flowmonHelper;
557 NodeContainer endpointNodes;
558 endpointNodes.Add(remoteHost);
559 endpointNodes.Add(gridScenario.GetUserTerminals());
560
561 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
562 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.001));
563 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
564 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
565
566 Simulator::Stop(simTime);
567 Simulator::Run();
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 double averageFlowThroughput = 0.0;
583 double averageFlowDelay = 0.0;
584
585 std::ofstream outFile;
586 std::string filename = outputDir + "/" + simTag;
587 outFile.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
588 if (!outFile.is_open())
589 {
590 std::cerr << "Can't open file " << filename << std::endl;
591 return 1;
592 }
593
594 outFile.setf(std::ios_base::fixed);
595
596 double flowDuration = (simTime - udpAppStartTime).GetSeconds();
597 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
598 i != stats.end();
599 ++i)
600 {
601 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
602 std::stringstream protoStream;
603 protoStream << (uint16_t)t.protocol;
604 if (t.protocol == 6)
605 {
606 protoStream.str("TCP");
607 }
608 if (t.protocol == 17)
609 {
610 protoStream.str("UDP");
611 }
612 outFile << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
613 << t.destinationAddress << ":" << t.destinationPort << ") proto "
614 << protoStream.str() << "\n";
615 outFile << " Tx Packets: " << i->second.txPackets << "\n";
616 outFile << " Tx Bytes: " << i->second.txBytes << "\n";
617 outFile << " TxOffered: " << i->second.txBytes * 8.0 / flowDuration / 1000.0 / 1000.0
618 << " Mbps\n";
619 outFile << " Rx Bytes: " << i->second.rxBytes << "\n";
620 if (i->second.rxPackets > 0)
621 {
622 // Measure the duration of the flow from receiver's perspective
623 averageFlowThroughput += i->second.rxBytes * 8.0 / flowDuration / 1000 / 1000;
624 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
625
626 outFile << " Throughput: " << i->second.rxBytes * 8.0 / flowDuration / 1000 / 1000
627 << " Mbps\n";
628 outFile << " Mean delay: "
629 << 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets << " ms\n";
630 // outFile << " Mean upt: " << i->second.uptSum / i->second.rxPackets / 1000/1000 << "
631 // Mbps \n";
632 outFile << " Mean jitter: "
633 << 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets << " ms\n";
634 }
635 else
636 {
637 outFile << " Throughput: 0 Mbps\n";
638 outFile << " Mean delay: 0 ms\n";
639 outFile << " Mean jitter: 0 ms\n";
640 }
641 outFile << " Rx Packets: " << i->second.rxPackets << "\n";
642 }
643
644 double meanFlowThroughput = averageFlowThroughput / stats.size();
645 double meanFlowDelay = averageFlowDelay / stats.size();
646
647 outFile << "\n\n Mean flow throughput: " << meanFlowThroughput << "\n";
648 outFile << " Mean flow delay: " << meanFlowDelay << "\n";
649
650 outFile.close();
651
652 std::ifstream f(filename.c_str());
653
654 if (f.is_open())
655 {
656 std::cout << f.rdbuf();
657 }
658
659 Simulator::Destroy();
660
661 if (argc == 0)
662 {
663 double toleranceMeanFlowThroughput = 0.0001 * 56.258560;
664 double toleranceMeanFlowDelay = 0.0001 * 0.553292;
665
666 if (meanFlowThroughput >= 56.258560 - toleranceMeanFlowThroughput &&
667 meanFlowThroughput <= 56.258560 + toleranceMeanFlowThroughput &&
668 meanFlowDelay >= 0.553292 - toleranceMeanFlowDelay &&
669 meanFlowDelay <= 0.553292 + toleranceMeanFlowDelay)
670 {
671 return EXIT_SUCCESS;
672 }
673 else
674 {
675 return EXIT_FAILURE;
676 }
677 }
678 else if (argc == 1 and ueNumPergNb == 9) // called from examples-to-run.py with these parameters
679 {
680 double toleranceMeanFlowThroughput = 0.0001 * 47.858536;
681 double toleranceMeanFlowDelay = 0.0001 * 10.504189;
682
683 if (meanFlowThroughput >= 47.858536 - toleranceMeanFlowThroughput &&
684 meanFlowThroughput <= 47.858536 + toleranceMeanFlowThroughput &&
685 meanFlowDelay >= 10.504189 - toleranceMeanFlowDelay &&
686 meanFlowDelay <= 10.504189 + toleranceMeanFlowDelay)
687 {
688 return EXIT_SUCCESS;
689 }
690 else
691 {
692 return EXIT_FAILURE;
693 }
694 }
695 else
696 {
697 return EXIT_SUCCESS; // we dont check other parameters configurations at the moment
698 }
699}
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.
This class contains the specification of EPS Bearers.
@ NGBR_LOW_LAT_EMBB
Non-GBR Low Latency eMBB applications.
@ GBR_CONV_VOICE
GBR Conversational Voice.
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.