5G-LENA nr-v3.0-32-g83aee33
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-traffic-ngmn-mixed.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
32/*
33 * Include part. Often, you will have to include the headers for an entire module;
34 * do that by including the name of the module you need with the suffix "-module.h".
35 */
36
37#include "ns3/applications-module.h"
38#include "ns3/config-store-module.h"
39#include "ns3/config-store.h"
40#include "ns3/core-module.h"
41#include "ns3/flow-monitor-module.h"
42#include "ns3/internet-apps-module.h"
43#include "ns3/internet-module.h"
44#include "ns3/log.h"
45#include "ns3/mobility-module.h"
46#include "ns3/network-module.h"
47#include "ns3/nr-module.h"
48#include "ns3/point-to-point-module.h"
49#include <ns3/antenna-module.h>
50#include <ns3/ping-helper.h>
51#include <ns3/radio-environment-map-helper.h>
52#include <ns3/rng-seed-manager.h>
53#include <ns3/three-gpp-ftp-m1-helper.h>
54#include <ns3/three-gpp-http-client.h>
55#include <ns3/three-gpp-http-helper.h>
56#include <ns3/three-gpp-http-server.h>
57#include <ns3/three-gpp-http-variables.h>
58#include <ns3/traffic-generator-ngmn-ftp-multi.h>
59#include <ns3/traffic-generator-ngmn-gaming.h>
60#include <ns3/traffic-generator-ngmn-video.h>
61#include <ns3/traffic-generator-ngmn-voip.h>
62
63#include <algorithm>
64#include <iostream>
65
66using namespace ns3;
67
68/*
69 * With this line, we will be able to see the logs of the file by enabling the
70 * component "CttcTrafficExample", in this way:
71 *
72 * $ export NS_LOG="CttcTrafficExample=level_info|prefix_func|prefix_time"
73 */
74NS_LOG_COMPONENT_DEFINE("CttcNrTrafficNgmnMixed");
75
76class RadioNetworkParametersHelper
77{
78 public:
83 void SetNetworkParams(const std::string scenario,
84 const std::string operationMode,
85 uint16_t numCcs);
90 double GetTxPower() const;
91
96 double GetBandwidth() const;
97
102 double GetCentralFrequency() const;
103
104 private:
105 double m_txPower{-1.0};
106 double m_bandwidth{0.0};
107 double m_centralFrequency{-1.0};
108};
109
110void
111RadioNetworkParametersHelper::SetNetworkParams(const std::string scenario,
112 const std::string operationMode,
113 uint16_t numCcs)
114{
115 NS_ABORT_MSG_IF(scenario != "UMa" && scenario != "UMi", "Unsupported scenario");
116
117 m_centralFrequency = 2e9;
118 m_bandwidth = 20e6 * numCcs; // 100 RBs per CC (freqReuse)
119 if (operationMode == "FDD")
120 {
121 m_bandwidth += m_bandwidth;
122 }
123 if (scenario == "UMa")
124 {
125 m_txPower = 43;
126 }
127 else
128 {
129 m_txPower = 30;
130 }
131}
132
133double
134RadioNetworkParametersHelper::GetTxPower() const
135{
136 return m_txPower;
137}
138
139double
140RadioNetworkParametersHelper::GetBandwidth() const
141{
142 return m_bandwidth;
143}
144
145double
146RadioNetworkParametersHelper::GetCentralFrequency() const
147{
148 return m_centralFrequency;
149}
150
151void
152Set5gLenaSimulatorParameters(HexagonalGridScenarioHelper gridScenario,
153 std::string scenario,
154 std::string radioNetwork,
155 std::string operationMode,
156 std::string direction,
157 NodeContainer gnbSector1Container,
158 NodeContainer gnbSector2Container,
159 NodeContainer gnbSector3Container,
160 NodeContainer ueSector1Container,
161 NodeContainer ueSector2Container,
162 NodeContainer ueSector3Container,
163 Ptr<PointToPointEpcHelper>& baseEpcHelper,
164 Ptr<NrHelper>& nrHelper,
165 NetDeviceContainer& gnbSector1NetDev,
166 NetDeviceContainer& gnbSector2NetDev,
167 NetDeviceContainer& gnbSector3NetDev,
168 NetDeviceContainer& ueSector1NetDev,
169 NetDeviceContainer& ueSector2NetDev,
170 NetDeviceContainer& ueSector3NetDev,
171 bool uniformLambda)
172{
173 /*
174 * Create the radio network related parameters
175 */
176 RadioNetworkParametersHelper ranHelper;
177 ranHelper.SetNetworkParams(scenario, operationMode, 1);
178
179 /*
180 * Setup the NR module. We create the various helpers needed for the
181 * NR simulation:
182 * - IdealBeamformingHelper, which takes care of the beamforming part
183 * - NrHelper, which takes care of creating and connecting the various
184 * part of the NR stack
185 */
186
187 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
188 nrHelper = CreateObject<NrHelper>();
189
190 // Put the pointers inside nrHelper
191 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
192
193 Ptr<NrPointToPointEpcHelper> epcHelper = DynamicCast<NrPointToPointEpcHelper>(baseEpcHelper);
194 nrHelper->SetEpcHelper(epcHelper);
195
196 /*
197 * Spectrum division. We create one operational band containing three
198 * component carriers, and each CC containing a single bandwidth part
199 * centered at the frequency specified by the input parameters.
200 * Each spectrum part length is, as well, specified by the input parameters.
201 * The operational band will use StreetCanyon channel or UrbanMacro modeling.
202 */
207 CcBwpCreator ccBwpCreator;
208 // Create the configuration for the CcBwpHelper. SimpleOperationBandConf creates
209 // a single BWP per CC. Get the spectrum values from the RadioNetworkParametersHelper
210 double centralFrequencyBand = ranHelper.GetCentralFrequency();
211 double bandwidthBand = ranHelper.GetBandwidth();
212 const uint8_t numCcPerBand = 1; // In this example, each cell will have one CC with one BWP
214 if (scenario == "UMi")
215 {
217 }
218 else if (scenario == "UMa")
219 {
221 }
222 else
223 {
224 NS_ABORT_MSG("Unsupported scenario");
225 }
226
227 /*
228 * Attributes of ThreeGppChannelModel still cannot be set in our way.
229 * TODO: Coordinate with Tommaso
230 */
231 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod",
232 TimeValue(MilliSeconds(0))); // 100ms
233 nrHelper->SetChannelConditionModelAttribute("UpdatePeriod", TimeValue(MilliSeconds(0)));
234 nrHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
235
236 std::string errorModel = "";
237
238 if (radioNetwork == "LTE")
239 {
240 errorModel = "ns3::LenaErrorModel";
241 }
242 else if (radioNetwork == "NR")
243 {
244 errorModel = "ns3::NrEesmIrT2";
245 }
246
247 // Error Model: UE and GNB with same spectrum error model.
248 nrHelper->SetUlErrorModel(errorModel);
249 nrHelper->SetDlErrorModel(errorModel);
250
251 // Both DL and UL AMC will have the same model behind.
252 nrHelper->SetGnbDlAmcAttribute(
253 "AmcModel",
254 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
255 nrHelper->SetGnbUlAmcAttribute(
256 "AmcModel",
257 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
258
259 /*
260 * Create the necessary operation bands. In this example, each sector operates
261 * in a separate band. Each band contains a single component carrier (CC),
262 * which is made of one BWP in TDD operation mode or two BWPs in FDD mode.
263 * Note that BWPs have the same bandwidth. Therefore, CCs and bands in FDD are
264 * twice larger than in TDD.
265 *
266 * The configured spectrum division for TDD operation is:
267 * |---Band1---|---Band2---|---Band3---|
268 * |----CC1----|----CC2----|----CC3----|
269 * |----BWP1---|----BWP2---|----BWP3---|
270 *
271 * And the configured spectrum division for FDD operation is:
272 * |---------Band1---------|---------Band2---------|---------Band3---------|
273 * |----------CC1----------|----------CC2----------|----------CC3----------|
274 * |----BWP1---|----BWP2---|----BWP3---|----BWP4---|----BWP5---|----BWP6---|
275 */
276 double centralFrequencyBand1 = centralFrequencyBand - bandwidthBand;
277 double centralFrequencyBand2 = centralFrequencyBand;
278 double centralFrequencyBand3 = centralFrequencyBand + bandwidthBand;
279 double bandwidthBand1 = bandwidthBand;
280 double bandwidthBand2 = bandwidthBand;
281 double bandwidthBand3 = bandwidthBand;
282
283 uint8_t numBwpPerCc = 1;
284 if (operationMode == "FDD")
285 {
286 numBwpPerCc = 2; // FDD will have 2 BWPs per CC
287 }
288
289 CcBwpCreator::SimpleOperationBandConf bandConf1(centralFrequencyBand1,
290 bandwidthBand1,
291 numCcPerBand,
292 scene);
293 bandConf1.m_numBwp = numBwpPerCc; // FDD will have 2 BWPs per CC
294 CcBwpCreator::SimpleOperationBandConf bandConf2(centralFrequencyBand2,
295 bandwidthBand2,
296 numCcPerBand,
297 scene);
298 bandConf2.m_numBwp = numBwpPerCc; // FDD will have 2 BWPs per CC
299 CcBwpCreator::SimpleOperationBandConf bandConf3(centralFrequencyBand3,
300 bandwidthBand3,
301 numCcPerBand,
302 scene);
303 bandConf3.m_numBwp = numBwpPerCc; // FDD will have 2 BWPs per CC
304
305 // By using the configuration created, it is time to make the operation bands
306 OperationBandInfo band1 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf1);
307 OperationBandInfo band2 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf2);
308 OperationBandInfo band3 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf3);
309
310 /*
311 * Initialize channel and pathloss, plus other things inside band1. If needed,
312 * the band configuration can be done manually, but we leave it for more
313 * sophisticated examples. For the moment, this method will take care
314 * of all the spectrum initialization needs.
315 */
316 nrHelper->InitializeOperationBand(&band1);
317 nrHelper->InitializeOperationBand(&band2);
318 nrHelper->InitializeOperationBand(&band3);
319 allBwps = CcBwpCreator::GetAllBwps({band1, band2, band3});
320 bwps1 = CcBwpCreator::GetAllBwps({band1});
321 bwps2 = CcBwpCreator::GetAllBwps({band2});
322 bwps3 = CcBwpCreator::GetAllBwps({band3});
323
324 double txPower = ranHelper.GetTxPower(); // Convert to mW
325
326 /*
327 * allBwps contains all the spectrum configuration needed for the nrHelper.
328 *
329 * Now, we can setup the attributes. We can have three kind of attributes:
330 * (i) parameters that are valid for all the bandwidth parts and applies to
331 * all nodes, (ii) parameters that are valid for all the bandwidth parts
332 * and applies to some node only, and (iii) parameters that are different for
333 * every bandwidth parts. The approach is:
334 *
335 * - for (i): Configure the attribute through the helper, and then install;
336 * - for (ii): Configure the attribute through the helper, and then install
337 * for the first set of nodes. Then, change the attribute through the helper,
338 * and install again;
339 * - for (iii): Install, and then configure the attributes by retrieving
340 * the pointer needed, and calling "SetAttribute" on top of such pointer.
341 *
342 */
343
344 Packet::EnableChecking();
345 Packet::EnablePrinting();
346
347 /*
348 * Case (i): Attributes valid for all the nodes
349 */
350 // Beamforming method
351 if (radioNetwork == "LTE")
352 {
353 idealBeamformingHelper->SetAttribute(
354 "BeamformingMethod",
356 }
357 else
358 {
359 idealBeamformingHelper->SetAttribute("BeamformingMethod",
360 TypeIdValue(DirectPathBeamforming::GetTypeId()));
361 }
362
363 // Scheduler type
364 if (radioNetwork == "LTE")
365 {
366 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaPF"));
367 nrHelper->SetSchedulerAttribute("DlCtrlSymbols", UintegerValue(1));
368 }
369 // Core latency
370 epcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
371
372 // Antennas for all the UEs
373 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(1));
374 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(1));
375 nrHelper->SetUeAntennaAttribute("AntennaElement",
376 PointerValue(CreateObject<IsotropicAntennaModel>()));
377
378 // Antennas for all the gNbs
379 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(8));
380 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
381 nrHelper->SetGnbAntennaAttribute("AntennaElement",
382 PointerValue(CreateObject<ThreeGppAntennaModel>()));
383
384 // Set numerology
385 nrHelper->SetGnbPhyAttribute("Numerology", UintegerValue(1));
386 // Set gNB TX power
387 nrHelper->SetGnbPhyAttribute("TxPower", DoubleValue(txPower));
388 // UE transmit power
389 nrHelper->SetUePhyAttribute("TxPower", DoubleValue(20.0));
390
391 // Set LTE RBG size
392 if (radioNetwork == "LTE")
393 {
394 nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(4));
395 }
396
397 // We assume a common traffic pattern for all UEs
398 uint32_t bwpIdForLowLat = 0;
399 if (operationMode == "FDD" && direction == "UL")
400 {
401 bwpIdForLowLat = 1;
402 }
403
404 // TODO check later when QoS scheduler is in place, that the type of bearer corresponds to the
405 // type of traffic gNb routing between Bearer and bandwidth part
406 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_DEFAULT",
407 UintegerValue(bwpIdForLowLat));
408
409 // Ue routing between Bearer and bandwidth part
410 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_DEFAULT",
411 UintegerValue(bwpIdForLowLat));
412
413 /*
414 * We have configured the attributes we needed. Now, install and get the pointers
415 * to the NetDevices, which contains all the NR stack:
416 */
417
418 // NetDeviceContainer enbNetDev = nrHelper->InstallGnbDevice (gridScenario.GetBaseStations (),
419 // allBwps);
420 gnbSector1NetDev = nrHelper->InstallGnbDevice(gnbSector1Container, bwps1);
421 gnbSector2NetDev = nrHelper->InstallGnbDevice(gnbSector2Container, bwps2);
422 gnbSector3NetDev = nrHelper->InstallGnbDevice(gnbSector3Container, bwps3);
423 ueSector1NetDev = nrHelper->InstallUeDevice(ueSector1Container, bwps1);
424 ueSector2NetDev = nrHelper->InstallUeDevice(ueSector2Container, bwps2);
425 ueSector3NetDev = nrHelper->InstallUeDevice(ueSector3Container, bwps3);
426
427 int64_t randomStream = 1;
428 randomStream += nrHelper->AssignStreams(gnbSector1NetDev, randomStream);
429 randomStream += nrHelper->AssignStreams(gnbSector2NetDev, randomStream);
430 randomStream += nrHelper->AssignStreams(gnbSector3NetDev, randomStream);
431 randomStream += nrHelper->AssignStreams(ueSector1NetDev, randomStream);
432 randomStream += nrHelper->AssignStreams(ueSector2NetDev, randomStream);
433 randomStream += nrHelper->AssignStreams(ueSector3NetDev, randomStream);
434
435 /*
436 * Case (iii): Go node for node and change the attributes we have to setup
437 * per-node.
438 */
439
440 // Sectors (cells) of a site are pointing at different directions
441 double orientationRads = gridScenario.GetAntennaOrientationRadians(0);
442 for (uint32_t numCell = 0; numCell < gnbSector1NetDev.GetN(); ++numCell)
443 {
444 Ptr<NetDevice> gnb = gnbSector1NetDev.Get(numCell);
445 uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
446 if (numBwps == 1) // TDD
447 {
448 // Change the antenna orientation
449 Ptr<NrGnbPhy> phy = nrHelper->GetGnbPhy(gnb, 0);
450 Ptr<UniformPlanarArray> antenna =
451 DynamicCast<UniformPlanarArray>(phy->GetSpectrumPhy()->GetAntenna());
452 antenna->SetAttribute("BearingAngle", DoubleValue(orientationRads));
453 // Set TDD pattern
454 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Pattern",
455 StringValue("F|F|F|F|F|F|F|F|F|F|"));
456 }
457
458 else if (numBwps == 2) // FDD
459 {
460 // Change the antenna orientation
461 Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0);
462 Ptr<UniformPlanarArray> antenna0 =
463 DynamicCast<UniformPlanarArray>(phy0->GetSpectrumPhy()->GetAntenna());
464 antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
465 Ptr<NrGnbPhy> phy1 = nrHelper->GetGnbPhy(gnb, 1);
466 Ptr<UniformPlanarArray> antenna1 =
467 DynamicCast<UniformPlanarArray>(phy1->GetSpectrumPhy()->GetAntenna());
468 antenna1->SetAttribute("BearingAngle", DoubleValue(orientationRads));
469 // Set TDD pattern
470 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute(
471 "Pattern",
472 StringValue("DL|DL|DL|DL|DL|DL|DL|DL|DL|DL|"));
473 nrHelper->GetGnbPhy(gnb, 1)->SetAttribute(
474 "Pattern",
475 StringValue("UL|UL|UL|UL|UL|UL|UL|UL|UL|UL|"));
476
477 // Link the two FDD BWP
478 nrHelper->GetBwpManagerGnb(gnb)->SetOutputLink(1, 0);
479 }
480
481 else
482 {
483 NS_ABORT_MSG("Incorrect number of BWPs per CC");
484 }
485 }
486
487 orientationRads = gridScenario.GetAntennaOrientationRadians(1);
488 for (uint32_t numCell = 0; numCell < gnbSector2NetDev.GetN(); ++numCell)
489 {
490 Ptr<NetDevice> gnb = gnbSector2NetDev.Get(numCell);
491 uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
492 if (numBwps == 1) // TDD
493 {
494 // Change the antenna orientation
495 Ptr<NrGnbPhy> phy = nrHelper->GetGnbPhy(gnb, 0);
496 Ptr<UniformPlanarArray> antenna =
497 DynamicCast<UniformPlanarArray>(phy->GetSpectrumPhy()->GetAntenna());
498 antenna->SetAttribute("BearingAngle", DoubleValue(orientationRads));
499 // Set TDD pattern
500 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Pattern",
501 StringValue("F|F|F|F|F|F|F|F|F|F|"));
502 }
503
504 else if (numBwps == 2) // FDD
505 {
506 // Change the antenna orientation
507 Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0);
508 Ptr<UniformPlanarArray> antenna0 =
509 DynamicCast<UniformPlanarArray>(phy0->GetSpectrumPhy()->GetAntenna());
510 antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
511 Ptr<NrGnbPhy> phy1 = nrHelper->GetGnbPhy(gnb, 1);
512 Ptr<UniformPlanarArray> antenna1 =
513 DynamicCast<UniformPlanarArray>(phy1->GetSpectrumPhy()->GetAntenna());
514 antenna1->SetAttribute("BearingAngle", DoubleValue(orientationRads));
515 // Set TDD pattern
516 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute(
517 "Pattern",
518 StringValue("DL|DL|DL|DL|DL|DL|DL|DL|DL|DL|"));
519 nrHelper->GetGnbPhy(gnb, 1)->SetAttribute(
520 "Pattern",
521 StringValue("UL|UL|UL|UL|UL|UL|UL|UL|UL|UL|"));
522 // Link the two FDD BWP
523 nrHelper->GetBwpManagerGnb(gnb)->SetOutputLink(1, 0);
524 }
525
526 else
527 {
528 NS_ABORT_MSG("Incorrect number of BWPs per CC");
529 }
530 }
531
532 orientationRads = gridScenario.GetAntennaOrientationRadians(2);
533 for (uint32_t numCell = 0; numCell < gnbSector3NetDev.GetN(); ++numCell)
534 {
535 Ptr<NetDevice> gnb = gnbSector3NetDev.Get(numCell);
536 uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
537 if (numBwps == 1) // TDD
538 {
539 // Change the antenna orientation
540 Ptr<NrGnbPhy> phy = nrHelper->GetGnbPhy(gnb, 0);
541 Ptr<UniformPlanarArray> antenna =
542 DynamicCast<UniformPlanarArray>(phy->GetSpectrumPhy()->GetAntenna());
543 antenna->SetAttribute("BearingAngle", DoubleValue(orientationRads));
544 // Set TDD pattern
545 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Pattern",
546 StringValue("F|F|F|F|F|F|F|F|F|F|"));
547 }
548
549 else if (numBwps == 2) // FDD
550 {
551 // Change the antenna orientation
552 Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0);
553 Ptr<UniformPlanarArray> antenna0 =
554 DynamicCast<UniformPlanarArray>(phy0->GetSpectrumPhy()->GetAntenna());
555 antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
556 Ptr<NrGnbPhy> phy1 = nrHelper->GetGnbPhy(gnb, 1);
557 Ptr<UniformPlanarArray> antenna1 =
558 DynamicCast<UniformPlanarArray>(phy1->GetSpectrumPhy()->GetAntenna());
559 antenna1->SetAttribute("BearingAngle", DoubleValue(orientationRads));
560 // Set TDD pattern
561 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute(
562 "Pattern",
563 StringValue("DL|DL|DL|DL|DL|DL|DL|DL|DL|DL|"));
564 nrHelper->GetGnbPhy(gnb, 1)->SetAttribute(
565 "Pattern",
566 StringValue("UL|UL|UL|UL|UL|UL|UL|UL|UL|UL|"));
567 // Link the two FDD BWP
568 nrHelper->GetBwpManagerGnb(gnb)->SetOutputLink(1, 0);
569 }
570
571 else
572 {
573 NS_ABORT_MSG("Incorrect number of BWPs per CC");
574 }
575 }
576
577 // Set the UE routing:
578
579 if (operationMode == "FDD")
580 {
581 for (uint32_t i = 0; i < ueSector1NetDev.GetN(); i++)
582 {
583 nrHelper->GetBwpManagerUe(ueSector1NetDev.Get(i))->SetOutputLink(0, 1);
584 }
585
586 for (uint32_t i = 0; i < ueSector2NetDev.GetN(); i++)
587 {
588 nrHelper->GetBwpManagerUe(ueSector2NetDev.Get(i))->SetOutputLink(0, 1);
589 }
590
591 for (uint32_t i = 0; i < ueSector3NetDev.GetN(); i++)
592 {
593 nrHelper->GetBwpManagerUe(ueSector3NetDev.Get(i))->SetOutputLink(0, 1);
594 }
595 }
596
597 // When all the configuration is done, explicitly call UpdateConfig ()
598
599 for (auto it = gnbSector1NetDev.Begin(); it != gnbSector1NetDev.End(); ++it)
600 {
601 DynamicCast<NrGnbNetDevice>(*it)->UpdateConfig();
602 }
603 for (auto it = gnbSector2NetDev.Begin(); it != gnbSector2NetDev.End(); ++it)
604 {
605 DynamicCast<NrGnbNetDevice>(*it)->UpdateConfig();
606 }
607 for (auto it = gnbSector3NetDev.Begin(); it != gnbSector3NetDev.End(); ++it)
608 {
609 DynamicCast<NrGnbNetDevice>(*it)->UpdateConfig();
610 }
611 for (auto it = ueSector1NetDev.Begin(); it != ueSector1NetDev.End(); ++it)
612 {
613 DynamicCast<NrUeNetDevice>(*it)->UpdateConfig();
614 }
615 for (auto it = ueSector2NetDev.Begin(); it != ueSector2NetDev.End(); ++it)
616 {
617 DynamicCast<NrUeNetDevice>(*it)->UpdateConfig();
618 }
619 for (auto it = ueSector3NetDev.Begin(); it != ueSector3NetDev.End(); ++it)
620 {
621 DynamicCast<NrUeNetDevice>(*it)->UpdateConfig();
622 }
623}
624
625enum TrafficTypeConf
626{
627 UDP_CBR, // 0
628 FTP_3GPP_M1, // 1
629 NGMN_FTP, // 2
630 NGMN_VIDEO, // 3
631 NGMN_HTTP, // 4
632 NGMN_GAMING, // 5
633 NGMN_VOIP, // 6
634 NGMN_MIXED // 7
635};
636
643static inline std::ostream&
644operator<<(std::ostream& os, const TrafficTypeConf& item)
645{
646 switch (item)
647 {
648 case UDP_CBR:
649 os << "UDP CBR";
650 break;
651 case FTP_3GPP_M1:
652 os << "FTP 3GPP M1";
653 break;
654 case NGMN_FTP:
655 os << "NGMN FTP";
656 break;
657 case NGMN_VIDEO:
658 os << "NGMN VIDEO";
659 break;
660 case NGMN_HTTP:
661 os << "NGMN HTTP";
662 break;
663 case NGMN_GAMING:
664 os << "NGMN GAMING";
665 break;
666 case NGMN_VOIP:
667 os << "NGMN VOIP";
668 break;
669 case NGMN_MIXED:
670 os << "NGMN MIXED";
671 break;
672 default:
673 NS_ABORT_MSG("Unknown traffic type");
674 }
675 return os;
676}
677
678static inline std::istream&
679operator>>(std::istream& is, TrafficTypeConf& item)
680{
681 uint32_t inputValue;
682 is >> inputValue;
683 item = (TrafficTypeConf)inputValue;
684 return is;
685}
686
687int
688main(int argc, char* argv[])
689{
690 /*
691 * Variables that represent the parameters we will accept as input by the
692 * command line. Each of them is initialized with a default value.
693 */
694
695 TrafficTypeConf trafficTypeConf = FTP_3GPP_M1;
696 // Traffic parameters (that we will use inside this script:)
697 uint32_t udpPacketSize = 600; // bytes
698 // 4000*600*8 = 19.2 Mbps/UE,
699 // 3000*600*8 = 14.4 Mbps/UE,
700 // 2000*600*8 = 9.6 Mbps/UE
701 // 1500*600*8 = 7.2 Mbps/UE
702 // 1000*600*8 = 4.8 Mbps/UE
703 uint32_t udpLambda = 2000;
704 double ftpM1Lambda = 5;
705 uint32_t ftpM1FileSize = 512000; // in bytes
706 Time clientAppStartTime = MilliSeconds(400);
707 Time serverAppStartTime = MilliSeconds(400);
708 // Simulation parameters. Please don't use double to indicate seconds, use
709 // milliseconds and integers to avoid representation errors.
710 uint32_t simTimeMs = 1400;
711 Time appStartTime = MilliSeconds(400);
712 std::string direction = "DL";
713 bool uniformLambda = true;
714
715 // topology
716 uint16_t numOuterRings = 0;
717 uint16_t uesPerGnb = 10;
718 std::string scenario = "UMi";
719 std::string radioNetwork = "NR"; // LTE or NR
720 std::string operationMode = "TDD"; // TDD or FDD
721
722 // Where we will store the output files.
723 std::string simTag = "default";
724 std::string outputDir = "./";
725 bool logging = false;
726 bool traces = true;
727 bool useUdp = true;
728
729 uint8_t ngmnMixedFtpPercentage = 10;
730 uint8_t ngmnMixedHttpPercentage = 20;
731 uint8_t ngmnMixedVideoPercentage = 20;
732 uint8_t ngmnMixedVoipPercentage = 30;
733 uint8_t ngmnMixedGamingPercentage = 20;
734
735 /*
736 * From here, we instruct the ns3::CommandLine class of all the input parameters
737 * that we may accept as input, as well as their description, and the storage
738 * variable.
739 */
740 CommandLine cmd(__FILE__);
741
742 cmd.AddValue("trafficTypeConf",
743 "The traffic type to be configured. Currently the following options are "
744 "available: 0 - UDP CBR, 1 - FTP Model 1, 2 - NGMN FTP, 3 - NGMN VIDEO, 4 - HTTP, "
745 "5-NGMN GAMING, 6 - NGMN VOIP, 7 - NGMN MIXED (e.g., "
746 "10% FTP, 20% HTTP, 20% VIDEO STREAMING, 30% VoIP, 20% GAMING)",
747 trafficTypeConf);
748 cmd.AddValue(
749 "ngmnMixedFtpPercentage",
750 "If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
751 "percentage of the FTP traffic. Percentage should be multiply of 10.",
752 ngmnMixedFtpPercentage);
753 cmd.AddValue(
754 "ngmnMixedHttpPercentage",
755 "If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
756 "percentage of the HTTP traffic. Percentage should be multiply of 10.",
757 ngmnMixedHttpPercentage);
758 cmd.AddValue(
759 "ngmnMixedVideoPercentage",
760 "If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
761 "percentage of the VIDEO traffic. Percentage should be multiply of 10.",
762 ngmnMixedVideoPercentage);
763 cmd.AddValue(
764 "ngmnMixedVoipPercentage",
765 "If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
766 "percentage of the VoIP traffic. Percentage should be multiply of 10.",
767 ngmnMixedVoipPercentage);
768 cmd.AddValue(
769 "ngmnMixedGamingPercentage",
770 "If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
771 "percentage of the GAMING traffic. Percentage should be multiply of 10.",
772 ngmnMixedGamingPercentage);
773 cmd.AddValue("useUdp",
774 "if true, the NGMN applications will run over UDP connection, otherwise a TCP "
775 "connection will be used. "
776 "Notice that HTTP application as it is present in ns-3 simulator is implemented "
777 "as typical HTTP application, i.e., "
778 "based on the TCP protocol and as such cannot be reconfigured to use UDP.",
779 useUdp);
780 cmd.AddValue("ftpM1Lambda",
781 "The lambda to be used for FTP M1 traffic model (Typical values are 2.5, 5). ",
782 ftpM1Lambda);
783 cmd.AddValue("udpLambda", "Number of UDP packets generated in one second per UE", udpLambda);
784 cmd.AddValue("uniformLambda",
785 "1: Use same lambda (packets/s) for all UEs and cells (equal to 'lambda' input), "
786 "0: use different packet arrival rates (lambdas) among cells",
787 uniformLambda);
788 cmd.AddValue("scenario", "The urban scenario string (UMa or UMi)", scenario);
789 cmd.AddValue("numRings", "The number of rings around the central site", numOuterRings);
790 cmd.AddValue("uesPerGnb",
791 "The number of UE per gNB, should be multiply of 10 so that the mixed traffic "
792 "works correctly.",
793 uesPerGnb);
794 cmd.AddValue("logging", "Enable logging", logging);
795 cmd.AddValue("traces", "Enable output traces", traces);
796 cmd.AddValue("packetSize", "packet size in bytes to be used by UE traffic", udpPacketSize);
797 cmd.AddValue("simTimeMs", "Simulation time", simTimeMs);
798 cmd.AddValue("direction", "The flow direction (DL or UL)", direction);
799 cmd.AddValue("technology", "The radio access network technology", radioNetwork);
800 cmd.AddValue("operationMode", "The network operation mode can be TDD or FDD", operationMode);
801 cmd.AddValue("simTag",
802 "tag to be appended to output filenames to distinguish simulation campaigns",
803 simTag);
804 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
805
806 // Parse the command line
807 cmd.Parse(argc, argv);
808
809 /*
810 * Check if the parameter values provided by the user are correct.
811 */
812 // NS_ABORT_IF (centralFrequencyBand > 100e9);]
813 NS_ABORT_MSG_IF(
814 trafficTypeConf > 7,
815 "Currently only supported values for traffic type are 0, 1, 2. Meaning: 0 -UDP CBR, 1 - "
816 "FTP Model 1, 2 - NGMN FTP, 3 - NGMN VIDEO, 4- HTTP, 5- NGMN GAMING, 6 - VOIP, 7 - NGMN "
817 "MIXED (e.g., 10% FTP, 20% HTTP, 20% VIDEO STREAMING, 30% VoIP, 20% GAMING");
818 NS_ABORT_MSG_IF(direction != "DL" && direction != "UL", "Flow direction can only be DL or UL");
819 NS_ABORT_MSG_IF(operationMode != "TDD" && operationMode != "FDD",
820 "Operation mode can only be TDD or FDD");
821 NS_ABORT_MSG_IF(radioNetwork != "LTE" && radioNetwork != "NR",
822 "Unrecognized radio network technology");
823
824 NS_ABORT_MSG_IF(
825 trafficTypeConf == 7 &&
826 (ngmnMixedFtpPercentage + ngmnMixedHttpPercentage + ngmnMixedVideoPercentage +
827 ngmnMixedVoipPercentage + ngmnMixedGamingPercentage) != 100,
828 "If trafficTypeConf selected is the NGMN mixed, then the sum of the percentages of FTP, "
829 "VOIP, HTTP, VIDEO STREAMING and GAMING traffic should give 100.");
830 /*
831 * If the logging variable is set to true, enable the log of some components
832 * through the code. The same effect can be obtained through the use
833 * of the NS_LOG environment variable:
834 *
835 * export NS_LOG="UdpClient=level_info|prefix_time|prefix_func|prefix_node:UdpServer=..."
836 *
837 * Usually, the environment variable way is preferred, as it is more customizable,
838 * and more expressive.
839 */
840 if (logging)
841 {
842 LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
843 LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
844 // LogComponentEnable ("NrMacSchedulerOfdma", LOG_LEVEL_ALL);
845 }
846
847 // configure the transport protocol to be used
848 std::string transportProtocol;
849 if (useUdp)
850 {
851 transportProtocol = "ns3::UdpSocketFactory";
852 }
853 else
854 {
855 transportProtocol = "ns3::TcpSocketFactory";
856 }
857
858 Time simTime = MilliSeconds(simTimeMs);
859
860 std::cout << "\n Traffic configuration selected is: " << trafficTypeConf << std::endl;
861
862 /*
863 * Create the scenario. In our examples, we heavily use helpers that setup
864 * the gnbs and ue following a pre-defined pattern. Please have a look at the
865 * GridScenarioHelper documentation to see how the nodes will be distributed.
866 */
867 HexagonalGridScenarioHelper gridScenario;
868 gridScenario.SetSectorization(HexagonalGridScenarioHelper::TRIPLE);
869 gridScenario.SetNumRings(numOuterRings);
870 gridScenario.SetScenarioParameters(scenario);
871 uint16_t gNbNum = gridScenario.GetNumCells();
872 std::cout << " GNB num: " << gNbNum << std::endl;
873 uint32_t ueNum = uesPerGnb * gNbNum;
874 std::cout << " UE num: " << ueNum << std::endl;
875 gridScenario.SetUtNumber(ueNum);
876 gridScenario.AssignStreams(RngSeedManager::GetRun());
877 gridScenario.CreateScenario();
878 const uint16_t ffr =
879 3; // Fractional Frequency Reuse scheme to mitigate intra-site inter-sector interferences
880
881 /*
882 * Create different gNB NodeContainer for the different sectors.
883 */
884 NodeContainer gnbSector1Container;
885 NodeContainer gnbSector2Container;
886 NodeContainer gnbSector3Container;
887 for (uint32_t j = 0; j < gridScenario.GetBaseStations().GetN(); ++j)
888 {
889 Ptr<Node> gnb = gridScenario.GetBaseStations().Get(j);
890 switch (j % ffr)
891 {
892 case 0:
893 gnbSector1Container.Add(gnb);
894 break;
895 case 1:
896 gnbSector2Container.Add(gnb);
897 break;
898 case 2:
899 gnbSector3Container.Add(gnb);
900 break;
901 default:
902 NS_ABORT_MSG("ffr param cannot be larger than 3");
903 break;
904 }
905 }
906
907 /*
908 * Create different UE NodeContainer for the different sectors.
909 */
910 NodeContainer ueSector1Container;
911 NodeContainer ueSector2Container;
912 NodeContainer ueSector3Container;
913
914 for (uint32_t j = 0; j < gridScenario.GetUserTerminals().GetN(); ++j)
915 {
916 Ptr<Node> ue = gridScenario.GetUserTerminals().Get(j);
917 switch (j % ffr)
918 {
919 case 0:
920 ueSector1Container.Add(ue);
921 break;
922 case 1:
923 ueSector2Container.Add(ue);
924 break;
925 case 2:
926 ueSector3Container.Add(ue);
927 break;
928 default:
929 NS_ABORT_MSG("ffr param cannot be larger than 3");
930 break;
931 }
932 }
933
934 /*
935 * Setup the 5G-LENA scenario
936 */
937 Ptr<PointToPointEpcHelper> epcHelper;
938
939 NetDeviceContainer gnbSector1NetDev;
940 NetDeviceContainer gnbSector2NetDev;
941 NetDeviceContainer gnbSector3NetDev;
942 NetDeviceContainer ueSector1NetDev;
943 NetDeviceContainer ueSector2NetDev;
944 NetDeviceContainer ueSector3NetDev;
945
946 Ptr<NrHelper> nrHelper = nullptr;
947
948 epcHelper = CreateObject<NrPointToPointEpcHelper>();
949 Set5gLenaSimulatorParameters(gridScenario,
950 scenario,
951 radioNetwork,
952 operationMode,
953 direction,
954 gnbSector1Container,
955 gnbSector2Container,
956 gnbSector3Container,
957 ueSector1Container,
958 ueSector2Container,
959 ueSector3Container,
960 epcHelper,
961 nrHelper,
962 gnbSector1NetDev,
963 gnbSector2NetDev,
964 gnbSector3NetDev,
965 ueSector1NetDev,
966 ueSector2NetDev,
967 ueSector3NetDev,
968 uniformLambda);
969
970 // From here, it is standard NS3. In the future, we will create helpers
971 // for this part as well.
972
973 // create the internet and install the IP stack on the UEs
974 // get SGW/PGW and create a single RemoteHost
975 Ptr<Node> pgw = epcHelper->GetPgwNode();
976 NodeContainer remoteHostContainer;
977 remoteHostContainer.Create(1);
978 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
979 InternetStackHelper internet;
980 internet.Install(remoteHostContainer);
981
982 // connect a remoteHost to pgw. Setup routing too
983 PointToPointHelper p2ph;
984 p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
985 p2ph.SetDeviceAttribute("Mtu", UintegerValue(2500));
986 p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.000)));
987 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
988 Ipv4AddressHelper ipv4h;
989 Ipv4StaticRoutingHelper ipv4RoutingHelper;
990 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
991 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
992 Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
993 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
994 remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
995 internet.Install(gridScenario.GetUserTerminals());
996
997 // if the mixed traffic type selected then determine for each which container IDs correposnd to
998 // each traffic type
999
1000 std::set<uint16_t> ngmnFtpIds;
1001 std::set<uint16_t> ngmnVideoIds;
1002 std::set<uint16_t> ngmnVoipIds;
1003 std::set<uint16_t> ngmnHttpIds;
1004 std::set<uint16_t> ngmnGamingIds;
1005
1006 // configure indexes of UEs per traffic type
1007
1008 if (trafficTypeConf == NGMN_MIXED)
1009 {
1010 // check if there is enough UEs to configure NGMN_MIXED traffic type
1011 NS_ABORT_MSG_UNLESS((ueSector1NetDev.GetN() % 10) == 0,
1012 "The number of UEs per sector must be mupliply of 10 when NGMN MIXED "
1013 "traffic configured");
1014
1015 std::cout << "\n ueSector1NetDev:" << ueSector1NetDev.GetN() / 10 << std::endl;
1016 NS_ABORT_MSG_UNLESS((ueSector1NetDev.GetN() / 10) >= 1,
1017 "The number of UEs per sector must be at least 10 when NGMN MIXED "
1018 "traffic is configured");
1019
1020 uint16_t ftp = (ueSector1NetDev.GetN() / 10) * ngmnMixedFtpPercentage / 10;
1021 uint16_t http = (ueSector1NetDev.GetN() / 10) * ngmnMixedHttpPercentage / 10;
1022 uint16_t video = (ueSector1NetDev.GetN() / 10) * ngmnMixedVideoPercentage / 10;
1023 uint16_t voip = (ueSector1NetDev.GetN() / 10) * ngmnMixedVoipPercentage / 10;
1024 uint16_t gaming = (ueSector1NetDev.GetN() / 10) * ngmnMixedGamingPercentage / 10;
1025 uint16_t index = 0;
1026
1027 std::cout << "\n Each sector has:" << std::endl;
1028 std::cout << ftp << " UEs with NGMN FTP traffic" << std::endl;
1029 std::cout << http << " UEs with NGMN HTTP traffic" << std::endl;
1030 std::cout << video << " UEs with NGMN VIDEO traffic" << std::endl;
1031 std::cout << voip << " UEs with NGMN VOIP traffic" << std::endl;
1032 std::cout << gaming << " UEs with NGMN GAMING traffic" << std::endl;
1033
1034 for (uint16_t i = 0; i < ftp; i++)
1035 {
1036 ngmnFtpIds.insert(index++);
1037 }
1038
1039 for (uint16_t i = 0; i < http; i++)
1040 {
1041 ngmnHttpIds.insert(index++);
1042 }
1043
1044 for (uint16_t i = 0; i < video; i++)
1045 {
1046 ngmnVideoIds.insert(index++);
1047 }
1048
1049 for (uint16_t i = 0; i < voip; i++)
1050 {
1051 ngmnVoipIds.insert(index++);
1052 }
1053
1054 for (uint16_t i = 0; i < gaming; i++)
1055 {
1056 ngmnGamingIds.insert(index++);
1057 }
1058 }
1059
1060 Ipv4InterfaceContainer ueSector1IpIface =
1061 epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueSector1NetDev));
1062 Ipv4InterfaceContainer ueSector2IpIface =
1063 epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueSector2NetDev));
1064 Ipv4InterfaceContainer ueSector3IpIface =
1065 epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueSector3NetDev));
1066
1067 Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress(1);
1068
1069 // Set the default gateway for the UEs
1070 for (uint32_t j = 0; j < gridScenario.GetUserTerminals().GetN(); ++j)
1071 {
1072 Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting(
1073 gridScenario.GetUserTerminals().Get(j)->GetObject<Ipv4>());
1074 ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
1075 }
1076
1077 // attach UEs to their gNB. Try to attach them per cellId order
1078 for (uint32_t u = 0; u < ueNum; ++u)
1079 {
1080 uint32_t sector = u % ffr;
1081 uint32_t i = u / ffr;
1082 if (sector == 0)
1083 {
1084 Ptr<NetDevice> gnbNetDev = gnbSector1NetDev.Get(i % gridScenario.GetNumSites());
1085 Ptr<NetDevice> ueNetDev = ueSector1NetDev.Get(i);
1086
1087 nrHelper->AttachToEnb(ueNetDev, gnbNetDev);
1088
1089 if (logging)
1090 {
1091 Vector gnbpos = gnbNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
1092 Vector uepos = ueNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
1093 double distance = CalculateDistance(gnbpos, uepos);
1094 std::cout << "Distance = " << distance << " meters" << std::endl;
1095 }
1096 }
1097 else if (sector == 1)
1098 {
1099 Ptr<NetDevice> gnbNetDev = gnbSector2NetDev.Get(i % gridScenario.GetNumSites());
1100 Ptr<NetDevice> ueNetDev = ueSector2NetDev.Get(i);
1101 nrHelper->AttachToEnb(ueNetDev, gnbNetDev);
1102 if (logging)
1103 {
1104 Vector gnbpos = gnbNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
1105 Vector uepos = ueNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
1106 double distance = CalculateDistance(gnbpos, uepos);
1107 std::cout << "Distance = " << distance << " meters" << std::endl;
1108 }
1109 }
1110 else if (sector == 2)
1111 {
1112 Ptr<NetDevice> gnbNetDev = gnbSector3NetDev.Get(i % gridScenario.GetNumSites());
1113 Ptr<NetDevice> ueNetDev = ueSector3NetDev.Get(i);
1114 nrHelper->AttachToEnb(ueNetDev, gnbNetDev);
1115 if (logging)
1116 {
1117 Vector gnbpos = gnbNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
1118 Vector uepos = ueNetDev->GetNode()->GetObject<MobilityModel>()->GetPosition();
1119 double distance = CalculateDistance(gnbpos, uepos);
1120 std::cout << "Distance = " << distance << " meters" << std::endl;
1121 }
1122 }
1123 else
1124 {
1125 NS_ABORT_MSG("Number of sector cannot be larger than 3");
1126 }
1127 }
1128
1129 /*
1130 * Traffic part. Install two kind of traffic: low-latency and voice, each
1131 * identified by a particular source port.
1132 */
1133 uint16_t dlPortLowLat = 1234;
1134
1135 ApplicationContainer serverApps;
1136
1137 // The sink will always listen to the specified ports
1138 UdpServerHelper dlPacketSinkLowLat(dlPortLowLat);
1139
1140 // The server, that is the application which is listening, is installed in the UE
1141 if (direction == "DL")
1142 {
1143 serverApps.Add(dlPacketSinkLowLat.Install(
1144 {ueSector1Container, ueSector2Container, ueSector3Container}));
1145 }
1146 else
1147 {
1148 serverApps.Add(dlPacketSinkLowLat.Install(remoteHost));
1149 }
1150
1151 /*
1152 * Configure attributes for the different generators, using user-provided
1153 * parameters for generating a CBR traffic
1154 *
1155 * Low-Latency configuration and object creation:
1156 */
1157 UdpClientHelper dlClientLowLat;
1158 dlClientLowLat.SetAttribute("RemotePort", UintegerValue(dlPortLowLat));
1159 dlClientLowLat.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
1160 dlClientLowLat.SetAttribute("PacketSize", UintegerValue(udpPacketSize));
1161 // dlClientLowLat.SetAttribute ("Interval", TimeValue (Seconds (1.0/lambda)));
1162
1163 // The bearer that will carry low latency traffic
1164 EpsBearer lowLatBearer(EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
1165
1166 // The filter for the low-latency traffic
1167 Ptr<EpcTft> lowLatTft = Create<EpcTft>();
1168 EpcTft::PacketFilter dlpfLowLat;
1169 if (direction == "DL")
1170 {
1171 dlpfLowLat.localPortStart = dlPortLowLat;
1172 dlpfLowLat.localPortEnd = dlPortLowLat;
1173 dlpfLowLat.direction = EpcTft::DOWNLINK;
1174 }
1175 else
1176 {
1177 dlpfLowLat.remotePortStart = dlPortLowLat;
1178 dlpfLowLat.remotePortEnd = dlPortLowLat;
1179 dlpfLowLat.direction = EpcTft::UPLINK;
1180 }
1181 lowLatTft->Add(dlpfLowLat);
1182
1183 std::vector<uint32_t> lambdaPerCell(gridScenario.GetNumCells());
1184
1185 if (trafficTypeConf == UDP_CBR)
1186 {
1187 if (uniformLambda)
1188 {
1189 for (uint32_t bs = 0; bs < gridScenario.GetNumCells(); ++bs)
1190 {
1191 lambdaPerCell[bs] = udpLambda;
1192 std::cout << "Cell: " << bs << " lambda (same lambda): " << lambdaPerCell[bs]
1193 << std::endl;
1194 }
1195 }
1196 else // non-uniform lambda values among the cells!
1197 {
1198 for (uint32_t bs = 0; bs < gridScenario.GetNumCells(); ++bs)
1199 {
1200 lambdaPerCell[bs] = 1000 + bs * 2000;
1201 std::cout << "Cell: " << bs << " lambda (diff lambda): " << lambdaPerCell[bs]
1202 << std::endl;
1203 }
1204 }
1205 }
1206
1207 /*
1208 * Let's install the applications!
1209 */
1210 ApplicationContainer clientApps;
1211 ApplicationContainer ftpClientAppsSector1;
1212 ApplicationContainer ftpServerAppsSector1;
1213 ApplicationContainer ftpClientAppsSector2;
1214 ApplicationContainer ftpServerAppsSector2;
1215 ApplicationContainer ftpClientAppsSector3;
1216 ApplicationContainer ftpServerAppsSector3;
1217 Ptr<ThreeGppFtpM1Helper> ftpHelperSector1;
1218 Ptr<ThreeGppFtpM1Helper> ftpHelperSector2;
1219 Ptr<ThreeGppFtpM1Helper> ftpHelperSector3;
1220 uint32_t port1 = 2001;
1221 uint32_t port2 = 2002;
1222 uint32_t port3 = 2003;
1223 // Seed the ARP cache by pinging early in the simulation
1224 // This is a workaround until a static ARP capability is provided
1225 ApplicationContainer pingApps;
1226
1227 if (trafficTypeConf == FTP_3GPP_M1)
1228 {
1229 // sector 1 FTP M1 applications configuration
1230 ftpHelperSector1 = CreateObject<ThreeGppFtpM1Helper>(&ftpServerAppsSector1,
1231 &ftpClientAppsSector1,
1232 &ueSector1Container,
1233 &remoteHostContainer,
1234 &ueSector1IpIface);
1235 ftpHelperSector1->Configure(port1,
1236 serverAppStartTime,
1237 clientAppStartTime,
1238 simTime,
1239 ftpM1Lambda,
1240 ftpM1FileSize);
1241 ftpHelperSector1->Start();
1242
1243 // sector 2 FTP M1 applications configuration
1244 ftpHelperSector2 = CreateObject<ThreeGppFtpM1Helper>(&ftpServerAppsSector2,
1245 &ftpClientAppsSector2,
1246 &ueSector2Container,
1247 &remoteHostContainer,
1248 &ueSector2IpIface);
1249 ftpHelperSector2->Configure(port2,
1250 serverAppStartTime,
1251 clientAppStartTime,
1252 simTime,
1253 ftpM1Lambda,
1254 ftpM1FileSize);
1255 ftpHelperSector2->Start();
1256
1257 // sector 3 FTP M1 applications configuration
1258 ftpHelperSector3 = CreateObject<ThreeGppFtpM1Helper>(&ftpServerAppsSector3,
1259 &ftpClientAppsSector3,
1260 &ueSector3Container,
1261 &remoteHostContainer,
1262 &ueSector3IpIface);
1263 ftpHelperSector3->Configure(port3,
1264 serverAppStartTime,
1265 clientAppStartTime,
1266 simTime,
1267 ftpM1Lambda,
1268 ftpM1FileSize);
1269 ftpHelperSector3->Start();
1270
1271 clientApps.Add(ftpClientAppsSector1);
1272 clientApps.Add(ftpClientAppsSector2);
1273 clientApps.Add(ftpClientAppsSector3);
1274
1275 serverApps.Add(ftpServerAppsSector1);
1276 serverApps.Add(ftpServerAppsSector2);
1277 serverApps.Add(ftpServerAppsSector3);
1278 }
1279
1280 if (trafficTypeConf == NGMN_FTP || (trafficTypeConf == NGMN_MIXED && !ngmnFtpIds.empty()))
1281 {
1282 uint32_t portFtpNgmn = 2000;
1283
1284 if (direction == "DL")
1285 {
1286 // configure FTP clients with file transfer application that generates multiple file
1287 // transfers
1288 TrafficGeneratorHelper ftpHelper(transportProtocol,
1289 Address(),
1291 ftpHelper.SetAttribute("PacketSize", UintegerValue(1448));
1292 ftpHelper.SetAttribute("MaxFileSize", UintegerValue(5e6));
1293
1294 // configure clients on sector 1
1295 for (uint32_t i = 0; i < ueSector1IpIface.GetN(); i++)
1296 {
1297 // in case of NGMN traffic allow installation of the specific traffic type only on
1298 // the specific nodes
1299 if ((trafficTypeConf == NGMN_MIXED) and (ngmnFtpIds.find(i) == ngmnFtpIds.end()))
1300 {
1301 continue;
1302 }
1303
1304 Ipv4Address ipAddress = ueSector1IpIface.GetAddress(i, 0);
1305 AddressValue ueAddress(InetSocketAddress(ipAddress, portFtpNgmn));
1306 ftpHelper.SetAttribute("Remote", ueAddress);
1307 clientApps.Add(ftpHelper.Install(remoteHostContainer));
1308 // Seed the ARP cache by pinging early in the simulation
1309 // This is a workaround until a static ARP capability is provided
1310 PingHelper ping(ipAddress);
1311 pingApps.Add(ping.Install(remoteHostContainer));
1312 }
1313 // configure clients on sector 2
1314 for (uint32_t i = 0; i < ueSector2IpIface.GetN(); i++)
1315 {
1316 // in case of NGMN traffic allow installation of the specific traffic type only on
1317 // the specific nodes
1318 if ((trafficTypeConf == NGMN_MIXED) and (ngmnFtpIds.find(i) == ngmnFtpIds.end()))
1319 {
1320 continue;
1321 }
1322 Ipv4Address ipAddress = ueSector2IpIface.GetAddress(i, 0);
1323 AddressValue ueAddress(InetSocketAddress(ipAddress, portFtpNgmn));
1324 ftpHelper.SetAttribute("Remote", ueAddress);
1325 clientApps.Add(ftpHelper.Install(remoteHostContainer));
1326 // Seed the ARP cache by pinging early in the simulation
1327 // This is a workaround until a static ARP capability is provided
1328 PingHelper ping(ipAddress);
1329 pingApps.Add(ping.Install(remoteHostContainer));
1330 }
1331 // configure clients on sector 3
1332 for (uint32_t i = 0; i < ueSector3IpIface.GetN(); i++)
1333 {
1334 // in case of NGMN traffic allow installation of the specific traffic type only on
1335 // the specific nodes
1336 if ((trafficTypeConf == NGMN_MIXED) and (ngmnFtpIds.find(i) == ngmnFtpIds.end()))
1337 {
1338 continue;
1339 }
1340
1341 Ipv4Address ipAddress = ueSector3IpIface.GetAddress(i, 0);
1342 AddressValue ueAddress(InetSocketAddress(ipAddress, portFtpNgmn));
1343 ftpHelper.SetAttribute("Remote", ueAddress);
1344 clientApps.Add(ftpHelper.Install(remoteHostContainer));
1345 // Seed the ARP cache by pinging early in the simulation
1346 // This is a workaround until a static ARP capability is provided
1347 PingHelper ping(ipAddress);
1348 pingApps.Add(ping.Install(remoteHostContainer));
1349 }
1350
1351 // configure FTP servers
1352 InetSocketAddress localAddress(Ipv4Address::GetAny(), portFtpNgmn);
1353 PacketSinkHelper packetSinkHelper(transportProtocol, localAddress);
1354
1355 for (uint32_t index = 0; index < ueSector1IpIface.GetN(); index++)
1356 {
1357 // in case of NGMN traffic we install packet sink for the subset of the nodes
1358 if ((trafficTypeConf == NGMN_MIXED) and
1359 (ngmnFtpIds.find(index) == ngmnFtpIds.end()))
1360 {
1361 continue;
1362 }
1363 serverApps.Add(packetSinkHelper.Install(ueSector1Container.Get(index)));
1364 serverApps.Add(packetSinkHelper.Install(ueSector2Container.Get(index)));
1365 serverApps.Add(packetSinkHelper.Install(ueSector3Container.Get(index)));
1366 }
1367 }
1368 else
1369 {
1370 NS_ABORT_MSG("Not yet supported option of FTP NGMN traffic with the UL traffic in this "
1371 "example. If you need it implement this else block");
1372 }
1373 }
1374
1375 if (trafficTypeConf == NGMN_VIDEO || (trafficTypeConf == NGMN_MIXED && !ngmnVideoIds.empty()))
1376 {
1377 uint32_t portNgmnVideo = 4000;
1378
1379 if (direction == "DL")
1380 {
1381 // configure FTP clients with file transfer application that generates multiple file
1382 // transfers
1383 TrafficGeneratorHelper trafficGeneratorHelper(transportProtocol,
1384 Address(),
1386 trafficGeneratorHelper.SetAttribute("NumberOfPacketsInFrame", UintegerValue(8));
1387 trafficGeneratorHelper.SetAttribute("InterframeIntervalTime",
1388 TimeValue(Seconds(0.100)));
1389
1390 // configure clients on sector 1
1391 for (uint32_t i = 0; i < ueSector1IpIface.GetN(); i++)
1392 {
1393 // in case of NGMN traffic allow installation of the specific traffic type only on
1394 // the specific nodes
1395 if ((trafficTypeConf == NGMN_MIXED) and
1396 (ngmnVideoIds.find(i) == ngmnVideoIds.end()))
1397 {
1398 continue;
1399 }
1400
1401 Ipv4Address ipAddress = ueSector1IpIface.GetAddress(i, 0);
1402 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnVideo));
1403 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1404 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1405 // Seed the ARP cache by pinging early in the simulation
1406 // This is a workaround until a static ARP capability is provided
1407 PingHelper ping(ipAddress);
1408 pingApps.Add(ping.Install(remoteHostContainer));
1409 }
1410 // configure clients on sector 2
1411 for (uint32_t i = 0; i < ueSector2IpIface.GetN(); i++)
1412 {
1413 // in case of NGMN traffic allow installation of the specific traffic type only on
1414 // the specific nodes
1415 if ((trafficTypeConf == NGMN_MIXED) and
1416 (ngmnVideoIds.find(i) == ngmnVideoIds.end()))
1417 {
1418 continue;
1419 }
1420
1421 Ipv4Address ipAddress = ueSector2IpIface.GetAddress(i, 0);
1422 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnVideo));
1423 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1424 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1425 // Seed the ARP cache by pinging early in the simulation
1426 // This is a workaround until a static ARP capability is provided
1427 PingHelper ping(ipAddress);
1428 pingApps.Add(ping.Install(remoteHostContainer));
1429 }
1430 // configure clients on sector 3
1431 for (uint32_t i = 0; i < ueSector3IpIface.GetN(); i++)
1432 {
1433 // in case of NGMN traffic allow installation of the specific traffic type only on
1434 // the specific nodes
1435 if ((trafficTypeConf == NGMN_MIXED) and
1436 (ngmnVideoIds.find(i) == ngmnVideoIds.end()))
1437 {
1438 continue;
1439 }
1440
1441 Ipv4Address ipAddress = ueSector3IpIface.GetAddress(i, 0);
1442 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnVideo));
1443 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1444 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1445 // Seed the ARP cache by pinging early in the simulation
1446 // This is a workaround until a static ARP capability is provided
1447 PingHelper ping(ipAddress);
1448 pingApps.Add(ping.Install(remoteHostContainer));
1449 }
1450
1451 // configure servers
1452 InetSocketAddress localAddress(Ipv4Address::GetAny(), portNgmnVideo);
1453 PacketSinkHelper packetSinkHelper(transportProtocol, localAddress);
1454
1455 for (uint32_t index = 0; index < ueSector1IpIface.GetN(); index++)
1456 {
1457 // in case of NGMN traffic we install packet sink for the subset of the nodes
1458 if ((trafficTypeConf == NGMN_MIXED) and
1459 (ngmnVideoIds.find(index) == ngmnVideoIds.end()))
1460 {
1461 continue;
1462 }
1463
1464 Ptr<PacketSink> ps1 = packetSinkHelper.Install(ueSector1Container.Get(index))
1465 .Get(0)
1466 ->GetObject<PacketSink>();
1467 Ptr<PacketSink> ps2 = packetSinkHelper.Install(ueSector2Container.Get(index))
1468 .Get(0)
1469 ->GetObject<PacketSink>();
1470 Ptr<PacketSink> ps3 = packetSinkHelper.Install(ueSector3Container.Get(index))
1471 .Get(0)
1472 ->GetObject<PacketSink>();
1473 serverApps.Add(ps1);
1474 serverApps.Add(ps2);
1475 serverApps.Add(ps3);
1476 }
1477 }
1478 else
1479 {
1480 NS_ABORT_MSG("Not yet supported option of FTP NGMN traffic with the UL traffic in this "
1481 "example. If you need it implement this else block");
1482 }
1483 }
1484
1485 if (trafficTypeConf == NGMN_GAMING || (trafficTypeConf == NGMN_MIXED && !ngmnGamingIds.empty()))
1486 {
1487 uint32_t portNgmnGaming = 5000;
1488 if (direction == "DL")
1489 {
1490 // configure FTP clients with file transfer application that generates multiple file
1491 // transfers
1492 TrafficGeneratorHelper trafficGeneratorHelper(transportProtocol,
1493 Address(),
1495 trafficGeneratorHelper.SetAttribute("IsDownlink", BooleanValue(true));
1496 trafficGeneratorHelper.SetAttribute("aParamPacketSizeDl", UintegerValue(120));
1497 trafficGeneratorHelper.SetAttribute("bParamPacketSizeDl", DoubleValue(36));
1498 trafficGeneratorHelper.SetAttribute("aParamPacketArrivalDl", DoubleValue(45));
1499 trafficGeneratorHelper.SetAttribute("bParamPacketArrivalDl", DoubleValue(5.7));
1500 trafficGeneratorHelper.SetAttribute("InitialPacketArrivalMin", UintegerValue(0));
1501 trafficGeneratorHelper.SetAttribute("InitialPacketArrivalMax", UintegerValue(40));
1502
1503 // configure clients on sector 1
1504 for (uint32_t i = 0; i < ueSector1IpIface.GetN(); i++)
1505 {
1506 // in case of NGMN traffic allow installation of the specific traffic type only on
1507 // the specific nodes
1508 if ((trafficTypeConf == NGMN_MIXED) and
1509 (ngmnGamingIds.find(i) == ngmnGamingIds.end()))
1510 {
1511 continue;
1512 }
1513
1514 Ipv4Address ipAddress = ueSector1IpIface.GetAddress(i, 0);
1515 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnGaming));
1516 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1517 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1518 // Seed the ARP cache by pinging early in the simulation
1519 // This is a workaround until a static ARP capability is provided
1520 PingHelper ping(ipAddress);
1521 pingApps.Add(ping.Install(remoteHostContainer));
1522 }
1523 // configure clients on sector 2
1524 for (uint32_t i = 0; i < ueSector2IpIface.GetN(); i++)
1525 {
1526 // in case of NGMN traffic allow installation of the specific traffic type only on
1527 // the specific nodes
1528 if ((trafficTypeConf == NGMN_MIXED) and
1529 (ngmnGamingIds.find(i) == ngmnGamingIds.end()))
1530 {
1531 continue;
1532 }
1533
1534 Ipv4Address ipAddress = ueSector2IpIface.GetAddress(i, 0);
1535 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnGaming));
1536 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1537 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1538 // Seed the ARP cache by pinging early in the simulation
1539 // This is a workaround until a static ARP capability is provided
1540 PingHelper ping(ipAddress);
1541 pingApps.Add(ping.Install(remoteHostContainer));
1542 }
1543 // configure clients on sector 3
1544 for (uint32_t i = 0; i < ueSector3IpIface.GetN(); i++)
1545 {
1546 // in case of NGMN traffic allow installation of the specific traffic type only on
1547 // the specific nodes
1548 if ((trafficTypeConf == NGMN_MIXED) and
1549 (ngmnGamingIds.find(i) == ngmnGamingIds.end()))
1550 {
1551 continue;
1552 }
1553
1554 Ipv4Address ipAddress = ueSector3IpIface.GetAddress(i, 0);
1555 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnGaming));
1556 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1557 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1558 // Seed the ARP cache by pinging early in the simulation
1559 // This is a workaround until a static ARP capability is provided
1560 PingHelper ping(ipAddress);
1561 pingApps.Add(ping.Install(remoteHostContainer));
1562 }
1563
1564 // configure GAMING servers
1565 InetSocketAddress localAddress(Ipv4Address::GetAny(), portNgmnGaming);
1566 PacketSinkHelper packetSinkHelper(transportProtocol, localAddress);
1567
1568 for (uint32_t index = 0; index < ueSector1IpIface.GetN(); index++)
1569 {
1570 // in case of NGMN traffic we install packet sink for the subset of the nodes
1571 if ((trafficTypeConf == NGMN_MIXED) and
1572 (ngmnGamingIds.find(index) == ngmnGamingIds.end()))
1573 {
1574 continue;
1575 }
1576 serverApps.Add(packetSinkHelper.Install(ueSector1Container.Get(index)));
1577 serverApps.Add(packetSinkHelper.Install(ueSector2Container.Get(index)));
1578 serverApps.Add(packetSinkHelper.Install(ueSector3Container.Get(index)));
1579 }
1580 }
1581 else
1582 {
1583 NS_ABORT_MSG("Not yet supported option of FTP NGMN traffic with the UL traffic in this "
1584 "example. If you need it implement this else block");
1585
1586 // TODO extend
1587 // configure FTP clients with file transfer application that generates multiple file
1588 // transfers
1589 // TrafficGeneratorHelper trafficGeneratorHelper ("ns3::UdpSocketFactory", Address (),
1590 // TrafficGeneratorVideo::GetTypeId ()); trafficGeneratorHelper.SetAttribute
1591 // ("IsDownlink", BooleanValue (false)); trafficGeneratorHelper.SetAttribute
1592 // ("aParamPacketSizeUl", UintegerValue (45)); trafficGeneratorHelper.SetAttribute
1593 // ("bParamPacketSizeUl", DoubleValue (5.7)); trafficGeneratorHelper.SetAttribute
1594 // ("PacketArrivalUl", UintegerValue (40)); trafficGeneratorHelper.SetAttribute
1595 // ("InitialPacketArrivalMin", UintegerValue (0)); trafficGeneratorHelper.SetAttribute
1596 // ("InitialPacketArrivalMax", UintegerValue (40));
1597 }
1598 }
1599
1600 if (trafficTypeConf == NGMN_VOIP || (trafficTypeConf == NGMN_MIXED && !ngmnVoipIds.empty()))
1601 {
1602 uint32_t portNgmnVoip = 5000;
1603 if (direction == "DL")
1604 {
1605 // configure FTP clients with file transfer application that generates multiple file
1606 // transfers
1607 TrafficGeneratorHelper trafficGeneratorHelper(transportProtocol,
1608 Address(),
1610
1611 trafficGeneratorHelper.SetAttribute("EncoderFrameLength", UintegerValue(20));
1612 trafficGeneratorHelper.SetAttribute("MeanTalkSpurtDuration", UintegerValue(2000));
1613 trafficGeneratorHelper.SetAttribute("VoiceActivityFactor", DoubleValue(0.5));
1614 trafficGeneratorHelper.SetAttribute("VoicePayload", UintegerValue(40));
1615 trafficGeneratorHelper.SetAttribute("SIDPeriodicity", UintegerValue(160));
1616 trafficGeneratorHelper.SetAttribute("SIDPayload", UintegerValue(15));
1617
1618 // configure clients on sector 1
1619 for (uint32_t i = 0; i < ueSector1IpIface.GetN(); i++)
1620 {
1621 // in case of NGMN traffic allow installation of the specific traffic type only on
1622 // the specific nodes
1623 if ((trafficTypeConf == NGMN_MIXED) and (ngmnVoipIds.find(i) == ngmnVoipIds.end()))
1624 {
1625 continue;
1626 }
1627
1628 Ipv4Address ipAddress = ueSector1IpIface.GetAddress(i, 0);
1629 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnVoip));
1630 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1631 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1632 // Seed the ARP cache by pinging early in the simulation
1633 // This is a workaround until a static ARP capability is provided
1634 PingHelper ping(ipAddress);
1635 pingApps.Add(ping.Install(remoteHostContainer));
1636 }
1637 // configure clients on sector 2
1638 for (uint32_t i = 0; i < ueSector2IpIface.GetN(); i++)
1639 {
1640 // in case of NGMN traffic allow installation of the specific traffic type only on
1641 // the specific nodes
1642 if ((trafficTypeConf == NGMN_MIXED) and (ngmnVoipIds.find(i) == ngmnVoipIds.end()))
1643 {
1644 continue;
1645 }
1646
1647 Ipv4Address ipAddress = ueSector2IpIface.GetAddress(i, 0);
1648 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnVoip));
1649 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1650 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1651 // Seed the ARP cache by pinging early in the simulation
1652 // This is a workaround until a static ARP capability is provided
1653 PingHelper ping(ipAddress);
1654 pingApps.Add(ping.Install(remoteHostContainer));
1655 }
1656 // configure clients on sector 3
1657 for (uint32_t i = 0; i < ueSector3IpIface.GetN(); i++)
1658 {
1659 // in case of NGMN traffic allow installation of the specific traffic type only on
1660 // the specific nodes
1661 if ((trafficTypeConf == NGMN_MIXED) and (ngmnVoipIds.find(i) == ngmnVoipIds.end()))
1662 {
1663 continue;
1664 }
1665
1666 Ipv4Address ipAddress = ueSector3IpIface.GetAddress(i, 0);
1667 AddressValue remoteAddress(InetSocketAddress(ipAddress, portNgmnVoip));
1668 trafficGeneratorHelper.SetAttribute("Remote", remoteAddress);
1669 clientApps.Add(trafficGeneratorHelper.Install(remoteHostContainer));
1670 // Seed the ARP cache by pinging early in the simulation
1671 // This is a workaround until a static ARP capability is provided
1672 PingHelper ping(ipAddress);
1673 pingApps.Add(ping.Install(remoteHostContainer));
1674 }
1675
1676 // configure servers
1677 InetSocketAddress localAddress(Ipv4Address::GetAny(), portNgmnVoip);
1678 PacketSinkHelper packetSinkHelper(transportProtocol, localAddress);
1679
1680 for (uint32_t index = 0; index < ueSector1IpIface.GetN(); index++)
1681 {
1682 // in case of NGMN traffic we install packet sink for the subset of the nodes
1683 if ((trafficTypeConf == NGMN_MIXED) and
1684 (ngmnVoipIds.find(index) == ngmnVoipIds.end()))
1685 {
1686 continue;
1687 }
1688 serverApps.Add(packetSinkHelper.Install(ueSector1Container.Get(index)));
1689 serverApps.Add(packetSinkHelper.Install(ueSector2Container.Get(index)));
1690 serverApps.Add(packetSinkHelper.Install(ueSector3Container.Get(index)));
1691 }
1692 }
1693 else
1694 {
1695 NS_ABORT_MSG("Not yet supported option of NGMN VOIP traffic with the UL traffic in "
1696 "this example. If you need it implement this else block");
1697
1698 // TODO extend
1699 // configure FTP clients with file transfer application that generates multiple file
1700 // transfers
1701 // TrafficGeneratorHelper trafficGeneratorHelper ("ns3::UdpSocketFactory", Address (),
1702 // TrafficGeneratorVideo::GetTypeId ()); trafficGeneratorHelper.SetAttribute
1703 // ("IsDownlink", BooleanValue (false)); trafficGeneratorHelper.SetAttribute
1704 // ("aParamPacketSizeUl", UintegerValue (45)); trafficGeneratorHelper.SetAttribute
1705 // ("bParamPacketSizeUl", DoubleValue (5.7)); trafficGeneratorHelper.SetAttribute
1706 // ("PacketArrivalUl", UintegerValue (40)); trafficGeneratorHelper.SetAttribute
1707 // ("InitialPacketArrivalMin", UintegerValue (0)); trafficGeneratorHelper.SetAttribute
1708 // ("InitialPacketArrivalMax", UintegerValue (40));
1709 }
1710 }
1711
1712 if (trafficTypeConf == NGMN_HTTP || (trafficTypeConf == NGMN_MIXED && !ngmnHttpIds.empty()))
1713 {
1714 // uint32_t portNgmnHttp = 7000;
1715 // the way how ThreeGppHttpClient and ThreeGppHttpServer are implemented in ns-3
1716 // it seems that the client should be installed on UEs and server on remote host
1717
1718 NodeContainer httpUeContainer;
1719
1720 for (uint32_t i = 0; i < ueSector1Container.GetN(); i++)
1721 {
1722 // in case of NGMN traffic allow installation of the specific traffic type only on the
1723 // specific nodes
1724 if ((trafficTypeConf == NGMN_MIXED) and (ngmnHttpIds.find(i) == ngmnHttpIds.end()))
1725 {
1726 continue;
1727 }
1728 httpUeContainer.Add(ueSector1Container.Get(i));
1729 httpUeContainer.Add(ueSector2Container.Get(i));
1730 httpUeContainer.Add(ueSector3Container.Get(i));
1731 }
1732
1733 // 1. Create HTTP client applications
1734 ThreeGppHttpClientHelper clientHelper(remoteHostAddr);
1735 // Install HTTP clients on UEs
1736 ApplicationContainer clientApps = clientHelper.Install(httpUeContainer);
1737
1738 // 2. Create HTTP server applications
1739 ThreeGppHttpServerHelper serverHelper(remoteHostAddr);
1740 // Install HTTP server on a remote host node
1741 ApplicationContainer serverApps = serverHelper.Install(remoteHostContainer.Get(0));
1742 Ptr<ThreeGppHttpServer> httpServer = serverApps.Get(0)->GetObject<ThreeGppHttpServer>();
1743
1744 // 3. Setup HTTP variables for the server according to NGMN white paper
1745 PointerValue ptrVal;
1746 httpServer->GetAttribute("Variables", ptrVal);
1747 Ptr<ThreeGppHttpVariables> httpParameters = ptrVal.Get<ThreeGppHttpVariables>();
1748 httpParameters->SetMainObjectSizeMean(10710); // according to NGMN white paper
1749 httpParameters->SetMainObjectSizeStdDev(25032); // according to NGMN white paper
1750 httpParameters->SetEmbeddedObjectSizeMean(7758); // according to NGMN white paper
1751 httpParameters->SetEmbeddedObjectSizeStdDev(126168);
1752 httpParameters->SetNumOfEmbeddedObjectsMax(55); // according to NGMN white paper
1753 httpParameters->SetNumOfEmbeddedObjectsScale(2); // according to NGMN white paper
1754 httpParameters->SetNumOfEmbeddedObjectsShape(1.1); // according to NGMN white paper
1755 httpParameters->SetReadingTimeMean(Seconds(30)); // according to NGMN white paper
1756 httpParameters->SetParsingTimeMean(Seconds(0.13)); // according to NGMN white paper
1757
1758 for (uint32_t i = 0; i < ueSector1IpIface.GetN(); i++)
1759 {
1760 // in case of NGMN traffic allow installation of the specific traffic type only on the
1761 // specific nodes
1762 if ((trafficTypeConf == NGMN_MIXED) and (ngmnHttpIds.find(i) == ngmnHttpIds.end()))
1763 {
1764 continue;
1765 }
1766
1767 Ipv4Address ipAddress = ueSector1IpIface.GetAddress(i, 0);
1768 PingHelper ping(ipAddress);
1769 pingApps.Add(ping.Install(remoteHostContainer));
1770 }
1771 // configure clients on sector 2
1772 for (uint32_t i = 0; i < ueSector2IpIface.GetN(); i++)
1773 {
1774 // in case of NGMN traffic allow installation of the specific traffic type only on the
1775 // specific nodes
1776 if ((trafficTypeConf == NGMN_MIXED) and (ngmnHttpIds.find(i) == ngmnHttpIds.end()))
1777 {
1778 continue;
1779 }
1780
1781 Ipv4Address ipAddress = ueSector2IpIface.GetAddress(i, 0);
1782 PingHelper ping(ipAddress);
1783 pingApps.Add(ping.Install(remoteHostContainer));
1784 }
1785 // configure clients on sector 3
1786 for (uint32_t i = 0; i < ueSector3IpIface.GetN(); i++)
1787 {
1788 // in case of NGMN traffic allow installation of the specific traffic type only on the
1789 // specific nodes
1790 if ((trafficTypeConf == NGMN_MIXED) and (ngmnHttpIds.find(i) == ngmnHttpIds.end()))
1791 {
1792 continue;
1793 }
1794
1795 Ipv4Address ipAddress = ueSector3IpIface.GetAddress(i, 0);
1796 PingHelper ping(ipAddress);
1797 pingApps.Add(ping.Install(remoteHostContainer));
1798 }
1799 }
1800
1801 if (trafficTypeConf == UDP_CBR)
1802 {
1803 for (uint32_t i = 0; i < ueSector1Container.GetN(); ++i)
1804 {
1805 dlClientLowLat.SetAttribute(
1806 "Interval",
1807 TimeValue(Seconds(1.0 / lambdaPerCell[(i % gridScenario.GetNumSites()) *
1808 gridScenario.GetNumSectorsPerSite()])));
1809 std::cout << "ue (sector1): " << i << " index: "
1810 << (i % gridScenario.GetNumSites()) * gridScenario.GetNumSectorsPerSite()
1811 << " lambda: "
1812 << lambdaPerCell[(i % gridScenario.GetNumSites()) *
1813 gridScenario.GetNumSectorsPerSite()]
1814 << std::endl;
1815 Ptr<Node> ue = ueSector1Container.Get(i);
1816 Ptr<NetDevice> ueDevice = ueSector1NetDev.Get(i);
1817 Address ueAddress = ueSector1IpIface.GetAddress(i);
1818
1819 // The client, who is transmitting, is installed in the remote host,
1820 // with destination address set to the address of the UE
1821 if (direction == "DL")
1822 {
1823 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(ueAddress));
1824 clientApps.Add(dlClientLowLat.Install(remoteHost));
1825 }
1826 else
1827 {
1828 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(remoteHostAddr));
1829 clientApps.Add(dlClientLowLat.Install(ue));
1830 }
1831 // Activate a dedicated bearer for the traffic type
1832 nrHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
1833 }
1834
1835 for (uint32_t i = 0; i < ueSector2Container.GetN(); ++i)
1836 {
1837 dlClientLowLat.SetAttribute(
1838 "Interval",
1839 TimeValue(Seconds(1.0 / lambdaPerCell[(i % gridScenario.GetNumSites()) *
1840 gridScenario.GetNumSectorsPerSite() +
1841 1])));
1842 std::cout << "ue (sector2): " << i << " index: "
1843 << (i % gridScenario.GetNumSites()) * gridScenario.GetNumSectorsPerSite() + 1
1844 << " lambda: "
1845 << lambdaPerCell[(i % gridScenario.GetNumSites()) *
1846 gridScenario.GetNumSectorsPerSite() +
1847 1]
1848 << std::endl;
1849 Ptr<Node> ue = ueSector2Container.Get(i);
1850 Ptr<NetDevice> ueDevice = ueSector2NetDev.Get(i);
1851 Address ueAddress = ueSector2IpIface.GetAddress(i);
1852
1853 // The client, who is transmitting, is instaviso entonces pronto, sualled in the remote
1854 // host, with destination address set to the address of the UE
1855 if (direction == "DL")
1856 {
1857 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(ueAddress));
1858 clientApps.Add(dlClientLowLat.Install(remoteHost));
1859 }
1860 else
1861 {
1862 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(remoteHostAddr));
1863 clientApps.Add(dlClientLowLat.Install(ue));
1864 }
1865 // Activate a dedicated bearer for the traffic type
1866 nrHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
1867 }
1868
1869 for (uint32_t i = 0; i < ueSector3Container.GetN(); ++i)
1870 {
1871 dlClientLowLat.SetAttribute(
1872 "Interval",
1873 TimeValue(Seconds(1.0 / lambdaPerCell[(i % gridScenario.GetNumSites()) *
1874 gridScenario.GetNumSectorsPerSite() +
1875 2])));
1876 std::cout << "ue (sector3): " << i << " index: "
1877 << (i % gridScenario.GetNumSites()) * gridScenario.GetNumSectorsPerSite() + 2
1878 << " lambda: "
1879 << lambdaPerCell[(i % gridScenario.GetNumSites()) *
1880 gridScenario.GetNumSectorsPerSite() +
1881 2]
1882 << std::endl;
1883 Ptr<Node> ue = ueSector3Container.Get(i);
1884 Ptr<NetDevice> ueDevice = ueSector3NetDev.Get(i);
1885 Address ueAddress = ueSector3IpIface.GetAddress(i);
1886
1887 // The client, who is transmitting, is installed in the remote host,
1888 // with destination address set to the address of the UE
1889 if (direction == "DL")
1890 {
1891 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(ueAddress));
1892 clientApps.Add(dlClientLowLat.Install(remoteHost));
1893 }
1894 else
1895 {
1896 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(remoteHostAddr));
1897 clientApps.Add(dlClientLowLat.Install(ue));
1898 }
1899 // Activate a dedicated bearer for the traffic type
1900 nrHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
1901 }
1902 }
1903
1904 // Add one or two pings for ARP at the beginning of the simulation
1905 pingApps.Start(Seconds(0.300));
1906 pingApps.Stop(Seconds(0.500));
1907 serverApps.Start(serverAppStartTime);
1908 serverApps.Stop(simTime - MilliSeconds(400));
1909 clientApps.Start(clientAppStartTime);
1910 clientApps.Stop(simTime - MilliSeconds(400));
1911
1912 // enable the traces provided by the nr module
1913 if (traces)
1914 {
1915 nrHelper->EnableTraces();
1916 }
1917
1918 FlowMonitorHelper flowmonHelper;
1919 NodeContainer endpointNodes;
1920 endpointNodes.Add(remoteHost);
1921 endpointNodes.Add(gridScenario.GetUserTerminals());
1922
1923 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
1924 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.001));
1925 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
1926 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
1927
1928 Simulator::Stop(simTime);
1929 Simulator::Run();
1930
1931 // Print per-flow statistics
1932 monitor->CheckForLostPackets();
1933 Ptr<Ipv4FlowClassifier> classifier =
1934 DynamicCast<Ipv4FlowClassifier>(flowmonHelper.GetClassifier());
1935 FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
1936
1937 double averageFlowThroughput = 0.0;
1938 double averageFlowDelay = 0.0;
1939
1940 std::ofstream outFile;
1941 std::string filename = outputDir + "/" + simTag;
1942 std::vector<double> delayValues(stats.size());
1943 uint64_t cont = 0;
1944
1945 outFile.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
1946 if (!outFile.is_open())
1947 {
1948 std::cerr << "Can't open file " << filename << std::endl;
1949 return 1;
1950 }
1951
1952 outFile.setf(std::ios_base::fixed);
1953
1954 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
1955 i != stats.end();
1956 ++i)
1957 {
1958 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
1959 std::stringstream protoStream;
1960 protoStream << (uint16_t)t.protocol;
1961 if (t.protocol == 6)
1962 {
1963 protoStream.str("TCP");
1964 }
1965 if (t.protocol == 17)
1966 {
1967 protoStream.str("UDP");
1968 }
1969 std::cout << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
1970 << t.destinationAddress << ":" << t.destinationPort << ") proto "
1971 << protoStream.str() << "\n";
1972 std::cout << " Tx Packets: " << i->second.txPackets << "\n";
1973 std::cout << " Tx Bytes: " << i->second.txBytes << "\n";
1974 std::cout << " TxOffered: "
1975 << i->second.txBytes * 8.0 / (simTime - appStartTime).GetSeconds() / 1000.0 /
1976 1000.0
1977 << " Mbps\n";
1978 std::cout << " Rx Packets: " << i->second.rxPackets << "\n";
1979 std::cout << " Rx Bytes: " << i->second.rxBytes << "\n";
1980 if (i->second.rxPackets > 0)
1981 {
1982 // Measure the duration of the flow from receiver's perspective
1983 // double rxDuration = i->second.timeLastRxPacket.GetSeconds () -
1984 // i->second.timeFirstTxPacket.GetSeconds ();
1985 double rxDuration = (simTime - appStartTime).GetSeconds();
1986
1987 averageFlowThroughput += i->second.rxBytes * 8.0 / rxDuration / 1000 / 1000;
1988 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
1989 delayValues[cont] = 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
1990 cont++;
1991
1992 std::cout << " Throughput: " << i->second.rxBytes * 8.0 / rxDuration / 1000 / 1000
1993 << " Mbps\n";
1994 std::cout << " Mean delay: "
1995 << double(1000 * i->second.delaySum.GetSeconds()) / (i->second.rxPackets)
1996 << " ms\n";
1997 std::cout << " Last packet delay: " << i->second.lastDelay.As(Time::MS) << "\n";
1998 // std::cout << " Mean upt: " << i->second.uptSum / i->second.rxPackets / 1000/1000 <<
1999 // " Mbps \n";
2000 std::cout << " Mean jitter: "
2001 << 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets << " ms\n";
2002 }
2003 else
2004 {
2005 // outFile << " Throughput: 0 Mbps\n";
2006 // outFile << " Mean delay: 0 ms\n";
2007 // outFile << " Mean jitter: 0 ms\n";
2008 }
2009 // outFile << " Rx Packets: " << i->second.rxPackets << "\n";
2010 }
2011 std::sort(delayValues.begin(), delayValues.end());
2012 // for (uint32_t i = 0; i < stats.size(); i++)
2013 // {
2014 // std::cout << delayValues[i] << " ";
2015 // }
2016 // double FiftyTileFlowDelay = (delayValues[stats.size()/2] + delayValues[stats.size()/2 -1])/2;
2017 double FiftyTileFlowDelay = delayValues[stats.size() / 2];
2018
2019 outFile << "\n\n Mean flow throughput: " << averageFlowThroughput / stats.size() << "\n";
2020 outFile << " Mean flow delay: " << averageFlowDelay / stats.size() << "\n";
2021 outFile << " Median flow delay: " << FiftyTileFlowDelay << "\n";
2022
2023 outFile.close();
2024
2025 std::ifstream f(filename.c_str());
2026
2027 if (f.is_open())
2028 {
2029 std::cout << f.rdbuf();
2030 }
2031
2032 Simulator::Destroy();
2033 return 0;
2034}
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 CreateScenario() override
Create the scenario, with the configured parameter.
void SetNumRings(uint8_t numRings)
Sets the number of outer rings of sites around the central site.
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.
std::size_t GetNumCells() const
Gets the total number of cells deployed.
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:89
uint32_t GetNumSectorsPerSite() const
Gets the number of sectors per site.
void SetSectorization(SiteSectorizationType numSectors)
Sets the number of sectors of every site.
void SetScenarioParameters(const std::string &scenario)
Sets parameters to the specified scenario.
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.
static TypeId GetTypeId()
Get the type ID.
static TypeId GetTypeId()
Get the type ID.
static std::ostream & operator<<(std::ostream &os, const TrafficTypeConf &item)
operator << for TrafficTypeConf
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Scenario
Different types for the propagation loss model of this bandwidth part.
@ UMi_StreetCanyon
UMi_StreetCanyon.
Minimum configuration requirements for a OperationBand.
Operation band information structure.