5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-lte-ca-demo.cc
Go to the documentation of this file.
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
33#include "ns3/antenna-module.h"
34#include "ns3/applications-module.h"
35#include "ns3/bandwidth-part-gnb.h"
36#include "ns3/config-store-module.h"
37#include "ns3/config-store.h"
38#include "ns3/core-module.h"
39#include "ns3/flow-monitor-module.h"
40#include "ns3/internet-apps-module.h"
41#include "ns3/internet-module.h"
42#include "ns3/ipv4-global-routing-helper.h"
43#include "ns3/log.h"
44#include "ns3/mobility-module.h"
45#include "ns3/nr-helper.h"
46#include "ns3/nr-module.h"
47#include "ns3/nr-point-to-point-epc-helper.h"
48#include "ns3/point-to-point-helper.h"
49
50using namespace ns3;
51
52NS_LOG_COMPONENT_DEFINE("3gppChannelFdmNrComponentCarriersExample");
53
54int
55main(int argc, char* argv[])
56{
57 uint16_t gNbNum = 1;
58 uint16_t ueNumPergNb = 1;
59
60 uint8_t numBands = 2;
61 double centralFrequencyBand40 = 2350e6;
62 double bandwidthBand40 = 50e6;
63 double centralFrequencyBand38 = 2595e6;
64 double bandwidthBand38 = 100e6;
65
66 double bandwidth = 20e6;
67
68 uint16_t numerologyBwp0 = 0;
69 uint16_t numerologyBwp1 = 0;
70 uint16_t numerologyBwp2 = 0;
71 uint16_t numerologyBwpDl = 0;
72 uint16_t numerologyBwpUl = 0;
73
74 double totalTxPower = 13;
75 std::string pattern =
76 "DL|S|UL|UL|DL|DL|S|UL|UL|DL|"; // Pattern can be e.g. "DL|S|UL|UL|DL|DL|S|UL|UL|DL|"
77 std::string patternDL = "DL|DL|DL|DL|DL|DL|DL|DL|DL|DL|";
78 std::string patternUL = "UL|UL|UL|UL|UL|UL|UL|UL|UL|UL|";
79 std::string operationMode = "TDD"; // TDD or FDD (mixed TDD and FDD mode)
80
81 bool cellScan = false;
82 double beamSearchAngleStep = 10.0;
83
84 uint32_t udpPacketSizeUll = 915;
85 uint32_t udpPacketSizeBe = 915;
86 uint32_t lambdaUll = 10000;
87 uint32_t lambdaBe = 10000;
88
89 bool enableLowLat = true;
90 bool enableVideo = true;
91 bool enableVoice = true;
92 bool enableGaming = false; // If FDD is selected is set automatically to true
93
94 bool logging = false;
95
96 std::string simTag = "default";
97 std::string outputDir = "./";
98
99 double simTime = 1.4; // seconds
100 double udpAppStartTime = 0.4; // seconds
101
102 CommandLine cmd(__FILE__);
103
104 cmd.AddValue("simTime", "Simulation time", simTime);
105 cmd.AddValue("gNbNum", "The number of gNbs in multiple-ue topology", gNbNum);
106 cmd.AddValue("ueNumPergNb", "The number of UE per gNb in multiple-ue topology", ueNumPergNb);
107 cmd.AddValue("numBands",
108 "Number of operation bands. More than one implies non-contiguous CC",
109 numBands);
110 cmd.AddValue("bandwidthBand40", "The system bandwidth to be used in band 1", bandwidthBand40);
111 cmd.AddValue("bandwidthBand38", "The system bandwidth to be used in band 2", bandwidthBand38);
112 cmd.AddValue("bandwidth", "The bandwidth of the CCs ", bandwidth);
113 cmd.AddValue("numerologyBwp0", "The numerology to be used in bandwidth part 1", numerologyBwp0);
114 cmd.AddValue("numerologyBwp1", "The numerology to be used in bandwidth part 1", numerologyBwp1);
115 cmd.AddValue("numerologyBwp2", "The numerology to be used in bandwidth part 2", numerologyBwp2);
116 cmd.AddValue("numerologyBwpDl",
117 "The numerology to be used in bandwidth part 2",
118 numerologyBwpDl);
119 cmd.AddValue("numerologyBwpUl",
120 "The numerology to be used in bandwidth part 2",
121 numerologyBwpUl);
122 cmd.AddValue("totalTxPower",
123 "total tx power that will be proportionally assigned to"
124 " bandwidth parts depending on each BWP bandwidth ",
125 totalTxPower);
126 cmd.AddValue("tddPattern",
127 "LTE TDD pattern to use (e.g. --tddPattern=DL|S|UL|UL|UL|DL|S|UL|UL|UL|)",
128 pattern);
129 cmd.AddValue("operationMode",
130 "The network operation mode can be TDD or FDD (In this case it"
131 "will be mixed TDD and FDD)",
132 operationMode);
133 cmd.AddValue("cellScan",
134 "Use beam search method to determine beamforming vector,"
135 "true to use cell scanning method",
136 cellScan);
137 cmd.AddValue("beamSearchAngleStep",
138 "Beam search angle step for beam search method",
139 beamSearchAngleStep);
140 cmd.AddValue("packetSizeUll",
141 "packet size in bytes to be used by ultra low latency traffic",
142 udpPacketSizeUll);
143 cmd.AddValue("packetSizeBe",
144 "packet size in bytes to be used by best effort traffic",
145 udpPacketSizeBe);
146 cmd.AddValue("lambdaUll",
147 "Number of UDP packets in one second for ultra low latency traffic",
148 lambdaUll);
149 cmd.AddValue("lambdaBe",
150 "Number of UDP packets in one second for best effort traffic",
151 lambdaBe);
152 cmd.AddValue("enableLowLat",
153 "If true, enables low latency traffic transmission (DL)",
154 enableLowLat);
155 cmd.AddValue("enableVideo", "If true, enables video traffic transmission (DL)", enableVideo);
156 cmd.AddValue("enableVoice", "If true, enables voice traffic transmission (UL)", enableVoice);
157 cmd.AddValue("enableGaming", "If true, enables gaming traffic transmission (UL)", enableGaming);
158 cmd.AddValue("logging", "Enable logging", logging);
159 cmd.AddValue("simTag",
160 "tag to be appended to output filenames to distinguish simulation campaigns",
161 simTag);
162 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
163
164 cmd.Parse(argc, argv);
165
166 NS_ABORT_IF(numBands < 1);
167 NS_ABORT_MSG_IF(enableLowLat == false && enableVideo == false && enableVoice == false &&
168 enableGaming == false && operationMode == "TDD",
169 "For TDD enable one of the flows");
170
171 // ConfigStore inputConfig;
172 // inputConfig.ConfigureDefaults ();
173
174 // enable logging or not
175 if (logging)
176 {
177 // LogComponentEnable ("Nr3gppPropagationLossModel", LOG_LEVEL_ALL);
178 // LogComponentEnable ("Nr3gppBuildingsPropagationLossModel", LOG_LEVEL_ALL);
179 // LogComponentEnable ("Nr3gppChannel", LOG_LEVEL_ALL);
180 // LogComponentEnable ("UdpClient", LOG_LEVEL_INFO);
181 // LogComponentEnable ("UdpServer", LOG_LEVEL_INFO);
182 // LogComponentEnable ("NrPdcp", LOG_LEVEL_INFO);
183 // LogComponentEnable ("BwpManagerGnb", LOG_LEVEL_INFO);
184 // LogComponentEnable ("BwpManagerAlgorithm", LOG_LEVEL_INFO);
185 LogComponentEnable("NrGnbPhy", LOG_LEVEL_INFO);
186 LogComponentEnable("NrUePhy", LOG_LEVEL_INFO);
187 // LogComponentEnable ("NrGnbMac", LOG_LEVEL_INFO);
188 // LogComponentEnable ("NrUeMac", LOG_LEVEL_INFO);
189 }
190
191 // create base stations and mobile terminals
192 NodeContainer gNbNodes;
193 NodeContainer ueNodes;
194 MobilityHelper mobility;
195
196 double gNbHeight = 10;
197 double ueHeight = 1.5;
198
199 gNbNodes.Create(gNbNum);
200 ueNodes.Create(ueNumPergNb * gNbNum);
201
202 Ptr<ListPositionAllocator> apPositionAlloc = CreateObject<ListPositionAllocator>();
203 Ptr<ListPositionAllocator> staPositionAlloc = CreateObject<ListPositionAllocator>();
204 int32_t yValue = 0.0;
205
206 for (uint32_t i = 1; i <= gNbNodes.GetN(); ++i)
207 {
208 // 2.0, -2.0, 6.0, -6.0, 10.0, -10.0, ....
209 if (i % 2 != 0)
210 {
211 yValue = static_cast<int>(i) * 30;
212 }
213 else
214 {
215 yValue = -yValue;
216 }
217
218 apPositionAlloc->Add(Vector(0.0, yValue, gNbHeight));
219
220 // 1.0, -1.0, 3.0, -3.0, 5.0, -5.0, ...
221 double xValue = 0.0;
222 for (uint32_t j = 1; j <= ueNumPergNb; ++j)
223 {
224 if (j % 2 != 0)
225 {
226 xValue = j;
227 }
228 else
229 {
230 xValue = -xValue;
231 }
232
233 if (yValue > 0)
234 {
235 staPositionAlloc->Add(Vector(xValue, 10, ueHeight));
236 }
237 else
238 {
239 staPositionAlloc->Add(Vector(xValue, -10, ueHeight));
240 }
241 }
242 }
243
244 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
245 mobility.SetPositionAllocator(apPositionAlloc);
246 mobility.Install(gNbNodes);
247
248 mobility.SetPositionAllocator(staPositionAlloc);
249 mobility.Install(ueNodes);
250
251 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
252 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
253 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
254 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
255 nrHelper->SetEpcHelper(nrEpcHelper);
256 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
257 if (cellScan)
258 {
259 idealBeamformingHelper->SetAttribute("BeamformingMethod",
260 TypeIdValue(CellScanBeamforming::GetTypeId()));
261 idealBeamformingHelper->SetBeamformingAlgorithmAttribute("BeamSearchAngleStep",
262 DoubleValue(beamSearchAngleStep));
263 }
264 else
265 {
266 idealBeamformingHelper->SetAttribute(
267 "BeamformingMethod",
269 }
270 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
271
272 std::string errorModel = "ns3::NrLteMiErrorModel";
273 // Scheduler
274 nrHelper->SetSchedulerAttribute("FixedMcsDl", BooleanValue(false));
275 nrHelper->SetSchedulerAttribute("FixedMcsUl", BooleanValue(false));
276
277 // Error Model: UE and GNB with same spectrum error model.
278 nrHelper->SetUlErrorModel(errorModel);
279 nrHelper->SetDlErrorModel(errorModel);
280
281 // Both DL and UL AMC will have the same model behind.
282 nrHelper->SetGnbDlAmcAttribute(
283 "AmcModel",
284 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
285 nrHelper->SetGnbUlAmcAttribute(
286 "AmcModel",
287 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
288
289 /*
290 * Adjust the average number of Reference symbols per RB only for LTE case,
291 * which is larger than in NR. We assume a value of 4 (could be 3 too).
292 */
293 nrHelper->SetGnbDlAmcAttribute("NumRefScPerRb", UintegerValue(2));
294 nrHelper->SetGnbUlAmcAttribute("NumRefScPerRb", UintegerValue(2));
295 nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(4));
296 nrHelper->SetSchedulerAttribute("DlCtrlSymbols", UintegerValue(1));
297 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaPF"));
298
299 /*
300 * Setup the operation bands.
301 * In this example, two standard operation bands are deployed:
302 *
303 * Band 38 that has a component carrier (CC) of 20 MHz
304 * Band 40 that has two non-contiguous CCs of 20 MHz each.
305 *
306 * If TDD mode is defined, 1 BWP per CC is created. All BWPs are TDD.
307 * If FDD mode is defined, Band 40 CC2 contains 2 BWPs (1 DL - 1 UL), while
308 * Band 40 CC1 has one TDD BWP and Band 38 CC0 also has one TDD BWP.
309 *
310 * This example manually creates a non-contiguous CC configuration with 2 CCs.
311 * First CC has two BWPs and the second only one.
312 *
313 * The configured spectrum division for TDD mode is:
314 * |--------- Band 40 --------| |--------------- Band 38 ---------------|
315 * |---------- CC0 -----------| |-------- CC1-------||------- CC2-------|
316 * |---------- BWP0 ----------| |------- BWP1 ------||------ BWP2 ------|
317 *
318 * The configured spectrum division for FDD mode is:
319 * |-------- Band 40 ---------| |----------------- Band 38 ----------------|
320 * |---------- CC0 -----------| |------- CC1-------| |-------- CC2--------|
321 * |---------- BWP0 ----------| |------ BWP1 ------| |- BWP2DL -|- BWP2UL-|
322 *
323 *
324 * In this example, each UE generates as many flows as the number of bwps
325 * (i.e. 3 flows in case of TDD mode and 4 in case mixed TDD with FDD).
326 * Each flow will be transmitted on a dedicated BWP. In particular, low
327 * latency flow is set as DL and goes through BWP0, voice is set as UL and
328 * goes through BWP1, video is set as DL and goes through BWP2DL, and gaming
329 * is enabled only in the mixed TDD/FDD mode, it is set as UL and goes
330 * through BWP2UL.
331 */
332 uint8_t numCcs = 3;
333
335
336 // Create the configuration for band40 (CC0 - BWP0)
337 OperationBandInfo band40;
338 band40.m_centralFrequency = centralFrequencyBand40;
339 band40.m_channelBandwidth = bandwidthBand40;
340 band40.m_lowerFrequency = band40.m_centralFrequency - band40.m_channelBandwidth / 2;
341 band40.m_higherFrequency = band40.m_centralFrequency + band40.m_channelBandwidth / 2;
342
343 // Component Carrier 0
344 std::unique_ptr<ComponentCarrierInfo> cc0(new ComponentCarrierInfo());
345 cc0->m_ccId = 0;
346 cc0->m_centralFrequency = band40.m_lowerFrequency + bandwidth;
347 cc0->m_channelBandwidth = bandwidth;
348 cc0->m_lowerFrequency = cc0->m_centralFrequency - cc0->m_channelBandwidth / 2;
349 cc0->m_higherFrequency = cc0->m_centralFrequency + cc0->m_channelBandwidth / 2;
350
351 // BWP 0
352 std::unique_ptr<BandwidthPartInfo> bwp0(new BandwidthPartInfo());
353 bwp0->m_bwpId = 0;
354 bwp0->m_centralFrequency = cc0->m_centralFrequency;
355 bwp0->m_channelBandwidth = cc0->m_channelBandwidth;
356 bwp0->m_lowerFrequency = cc0->m_lowerFrequency;
357 bwp0->m_higherFrequency = cc0->m_higherFrequency;
358
359 cc0->AddBwp(std::move(bwp0));
360
361 band40.AddCc(std::move(cc0));
362
363 // Create the configuration for band38
364 OperationBandInfo band38;
365 band38.m_centralFrequency = centralFrequencyBand38;
366 band38.m_channelBandwidth = bandwidthBand38;
367 band38.m_lowerFrequency = band38.m_centralFrequency - band38.m_channelBandwidth / 2;
368 band38.m_higherFrequency = band38.m_centralFrequency + band38.m_channelBandwidth / 2;
369
370 //(CC1 - BWP1)
371 // Component Carrier 1
372 std::unique_ptr<ComponentCarrierInfo> cc1(new ComponentCarrierInfo());
373 cc1->m_ccId = 1;
374 cc1->m_centralFrequency = band38.m_lowerFrequency + bandwidth;
375 cc1->m_channelBandwidth = bandwidth;
376 cc1->m_lowerFrequency = cc1->m_centralFrequency - cc1->m_channelBandwidth / 2;
377 cc1->m_higherFrequency = cc1->m_centralFrequency + cc1->m_channelBandwidth / 2;
378
379 // BWP 1
380 std::unique_ptr<BandwidthPartInfo> bwp1(new BandwidthPartInfo());
381 bwp1->m_bwpId = 1;
382 bwp1->m_centralFrequency = cc1->m_centralFrequency;
383 bwp1->m_channelBandwidth = cc1->m_channelBandwidth;
384 bwp1->m_lowerFrequency = cc1->m_lowerFrequency;
385 bwp1->m_higherFrequency = cc1->m_higherFrequency;
386
387 cc1->AddBwp(std::move(bwp1));
388
389 std::unique_ptr<ComponentCarrierInfo> cc2(new ComponentCarrierInfo());
390 std::unique_ptr<BandwidthPartInfo> bwp2(new BandwidthPartInfo());
391 std::unique_ptr<BandwidthPartInfo> bwpdl(new BandwidthPartInfo());
392 std::unique_ptr<BandwidthPartInfo> bwpul(new BandwidthPartInfo());
393
394 // Component Carrier 2
395 cc2->m_ccId = 2;
396 cc2->m_centralFrequency = band38.m_higherFrequency - bandwidth;
397 cc2->m_channelBandwidth = bandwidth;
398 cc2->m_lowerFrequency = cc2->m_centralFrequency - cc2->m_channelBandwidth / 2;
399 cc2->m_higherFrequency = cc2->m_centralFrequency + cc2->m_channelBandwidth / 2;
400
401 if (operationMode == "TDD") //(CC2 - BWP2)
402 {
403 bwp2->m_bwpId = 1;
404 bwp2->m_centralFrequency = cc2->m_centralFrequency;
405 bwp2->m_channelBandwidth = cc2->m_channelBandwidth;
406 bwp2->m_lowerFrequency = cc2->m_lowerFrequency;
407 bwp2->m_higherFrequency = cc2->m_higherFrequency;
408
409 cc2->AddBwp(std::move(bwp2));
410 }
411 else // FDD case (CC2 - BWPdl & BWPul)
412 {
413 // BWP DL
414 bwpdl->m_bwpId = 2;
415 bwpdl->m_channelBandwidth = cc2->m_channelBandwidth / 2;
416 bwpdl->m_lowerFrequency = cc2->m_lowerFrequency;
417 bwpdl->m_higherFrequency = bwpdl->m_lowerFrequency + bwpdl->m_channelBandwidth;
418 bwpdl->m_centralFrequency = bwpdl->m_lowerFrequency + bwpdl->m_channelBandwidth / 2;
419
420 cc2->AddBwp(std::move(bwpdl));
421
422 // BWP UL
423 bwpul->m_bwpId = 3;
424 bwpul->m_channelBandwidth = cc2->m_channelBandwidth / 2;
425 bwpul->m_lowerFrequency = cc2->m_centralFrequency;
426 bwpul->m_higherFrequency = cc2->m_higherFrequency;
427 bwpul->m_centralFrequency = bwpul->m_lowerFrequency + bwpul->m_channelBandwidth / 2;
428
429 cc2->AddBwp(std::move(bwpul));
430 Config::SetDefault("ns3::NrUeNetDevice::PrimaryUlIndex", UintegerValue(1));
431 }
432
433 band38.AddCc(std::move(cc1));
434 band38.AddCc(std::move(cc2));
435 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
436 // use the default spectrum channel {RMa, Default, ThreeGpp}
437 channelHelper->ConfigureFactories("RMa", "Default", "ThreeGpp");
438 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
439 channelHelper->AssignChannelsToBands({band40, band38});
440 allBwps = CcBwpCreator::GetAllBwps({band38, band40});
441
442 // Antennas for all the UEs
443 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(1));
444 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(1));
445 nrHelper->SetUeAntennaAttribute("AntennaElement",
446 PointerValue(CreateObject<IsotropicAntennaModel>()));
447
448 // Antennas for all the gNbs
449 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(2));
450 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(2));
451 nrHelper->SetGnbAntennaAttribute("AntennaElement",
452 PointerValue(CreateObject<IsotropicAntennaModel>()));
453
454 // Assign each flow type to a BWP
455 uint32_t bwpIdForLowLat = 0;
456 uint32_t bwpIdForVoice = 1;
457 uint32_t bwpIdForVideo = 2;
458 uint32_t bwpIdForVideoGaming = 3;
459
460 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB",
461 UintegerValue(bwpIdForLowLat));
462 nrHelper->SetGnbBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
463 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_PREMIUM",
464 UintegerValue(bwpIdForVideo));
465 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_VOICE_VIDEO_GAMING",
466 UintegerValue(bwpIdForVideoGaming));
467
468 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdForLowLat));
469 nrHelper->SetUeBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
470 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_PREMIUM",
471 UintegerValue(bwpIdForVideo));
472 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_VOICE_VIDEO_GAMING",
473 UintegerValue(bwpIdForVideoGaming));
474
475 // install nr net devices
476 NetDeviceContainer gnbNetDev = nrHelper->InstallGnbDevice(gNbNodes, allBwps);
477 NetDeviceContainer ueNetDev = nrHelper->InstallUeDevice(ueNodes, allBwps);
478
479 int64_t randomStream = 1;
480 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
481 randomStream += nrHelper->AssignStreams(ueNetDev, randomStream);
482
483 // Share the total transmission power among CCs proportionally with the BW
484 double x = pow(10, totalTxPower / 10);
485 double totalBandwidth = numCcs * bandwidth;
486
487 // Band40: CC0 - BWP0 & Band38: CC1 - BWP1
488 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)
489 ->SetAttribute("Numerology", UintegerValue(numerologyBwp0));
490 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)
491 ->SetAttribute(
492 "TxPower",
493 DoubleValue(10 *
494 log10((band40.GetBwpAt(0, 0)->m_channelBandwidth / totalBandwidth) * x)));
495 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("Pattern", StringValue(pattern));
496 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("RbOverhead", DoubleValue(0.1));
497
498 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)
499 ->SetAttribute("Numerology", UintegerValue(numerologyBwp1));
500 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)
501 ->SetAttribute(
502 "TxPower",
503 DoubleValue(10 *
504 log10((band38.GetBwpAt(0, 0)->m_channelBandwidth / totalBandwidth) * x)));
505 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)->SetAttribute("Pattern", StringValue(pattern));
506 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)->SetAttribute("RbOverhead", DoubleValue(0.1));
507
508 // Band38: CC2 - BWP2
509 if (operationMode == "TDD")
510 {
511 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
512 ->SetAttribute("Numerology", UintegerValue(numerologyBwp2));
513 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
514 ->SetAttribute(
515 "TxPower",
516 DoubleValue(
517 10 * log10((band38.GetBwpAt(1, 0)->m_channelBandwidth / totalBandwidth) * x)));
518 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("Pattern", StringValue(pattern));
519 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("RbOverhead", DoubleValue(0.1));
520 }
521 else // FDD case
522 {
523 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
524 ->SetAttribute("Numerology", UintegerValue(numerologyBwpDl));
525 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
526 ->SetAttribute(
527 "TxPower",
528 DoubleValue(
529 10 * log10((band38.GetBwpAt(1, 0)->m_channelBandwidth / totalBandwidth) * x)));
530 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("Pattern", StringValue(patternDL));
531 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("RbOverhead", DoubleValue(0.1));
532
533 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 3)
534 ->SetAttribute("Numerology", UintegerValue(numerologyBwpUl));
535 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 3)->SetAttribute("Pattern", StringValue(patternUL));
536 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 3)->SetAttribute("RbOverhead", DoubleValue(0.1));
537
538 // Link the two FDD BWP:
539 nrHelper->GetBwpManagerGnb(gnbNetDev.Get(0))->SetOutputLink(3, 2);
540
541 // Set the UE routing:
542 for (uint32_t i = 0; i < ueNetDev.GetN(); i++)
543 {
544 nrHelper->GetBwpManagerUe(ueNetDev.Get(i))->SetOutputLink(2, 3);
545 }
546
547 // enable 4rth flow
548 enableGaming = true;
549 }
550
551 // create the internet and install the IP stack on the UEs
552 // get SGW/PGW and create a single RemoteHost
553 auto [remoteHost, remoteHostIpv4Address] =
554 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
555
556 InternetStackHelper internet;
557
558 internet.Install(ueNodes);
559 Ipv4InterfaceContainer ueIpIface;
560 ueIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDev));
561
562 // attach UEs to the closest gNB
563 nrHelper->AttachToClosestGnb(ueNetDev, gnbNetDev);
564
565 // install UDP applications
566 uint16_t dlPortLowLat = 1234;
567 uint16_t ulPortVoice = 1235;
568 uint16_t dlPortVideo = 1236;
569 uint16_t ulPortGaming = 1237;
570
571 ApplicationContainer serverApps;
572
573 // The sink will always listen to the specified ports
574 UdpServerHelper dlPacketSinkLowLat(dlPortLowLat);
575 UdpServerHelper ulPacketSinkVoice(ulPortVoice);
576 UdpServerHelper dlPacketSinkVideo(dlPortVideo);
577 UdpServerHelper ulPacketSinkGaming(ulPortGaming);
578
579 // The server, that is the application which is listening, is installed in the UE
580 // for the DL traffic, and in the remote host for the UL traffic
581 serverApps.Add(dlPacketSinkLowLat.Install(ueNodes));
582 serverApps.Add(ulPacketSinkVoice.Install(remoteHost));
583 serverApps.Add(dlPacketSinkVideo.Install(ueNodes));
584 serverApps.Add(ulPacketSinkGaming.Install(remoteHost));
585
586 /*
587 * Configure attributes for the different generators, using user-provided
588 * parameters for generating a CBR traffic
589 *
590 * Low-Latency configuration and object creation:
591 */
592 UdpClientHelper dlClientLowLat;
593 dlClientLowLat.SetAttribute("RemotePort", UintegerValue(dlPortLowLat));
594 dlClientLowLat.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
595 dlClientLowLat.SetAttribute("PacketSize", UintegerValue(udpPacketSizeBe));
596 dlClientLowLat.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaBe)));
597
598 // The bearer that will carry low latency traffic
600
601 // The filter for the low-latency traffic
602 Ptr<NrEpcTft> lowLatTft = Create<NrEpcTft>();
603 NrEpcTft::PacketFilter dlpfLowLat;
604 dlpfLowLat.localPortStart = dlPortLowLat;
605 dlpfLowLat.localPortEnd = dlPortLowLat;
606 lowLatTft->Add(dlpfLowLat);
607
608 // Voice configuration and object creation:
609 UdpClientHelper ulClientVoice;
610 ulClientVoice.SetAttribute("RemotePort", UintegerValue(ulPortVoice));
611 ulClientVoice.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
612 ulClientVoice.SetAttribute("PacketSize", UintegerValue(udpPacketSizeBe));
613 ulClientVoice.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaBe)));
614
615 // The bearer that will carry voice traffic
617
618 // The filter for the voice traffic
619 Ptr<NrEpcTft> voiceTft = Create<NrEpcTft>();
620 NrEpcTft::PacketFilter ulpfVoice;
621 ulpfVoice.localPortStart = ulPortVoice;
622 ulpfVoice.localPortEnd = ulPortVoice;
623 ulpfVoice.direction = NrEpcTft::UPLINK;
624 voiceTft->Add(ulpfVoice);
625
626 // Video configuration and object creation:
627 UdpClientHelper dlClientVideo;
628 dlClientVideo.SetAttribute("RemotePort", UintegerValue(dlPortVideo));
629 dlClientVideo.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
630 dlClientVideo.SetAttribute("PacketSize", UintegerValue(udpPacketSizeUll));
631 dlClientVideo.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaUll)));
632
633 // The bearer that will carry video traffic
635
636 // The filter for the video traffic
637 Ptr<NrEpcTft> videoTft = Create<NrEpcTft>();
638 NrEpcTft::PacketFilter dlpfVideo;
639 dlpfVideo.localPortStart = dlPortVideo;
640 dlpfVideo.localPortEnd = dlPortVideo;
641 videoTft->Add(dlpfVideo);
642
643 // Gaming configuration and object creation:
644 UdpClientHelper ulClientGaming;
645 ulClientGaming.SetAttribute("RemotePort", UintegerValue(ulPortGaming));
646 ulClientGaming.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
647 ulClientGaming.SetAttribute("PacketSize", UintegerValue(udpPacketSizeUll));
648 ulClientGaming.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaUll)));
649
650 // The bearer that will carry gaming traffic
652
653 // The filter for the gaming traffic
654 Ptr<NrEpcTft> gamingTft = Create<NrEpcTft>();
655 NrEpcTft::PacketFilter ulpfGaming;
656 ulpfGaming.remotePortStart = ulPortGaming;
657 ulpfGaming.remotePortEnd = ulPortGaming;
658 ulpfGaming.direction = NrEpcTft::UPLINK;
659 gamingTft->Add(ulpfGaming);
660
661 // Install the applications
662 ApplicationContainer clientApps;
663
664 for (uint32_t i = 0; i < ueNodes.GetN(); ++i)
665 {
666 Ptr<Node> ue = ueNodes.Get(i);
667 Ptr<NetDevice> ueDevice = ueNetDev.Get(i);
668 Address ueAddress = ueIpIface.GetAddress(i);
669
670 // The client, who is transmitting, is installed in the remote host,
671 // with destination address set to the address of the UE
672 if (enableLowLat)
673 {
674 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(ueAddress));
675 clientApps.Add(dlClientLowLat.Install(remoteHost));
676
677 nrHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
678 }
679 if (enableVideo)
680 {
681 dlClientVideo.SetAttribute("RemoteAddress", AddressValue(ueAddress));
682 clientApps.Add(dlClientVideo.Install(remoteHost));
683
684 nrHelper->ActivateDedicatedEpsBearer(ueDevice, videoBearer, videoTft);
685 }
686
687 // For the uplink, the installation happens in the UE, and the remote address
688 // is the one of the remote host
689
690 if (enableVoice)
691 {
692 ulClientVoice.SetAttribute("RemoteAddress", AddressValue(remoteHostIpv4Address));
693 clientApps.Add(ulClientVoice.Install(ue));
694
695 nrHelper->ActivateDedicatedEpsBearer(ueDevice, voiceBearer, voiceTft);
696 }
697
698 if (enableGaming)
699 {
700 ulClientGaming.SetAttribute("RemoteAddress", AddressValue(remoteHostIpv4Address));
701 clientApps.Add(ulClientGaming.Install(ue));
702
703 nrHelper->ActivateDedicatedEpsBearer(ueDevice, gamingBearer, gamingTft);
704 }
705 }
706
707 // start UDP server and client apps
708 serverApps.Start(Seconds(udpAppStartTime));
709 clientApps.Start(Seconds(udpAppStartTime));
710 serverApps.Stop(Seconds(simTime));
711 clientApps.Stop(Seconds(simTime));
712
713 // enable the traces provided by the nr module
714 nrHelper->EnableTraces();
715
716 FlowMonitorHelper flowmonHelper;
717 NodeContainer endpointNodes;
718 endpointNodes.Add(remoteHost);
719 endpointNodes.Add(ueNodes);
720
721 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
722 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.001));
723 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
724 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
725
726 Simulator::Stop(Seconds(simTime));
727 Simulator::Run();
728
729 /*
730 * To check what was installed in the memory, i.e., BWPs of gNB Device, and its configuration.
731 * Example is: Node 1 -> Device 0 -> BandwidthPartMap -> {0,1} BWPs -> NrGnbPhy ->
732 NrPhyMacCommong-> Numerology, Bandwidth, ... GtkConfigStore config; config.ConfigureAttributes
733 ();
734 */
735
736 // Print per-flow statistics
737 monitor->CheckForLostPackets();
738 Ptr<Ipv4FlowClassifier> classifier =
739 DynamicCast<Ipv4FlowClassifier>(flowmonHelper.GetClassifier());
740 FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
741
742 double averageFlowThroughput = 0.0;
743 double averageFlowDelay = 0.0;
744
745 std::ofstream outFile;
746 std::string filename = outputDir + "/" + simTag;
747 outFile.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
748 if (!outFile.is_open())
749 {
750 std::cerr << "Can't open file " << filename << std::endl;
751 return 1;
752 }
753
754 outFile.setf(std::ios_base::fixed);
755
756 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
757 i != stats.end();
758 ++i)
759 {
760 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
761 std::stringstream protoStream;
762 protoStream << (uint16_t)t.protocol;
763 if (t.protocol == 6)
764 {
765 protoStream.str("TCP");
766 }
767 if (t.protocol == 17)
768 {
769 protoStream.str("UDP");
770 }
771 outFile << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
772 << t.destinationAddress << ":" << t.destinationPort << ") proto "
773 << protoStream.str() << "\n";
774 outFile << " Tx Packets: " << i->second.txPackets << "\n";
775 outFile << " Tx Bytes: " << i->second.txBytes << "\n";
776 outFile << " TxOffered: "
777 << i->second.txBytes * 8.0 / (simTime - udpAppStartTime) / 1000 / 1000 << " Mbps\n";
778 outFile << " Rx Bytes: " << i->second.rxBytes << "\n";
779 if (i->second.rxPackets > 0)
780 {
781 // Measure the duration of the flow from receiver's perspective
782 // double rxDuration = i->second.timeLastRxPacket.GetSeconds () -
783 // i->second.timeFirstTxPacket.GetSeconds ();
784 double rxDuration = (simTime - udpAppStartTime);
785
786 averageFlowThroughput += i->second.rxBytes * 8.0 / rxDuration / 1000 / 1000;
787 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
788
789 outFile << " Throughput: " << i->second.rxBytes * 8.0 / rxDuration / 1000 / 1000
790 << " Mbps\n";
791 outFile << " Mean delay: "
792 << 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets << " ms\n";
793 // outFile << " Mean upt: " << i->second.uptSum / i->second.rxPackets / 1000/1000 << "
794 // Mbps \n";
795 outFile << " Mean jitter: "
796 << 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets << " ms\n";
797 }
798 else
799 {
800 outFile << " Throughput: 0 Mbps\n";
801 outFile << " Mean delay: 0 ms\n";
802 outFile << " Mean jitter: 0 ms\n";
803 }
804 outFile << " Rx Packets: " << i->second.rxPackets << "\n";
805 }
806
807 outFile << "\n\n Aggregated throughput: " << averageFlowThroughput << "\n";
808 outFile << " Mean flow throughput: " << averageFlowThroughput / stats.size() << "\n";
809 outFile << " Mean flow delay: " << averageFlowDelay / stats.size() << "\n";
810
811 outFile.close();
812
813 std::ifstream f(filename.c_str());
814
815 if (f.is_open())
816 {
817 std::cout << f.rdbuf();
818 }
819
820 Simulator::Destroy();
821 return 0;
822}
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.
@ ErrorModel
Error Model version (can use different error models, see NrErrorModel)
Definition nr-amc.h:81
This class contains the specification of EPS Bearers.
@ NGBR_LOW_LAT_EMBB
Non-GBR Low Latency eMBB applications.
@ GBR_CONV_VOICE
GBR Conversational Voice.
@ NGBR_VOICE_VIDEO_GAMING
Non-GBR Voice, Video, Interactive Streaming.
@ NGBR_VIDEO_TCP_PREMIUM
Non-GBR TCP-based Video (Buffered Streaming, e.g., www, e-mail...)
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Component carrier configuration element.
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 remotePortEnd
end of the port number range of the remote host
Definition nr-epc-tft.h:117
uint16_t localPortStart
start of the port number range of the UE
Definition nr-epc-tft.h:118
uint16_t remotePortStart
start of the port number range of the remote host
Definition nr-epc-tft.h:116
uint16_t localPortEnd
end of the port number range of the UE
Definition nr-epc-tft.h:119
Operation band information structure.
double m_channelBandwidth
Operation band bandwidth.
BandwidthPartInfoPtr & GetBwpAt(uint32_t ccId, uint32_t bwpId) const
Get the BWP at the cc/bwp specified.
bool AddCc(ComponentCarrierInfoPtr &&cc)
Adds the component carrier definition given as an input reference to the current operation band confi...
double m_lowerFrequency
Operation band lower frequency.
double m_centralFrequency
Operation band central frequency.
double m_higherFrequency
Operation band higher frequency.