5G-LENA nr-v4.0
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-traffic-3gpp-xr.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
5#include "ns3/antenna-module.h"
6#include "ns3/applications-module.h"
7#include "ns3/boolean.h"
8#include "ns3/config-store-module.h"
9#include "ns3/config-store.h"
10#include "ns3/core-module.h"
11#include "ns3/flow-monitor-module.h"
12#include "ns3/internet-apps-module.h"
13#include "ns3/internet-module.h"
14#include "ns3/mobility-module.h"
15#include "ns3/nr-gnb-rrc.h"
16#include "ns3/nr-module.h"
17#include "ns3/packet-sink.h"
18#include "ns3/point-to-point-module.h"
19#include "ns3/xr-traffic-mixer-helper.h"
20
21#include <vector>
22
37using namespace ns3;
38
39NS_LOG_COMPONENT_DEFINE("CttcNrTraffic3gppXr");
40
41void
42ConfigureXrApp(NodeContainer& ueContainer,
43 uint32_t i,
44 Ipv4InterfaceContainer& ueIpIface,
45 enum NrXrConfig config,
46 double appDataRate,
47 uint16_t appFps,
48 uint16_t port,
49 std::string transportProtocol,
50 NodeContainer& remoteHostContainer,
51 NetDeviceContainer& ueNetDev,
52 Ptr<NrHelper> nrHelper,
53 NrEpsBearer& bearer,
54 Ptr<NrEpcTft> tft,
55 bool isMx1,
56 std::vector<Ptr<NrEpcTft>>& tfts,
57 ApplicationContainer& serverApps,
58 ApplicationContainer& clientApps,
59 ApplicationContainer& pingApps)
60{
61 XrTrafficMixerHelper trafficMixerHelper;
62 Ipv4Address ipAddress = ueIpIface.GetAddress(i, 0);
63 trafficMixerHelper.ConfigureXr(config);
64 auto it = XrPreconfig.find(config);
65
66 std::vector<Address> addresses;
67 std::vector<InetSocketAddress> localAddresses;
68 for (size_t j = 0; j < it->second.size(); j++)
69 {
70 addresses.emplace_back(InetSocketAddress(ipAddress, port + j));
71 // The sink will always listen to the specified ports
72 localAddresses.emplace_back(Ipv4Address::GetAny(), port + j);
73 }
74
75 ApplicationContainer currentUeClientApps;
76 currentUeClientApps.Add(
77 trafficMixerHelper.Install(transportProtocol, addresses, remoteHostContainer.Get(0)));
78
79 // Seed the ARP cache by pinging early in the simulation
80 // This is a workaround until a static ARP capability is provided
81 PingHelper ping(ipAddress);
82 pingApps.Add(ping.Install(remoteHostContainer));
83
84 Ptr<NetDevice> ueDevice = ueNetDev.Get(i);
85 // Activate a dedicated bearer for the traffic type per node
86 nrHelper->ActivateDedicatedEpsBearer(ueDevice, bearer, tft);
87 // Activate a dedicated bearer for the traffic type per node
88 if (isMx1)
89 {
90 nrHelper->ActivateDedicatedEpsBearer(ueDevice, bearer, tft);
91 }
92 else
93 {
94 NS_ASSERT(tfts.size() >= currentUeClientApps.GetN());
95 for (uint32_t j = 0; j < currentUeClientApps.GetN(); j++)
96 {
97 nrHelper->ActivateDedicatedEpsBearer(ueDevice, bearer, tfts[j]);
98 }
99 }
100
101 for (uint32_t j = 0; j < currentUeClientApps.GetN(); j++)
102 {
103 PacketSinkHelper dlPacketSinkHelper(transportProtocol, localAddresses.at(j));
104 Ptr<Application> packetSink = dlPacketSinkHelper.Install(ueContainer.Get(i)).Get(0);
105 serverApps.Add(packetSink);
106 Ptr<TrafficGenerator3gppGenericVideo> app =
107 DynamicCast<TrafficGenerator3gppGenericVideo>(currentUeClientApps.Get(j));
108 if (app)
109 {
110 app->SetAttribute("DataRate", DoubleValue(appDataRate));
111 app->SetAttribute("Fps", UintegerValue(appFps));
112 }
113 }
114 clientApps.Add(currentUeClientApps);
115}
116
117int
118main(int argc, char* argv[])
119{
120 // set simulation time and mobility
121 uint32_t appDuration = 10000;
122 uint32_t appStartTimeMs = 400;
123 uint16_t numerology = 0;
124 uint16_t arUeNum = 1;
125 uint16_t vrUeNum = 1;
126 uint16_t cgUeNum = 1;
127 double centralFrequency = 4e9;
128 double bandwidth = 10e6;
129 double txPower = 41;
130 bool isMx1 = true;
131 bool useUdp = true;
132 double arDataRate = 5; // Mbps
133 double vrDataRate = 30; // Mbps
134 double cgDataRate = 20; // Mbps
135 uint16_t arFps = 30;
136 uint16_t vrFps = 60;
137 uint16_t cgFps = 60;
138 uint32_t rngRun = 1;
139
140 CommandLine cmd(__FILE__);
141 cmd.AddValue("arUeNum", "The number of AR UEs", arUeNum);
142 cmd.AddValue("vrUeNum", "The number of VR UEs", vrUeNum);
143 cmd.AddValue("cgUeNum", "The number of CG UEs", cgUeNum);
144 cmd.AddValue("arDataRate", "The Datarate for AR UEs", arDataRate);
145 cmd.AddValue("vrDataRate", "The Datarate for vR UEs", vrDataRate);
146 cmd.AddValue("cgDataRate", "The Datarate for cg UEs", cgDataRate);
147 cmd.AddValue("arFps", "The fps for AR UEs", arFps);
148 cmd.AddValue("vrFps", "The fps for vR UEs", vrFps);
149 cmd.AddValue("cgFps", "The fps for cg UEs", cgFps);
150 cmd.AddValue("numerology", "The numerology to be used.", numerology);
151 cmd.AddValue("txPower", "Tx power to be configured to gNB", txPower);
152 cmd.AddValue("frequency", "The system frequency", centralFrequency);
153 cmd.AddValue("bandwidth", "The system bandwidth", bandwidth);
154 cmd.AddValue("useUdp",
155 "if true, the NGMN applications will run over UDP connection, otherwise a TCP "
156 "connection will be used.",
157 useUdp);
158 cmd.AddValue("isMx1",
159 "if true M SDFs will be mapped to 1 DRB, otherwise the mapping will "
160 "be 1x1, i.e., 1 SDF to 1 DRB.",
161 isMx1);
162 cmd.AddValue("rngRun", "Rng run random number.", rngRun);
163 cmd.AddValue("appDuration", "Duration of the application in milliseconds.", appDuration);
164 cmd.Parse(argc, argv);
165
166 NS_ABORT_MSG_IF(appDuration < 1000, "The appDuration should be at least 1000ms.");
167 NS_ABORT_MSG_IF(
168 !vrUeNum && !arUeNum && !cgUeNum,
169 "Activate at least one type of XR traffic by configuring the number of XR users");
170
171 uint32_t simTimeMs = appStartTimeMs + appDuration + 2000;
172
173 // Set simulation run number
174 SeedManager::SetRun(rngRun);
175
176 // setup the nr simulation
177 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
178 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
179 // Set channel using UMa scenario and LOS channel condition
180 channelHelper->ConfigureFactories("UMa", "LOS", "ThreeGpp");
181 // simple band configuration and initialize
182 CcBwpCreator ccBwpCreator;
183 CcBwpCreator::SimpleOperationBandConf bandConf(centralFrequency, bandwidth, 1);
184
185 OperationBandInfo band = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
186 // Set and create channel to this band
187 channelHelper->AssignChannelsToBands({band});
189
190 nrHelper->SetGnbPhyAttribute("TxPower", DoubleValue(txPower));
191 nrHelper->SetGnbPhyAttribute("Numerology", UintegerValue(numerology));
192 nrHelper->SetGnbPhyAttribute("NoiseFigure", DoubleValue(5));
193 nrHelper->SetUePhyAttribute("TxPower", DoubleValue(23));
194 nrHelper->SetUePhyAttribute("NoiseFigure", DoubleValue(7));
195
196 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
197 Config::SetDefault("ns3::NrGnbRrc::EpsBearerToRlcMapping",
198 EnumValue(useUdp ? NrGnbRrc::RLC_UM_ALWAYS : NrGnbRrc::RLC_AM_ALWAYS));
199
200 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(4));
201 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
202 nrHelper->SetGnbAntennaAttribute("AntennaElement",
203 PointerValue(CreateObject<ThreeGppAntennaModel>()));
204 nrHelper->SetGnbAntennaAttribute("AntennaHorizontalSpacing", DoubleValue(0.5));
205 nrHelper->SetGnbAntennaAttribute("AntennaVerticalSpacing", DoubleValue(0.8));
206 nrHelper->SetGnbAntennaAttribute("DowntiltAngle", DoubleValue(0 * M_PI / 180.0));
207 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(1));
208 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(1));
209 nrHelper->SetUeAntennaAttribute("AntennaElement",
210 PointerValue(CreateObject<IsotropicAntennaModel>()));
211
212 // Beamforming method
213 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
214 idealBeamformingHelper->SetAttribute("BeamformingMethod",
215 TypeIdValue(DirectPathBeamforming::GetTypeId()));
216 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
217
218 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
219 nrHelper->SetEpcHelper(nrEpcHelper);
220 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
221
222 NodeContainer gNbNodes;
223 NodeContainer ueNodes;
224 MobilityHelper mobility;
225 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
226
227 const double gNbHeight = 25;
228 const double ueHeight = 1.5;
229
230 gNbNodes.Create(1);
231 ueNodes.Create(arUeNum + vrUeNum + cgUeNum);
232
233 Ptr<ListPositionAllocator> bsPositionAlloc = CreateObject<ListPositionAllocator>();
234 bsPositionAlloc->Add(Vector(0.0, 0.0, gNbHeight));
235 mobility.SetPositionAllocator(bsPositionAlloc);
236 mobility.Install(gNbNodes);
237
238 Ptr<RandomDiscPositionAllocator> ueDiscPositionAlloc =
239 CreateObject<RandomDiscPositionAllocator>();
240 ueDiscPositionAlloc->SetX(0.0);
241 ueDiscPositionAlloc->SetY(0.0);
242 ueDiscPositionAlloc->SetZ(ueHeight);
243 mobility.SetPositionAllocator(ueDiscPositionAlloc);
244
245 for (uint32_t i = 0; i < ueNodes.GetN(); i++)
246 {
247 mobility.Install(ueNodes.Get(i));
248 }
249
250 /*
251 * Create various NodeContainer(s) for the different traffic types.
252 * In ueArContainer, ueVrContainer, ueCgContainer, we will put
253 * AR, VR, CG UEs, respectively.*/
254 NodeContainer ueArContainer;
255 NodeContainer ueVrContainer;
256 NodeContainer ueCgContainer;
257
258 for (auto j = 0; j < arUeNum; ++j)
259 {
260 Ptr<Node> ue = ueNodes.Get(j);
261 ueArContainer.Add(ue);
262 }
263 for (auto j = arUeNum; j < arUeNum + vrUeNum; ++j)
264 {
265 Ptr<Node> ue = ueNodes.Get(j);
266 ueVrContainer.Add(ue);
267 }
268 for (auto j = arUeNum + vrUeNum; j < arUeNum + vrUeNum + cgUeNum; ++j)
269 {
270 Ptr<Node> ue = ueNodes.Get(j);
271 ueCgContainer.Add(ue);
272 }
273
274 NetDeviceContainer gNbNetDev = nrHelper->InstallGnbDevice(gNbNodes, allBwps);
275 NetDeviceContainer ueArNetDev = nrHelper->InstallUeDevice(ueArContainer, allBwps);
276 NetDeviceContainer ueVrNetDev = nrHelper->InstallUeDevice(ueVrContainer, allBwps);
277 NetDeviceContainer ueCgNetDev = nrHelper->InstallUeDevice(ueCgContainer, allBwps);
278
279 int64_t randomStream = 1;
280 randomStream += nrHelper->AssignStreams(gNbNetDev, randomStream);
281 randomStream += nrHelper->AssignStreams(ueArNetDev, randomStream);
282 randomStream += nrHelper->AssignStreams(ueVrNetDev, randomStream);
283 randomStream += nrHelper->AssignStreams(ueCgNetDev, randomStream);
284
285 // create the internet and install the IP stack on the UEs
286 // get SGW/PGW and create a single RemoteHost
287 auto [remoteHost, remoteHostIpv4Address] =
288 nrEpcHelper->SetupRemoteHost("100Gb/s", 1000, Seconds(0.000));
289 auto remoteHostContainer = NodeContainer(remoteHost);
290
291 InternetStackHelper internet;
292 internet.Install(ueNodes);
293
294 Ipv4InterfaceContainer ueArIpIface;
295 Ipv4InterfaceContainer ueVrIpIface;
296 Ipv4InterfaceContainer ueCgIpIface;
297
298 ueArIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueArNetDev));
299 ueVrIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVrNetDev));
300 ueCgIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueCgNetDev));
301
302 // attach UEs to the closest gNB
303 nrHelper->AttachToClosestGnb(ueArNetDev, gNbNetDev);
304 nrHelper->AttachToClosestGnb(ueVrNetDev, gNbNetDev);
305 nrHelper->AttachToClosestGnb(ueCgNetDev, gNbNetDev);
306
307 // Install sink application
308 ApplicationContainer serverApps;
309
310 // configure the transport protocol to be used
311 std::string transportProtocol;
312 transportProtocol = useUdp ? "ns3::UdpSocketFactory" : "ns3::TcpSocketFactory";
313 uint16_t dlPortArStart = 1121; // AR has 3 flows
314 uint16_t dlPortArStop = 1124;
315 uint16_t dlPortVrStart = 1131;
316 uint16_t dlPortCgStart = 1141;
317
318 // The bearer that will carry AR traffic
320 Ptr<NrEpcTft> arTft = Create<NrEpcTft>();
322 std::vector<Ptr<NrEpcTft>> arTfts;
323
324 if (isMx1)
325 {
326 dlpfAr.localPortStart = dlPortArStart;
327 dlpfAr.localPortEnd = dlPortArStop;
328 arTft->Add(dlpfAr);
329 }
330 else
331 {
332 // create 3 xrTfts for 1x1 mapping
333 for (uint32_t i = 0; i < 3; i++)
334 {
335 Ptr<NrEpcTft> tempTft = Create<NrEpcTft>();
336 dlpfAr.localPortStart = dlPortArStart + i;
337 dlpfAr.localPortEnd = dlPortArStart + i;
338 tempTft->Add(dlpfAr);
339 arTfts.emplace_back(tempTft);
340 }
341 }
342 // The bearer that will carry VR traffic
344
345 Ptr<NrEpcTft> vrTft = Create<NrEpcTft>();
347 dlpfVr.localPortStart = dlPortVrStart;
348 dlpfVr.localPortEnd = dlPortVrStart;
349 vrTft->Add(dlpfVr);
350
351 // The bearer that will carry CG traffic
353
354 Ptr<NrEpcTft> cgTft = Create<NrEpcTft>();
356 dlpfCg.localPortStart = dlPortCgStart;
357 dlpfCg.localPortEnd = dlPortCgStart;
358 cgTft->Add(dlpfCg);
359
360 // Install traffic generators
361 ApplicationContainer clientApps;
362 ApplicationContainer pingApps;
363
364 std::ostringstream xrFileTag;
365
366 for (uint32_t i = 0; i < ueArContainer.GetN(); ++i)
367 {
368 ConfigureXrApp(ueArContainer,
369 i,
370 ueArIpIface,
371 AR_M3,
372 arDataRate,
373 arFps,
374 dlPortArStart,
375 transportProtocol,
376 remoteHostContainer,
377 ueArNetDev,
378 nrHelper,
379 arBearer,
380 arTft,
381 isMx1,
382 arTfts,
383 serverApps,
384 clientApps,
385 pingApps);
386 }
387 // TODO for VR and CG of 2 flows Tfts and isMx1 have to be set. Currently they are
388 // hardcoded for 1 flow
389 for (uint32_t i = 0; i < ueVrContainer.GetN(); ++i)
390 {
391 ConfigureXrApp(ueVrContainer,
392 i,
393 ueVrIpIface,
394 VR_DL1,
395 vrDataRate,
396 vrFps,
397 dlPortVrStart,
398 transportProtocol,
399 remoteHostContainer,
400 ueVrNetDev,
401 nrHelper,
402 vrBearer,
403 vrTft,
404 true,
405 arTfts,
406 serverApps,
407 clientApps,
408 pingApps);
409 }
410 for (uint32_t i = 0; i < ueCgContainer.GetN(); ++i)
411 {
412 ConfigureXrApp(ueCgContainer,
413 i,
414 ueCgIpIface,
415 CG_DL1,
416 cgDataRate,
417 cgFps,
418 dlPortCgStart,
419 transportProtocol,
420 remoteHostContainer,
421 ueCgNetDev,
422 nrHelper,
423 cgBearer,
424 cgTft,
425 true,
426 arTfts,
427 serverApps,
428 clientApps,
429 pingApps);
430 }
431
432 pingApps.Start(MilliSeconds(100));
433 pingApps.Stop(MilliSeconds(appStartTimeMs));
434
435 // start server and client apps
436 serverApps.Start(MilliSeconds(appStartTimeMs));
437 clientApps.Start(MilliSeconds(appStartTimeMs));
438 serverApps.Stop(MilliSeconds(simTimeMs));
439 clientApps.Stop(MilliSeconds(appStartTimeMs + appDuration));
440
441 FlowMonitorHelper flowmonHelper;
442 NodeContainer endpointNodes;
443 endpointNodes.Add(remoteHost);
444 endpointNodes.Add(ueNodes);
445
446 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
447 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.0001));
448 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
449 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
450
451 Simulator::Stop(MilliSeconds(simTimeMs));
452 Simulator::Run();
453
454 // Print per-flow statistics
455 monitor->CheckForLostPackets();
456 Ptr<Ipv4FlowClassifier> classifier =
457 DynamicCast<Ipv4FlowClassifier>(flowmonHelper.GetClassifier());
458 FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
459
460 double averageFlowThroughput = 0.0;
461 double averageFlowDelay = 0.0;
462
463 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
464 i != stats.end();
465 ++i)
466 {
467 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
468 std::stringstream protoStream;
469 protoStream << (uint16_t)t.protocol;
470 if (t.protocol == 6)
471 {
472 protoStream.str("TCP");
473 }
474 if (t.protocol == 17)
475 {
476 protoStream.str("UDP");
477 }
478
479 Time txDuration = MilliSeconds(appDuration);
480 std::cout << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
481 << t.destinationAddress << ":" << t.destinationPort << ") proto "
482 << protoStream.str() << "\n";
483 std::cout << " Tx Packets: " << i->second.txPackets << "\n";
484 std::cout << " Tx Bytes: " << i->second.txBytes << "\n";
485 std::cout << " TxOffered: "
486 << ((i->second.txBytes * 8.0) / txDuration.GetSeconds()) * 1e-6 << " Mbps\n";
487 std::cout << " Rx Bytes: " << i->second.rxBytes << "\n";
488
489 if (i->second.rxPackets > 0)
490 {
491 // Measure the duration of the flow from receiver's perspective
492 Time rxDuration = i->second.timeLastRxPacket - i->second.timeFirstTxPacket;
493 averageFlowThroughput += ((i->second.rxBytes * 8.0) / rxDuration.GetSeconds()) * 1e-6;
494 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
495
496 double throughput = ((i->second.rxBytes * 8.0) / rxDuration.GetSeconds()) * 1e-6;
497 double delay = 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
498 double jitter = 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets;
499
500 std::cout << " Throughput: " << throughput << " Mbps\n";
501 std::cout << " Mean delay: " << delay << " ms\n";
502 std::cout << " Mean jitter: " << jitter << " ms\n";
503 }
504 else
505 {
506 std::cout << " Throughput: 0 Mbps\n";
507 std::cout << " Mean delay: 0 ms\n";
508 std::cout << " Mean upt: 0 Mbps \n";
509 std::cout << " Mean jitter: 0 ms\n";
510 }
511 std::cout << " Rx Packets: " << i->second.rxPackets << "\n";
512 }
513
514 std::cout << "\n\n Mean flow throughput: " << averageFlowThroughput / stats.size()
515 << "Mbps \n";
516 std::cout << " Mean flow delay: " << averageFlowDelay / stats.size() << " ms\n";
517
518 Simulator::Destroy();
519 return 0;
520}
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.
This class contains the specification of EPS Bearers.
@ NGBR_LOW_LAT_EMBB
Non-GBR Low Latency eMBB applications.
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.