5G-LENA nr-v4.0
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-3gpp-calibration.cc
1// Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2// Copyright (c) 2022 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3//
4// SPDX-License-Identifier: GPL-2.0-only
5
6#include "cttc-nr-3gpp-calibration.h"
7
8#include "cttc-nr-3gpp-calibration-utils-v1.h"
9#include "cttc-nr-3gpp-calibration-utils-v2.h"
10#include "flow-monitor-output-stats.h"
11#include "power-output-stats.h"
12#include "rb-output-stats.h"
13#include "sinr-output-stats.h"
14#include "slot-output-stats.h"
15
16#include "ns3/antenna-module.h"
17#include "ns3/applications-module.h"
18#include "ns3/config-store-module.h"
19#include "ns3/config-store.h"
20#include "ns3/core-module.h"
21#include "ns3/flow-monitor-module.h"
22#include "ns3/internet-apps-module.h"
23#include "ns3/internet-module.h"
24#include "ns3/lte-module.h"
25#include "ns3/mobility-module.h"
26#include "ns3/network-module.h"
27#include "ns3/point-to-point-module.h"
28#include "ns3/radio-environment-map-helper.h"
29#include "ns3/sqlite-output.h"
30
31#include <iomanip>
32
33/*
34 * To be able to use LOG_* functions.
35 */
36#include "ns3/log.h"
37
38/*
39 * With this line, we will be able to see the logs of the file by enabling the
40 * component "Nr3gppCalibration", in this way:
41 *
42 * $ export NS_LOG="Nr3gppCalibration=level_info|prefix_func|prefix_time"
43 */
44NS_LOG_COMPONENT_DEFINE("Nr3gppCalibration");
45
46namespace ns3
47{
48
49const Time appStartWindow = MilliSeconds(50);
50
51template <typename T>
52Ptr<T>
53CreateLowLatTft(uint16_t start, uint16_t end, std::string dir)
54{
55 Ptr<T> lowLatTft;
56 lowLatTft = Create<T>();
57 typename T::PacketFilter dlpfLowLat;
58 if (dir == "DL")
59 {
60 dlpfLowLat.localPortStart = start;
61 dlpfLowLat.localPortEnd = end;
62 dlpfLowLat.direction = T::DOWNLINK;
63 }
64 else
65 {
66 dlpfLowLat.remotePortStart = start;
67 dlpfLowLat.remotePortEnd = end;
68 dlpfLowLat.direction = T::UPLINK;
69 }
70 lowLatTft->Add(dlpfLowLat);
71 return lowLatTft;
72}
73
74template Ptr<ns3::EpcTft> CreateLowLatTft<ns3::EpcTft>(uint16_t, uint16_t, std::string);
75template Ptr<ns3::NrEpcTft> CreateLowLatTft<ns3::NrEpcTft>(uint16_t, uint16_t, std::string);
76
77static std::pair<ApplicationContainer, Time>
78InstallApps(const Ptr<Node>& ue,
79 const Ptr<NetDevice>& ueDevice,
80 const Address& ueAddress,
81 const std::string& direction,
82 UdpClientHelper* dlClientLowLat,
83 const Ptr<Node>& remoteHost,
84 const Ipv4Address& remoteHostAddr,
85 Time udpAppStartTime,
86 uint16_t dlPortLowLat,
87 const Ptr<UniformRandomVariable>& x,
88 Time appGenerationTime,
89 const Ptr<LteHelper>& lteHelper,
90 const Ptr<NrHelper>& nrHelper)
91{
92 ApplicationContainer app;
93
94 // The bearer that will carry low latency traffic
95 EpsBearer lowLatBearer(EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
96 NrEpsBearer nrLowLatBearer(NrEpsBearer::NGBR_VIDEO_TCP_DEFAULT);
97
98 // The filter for the low-latency traffic
99 Ptr<EpcTft> lowLatTft = CreateLowLatTft<EpcTft>(dlPortLowLat, dlPortLowLat, direction);
100 Ptr<NrEpcTft> nrLowLatTft = CreateLowLatTft<NrEpcTft>(dlPortLowLat, dlPortLowLat, direction);
101
102 // The client, who is transmitting, is installed in the remote host,
103 // with destination address set to the address of the UE
104 if (direction == "DL")
105 {
106 dlClientLowLat->SetAttribute(
107 "Remote",
108 AddressValue(addressUtils::ConvertToSocketAddress(ueAddress, dlPortLowLat)));
109 app = dlClientLowLat->Install(remoteHost);
110 }
111 else
112 {
113 dlClientLowLat->SetAttribute(
114 "Remote",
115 AddressValue(addressUtils::ConvertToSocketAddress(remoteHostAddr, dlPortLowLat)));
116 app = dlClientLowLat->Install(ue);
117 }
118
119 // double start = x->GetValue (udpAppStartTime.GetMilliSeconds (),
120 // (udpAppStartTime + appStartWindow).GetMilliSeconds ());
121
122 // we want the all application start at the same time to have the full buffer traffic since the
123 // beginning
124 Time startTime = udpAppStartTime;
125 app.Start(startTime);
126 app.Stop(startTime + appGenerationTime);
127
128 std::cout << "\tStarts at time " << startTime.As(Time::MS) << " and ends at "
129 << (startTime + appGenerationTime).As(Time::MS) << std::endl;
130
131 // Activate a dedicated bearer for the traffic type
132 if (lteHelper != nullptr)
133 {
134 lteHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
135 }
136 else if (nrHelper != nullptr)
137 {
138 nrHelper->ActivateDedicatedEpsBearer(ueDevice, nrLowLatBearer, nrLowLatTft);
139 }
140
141 return std::make_pair(app, startTime);
142}
143
144static void
145PrintUePosition(NetDeviceContainer ueNetDevs, NodeContainer ueNodes)
146{
147 for (uint32_t ueId = 0; ueId < ueNodes.GetN(); ++ueId)
148 {
149 Ptr<NetDevice> ueNetDev = ueNetDevs.Get(ueId);
150 Vector uepos = ueNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
151
152 std::cout << "ueId: " << ueId << ", at " << uepos << std::endl;
153 }
154
155 Simulator::Schedule(MilliSeconds(100), &PrintUePosition, ueNetDevs, ueNodes);
156}
157
158bool
159Parameters::Validate() const
160{
161 NS_ABORT_MSG_IF(bandwidthMHz != 40 && bandwidthMHz != 20 && bandwidthMHz != 10 &&
162 bandwidthMHz != 5,
163 "Valid bandwidth values are 40, 20, 10, 5, you set " << bandwidthMHz);
164
165 NS_ABORT_MSG_IF(trafficScenario > 4 && trafficScenario != UINT32_MAX,
166 "Traffic scenario " << trafficScenario
167 << " not valid. Valid values are 0 1 2 3 4");
168
169 NS_ABORT_MSG_IF(numerologyBwp > 4, "At most 4 bandwidth parts supported.");
170
171 NS_ABORT_MSG_IF(direction != "DL" && direction != "UL",
172 "Flow direction can only be DL or UL: " << direction);
173 NS_ABORT_MSG_IF(operationMode != "TDD" && operationMode != "FDD",
174 "Operation mode can only be TDD or FDD: " << operationMode);
175 // NS_ABORT_MSG_IF (radioNetwork == "LTE" && operationMode != "FDD",
176 // "Operation mode must be FDD in a 4G LTE network: " << operationMode);
177 NS_ABORT_MSG_IF(simulator != "LENA" && simulator != "5GLENA",
178 "Unrecognized simulator: " << simulator);
179 NS_ABORT_MSG_IF(scheduler != "PF" && scheduler != "RR",
180 "Unrecognized scheduler: " << scheduler);
181 NS_ABORT_MSG_IF(radioNetwork == "NR" && enableFading == false && enableRealBF == true,
182 "Realistic BF should not be enabled in when fading is disabled");
183 // NS_ABORT_MSG_IF (enableFading == false && enableShadowing == true,
184 // "Shadowing must be disabled fading is disabled mode");
185 NS_ABORT_MSG_IF(bfMethod != "Omni" && bfMethod != "CellScan" && bfMethod != "FixedBeam",
186 "For bfMethod you can choose among Omni, CellScan, and FixedBeam");
187 NS_ABORT_MSG_IF(confType != "customConf" && confType != "calibrationConf",
188 "Unrecognized Configuration type: " << confType);
189
190 if (confType == "calibrationConf")
191 {
192 if (radioNetwork == "LTE")
193 {
194 NS_FATAL_ERROR("LTE not supported currently");
195 }
196 else if (radioNetwork == "NR")
197 {
198 NS_ABORT_MSG_IF(
199 (nrConfigurationScenario != "DenseA" && nrConfigurationScenario != "DenseB" &&
200 nrConfigurationScenario != "RuralA" && nrConfigurationScenario != "RuralB"),
201 "NR needs one of the NR pre-defined scenarios to be specified");
202 }
203 else
204 {
205 NS_FATAL_ERROR("Unrecognized radio network technology: " << radioNetwork);
206 }
207 }
208
209 NS_ABORT_MSG_IF(
210 attachToClosest == true && freqScenario == 0,
211 "attachToClosest option should be activated only in overlapping frequency scenario");
212
213 if (dlRem || ulRem)
214 {
215 NS_ABORT_MSG_IF(simulator != "5GLENA",
216 "Cannot do the REM with the simulator " << simulator);
217 NS_ABORT_MSG_IF(dlRem && ulRem, "You selected both DL and UL REM, that is not supported");
218 NS_ABORT_MSG_IF(remSector > 3, "Only three sectors supported for REM");
219
220 NS_ABORT_MSG_IF(remSector == 0 && freqScenario != 1,
221 "RemSector == 0 makes sense only in a OVERLAPPING scenario");
222 }
223
224 return true;
225}
226
227void
228ChooseCalibrationScenario(Parameters& params)
229{
230 if (params.confType == "calibrationConf")
231 {
232 params.utHeight = 1.5;
233
234 if (params.radioNetwork == "NR")
235 {
236 params.freqScenario = 1;
237 if (params.trafficScenario == UINT32_MAX)
238 { // if not configured then set it
239 params.trafficScenario = 0; // full buffer
240 }
241 params.ueTxPower = 23;
242 params.speed = 0.8333; // in m/s (3 km/h)
243
244 params.ueNumRows = 1; // only in DenseB we have 2x4
245 params.ueNumColumns = 1;
246 params.gnbEnable3gppElement = true;
247
248 params.linkO2iConditionToAntennaHeight = false;
249
250 params.scheduler = "RR";
251
252 if (params.nrConfigurationScenario == "DenseA")
253 {
254 params.scenario = "UMa";
255 params.startingFreq = 4e9;
256 params.bandwidthMHz = 10;
257 params.gnbTxPower = 41;
258 params.bsHeight = 25;
259 params.uesWithRandomUtHeight = 0.8;
260 params.isd = 200;
261 params.o2iThreshold = 0.8;
262 params.o2iLowLossThreshold = 0.8;
263 params.linkO2iConditionToAntennaHeight = true;
264
265 params.gnbNumRows = 4;
266 params.gnbNumColumns = 8;
267
268 params.gnbHSpacing = 0.5;
269 params.gnbVSpacing = 0.8;
270
271 params.ueEnable3gppElement = false;
272 params.downtiltAngle = 0;
273 params.gnbNoiseFigure = 5;
274 params.ueNoiseFigure = 7;
275 }
276 else if (params.nrConfigurationScenario == "DenseB")
277 {
278 params.scenario = "UMa";
279 params.startingFreq = 30e9;
280 params.bandwidthMHz = 40;
281 params.gnbTxPower = 37;
282 params.uesWithRandomUtHeight = 0.8;
283 params.bsHeight = 25;
284 params.isd = 200;
285 params.o2iThreshold = 0.8;
286 params.o2iLowLossThreshold = 0.8;
287 params.linkO2iConditionToAntennaHeight = true;
288
289 params.gnbNumRows = 4;
290 params.gnbNumColumns = 8;
291 params.ueNumRows = 2;
292 params.ueNumColumns = 4;
293
294 params.gnbHSpacing = 0.5;
295 params.gnbVSpacing = 0.5;
296
297 params.ueEnable3gppElement = true;
298 params.downtiltAngle = 0;
299 params.gnbNoiseFigure = 7;
300 params.ueNoiseFigure = 10;
301 }
302 else if (params.nrConfigurationScenario == "RuralA")
303 {
304 params.scenario = "RMa";
305 params.startingFreq = 700e6;
306 params.bandwidthMHz = 10;
307 params.gnbTxPower = 46;
308 params.bsHeight = 35;
309 params.isd = 1732;
310 params.o2iThreshold = 0.5;
311
312 params.gnbNumRows = 8;
313 params.gnbNumColumns = 1;
314
315 params.gnbHSpacing = 0.5;
316 params.gnbVSpacing = 0.8;
317
318 params.ueEnable3gppElement = false;
319 params.downtiltAngle = 0; // points towards to horizontal direction
320 params.gnbNoiseFigure = 5;
321 params.ueNoiseFigure = 7;
322 }
323 else if (params.nrConfigurationScenario == "RuralB")
324 {
325 params.scenario = "RMa";
326 params.startingFreq = 4e9;
327 params.bandwidthMHz = 10;
328 params.gnbTxPower = 46;
329 params.bsHeight = 35;
330 params.isd = 1732;
331 params.o2iThreshold = 0.5;
332
333 params.gnbNumRows = 8;
334 params.gnbNumColumns = 1;
335
336 params.gnbHSpacing = 0.5;
337 params.gnbVSpacing = 0.8;
338
339 params.ueEnable3gppElement = false;
340 params.downtiltAngle = 0; // points towards to horizontal direction
341 params.gnbNoiseFigure = 5;
342 params.ueNoiseFigure = 7;
343 }
344 }
345 }
346}
347
348void
349Nr3gppCalibration(Parameters& params)
350{
351 params.Validate();
352
353 // Traffic parameters (that we will use inside this script:)
354 uint32_t udpPacketSize = 1000;
355 uint32_t lambda;
356 uint32_t packetCount;
357
358 std::cout << "\n----------------------------------------\n"
359 << "Configuring scenario" << std::endl;
360
361 std::cout << " traffic parameters\n";
362 switch (params.trafficScenario)
363 {
364 case 0: // let's put 80 Mbps with 20 MHz of bandwidth. Everything else is scaled
365 packetCount = 0xFFFFFFFF;
366 switch (params.bandwidthMHz)
367 {
368 case 40:
369 udpPacketSize = 2000;
370 break;
371 case 20:
372 udpPacketSize = 1000;
373 break;
374 case 10:
375 udpPacketSize = 500;
376 break;
377 case 5:
378 udpPacketSize = 250;
379 break;
380 default:
381 udpPacketSize = 1000;
382 }
383 lambda = 10000 / params.ueNumPergNb;
384 break;
385 case 1:
386 packetCount = 1;
387 udpPacketSize = 12;
388 lambda = 1;
389 break;
390 case 2: // 1 Mbps == 0.125 MB/s in case of 20 MHz, everything else is scaled
391 packetCount = 0xFFFFFFFF;
392 switch (params.bandwidthMHz)
393 {
394 case 40:
395 udpPacketSize = 250;
396 break;
397 case 20:
398 udpPacketSize = 125;
399 break;
400 case 10:
401 udpPacketSize = 63;
402 break;
403 case 5:
404 udpPacketSize = 32;
405 break;
406 default:
407 udpPacketSize = 125;
408 }
409 lambda = 1000 / params.ueNumPergNb;
410 break;
411 case 3: // 20 Mbps == 2.5 MB/s in case of 20 MHz, everything else is scaled
412 packetCount = 0xFFFFFFFF;
413 switch (params.bandwidthMHz)
414 {
415 case 40:
416 udpPacketSize = 500;
417 break;
418 case 20:
419 udpPacketSize = 250;
420 break;
421 case 10:
422 udpPacketSize = 125;
423 break;
424 case 5:
425 udpPacketSize = 75;
426 break;
427 default:
428 udpPacketSize = 250;
429 }
430 lambda = 10000 / params.ueNumPergNb;
431 break;
432 case 4: // let's put 120 Mbps with 20 MHz of bandwidth. Everything else is scaled
433 packetCount = 0xFFFFFFFF;
434 switch (params.bandwidthMHz)
435 {
436 case 40:
437 udpPacketSize = 3000;
438 break;
439 case 20:
440 udpPacketSize = 1500;
441 break;
442 case 10:
443 udpPacketSize = 750;
444 break;
445 case 5:
446 udpPacketSize = 375;
447 break;
448 default:
449 udpPacketSize = 1500;
450 }
451 lambda = 10000 / params.ueNumPergNb;
452 break;
453 default:
454 NS_FATAL_ERROR("Traffic scenario " << params.trafficScenario
455 << " not valid. Valid values are 0 1 2 3 4");
456 }
457
458 std::cout << " statistics\n";
459 SQLiteOutput db(params.outputDir + "/" + params.simTag + ".db");
460 SinrOutputStats sinrStats;
461 PowerOutputStats ueTxPowerStats;
462 PowerOutputStats gnbRxPowerStats;
463 SlotOutputStats slotStats;
464 RbOutputStats rbStats;
465
466 sinrStats.SetDb(&db);
467 ueTxPowerStats.SetDb(&db, "ueTxPower");
468 slotStats.SetDb(&db);
469 rbStats.SetDb(&db);
470 gnbRxPowerStats.SetDb(&db, "gnbRxPower");
471
472 /*
473 * Check if the frequency and numerology are in the allowed range.
474 * If you need to add other checks, here is the best position to put them.
475 */
476 std::cout << " checking frequency and numerology\n";
477
478 /*
479 * If the logging variable is set to true, enable the log of some components
480 * through the code. The same effect can be obtained through the use
481 * of the NS_LOG environment variable:
482 *
483 * export NS_LOG="UdpClient=level_info|prefix_time|prefix_func|prefix_node:UdpServer=..."
484 *
485 * Usually, the environment variable way is preferred, as it is more customizable,
486 * and more expressive.
487 */
488 std::cout << " logging\n";
489 if (params.logging)
490 {
491 LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
492 LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
493 LogComponentEnable("LtePdcp", LOG_LEVEL_INFO);
494 }
495
496 /*
497 * Default values for the simulation. We are progressively removing all
498 * the instances of SetDefault, but we need it for legacy code (LTE)
499 */
500 std::cout << " max tx buffer size\n";
501 Config::SetDefault("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue(999999999));
502 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
503
504 /*
505 * Create the scenario. In our examples, we heavily use helpers that setup
506 * the gnbs and ue following a pre-defined pattern. Please have a look at the
507 * HexagonalGridScenarioHelper documentation to see how the nodes will be distributed.
508 */
509
510 ScenarioParameters scenarioParams;
511
512 // The essentials describing a laydown
513 uint32_t gnbSites = 0;
514 NodeContainer gnbNodes;
515 NodeContainer ueNodes;
516 double sector0AngleRad = 30;
517 const uint32_t sectors = 3;
518
519 scenarioParams.m_isd = params.isd;
520 scenarioParams.m_bsHeight = params.bsHeight;
521 scenarioParams.m_utHeight = params.utHeight;
522 scenarioParams.m_minBsUtDistance = params.minBsUtDistance;
523 scenarioParams.m_antennaOffset = params.antennaOffset;
524
525 scenarioParams.SetSectorization(sectors);
526 scenarioParams.SetScenarioParameters(scenarioParams);
527
528 //
529 NodeDistributionScenarioInterface* scenario{nullptr};
530 HexagonalGridScenarioHelper gridScenario;
531
532 std::cout << " hexagonal grid: ";
533 gridScenario.SetScenarioParameters(scenarioParams);
534 gridScenario.SetSimTag(params.simTag);
535 gridScenario.SetResultsDir(params.outputDir);
536 gridScenario.SetNumRings(params.numOuterRings);
537 gnbSites = gridScenario.GetNumSites();
538 uint32_t ueNum = params.ueNumPergNb * gnbSites * sectors;
539 gridScenario.SetUtNumber(ueNum);
540 sector0AngleRad = gridScenario.GetAntennaOrientationRadians(0);
541 std::cout << sector0AngleRad << std::endl;
542
543 // Creates and plots the network deployment
544 gridScenario.SetMaxUeDistanceToClosestSite(params.maxUeClosestSiteDistance);
545 gridScenario.CreateScenarioWithMobility(
546 Vector(params.speed, 0, 0),
547 params.uesWithRandomUtHeight); // move UEs along the x axis
548
549 gnbNodes = gridScenario.GetBaseStations();
550 ueNodes = gridScenario.GetUserTerminals();
551 scenario = &gridScenario;
552
553 // Log the configuration
554 std::cout << "\n Topology configuration: " << gnbSites << " sites, " << sectors
555 << " sectors/site, " << gnbNodes.GetN() << " cells, " << ueNodes.GetN() << " UEs\n";
556
557 /*
558 * Create different gNB NodeContainer for the different sectors.
559 *
560 * Relationships between ueId, cellId, sectorId and siteId:
561 * ~~~{.cc}
562 * cellId = scenario->GetCellIndex (ueId);
563 * sector = scenario->GetSectorIndex (cellId);
564 * siteId = scenario->GetSiteIndex (cellId);
565 * ~~~{.cc}
566 *
567 * Iterate/index gnbNodes, gnbNetDevs by `cellId`.
568 * Iterate/index gnbSector<N>Container, gnbNodesBySector[sector],
569 * gnbSector<N>NetDev, gnbNdBySector[sector] by `siteId`
570 */
571 NodeContainer gnbSector1Container;
572 NodeContainer gnbSector2Container;
573 NodeContainer gnbSector3Container;
574 std::vector<NodeContainer*> gnbNodesBySector{&gnbSector1Container,
575 &gnbSector2Container,
576 &gnbSector3Container};
577 for (uint32_t cellId = 0; cellId < gnbNodes.GetN(); ++cellId)
578 {
579 Ptr<Node> gnb = gnbNodes.Get(cellId);
580 auto sector = scenario->GetSectorIndex(cellId);
581 gnbNodesBySector[sector]->Add(gnb);
582 }
583 std::cout << " gNb containers: " << gnbSector1Container.GetN() << ", "
584 << gnbSector2Container.GetN() << ", " << gnbSector3Container.GetN() << std::endl;
585
586 /*
587 * Create different UE NodeContainer for the different sectors.
588 *
589 * Multiple UEs per sector!
590 * Iterate/index ueNodes, ueNetDevs, ueIpIfaces by `ueId`.
591 * Iterate/Index ueSector<N>Container, ueNodesBySector[sector],
592 * ueSector<N>NetDev, ueNdBySector[sector] with i % gnbSites
593 */
594 NodeContainer ueSector1Container;
595 NodeContainer ueSector2Container;
596 NodeContainer ueSector3Container;
597 std::vector<NodeContainer*> ueNodesBySector{&ueSector1Container,
598 &ueSector2Container,
599 &ueSector3Container};
600 for (uint32_t ueId = 0; ueId < ueNodes.GetN(); ++ueId)
601 {
602 Ptr<Node> ue = ueNodes.Get(ueId);
603 auto cellId = scenario->GetCellIndex(ueId);
604 auto sector = scenario->GetSectorIndex(cellId);
605 ueNodesBySector[sector]->Add(ue);
606 }
607 std::cout << " UE containers: " << ueSector1Container.GetN() << ", "
608 << ueSector2Container.GetN() << ", " << ueSector3Container.GetN() << std::endl;
609
610 /*
611 * Setup the LTE or NR module. We create the various helpers needed inside
612 * their respective configuration functions
613 */
614 std::cout << " helpers\n";
615 Ptr<PointToPointEpcHelper> epcHelper;
616 Ptr<NrPointToPointEpcHelper> nrEpcHelper;
617
618 NetDeviceContainer gnbSector1NetDev;
619 NetDeviceContainer gnbSector2NetDev;
620 NetDeviceContainer gnbSector3NetDev;
621 std::vector<NetDeviceContainer*> gnbNdBySector{&gnbSector1NetDev,
622 &gnbSector2NetDev,
623 &gnbSector3NetDev};
624 NetDeviceContainer ueSector1NetDev;
625 NetDeviceContainer ueSector2NetDev;
626 NetDeviceContainer ueSector3NetDev;
627 std::vector<NetDeviceContainer*> ueNdBySector{&ueSector1NetDev,
628 &ueSector2NetDev,
629 &ueSector3NetDev};
630
631 Ptr<LteHelper> lteHelper = nullptr;
632 Ptr<NrHelper> nrHelper = nullptr;
633
634 if (params.simulator == "LENA")
635 {
636 epcHelper = CreateObject<PointToPointEpcHelper>();
637 LenaV1Utils::SetLenaV1SimulatorParameters(sector0AngleRad,
638 params.scenario,
639 params.confType,
640 gnbSector1Container,
641 gnbSector2Container,
642 gnbSector3Container,
643 ueSector1Container,
644 ueSector2Container,
645 ueSector3Container,
646 epcHelper,
647 lteHelper,
648 gnbSector1NetDev,
649 gnbSector2NetDev,
650 gnbSector3NetDev,
651 ueSector1NetDev,
652 ueSector2NetDev,
653 ueSector3NetDev,
654 params.lenaCalibration,
655 params.enableUlPc,
656 &sinrStats,
657 &ueTxPowerStats,
658 params.scheduler,
659 params.bandwidthMHz,
660 params.startingFreq,
661 params.freqScenario,
662 params.gnbTxPower,
663 params.ueTxPower,
664 params.gnbNoiseFigure,
665 params.ueNoiseFigure,
666 params.enableShadowing);
667 }
668 else if (params.simulator == "5GLENA")
669 {
670 nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
672 params.scenario,
673 params.confType,
674 params.radioNetwork,
675 params.errorModel,
676 params.operationMode,
677 params.direction,
678 params.numerologyBwp,
679 params.pattern,
680 gnbSector1Container,
681 gnbSector2Container,
682 gnbSector3Container,
683 ueSector1Container,
684 ueSector2Container,
685 ueSector3Container,
686 nrEpcHelper,
687 nrHelper,
688 gnbSector1NetDev,
689 gnbSector2NetDev,
690 gnbSector3NetDev,
691 ueSector1NetDev,
692 ueSector2NetDev,
693 ueSector3NetDev,
694 params.enableFading,
695 params.enableUlPc,
696 params.powerAllocation,
697 &sinrStats,
698 &ueTxPowerStats,
699 &gnbRxPowerStats,
700 &slotStats,
701 &rbStats,
702 params.scheduler,
703 params.bandwidthMHz,
704 params.startingFreq,
705 params.freqScenario,
706 params.gnbTxPower,
707 params.ueTxPower,
708 params.downtiltAngle,
709 params.gnbNumRows,
710 params.gnbNumColumns,
711 params.ueNumRows,
712 params.ueNumColumns,
713 params.gnbEnable3gppElement,
714 params.ueEnable3gppElement,
715 params.gnbHSpacing,
716 params.gnbVSpacing,
717 params.ueHSpacing,
718 params.ueVSpacing,
719 params.gnbNoiseFigure,
720 params.ueNoiseFigure,
721 params.enableRealBF,
722 params.enableShadowing,
723 params.o2iThreshold,
724 params.o2iLowLossThreshold,
725 params.linkO2iConditionToAntennaHeight,
726 params.crossPolarizedGnb,
727 params.crossPolarizedUe,
728 params.polSlantAngleGnb1,
729 params.polSlantAngleGnb2,
730 params.polSlantAngleUe1,
731 params.polSlantAngleUe2,
732 params.bfMethod,
733 params.bfConfSector,
734 params.bfConfElevation,
735 params.isd,
736 params.ueBearingAngle);
737 }
738
739 // Check we got one valid helper
740 if ((lteHelper == nullptr) && (nrHelper == nullptr))
741 {
742 NS_ABORT_MSG("Programming error: no valid helper");
743 }
744
745 // create the internet and install the IP stack on the UEs
746 // get SGW/PGW and create a single RemoteHost
747 std::cout << " pgw and internet\n";
748 Ptr<Node> pgw;
749 if (lteHelper)
750 {
751 pgw = epcHelper->GetPgwNode();
752 }
753 else
754 {
755 pgw = nrEpcHelper->GetPgwNode();
756 }
757 NodeContainer remoteHostContainer;
758 remoteHostContainer.Create(1);
759 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
760 InternetStackHelper internet;
761 internet.Install(remoteHostContainer);
762
763 // connect a remoteHost to pgw. Setup routing too
764 PointToPointHelper p2ph;
765 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
766 p2ph.SetDeviceAttribute("Mtu", UintegerValue(2500));
767 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.000)));
768 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
769 Ipv4AddressHelper ipv4h;
770 Ipv4StaticRoutingHelper ipv4RoutingHelper;
771 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
772 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
773 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
774 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
775 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
776 internet.Install(ueNodes);
777
778 NetDeviceContainer gnbNetDevs(gnbSector1NetDev, gnbSector2NetDev);
779 gnbNetDevs.Add(gnbSector3NetDev);
780 NetDeviceContainer ueNetDevs(ueSector1NetDev, ueSector2NetDev);
781 ueNetDevs.Add(ueSector3NetDev);
782
783 Ipv4InterfaceContainer ueIpIfaces;
784 Ipv4Address gatewayAddress;
785 if (lteHelper)
786 {
787 ueIpIfaces = epcHelper->AssignUeIpv4Address(ueNetDevs);
788 gatewayAddress = epcHelper->GetUeDefaultGatewayAddress();
789 }
790 else
791 {
792 ueIpIfaces = nrEpcHelper->AssignUeIpv4Address(ueNetDevs);
793 gatewayAddress = nrEpcHelper->GetUeDefaultGatewayAddress();
794 }
795
796 Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress(1);
797
798 // Set the default gateway for the UEs
799 std::cout << " default gateway\n";
800 for (auto ue = ueNodes.Begin(); ue != ueNodes.End(); ++ue)
801 {
802 Ptr<Ipv4StaticRouting> ueStaticRouting =
803 ipv4RoutingHelper.GetStaticRouting((*ue)->GetObject<Ipv4>());
804 ueStaticRouting->SetDefaultRoute(gatewayAddress, 1);
805 }
806
807 if (nrHelper != nullptr && params.attachToClosest)
808 {
809 nrHelper->AttachToClosestGnb(ueNetDevs, gnbNetDevs);
810 }
811 else
812 {
813 // attach UEs to their gNB. Try to attach them per cellId order
814 std::cout << " attach UEs to gNBs\n" << std::endl;
815 for (uint32_t ueId = 0; ueId < ueNodes.GetN(); ++ueId)
816 {
817 auto cellId = scenario->GetCellIndex(ueId);
818 Ptr<NetDevice> gnbNetDev = gnbNodes.Get(cellId)->GetDevice(0);
819 Ptr<NetDevice> ueNetDev = ueNodes.Get(ueId)->GetDevice(0);
820 if (lteHelper != nullptr)
821 {
822 lteHelper->Attach(ueNetDev, gnbNetDev);
823 }
824 else if (nrHelper != nullptr)
825 {
826 nrHelper->AttachToGnb(ueNetDev, gnbNetDev);
827 auto uePhyBwp0{nrHelper->GetUePhy(ueNetDev, 0)};
828 auto gnbPhyBwp0{nrHelper->GetGnbPhy(gnbNetDev, 0)};
829 Vector gnbpos = gnbNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
830 Vector uepos = ueNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
831 double distance = CalculateDistance(gnbpos, uepos);
832 std::cout << "ueId " << ueId << ", cellIndex " << cellId << " ue Pos: " << uepos
833 << " gnb Pos: " << gnbpos << ", ue freq "
834 << uePhyBwp0->GetCentralFrequency() / 1e9 << ", gnb freq "
835 << gnbPhyBwp0->GetCentralFrequency() / 1e9 << ", sector "
836 << scenario->GetSectorIndex(cellId) << ", distance " << distance
837 << ", azimuth gnb->ue:"
838 << RadiansToDegrees(Angles(gnbpos, uepos).GetAzimuth()) << std::endl;
839 }
840 }
841 }
842
843 if (params.checkUeMobility)
844 {
845 Simulator::Schedule(MilliSeconds(100), &PrintUePosition, ueNetDevs, ueNodes);
846 }
847
848 /*
849 * Traffic part. Install two kind of traffic: low-latency and voice, each
850 * identified by a particular source port.
851 */
852 std::cout << " server factory\n";
853 uint16_t dlPortLowLat = 1234;
854
855 ApplicationContainer serverApps;
856
857 // The sink will always listen to the specified ports
858 UdpServerHelper dlPacketSinkLowLat(dlPortLowLat);
859
860 // The server, that is the application which is listening, is installed in the UE
861 if (params.direction == "DL")
862 {
863 serverApps.Add(dlPacketSinkLowLat.Install(ueNodes));
864 }
865 else
866 {
867 serverApps.Add(dlPacketSinkLowLat.Install(remoteHost));
868 }
869
870 // start UDP server
871 serverApps.Start(params.udpAppStartTime);
872
873 /*
874 * Configure attributes for the different generators, using user-provided
875 * parameters for generating a CBR traffic
876 *
877 * Low-Latency configuration and object creation:
878 */
879 Time interval = Seconds(1.0 / lambda);
880 std::cout << " client factory:"
881 << "\n packet size: " << udpPacketSize << "\n interval: " << interval
882 << "\n max packets: " << packetCount << std::endl;
883
884 UdpClientHelper dlClientLowLat;
885 dlClientLowLat.SetAttribute("MaxPackets", UintegerValue(packetCount));
886 dlClientLowLat.SetAttribute("PacketSize", UintegerValue(udpPacketSize));
887 dlClientLowLat.SetAttribute("Interval", TimeValue(interval));
888
889 /*
890 * Let's install the applications!
891 */
892 std::cout << " applications\n";
893 ApplicationContainer clientApps;
894 Ptr<UniformRandomVariable> startRng = CreateObject<UniformRandomVariable>();
895 startRng->SetStream(RngSeedManager::GetRun());
896 Time maxStartTime;
897
898 for (uint32_t ueId = 0; ueId < ueNodes.GetN(); ++ueId)
899 {
900 auto cellId = scenario->GetCellIndex(ueId);
901 auto sector = scenario->GetSectorIndex(cellId);
902 auto siteId = scenario->GetSiteIndex(cellId);
903 Ptr<Node> node = ueNodes.Get(ueId);
904 Ptr<NetDevice> dev = ueNetDevs.Get(ueId);
905 Address addr = ueIpIfaces.GetAddress(ueId);
906
907 std::cout << "app for ue " << ueId << ", cellId " << cellId << ", sector " << sector
908 << ", siteId " << siteId;
909 // << ":" << std::endl;
910
911 auto app = InstallApps(node,
912 dev,
913 addr,
914 params.direction,
915 &dlClientLowLat,
916 remoteHost,
917 remoteHostAddr,
918 params.udpAppStartTime,
919 dlPortLowLat,
920 startRng,
921 params.appGenerationTime,
922 lteHelper,
923 nrHelper);
924 maxStartTime = std::max(app.second, maxStartTime);
925 clientApps.Add(app.first);
926 }
927 std::cout << clientApps.GetN() << " apps\n";
928
929 // enable the traces provided by the nr module
930 std::cout << " tracing\n";
931
932 if (lteHelper != nullptr && (params.basicTraces || params.extendedTraces))
933 {
934 lteHelper->EnableTraces();
935 }
936 else if (nrHelper != nullptr && params.extendedTraces)
937 {
938 nrHelper->EnableTraces();
939 nrHelper->GetPhyRxTrace()->SetSimTag(params.simTag);
940 nrHelper->GetPhyRxTrace()->SetResultsFolder(params.outputDir);
941 }
942 else if (nrHelper != nullptr && params.basicTraces)
943 {
944 nrHelper->EnableDlDataPhyTraces();
945 nrHelper->EnableDlCtrlPhyTraces();
946 nrHelper->EnableDlCtrlPhyTraces();
947 nrHelper->EnableDlCtrlPathlossTraces(ueNetDevs);
948 nrHelper->EnableDlDataPathlossTraces(ueNetDevs);
949 nrHelper->EnableUlPhyTraces();
950 nrHelper->EnablePathlossTraces();
951 nrHelper->GetPhyRxTrace()->SetSimTag(params.simTag);
952 nrHelper->GetPhyRxTrace()->SetResultsFolder(params.outputDir);
953 }
954
955 std::cout << " flowmon\n";
956 FlowMonitorHelper flowmonHelper;
957 NodeContainer endpointNodes;
958 endpointNodes.Add(remoteHost);
959 endpointNodes.Add(ueNodes);
960
961 Ptr<FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
962 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.001));
963 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
964 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
965
966 std::string tableName = "e2e";
967
968 Ptr<NrRadioEnvironmentMapHelper>
969 remHelper; // Must be placed outside of block "if (generateRem)" because otherwise it gets
970 // destroyed, and when simulation starts the object does not exist anymore, but
971 // the scheduled REM events do (exist). So, REM events would be called with
972 // invalid pointer to remHelper ...
973 if (params.operationMode == "FDD")
974 {
975 Config::SetDefault("ns3::NrUeNetDevice::PrimaryUlIndex", UintegerValue(1));
976 }
977 if (params.dlRem || params.ulRem)
978 {
979 std::cout << " rem helper\n";
980
981 uint16_t remPhyIndex = 0;
982 if (params.operationMode == "FDD" && params.direction == "UL")
983 {
984 remPhyIndex = 1;
985 }
986
987 NetDeviceContainer remNd;
988 Ptr<NetDevice> remDevice;
989
990 // params.ulRem:
991 std::vector<NetDeviceContainer*> remNdBySector{ueNdBySector};
992 std::vector<NetDeviceContainer*> remDevBySector{gnbNdBySector};
993
994 if (params.dlRem)
995 {
996 remNdBySector = gnbNdBySector;
997 remDevBySector = ueNdBySector;
998 }
999
1000 uint32_t sectorIndex;
1001 // Reverse order so we get sector 1 for the remSector == 0 case
1002 for (uint32_t sector = sectors; sector > 0; --sector)
1003 {
1004 if (params.remSector == sector || params.remSector == 0)
1005 {
1006 sectorIndex = sector - 1;
1007 remNd.Add(*remNdBySector[sectorIndex]);
1008
1009 uint32_t remUe;
1010 if (params.useLastUeForRem)
1011 {
1012 remUe = (remDevBySector[sectorIndex]->GetN() - 1);
1013 remDevice = remDevBySector[sectorIndex]->Get(remUe);
1014 }
1015 else
1016 {
1017 remDevice = remDevBySector[sectorIndex]->Get(0);
1018 }
1019 }
1020 }
1021
1022 if (params.ulRem)
1023 {
1024 auto antArray = DynamicCast<NrGnbNetDevice>(remDevice)
1025 ->GetPhy(0)
1026 ->GetSpectrumPhy()
1027 ->GetAntenna()
1028 ->GetObject<UniformPlanarArray>();
1029 auto antenna = ConstCast<UniformPlanarArray>(antArray);
1030 antenna->SetAttribute("AntennaElement",
1031 PointerValue(CreateObject<IsotropicAntennaModel>()));
1032 }
1033
1034 // Radio Environment Map Generation for ccId 0
1035 remHelper = CreateObject<NrRadioEnvironmentMapHelper>();
1036 remHelper->SetMinX(params.xMinRem);
1037 remHelper->SetMaxX(params.xMaxRem);
1038 remHelper->SetResX(params.xResRem);
1039 remHelper->SetMinY(params.yMinRem);
1040 remHelper->SetMaxY(params.yMaxRem);
1041 remHelper->SetResY(params.yResRem);
1042 remHelper->SetZ(params.zRem);
1043
1044 // save beamforming vectors, one per site (?)
1045 for (uint32_t sector = sectors; sector > 0; --sector)
1046 {
1047 if ((params.remSector == sector) || (params.remSector == 0))
1048 {
1049 sectorIndex = sector - 1;
1050 for (uint32_t siteId = 0; siteId < gnbSites; ++siteId)
1051 {
1052 gnbNdBySector[sectorIndex]
1053 ->Get(siteId)
1054 ->GetObject<NrGnbNetDevice>()
1055 ->GetPhy(remPhyIndex)
1056 ->ChangeBeamformingVector(
1057 DynamicCast<NrUeNetDevice>(ueNdBySector[sectorIndex]->Get(siteId)));
1058 }
1059 }
1060 }
1061
1062 remHelper->CreateRem(remNd, remDevice, remPhyIndex);
1063 }
1064
1065 std::cout << "\n----------------------------------------\n"
1066 << "Start simulation" << std::endl;
1067 // Add some extra time for the last generated packets to be received
1068 const Time appStopWindow = MilliSeconds(50);
1069 Time stopTime = maxStartTime + params.appGenerationTime + appStopWindow;
1070 Simulator::Stop(stopTime);
1071 Simulator::Run();
1072
1073 sinrStats.EmptyCache();
1074 ueTxPowerStats.EmptyCache();
1075 gnbRxPowerStats.EmptyCache();
1076 slotStats.EmptyCache();
1077 rbStats.EmptyCache();
1078
1079 /*
1080 * To check what was installed in the memory, i.e., BWPs of gNB Device, and its configuration.
1081 * Example is: Node 1 -> Device 0 -> BandwidthPartMap -> {0,1} BWPs -> NrGnbPhy -> Numerology,
1082 GtkConfigStore config;
1083 config.ConfigureAttributes ();
1084 */
1085
1086 FlowMonitorOutputStats flowMonStats;
1087 flowMonStats.SetDb(&db, tableName);
1088 flowMonStats.Save(monitor, flowmonHelper, params.outputDir + "/" + params.simTag);
1089
1090 std::cout << "\n----------------------------------------\n"
1091 << "End simulation" << std::endl;
1092
1093 Simulator::Destroy();
1094}
1095
1096std::ostream&
1097operator<<(std::ostream& os, const Parameters& parameters)
1098{
1099 // Use p as shorthand for arg parametersx
1100 auto p{parameters};
1101
1102#define MSG(m) \
1103 os << "\n" << m << std::left << std::setw(40 - strlen(m)) << (strlen(m) > 0 ? ":" : "")
1104
1105 MSG("Calibration Scenario Parameters");
1106 MSG("");
1107 MSG("Model version") << p.simulator << (p.simulator == "LENA" ? " (v1)" : " (v2)");
1108
1109 MSG("Starting Frequency") << (p.startingFreq);
1110 MSG("Channel bandwidth") << p.bandwidthMHz << " MHz";
1111 MSG("Spectrum configuration") << (p.freqScenario == 0 ? "non-" : "") << "overlapping";
1112 MSG("Scheduler") << p.scheduler;
1113 MSG("Number of UEs per sector") << p.ueNumPergNb;
1114
1115 if (p.simulator == "5GLENA")
1116 {
1117 MSG("LTE Standard") << p.radioNetwork << (p.radioNetwork == "LTE" ? " (4G)" : " (5G NR)");
1118 MSG("Configuration") << (p.confType == "calibrationConf" ? "pre-defined Scenarios"
1119 : "custom Configuration");
1120 if (p.confType == "calibrationConf")
1121 {
1122 MSG("Pre-defined Scenario") << p.nrConfigurationScenario;
1123 }
1124 MSG("Operation mode") << p.operationMode;
1125 MSG("Numerology") << p.numerologyBwp;
1126
1127 if (p.operationMode == "TDD")
1128 {
1129 MSG("TDD pattern") << p.pattern;
1130 }
1131
1132 MSG("gNB/UE Tx Power (dBm)") << p.gnbTxPower << (", ") << p.ueTxPower;
1133 MSG("gNB/UE Antenna Height (m)") << p.bsHeight << (", ") << p.utHeight;
1134
1135 MSG("UE-BS min distance (m)") << p.minBsUtDistance;
1136
1137 MSG("UE-BS max distance (m)") << p.maxUeClosestSiteDistance;
1138
1139 MSG("Error model") << p.errorModel;
1140
1141 MSG("Downtilt(deg)") << p.downtiltAngle;
1142
1143 MSG("gNB Antenna") << p.gnbNumRows << (", ") << p.gnbNumColumns << (", ") << p.gnbHSpacing
1144 << (", ") << p.gnbVSpacing;
1145
1146 MSG("gNB Antenna Element") << (p.gnbEnable3gppElement ? "3GPP" : "ISO");
1147
1148 MSG("UE Antenna") << p.ueNumRows << (", ") << p.ueNumColumns << (", ") << p.ueHSpacing
1149 << (", ") << p.ueVSpacing;
1150 MSG("UE Antenna Element") << (p.ueEnable3gppElement ? "3GPP" : "ISO");
1151
1152 MSG("gNB/UE Noise Figure") << p.gnbNoiseFigure << (", ") << p.ueNoiseFigure;
1153
1154 if (p.radioNetwork == "NR")
1155 {
1156 MSG("5G-NR Realistic BF") << (p.enableRealBF ? "Enabled" : "Disabled");
1157 }
1158
1159 MSG("Shadowing") << (p.enableShadowing ? "Enabled" : "Disabled");
1160 MSG("Fading") << (p.enableFading ? "Enabled" : "Disabled");
1161
1162 MSG("BF method") << p.bfMethod;
1163
1164 if (p.crossPolarizedGnb)
1165 {
1166 MSG("Cross Polarization at gNB with angles")
1167 << p.polSlantAngleGnb1 << (", ") << p.polSlantAngleGnb2;
1168
1169 if (p.crossPolarizedUe)
1170 {
1171 MSG("Cross Polarization at UE with angles")
1172 << p.polSlantAngleUe1 << (", ") << p.polSlantAngleUe2;
1173 }
1174 else
1175 {
1176 MSG("Cross Polarization at UE is NOT ENABLED");
1177 }
1178 }
1179 else
1180 {
1181 MSG("Cross Polarization is NOT ENABLED");
1182 }
1183 MSG("4G-NR ULPC mode") << (p.enableUlPc ? "Enabled" : "Disabled");
1184 }
1185 else
1186 {
1187 // LENA v1
1188 MSG("Operation mode") << p.operationMode;
1189 MSG("LTE Standard") << "4G";
1190 MSG("Lena calibration mode") << (p.lenaCalibration ? "ON" : "off");
1191 MSG("LTE ULPC mode") << (p.enableUlPc ? "Enabled" : "Disabled");
1192 }
1193 MSG("");
1194
1195 MSG("Base station positions") << "regular hexagonal lay down";
1196 MSG("Number of rings") << p.numOuterRings;
1197
1198 if (p.baseStationFile.empty() and p.useSiteFile)
1199 {
1200 MSG("Number of outer rings") << p.numOuterRings;
1201 }
1202
1203 MSG("");
1204 MSG("Network loading") << p.trafficScenario;
1205 switch (p.trafficScenario)
1206 {
1207 case 0:
1208 MSG(" Max loading (80 Mbps/20 MHz)");
1209 MSG(" Number of packets") << "infinite";
1210 MSG(" Packet size");
1211 switch (p.bandwidthMHz)
1212 {
1213 case 40:
1214 os << "2000 bytes";
1215 break;
1216 case 20:
1217 os << "1000 bytes";
1218 break;
1219 case 10:
1220 os << "500 bytes";
1221 break;
1222 case 5:
1223 os << "250 bytes";
1224 break;
1225 default:
1226 os << "1000 bytes";
1227 }
1228 // 1 s / (10000 / nUes)
1229 MSG(" Inter-packet interval (per UE)") << p.ueNumPergNb / 10.0 << " ms";
1230 break;
1231
1232 case 1:
1233 MSG(" Latency");
1234 MSG(" Number of packets") << 1;
1235 MSG(" Packet size") << "12 bytes";
1236 MSG(" Inter-packet interval (per UE)") << "1 s";
1237 break;
1238
1239 case 2:
1240 MSG(" Moderate loading");
1241 MSG(" Number of packets") << "infinite";
1242 MSG(" Packet size");
1243 switch (p.bandwidthMHz)
1244 {
1245 case 40:
1246 os << "250 bytes";
1247 break;
1248 case 20:
1249 os << "125 bytes";
1250 break;
1251 case 10:
1252 os << "63 bytes";
1253 break;
1254 case 5:
1255 os << "32 bytes";
1256 break;
1257 default:
1258 os << "125 bytes";
1259 }
1260 // 1 s / (1000 / nUes)
1261 MSG(" Inter-packet interval (per UE)") << 1 / (1000 / p.ueNumPergNb) << " s";
1262
1263 break;
1264
1265 case 3:
1266 MSG(" Moderate-high loading");
1267 MSG(" Number of packets") << "infinite";
1268 MSG(" Packet size");
1269 switch (p.bandwidthMHz)
1270 {
1271 case 40:
1272 os << "500 bytes";
1273 break;
1274 case 20:
1275 os << "250 bytes";
1276 break;
1277 case 10:
1278 os << "125 bytes";
1279 break;
1280 case 5:
1281 os << "75 bytes";
1282 break;
1283 default:
1284 os << "250 bytes";
1285 }
1286 // 1 s / (10000 / nUes)
1287 MSG(" Inter-packet interval (per UE)") << 1 / (10000.0 / p.ueNumPergNb) << " s";
1288
1289 break;
1290 case 4:
1291 MSG(" Max loading (120 Mbps/20 MHz)");
1292 MSG(" Number of packets") << "infinite";
1293 MSG(" Packet size");
1294 switch (p.bandwidthMHz)
1295 {
1296 case 40:
1297 os << "3000 bytes";
1298 break;
1299 case 20:
1300 os << "1500 bytes";
1301 break;
1302 case 10:
1303 os << "750 bytes";
1304 break;
1305 case 5:
1306 os << "375 bytes";
1307 break;
1308 default:
1309 os << "1500 bytes";
1310 }
1311 // 1 s / (10000 / nUes)
1312 MSG(" Inter-packet interval (per UE)") << p.ueNumPergNb / 10.0 << " ms";
1313 break;
1314 default:
1315 os << "\n (Unknown configuration)";
1316 }
1317
1318 MSG("Application start window")
1319 << p.udpAppStartTime.As(Time::MS) << " + " << appStartWindow.As(Time::MS);
1320 MSG("Application on duration") << p.appGenerationTime.As(Time::MS);
1321 MSG("Traffic direction") << p.direction;
1322
1323 MSG("");
1324 MSG("Output file name") << p.simTag;
1325 MSG("Output directory") << p.outputDir;
1326 MSG("Logging") << (p.logging ? "ON" : "off");
1327 MSG("Basic Trace file generation") << (p.basicTraces ? "ON" : "OFF");
1328 MSG("Extended Trace file generation") << (p.extendedTraces ? "ON" : "OFF");
1329 MSG("");
1330 MSG("Radio environment map") << (p.dlRem ? "DL" : (p.ulRem ? "UL" : "off"));
1331 if (p.dlRem || p.ulRem)
1332 {
1333 MSG(" Sector to sample");
1334 if (p.remSector == 0)
1335 {
1336 os << "all";
1337 }
1338 else
1339 {
1340 os << p.remSector;
1341 }
1342 MSG(" X range") << p.xMinRem << " - " << p.xMaxRem << ", in " << p.xResRem << " m steps";
1343 MSG(" Y range") << p.yMinRem << " - " << p.yMaxRem << ", in " << p.yResRem << " m steps";
1344 MSG(" Altitude (Z)") << p.zRem << " m";
1345 }
1346
1347 os << std::endl;
1348 return os;
1349}
1350
1351} // namespace ns3
static void SetLenaV2SimulatorParameters(const double sector0AngleRad, const std::string &scenario, const std::string &confType, const std::string &radioNetwork, std::string errorModel, const std::string &operationMode, const std::string &direction, uint16_t numerology, const std::string &pattern, const NodeContainer &gnbSector1Container, const NodeContainer &gnbSector2Container, const NodeContainer &gnbSector3Container, const NodeContainer &ueSector1Container, const NodeContainer &ueSector2Container, const NodeContainer &ueSector3Container, const Ptr< NrPointToPointEpcHelper > &baseEpcHelper, Ptr< NrHelper > &nrHelper, NetDeviceContainer &gnbSector1NetDev, NetDeviceContainer &gnbSector2NetDev, NetDeviceContainer &gnbSector3NetDev, NetDeviceContainer &ueSector1NetDev, NetDeviceContainer &ueSector2NetDev, NetDeviceContainer &ueSector3NetDev, bool enableFading, bool enableUlPc, std::string powerAllocation, SinrOutputStats *sinrStats, PowerOutputStats *ueTxPowerStats, PowerOutputStats *gnbRxPowerStats, SlotOutputStats *slotStats, RbOutputStats *rbStats, const std::string &scheduler, uint32_t bandwidthMHz, double startingFreq, uint32_t freqScenario, double gnbTxPower, double ueTxPower, double downtiltAngle, const uint32_t gnbNumRows, const uint32_t gnbNumColumns, const uint32_t ueNumRows, const uint32_t ueNumColumns, bool gnbEnable3gppElement, bool ueEnable3gppElement, const double gnbHSpacing, const double gnbVSpacing, const double ueHSpacing, const double ueVSpacing, const double gnbNoiseFigure, const double ueNoiseFigure, bool enableRealBF, bool enableShadowing, double o2iThreshold, double o2iLowLossThreshold, bool linkO2iConditionToAntennaHeight, bool crossPolarizedGnb, bool crossPolarizedUe, double polSlantAngleGnb1, double polSlantAngleGnb2, double polSlantAngleUe1, double polSlantAngleUe2, std::string bfMethod, uint16_t beamConfSector, double beamConfElevation, double isd, bool ueBearingAngle)
@ NGBR_VIDEO_TCP_DEFAULT
Non-GBR TCP-based Video (Buffered Streaming, e.g., www, e-mail...)