5G-LENA nr-v4.1
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
83 uint32_t udpPacketSizeUll = 915;
84 uint32_t udpPacketSizeBe = 915;
85 uint32_t lambdaUll = 10000;
86 uint32_t lambdaBe = 10000;
87
88 bool enableLowLat = true;
89 bool enableVideo = true;
90 bool enableVoice = true;
91 bool enableGaming = false; // If FDD is selected is set automatically to true
92
93 bool logging = false;
94
95 std::string simTag = "default";
96 std::string outputDir = "./";
97
98 double simTime = 1.4; // seconds
99 double udpAppStartTime = 0.4; // seconds
100
101 CommandLine cmd(__FILE__);
102
103 cmd.AddValue("simTime", "Simulation time", simTime);
104 cmd.AddValue("gNbNum", "The number of gNbs in multiple-ue topology", gNbNum);
105 cmd.AddValue("ueNumPergNb", "The number of UE per gNb in multiple-ue topology", ueNumPergNb);
106 cmd.AddValue("numBands",
107 "Number of operation bands. More than one implies non-contiguous CC",
108 numBands);
109 cmd.AddValue("bandwidthBand40", "The system bandwidth to be used in band 1", bandwidthBand40);
110 cmd.AddValue("bandwidthBand38", "The system bandwidth to be used in band 2", bandwidthBand38);
111 cmd.AddValue("bandwidth", "The bandwidth of the CCs ", bandwidth);
112 cmd.AddValue("numerologyBwp0", "The numerology to be used in bandwidth part 1", numerologyBwp0);
113 cmd.AddValue("numerologyBwp1", "The numerology to be used in bandwidth part 1", numerologyBwp1);
114 cmd.AddValue("numerologyBwp2", "The numerology to be used in bandwidth part 2", numerologyBwp2);
115 cmd.AddValue("numerologyBwpDl",
116 "The numerology to be used in bandwidth part 2",
117 numerologyBwpDl);
118 cmd.AddValue("numerologyBwpUl",
119 "The numerology to be used in bandwidth part 2",
120 numerologyBwpUl);
121 cmd.AddValue("totalTxPower",
122 "total tx power that will be proportionally assigned to"
123 " bandwidth parts depending on each BWP bandwidth ",
124 totalTxPower);
125 cmd.AddValue("tddPattern",
126 "LTE TDD pattern to use (e.g. --tddPattern=DL|S|UL|UL|UL|DL|S|UL|UL|UL|)",
127 pattern);
128 cmd.AddValue("operationMode",
129 "The network operation mode can be TDD or FDD (In this case it"
130 "will be mixed TDD and FDD)",
131 operationMode);
132 cmd.AddValue("cellScan",
133 "Use beam search method to determine beamforming vector,"
134 "true to use cell scanning method",
135 cellScan);
136 cmd.AddValue("packetSizeUll",
137 "packet size in bytes to be used by ultra low latency traffic",
138 udpPacketSizeUll);
139 cmd.AddValue("packetSizeBe",
140 "packet size in bytes to be used by best effort traffic",
141 udpPacketSizeBe);
142 cmd.AddValue("lambdaUll",
143 "Number of UDP packets in one second for ultra low latency traffic",
144 lambdaUll);
145 cmd.AddValue("lambdaBe",
146 "Number of UDP packets in one second for best effort traffic",
147 lambdaBe);
148 cmd.AddValue("enableLowLat",
149 "If true, enables low latency traffic transmission (DL)",
150 enableLowLat);
151 cmd.AddValue("enableVideo", "If true, enables video traffic transmission (DL)", enableVideo);
152 cmd.AddValue("enableVoice", "If true, enables voice traffic transmission (UL)", enableVoice);
153 cmd.AddValue("enableGaming", "If true, enables gaming traffic transmission (UL)", enableGaming);
154 cmd.AddValue("logging", "Enable logging", logging);
155 cmd.AddValue("simTag",
156 "tag to be appended to output filenames to distinguish simulation campaigns",
157 simTag);
158 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
159
160 cmd.Parse(argc, argv);
161
162 NS_ABORT_IF(numBands < 1);
163 NS_ABORT_MSG_IF(enableLowLat == false && enableVideo == false && enableVoice == false &&
164 enableGaming == false && operationMode == "TDD",
165 "For TDD enable one of the flows");
166
167 // ConfigStore inputConfig;
168 // inputConfig.ConfigureDefaults ();
169
170 // enable logging or not
171 if (logging)
172 {
173 // LogComponentEnable ("Nr3gppPropagationLossModel", LOG_LEVEL_ALL);
174 // LogComponentEnable ("Nr3gppBuildingsPropagationLossModel", LOG_LEVEL_ALL);
175 // LogComponentEnable ("Nr3gppChannel", LOG_LEVEL_ALL);
176 // LogComponentEnable ("UdpClient", LOG_LEVEL_INFO);
177 // LogComponentEnable ("UdpServer", LOG_LEVEL_INFO);
178 // LogComponentEnable ("NrPdcp", LOG_LEVEL_INFO);
179 // LogComponentEnable ("BwpManagerGnb", LOG_LEVEL_INFO);
180 // LogComponentEnable ("BwpManagerAlgorithm", LOG_LEVEL_INFO);
181 LogComponentEnable("NrGnbPhy", LOG_LEVEL_INFO);
182 LogComponentEnable("NrUePhy", LOG_LEVEL_INFO);
183 // LogComponentEnable ("NrGnbMac", LOG_LEVEL_INFO);
184 // LogComponentEnable ("NrUeMac", LOG_LEVEL_INFO);
185 }
186
187 // create base stations and mobile terminals
188 NodeContainer gNbNodes;
189 NodeContainer ueNodes;
190 MobilityHelper mobility;
191
192 double gNbHeight = 10;
193 double ueHeight = 1.5;
194
195 gNbNodes.Create(gNbNum);
196 ueNodes.Create(ueNumPergNb * gNbNum);
197
198 Ptr<ListPositionAllocator> apPositionAlloc = CreateObject<ListPositionAllocator>();
199 Ptr<ListPositionAllocator> staPositionAlloc = CreateObject<ListPositionAllocator>();
200 int32_t yValue = 0.0;
201
202 for (uint32_t i = 1; i <= gNbNodes.GetN(); ++i)
203 {
204 // 2.0, -2.0, 6.0, -6.0, 10.0, -10.0, ....
205 if (i % 2 != 0)
206 {
207 yValue = static_cast<int>(i) * 30;
208 }
209 else
210 {
211 yValue = -yValue;
212 }
213
214 apPositionAlloc->Add(Vector(0.0, yValue, gNbHeight));
215
216 // 1.0, -1.0, 3.0, -3.0, 5.0, -5.0, ...
217 double xValue = 0.0;
218 for (uint32_t j = 1; j <= ueNumPergNb; ++j)
219 {
220 if (j % 2 != 0)
221 {
222 xValue = j;
223 }
224 else
225 {
226 xValue = -xValue;
227 }
228
229 if (yValue > 0)
230 {
231 staPositionAlloc->Add(Vector(xValue, 10, ueHeight));
232 }
233 else
234 {
235 staPositionAlloc->Add(Vector(xValue, -10, ueHeight));
236 }
237 }
238 }
239
240 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
241 mobility.SetPositionAllocator(apPositionAlloc);
242 mobility.Install(gNbNodes);
243
244 mobility.SetPositionAllocator(staPositionAlloc);
245 mobility.Install(ueNodes);
246
247 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
248 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
249 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
250 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
251 nrHelper->SetEpcHelper(nrEpcHelper);
252 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
253 if (cellScan)
254 {
255 idealBeamformingHelper->SetAttribute("BeamformingMethod",
256 TypeIdValue(CellScanBeamforming::GetTypeId()));
257 }
258 else
259 {
260 idealBeamformingHelper->SetAttribute(
261 "BeamformingMethod",
263 }
264 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
265
266 std::string errorModel = "ns3::NrLteMiErrorModel";
267 // Scheduler
268 nrHelper->SetSchedulerAttribute("FixedMcsDl", BooleanValue(false));
269 nrHelper->SetSchedulerAttribute("FixedMcsUl", BooleanValue(false));
270
271 // Error Model: UE and GNB with same spectrum error model.
272 nrHelper->SetUlErrorModel(errorModel);
273 nrHelper->SetDlErrorModel(errorModel);
274
275 // Both DL and UL AMC will have the same model behind.
276 nrHelper->SetGnbDlAmcAttribute(
277 "AmcModel",
278 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
279 nrHelper->SetGnbUlAmcAttribute(
280 "AmcModel",
281 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
282
283 /*
284 * Adjust the average number of Reference symbols per RB only for LTE case,
285 * which is larger than in NR. We assume a value of 4 (could be 3 too).
286 */
287 nrHelper->SetGnbDlAmcAttribute("NumRefScPerRb", UintegerValue(2));
288 nrHelper->SetGnbUlAmcAttribute("NumRefScPerRb", UintegerValue(2));
289 nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(4));
290 nrHelper->SetSchedulerAttribute("DlCtrlSymbols", UintegerValue(1));
291 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaPF"));
292
293 /*
294 * Setup the operation bands.
295 * In this example, two standard operation bands are deployed:
296 *
297 * Band 38 that has a component carrier (CC) of 20 MHz
298 * Band 40 that has two non-contiguous CCs of 20 MHz each.
299 *
300 * If TDD mode is defined, 1 BWP per CC is created. All BWPs are TDD.
301 * If FDD mode is defined, Band 40 CC2 contains 2 BWPs (1 DL - 1 UL), while
302 * Band 40 CC1 has one TDD BWP and Band 38 CC0 also has one TDD BWP.
303 *
304 * This example manually creates a non-contiguous CC configuration with 2 CCs.
305 * First CC has two BWPs and the second only one.
306 *
307 * The configured spectrum division for TDD mode is:
308 * |--------- Band 40 --------| |--------------- Band 38 ---------------|
309 * |---------- CC0 -----------| |-------- CC1-------||------- CC2-------|
310 * |---------- BWP0 ----------| |------- BWP1 ------||------ BWP2 ------|
311 *
312 * The configured spectrum division for FDD mode is:
313 * |-------- Band 40 ---------| |----------------- Band 38 ----------------|
314 * |---------- CC0 -----------| |------- CC1-------| |-------- CC2--------|
315 * |---------- BWP0 ----------| |------ BWP1 ------| |- BWP2DL -|- BWP2UL-|
316 *
317 *
318 * In this example, each UE generates as many flows as the number of bwps
319 * (i.e. 3 flows in case of TDD mode and 4 in case mixed TDD with FDD).
320 * Each flow will be transmitted on a dedicated BWP. In particular, low
321 * latency flow is set as DL and goes through BWP0, voice is set as UL and
322 * goes through BWP1, video is set as DL and goes through BWP2DL, and gaming
323 * is enabled only in the mixed TDD/FDD mode, it is set as UL and goes
324 * through BWP2UL.
325 */
326 uint8_t numCcs = 3;
327
329
330 // Create the configuration for band40 (CC0 - BWP0)
331 OperationBandInfo band40;
332 band40.m_centralFrequency = centralFrequencyBand40;
333 band40.m_channelBandwidth = bandwidthBand40;
334 band40.m_lowerFrequency = band40.m_centralFrequency - band40.m_channelBandwidth / 2;
335 band40.m_higherFrequency = band40.m_centralFrequency + band40.m_channelBandwidth / 2;
336
337 // Component Carrier 0
338 std::unique_ptr<ComponentCarrierInfo> cc0(new ComponentCarrierInfo());
339 cc0->m_ccId = 0;
340 cc0->m_centralFrequency = band40.m_lowerFrequency + bandwidth;
341 cc0->m_channelBandwidth = bandwidth;
342 cc0->m_lowerFrequency = cc0->m_centralFrequency - cc0->m_channelBandwidth / 2;
343 cc0->m_higherFrequency = cc0->m_centralFrequency + cc0->m_channelBandwidth / 2;
344
345 // BWP 0
346 std::unique_ptr<BandwidthPartInfo> bwp0(new BandwidthPartInfo());
347 bwp0->m_bwpId = 0;
348 bwp0->m_centralFrequency = cc0->m_centralFrequency;
349 bwp0->m_channelBandwidth = cc0->m_channelBandwidth;
350 bwp0->m_lowerFrequency = cc0->m_lowerFrequency;
351 bwp0->m_higherFrequency = cc0->m_higherFrequency;
352
353 cc0->AddBwp(std::move(bwp0));
354
355 band40.AddCc(std::move(cc0));
356
357 // Create the configuration for band38
358 OperationBandInfo band38;
359 band38.m_centralFrequency = centralFrequencyBand38;
360 band38.m_channelBandwidth = bandwidthBand38;
361 band38.m_lowerFrequency = band38.m_centralFrequency - band38.m_channelBandwidth / 2;
362 band38.m_higherFrequency = band38.m_centralFrequency + band38.m_channelBandwidth / 2;
363
364 //(CC1 - BWP1)
365 // Component Carrier 1
366 std::unique_ptr<ComponentCarrierInfo> cc1(new ComponentCarrierInfo());
367 cc1->m_ccId = 1;
368 cc1->m_centralFrequency = band38.m_lowerFrequency + bandwidth;
369 cc1->m_channelBandwidth = bandwidth;
370 cc1->m_lowerFrequency = cc1->m_centralFrequency - cc1->m_channelBandwidth / 2;
371 cc1->m_higherFrequency = cc1->m_centralFrequency + cc1->m_channelBandwidth / 2;
372
373 // BWP 1
374 std::unique_ptr<BandwidthPartInfo> bwp1(new BandwidthPartInfo());
375 bwp1->m_bwpId = 1;
376 bwp1->m_centralFrequency = cc1->m_centralFrequency;
377 bwp1->m_channelBandwidth = cc1->m_channelBandwidth;
378 bwp1->m_lowerFrequency = cc1->m_lowerFrequency;
379 bwp1->m_higherFrequency = cc1->m_higherFrequency;
380
381 cc1->AddBwp(std::move(bwp1));
382
383 std::unique_ptr<ComponentCarrierInfo> cc2(new ComponentCarrierInfo());
384 std::unique_ptr<BandwidthPartInfo> bwp2(new BandwidthPartInfo());
385 std::unique_ptr<BandwidthPartInfo> bwpdl(new BandwidthPartInfo());
386 std::unique_ptr<BandwidthPartInfo> bwpul(new BandwidthPartInfo());
387
388 // Component Carrier 2
389 cc2->m_ccId = 2;
390 cc2->m_centralFrequency = band38.m_higherFrequency - bandwidth;
391 cc2->m_channelBandwidth = bandwidth;
392 cc2->m_lowerFrequency = cc2->m_centralFrequency - cc2->m_channelBandwidth / 2;
393 cc2->m_higherFrequency = cc2->m_centralFrequency + cc2->m_channelBandwidth / 2;
394
395 if (operationMode == "TDD") //(CC2 - BWP2)
396 {
397 bwp2->m_bwpId = 1;
398 bwp2->m_centralFrequency = cc2->m_centralFrequency;
399 bwp2->m_channelBandwidth = cc2->m_channelBandwidth;
400 bwp2->m_lowerFrequency = cc2->m_lowerFrequency;
401 bwp2->m_higherFrequency = cc2->m_higherFrequency;
402
403 cc2->AddBwp(std::move(bwp2));
404 }
405 else // FDD case (CC2 - BWPdl & BWPul)
406 {
407 // BWP DL
408 bwpdl->m_bwpId = 2;
409 bwpdl->m_channelBandwidth = cc2->m_channelBandwidth / 2;
410 bwpdl->m_lowerFrequency = cc2->m_lowerFrequency;
411 bwpdl->m_higherFrequency = bwpdl->m_lowerFrequency + bwpdl->m_channelBandwidth;
412 bwpdl->m_centralFrequency = bwpdl->m_lowerFrequency + bwpdl->m_channelBandwidth / 2;
413
414 cc2->AddBwp(std::move(bwpdl));
415
416 // BWP UL
417 bwpul->m_bwpId = 3;
418 bwpul->m_channelBandwidth = cc2->m_channelBandwidth / 2;
419 bwpul->m_lowerFrequency = cc2->m_centralFrequency;
420 bwpul->m_higherFrequency = cc2->m_higherFrequency;
421 bwpul->m_centralFrequency = bwpul->m_lowerFrequency + bwpul->m_channelBandwidth / 2;
422
423 cc2->AddBwp(std::move(bwpul));
424 Config::SetDefault("ns3::NrUeNetDevice::PrimaryUlIndex", UintegerValue(1));
425 }
426
427 band38.AddCc(std::move(cc1));
428 band38.AddCc(std::move(cc2));
429 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
430 // use the default spectrum channel {RMa, Default, ThreeGpp}
431 channelHelper->ConfigureFactories("RMa", "Default", "ThreeGpp");
432 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
433 channelHelper->AssignChannelsToBands({band40, band38});
434 allBwps = CcBwpCreator::GetAllBwps({band38, band40});
435
436 // Antennas for all the UEs
437 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(1));
438 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(1));
439 nrHelper->SetUeAntennaAttribute("AntennaElement",
440 PointerValue(CreateObject<IsotropicAntennaModel>()));
441
442 // Antennas for all the gNbs
443 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(2));
444 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(2));
445 nrHelper->SetGnbAntennaAttribute("AntennaElement",
446 PointerValue(CreateObject<IsotropicAntennaModel>()));
447
448 // Assign each flow type to a BWP
449 uint32_t bwpIdForLowLat = 0;
450 uint32_t bwpIdForVoice = 1;
451 uint32_t bwpIdForVideo = 2;
452 uint32_t bwpIdForVideoGaming = 3;
453
454 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB",
455 UintegerValue(bwpIdForLowLat));
456 nrHelper->SetGnbBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
457 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_PREMIUM",
458 UintegerValue(bwpIdForVideo));
459 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_VOICE_VIDEO_GAMING",
460 UintegerValue(bwpIdForVideoGaming));
461
462 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdForLowLat));
463 nrHelper->SetUeBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
464 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_PREMIUM",
465 UintegerValue(bwpIdForVideo));
466 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_VOICE_VIDEO_GAMING",
467 UintegerValue(bwpIdForVideoGaming));
468
469 // install nr net devices
470 NetDeviceContainer gnbNetDev = nrHelper->InstallGnbDevice(gNbNodes, allBwps);
471 NetDeviceContainer ueNetDev = nrHelper->InstallUeDevice(ueNodes, allBwps);
472
473 int64_t randomStream = 1;
474 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
475 randomStream += nrHelper->AssignStreams(ueNetDev, randomStream);
476
477 // Share the total transmission power among CCs proportionally with the BW
478 double x = pow(10, totalTxPower / 10);
479 double totalBandwidth = numCcs * bandwidth;
480
481 // Band40: CC0 - BWP0 & Band38: CC1 - BWP1
482 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)
483 ->SetAttribute("Numerology", UintegerValue(numerologyBwp0));
484 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)
485 ->SetAttribute(
486 "TxPower",
487 DoubleValue(10 *
488 log10((band40.GetBwpAt(0, 0)->m_channelBandwidth / totalBandwidth) * x)));
489 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("Pattern", StringValue(pattern));
490 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("RbOverhead", DoubleValue(0.1));
491
492 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)
493 ->SetAttribute("Numerology", UintegerValue(numerologyBwp1));
494 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)
495 ->SetAttribute(
496 "TxPower",
497 DoubleValue(10 *
498 log10((band38.GetBwpAt(0, 0)->m_channelBandwidth / totalBandwidth) * x)));
499 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)->SetAttribute("Pattern", StringValue(pattern));
500 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 1)->SetAttribute("RbOverhead", DoubleValue(0.1));
501
502 // Band38: CC2 - BWP2
503 if (operationMode == "TDD")
504 {
505 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
506 ->SetAttribute("Numerology", UintegerValue(numerologyBwp2));
507 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
508 ->SetAttribute(
509 "TxPower",
510 DoubleValue(
511 10 * log10((band38.GetBwpAt(1, 0)->m_channelBandwidth / totalBandwidth) * x)));
512 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("Pattern", StringValue(pattern));
513 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("RbOverhead", DoubleValue(0.1));
514 }
515 else // FDD case
516 {
517 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
518 ->SetAttribute("Numerology", UintegerValue(numerologyBwpDl));
519 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)
520 ->SetAttribute(
521 "TxPower",
522 DoubleValue(
523 10 * log10((band38.GetBwpAt(1, 0)->m_channelBandwidth / totalBandwidth) * x)));
524 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("Pattern", StringValue(patternDL));
525 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 2)->SetAttribute("RbOverhead", DoubleValue(0.1));
526
527 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 3)
528 ->SetAttribute("Numerology", UintegerValue(numerologyBwpUl));
529 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 3)->SetAttribute("Pattern", StringValue(patternUL));
530 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 3)->SetAttribute("RbOverhead", DoubleValue(0.1));
531
532 // Link the two FDD BWP:
533 nrHelper->GetBwpManagerGnb(gnbNetDev.Get(0))->SetOutputLink(3, 2);
534
535 // Set the UE routing:
536 for (uint32_t i = 0; i < ueNetDev.GetN(); i++)
537 {
538 nrHelper->GetBwpManagerUe(ueNetDev.Get(i))->SetOutputLink(2, 3);
539 }
540
541 // enable 4rth flow
542 enableGaming = true;
543 }
544
545 // create the internet and install the IP stack on the UEs
546 // get SGW/PGW and create a single RemoteHost
547 auto [remoteHost, remoteHostIpv4Address] =
548 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
549
550 InternetStackHelper internet;
551
552 internet.Install(ueNodes);
553 Ipv4InterfaceContainer ueIpIface;
554 ueIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDev));
555
556 // attach UEs to the closest gNB
557 nrHelper->AttachToClosestGnb(ueNetDev, gnbNetDev);
558
559 // install UDP applications
560 uint16_t dlPortLowLat = 1234;
561 uint16_t ulPortVoice = 1235;
562 uint16_t dlPortVideo = 1236;
563 uint16_t ulPortGaming = 1237;
564
565 ApplicationContainer serverApps;
566
567 // The sink will always listen to the specified ports
568 UdpServerHelper dlPacketSinkLowLat(dlPortLowLat);
569 UdpServerHelper ulPacketSinkVoice(ulPortVoice);
570 UdpServerHelper dlPacketSinkVideo(dlPortVideo);
571 UdpServerHelper ulPacketSinkGaming(ulPortGaming);
572
573 // The server, that is the application which is listening, is installed in the UE
574 // for the DL traffic, and in the remote host for the UL traffic
575 serverApps.Add(dlPacketSinkLowLat.Install(ueNodes));
576 serverApps.Add(ulPacketSinkVoice.Install(remoteHost));
577 serverApps.Add(dlPacketSinkVideo.Install(ueNodes));
578 serverApps.Add(ulPacketSinkGaming.Install(remoteHost));
579
580 /*
581 * Configure attributes for the different generators, using user-provided
582 * parameters for generating a CBR traffic
583 *
584 * Low-Latency configuration and object creation:
585 */
586 UdpClientHelper dlClientLowLat;
587 dlClientLowLat.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
588 dlClientLowLat.SetAttribute("PacketSize", UintegerValue(udpPacketSizeBe));
589 dlClientLowLat.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaBe)));
590
591 // The bearer that will carry low latency traffic
593
594 // The filter for the low-latency traffic
595 Ptr<NrEpcTft> lowLatTft = Create<NrEpcTft>();
596 NrEpcTft::PacketFilter dlpfLowLat;
597 dlpfLowLat.localPortStart = dlPortLowLat;
598 dlpfLowLat.localPortEnd = dlPortLowLat;
599 lowLatTft->Add(dlpfLowLat);
600
601 // Voice configuration and object creation:
602 UdpClientHelper ulClientVoice;
603 ulClientVoice.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
604 ulClientVoice.SetAttribute("PacketSize", UintegerValue(udpPacketSizeBe));
605 ulClientVoice.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaBe)));
606
607 // The bearer that will carry voice traffic
609
610 // The filter for the voice traffic
611 Ptr<NrEpcTft> voiceTft = Create<NrEpcTft>();
612 NrEpcTft::PacketFilter ulpfVoice;
613 ulpfVoice.localPortStart = ulPortVoice;
614 ulpfVoice.localPortEnd = ulPortVoice;
615 ulpfVoice.direction = NrEpcTft::UPLINK;
616 voiceTft->Add(ulpfVoice);
617
618 // Video configuration and object creation:
619 UdpClientHelper dlClientVideo;
620 dlClientVideo.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
621 dlClientVideo.SetAttribute("PacketSize", UintegerValue(udpPacketSizeUll));
622 dlClientVideo.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaUll)));
623
624 // The bearer that will carry video traffic
626
627 // The filter for the video traffic
628 Ptr<NrEpcTft> videoTft = Create<NrEpcTft>();
629 NrEpcTft::PacketFilter dlpfVideo;
630 dlpfVideo.localPortStart = dlPortVideo;
631 dlpfVideo.localPortEnd = dlPortVideo;
632 videoTft->Add(dlpfVideo);
633
634 // Gaming configuration and object creation:
635 UdpClientHelper ulClientGaming;
636 ulClientGaming.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
637 ulClientGaming.SetAttribute("PacketSize", UintegerValue(udpPacketSizeUll));
638 ulClientGaming.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaUll)));
639
640 // The bearer that will carry gaming traffic
642
643 // The filter for the gaming traffic
644 Ptr<NrEpcTft> gamingTft = Create<NrEpcTft>();
645 NrEpcTft::PacketFilter ulpfGaming;
646 ulpfGaming.remotePortStart = ulPortGaming;
647 ulpfGaming.remotePortEnd = ulPortGaming;
648 ulpfGaming.direction = NrEpcTft::UPLINK;
649 gamingTft->Add(ulpfGaming);
650
651 // Install the applications
652 ApplicationContainer clientApps;
653
654 for (uint32_t i = 0; i < ueNodes.GetN(); ++i)
655 {
656 Ptr<Node> ue = ueNodes.Get(i);
657 Ptr<NetDevice> ueDevice = ueNetDev.Get(i);
658 Address ueAddress = ueIpIface.GetAddress(i);
659
660 // The client, who is transmitting, is installed in the remote host,
661 // with destination address set to the address of the UE
662 if (enableLowLat)
663 {
664 dlClientLowLat.SetAttribute(
665 "Remote",
666 AddressValue(addressUtils::ConvertToSocketAddress(ueAddress, dlPortLowLat)));
667 clientApps.Add(dlClientLowLat.Install(remoteHost));
668
669 nrHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
670 }
671 if (enableVideo)
672 {
673 dlClientVideo.SetAttribute(
674 "Remote",
675 AddressValue(addressUtils::ConvertToSocketAddress(ueAddress, dlPortVideo)));
676 clientApps.Add(dlClientVideo.Install(remoteHost));
677
678 nrHelper->ActivateDedicatedEpsBearer(ueDevice, videoBearer, videoTft);
679 }
680
681 // For the uplink, the installation happens in the UE, and the remote address
682 // is the one of the remote host
683
684 if (enableVoice)
685 {
686 ulClientVoice.SetAttribute(
687 "Remote",
688 AddressValue(
689 addressUtils::ConvertToSocketAddress(remoteHostIpv4Address, ulPortVoice)));
690 clientApps.Add(ulClientVoice.Install(ue));
691
692 nrHelper->ActivateDedicatedEpsBearer(ueDevice, voiceBearer, voiceTft);
693 }
694
695 if (enableGaming)
696 {
697 ulClientGaming.SetAttribute(
698 "Remote",
699 AddressValue(
700 addressUtils::ConvertToSocketAddress(remoteHostIpv4Address, ulPortGaming)));
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.