5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-3gpp-channel-nums.cc
Go to the documentation of this file.
1// Copyright (c) 2017 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "ns3/antenna-module.h"
6#include "ns3/applications-module.h"
7#include "ns3/config-store-module.h"
8#include "ns3/config-store.h"
9#include "ns3/core-module.h"
10#include "ns3/flow-monitor-module.h"
11#include "ns3/internet-apps-module.h"
12#include "ns3/internet-module.h"
13#include "ns3/mobility-module.h"
14#include "ns3/nr-module.h"
15#include "ns3/point-to-point-module.h"
47using namespace ns3;
48
49NS_LOG_COMPONENT_DEFINE("3gppChannelNumerologiesExample");
50
51int
52main(int argc, char* argv[])
53{
54 // enable logging or not
55 bool logging = false;
56 if (logging)
57 {
58 LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
59 LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
60 LogComponentEnable("NrPdcp", LOG_LEVEL_INFO);
61 }
62
63 // set simulation time and mobility
64 double simTime = 1; // seconds
65 double udpAppStartTime = 0.4; // seconds
66
67 // other simulation parameters default values
68 uint16_t numerology = 0;
69
70 uint16_t gNbNum = 1;
71 uint16_t ueNumPergNb = 1;
72
73 double centralFrequency = 7e9;
74 double bandwidth = 100e6;
75 double txPower = 14;
76 double lambda = 1000;
77 uint32_t udpPacketSize = 1000;
78 bool udpFullBuffer = true;
79 uint8_t fixedMcs = 28;
80 bool useFixedMcs = true;
81 bool singleUeTopology = true;
82 // Where we will store the output files.
83 std::string simTag = "default";
84 std::string outputDir = "./";
85
86 CommandLine cmd(__FILE__);
87 cmd.AddValue("gNbNum", "The number of gNbs in multiple-ue topology", gNbNum);
88 cmd.AddValue("ueNumPergNb", "The number of UE per gNb in multiple-ue topology", ueNumPergNb);
89 cmd.AddValue("numerology", "The numerology to be used.", numerology);
90 cmd.AddValue("txPower", "Tx power to be configured to gNB", txPower);
91 cmd.AddValue("simTag",
92 "tag to be appended to output filenames to distinguish simulation campaigns",
93 simTag);
94 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
95 cmd.AddValue("frequency", "The system frequency", centralFrequency);
96 cmd.AddValue("bandwidth", "The system bandwidth", bandwidth);
97 cmd.AddValue("udpPacketSize", "UDP packet size in bytes", udpPacketSize);
98 cmd.AddValue("lambda", "Number of UDP packets per second", lambda);
99 cmd.AddValue("udpFullBuffer",
100 "Whether to set the full buffer traffic; if this parameter is set then the "
101 "udpInterval parameter"
102 "will be neglected",
103 udpFullBuffer);
104 cmd.AddValue(
105 "fixedMcs",
106 "The fixed MCS that will be used in this example if useFixedMcs is configured to true (1).",
107 fixedMcs);
108 cmd.AddValue("useFixedMcs",
109 "Whether to use fixed mcs, normally used for testing purposes",
110 useFixedMcs);
111 cmd.AddValue("singleUeTopology",
112 "If true, the example uses a predefined topology with one UE and one gNB; "
113 "if false, the example creates a grid of gNBs with a number of UEs attached",
114 singleUeTopology);
115
116 cmd.Parse(argc, argv);
117
118 NS_ASSERT(ueNumPergNb > 0);
119
120 // setup the nr simulation
121 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
122 // Setup the channel helper
123 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
124
125 /*
126 * Spectrum division. We create one operation band with one component carrier
127 * (CC) which occupies the whole operation band bandwidth. The CC contains a
128 * single Bandwidth Part (BWP). This BWP occupies the whole CC band.
129 * Both operational bands will use the StreetCanyon channel modeling.
130 */
131 CcBwpCreator ccBwpCreator;
132 const uint8_t numCcPerBand = 1; // in this example, both bands have a single CC
133 std::string scenario = "RMa";
134 std::string condition = "LOS";
135 if (ueNumPergNb > 1)
136 {
137 scenario = "InH-OfficeOpen";
138 }
139
140 // Create the spectrum channel using the desired scenario and condition
141 channelHelper->ConfigureFactories(scenario, condition, "ThreeGpp");
142 // Set configurations for the channel model
143 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(MilliSeconds(0)));
144 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
145 // Create the configuration for the CcBwpHelper. SimpleOperationBandConf creates
146 // a single BWP per CC
147 CcBwpCreator::SimpleOperationBandConf bandConf(centralFrequency, bandwidth, numCcPerBand);
148
149 // By using the configuration created, it is time to make the operation bands
150 OperationBandInfo band = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
151 // Set and create the channel model to the band
152 channelHelper->AssignChannelsToBands({band});
154
155 /*
156 * Continue setting the parameters which are common to all the nodes, like the
157 * gNB transmit power or numerology.
158 */
159 nrHelper->SetGnbPhyAttribute("TxPower", DoubleValue(txPower));
160 nrHelper->SetGnbPhyAttribute("Numerology", UintegerValue(numerology));
161
162 // Scheduler
163 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaRR"));
164 nrHelper->SetSchedulerAttribute("FixedMcsDl", BooleanValue(useFixedMcs));
165 nrHelper->SetSchedulerAttribute("FixedMcsUl", BooleanValue(useFixedMcs));
166
167 if (useFixedMcs)
168 {
169 nrHelper->SetSchedulerAttribute("StartingMcsDl", UintegerValue(fixedMcs));
170 nrHelper->SetSchedulerAttribute("StartingMcsUl", UintegerValue(fixedMcs));
171 }
172
173 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
174
175 // Antennas for all the UEs
176 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(2));
177 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(4));
178 nrHelper->SetUeAntennaAttribute("AntennaElement",
179 PointerValue(CreateObject<IsotropicAntennaModel>()));
180
181 // Antennas for all the gNbs
182 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(4));
183 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
184 nrHelper->SetGnbAntennaAttribute("AntennaElement",
185 PointerValue(CreateObject<ThreeGppAntennaModel>()));
186
187 // Beamforming method
188 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
189 idealBeamformingHelper->SetAttribute("BeamformingMethod",
190 TypeIdValue(DirectPathBeamforming::GetTypeId()));
191 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
192
193 // Error Model: UE and GNB with same spectrum error model.
194 nrHelper->SetUlErrorModel("ns3::NrEesmIrT1");
195 nrHelper->SetDlErrorModel("ns3::NrEesmIrT1");
196
197 // Both DL and UL AMC will have the same model behind.
198 nrHelper->SetGnbDlAmcAttribute(
199 "AmcModel",
200 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
201 nrHelper->SetGnbUlAmcAttribute(
202 "AmcModel",
203 EnumValue(NrAmc::ErrorModel)); // NrAmc::ShannonModel or NrAmc::ErrorModel
204
205 // Create EPC helper
206 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
207 nrHelper->SetEpcHelper(nrEpcHelper);
208 // Core latency
209 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
210
211 // gNb routing between Bearer and bandwidh part
212 uint32_t bwpIdForBearer = 0;
213 nrHelper->SetGnbBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForBearer));
214
215 /*
216 * Create the gNB and UE nodes according to the network topology
217 */
218 NodeContainer gNbNodes;
219 NodeContainer ueNodes;
220 MobilityHelper mobility;
221 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
222 Ptr<ListPositionAllocator> bsPositionAlloc = CreateObject<ListPositionAllocator>();
223 Ptr<ListPositionAllocator> utPositionAlloc = CreateObject<ListPositionAllocator>();
224
225 const double gNbHeight = 10;
226 const double ueHeight = 1.5;
227
228 if (singleUeTopology)
229 {
230 gNbNodes.Create(1);
231 ueNodes.Create(1);
232 gNbNum = 1;
233 ueNumPergNb = 1;
234
235 mobility.Install(gNbNodes);
236 mobility.Install(ueNodes);
237 bsPositionAlloc->Add(Vector(0.0, 0.0, gNbHeight));
238 utPositionAlloc->Add(Vector(0.0, 30.0, ueHeight));
239 }
240 else
241 {
242 gNbNodes.Create(gNbNum);
243 ueNodes.Create(ueNumPergNb * gNbNum);
244
245 int32_t yValue = 0.0;
246 for (uint32_t i = 1; i <= gNbNodes.GetN(); ++i)
247 {
248 // 2.0, -2.0, 6.0, -6.0, 10.0, -10.0, ....
249 if (i % 2 != 0)
250 {
251 yValue = static_cast<int>(i) * 30;
252 }
253 else
254 {
255 yValue = -yValue;
256 }
257
258 bsPositionAlloc->Add(Vector(0.0, yValue, gNbHeight));
259
260 // 1.0, -1.0, 3.0, -3.0, 5.0, -5.0, ...
261 double xValue = 0.0;
262 for (uint16_t j = 1; j <= ueNumPergNb; ++j)
263 {
264 if (j % 2 != 0)
265 {
266 xValue = j;
267 }
268 else
269 {
270 xValue = -xValue;
271 }
272
273 if (yValue > 0)
274 {
275 utPositionAlloc->Add(Vector(xValue, 1, ueHeight));
276 }
277 else
278 {
279 utPositionAlloc->Add(Vector(xValue, -1, ueHeight));
280 }
281 }
282 }
283 }
284 mobility.SetPositionAllocator(bsPositionAlloc);
285 mobility.Install(gNbNodes);
286
287 mobility.SetPositionAllocator(utPositionAlloc);
288 mobility.Install(ueNodes);
289
290 // Install nr net devices
291 NetDeviceContainer gNbNetDev = nrHelper->InstallGnbDevice(gNbNodes, allBwps);
292
293 NetDeviceContainer ueNetDev = nrHelper->InstallUeDevice(ueNodes, allBwps);
294
295 int64_t randomStream = 1;
296 randomStream += nrHelper->AssignStreams(gNbNetDev, randomStream);
297 randomStream += nrHelper->AssignStreams(ueNetDev, randomStream);
298
299 // create the internet and install the IP stack on the UEs
300 // get SGW/PGW and create a single RemoteHost
301 auto [remoteHost, remoteHostIpv4Address] =
302 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
303
304 InternetStackHelper internet;
305 internet.Install(ueNodes);
306
307 Ipv4InterfaceContainer ueIpIface =
308 nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDev));
309
310 // attach UEs to the closest gNB
311 nrHelper->AttachToClosestGnb(ueNetDev, gNbNetDev);
312
313 // assign IP address to UEs, and install UDP downlink applications
314 uint16_t dlPort = 1234;
315
316 ApplicationContainer serverApps;
317
318 // The sink will always listen to the specified ports
319 UdpServerHelper dlPacketSinkHelper(dlPort);
320 serverApps.Add(dlPacketSinkHelper.Install(ueNodes.Get(0)));
321
322 UdpClientHelper dlClient;
323 dlClient.SetAttribute("RemotePort", UintegerValue(dlPort));
324 dlClient.SetAttribute("PacketSize", UintegerValue(udpPacketSize));
325 dlClient.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
326 if (udpFullBuffer)
327 {
328 double bitRate = 75000000; // 75 Mbps will saturate the NR system of 20 MHz with the
329 // NrEesmIrT1 error model
330 bitRate /= ueNumPergNb; // Divide the cell capacity among UEs
331 if (bandwidth > 20e6)
332 {
333 bitRate *= bandwidth / 20e6;
334 }
335 lambda = bitRate / static_cast<double>(udpPacketSize * 8);
336 }
337 dlClient.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambda)));
338
339 // The bearer that will carry low latency traffic
341
342 Ptr<NrEpcTft> tft = Create<NrEpcTft>();
344 dlpf.localPortStart = dlPort;
345 dlpf.localPortEnd = dlPort;
346 tft->Add(dlpf);
347
348 /*
349 * Let's install the applications!
350 */
351 ApplicationContainer clientApps;
352
353 for (uint32_t i = 0; i < ueNodes.GetN(); ++i)
354 {
355 Ptr<Node> ue = ueNodes.Get(i);
356 Ptr<NetDevice> ueDevice = ueNetDev.Get(i);
357 Address ueAddress = ueIpIface.GetAddress(i);
358
359 // The client, who is transmitting, is installed in the remote host,
360 // with destination address set to the address of the UE
361 dlClient.SetAttribute("RemoteAddress", AddressValue(ueAddress));
362 clientApps.Add(dlClient.Install(remoteHost));
363
364 // Activate a dedicated bearer for the traffic type
365 nrHelper->ActivateDedicatedEpsBearer(ueDevice, bearer, tft);
366 }
367
368 // start server and client apps
369 serverApps.Start(Seconds(udpAppStartTime));
370 clientApps.Start(Seconds(udpAppStartTime));
371 serverApps.Stop(Seconds(simTime));
372 clientApps.Stop(Seconds(simTime));
373
374 // enable the traces provided by the nr module
375 // nrHelper->EnableTraces();
376
377 FlowMonitorHelper flowmonHelper;
378 NodeContainer endpointNodes;
379 endpointNodes.Add(remoteHost);
380 endpointNodes.Add(ueNodes);
381
382 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
383 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.001));
384 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
385 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
386
387 Simulator::Stop(Seconds(simTime));
388 Simulator::Run();
389
390 // Print per-flow statistics
391 monitor->CheckForLostPackets();
392 Ptr<Ipv4FlowClassifier> classifier =
393 DynamicCast<Ipv4FlowClassifier>(flowmonHelper.GetClassifier());
394 FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
395
396 double averageFlowThroughput = 0.0;
397 double averageFlowDelay = 0.0;
398
399 std::ofstream outFile;
400 std::string filename = outputDir + "/" + simTag;
401 outFile.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
402 if (!outFile.is_open())
403 {
404 NS_LOG_ERROR("Can't open file " << filename);
405 return 1;
406 }
407 outFile.setf(std::ios_base::fixed);
408
409 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
410 i != stats.end();
411 ++i)
412 {
413 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
414 std::stringstream protoStream;
415 protoStream << (uint16_t)t.protocol;
416 if (t.protocol == 6)
417 {
418 protoStream.str("TCP");
419 }
420 if (t.protocol == 17)
421 {
422 protoStream.str("UDP");
423 }
424 outFile << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
425 << t.destinationAddress << ":" << t.destinationPort << ") proto "
426 << protoStream.str() << "\n";
427 outFile << " Tx Packets: " << i->second.txPackets << "\n";
428 outFile << " Tx Bytes: " << i->second.txBytes << "\n";
429 outFile << " TxOffered: "
430 << i->second.txBytes * 8.0 / (simTime - udpAppStartTime) / 1000 / 1000 << " Mbps\n";
431 outFile << " Rx Bytes: " << i->second.rxBytes << "\n";
432 if (i->second.rxPackets > 0)
433 {
434 // Measure the duration of the flow from receiver's perspective
435 double rxDuration =
436 i->second.timeLastRxPacket.GetSeconds() - i->second.timeFirstTxPacket.GetSeconds();
437
438 averageFlowThroughput += i->second.rxBytes * 8.0 / rxDuration / 1000 / 1000;
439 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
440
441 outFile << " Throughput: " << i->second.rxBytes * 8.0 / rxDuration / 1000 / 1000
442 << " Mbps\n";
443 outFile << " Mean delay: "
444 << 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets << " ms\n";
445 // outFile << " Mean upt: " << i->second.uptSum / i->second.rxPackets / 1000/1000 << "
446 // Mbps \n";
447 outFile << " Mean jitter: "
448 << 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets << " ms\n";
449 }
450 else
451 {
452 outFile << " Throughput: 0 Mbps\n";
453 outFile << " Mean delay: 0 ms\n";
454 outFile << " Mean upt: 0 Mbps \n";
455 outFile << " Mean jitter: 0 ms\n";
456 }
457 outFile << " Rx Packets: " << i->second.rxPackets << "\n";
458 }
459
460 double meanFlowThroughput = averageFlowThroughput / stats.size();
461 double meanFlowDelay = averageFlowDelay / stats.size();
462 Ptr<UdpServer> serverApp = serverApps.Get(0)->GetObject<UdpServer>();
463 double totalUdpThroughput =
464 ((serverApp->GetReceived() * udpPacketSize * 8) / (simTime - udpAppStartTime)) * 1e-6;
465
466 outFile << "\n\n Mean flow throughput: " << meanFlowThroughput << "\n";
467 outFile << " Mean flow delay: " << meanFlowDelay << "\n";
468 outFile << "\n UDP throughput (bps) for UE with node ID 0:" << totalUdpThroughput << std::endl;
469
470 outFile.close();
471
472 std::ifstream f(filename.c_str());
473
474 if (f.is_open())
475 {
476 std::cout << f.rdbuf();
477 }
478
479 Simulator::Destroy();
480
481 double toleranceMeanFlowThroughput = 383.557857 * 0.0001;
482 double toleranceMeanFlowDelay = 3.533664 * 0.0001;
483 double toleranceUdpThroughput = 372.5066667 * 0.0001;
484
485 // called from examples-to-run.py with all default parameters
486 if (argc == 0 && (meanFlowThroughput < 383.557857 - toleranceMeanFlowThroughput ||
487 meanFlowThroughput > 383.557857 + toleranceMeanFlowThroughput ||
488 meanFlowDelay < 3.533664 - toleranceMeanFlowDelay ||
489 meanFlowDelay > 3.533664 + toleranceMeanFlowDelay ||
490 totalUdpThroughput < 372.5066667 - toleranceUdpThroughput ||
491 totalUdpThroughput > 372.5066667 + toleranceUdpThroughput))
492 {
493 return EXIT_FAILURE;
494 }
495 else
496 {
497 return EXIT_SUCCESS;
498 }
499}
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.
@ ErrorModel
Error Model version (can use different error models, see NrErrorModel)
Definition nr-amc.h:81
This class contains the specification of EPS Bearers.
@ GBR_CONV_VOICE
GBR Conversational Voice.
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
uint16_t localPortStart
start of the port number range of the UE
Definition nr-epc-tft.h:118
uint16_t localPortEnd
end of the port number range of the UE
Definition nr-epc-tft.h:119
Operation band information structure.