5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-fh-xr.cc
Go to the documentation of this file.
1// Copyright (c) 2023 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "ns3/antenna-module.h"
6#include "ns3/applications-module.h"
7#include "ns3/boolean.h"
8#include "ns3/config-store.h"
9#include "ns3/core-module.h"
10#include "ns3/flow-monitor-module.h"
11#include "ns3/internet-module.h"
12#include "ns3/mobility-module.h"
13#include "ns3/network-module.h"
14#include "ns3/nr-module.h"
15#include "ns3/point-to-point-module.h"
16#include "ns3/xr-traffic-mixer-helper.h"
17
18#include <vector>
19
67using namespace ns3;
68
69NS_LOG_COMPONENT_DEFINE("CttcNrFhXr");
70
71std::string m_fhControlMethod;
72uint32_t m_fhCapacity;
73std::ofstream m_fhTraceFile;
74std::string m_fhTraceFileName;
75std::ofstream m_aiTraceFile;
76std::string m_aiTraceFileName;
77std::string m_outputDir;
78
79struct VoiceApplicationSettings
80{
81 Ptr<Node> ue;
82 uint32_t i;
83 Ipv4Address ueIp;
84 uint16_t uePort;
85 std::string transportProtocol;
86 Ptr<Node> remoteHost;
87 Ptr<NetDevice> ueNetDev;
88 Ptr<NrHelper> nrHelper;
89 NrEpsBearer& bearer;
90 Ptr<NrEpcTft> tft;
91 ApplicationContainer& serverApps;
92 ApplicationContainer& clientApps;
93 ApplicationContainer& pingApps;
94 std::string direction;
95 Ipv4Address remoteHostAddress;
96 uint16_t remoteHostPort;
97};
98
99static void PrintUePosition(NodeContainer ueNodes);
100void ConfigureBwpTo(BandwidthPartInfoPtr& bwp, double centerFreq, double bwpBw);
101void ReportFhTrace(const SfnSf& sfn, uint16_t physCellId, uint16_t bwpId, uint64_t reqFh);
102void ReportAiTrace(const SfnSf& sfn, uint16_t physCellId, uint16_t bwpId, uint32_t airRbs);
103
104void ConfigurePhy(Ptr<NrHelper> nrHelper,
105 Ptr<NetDevice> gnb,
106 double orientationRads,
107 uint16_t beamConfSector,
108 double beamConfElevation);
109
110void ConfigureVoiceApp(VoiceApplicationSettings& voiceAppSettings);
111void ConfigureXrApp(NodeContainer& ueContainer,
112 uint32_t i,
113 Ipv4InterfaceContainer& ueIpIface,
114 enum NrXrConfig config,
115 uint16_t uePort,
116 std::string transportProtocol,
117 NodeContainer& remoteHostContainer,
118 NetDeviceContainer& ueNetDev,
119 Ptr<NrHelper> nrHelper,
120 NrEpsBearer& bearer,
121 Ptr<NrEpcTft> tft,
122 bool isMx1,
123 std::vector<Ptr<NrEpcTft>>& tfts,
124 ApplicationContainer& serverApps,
125 ApplicationContainer& clientApps,
126 ApplicationContainer& pingApps,
127 std::string direction,
128 double arDataRate,
129 uint16_t arFps,
130 double vrDataRate,
131 uint16_t vrFps,
132 double cgDataRate,
133 Ipv4Address remoteHostAddress,
134 uint16_t remoteHostPort);
135
136int
137main(int argc, char* argv[])
138{
139 // enable logging or not
140 bool logging = false;
141
142 std::string nrConfigurationScenario = "DenseA";
143 std::string deployment = "HEX";
144 uint32_t freqScenario = 0; // 0 is NON-OVERLAPPING, 1 OVERLAPPING
145
146 // set simulation time and mobility
147 uint32_t appDurationParam = 10000;
148 Time appStartTimeMs = MilliSeconds(400);
149
150 uint16_t arUeNum = 0;
151 uint16_t vrUeNum = 0;
152 uint16_t cgUeNum = 0;
153 uint16_t voiceUeNum = 0;
154
155 double centralFrequency = 4e9;
156 double bandwidth = 10e6;
157 double txPower = 41;
158 double ueTxPower = 23;
159 uint16_t numerology = 1;
160 std::string pattern = "DL|DL|DL|DL|UL|DL|DL|DL|DL|UL|";
161 bool enableTDD4_1 = false;
162
163 std::string propScenario = "UMa";
164 std::string propChannelCondition = "Default";
165 uint16_t numOuterRings = 0;
166 double isd = 200;
167 double bsHeight = 25.0;
168 double utHeight = 1.5;
169 double maxUeClosestSiteDistance = 1000;
170 double minBsUtDistance = 10.0;
171 double speed = 0;
172 double antennaOffset = 1.0;
173 double uesWithRandomUtHeight = 0;
174 double distance = 200;
175
176 double gnbNoiseFigure = 5.0;
177 double ueNoiseFigure = 7.0;
178
179 bool enableMimoFeedback = false;
180
181 bool isGnbDualPolarized = false;
182 uint32_t gnbNumRows = 4;
183 uint32_t gnbNumColumns = 8;
184 size_t gnbHorizPorts = 1;
185 size_t gnbVertPorts = 1;
186 double gnbHSpacing = 0.5;
187 double gnbVSpacing = 0.8;
188 double polSlantAngleGnb = 0.0;
189 double bearingAngleGnb = 0.0;
190
191 bool isUeDualPolarized = false;
192 uint32_t ueNumRows = 1;
193 uint32_t ueNumColumns = 1;
194 size_t ueHorizPorts = 1;
195 size_t ueVertPorts = 1;
196 double ueHSpacing = 0.5;
197 double ueVSpacing = 0.5;
198 double polSlantAngleUe = 90.0;
199 double bearingAngleUe = 180.0;
200
201 double downtiltAngle = 0.0;
202 uint16_t bfConfSector = 1;
203 double bfConfElevation = 30;
204 std::string bfMethod = "CellScan";
205
206 NrHelper::MimoPmiParams mimoPmiParams;
207 mimoPmiParams.pmSearchMethod = "ns3::NrPmSearchFast";
208 mimoPmiParams.fullSearchCb = "ns3::NrCbTwoPort";
209 mimoPmiParams.rankLimit = 2;
210 mimoPmiParams.subbandSize = 8;
211
212 bool enableOfdma = true;
213 std::string schedulerType = "RR";
214
215 bool isLos = false;
216 int channelUpdatePeriod = 20;
217 int channelConditionUpdatePeriod = 100;
218
219 double o2iThreshold = 0;
220 double o2iLowLossThreshold =
221 1.0; // shows the percentage of low losses. Default value is 100% low
222 bool linkO2iConditionToAntennaHeight = false;
223
224 bool enableShadowing = true;
225 uint8_t fixedMcs = 0;
226 bool useFixedMcs = false;
227 std::string errorModel = "ns3::NrEesmIrT2";
228
229 // modulation compression parameters:
230 uint32_t fhCapacity = 10000; // in Mbps
231 uint8_t ohDyn = 100; // in bits
232 std::string fhControlMethod = "OptimizeMcs"; // The FH Control Method to be applied
233 // (Dropping, Postponing, OptimmizeMcs, OptimizeRBs)
234
235 bool isMx1 = true;
236 bool enableHarqRetx = true;
237 bool enableInterServ = false;
238 bool useUdp = true;
239 bool useRlcUm = true;
240 bool enableUl = false;
241
242 double arDataRate = 5; // Mbps
243 uint16_t arFps = 60;
244 double vrDataRate = 5; // Mbps
245 uint16_t vrFps = 60;
246 double cgDataRate = 5; // Mbps
247
248 bool enablePdcpDiscarding = false;
249 uint32_t discardTimerMs = 0;
250 uint32_t reorderingTimerMs = 100;
251
252 bool enableNrHelperTraces = false;
253 bool enableQosTrafficTraces = true;
254
255 // Where we will store the output files.
256 std::string simTag = "";
257 std::string outputDir = "./";
258
259 bool dlRem = false;
260 double xMinRem = -2000.0;
261 double xMaxRem = 2000.0;
262 uint16_t xResRem = 100;
263 double yMinRem = -2000.0;
264 double yMaxRem = 2000.0;
265 uint16_t yResRem = 100;
266 double zRem = 1.5;
267 uint32_t remSector = 0;
268 bool enableFading = true;
269
270 double progressIntervalInSeconds = 600; // 10 minutes
271
272 CommandLine cmd;
273 cmd.AddValue("deployment",
274 "The deployment of the cells. Choose among HEX or SIMPLE",
275 deployment);
276 cmd.AddValue("nrConfigurationScenario",
277 "The NR calibration scenario string. Choose among:"
278 "DenseA (default), RuralA.",
279 nrConfigurationScenario);
280 cmd.AddValue("propScenario", "The urban scenario string (UMa, RMa)", propScenario);
281 cmd.AddValue("freqScenario",
282 "0: NON_OVERLAPPING (each sector in different freq - FR3), "
283 "1: OVERLAPPING (same freq for all sectors - FR1)",
284 freqScenario);
285 cmd.AddValue("isd", "The ISD", isd);
286 cmd.AddValue("numRings", "The number of rings", numOuterRings);
287 cmd.AddValue("arUeNum", "The number of AR UEs", arUeNum);
288 cmd.AddValue("vrUeNum", "The number of VR UEs", vrUeNum);
289 cmd.AddValue("cgUeNum", "The number of CG UEs", cgUeNum);
290 cmd.AddValue("voiceUeNum", "The number of VoIP UEs", voiceUeNum);
291 cmd.AddValue("numerology", "The numerology to be used.", numerology);
292 cmd.AddValue("enableTDD4_1",
293 "If True enables TDD 4:1 and numerology 1, DataRate 30Mbps for VR"
294 "and Fps 30 for AR.",
295 enableTDD4_1);
296 cmd.AddValue("txPower", "Tx power to be configured to gNB", txPower);
297 cmd.AddValue("bsHeight", "The gNB antenna height", bsHeight);
298 cmd.AddValue("distance",
299 "The radius of the disc (in meters) that the UEs will be distributed."
300 "Default value is 200m",
301 distance);
302 cmd.AddValue("enableMimoFeedback", "Enables MIMO feedback", enableMimoFeedback);
303 cmd.AddValue("gnbNumRows", "The number of rows of the phased array of the gNB", gnbNumRows);
304 cmd.AddValue("gnbNumColumns",
305 "The number of columns of the phased array of the gNB",
306 gnbNumColumns);
307 cmd.AddValue("simTag",
308 "tag to be appended to output filenames to distinguish simulation campaigns",
309 simTag);
310 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
311 cmd.AddValue("frequency", "The system frequency", centralFrequency);
312 cmd.AddValue("bandwidth", "The system bandwidth", bandwidth);
313 cmd.AddValue(
314 "fixedMcs",
315 "The fixed MCS that will be used in this example if useFixedMcs is configured to true (1).",
316 fixedMcs);
317 cmd.AddValue("useFixedMcs",
318 "Whether to use fixed mcs, normally used for testing purposes",
319 useFixedMcs);
320 cmd.AddValue("gnbNoiseFigure", "gNB Noise Figure", gnbNoiseFigure);
321 cmd.AddValue("ueNoiseFigure", "UE Noise Figure", ueNoiseFigure);
322 cmd.AddValue("useUdp",
323 "if true, the applications will run over UDP connection, otherwise a TCP "
324 "connection will be used. ",
325 useUdp);
326 cmd.AddValue("useRlcUm", "if true, the Rlc UM will be used, otherwise RLC AM ", useRlcUm);
327 cmd.AddValue("isLos", "if true, configure the LOS scenario, otherwise the default.", isLos);
328 cmd.AddValue("enableOfdma",
329 "If set to true it enables Ofdma scheduler. Default value is false (Tdma)",
330 enableOfdma);
331 cmd.AddValue("schedulerType",
332 "RR: Round-Robin (default), PF: Proportional Fair, Qos",
333 schedulerType);
334 cmd.AddValue("isMx1",
335 "if true M SDFs will be mapped to 1 DRB, otherwise the mapping will "
336 "be 1x1, i.e., 1 SDF to 1 DRB.",
337 isMx1);
338 cmd.AddValue("logging", "Enable logging", logging);
339 cmd.AddValue("enableNrHelperTraces",
340 "If true, it enables the generation of the NrHelper traces, otherwise"
341 "NrHelper traces will not be generated. Default value is true",
342 enableNrHelperTraces);
343 cmd.AddValue("enableQosTrafficTraces",
344 "If true, it enables the generation of the the Delay and Throughput"
345 "traces, otherwise these traces will not be generated. Default value is true",
346 enableQosTrafficTraces);
347 cmd.AddValue("enableInterServ",
348 "If set to true VR is assigned 5QI87. Default value is false (5QI80)",
349 enableInterServ);
350 cmd.AddValue("channelUpdatePeriod",
351 "The channel updated period value in ms. Default value is 20 ms",
352 channelUpdatePeriod);
353 cmd.AddValue("channelConditionUpdatePeriod",
354 "The channel condition updated period value in ms. Default value is 100 ms",
355 channelConditionUpdatePeriod);
356 cmd.AddValue("enableShadowing",
357 "If set to false shadowing is disabled. Default value is true",
358 enableShadowing);
359 cmd.AddValue(
360 "enableFading",
361 "Used to enable/disable fading. By default is enabled. Used for the testing purposes.",
362 enableFading);
363 cmd.AddValue("appDuration", "Duration of the application in milliseconds.", appDurationParam);
364 cmd.AddValue("enableHarqRetx",
365 "If set to false HARQ retransmissions are disabled. Default value is true",
366 enableHarqRetx);
367 cmd.AddValue("maxUeClosestSiteDistance",
368 "Max distance between UE and the closest site",
369 maxUeClosestSiteDistance);
370 cmd.AddValue("enablePdcpDiscarding",
371 "Whether to enable PDCP TX discarding",
372 enablePdcpDiscarding);
373 cmd.AddValue("discardTimerMs",
374 "Discard timer value in milliseconds to use for all the flows",
375 discardTimerMs);
376 cmd.AddValue("reorderingTimerMs",
377 "RLC t-Reordering timer value (See section 7.3 of 3GPP TS 36.322) in milliseconds "
378 "to use for all the flows",
379 reorderingTimerMs);
380 cmd.AddValue("enableUl",
381 "If true, it enables UL direction traffic for AR and VoIP."
382 "Default is false",
383 enableUl);
384 cmd.AddValue("dlRem",
385 "Generates DL REM without executing simulation. REM needs the"
386 "declaration of VoIP UEs for illustrative purposes",
387 dlRem);
388 cmd.AddValue("xMin", "The min x coordinate of the rem map", xMinRem);
389 cmd.AddValue("xMax", "The max x coordinate of the rem map", xMaxRem);
390 cmd.AddValue("xRes", "The resolution on the x axis of the rem map", xResRem);
391 cmd.AddValue("yMin", "The min y coordinate of the rem map", yMinRem);
392 cmd.AddValue("yMax", "The max y coordinate of the rem map", yMaxRem);
393 cmd.AddValue("yRes", "The resolution on the y axis of the rem map", yResRem);
394 cmd.AddValue("z", "The z coordinate of the rem map", zRem);
395 cmd.AddValue("remSector", "For which sector to generate the rem", remSector);
396 cmd.AddValue("progressInterval", "Progress reporting interval", progressIntervalInSeconds);
397 cmd.AddValue("fhCapacity", "Fronthaul capacity (Mbps)", fhCapacity);
398 cmd.AddValue("ohDyn", "Overhead for dynamic modulation compression (bits)", ohDyn);
399 cmd.AddValue(
400 "fhControlMethod",
401 "The FH Control Method to be applied. Choose among: Dropping, Postponing, OptimmizeMcs, "
402 "OptimizeRBs",
403 fhControlMethod);
404
405 cmd.Parse(argc, argv);
406
407 Time appDuration = MilliSeconds(appDurationParam);
408 NS_ABORT_MSG_IF(deployment == "HEX",
409 "HEX deployment needs to be updated for proper operation."
410 "Currently, only SIMPLE deployment can be tested.");
411 NS_ABORT_MSG_IF(appDuration < MilliSeconds(1000), "The appDuration should be at least 1000ms.");
412 NS_ABORT_MSG_IF(!voiceUeNum && !vrUeNum && !arUeNum && !cgUeNum,
413 "Activate at least one type of traffic");
414 NS_ABORT_MSG_IF(dlRem && !voiceUeNum, "For REM generation please declare a VoIP UE.");
415 NS_ABORT_MSG_IF(deployment == "SIMPLE" && (nrConfigurationScenario == "RuralA"),
416 "SIMPLE can be used only with default DenseA configuration");
417
418 // TODO: Fix HEX deployment to work properly with the latest code updates
419
420 m_fhControlMethod = fhControlMethod;
421 m_fhCapacity = fhCapacity;
422 m_outputDir = outputDir;
423
424 if (deployment == "HEX")
425 {
426 if (nrConfigurationScenario == "DenseA")
427 {
428 // For Dense most params are default, but data rates are not
429 arDataRate = 1; // Mbps
430 arFps = 30;
431 vrDataRate = 5; // Mbps
432 cgDataRate = 5; // Mbps
433 }
434 else if (nrConfigurationScenario == "RuralA")
435 {
436 propScenario = "RMa";
437 isd = 1732;
438 centralFrequency = 700e6;
439 pattern = "DL|DL|DL|DL|UL|DL|DL|DL|DL|UL|";
440 enableTDD4_1 = true;
441
442 txPower = 46;
443 bsHeight = 35;
444 maxUeClosestSiteDistance = 500;
445
446 useFixedMcs = false;
447
448 gnbNumRows = 8;
449 gnbNumColumns = 1;
450 bfMethod = "Omni";
451
452 arDataRate = 1; // Mbps
453 arFps = 30;
454 vrDataRate = 5; // Mbps
455 cgDataRate = 5; // Mbps
456 }
457 }
458 else if (deployment == "SIMPLE")
459 {
460 nrConfigurationScenario = "InH_OfficeOpen_LoS";
461 propChannelCondition = "LOS";
462 propScenario = "InH-OfficeOpen";
463 centralFrequency = 30e9;
464 pattern = "DL|DL|DL|DL|UL|DL|DL|DL|DL|UL|";
465 enableTDD4_1 = true;
466 numerology = 3;
467
468 txPower = 30;
469 bsHeight = 3.0;
470 utHeight = 1.5;
471
472 gnbNoiseFigure = 7;
473 ueNoiseFigure = 13;
474
475 useFixedMcs = false;
476
477 gnbNumRows = 16;
478 gnbNumColumns = 8;
479 gnbHSpacing = 0.5;
480 gnbVSpacing = 0.5;
481
482 ueNumRows = 1;
483 ueNumColumns = 4;
484 ueHSpacing = 0.5;
485 ueVSpacing = 0.5;
486
487 bearingAngleGnb = 0.0;
488 bearingAngleUe = 180.0;
489
490 if (enableMimoFeedback)
491 {
492 Config::SetDefault("ns3::NrHelper::EnableMimoFeedback", BooleanValue(true));
493
494 isGnbDualPolarized = true;
495 gnbHorizPorts = 1;
496 gnbVertPorts = 1;
497 polSlantAngleGnb = 0.0;
498
499 isUeDualPolarized = true;
500 ueHorizPorts = 2;
501 ueVertPorts = 1;
502 polSlantAngleUe = 0.0;
503
504 if (bandwidth == 400e6)
505 {
506 mimoPmiParams.subbandSize = 32;
507 }
508 }
509
510 downtiltAngle = 90.0;
511
512 arDataRate = 20; // Mbps
513 arFps = 60;
514 vrDataRate = 45; // Mbps
515 vrFps = 120;
516 cgDataRate = 30; // Mbps
517 }
518 else
519 {
520 NS_ABORT_MSG("Please choose between HEX and SIMPLE deployment");
521 }
522
523 NS_ABORT_MSG_IF(discardTimerMs && !enablePdcpDiscarding,
524 "General discard timer enabled but PDCP discarding not enabled!");
525
526 ShowProgress spinner(Seconds(progressIntervalInSeconds));
527
528 Time simTimeMs = appStartTimeMs + appDuration + MilliSeconds(10);
529 std::cout << "Start example" << std::endl;
530
531 if (deployment == "HEX")
532 {
533 std::string frChosen = freqScenario == 0 ? "FR3" : "FR1";
534 }
535 std::cout << "Deployment chosen: " << deployment
536 << " - Configuration: " << nrConfigurationScenario << std::endl;
537
538 std::string qosScenarioState = enableInterServ == 1 ? "Enabled" : "Disabled";
539 std::cout << "Interactive Service for VR is: " << qosScenarioState << std::endl;
540
541 std::string mappingArch = isMx1 == 1 ? "Mx1" : "1x1";
542 std::cout << "Mapping architecture is set to: " << mappingArch << std::endl;
543
544 std::string enableMimo = enableMimoFeedback == 1 ? "Enabled" : "Disabled";
545 std::cout << "Mimo is set to: " << enableMimo << std::endl;
546
547 if (logging)
548 {
549 LogLevel logLevel1 =
550 (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_LEVEL_INFO);
551 // LogLevel logLevel2 =
552 // (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_LEVEL_DEBUG);
553 LogComponentEnable("NrFhControl", logLevel1);
554 // LogComponentEnable("NrGnbPhy", logLevel1);
555 // LogComponentEnable("NrMacSchedulerNs3", logLevel2);
556 // LogComponentEnable("NrMacSchedulerOfdma", logLevel2);
557 // LogComponentEnable("NrRlcUm", logLevel2);
558 // LogComponentEnable("NrHelper", logLevel2);
559 // LogComponentEnable("FlowMonitor", logLevel2);
560 }
561 Config::SetDefault("ns3::NrRlcUm::EnablePdcpDiscarding", BooleanValue(enablePdcpDiscarding));
562 Config::SetDefault("ns3::NrRlcUm::DiscardTimerMs", UintegerValue(discardTimerMs));
563 Config::SetDefault("ns3::NrRlcUm::ReorderingTimer", TimeValue(MilliSeconds(reorderingTimerMs)));
564
565 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod",
566 TimeValue(MilliSeconds(channelUpdatePeriod)));
567 Config::SetDefault("ns3::NrGnbRrc::EpsBearerToRlcMapping",
568 EnumValue(useUdp ? NrGnbRrc::RLC_UM_ALWAYS : NrGnbRrc::RLC_AM_ALWAYS));
569 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
570
571 // Create Hex Deployment
572 ScenarioParameters scenarioParams;
573
574 // The essentials describing a laydown
575 uint32_t gnbSites = 0;
576 NodeContainer gnbNodes;
577 NodeContainer ueNodes;
578 MobilityHelper mobility;
579 double sector0AngleRad = 30;
580 uint32_t sectors = 3;
581 NodeDistributionScenarioInterface* scenario{nullptr};
582 HexagonalGridScenarioHelper gridScenario;
583
584 if (deployment == "HEX")
585 {
586 scenarioParams.m_isd = isd;
587 scenarioParams.m_bsHeight = bsHeight;
588 scenarioParams.m_utHeight = utHeight;
589 scenarioParams.m_minBsUtDistance = minBsUtDistance;
590 scenarioParams.m_antennaOffset = antennaOffset;
591
592 scenarioParams.SetSectorization(sectors);
593 scenarioParams.SetScenarioParameters(scenarioParams);
594
595 std::cout << " hexagonal grid: ";
596 gridScenario.SetScenarioParameters(scenarioParams);
597 gridScenario.SetSimTag(simTag);
598 gridScenario.SetResultsDir(outputDir);
599 gridScenario.SetNumRings(numOuterRings);
600 gnbSites = gridScenario.GetNumSites();
601 uint32_t ueNum = (voiceUeNum + arUeNum + vrUeNum + cgUeNum) * gnbSites * sectors;
602 gridScenario.SetUtNumber(ueNum);
603 sector0AngleRad = gridScenario.GetAntennaOrientationRadians(0);
604 std::cout << sector0AngleRad << std::endl;
605
606 // Creates and plots the network deployment
607 gridScenario.SetMaxUeDistanceToClosestSite(maxUeClosestSiteDistance);
608 gridScenario.CreateScenarioWithMobility(Vector(speed, 0, 0),
609 uesWithRandomUtHeight); // move UEs along the x axis
610
611 gnbNodes = gridScenario.GetBaseStations();
612 ueNodes = gridScenario.GetUserTerminals();
613 scenario = &gridScenario;
614 }
615 else
616 {
617 sectors = 0; // this would be the sector index
618 gnbSites = 1;
619 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
620
621 gnbNodes.Create(1);
622 ueNodes.Create(voiceUeNum + arUeNum + vrUeNum + cgUeNum);
623
624 Ptr<ListPositionAllocator> bsPositionAlloc = CreateObject<ListPositionAllocator>();
625 bsPositionAlloc->Add(Vector(0.0, 0.0, bsHeight));
626 mobility.SetPositionAllocator(bsPositionAlloc);
627 mobility.Install(gnbNodes);
628
629 Ptr<ListPositionAllocator> uePositionAlloc = CreateObject<ListPositionAllocator>();
630 uePositionAlloc->Add(Vector(0.0, distance, utHeight));
631 mobility.SetPositionAllocator(uePositionAlloc);
632 mobility.Install(ueNodes.Get(
633 0)); // we want the first node on a specific location, the rest is randomly distributed
634
635 // by default the disc is of the radius of 200 meters - we change it to 20 meters
636 Ptr<RandomDiscPositionAllocator> ueDiscPositionAlloc =
637 CreateObject<RandomDiscPositionAllocator>();
638 ueDiscPositionAlloc->SetX(0.0);
639 ueDiscPositionAlloc->SetY(0.0);
640 ueDiscPositionAlloc->SetZ(utHeight);
641 Ptr<UniformRandomVariable> randomDiscPos = CreateObject<UniformRandomVariable>();
642 randomDiscPos->SetAttribute("Min", DoubleValue(0));
643 randomDiscPos->SetAttribute("Max", DoubleValue(20));
644 ueDiscPositionAlloc->SetRho(randomDiscPos);
645 mobility.SetPositionAllocator(ueDiscPositionAlloc);
646
647 for (uint32_t i = 1; i < ueNodes.GetN(); i++)
648 {
649 mobility.Install(ueNodes.Get(i));
650 }
651 }
652
653 // Log the configuration
654 std::cout << "\n Topology configuration: " << gnbSites << " sites, " << sectors
655 << " sectors/site, " << gnbNodes.GetN() << " cells, " << ueNodes.GetN() << " UEs\n";
656
657 /*
658 * Create different gNB NodeContainer for the different sectors.
659 *
660 * Relationships between ueId, cellId, sectorId and siteId:
661 * ~~~{.cc}
662 * cellId = scenario->GetCellIndex (ueId);
663 * sector = scenario->GetSectorIndex (cellId);
664 * siteId = scenario->GetSiteIndex (cellId);
665 * ~~~{.cc}
666 *
667 * Iterate/index gnbNodes, gnbNetDevs by `cellId`.
668 * Iterate/index gnbSector<N>Container, gnbNodesBySector[sector],
669 * gnbSector<N>NetDev, gnbNdBySector[sector] by `siteId`
670 */
671 NodeContainer gnbSector1Container;
672 NodeContainer gnbSector2Container;
673 NodeContainer gnbSector3Container;
674 std::vector<NodeContainer*> gnbNodesBySector{&gnbSector1Container,
675 &gnbSector2Container,
676 &gnbSector3Container};
677
678 for (uint32_t cellId = 0; cellId < gnbNodes.GetN(); ++cellId)
679 {
680 Ptr<Node> gnb = gnbNodes.Get(cellId);
681 auto sectorIndex = deployment == "HEX" ? scenario->GetSectorIndex(cellId) : 0;
682 gnbNodesBySector[sectorIndex]->Add(gnb);
683 }
684 std::cout << " gNb containers: " << gnbSector1Container.GetN() << ", "
685 << gnbSector2Container.GetN() << ", " << gnbSector3Container.GetN() << std::endl;
686
687 /*
688 * Create different UE NodeContainer for the different sectors and the
689 * different traffic types.
690 *
691 * Multiple UEs per sector!
692 * Iterate/index ueNodes, ueNetDevs, ueIpIfaces by `ueId`.
693 * Iterate/Index ueSector<N>Container, ueNodesBySector[sector],
694 * ueSector<N>NetDev, ueNdBySector[sector] with i % gnbSites
695 */
696 NodeContainer ueSector1Container;
697 NodeContainer ueSector2Container;
698 NodeContainer ueSector3Container;
699 std::vector<NodeContainer*> ueNodesBySector{&ueSector1Container,
700 &ueSector2Container,
701 &ueSector3Container};
702
703 NodeContainer ueArSector1Container;
704 NodeContainer ueVrSector1Container;
705 NodeContainer ueCgSector1Container;
706 NodeContainer ueVoiceSector1Container;
707 NodeContainer ueArSector2Container;
708 NodeContainer ueVrSector2Container;
709 NodeContainer ueCgSector2Container;
710 NodeContainer ueVoiceSector2Container;
711 NodeContainer ueArSector3Container;
712 NodeContainer ueVrSector3Container;
713 NodeContainer ueCgSector3Container;
714 NodeContainer ueVoiceSector3Container;
715
716 std::vector<NodeContainer*> ueVoiceBySector{&ueVoiceSector1Container,
717 &ueVoiceSector2Container,
718 &ueVoiceSector3Container};
719 std::vector<NodeContainer*> ueArBySector{&ueArSector1Container,
720 &ueArSector2Container,
721 &ueArSector3Container};
722 std::vector<NodeContainer*> ueVrBySector{&ueVrSector1Container,
723 &ueVrSector2Container,
724 &ueVrSector3Container};
725 std::vector<NodeContainer*> ueCgBySector{&ueCgSector1Container,
726 &ueCgSector2Container,
727 &ueCgSector3Container};
728
729 uint32_t voiceUeCnt = voiceUeNum * gnbNodes.GetN();
730 uint32_t arUeCnt = arUeNum * gnbNodes.GetN();
731 uint32_t vrUeCnt = vrUeNum * gnbNodes.GetN();
732 uint32_t cgUeCnt = cgUeNum * gnbNodes.GetN();
733
734 for (uint32_t ueId = 0; ueId < ueNodes.GetN(); ++ueId)
735 {
736 Ptr<Node> ue = ueNodes.Get(ueId);
737 auto cellId = deployment == "HEX" ? scenario->GetCellIndex(ueId) : 0;
738 auto sectorIndex = deployment == "HEX" ? scenario->GetSectorIndex(cellId) : 0;
739 ueNodesBySector[sectorIndex]->Add(ue);
740
741 if (voiceUeCnt > 0)
742 {
743 ueVoiceBySector[sectorIndex]->Add(ue);
744 voiceUeCnt--;
745 }
746 else if (arUeCnt > 0)
747 {
748 ueArBySector[sectorIndex]->Add(ue);
749 arUeCnt--;
750 }
751 else if (vrUeCnt > 0)
752 {
753 ueVrBySector[sectorIndex]->Add(ue);
754 vrUeCnt--;
755 }
756 else if (cgUeCnt > 0)
757 {
758 ueCgBySector[sectorIndex]->Add(ue);
759 cgUeCnt--;
760 }
761 }
762 std::cout << " UE containers: " << ueSector1Container.GetN() << ", "
763 << ueSector2Container.GetN() << ", " << ueSector3Container.GetN() << std::endl;
764
765 std::cout << " UE Traffic containers: "
766 << ", "
767 << "Sector 1: " << ueVoiceSector1Container.GetN() << ", "
768 << ueArSector1Container.GetN() << ", " << ueVrSector1Container.GetN() << ", "
769 << ueCgSector1Container.GetN() << ", "
770 << "Sector 2: " << ueVoiceSector2Container.GetN() << ", "
771 << ueArSector2Container.GetN() << ", " << ueVrSector2Container.GetN() << ", "
772 << ueCgSector2Container.GetN() << ", "
773 << "Sector 3: " << ueVoiceSector3Container.GetN() << ", "
774 << ueArSector3Container.GetN() << ", " << ueVrSector3Container.GetN() << ", "
775 << ueCgSector3Container.GetN() << ", " << std::endl;
776
777 // setup the nr simulation
778 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
779
780 Ptr<NrPointToPointEpcHelper> epcHelper = CreateObject<NrPointToPointEpcHelper>();
781 nrHelper->SetEpcHelper(epcHelper);
782
783 Ptr<IdealBeamformingHelper> idealBeamformingHelper;
784 idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
785
786 uint8_t numScPerRb = 1;
787 double rbOverhead = 0.04;
788 uint32_t harqProcesses = 16;
789
790 uint32_t n1Delay = 2;
791 uint32_t n2Delay = 2;
792 uint8_t dlCtrlSymbols = 1;
793
794 // Create ChannelHelper API
795 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
796 if (isLos)
797 {
798 propChannelCondition = "LOS";
799 }
800
801 NS_ABORT_MSG_UNLESS(
802 propScenario == "UMa" || propScenario == "RMa" || propScenario == "InH-OfficeOpen",
803 "Unsupported scenario " << scenario << ". Supported values: UMa, RMa, InH-OfficeOpen");
804 // Configure the factories for the channel creation
805 channelHelper->ConfigureFactories(propScenario, propChannelCondition);
806 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(enableShadowing));
807 if (!isLos)
808 {
809 channelHelper->SetChannelConditionModelAttribute(
810 "UpdatePeriod",
811 TimeValue(MilliSeconds(channelConditionUpdatePeriod)));
812 }
813 // In case of DistanceBasedThreeGppSpectrumPropagationLossModel, the creation of the channel
814 // must be manually done, as the channel helper does not support the creation of this specific
815 // model.
816 ObjectFactory distanceBasedChannelFactory;
817 if (deployment == "HEX")
818 {
819 distanceBasedChannelFactory.SetTypeId(
820 DistanceBasedThreeGppSpectrumPropagationLossModel::GetTypeId());
821 distanceBasedChannelFactory.Set("MaxDistance", DoubleValue(2 * isd));
822 channelHelper->SetChannelConditionModelAttribute(
823 "LinkO2iConditionToAntennaHeight",
824 BooleanValue(linkO2iConditionToAntennaHeight));
825 channelHelper->SetChannelConditionModelAttribute("O2iThreshold", DoubleValue(o2iThreshold));
826 channelHelper->SetChannelConditionModelAttribute("O2iLowLossThreshold",
827 DoubleValue(o2iLowLossThreshold));
828
829 std::cout << "o2iThreshold: " << o2iThreshold << std::endl;
830 }
831
832 /********************************************************************/
833 nrHelper->EnableFhControl();
834 nrHelper->SetFhControlAttribute("FhControlMethod", StringValue(fhControlMethod));
835 nrHelper->SetFhControlAttribute("FhCapacity", UintegerValue(fhCapacity));
836 nrHelper->SetFhControlAttribute("OverheadDyn", UintegerValue(ohDyn));
837 /********************************************************************/
838
839 std::stringstream scheduler;
840 std::string subType;
841
842 subType = !enableOfdma ? "Tdma" : "Ofdma";
843 scheduler << "ns3::NrMacScheduler" << subType << schedulerType;
844 std::cout << "Scheduler: " << scheduler.str() << std::endl;
845 nrHelper->SetSchedulerTypeId(TypeId::LookupByName(scheduler.str()));
846
847 if (enableTDD4_1)
848 {
849 nrHelper->SetGnbPhyAttribute("Pattern", StringValue(pattern));
850 }
851
852 // Error Model: UE and GNB with same spectrum error model.
853 nrHelper->SetUlErrorModel(errorModel);
854 nrHelper->SetDlErrorModel(errorModel);
855
856 // Both DL and UL AMC will have the same model behind.
857 nrHelper->SetGnbDlAmcAttribute("AmcModel", EnumValue(NrAmc::ErrorModel));
858 nrHelper->SetGnbUlAmcAttribute("AmcModel", EnumValue(NrAmc::ErrorModel));
859
860 if (deployment == "HEX")
861 {
862 Config::SetDefault("ns3::NrMacSchedulerSrsDefault::StartingPeriodicity", UintegerValue(16));
863 // configure SRS symbols
864 nrHelper->SetSchedulerAttribute("SrsSymbols", UintegerValue(1));
865 nrHelper->SetSchedulerAttribute("EnableSrsInUlSlots", BooleanValue(false));
866 nrHelper->SetSchedulerAttribute("EnableSrsInFSlots", BooleanValue(false));
867
868 /*
869 * Adjust the average number of Reference symbols per RB only for LTE case,
870 * which is larger than in NR. We assume a value of 4 (could be 3 too).
871 */
872 nrHelper->SetGnbDlAmcAttribute("NumRefScPerRb", UintegerValue(numScPerRb));
873 nrHelper->SetGnbUlAmcAttribute("NumRefScPerRb",
874 UintegerValue(1)); // FIXME: Might change in LTE
875
876 nrHelper->SetGnbPhyAttribute("RbOverhead", DoubleValue(rbOverhead));
877 nrHelper->SetGnbPhyAttribute("N2Delay", UintegerValue(n2Delay));
878 nrHelper->SetGnbPhyAttribute("N1Delay", UintegerValue(n1Delay));
879
880 nrHelper->SetUeMacAttribute("NumHarqProcess", UintegerValue(harqProcesses));
881 nrHelper->SetGnbMacAttribute("NumHarqProcess", UintegerValue(harqProcesses));
882
883 // configure CTRL symbols
884 nrHelper->SetSchedulerAttribute("DlCtrlSymbols", UintegerValue(dlCtrlSymbols));
885 }
886
887 nrHelper->SetSchedulerAttribute("EnableHarqReTx", BooleanValue(enableHarqRetx));
888 nrHelper->SetGnbPhyAttribute("TxPower", DoubleValue(txPower));
889 nrHelper->SetGnbPhyAttribute("Numerology", UintegerValue(numerology));
890 nrHelper->SetUePhyAttribute("TxPower", DoubleValue(ueTxPower));
891
892 nrHelper->SetSchedulerAttribute("FixedMcsDl", BooleanValue(useFixedMcs));
893 nrHelper->SetSchedulerAttribute("FixedMcsUl", BooleanValue(useFixedMcs));
894 if (useFixedMcs)
895 {
896 nrHelper->SetSchedulerAttribute("StartingMcsDl", UintegerValue(fixedMcs));
897 nrHelper->SetSchedulerAttribute("StartingMcsUl", UintegerValue(fixedMcs));
898 }
899
900 // Noise figure for the gNB
901 nrHelper->SetGnbPhyAttribute("NoiseFigure", DoubleValue(gnbNoiseFigure));
902 // Noise figure for the UE
903 nrHelper->SetUePhyAttribute("NoiseFigure", DoubleValue(ueNoiseFigure));
904
905 const double band0Start = centralFrequency;
906 uint8_t numBwp = 1;
907 double bandwidthCc = numBwp * bandwidth;
908 uint8_t numCcPerBand = 1;
909 double bandwidthBand = numCcPerBand * bandwidthCc;
910 double bandCenter = band0Start + bandwidthBand / 2.0;
911
912 OperationBandInfo band0;
913 OperationBandInfo band1;
914 OperationBandInfo band2;
915 band0.m_bandId = 0;
916 band1.m_bandId = 1;
917 band2.m_bandId = 2;
918
919 uint8_t bandMask = NrChannelHelper::INIT_PROPAGATION;
920 if (enableFading)
921 {
923 }
924 // Create NrChannelHelper
925 if (deployment == "SIMPLE")
926 {
927 // simple band configuration and initialize
928 CcBwpCreator ccBwpCreator;
929 CcBwpCreator::SimpleOperationBandConf bandConf(centralFrequency, bandwidth, 1);
930 band0 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
931 channelHelper->AssignChannelsToBands({band0}, bandMask);
932 }
933 else if (deployment == "HEX" && freqScenario == 0) // NON_OVERLAPPING
934 {
935 NS_LOG_LOGIC("NON_OVERLAPPING, "
936 << ": " << bandwidthBand << ":" << bandwidthCc << ", " << (int)numCcPerBand
937 << ", " << (int)numBwp);
938
939 NS_LOG_LOGIC("bandConf0: " << bandCenter << " " << bandwidthBand);
940 CcBwpCreator::SimpleOperationBandConf bandConf0(bandCenter, bandwidthBand, numCcPerBand);
941 bandConf0.m_numBwp = numBwp;
942 bandCenter += bandwidthBand;
943
944 NS_LOG_LOGIC("bandConf1: " << bandCenter << " " << bandwidthBand);
945 CcBwpCreator::SimpleOperationBandConf bandConf1(bandCenter, bandwidthBand, numCcPerBand);
946 bandConf1.m_numBwp = numBwp;
947 bandCenter += bandwidthBand;
948
949 NS_LOG_LOGIC("bandConf2: " << bandCenter << " " << bandwidthBand);
950 CcBwpCreator::SimpleOperationBandConf bandConf2(bandCenter, bandwidthBand, numCcPerBand);
951 bandConf2.m_numBwp = numBwp;
952
953 // Create, then configure
954 CcBwpCreator ccBwpCreator;
955 band0 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf0);
956 band0.m_bandId = 0;
957
958 band1 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf1);
959 band1.m_bandId = 1;
960
961 band2 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf2);
962 band2.m_bandId = 2;
963
964 bandCenter = band0Start + bandwidth / 2.0;
965
966 NS_LOG_LOGIC("band0[0][0]: " << bandCenter << " " << bandwidth);
967 ConfigureBwpTo(band0.m_cc[0]->m_bwp[0], bandCenter, bandwidth);
968 bandCenter += bandwidth;
969
970 NS_LOG_LOGIC("band1[0][0]: " << bandCenter << " " << bandwidth);
971 ConfigureBwpTo(band1.m_cc[0]->m_bwp[0], bandCenter, bandwidth);
972 bandCenter += bandwidth;
973
974 NS_LOG_LOGIC("band2[0][0]: " << bandCenter << " " << bandwidth);
975 ConfigureBwpTo(band2.m_cc[0]->m_bwp[0], bandCenter, bandwidth);
976 bandCenter += bandwidth;
977
978 std::cout << "BWP Configuration for NON_OVERLAPPING case "
979 << "\n"
980 << band0 << band1 << band2;
981
982 // Manually assignment of the distance-based channels to the bands
983 for (size_t i = 0; i < band0.GetBwps().size(); i++)
984 {
985 auto distanceBased3gpp =
986 distanceBasedChannelFactory
987 .Create<DistanceBasedThreeGppSpectrumPropagationLossModel>();
988 distanceBased3gpp->SetChannelModelAttribute(
989 "Frequency",
990 DoubleValue(band0.GetBwpAt(0, i)->m_centralFrequency));
991 distanceBased3gpp->SetChannelModelAttribute("Scenario", StringValue(propScenario));
992 auto specChannelBand0 = channelHelper->CreateChannel(NrChannelHelper::INIT_PROPAGATION);
993 if (enableFading)
994 {
995 PointerValue channelConditionModel0;
996 specChannelBand0->GetPropagationLossModel()->GetAttribute("ChannelConditionModel",
997 channelConditionModel0);
998 distanceBased3gpp->SetChannelModelAttribute(
999 "ChannelConditionModel",
1000 PointerValue(channelConditionModel0.Get<ChannelConditionModel>()));
1001 specChannelBand0->AddPhasedArraySpectrumPropagationLossModel(distanceBased3gpp);
1002 }
1003 band0.GetBwpAt(0, i)->SetChannel(specChannelBand0);
1004 }
1005 for (size_t i = 0; i < band1.GetBwps().size(); i++)
1006 {
1007 auto distanceBased3gpp =
1008 distanceBasedChannelFactory
1009 .Create<DistanceBasedThreeGppSpectrumPropagationLossModel>();
1010 distanceBased3gpp->SetChannelModelAttribute(
1011 "Frequency",
1012 DoubleValue(band1.GetBwpAt(0, i)->m_centralFrequency));
1013 distanceBased3gpp->SetChannelModelAttribute("Scenario", StringValue(propScenario));
1014 auto specChannelBand1 = channelHelper->CreateChannel(NrChannelHelper::INIT_PROPAGATION);
1015 if (enableFading)
1016 {
1017 PointerValue channelConditionModel1;
1018 specChannelBand1->GetPropagationLossModel()->GetAttribute("ChannelConditionModel",
1019 channelConditionModel1);
1020 distanceBased3gpp->SetChannelModelAttribute(
1021 "ChannelConditionModel",
1022 PointerValue(channelConditionModel1.Get<ChannelConditionModel>()));
1023 specChannelBand1->AddPhasedArraySpectrumPropagationLossModel(distanceBased3gpp);
1024 }
1025 band1.GetBwpAt(0, i)->SetChannel(specChannelBand1);
1026 }
1027 for (size_t i = 0; i < band2.GetBwps().size(); i++)
1028 {
1029 auto distanceBased3gpp =
1030 distanceBasedChannelFactory
1031 .Create<DistanceBasedThreeGppSpectrumPropagationLossModel>();
1032 distanceBased3gpp->SetAttribute("MaxDistance", DoubleValue(2 * isd));
1033 distanceBased3gpp->SetChannelModelAttribute("Scenario", StringValue(propScenario));
1034 distanceBased3gpp->SetChannelModelAttribute(
1035 "Frequency",
1036 DoubleValue(band2.GetBwpAt(0, i)->m_centralFrequency));
1037 auto specChannelBand2 = channelHelper->CreateChannel(NrChannelHelper::INIT_PROPAGATION);
1038 if (enableFading)
1039 {
1040 PointerValue channelConditionModel2;
1041 specChannelBand2->GetPropagationLossModel()->GetAttribute("ChannelConditionModel",
1042 channelConditionModel2);
1043 distanceBased3gpp->SetChannelModelAttribute(
1044 "ChannelConditionModel",
1045 PointerValue(channelConditionModel2.Get<ChannelConditionModel>()));
1046 specChannelBand2->AddPhasedArraySpectrumPropagationLossModel(distanceBased3gpp);
1047 }
1048 band2.GetBwpAt(0, i)->SetChannel(specChannelBand2);
1049 }
1050 }
1051 else if (deployment == "HEX" && freqScenario == 1) // // OVERLAPPING
1052 {
1053 NS_LOG_LOGIC("OVERLAPPING, " << bandwidthBand << ":" << bandwidthCc << ":" << bandwidth
1054 << ", " << (int)numCcPerBand << ", " << (int)numBwp);
1055
1056 NS_LOG_LOGIC("bandConf0: " << bandCenter << " " << bandwidthBand);
1057 CcBwpCreator::SimpleOperationBandConf bandConf0(bandCenter, bandwidthBand, numCcPerBand);
1058 bandConf0.m_numBwp = numBwp;
1059 bandCenter += bandwidthBand;
1060
1061 // Create, then configure
1062 CcBwpCreator ccBwpCreator;
1063 band0 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf0);
1064 band0.m_bandId = 0;
1065
1066 bandCenter = band0Start + bandwidth / 2.0;
1067
1068 NS_LOG_LOGIC("band0[0][0]: " << bandCenter << " " << bandwidth);
1069 ConfigureBwpTo(band0.m_cc[0]->m_bwp[0], bandCenter, bandwidth);
1070 bandCenter += bandwidth;
1071
1072 for (size_t i = 0; i < band0.GetBwps().size(); i++)
1073 {
1074 auto distanceBased3gpp =
1075 distanceBasedChannelFactory
1076 .Create<DistanceBasedThreeGppSpectrumPropagationLossModel>();
1077 distanceBased3gpp->SetChannelModelAttribute(
1078 "Frequency",
1079 DoubleValue(band0.GetBwpAt(0, i)->m_centralFrequency));
1080 distanceBased3gpp->SetChannelModelAttribute("Scenario", StringValue(propScenario));
1081 auto specChannelBand0 = channelHelper->CreateChannel(NrChannelHelper::INIT_PROPAGATION);
1082 if (enableFading)
1083 {
1084 PointerValue channelConditionModel0;
1085 specChannelBand0->GetPropagationLossModel()->GetAttribute("ChannelConditionModel",
1086 channelConditionModel0);
1087 distanceBased3gpp->SetChannelModelAttribute(
1088 "ChannelConditionModel",
1089 PointerValue(channelConditionModel0.Get<ChannelConditionModel>()));
1090 specChannelBand0->AddPhasedArraySpectrumPropagationLossModel(distanceBased3gpp);
1091 }
1092 band0.GetBwpAt(0, i)->SetChannel(specChannelBand0);
1093 }
1094 }
1095
1096 BandwidthPartInfoPtrVector sector1Bwps;
1097 BandwidthPartInfoPtrVector sector2Bwps;
1098 BandwidthPartInfoPtrVector sector3Bwps;
1099
1100 if (deployment == "SIMPLE")
1101 {
1102 sector1Bwps = CcBwpCreator::GetAllBwps({band0});
1103 }
1104 else if (deployment == "HEX" && freqScenario == 0) // NON_OVERLAPPING
1105 {
1106 sector1Bwps = CcBwpCreator::GetAllBwps({band0});
1107 sector2Bwps = CcBwpCreator::GetAllBwps({band1});
1108 sector3Bwps = CcBwpCreator::GetAllBwps({band2});
1109 }
1110 else // OVERLAPPING
1111 {
1112 sector1Bwps = CcBwpCreator::GetAllBwps({band0});
1113 sector2Bwps = CcBwpCreator::GetAllBwps({band0});
1114 sector3Bwps = CcBwpCreator::GetAllBwps({band0});
1115 }
1116
1117 // Beamforming method
1118 if (deployment == "HEX")
1119 {
1120 if (bfMethod == "Omni")
1121 {
1122 idealBeamformingHelper->SetBeamformingMethod(
1124 }
1125 else if (bfMethod == "CellScan")
1126 {
1127 idealBeamformingHelper->SetBeamformingMethod(CellScanBeamforming::GetTypeId());
1128 idealBeamformingHelper->SetAttribute("BeamformingPeriodicity",
1129 TimeValue(MilliSeconds(10)));
1130 }
1131 }
1132 else if (deployment == "SIMPLE")
1133 {
1134 idealBeamformingHelper->SetAttribute(
1135 "BeamformingMethod",
1137 }
1138 if (enableFading)
1139 {
1140 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
1141 }
1142
1143 bearingAngleGnb = bearingAngleGnb * (M_PI / 180);
1144 bearingAngleUe = bearingAngleUe * (M_PI / 180);
1145
1146 epcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
1147
1148 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(gnbNumRows));
1149 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(gnbNumColumns));
1150 nrHelper->SetGnbAntennaAttribute("AntennaHorizontalSpacing", DoubleValue(gnbHSpacing));
1151 nrHelper->SetGnbAntennaAttribute("AntennaVerticalSpacing", DoubleValue(gnbVSpacing));
1152 nrHelper->SetGnbAntennaAttribute("DowntiltAngle", DoubleValue(downtiltAngle * M_PI / 180.0));
1153 nrHelper->SetGnbAntennaAttribute("AntennaElement",
1154 PointerValue(CreateObject<IsotropicAntennaModel>()));
1155 nrHelper->SetGnbAntennaAttribute("BearingAngle", DoubleValue(bearingAngleGnb));
1156
1157 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(ueNumRows));
1158 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(ueNumColumns));
1159 nrHelper->SetUeAntennaAttribute("AntennaHorizontalSpacing", DoubleValue(ueHSpacing));
1160 nrHelper->SetUeAntennaAttribute("AntennaVerticalSpacing", DoubleValue(ueVSpacing));
1161 nrHelper->SetUeAntennaAttribute("AntennaElement",
1162 PointerValue(CreateObject<IsotropicAntennaModel>()));
1163 nrHelper->SetUeAntennaAttribute("BearingAngle", DoubleValue(bearingAngleUe));
1164
1165 if (enableMimoFeedback)
1166 {
1167 polSlantAngleGnb = bearingAngleGnb * (M_PI / 180);
1168
1169 nrHelper->SetGnbAntennaAttribute("IsDualPolarized", BooleanValue(isGnbDualPolarized));
1170 nrHelper->SetGnbAntennaAttribute("NumHorizontalPorts", UintegerValue(gnbHorizPorts));
1171 nrHelper->SetGnbAntennaAttribute("NumVerticalPorts", UintegerValue(gnbVertPorts));
1172 nrHelper->SetGnbAntennaAttribute("PolSlantAngle", DoubleValue(polSlantAngleGnb));
1173
1174 polSlantAngleUe = polSlantAngleUe * (M_PI / 180);
1175
1176 nrHelper->SetUeAntennaAttribute("IsDualPolarized", BooleanValue(isUeDualPolarized));
1177 nrHelper->SetUeAntennaAttribute("NumHorizontalPorts", UintegerValue(ueHorizPorts));
1178 nrHelper->SetUeAntennaAttribute("NumVerticalPorts", UintegerValue(ueVertPorts));
1179 nrHelper->SetUeAntennaAttribute("PolSlantAngle", DoubleValue(polSlantAngleUe));
1180
1181 nrHelper->SetupMimoPmi(mimoPmiParams);
1182 }
1183
1184 uint32_t bwpIdForLowLat = 0;
1185 uint32_t bwpIdForVoice = 0;
1186 uint32_t bwpIdForVR = 0;
1187
1188 // gNb routing between Bearer and bandwidh part
1189 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB",
1190 UintegerValue(bwpIdForLowLat));
1191 nrHelper->SetGnbBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
1192
1193 // Ue routing between Bearer and bandwidth part
1194 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdForLowLat));
1195 nrHelper->SetUeBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
1196
1197 if (enableInterServ)
1198 {
1199 nrHelper->SetGnbBwpManagerAlgorithmAttribute("DGBR_INTER_SERV_87",
1200 UintegerValue(bwpIdForVR));
1201 nrHelper->SetUeBwpManagerAlgorithmAttribute("DGBR_INTER_SERV_87",
1202 UintegerValue(bwpIdForVR));
1203 }
1204
1205 // Initialize nrHelper
1206 nrHelper->Initialize();
1207
1208 NetDeviceContainer gnbSector1NetDev;
1209 NetDeviceContainer gnbSector2NetDev;
1210 NetDeviceContainer gnbSector3NetDev;
1211
1212 NetDeviceContainer ueVoiceSector1NetDev;
1213 NetDeviceContainer ueArSector1NetDev;
1214 NetDeviceContainer ueVrSector1NetDev;
1215 NetDeviceContainer ueCgSector1NetDev;
1216 NetDeviceContainer ueVoiceSector2NetDev;
1217 NetDeviceContainer ueArSector2NetDev;
1218 NetDeviceContainer ueVrSector2NetDev;
1219 NetDeviceContainer ueCgSector2NetDev;
1220 NetDeviceContainer ueVoiceSector3NetDev;
1221 NetDeviceContainer ueArSector3NetDev;
1222 NetDeviceContainer ueVrSector3NetDev;
1223 NetDeviceContainer ueCgSector3NetDev;
1224
1225 // Defined for REM purposes
1226 std::vector<NetDeviceContainer*> gnbNdBySector{&gnbSector1NetDev,
1227 &gnbSector2NetDev,
1228 &gnbSector3NetDev};
1229 std::vector<NetDeviceContainer*> ueNdBySector{&ueVoiceSector1NetDev,
1230 &ueVoiceSector2NetDev,
1231 &ueVoiceSector3NetDev};
1232
1233 gnbSector1NetDev = nrHelper->InstallGnbDevice(gnbSector1Container, sector1Bwps);
1234 NetDeviceContainer gnbNetDevs(gnbSector1NetDev);
1235
1236 ueVoiceSector1NetDev = nrHelper->InstallUeDevice(ueVoiceSector1Container, sector1Bwps);
1237 ueArSector1NetDev = nrHelper->InstallUeDevice(ueArSector1Container, sector1Bwps);
1238 ueVrSector1NetDev = nrHelper->InstallUeDevice(ueVrSector1Container, sector1Bwps);
1239 ueCgSector1NetDev = nrHelper->InstallUeDevice(ueCgSector1Container, sector1Bwps);
1240
1241 NetDeviceContainer ueNetDevs(ueVoiceSector1NetDev);
1242 ueNetDevs.Add(ueArSector1NetDev);
1243 ueNetDevs.Add(ueVrSector1NetDev);
1244 ueNetDevs.Add(ueCgSector1NetDev);
1245
1246 if (deployment == "HEX")
1247 {
1248 gnbSector2NetDev = nrHelper->InstallGnbDevice(gnbSector2Container, sector2Bwps);
1249 gnbNetDevs.Add(gnbSector2NetDev);
1250 gnbSector3NetDev = nrHelper->InstallGnbDevice(gnbSector3Container, sector3Bwps);
1251 gnbNetDevs.Add(gnbSector3NetDev);
1252
1253 ueVoiceSector2NetDev = nrHelper->InstallUeDevice(ueVoiceSector2Container, sector2Bwps);
1254 ueArSector2NetDev = nrHelper->InstallUeDevice(ueArSector2Container, sector2Bwps);
1255 ueVrSector2NetDev = nrHelper->InstallUeDevice(ueVrSector2Container, sector2Bwps);
1256 ueCgSector2NetDev = nrHelper->InstallUeDevice(ueCgSector2Container, sector2Bwps);
1257 ueNetDevs.Add(ueVoiceSector2NetDev);
1258 ueNetDevs.Add(ueArSector2NetDev);
1259 ueNetDevs.Add(ueVrSector2NetDev);
1260 ueNetDevs.Add(ueCgSector2NetDev);
1261
1262 ueVoiceSector3NetDev = nrHelper->InstallUeDevice(ueVoiceSector3Container, sector3Bwps);
1263 ueArSector3NetDev = nrHelper->InstallUeDevice(ueArSector3Container, sector3Bwps);
1264 ueVrSector3NetDev = nrHelper->InstallUeDevice(ueVrSector3Container, sector3Bwps);
1265 ueCgSector3NetDev = nrHelper->InstallUeDevice(ueCgSector3Container, sector3Bwps);
1266 ueNetDevs.Add(ueVoiceSector3NetDev);
1267 ueNetDevs.Add(ueArSector3NetDev);
1268 ueNetDevs.Add(ueVrSector3NetDev);
1269 ueNetDevs.Add(ueCgSector3NetDev);
1270 }
1271
1272 int64_t randomStream = 1;
1273 randomStream += nrHelper->AssignStreams(gnbNetDevs, randomStream);
1274 randomStream += nrHelper->AssignStreams(ueNetDevs, randomStream);
1275
1276 // Sectors (cells) of a site are pointing at different directions
1277 std::vector<double> sectorOrientationRad{
1278 sector0AngleRad,
1279 sector0AngleRad + 2.0 * M_PI / 3.0, // + 120 deg
1280 sector0AngleRad - 2.0 * M_PI / 3.0 // - 120 deg
1281 };
1282
1283 // TODO: Check that for HEX case we configure correctly the antenna orientations
1284 if (deployment == "HEX")
1285 {
1286 for (uint32_t cellId = 0; cellId < gnbNetDevs.GetN(); ++cellId)
1287 {
1288 Ptr<NetDevice> gnb = gnbNetDevs.Get(cellId);
1289 uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
1290 if (numBwps > 2)
1291 {
1292 NS_ABORT_MSG("Incorrect number of BWPs per CC");
1293 }
1294
1295 uint32_t sector = cellId % (gnbSector3NetDev.GetN() == 0 ? 1 : 3);
1296 double orientation = sectorOrientationRad[sector];
1297
1298 // BWP (in case of TDD)
1299 ConfigurePhy(nrHelper, gnb, orientation, bfConfSector, bfConfElevation);
1300 }
1301 }
1302
1303 nrHelper->ConfigureFhControl(gnbSector1NetDev);
1304 if (deployment == "HEX")
1305 {
1306 nrHelper->ConfigureFhControl(gnbSector2NetDev);
1307 nrHelper->ConfigureFhControl(gnbSector3NetDev);
1308 }
1309
1310 PrintUePosition(ueNodes);
1311
1312 // create the internet and install the IP stack on the UEs
1313 // get SGW/PGW and create a single RemoteHost
1314 Ptr<Node> pgw = epcHelper->GetPgwNode();
1315 NodeContainer remoteHostContainer;
1316 remoteHostContainer.Create(1);
1317 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
1318 InternetStackHelper internet;
1319 internet.Install(remoteHostContainer);
1320
1321 // connect a remoteHost to pgw. Setup routing too
1322 PointToPointHelper p2ph;
1323 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
1324 p2ph.SetDeviceAttribute("Mtu", UintegerValue(1000));
1325 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.000)));
1326 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
1327 Ipv4AddressHelper ipv4h;
1328 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
1329 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
1330
1331 Ipv4StaticRoutingHelper ipv4RoutingHelper;
1332 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
1333 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
1334 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
1335 internet.Install(ueNodes);
1336
1337 Ipv4InterfaceContainer ueVoiceSector1IpIface;
1338 Ipv4InterfaceContainer ueArSector1IpIface;
1339 Ipv4InterfaceContainer ueVrSector1IpIface;
1340 Ipv4InterfaceContainer ueCgSector1IpIface;
1341
1342 Ipv4InterfaceContainer ueVoiceSector2IpIface;
1343 Ipv4InterfaceContainer ueArSector2IpIface;
1344 Ipv4InterfaceContainer ueVrSector2IpIface;
1345 Ipv4InterfaceContainer ueCgSector2IpIface;
1346
1347 Ipv4InterfaceContainer ueVoiceSector3IpIface;
1348 Ipv4InterfaceContainer ueArSector3IpIface;
1349 Ipv4InterfaceContainer ueVrSector3IpIface;
1350 Ipv4InterfaceContainer ueCgSector3IpIface;
1351
1352 ueVoiceSector1IpIface =
1353 epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVoiceSector1NetDev));
1354 ueArSector1IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueArSector1NetDev));
1355 ueVrSector1IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVrSector1NetDev));
1356 ueCgSector1IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueCgSector1NetDev));
1357
1358 if (deployment == "HEX")
1359 {
1360 ueVoiceSector2IpIface =
1361 epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVoiceSector2NetDev));
1362 ueArSector2IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueArSector2NetDev));
1363 ueVrSector2IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVrSector2NetDev));
1364 ueCgSector2IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueCgSector2NetDev));
1365
1366 ueVoiceSector3IpIface =
1367 epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVoiceSector3NetDev));
1368 ueArSector3IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueArSector3NetDev));
1369 ueVrSector3IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVrSector3NetDev));
1370 ueCgSector3IpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueCgSector3NetDev));
1371 }
1372
1373 // attach UEs to the closest eNB
1374 nrHelper->AttachToClosestGnb(ueVoiceSector1NetDev, gnbSector1NetDev);
1375 nrHelper->AttachToClosestGnb(ueArSector1NetDev, gnbSector1NetDev);
1376 nrHelper->AttachToClosestGnb(ueVrSector1NetDev, gnbSector1NetDev);
1377 nrHelper->AttachToClosestGnb(ueCgSector1NetDev, gnbSector1NetDev);
1378
1379 if (deployment == "HEX")
1380 {
1381 nrHelper->AttachToClosestGnb(ueVoiceSector2NetDev, gnbSector2NetDev);
1382 nrHelper->AttachToClosestGnb(ueArSector2NetDev, gnbSector2NetDev);
1383 nrHelper->AttachToClosestGnb(ueVrSector2NetDev, gnbSector2NetDev);
1384 nrHelper->AttachToClosestGnb(ueCgSector2NetDev, gnbSector2NetDev);
1385
1386 nrHelper->AttachToClosestGnb(ueVoiceSector3NetDev, gnbSector3NetDev);
1387 nrHelper->AttachToClosestGnb(ueArSector3NetDev, gnbSector3NetDev);
1388 nrHelper->AttachToClosestGnb(ueVrSector3NetDev, gnbSector3NetDev);
1389 nrHelper->AttachToClosestGnb(ueCgSector3NetDev, gnbSector3NetDev);
1390 }
1391
1392 // Install sink application
1393 ApplicationContainer serverApps;
1394
1395 // configure the transport protocol to be used
1396 std::string transportProtocol;
1397 transportProtocol = useUdp ? "ns3::UdpSocketFactory" : "ns3::TcpSocketFactory";
1398
1399 // DL
1400 uint16_t dlPortArStart = 1121; // AR has 3 flows
1401 uint16_t dlPortArStop = 1124;
1402 uint16_t dlPortVrStart = 1131; // VR Traffic (1 flow)
1403 uint16_t dlPortCgStart = 1141; // CG Traffic (1 flow)
1404
1405 uint16_t dlPortVoiceStart = 1254; // VoIP Traffic (1 flow)
1406
1407 // UL
1408 uint16_t ulPortArStart = 2121; // AR has 3 flows
1409 uint16_t ulPortArStop = 2124;
1410 uint16_t ulPortVoiceStart = 2254; // VoIP has 1 flow
1411
1412 // The bearer that will carry AR traffic (QCI80)
1414
1415 Ptr<NrEpcTft> arTft = Create<NrEpcTft>();
1417 std::vector<Ptr<NrEpcTft>> arTfts;
1418
1419 if (isMx1)
1420 {
1421 dlpfAr.localPortStart = dlPortArStart;
1422 dlpfAr.localPortEnd = dlPortArStop;
1423 arTft->Add(dlpfAr);
1424 }
1425 else
1426 {
1427 // create 3 xrTfts for 1x1 mapping
1428 for (uint32_t i = 0; i < 3; i++)
1429 {
1430 Ptr<NrEpcTft> tempTft = Create<NrEpcTft>();
1431 dlpfAr.localPortStart = dlPortArStart + i;
1432 dlpfAr.localPortEnd = dlPortArStart + i;
1433 tempTft->Add(dlpfAr);
1434 arTfts.push_back(tempTft);
1435 }
1436 }
1437
1438 // The bearer that will carry VR traffic (can be QCI80/QCI87)
1439 NrEpsBearer vrConfig =
1441 NrEpsBearer vrBearer(vrConfig);
1442
1443 Ptr<NrEpcTft> vrTft = Create<NrEpcTft>();
1445 dlpfVr.localPortStart = dlPortVrStart;
1446 dlpfVr.localPortEnd = dlPortVrStart;
1447 vrTft->Add(dlpfVr);
1448
1449 // The bearer that will carry CG traffic (QCI80)
1451
1452 Ptr<NrEpcTft> cgTft = Create<NrEpcTft>();
1454 dlpfCg.localPortStart = dlPortCgStart;
1455 dlpfCg.localPortEnd = dlPortCgStart;
1456 cgTft->Add(dlpfCg);
1457
1458 // The bearer that will carry VoIP traffic
1460
1461 Ptr<NrEpcTft> voiceTft = Create<NrEpcTft>();
1462 NrEpcTft::PacketFilter dlpfVoice;
1463 dlpfVoice.localPortStart = dlPortVoiceStart;
1464 dlpfVoice.localPortEnd = dlPortVoiceStart;
1465 voiceTft->Add(dlpfVoice);
1466
1467 // UL
1468 // The bearer that will carry UL AR traffic (QCI80)
1470
1471 Ptr<NrEpcTft> arUlTft = Create<NrEpcTft>();
1473 std::vector<Ptr<NrEpcTft>> arUlTfts;
1474
1475 if (isMx1)
1476 {
1477 ulpfAr.localPortStart = ulPortArStart;
1478 ulpfAr.localPortEnd = ulPortArStop;
1479 ulpfAr.direction = NrEpcTft::UPLINK;
1480 arUlTft->Add(ulpfAr);
1481 }
1482 else
1483 {
1484 // create 3 xrTfts for 1x1 mapping
1485 for (uint32_t i = 0; i < 3; i++)
1486 {
1487 Ptr<NrEpcTft> tempTft = Create<NrEpcTft>();
1488 ulpfAr.localPortStart = ulPortArStart + i;
1489 ulpfAr.localPortEnd = ulPortArStart + i;
1490 ulpfAr.direction = NrEpcTft::UPLINK;
1491 tempTft->Add(ulpfAr);
1492 arUlTfts.push_back(tempTft);
1493 }
1494 }
1495
1496 // The bearer that will carry UL VoIP traffic
1498
1499 Ptr<NrEpcTft> voiceUlTft = Create<NrEpcTft>();
1500 NrEpcTft::PacketFilter ulpfVoice;
1501 ulpfVoice.localPortStart = ulPortVoiceStart;
1502 ulpfVoice.localPortEnd = ulPortVoiceStart;
1503 ulpfVoice.direction = NrEpcTft::UPLINK;
1504 voiceUlTft->Add(ulpfVoice);
1505
1506 // Install traffic generators
1507 ApplicationContainer clientApps;
1508 ApplicationContainer pingApps;
1509
1510 auto sectorContainers =
1511 std::vector<std::tuple<NodeContainer, NetDeviceContainer, Ipv4InterfaceContainer>>{
1512 {ueVoiceSector1Container, ueVoiceSector1NetDev, ueVoiceSector1IpIface},
1513 {ueVoiceSector2Container, ueVoiceSector2NetDev, ueVoiceSector2IpIface},
1514 {ueVoiceSector3Container, ueVoiceSector3NetDev, ueVoiceSector3IpIface}};
1515
1516 VoiceApplicationSettings voiceAppSettings = {
1517 .uePort = dlPortVoiceStart,
1518 .transportProtocol = transportProtocol,
1519 .nrHelper = nrHelper,
1520 .bearer = voiceBearer,
1521 .tft = voiceTft,
1522 .serverApps = serverApps,
1523 .clientApps = clientApps,
1524 .pingApps = pingApps,
1525 .direction = "DL",
1526
1527 };
1528 for (auto [nodeContainer, netDevContainer, ipIfaceContainer] : sectorContainers)
1529 {
1530 for (uint32_t i = 0; i < nodeContainer.GetN(); ++i)
1531 {
1532 voiceAppSettings.ue = nodeContainer.Get(i);
1533 voiceAppSettings.ueNetDev = netDevContainer.Get(i);
1534 voiceAppSettings.ueIp = ipIfaceContainer.GetAddress(i, 0);
1535 voiceAppSettings.remoteHost = remoteHostContainer.Get(0);
1536 ConfigureVoiceApp(voiceAppSettings);
1537 }
1538 }
1539
1540 uint16_t remoteHostPort = 3254;
1541 if (enableUl)
1542 {
1543 voiceAppSettings.bearer = voiceUlBearer;
1544 voiceAppSettings.tft = voiceUlTft;
1545 voiceAppSettings.direction = "UL";
1546 for (auto [nodeContainer, netDevContainer, ipIfaceContainer] : sectorContainers)
1547 {
1548 for (uint32_t i = 0; i < nodeContainer.GetN(); ++i)
1549 {
1550 voiceAppSettings.uePort = remoteHostPort++;
1551 ConfigureVoiceApp(voiceAppSettings);
1552 }
1553 }
1554 }
1555 /*std::map<NrXrConfig, std::pair<double, std::optional<uint32_t>>> xrconfigs{
1556 {AR_M3, {arDataRate, arFps}},
1557 {VR_DL1, {vrDataRate, vrFps}},
1558 {CG_DL1, {cgDataRate, {}}},
1559 };
1560 for (auto config: xrconfigs)
1561 {
1562 */
1563
1564 for (uint32_t i = 0; i < ueArSector1Container.GetN(); ++i)
1565 {
1566 ConfigureXrApp(ueArSector1Container,
1567 i,
1568 ueArSector1IpIface,
1569 AR_M3,
1570 dlPortArStart,
1571 transportProtocol,
1572 remoteHostContainer,
1573 ueArSector1NetDev,
1574 nrHelper,
1575 arBearer,
1576 arTft,
1577 isMx1,
1578 arTfts,
1579 serverApps,
1580 clientApps,
1581 pingApps,
1582 "DL",
1583 arDataRate,
1584 arFps,
1585 vrDataRate,
1586 vrFps,
1587 cgDataRate,
1588 internetIpIfaces.GetAddress(1),
1589 0);
1590
1591 /* Ptr<TrafficGenerator3gppGenericVideo> app =
1592 DynamicCast<TrafficGenerator3gppGenericVideo>(currentUeClientApps.Get(j));
1593
1594 app->SetAttribute("DataRate", DoubleValue(xrconfigs.at(config).first));
1595 if(!xrconfigs.at(config).second.empty())
1596 {
1597 app->SetAttribute("Fps", DoubleValue(xrconfigs.at(config).second));
1598 }*/
1599 }
1600 for (uint32_t i = 0; i < ueArSector2Container.GetN(); ++i)
1601 {
1602 ConfigureXrApp(ueArSector2Container,
1603 i,
1604 ueArSector2IpIface,
1605 AR_M3,
1606 dlPortArStart,
1607 transportProtocol,
1608 remoteHostContainer,
1609 ueArSector2NetDev,
1610 nrHelper,
1611 arBearer,
1612 arTft,
1613 isMx1,
1614 arTfts,
1615 serverApps,
1616 clientApps,
1617 pingApps,
1618 "DL",
1619 arDataRate,
1620 arFps,
1621 vrDataRate,
1622 vrFps,
1623 cgDataRate,
1624 internetIpIfaces.GetAddress(1),
1625 0);
1626 }
1627 for (uint32_t i = 0; i < ueArSector3Container.GetN(); ++i)
1628 {
1629 ConfigureXrApp(ueArSector3Container,
1630 i,
1631 ueArSector3IpIface,
1632 AR_M3,
1633 dlPortArStart,
1634 transportProtocol,
1635 remoteHostContainer,
1636 ueArSector3NetDev,
1637 nrHelper,
1638 arBearer,
1639 arTft,
1640 isMx1,
1641 arTfts,
1642 serverApps,
1643 clientApps,
1644 pingApps,
1645 "DL",
1646 arDataRate,
1647 arFps,
1648 vrDataRate,
1649 vrFps,
1650 cgDataRate,
1651 internetIpIfaces.GetAddress(1),
1652 0);
1653 }
1654
1655 if (enableUl)
1656 {
1657 remoteHostPort = 4121;
1658 for (uint32_t i = 0; i < ueArSector1Container.GetN(); ++i)
1659 {
1660 ConfigureXrApp(ueArSector1Container,
1661 i,
1662 ueArSector1IpIface,
1663 AR_M3,
1664 ulPortArStart,
1665 transportProtocol,
1666 remoteHostContainer,
1667 ueArSector1NetDev,
1668 nrHelper,
1669 arUlBearer,
1670 arUlTft,
1671 isMx1,
1672 arUlTfts,
1673 serverApps,
1674 clientApps,
1675 pingApps,
1676 "UL",
1677 arDataRate,
1678 arFps,
1679 vrDataRate,
1680 vrFps,
1681 cgDataRate,
1682 internetIpIfaces.GetAddress(1),
1683 remoteHostPort);
1684 remoteHostPort += 3;
1685 }
1686 for (uint32_t i = 0; i < ueArSector2Container.GetN(); ++i)
1687 {
1688 ConfigureXrApp(ueArSector2Container,
1689 i,
1690 ueArSector2IpIface,
1691 AR_M3,
1692 ulPortArStart,
1693 transportProtocol,
1694 remoteHostContainer,
1695 ueArSector2NetDev,
1696 nrHelper,
1697 arUlBearer,
1698 arUlTft,
1699 isMx1,
1700 arUlTfts,
1701 serverApps,
1702 clientApps,
1703 pingApps,
1704 "UL",
1705 arDataRate,
1706 arFps,
1707 vrDataRate,
1708 vrFps,
1709 cgDataRate,
1710 internetIpIfaces.GetAddress(1),
1711 remoteHostPort);
1712 remoteHostPort += 3;
1713 }
1714 for (uint32_t i = 0; i < ueArSector3Container.GetN(); ++i)
1715 {
1716 ConfigureXrApp(ueArSector3Container,
1717 i,
1718 ueArSector3IpIface,
1719 AR_M3,
1720 ulPortArStart,
1721 transportProtocol,
1722 remoteHostContainer,
1723 ueArSector3NetDev,
1724 nrHelper,
1725 arUlBearer,
1726 arUlTft,
1727 isMx1,
1728 arUlTfts,
1729 serverApps,
1730 clientApps,
1731 pingApps,
1732 "UL",
1733 arDataRate,
1734 arFps,
1735 vrDataRate,
1736 vrFps,
1737 cgDataRate,
1738 internetIpIfaces.GetAddress(1),
1739 remoteHostPort);
1740 remoteHostPort += 3;
1741 }
1742 }
1743
1744 for (uint32_t i = 0; i < ueVrSector1Container.GetN(); ++i)
1745 {
1746 ConfigureXrApp(ueVrSector1Container,
1747 i,
1748 ueVrSector1IpIface,
1749 VR_DL1,
1750 dlPortVrStart,
1751 transportProtocol,
1752 remoteHostContainer,
1753 ueVrSector1NetDev,
1754 nrHelper,
1755 vrBearer,
1756 vrTft,
1757 true,
1758 arTfts,
1759 serverApps,
1760 clientApps,
1761 pingApps,
1762 "DL",
1763 arDataRate,
1764 arFps,
1765 vrDataRate,
1766 vrFps,
1767 cgDataRate,
1768 internetIpIfaces.GetAddress(1),
1769 0);
1770 }
1771 for (uint32_t i = 0; i < ueVrSector2Container.GetN(); ++i)
1772 {
1773 ConfigureXrApp(ueVrSector2Container,
1774 i,
1775 ueVrSector2IpIface,
1776 VR_DL1,
1777 dlPortVrStart,
1778 transportProtocol,
1779 remoteHostContainer,
1780 ueVrSector2NetDev,
1781 nrHelper,
1782 vrBearer,
1783 vrTft,
1784 true,
1785 arTfts,
1786 serverApps,
1787 clientApps,
1788 pingApps,
1789 "DL",
1790 arDataRate,
1791 arFps,
1792 vrDataRate,
1793 vrFps,
1794 cgDataRate,
1795 internetIpIfaces.GetAddress(1),
1796 0);
1797 }
1798 for (uint32_t i = 0; i < ueVrSector3Container.GetN(); ++i)
1799 {
1800 ConfigureXrApp(ueVrSector3Container,
1801 i,
1802 ueVrSector3IpIface,
1803 VR_DL1,
1804 dlPortVrStart,
1805 transportProtocol,
1806 remoteHostContainer,
1807 ueVrSector3NetDev,
1808 nrHelper,
1809 vrBearer,
1810 vrTft,
1811 true,
1812 arTfts,
1813 serverApps,
1814 clientApps,
1815 pingApps,
1816 "DL",
1817 arDataRate,
1818 arFps,
1819 vrDataRate,
1820 vrFps,
1821 cgDataRate,
1822 internetIpIfaces.GetAddress(1),
1823 0);
1824 }
1825
1826 for (uint32_t i = 0; i < ueCgSector1Container.GetN(); ++i)
1827 {
1828 ConfigureXrApp(ueCgSector1Container,
1829 i,
1830 ueCgSector1IpIface,
1831 CG_DL1,
1832 dlPortCgStart,
1833 transportProtocol,
1834 remoteHostContainer,
1835 ueCgSector1NetDev,
1836 nrHelper,
1837 cgBearer,
1838 cgTft,
1839 true,
1840 arTfts,
1841 serverApps,
1842 clientApps,
1843 pingApps,
1844 "DL",
1845 arDataRate,
1846 arFps,
1847 vrDataRate,
1848 vrFps,
1849 cgDataRate,
1850 internetIpIfaces.GetAddress(1),
1851 0);
1852 }
1853 for (uint32_t i = 0; i < ueCgSector2Container.GetN(); ++i)
1854 {
1855 ConfigureXrApp(ueCgSector2Container,
1856 i,
1857 ueCgSector2IpIface,
1858 CG_DL1,
1859 dlPortCgStart,
1860 transportProtocol,
1861 remoteHostContainer,
1862 ueCgSector2NetDev,
1863 nrHelper,
1864 cgBearer,
1865 cgTft,
1866 true,
1867 arTfts,
1868 serverApps,
1869 clientApps,
1870 pingApps,
1871 "DL",
1872 arDataRate,
1873 arFps,
1874 vrDataRate,
1875 vrFps,
1876 cgDataRate,
1877 internetIpIfaces.GetAddress(1),
1878 0);
1879 }
1880 for (uint32_t i = 0; i < ueCgSector3Container.GetN(); ++i)
1881 {
1882 ConfigureXrApp(ueCgSector3Container,
1883 i,
1884 ueCgSector3IpIface,
1885 CG_DL1,
1886 dlPortCgStart,
1887 transportProtocol,
1888 remoteHostContainer,
1889 ueCgSector3NetDev,
1890 nrHelper,
1891 cgBearer,
1892 cgTft,
1893 true,
1894 arTfts,
1895 serverApps,
1896 clientApps,
1897 pingApps,
1898 "DL",
1899 arDataRate,
1900 arFps,
1901 vrDataRate,
1902 vrFps,
1903 cgDataRate,
1904 internetIpIfaces.GetAddress(1),
1905 0);
1906 }
1907
1908 pingApps.Start(MilliSeconds(100));
1909 pingApps.Stop(appStartTimeMs);
1910
1911 // start server and client apps
1912 serverApps.Start(appStartTimeMs);
1913 clientApps.Start(appStartTimeMs);
1914 serverApps.Stop(simTimeMs);
1915 clientApps.Stop(appStartTimeMs + appDuration);
1916
1917 // enable the traces provided by the nr module
1918 if (enableNrHelperTraces)
1919 {
1920 nrHelper->EnableTraces();
1921 }
1922
1923 for (NetDeviceContainer::Iterator i = gnbSector1NetDev.Begin(); i != gnbSector1NetDev.End();
1924 ++i)
1925 {
1926 Ptr<NrGnbNetDevice> gnbNetDev = DynamicCast<NrGnbNetDevice>(*i);
1927 gnbNetDev->GetNrFhControl()->TraceConnectWithoutContext("RequiredFhDlThroughput",
1928 MakeCallback(&ReportFhTrace));
1929 gnbNetDev->GetNrFhControl()->TraceConnectWithoutContext("UsedAirRbs",
1930 MakeCallback(&ReportAiTrace));
1931 }
1932
1933 if (deployment == "HEX")
1934 {
1935 for (NetDeviceContainer::Iterator i = gnbSector2NetDev.Begin(); i != gnbSector2NetDev.End();
1936 ++i)
1937 {
1938 Ptr<NrGnbNetDevice> gnbNetDev = DynamicCast<NrGnbNetDevice>(*i);
1939 gnbNetDev->GetNrFhControl()->TraceConnectWithoutContext("RequiredFhDlThroughput",
1940 MakeCallback(&ReportFhTrace));
1941 gnbNetDev->GetNrFhControl()->TraceConnectWithoutContext("UsedAirRbs",
1942 MakeCallback(&ReportAiTrace));
1943 }
1944
1945 for (NetDeviceContainer::Iterator i = gnbSector3NetDev.Begin(); i != gnbSector3NetDev.End();
1946 ++i)
1947 {
1948 Ptr<NrGnbNetDevice> gnbNetDev = DynamicCast<NrGnbNetDevice>(*i);
1949 gnbNetDev->GetNrFhControl()->TraceConnectWithoutContext("RequiredFhDlThroughput",
1950 MakeCallback(&ReportFhTrace));
1951 gnbNetDev->GetNrFhControl()->TraceConnectWithoutContext("UsedAirRbs",
1952 MakeCallback(&ReportAiTrace));
1953 }
1954 }
1955
1956 // REM
1957 Ptr<NrRadioEnvironmentMapHelper> remHelper;
1958
1959 if (dlRem)
1960 {
1961 std::cout << " rem helper\n";
1962 uint16_t remPhyIndex = 0;
1963
1964 NetDeviceContainer remNd;
1965 Ptr<NetDevice> remDevice;
1966
1967 std::vector<NetDeviceContainer*> remNdBySector{gnbNdBySector};
1968 std::vector<NetDeviceContainer*> remDevBySector{ueNdBySector};
1969
1970 uint32_t sectorIndex = 0;
1971 // Reverse order so we get sector 1 for the remSector == 0 case
1972 for (uint32_t sector = sectors; sector > 0; --sector)
1973 {
1974 if (remSector == sector || remSector == 0)
1975 {
1976 sectorIndex = sector - 1;
1977 remNd.Add(*remNdBySector[sectorIndex]);
1978 remDevice = remDevBySector[sectorIndex]->Get(0);
1979 }
1980 }
1981
1982 // Radio Environment Map Generation for ccId 0
1983 remHelper = CreateObject<NrRadioEnvironmentMapHelper>();
1984 remHelper->SetMinX(xMinRem);
1985 remHelper->SetMaxX(xMaxRem);
1986 remHelper->SetResX(xResRem);
1987 remHelper->SetMinY(yMinRem);
1988 remHelper->SetMaxY(yMaxRem);
1989 remHelper->SetResY(yResRem);
1990 remHelper->SetZ(zRem);
1991
1992 // save beamforming vectors, one per site (?)
1993 for (uint32_t sector = sectors; sector > 0; --sector)
1994 {
1995 if ((remSector == sector) || (remSector == 0))
1996 {
1997 sectorIndex = sector - 1;
1998 for (uint32_t siteId = 0; siteId < gnbSites; ++siteId)
1999 {
2000 gnbNdBySector[sectorIndex]
2001 ->Get(siteId)
2002 ->GetObject<NrGnbNetDevice>()
2003 ->GetPhy(remPhyIndex)
2004 ->ChangeBeamformingVector(
2005 DynamicCast<NrUeNetDevice>(ueNdBySector[sectorIndex]->Get(siteId)));
2006 }
2007 }
2008 }
2009
2010 remHelper->CreateRem(remNd, remDevice, remPhyIndex);
2011 }
2012
2013 FlowMonitorHelper flowmonHelper;
2014 NodeContainer endpointNodes;
2015 endpointNodes.Add(remoteHost);
2016 endpointNodes.Add(ueNodes);
2017
2018 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
2019 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.0001));
2020 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
2021 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
2022
2023 Simulator::Stop(simTimeMs);
2024
2025 std::cout << "Run simulation" << std::endl;
2026
2027 Simulator::Run();
2028
2029 // Print per-flow statistics
2030 monitor->CheckForLostPackets();
2031 Ptr<Ipv4FlowClassifier> classifier =
2032 DynamicCast<Ipv4FlowClassifier>(flowmonHelper.GetClassifier());
2033 FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
2034
2035 double averageFlowThroughput = 0.0;
2036 double averageFlowDelay = 0.0;
2037
2038 std::ofstream delayFile;
2039 std::ofstream throughputFile;
2040
2041 std::ostringstream delayFileName;
2042 std::ostringstream throughputFileName;
2043 if (simTag.empty())
2044 {
2045 delayFileName << "XR_Delay"
2046 << "_ar_" << std::to_string(arUeNum).c_str() << "_vr_"
2047 << std::to_string(vrUeNum).c_str() << "_cg_"
2048 << std::to_string(cgUeNum).c_str() << "_voice_"
2049 << std::to_string(voiceUeNum).c_str() << "_" << schedulerType.c_str()
2050 << "_Mx1_" << isMx1 << ".txt";
2051
2052 throughputFileName << "XR_Throughput"
2053 << "_ar_" << std::to_string(arUeNum).c_str() << "_vr_"
2054 << std::to_string(vrUeNum).c_str() << "_cg_"
2055 << std::to_string(cgUeNum).c_str() << "_voice_"
2056 << std::to_string(voiceUeNum).c_str() << "_" << schedulerType.c_str()
2057 << "_Mx1_" << isMx1 << ".txt";
2058 }
2059 else
2060 {
2061 delayFileName << outputDir << "Delay_" << simTag << std::string(".txt").c_str();
2062 throughputFileName << outputDir << "Throughput_" << simTag << std::string(".txt").c_str();
2063 }
2064
2065 if (enableQosTrafficTraces)
2066 {
2067 delayFile.open(delayFileName.str());
2068 delayFile.setf(std::ios_base::fixed);
2069
2070 if (!delayFile.is_open())
2071 {
2072 NS_ABORT_MSG("Can't open file " << delayFileName.str());
2073 }
2074 delayFile << "source_address"
2075 << "\t"
2076 << "source_port"
2077 << "\t"
2078 << "dest_address"
2079 << "\t"
2080 << "dest_port"
2081 << "\t"
2082 << "delay"
2083 << "\n";
2084
2085 throughputFile.open(throughputFileName.str());
2086 throughputFile.setf(std::ios_base::fixed);
2087
2088 if (!throughputFile.is_open())
2089 {
2090 NS_ABORT_MSG("Can't open file " << throughputFileName.str());
2091 }
2092
2093 throughputFile << "source_port"
2094 << "\t"
2095 << "dest_port"
2096 << "\t"
2097 << "Throughput"
2098 << "\t"
2099 << "Delay"
2100 << "\n";
2101 }
2102
2103 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
2104 i != stats.end();
2105 ++i)
2106 {
2107 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
2108
2109 if (enableQosTrafficTraces)
2110 {
2111 for (uint32_t j = 0; j < i->second.delayHistogram.GetNBins(); j++)
2112 {
2113 Histogram h = i->second.delayHistogram;
2114 if (h.GetBinCount(j))
2115 {
2116 for (uint32_t k = 0; k < h.GetBinCount(j); k++)
2117 {
2118 delayFile << t.sourceAddress << "\t" << t.sourcePort << "\t"
2119 << t.destinationAddress << "\t" << t.destinationPort << "\t"
2120 << h.GetBinStart(j) << "\n";
2121 }
2122 }
2123 }
2124 }
2125
2126 std::stringstream protoStream;
2127 protoStream << (uint16_t)t.protocol;
2128 if (t.protocol == 6)
2129 {
2130 protoStream.str("TCP");
2131 }
2132 if (t.protocol == 17)
2133 {
2134 protoStream.str("UDP");
2135 }
2136
2137 const Time& txDuration = appDuration;
2138 std::cout << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
2139 << t.destinationAddress << ":" << t.destinationPort << ") proto "
2140 << protoStream.str() << "\n";
2141 std::cout << " Tx Packets: " << i->second.txPackets << "\n";
2142 std::cout << " Tx Bytes: " << i->second.txBytes << "\n";
2143 std::cout << " TxOffered: "
2144 << ((i->second.txBytes * 8.0) / txDuration.GetSeconds()) * 1e-6 << " Mbps\n";
2145 std::cout << " Rx Bytes: " << i->second.rxBytes << "\n";
2146
2147 if (i->second.rxPackets > 0)
2148 {
2149 // Measure the duration of the flow from receiver's perspective
2150 Time rxDuration = Seconds(0);
2151 if (t.protocol == 6) // tcp
2152 {
2153 rxDuration = appDuration;
2154 }
2155 else if (t.protocol == 17) // udp
2156 {
2157 // rxDuration = i->second.timeLastRxPacket - i->second.timeFirstTxPacket;
2158 rxDuration = appDuration + MilliSeconds(10);
2159 }
2160 else
2161 {
2162 continue;
2163 }
2164
2165 // Time rxDuration = i->second.timeLastRxPacket - i->second.timeFirstRxPacket;
2166 averageFlowThroughput += ((i->second.rxBytes * 8.0) / rxDuration.GetSeconds()) * 1e-6;
2167 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
2168
2169 double throughput = ((i->second.rxBytes * 8.0) / rxDuration.GetSeconds()) * 1e-6;
2170 double delay = 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
2171 double jitter = 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets;
2172
2173 std::cout << " Throughput: " << throughput << " Mbps\n";
2174 std::cout << " Mean delay: " << delay << " ms\n";
2175 std::cout << " Mean jitter: " << jitter << " ms\n";
2176
2177 if (enableQosTrafficTraces)
2178 {
2179 throughputFile << t.sourcePort << "\t" << t.destinationPort << "\t" << throughput
2180 << "\t" << delay << std::endl;
2181 }
2182 }
2183 else
2184 {
2185 std::cout << " Throughput: 0 Mbps\n";
2186 std::cout << " Mean delay: 0 ms\n";
2187 std::cout << " Mean upt: 0 Mbps \n";
2188 std::cout << " Mean jitter: 0 ms\n";
2189
2190 if (enableQosTrafficTraces)
2191 {
2192 throughputFile << t.sourcePort << "\t" << t.destinationPort << "\t" << 0 << "\t"
2193 << 0 << std::endl;
2194 }
2195 }
2196 std::cout << " Rx Packets: " << i->second.rxPackets << "\n";
2197 }
2198
2199 delayFile.close();
2200 throughputFile.close();
2201
2202 std::cout << "\n\n Mean flow throughput: " << averageFlowThroughput / stats.size()
2203 << "Mbps \n";
2204 std::cout << " Mean flow delay: " << averageFlowDelay / stats.size() << " ms\n";
2205
2206 Simulator::Destroy();
2207 return 0;
2208}
2209
2210static void
2211PrintUePosition(NodeContainer ueNodes)
2212{
2213 std::ofstream outUePositionsFile;
2214 std::string filenameUePositions = "uePositions.txt";
2215
2216 outUePositionsFile.open(filenameUePositions.c_str());
2217 outUePositionsFile.setf(std::ios_base::fixed);
2218
2219 if (!outUePositionsFile.is_open())
2220 {
2221 NS_ABORT_MSG("Can't open file " << filenameUePositions);
2222 }
2223
2224 for (uint32_t ueId = 0; ueId < ueNodes.GetN(); ++ueId)
2225 {
2226 Vector uepos = ueNodes.Get(ueId)->GetObject<MobilityModel>()->GetPosition();
2227 outUePositionsFile << "ueId: " << ueId << ", at " << uepos << std::endl;
2228 }
2229
2230 outUePositionsFile.close();
2231}
2232
2233void
2234ConfigureBwpTo(BandwidthPartInfoPtr& bwp, double centerFreq, double bwpBw)
2235{
2236 bwp->m_centralFrequency = centerFreq;
2237 bwp->m_higherFrequency = centerFreq + (bwpBw / 2);
2238 bwp->m_lowerFrequency = centerFreq - (bwpBw / 2);
2239 bwp->m_channelBandwidth = bwpBw;
2240}
2241
2242void
2243ConfigurePhy(Ptr<NrHelper> nrHelper,
2244 Ptr<NetDevice> gnb,
2245 double orientationRads,
2246 uint16_t beamConfSector,
2247 double beamConfElevation)
2248{
2249 // Change the antenna orientation
2250 Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0); // BWP 0
2251 Ptr<UniformPlanarArray> antenna0 = ConstCast<UniformPlanarArray>(
2252 phy0->GetSpectrumPhy()->GetAntenna()->GetObject<UniformPlanarArray>());
2253 antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
2254
2255 // configure the beam that points toward the center of hexagonal
2256 // In case of beamforming, it will be overwritten.
2257 phy0->GetSpectrumPhy()->GetBeamManager()->SetPredefinedBeam(beamConfSector, beamConfElevation);
2258}
2259
2260void
2261ConfigureXrApp(NodeContainer& ueContainer,
2262 uint32_t i,
2263 Ipv4InterfaceContainer& ueIpIface,
2264 enum NrXrConfig config,
2265 uint16_t uePort,
2266 std::string transportProtocol,
2267 NodeContainer& remoteHostContainer,
2268 NetDeviceContainer& ueNetDev,
2269 Ptr<NrHelper> nrHelper,
2270 NrEpsBearer& bearer,
2271 Ptr<NrEpcTft> tft,
2272 bool isMx1,
2273 std::vector<Ptr<NrEpcTft>>& tfts,
2274 ApplicationContainer& serverApps,
2275 ApplicationContainer& clientApps,
2276 ApplicationContainer& pingApps,
2277 std::string direction,
2278 double arDataRate,
2279 uint16_t arFps,
2280 double vrDataRate,
2281 uint16_t vrFps,
2282 double cgDataRate,
2283 Ipv4Address remoteHostAddress,
2284 uint16_t remoteHostPort)
2285{
2286 XrTrafficMixerHelper trafficMixerHelper;
2287 Ipv4Address ipAddress = ueIpIface.GetAddress(i, 0);
2288 trafficMixerHelper.ConfigureXr(config);
2289 auto it = XrPreconfig.find(config);
2290
2291 Ipv4Address address = direction == "UL" ? remoteHostAddress : ipAddress;
2292 uint16_t port = direction == "UL" ? remoteHostPort : uePort;
2293
2294 std::vector<Address> addresses;
2295 std::vector<InetSocketAddress> localAddresses;
2296
2297 for (size_t j = 0; j < it->second.size(); j++)
2298 {
2299 addresses.push_back(InetSocketAddress(address, port + j));
2300 // The sink will always listen to the specified ports
2301 localAddresses.emplace_back(Ipv4Address::GetAny(), port + j);
2302 }
2303
2304 ApplicationContainer currentUeClientApps;
2305
2306 // Seed the ARP cache by pinging early in the simulation
2307 // This is a workaround until a static ARP capability is provided
2308 PingHelper ping(address);
2309
2310 if (direction == "UL")
2311 {
2312 pingApps.Add(ping.Install(ueContainer.Get(i)));
2313 currentUeClientApps.Add(
2314 trafficMixerHelper.Install(transportProtocol, addresses, ueContainer.Get(i)));
2315 }
2316 else
2317 {
2318 pingApps.Add(ping.Install(remoteHostContainer));
2319 currentUeClientApps.Add(
2320 trafficMixerHelper.Install(transportProtocol, addresses, remoteHostContainer.Get(0)));
2321 }
2322
2323 Ptr<NetDevice> ueDevice = ueNetDev.Get(i);
2324
2325 // Activate a dedicated bearer for the traffic type per node
2326 nrHelper->ActivateDedicatedEpsBearer(ueDevice, bearer, tft);
2327
2328 // Activate a dedicated bearer for the traffic type per node
2329 if (isMx1)
2330 {
2331 nrHelper->ActivateDedicatedEpsBearer(ueDevice, bearer, tft);
2332 }
2333 else
2334 {
2335 NS_ASSERT(tfts.size() >= currentUeClientApps.GetN());
2336 for (uint32_t j = 0; j < currentUeClientApps.GetN(); j++)
2337 {
2338 nrHelper->ActivateDedicatedEpsBearer(ueDevice, bearer, tfts[j]);
2339 }
2340 }
2341
2342 for (uint32_t j = 0; j < currentUeClientApps.GetN(); j++)
2343 {
2344 PacketSinkHelper dlPacketSinkHelper(transportProtocol, localAddresses.at(j));
2345 Ptr<Application> packetSink;
2346 if (direction == "UL")
2347 {
2348 packetSink = dlPacketSinkHelper.Install(remoteHostContainer.Get(0)).Get(0);
2349 }
2350 else
2351 {
2352 packetSink = dlPacketSinkHelper.Install(ueContainer.Get(i)).Get(0);
2353 }
2354
2355 serverApps.Add(packetSink);
2356
2357 Ptr<TrafficGenerator3gppGenericVideo> app =
2358 DynamicCast<TrafficGenerator3gppGenericVideo>(currentUeClientApps.Get(j));
2359 if (app && config == NrXrConfig::AR_M3)
2360 {
2361 app->SetAttribute("DataRate", DoubleValue(arDataRate));
2362 app->SetAttribute("Fps", UintegerValue(arFps));
2363 }
2364 else if (app && config == NrXrConfig::VR_DL1)
2365 {
2366 app->SetAttribute("DataRate", DoubleValue(vrDataRate));
2367 app->SetAttribute("Fps", UintegerValue(vrFps));
2368 }
2369 else if (app && config == NrXrConfig::CG_DL1)
2370 {
2371 app->SetAttribute("DataRate", DoubleValue(cgDataRate));
2372 }
2373 }
2374 clientApps.Add(currentUeClientApps);
2375}
2376
2377void
2378ConfigureVoiceApp(VoiceApplicationSettings& voiceAppSettings)
2379{
2380 Ipv4Address ipAddress = voiceAppSettings.ueIp;
2381 Ipv4Address address =
2382 voiceAppSettings.direction == "UL" ? voiceAppSettings.remoteHostAddress : ipAddress;
2383 uint16_t port = voiceAppSettings.direction == "UL" ? voiceAppSettings.remoteHostPort
2384 : voiceAppSettings.uePort;
2385
2386 TrafficGeneratorHelper trafficGeneratorHelper(voiceAppSettings.transportProtocol,
2387 InetSocketAddress(address, port),
2389
2390 // Seed the ARP cache by pinging early in the simulation
2391 // This is a workaround until a static ARP capability is provided
2392 PingHelper ping(ipAddress);
2393
2394 if (voiceAppSettings.direction == "UL")
2395 {
2396 voiceAppSettings.clientApps.Add(trafficGeneratorHelper.Install(voiceAppSettings.ue).Get(0));
2397 voiceAppSettings.pingApps.Add(ping.Install(voiceAppSettings.ue));
2398 }
2399 else
2400 {
2401 voiceAppSettings.clientApps.Add(
2402 trafficGeneratorHelper.Install(voiceAppSettings.remoteHost));
2403 voiceAppSettings.pingApps.Add(ping.Install(voiceAppSettings.remoteHost));
2404 }
2405
2406 Ptr<NetDevice> ueDevice = voiceAppSettings.ueNetDev;
2407 // Activate a dedicated bearer for the traffic type per node
2408 voiceAppSettings.nrHelper->ActivateDedicatedEpsBearer(ueDevice,
2409 voiceAppSettings.bearer,
2410 voiceAppSettings.tft);
2411
2412 InetSocketAddress localAddress(Ipv4Address::GetAny(), port);
2413 PacketSinkHelper dlPacketSinkHelper(voiceAppSettings.transportProtocol, localAddress);
2414 Ptr<Application> packetSink;
2415 if (voiceAppSettings.direction == "UL")
2416 {
2417 packetSink = dlPacketSinkHelper.Install(voiceAppSettings.remoteHost).Get(0);
2418 }
2419 else
2420 {
2421 packetSink = dlPacketSinkHelper.Install(voiceAppSettings.ue).Get(0);
2422 }
2423
2424 voiceAppSettings.serverApps.Add(packetSink);
2425}
2426
2427void
2428ReportFhTrace(const SfnSf& sfn, uint16_t physCellId, uint16_t bwpId, uint64_t reqFh)
2429{
2430 if (!m_fhTraceFile.is_open())
2431 {
2432 std::stringstream fileName;
2433 fileName << m_outputDir << "fh-trace_" << m_fhControlMethod.c_str() << "_"
2434 << std::to_string(m_fhCapacity) << ".txt";
2435 m_fhTraceFileName = fileName.str();
2436 m_fhTraceFile.open(m_fhTraceFileName.c_str());
2437
2438 if (!m_fhTraceFile.is_open())
2439 {
2440 NS_FATAL_ERROR("Could not open FH tracefile");
2441 }
2442
2443 m_fhTraceFile << "CellId"
2444 << "\t"
2445 << "BwpId"
2446 << "\t"
2447 << "FhThroughput"
2448 << "\n";
2449 }
2450 m_fhTraceFile << physCellId << "\t" << bwpId << "\t" << reqFh << std::endl;
2451}
2452
2453void
2454ReportAiTrace(const SfnSf& sfn, uint16_t physCellId, uint16_t bwpId, uint32_t airRbs)
2455{
2456 if (!m_aiTraceFile.is_open())
2457 {
2458 std::stringstream fileName;
2459 fileName << m_outputDir << "air-trace_" << m_fhControlMethod.c_str() << "_"
2460 << std::to_string(m_fhCapacity) << ".txt";
2461 m_aiTraceFileName = fileName.str();
2462 m_aiTraceFile.open(m_aiTraceFileName.c_str());
2463
2464 if (!m_aiTraceFile.is_open())
2465 {
2466 NS_FATAL_ERROR("Could not open Air tracefile");
2467 }
2468 }
2469 m_aiTraceFile << physCellId << "\t" << bwpId << "\t" << airRbs << std::endl;
2470}
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 HexagonalGridScenarioHelper class.
void SetNumRings(uint8_t numRings)
Sets the number of outer rings of sites around the central site.
void CreateScenarioWithMobility(const Vector &speed, double percentage)
This function can be used to create a scenario with UEs with mobility and define a percentage of UEs,...
Represents a scenario with base stations and user terminals.
const NodeContainer & GetUserTerminals() const
Get the list of user nodes.
std::size_t GetNumSites() const
Gets the number of sites with cell 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.
double GetAntennaOrientationRadians(std::size_t cellId) const
Returns the orientation in radians of the antenna array for the given cellId.
@ ErrorModel
Error Model version (can use different error models, see NrErrorModel)
Definition nr-amc.h:81
@ INIT_PROPAGATION
Initialize the propagation loss model.
@ INIT_FADING
Initialize the fading model.
This class contains the specification of EPS Bearers.
@ NGBR_LOW_LAT_EMBB
Non-GBR Low Latency eMBB applications.
@ GBR_CONV_VOICE
GBR Conversational Voice.
@ DGBR_INTER_SERV_87
Delay-Critical GBR Interactive Service - Motion tracking data (TS 23.501)
The NrGnbNetDevice class.
Basic simulation scenario parameters.
double m_isd
Inter-site distance (ISD) in meters.
double m_bsHeight
Height of gNB nodes.
void SetSectorization(SiteSectorizationType numSectors)
Sets the number of sectors of every site.
double m_minBsUtDistance
Minimum distance between BS and UT in meters.
void SetScenarioParameters(const std::string &scenario)
Sets parameters to the specified scenario.
double m_utHeight
Height of UE nodes.
double m_antennaOffset
Cell antenna offset in meters w.r.t. site location.
The SfnSf class.
Definition sfnsf.h:32
A helper to make it easier to instantiate an ns3::TrafficGenerator types of applications on a set of ...
static TypeId GetTypeId()
Get the type ID.
std::unique_ptr< BandwidthPartInfo > BandwidthPartInfoPtr
unique_ptr of BandwidthPartInfo
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
Direction direction
Whether the filter needs to be applied to uplink / downlink only, or in both cases.
Definition nr-epc-tft.h:104
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
parameters for the search of optimal rank and precoding matrix indicator (RI, PMI)
Definition nr-helper.h:868
uint8_t subbandSize
Number of PRBs per subband for downsampling.
Definition nr-helper.h:876
std::string fullSearchCb
Codebook when using full-search algorithm.
Definition nr-helper.h:870
std::string pmSearchMethod
Precoding matrix search algorithm.
Definition nr-helper.h:869
Operation band information structure.
BandwidthPartInfoPtr & GetBwpAt(uint32_t ccId, uint32_t bwpId) const
Get the BWP at the cc/bwp specified.
std::vector< ComponentCarrierInfoPtr > m_cc
Operation band component carriers.
BandwidthPartInfoPtrVector GetBwps() const
Get the list of all the BWPs to pass to NrHelper.
uint8_t m_bandId
Operation band id.