-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcttc-nr-traffic-ngmn-mixed.cc
2019 lines (1829 loc) · 85.8 KB
/
cttc-nr-traffic-ngmn-mixed.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (c) 2023 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
//
// SPDX-License-Identifier: GPL-2.0-only
/**
* \ingroup examples
* \file cttc-nr-traffic-ngmn-mixed.cc
* \brief A hegagonal topology example used to show how to configure different
* NGMN types of traffics or NGMN mixed scenario
*
* The example consists of an hexagonal grid deployment
* consisting on a central site and a number of outer rings of sites around this
* central site. Each site is sectorized, meaning that a number of three antenna
* arrays or panels are deployed per gNB. These three antennas are pointing to
* 30º, 150º and 270º w.r.t. the horizontal axis.
* We allocate a band to each sector of a site, and the bands are contiguous in frequency.
* We provide a number of simulation parameters that can be configured in the
* command line.
*
* Please have a look at the possible parameters to know what you can configure
* through the command line.
*
* \code{.unparsed}
$ ./ns3 run "cttc-nr-traffic-ngmn-mixed --PrintHelp"
\endcode
*
* The example will print on-screen the end-to-end result of each flow,
* as well as writing them on a file.
*
*/
/*
* Include part. Often, you will have to include the headers for an entire module;
* do that by including the name of the module you need with the suffix "-module.h".
*/
#include "ns3/applications-module.h"
#include "ns3/config-store-module.h"
#include "ns3/config-store.h"
#include "ns3/core-module.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/internet-module.h"
#include "ns3/log.h"
#include "ns3/mobility-module.h"
#include "ns3/network-module.h"
#include "ns3/nr-module.h"
#include "ns3/point-to-point-module.h"
#include <ns3/antenna-module.h>
#include <ns3/ping-helper.h>
#include <ns3/radio-environment-map-helper.h>
#include <ns3/rng-seed-manager.h>
#include <ns3/three-gpp-ftp-m1-helper.h>
#include <ns3/three-gpp-http-client.h>
#include <ns3/three-gpp-http-helper.h>
#include <ns3/three-gpp-http-server.h>
#include <ns3/three-gpp-http-variables.h>
#include <ns3/traffic-generator-ngmn-ftp-multi.h>
#include <ns3/traffic-generator-ngmn-gaming.h>
#include <ns3/traffic-generator-ngmn-video.h>
#include <ns3/traffic-generator-ngmn-voip.h>
#include <algorithm>
#include <iostream>
using namespace ns3;
/*
* With this line, we will be able to see the logs of the file by enabling the
* component "CttcTrafficExample", in this way:
*
* $ export NS_LOG="CttcTrafficExample=level_info|prefix_func|prefix_time"
*/
NS_LOG_COMPONENT_DEFINE("CttcNrTrafficNgmnMixed");
class RadioNetworkParametersHelper
{
public:
/**
* \brief Set the main radio network parameters.
* \param freqReuse The cell frequency reuse.
*/
void SetNetworkParams(const std::string scenario,
const std::string operationMode,
uint16_t numCcs);
/**
* \brief Gets the BS transmit power
* \return Transmit power in dBW
*/
double GetTxPower();
/**
* \brief Gets the operation bandwidth
* \return Bandwidth in Hz
*/
double GetBandwidth();
/**
* \brief Gets the central frequency
* \return Central frequency in Hz
*/
double GetCentralFrequency();
private:
double m_txPower{-1.0}; //!< Transmit power in dBm
double m_bandwidth{0.0}; //!< System bandwidth in Hz
double m_centralFrequency{-1.0}; //!< Band central frequency in Hz
};
void
RadioNetworkParametersHelper::SetNetworkParams(const std::string scenario,
const std::string operationMode,
uint16_t numCcs)
{
NS_ABORT_MSG_IF(scenario != "UMa" && scenario != "UMi", "Unsupported scenario");
m_centralFrequency = 2e9;
m_bandwidth = 20e6 * numCcs; // 100 RBs per CC (freqReuse)
if (operationMode == "FDD")
{
m_bandwidth += m_bandwidth;
}
if (scenario == "UMa")
{
m_txPower = 43;
}
else
{
m_txPower = 30;
}
}
double
RadioNetworkParametersHelper::GetTxPower()
{
return m_txPower;
}
double
RadioNetworkParametersHelper::GetBandwidth()
{
return m_bandwidth;
}
double
RadioNetworkParametersHelper::GetCentralFrequency()
{
return m_centralFrequency;
}
void
Set5gLenaSimulatorParameters(HexagonalGridScenarioHelper gridScenario,
std::string scenario,
std::string radioNetwork,
std::string operationMode,
std::string direction,
NodeContainer gnbSector1Container,
NodeContainer gnbSector2Container,
NodeContainer gnbSector3Container,
NodeContainer ueSector1Container,
NodeContainer ueSector2Container,
NodeContainer ueSector3Container,
Ptr<PointToPointEpcHelper>& baseEpcHelper,
Ptr<NrHelper>& nrHelper,
NetDeviceContainer& gnbSector1NetDev,
NetDeviceContainer& gnbSector2NetDev,
NetDeviceContainer& gnbSector3NetDev,
NetDeviceContainer& ueSector1NetDev,
NetDeviceContainer& ueSector2NetDev,
NetDeviceContainer& ueSector3NetDev,
bool uniformLambda)
{
/*
* Create the radio network related parameters
*/
RadioNetworkParametersHelper ranHelper;
ranHelper.SetNetworkParams(scenario, operationMode, 1);
/*
* Setup the NR module. We create the various helpers needed for the
* NR simulation:
* - IdealBeamformingHelper, which takes care of the beamforming part
* - NrHelper, which takes care of creating and connecting the various
* part of the NR stack
*/
Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
nrHelper = CreateObject<NrHelper>();
// Put the pointers inside nrHelper
nrHelper->SetBeamformingHelper(idealBeamformingHelper);
Ptr<NrPointToPointEpcHelper> epcHelper = DynamicCast<NrPointToPointEpcHelper>(baseEpcHelper);
nrHelper->SetEpcHelper(epcHelper);
/*
* Spectrum division. We create one operational band containing three
* component carriers, and each CC containing a single bandwidth part
* centered at the frequency specified by the input parameters.
* Each spectrum part length is, as well, specified by the input parameters.
* The operational band will use StreetCanyon channel or UrbanMacro modeling.
*/
BandwidthPartInfoPtrVector allBwps, bwps1, bwps2, bwps3;
CcBwpCreator ccBwpCreator;
// Create the configuration for the CcBwpHelper. SimpleOperationBandConf creates
// a single BWP per CC. Get the spectrum values from the RadioNetworkParametersHelper
double centralFrequencyBand = ranHelper.GetCentralFrequency();
double bandwidthBand = ranHelper.GetBandwidth();
const uint8_t numCcPerBand = 1; // In this example, each cell will have one CC with one BWP
BandwidthPartInfo::Scenario scene;
if (scenario == "UMi")
{
scene = BandwidthPartInfo::UMi_StreetCanyon;
}
else if (scenario == "UMa")
{
scene = BandwidthPartInfo::UMa;
}
else
{
NS_ABORT_MSG("Unsupported scenario");
}
/*
* Attributes of ThreeGppChannelModel still cannot be set in our way.
* TODO: Coordinate with Tommaso
*/
Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod",
TimeValue(MilliSeconds(0))); // 100ms
nrHelper->SetChannelConditionModelAttribute("UpdatePeriod", TimeValue(MilliSeconds(0)));
nrHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
std::string errorModel = "";
if (radioNetwork == "LTE")
{
errorModel = "ns3::LenaErrorModel";
}
else if (radioNetwork == "NR")
{
errorModel = "ns3::NrEesmIrT2";
}
// Error Model: UE and GNB with same spectrum error model.
nrHelper->SetUlErrorModel(errorModel);
nrHelper->SetDlErrorModel(errorModel);
// Both DL and UL AMC will have the same model behind.
nrHelper->SetGnbDlAmcAttribute(
"AmcModel",
EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
nrHelper->SetGnbUlAmcAttribute(
"AmcModel",
EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
/*
* Create the necessary operation bands. In this example, each sector operates
* in a separate band. Each band contains a single component carrier (CC),
* which is made of one BWP in TDD operation mode or two BWPs in FDD mode.
* Note that BWPs have the same bandwidth. Therefore, CCs and bands in FDD are
* twice larger than in TDD.
*
* The configured spectrum division for TDD operation is:
* |---Band1---|---Band2---|---Band3---|
* |----CC1----|----CC2----|----CC3----|
* |----BWP1---|----BWP2---|----BWP3---|
*
* And the configured spectrum division for FDD operation is:
* |---------Band1---------|---------Band2---------|---------Band3---------|
* |----------CC1----------|----------CC2----------|----------CC3----------|
* |----BWP1---|----BWP2---|----BWP3---|----BWP4---|----BWP5---|----BWP6---|
*/
double centralFrequencyBand1 = centralFrequencyBand - bandwidthBand;
double centralFrequencyBand2 = centralFrequencyBand;
double centralFrequencyBand3 = centralFrequencyBand + bandwidthBand;
double bandwidthBand1 = bandwidthBand;
double bandwidthBand2 = bandwidthBand;
double bandwidthBand3 = bandwidthBand;
uint8_t numBwpPerCc = 1;
if (operationMode == "FDD")
{
numBwpPerCc = 2; // FDD will have 2 BWPs per CC
}
CcBwpCreator::SimpleOperationBandConf bandConf1(centralFrequencyBand1,
bandwidthBand1,
numCcPerBand,
scene);
bandConf1.m_numBwp = numBwpPerCc; // FDD will have 2 BWPs per CC
CcBwpCreator::SimpleOperationBandConf bandConf2(centralFrequencyBand2,
bandwidthBand2,
numCcPerBand,
scene);
bandConf2.m_numBwp = numBwpPerCc; // FDD will have 2 BWPs per CC
CcBwpCreator::SimpleOperationBandConf bandConf3(centralFrequencyBand3,
bandwidthBand3,
numCcPerBand,
scene);
bandConf3.m_numBwp = numBwpPerCc; // FDD will have 2 BWPs per CC
// By using the configuration created, it is time to make the operation bands
OperationBandInfo band1 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf1);
OperationBandInfo band2 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf2);
OperationBandInfo band3 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf3);
/*
* Initialize channel and pathloss, plus other things inside band1. If needed,
* the band configuration can be done manually, but we leave it for more
* sophisticated examples. For the moment, this method will take care
* of all the spectrum initialization needs.
*/
nrHelper->InitializeOperationBand(&band1);
nrHelper->InitializeOperationBand(&band2);
nrHelper->InitializeOperationBand(&band3);
allBwps = CcBwpCreator::GetAllBwps({band1, band2, band3});
bwps1 = CcBwpCreator::GetAllBwps({band1});
bwps2 = CcBwpCreator::GetAllBwps({band2});
bwps3 = CcBwpCreator::GetAllBwps({band3});
double txPower = ranHelper.GetTxPower(); // Convert to mW
/*
* allBwps contains all the spectrum configuration needed for the nrHelper.
*
* Now, we can setup the attributes. We can have three kind of attributes:
* (i) parameters that are valid for all the bandwidth parts and applies to
* all nodes, (ii) parameters that are valid for all the bandwidth parts
* and applies to some node only, and (iii) parameters that are different for
* every bandwidth parts. The approach is:
*
* - for (i): Configure the attribute through the helper, and then install;
* - for (ii): Configure the attribute through the helper, and then install
* for the first set of nodes. Then, change the attribute through the helper,
* and install again;
* - for (iii): Install, and then configure the attributes by retrieving
* the pointer needed, and calling "SetAttribute" on top of such pointer.
*
*/
Packet::EnableChecking();
Packet::EnablePrinting();
/*
* Case (i): Attributes valid for all the nodes
*/
// Beamforming method
if (radioNetwork == "LTE")
{
idealBeamformingHelper->SetAttribute(
"BeamformingMethod",
TypeIdValue(QuasiOmniDirectPathBeamforming::GetTypeId()));
}
else
{
idealBeamformingHelper->SetAttribute("BeamformingMethod",
TypeIdValue(DirectPathBeamforming::GetTypeId()));
}
// Scheduler type
if (radioNetwork == "LTE")
{
nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaPF"));
nrHelper->SetSchedulerAttribute("DlCtrlSymbols", UintegerValue(1));
}
// Core latency
epcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
// Antennas for all the UEs
nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(1));
nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(1));
nrHelper->SetUeAntennaAttribute("AntennaElement",
PointerValue(CreateObject<IsotropicAntennaModel>()));
// Antennas for all the gNbs
nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(8));
nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
nrHelper->SetGnbAntennaAttribute("AntennaElement",
PointerValue(CreateObject<ThreeGppAntennaModel>()));
// Set numerology
nrHelper->SetGnbPhyAttribute("Numerology", UintegerValue(1));
// Set gNB TX power
nrHelper->SetGnbPhyAttribute("TxPower", DoubleValue(txPower));
// UE transmit power
nrHelper->SetUePhyAttribute("TxPower", DoubleValue(20.0));
// Set LTE RBG size
if (radioNetwork == "LTE")
{
nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(4));
}
// We assume a common traffic pattern for all UEs
uint32_t bwpIdForLowLat = 0;
if (operationMode == "FDD" && direction == "UL")
{
bwpIdForLowLat = 1;
}
// TODO check later when QoS scheduler is in place, that the type of bearer coresponds to the
// type of traffic gNb routing between Bearer and bandwidth part
nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_DEFAULT",
UintegerValue(bwpIdForLowLat));
// Ue routing between Bearer and bandwidth part
nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_VIDEO_TCP_DEFAULT",
UintegerValue(bwpIdForLowLat));
/*
* We have configured the attributes we needed. Now, install and get the pointers
* to the NetDevices, which contains all the NR stack:
*/
// NetDeviceContainer enbNetDev = nrHelper->InstallGnbDevice (gridScenario.GetBaseStations (),
// allBwps);
gnbSector1NetDev = nrHelper->InstallGnbDevice(gnbSector1Container, bwps1);
gnbSector2NetDev = nrHelper->InstallGnbDevice(gnbSector2Container, bwps2);
gnbSector3NetDev = nrHelper->InstallGnbDevice(gnbSector3Container, bwps3);
ueSector1NetDev = nrHelper->InstallUeDevice(ueSector1Container, bwps1);
ueSector2NetDev = nrHelper->InstallUeDevice(ueSector2Container, bwps2);
ueSector3NetDev = nrHelper->InstallUeDevice(ueSector3Container, bwps3);
int64_t randomStream = 1;
randomStream += nrHelper->AssignStreams(gnbSector1NetDev, randomStream);
randomStream += nrHelper->AssignStreams(gnbSector2NetDev, randomStream);
randomStream += nrHelper->AssignStreams(gnbSector3NetDev, randomStream);
randomStream += nrHelper->AssignStreams(ueSector1NetDev, randomStream);
randomStream += nrHelper->AssignStreams(ueSector2NetDev, randomStream);
randomStream += nrHelper->AssignStreams(ueSector3NetDev, randomStream);
/*
* Case (iii): Go node for node and change the attributes we have to setup
* per-node.
*/
// Sectors (cells) of a site are pointing at different directions
double orientationRads = gridScenario.GetAntennaOrientationRadians(0);
for (uint32_t numCell = 0; numCell < gnbSector1NetDev.GetN(); ++numCell)
{
Ptr<NetDevice> gnb = gnbSector1NetDev.Get(numCell);
uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
if (numBwps == 1) // TDD
{
// Change the antenna orientation
Ptr<NrGnbPhy> phy = nrHelper->GetGnbPhy(gnb, 0);
Ptr<UniformPlanarArray> antenna =
DynamicCast<UniformPlanarArray>(phy->GetSpectrumPhy(0)->GetAntenna());
antenna->SetAttribute("BearingAngle", DoubleValue(orientationRads));
// Set TDD pattern
nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Pattern",
StringValue("F|F|F|F|F|F|F|F|F|F|"));
}
else if (numBwps == 2) // FDD
{
// Change the antenna orientation
Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0);
Ptr<UniformPlanarArray> antenna0 =
DynamicCast<UniformPlanarArray>(phy0->GetSpectrumPhy(0)->GetAntenna());
antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
Ptr<NrGnbPhy> phy1 = nrHelper->GetGnbPhy(gnb, 1);
Ptr<UniformPlanarArray> antenna1 =
DynamicCast<UniformPlanarArray>(phy1->GetSpectrumPhy(0)->GetAntenna());
antenna1->SetAttribute("BearingAngle", DoubleValue(orientationRads));
// Set TDD pattern
nrHelper->GetGnbPhy(gnb, 0)->SetAttribute(
"Pattern",
StringValue("DL|DL|DL|DL|DL|DL|DL|DL|DL|DL|"));
nrHelper->GetGnbPhy(gnb, 1)->SetAttribute(
"Pattern",
StringValue("UL|UL|UL|UL|UL|UL|UL|UL|UL|UL|"));
// Link the two FDD BWP
nrHelper->GetBwpManagerGnb(gnb)->SetOutputLink(1, 0);
}
else
{
NS_ABORT_MSG("Incorrect number of BWPs per CC");
}
}
orientationRads = gridScenario.GetAntennaOrientationRadians(1);
for (uint32_t numCell = 0; numCell < gnbSector2NetDev.GetN(); ++numCell)
{
Ptr<NetDevice> gnb = gnbSector2NetDev.Get(numCell);
uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
if (numBwps == 1) // TDD
{
// Change the antenna orientation
Ptr<NrGnbPhy> phy = nrHelper->GetGnbPhy(gnb, 0);
Ptr<UniformPlanarArray> antenna =
DynamicCast<UniformPlanarArray>(phy->GetSpectrumPhy(0)->GetAntenna());
antenna->SetAttribute("BearingAngle", DoubleValue(orientationRads));
// Set TDD pattern
nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Pattern",
StringValue("F|F|F|F|F|F|F|F|F|F|"));
}
else if (numBwps == 2) // FDD
{
// Change the antenna orientation
Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0);
Ptr<UniformPlanarArray> antenna0 =
DynamicCast<UniformPlanarArray>(phy0->GetSpectrumPhy(0)->GetAntenna());
antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
Ptr<NrGnbPhy> phy1 = nrHelper->GetGnbPhy(gnb, 1);
Ptr<UniformPlanarArray> antenna1 =
DynamicCast<UniformPlanarArray>(phy1->GetSpectrumPhy(0)->GetAntenna());
antenna1->SetAttribute("BearingAngle", DoubleValue(orientationRads));
// Set TDD pattern
nrHelper->GetGnbPhy(gnb, 0)->SetAttribute(
"Pattern",
StringValue("DL|DL|DL|DL|DL|DL|DL|DL|DL|DL|"));
nrHelper->GetGnbPhy(gnb, 1)->SetAttribute(
"Pattern",
StringValue("UL|UL|UL|UL|UL|UL|UL|UL|UL|UL|"));
// Link the two FDD BWP
nrHelper->GetBwpManagerGnb(gnb)->SetOutputLink(1, 0);
}
else
{
NS_ABORT_MSG("Incorrect number of BWPs per CC");
}
}
orientationRads = gridScenario.GetAntennaOrientationRadians(2);
for (uint32_t numCell = 0; numCell < gnbSector3NetDev.GetN(); ++numCell)
{
Ptr<NetDevice> gnb = gnbSector3NetDev.Get(numCell);
uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
if (numBwps == 1) // TDD
{
// Change the antenna orientation
Ptr<NrGnbPhy> phy = nrHelper->GetGnbPhy(gnb, 0);
Ptr<UniformPlanarArray> antenna =
DynamicCast<UniformPlanarArray>(phy->GetSpectrumPhy(0)->GetAntenna());
antenna->SetAttribute("BearingAngle", DoubleValue(orientationRads));
// Set TDD pattern
nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Pattern",
StringValue("F|F|F|F|F|F|F|F|F|F|"));
}
else if (numBwps == 2) // FDD
{
// Change the antenna orientation
Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0);
Ptr<UniformPlanarArray> antenna0 =
DynamicCast<UniformPlanarArray>(phy0->GetSpectrumPhy(0)->GetAntenna());
antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
Ptr<NrGnbPhy> phy1 = nrHelper->GetGnbPhy(gnb, 1);
Ptr<UniformPlanarArray> antenna1 =
DynamicCast<UniformPlanarArray>(phy1->GetSpectrumPhy(0)->GetAntenna());
antenna1->SetAttribute("BearingAngle", DoubleValue(orientationRads));
// Set TDD pattern
nrHelper->GetGnbPhy(gnb, 0)->SetAttribute(
"Pattern",
StringValue("DL|DL|DL|DL|DL|DL|DL|DL|DL|DL|"));
nrHelper->GetGnbPhy(gnb, 1)->SetAttribute(
"Pattern",
StringValue("UL|UL|UL|UL|UL|UL|UL|UL|UL|UL|"));
// Link the two FDD BWP
nrHelper->GetBwpManagerGnb(gnb)->SetOutputLink(1, 0);
}
else
{
NS_ABORT_MSG("Incorrect number of BWPs per CC");
}
}
// Set the UE routing:
if (operationMode == "FDD")
{
for (uint32_t i = 0; i < ueSector1NetDev.GetN(); i++)
{
nrHelper->GetBwpManagerUe(ueSector1NetDev.Get(i))->SetOutputLink(0, 1);
}
for (uint32_t i = 0; i < ueSector2NetDev.GetN(); i++)
{
nrHelper->GetBwpManagerUe(ueSector2NetDev.Get(i))->SetOutputLink(0, 1);
}
for (uint32_t i = 0; i < ueSector3NetDev.GetN(); i++)
{
nrHelper->GetBwpManagerUe(ueSector3NetDev.Get(i))->SetOutputLink(0, 1);
}
}
// When all the configuration is done, explicitly call UpdateConfig ()
for (auto it = gnbSector1NetDev.Begin(); it != gnbSector1NetDev.End(); ++it)
{
DynamicCast<NrGnbNetDevice>(*it)->UpdateConfig();
}
for (auto it = gnbSector2NetDev.Begin(); it != gnbSector2NetDev.End(); ++it)
{
DynamicCast<NrGnbNetDevice>(*it)->UpdateConfig();
}
for (auto it = gnbSector3NetDev.Begin(); it != gnbSector3NetDev.End(); ++it)
{
DynamicCast<NrGnbNetDevice>(*it)->UpdateConfig();
}
for (auto it = ueSector1NetDev.Begin(); it != ueSector1NetDev.End(); ++it)
{
DynamicCast<NrUeNetDevice>(*it)->UpdateConfig();
}
for (auto it = ueSector2NetDev.Begin(); it != ueSector2NetDev.End(); ++it)
{
DynamicCast<NrUeNetDevice>(*it)->UpdateConfig();
}
for (auto it = ueSector3NetDev.Begin(); it != ueSector3NetDev.End(); ++it)
{
DynamicCast<NrUeNetDevice>(*it)->UpdateConfig();
}
}
enum TrafficTypeConf
{
UDP_CBR, // 0
FTP_3GPP_M1, // 1
NGMN_FTP, // 2
NGMN_VIDEO, // 3
NGMN_HTTP, // 4
NGMN_GAMING, // 5
NGMN_VOIP, // 6
NGMN_MIXED // 7
};
/**
* \brief operator << for TrafficTypeConf
* \param os output stream
* \param item TrafficType to print
* \return a copy of the output stream
*/
static inline std::ostream&
operator<<(std::ostream& os, const TrafficTypeConf& item)
{
switch (item)
{
case UDP_CBR:
os << "UDP CBR";
break;
case FTP_3GPP_M1:
os << "FTP 3GPP M1";
break;
case NGMN_FTP:
os << "NGMN FTP";
break;
case NGMN_VIDEO:
os << "NGMN VIDEO";
break;
case NGMN_HTTP:
os << "NGMN HTTP";
break;
case NGMN_GAMING:
os << "NGMN GAMING";
break;
case NGMN_VOIP:
os << "NGMN VOIP";
break;
case NGMN_MIXED:
os << "NGMN MIXED";
break;
default:
NS_ABORT_MSG("Unknown traffic type");
}
return os;
}
static inline std::istream&
operator>>(std::istream& is, TrafficTypeConf& item)
{
uint32_t inputValue;
is >> inputValue;
item = (TrafficTypeConf)inputValue;
return is;
}
int
main(int argc, char* argv[])
{
/*
* Variables that represent the parameters we will accept as input by the
* command line. Each of them is initialized with a default value.
*/
TrafficTypeConf trafficTypeConf = FTP_3GPP_M1;
// Traffic parameters (that we will use inside this script:)
uint32_t udpPacketSize = 600; // bytes
// 4000*600*8 = 19.2 Mbps/UE,
// 3000*600*8 = 14.4 Mbps/UE,
// 2000*600*8 = 9.6 Mbps/UE
// 1500*600*8 = 7.2 Mbps/UE
// 1000*600*8 = 4.8 Mbps/UE
uint32_t udpLambda = 2000;
double ftpM1Lambda = 5;
uint32_t ftpM1FileSize = 512000; // in bytes
Time clientAppStartTime = MilliSeconds(400);
Time serverAppStartTime = MilliSeconds(400);
// Simulation parameters. Please don't use double to indicate seconds, use
// milliseconds and integers to avoid representation errors.
uint32_t simTimeMs = 1400;
Time appStartTime = MilliSeconds(400);
std::string direction = "DL";
bool uniformLambda = true;
// topology
uint16_t numOuterRings = 0;
uint16_t uesPerGnb = 10;
std::string scenario = "UMi";
std::string radioNetwork = "NR"; // LTE or NR
std::string operationMode = "TDD"; // TDD or FDD
// Where we will store the output files.
std::string simTag = "default";
std::string outputDir = "./";
bool logging = false;
bool traces = true;
bool useUdp = true;
uint8_t ngmnMixedFtpPercentage = 10;
uint8_t ngmnMixedHttpPercentage = 20;
uint8_t ngmnMixedVideoPercentage = 20;
uint8_t ngmnMixedVoipPercentage = 30;
uint8_t ngmnMixedGamingPercentage = 20;
/*
* From here, we instruct the ns3::CommandLine class of all the input parameters
* that we may accept as input, as well as their description, and the storage
* variable.
*/
CommandLine cmd(__FILE__);
cmd.AddValue("trafficTypeConf",
"The traffic type to be configured. Currently the following options are "
"available: 0 - UDP CBR, 1 - FTP Model 1, 2 - NGMN FTP, 3 - NGMN VIDEO, 4 - HTTP, "
"5-NGMN GAMING, 6 - NGMN VOIP, 7 - NGMN MIXED (e.g., "
"10% FTP, 20% HTTP, 20% VIDEO STREAMING, 30% VoIP, 20% GAMING)",
trafficTypeConf);
cmd.AddValue(
"ngmnMixedFtpPercentage",
"If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
"percentage of the FTP traffic. Percentage should be multiply of 10.",
ngmnMixedFtpPercentage);
cmd.AddValue(
"ngmnMixedHttpPercentage",
"If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
"percentage of the HTTP traffic. Percentage should be multiply of 10.",
ngmnMixedHttpPercentage);
cmd.AddValue(
"ngmnMixedVideoPercentage",
"If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
"percentage of the VIDEO traffic. Percentage should be multiply of 10.",
ngmnMixedVideoPercentage);
cmd.AddValue(
"ngmnMixedVoipPercentage",
"If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
"percentage of the VoIP traffic. Percentage should be multiply of 10.",
ngmnMixedVoipPercentage);
cmd.AddValue(
"ngmnMixedGamingPercentage",
"If trafficTypeConf selected is NGMN MIXED this value can be configured to determine the "
"percentage of the GAMING traffic. Percentage should be multiply of 10.",
ngmnMixedGamingPercentage);
cmd.AddValue("useUdp",
"if true, the NGMN applications will run over UDP connection, otherwise a TCP "
"connection will be used. "
"Notice that HTTP application as it is present in ns-3 simulator is implemented "
"as typical HTTP application, i.e., "
"based on the TCP protocol and as such cannot be reconfigured to use UDP.",
useUdp);
cmd.AddValue("ftpM1Lambda",
"The lambda to be used for FTP M1 traffic model (Typical values are 2.5, 5). ",
ftpM1Lambda);
cmd.AddValue("udpLambda", "Number of UDP packets generated in one second per UE", udpLambda);
cmd.AddValue("uniformLambda",
"1: Use same lambda (packets/s) for all UEs and cells (equal to 'lambda' input), "
"0: use different packet arrival rates (lambdas) among cells",
uniformLambda);
cmd.AddValue("scenario", "The urban scenario string (UMa or UMi)", scenario);
cmd.AddValue("numRings", "The number of rings around the central site", numOuterRings);
cmd.AddValue("uesPerGnb",
"The number of UE per gNB, should be multiply of 10 so that the mixed traffic "
"works correctly.",
uesPerGnb);
cmd.AddValue("logging", "Enable logging", logging);
cmd.AddValue("traces", "Enable output traces", traces);
cmd.AddValue("packetSize", "packet size in bytes to be used by UE traffic", udpPacketSize);
cmd.AddValue("simTimeMs", "Simulation time", simTimeMs);
cmd.AddValue("direction", "The flow direction (DL or UL)", direction);
cmd.AddValue("technology", "The radio access network technology", radioNetwork);
cmd.AddValue("operationMode", "The network operation mode can be TDD or FDD", operationMode);
cmd.AddValue("simTag",
"tag to be appended to output filenames to distinguish simulation campaigns",
simTag);
cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
// Parse the command line
cmd.Parse(argc, argv);
/*
* Check if the parameter values provided by the user are correct.
*/
// NS_ABORT_IF (centralFrequencyBand > 100e9);]
NS_ABORT_MSG_IF(
trafficTypeConf > 7,
"Currently only supported values for traffic type are 0, 1, 2. Meaning: 0 -UDP CBR, 1 - "
"FTP Model 1, 2 - NGMN FTP, 3 - NGMN VIDEO, 4- HTTP, 5- NGMN GAMING, 6 - VOIP, 7 - NGMN "
"MIXED (e.g., 10% FTP, 20% HTTP, 20% VIDEO STREAMING, 30% VoIP, 20% GAMING");
NS_ABORT_MSG_IF(direction != "DL" && direction != "UL", "Flow direction can only be DL or UL");
NS_ABORT_MSG_IF(operationMode != "TDD" && operationMode != "FDD",
"Operation mode can only be TDD or FDD");
NS_ABORT_MSG_IF(radioNetwork != "LTE" && radioNetwork != "NR",
"Unrecognized radio network technology");
NS_ABORT_MSG_IF(
trafficTypeConf == 7 &&
(ngmnMixedFtpPercentage + ngmnMixedHttpPercentage + ngmnMixedVideoPercentage +
ngmnMixedVoipPercentage + ngmnMixedGamingPercentage) != 100,
"If trafficTypeConf selected is the NGMN mixed, then the sum of the percentages of FTP, "
"VOIP, HTTP, VIDEO STREAMING and GAMING traffic should give 100.");
/*
* If the logging variable is set to true, enable the log of some components
* through the code. The same effect can be obtained through the use
* of the NS_LOG environment variable:
*
* export NS_LOG="UdpClient=level_info|prefix_time|prefix_func|prefix_node:UdpServer=..."
*
* Usually, the environment variable way is preferred, as it is more customizable,
* and more expressive.
*/
if (logging)
{
LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
// LogComponentEnable ("NrMacSchedulerOfdma", LOG_LEVEL_ALL);
}
// configure the transport protocol to be used
std::string transportProtocol;
if (useUdp)
{
transportProtocol = "ns3::UdpSocketFactory";
}
else
{
transportProtocol = "ns3::TcpSocketFactory";
}
Time simTime = MilliSeconds(simTimeMs);
std::cout << "\n Traffic configuration selected is: " << trafficTypeConf << std::endl;
/*
* Create the scenario. In our examples, we heavily use helpers that setup
* the gnbs and ue following a pre-defined pattern. Please have a look at the
* GridScenarioHelper documentation to see how the nodes will be distributed.
*/
HexagonalGridScenarioHelper gridScenario;
gridScenario.SetSectorization(HexagonalGridScenarioHelper::TRIPLE);
gridScenario.SetNumRings(numOuterRings);
gridScenario.SetScenarioParameters(scenario);
uint16_t gNbNum = gridScenario.GetNumCells();
std::cout << " GNB num: " << gNbNum << std::endl;
uint32_t ueNum = uesPerGnb * gNbNum;
std::cout << " UE num: " << ueNum << std::endl;
gridScenario.SetUtNumber(ueNum);
gridScenario.AssignStreams(RngSeedManager::GetRun());
gridScenario.CreateScenario(); //!< Creates and plots the network deployment
const uint16_t ffr =
3; // Fractional Frequency Reuse scheme to mitigate intra-site inter-sector interferences
/*
* Create different gNB NodeContainer for the different sectors.
*/
NodeContainer gnbSector1Container, gnbSector2Container, gnbSector3Container;
for (uint32_t j = 0; j < gridScenario.GetBaseStations().GetN(); ++j)
{
Ptr<Node> gnb = gridScenario.GetBaseStations().Get(j);
switch (j % ffr)
{
case 0:
gnbSector1Container.Add(gnb);
break;
case 1:
gnbSector2Container.Add(gnb);
break;
case 2:
gnbSector3Container.Add(gnb);
break;
default:
NS_ABORT_MSG("ffr param cannot be larger than 3");
break;
}
}
/*
* Create different UE NodeContainer for the different sectors.
*/
NodeContainer ueSector1Container, ueSector2Container, ueSector3Container;
for (uint32_t j = 0; j < gridScenario.GetUserTerminals().GetN(); ++j)
{
Ptr<Node> ue = gridScenario.GetUserTerminals().Get(j);
switch (j % ffr)
{
case 0:
ueSector1Container.Add(ue);
break;
case 1:
ueSector2Container.Add(ue);
break;
case 2:
ueSector3Container.Add(ue);
break;
default:
NS_ABORT_MSG("ffr param cannot be larger than 3");
break;
}
}
/*
* Setup the 5G-LENA scenario
*/
Ptr<PointToPointEpcHelper> epcHelper;
NetDeviceContainer gnbSector1NetDev, gnbSector2NetDev, gnbSector3NetDev;
NetDeviceContainer ueSector1NetDev, ueSector2NetDev, ueSector3NetDev;
Ptr<NrHelper> nrHelper = nullptr;
epcHelper = CreateObject<NrPointToPointEpcHelper>();
Set5gLenaSimulatorParameters(gridScenario,
scenario,
radioNetwork,
operationMode,
direction,
gnbSector1Container,
gnbSector2Container,
gnbSector3Container,
ueSector1Container,
ueSector2Container,
ueSector3Container,
epcHelper,
nrHelper,
gnbSector1NetDev,
gnbSector2NetDev,
gnbSector3NetDev,
ueSector1NetDev,
ueSector2NetDev,
ueSector3NetDev,
uniformLambda);
// From here, it is standard NS3. In the future, we will create helpers
// for this part as well.
// create the internet and install the IP stack on the UEs
// get SGW/PGW and create a single RemoteHost
Ptr<Node> pgw = epcHelper->GetPgwNode();
NodeContainer remoteHostContainer;
remoteHostContainer.Create(1);
Ptr<Node> remoteHost = remoteHostContainer.Get(0);
InternetStackHelper internet;
internet.Install(remoteHostContainer);
// connect a remoteHost to pgw. Setup routing too
PointToPointHelper p2ph;
p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
p2ph.SetDeviceAttribute("Mtu", UintegerValue(2500));
p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.000)));
NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
Ipv4AddressHelper ipv4h;
Ipv4StaticRoutingHelper ipv4RoutingHelper;
ipv4h.SetBase("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
internet.Install(gridScenario.GetUserTerminals());
// if the mixed traffic type selected then determine for each which container IDs correposnd to
// each traffic type
std::set<uint16_t> ngmnFtpIds;
std::set<uint16_t> ngmnVideoIds;
std::set<uint16_t> ngmnVoipIds;
std::set<uint16_t> ngmnHttpIds;
std::set<uint16_t> ngmnGamingIds;
// configure indexes of UEs per traffic type
if (trafficTypeConf == NGMN_MIXED)
{
// check if there is enough UEs to configure NGMN_MIXED traffic type
NS_ABORT_MSG_UNLESS((ueSector1NetDev.GetN() % 10) == 0,