5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-simple-qos-sched.cc
Go to the documentation of this file.
1// Copyright (c) 2022 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
28#include "ns3/antenna-module.h"
29#include "ns3/applications-module.h"
30#include "ns3/buildings-module.h"
31#include "ns3/config-store-module.h"
32#include "ns3/core-module.h"
33#include "ns3/flow-monitor-module.h"
34#include "ns3/internet-apps-module.h"
35#include "ns3/internet-module.h"
36#include "ns3/mobility-module.h"
37#include "ns3/nr-module.h"
38#include "ns3/point-to-point-module.h"
39
40using namespace ns3;
41
42NS_LOG_COMPONENT_DEFINE("CttcNrSimpleQosSched");
43
44int
45main(int argc, char* argv[])
46{
47 /*
48 * Variables that represent the parameters we will accept as input by the
49 * command line. Each of them is initialized with a default value, and
50 * possibly overridden below when command-line arguments are parsed.
51 */
52 // Scenario parameters (that we will use inside this script):
53 uint16_t gNbNum = 1;
54 uint16_t ueNumPergNb = 2;
55 bool logging = false;
56
57 // Simulation parameters. Please don't use double to indicate seconds; use
58 // ns-3 Time values which use integers to avoid portability issues.
59 Time simTime = MilliSeconds(1000);
60 Time udpAppStartTime = MilliSeconds(400);
61
62 // NR parameters. We will take the input from the command line, and then we
63 // will pass them inside the NR module.
64 uint16_t numerology = 0;
65 double centralFrequency = 4e9;
66 double bandwidth = 5e6;
67 double totalTxPower = 43;
68
69 bool enableOfdma = false;
70
71 uint8_t priorityTrafficScenario = 0; // default is saturation
72
73 uint16_t mcsTable = 2;
74
75 // Where we will store the output files.
76 std::string simTag = "default";
77 std::string outputDir = "./";
78
79 /*
80 * From here, we instruct the ns3::CommandLine class of all the input parameters
81 * that we may accept as input, as well as their description, and the storage
82 * variable.
83 */
84 CommandLine cmd;
85
86 cmd.AddValue("gNbNum", "The number of gNbs in multiple-ue topology", gNbNum);
87 cmd.AddValue("ueNumPergNb", "The number of UE per gNb in multiple-ue topology", ueNumPergNb);
88 cmd.AddValue("logging", "Enable logging", logging);
89 cmd.AddValue("priorityTrafficScenario",
90 "The traffic scenario for the case of priority. Can be 0: saturation"
91 "or 1: medium-load",
92 priorityTrafficScenario);
93 cmd.AddValue("simTime", "Simulation time", simTime);
94 cmd.AddValue("numerology", "The numerology to be used", numerology);
95 cmd.AddValue("centralFrequency", "The system frequency to be used", centralFrequency);
96 cmd.AddValue("bandwidth", "The system bandwidth to be used", bandwidth);
97 cmd.AddValue("totalTxPower",
98 "total tx power that will be proportionally assigned to"
99 " bands, CCs and bandwidth parts depending on each BWP bandwidth ",
100 totalTxPower);
101 cmd.AddValue("simTag",
102 "tag to be appended to output filenames to distinguish simulation campaigns",
103 simTag);
104 cmd.AddValue("outputDir", "directory where to store simulation results", outputDir);
105 cmd.AddValue("enableOfdma",
106 "If set to true it enables Ofdma scheduler. Default value is false (Tdma)",
107 enableOfdma);
108
109 cmd.Parse(argc, argv);
110
111 // enable logging or not
112 if (logging)
113 {
114 LogLevel logLevel1 =
115 (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_LEVEL_INFO);
116 LogComponentEnable("NrMacSchedulerNs3", logLevel1);
117 LogComponentEnable("NrMacSchedulerTdma", logLevel1);
118 }
119
120 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
121
122 /*
123 * Create the scenario. In our examples, we heavily use helpers that setup
124 * the gnbs and ue following a pre-defined pattern. Please have a look at the
125 * GridScenarioHelper documentation to see how the nodes will be distributed.
126 */
127 int64_t randomStream = 1;
128
129 GridScenarioHelper gridScenario;
130 gridScenario.SetRows(1);
131 gridScenario.SetColumns(gNbNum);
132 gridScenario.SetHorizontalBsDistance(5.0);
133 gridScenario.SetVerticalBsDistance(5.0);
134 gridScenario.SetBsHeight(1.5);
135 gridScenario.SetUtHeight(1.5);
136 // must be set before BS number
137 gridScenario.SetSectorization(GridScenarioHelper::SINGLE);
138 gridScenario.SetBsNumber(gNbNum);
139 gridScenario.SetUtNumber(ueNumPergNb * gNbNum);
140 gridScenario.SetScenarioHeight(3); // Create a 3x3 scenario where the UE will
141 gridScenario.SetScenarioLength(3); // be distributed.
142 randomStream += gridScenario.AssignStreams(randomStream);
143 gridScenario.CreateScenario();
144
145 uint32_t udpPacketSizeULL;
146 uint32_t udpPacketSizeBe;
147 uint32_t lambdaULL = 1000;
148 uint32_t lambdaBe = 1000;
149
150 if (priorityTrafficScenario == 0) // saturation
151 {
152 udpPacketSizeULL = 3000;
153 udpPacketSizeBe = 3000;
154 }
155 else if (priorityTrafficScenario == 1) // medium-load
156 {
157 udpPacketSizeULL = 3000;
158 udpPacketSizeBe = 1252;
159 }
160 else
161 {
162 NS_ABORT_MSG("The priorityTrafficScenario chosen is not correct. "
163 "Please choose among 0: saturation and 1: medium-load");
164 }
165
166 /*
167 * Create two different NodeContainer for the different traffic type.
168 * In ueLowLat we will put the UEs that will receive low-latency traffic,
169 * while in ueVoice we will put the UEs that will receive the voice traffic.
170 */
171 NodeContainer ueLowLatContainer;
172 NodeContainer ueVoiceContainer;
173
174 for (uint32_t j = 0; j < gridScenario.GetUserTerminals().GetN(); ++j)
175 {
176 Ptr<Node> ue = gridScenario.GetUserTerminals().Get(j);
177
178 j % 2 == 0 ? ueLowLatContainer.Add(ue) : ueVoiceContainer.Add(ue);
179 }
180
181 if (priorityTrafficScenario == 1)
182 {
183 lambdaULL = 1000 / ueLowLatContainer.GetN();
184 lambdaBe = 1000 / ueVoiceContainer.GetN();
185 }
186
187 // setup the nr simulation
188 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
189 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
190 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
191
192 // Put the pointers inside nrHelper
193 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
194 nrHelper->SetEpcHelper(nrEpcHelper);
195 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
196
197 std::stringstream schedulerType;
198 std::string subType;
199 std::string sched;
200
201 subType = !enableOfdma ? "Tdma" : "Ofdma";
202 sched = "Qos";
203 schedulerType << "ns3::NrMacScheduler" << subType << sched;
204 std::cout << "SchedulerType: " << schedulerType.str() << std::endl;
205 nrHelper->SetSchedulerTypeId(TypeId::LookupByName(schedulerType.str()));
206
207 // Error Model: gNB and UE with same spectrum error model.
208 std::string errorModel = "ns3::NrEesmIrT" + std::to_string(mcsTable);
209 nrHelper->SetDlErrorModel(errorModel);
210 nrHelper->SetUlErrorModel(errorModel);
211
212 // Both DL and UL AMC will have the same model behind.
213 nrHelper->SetGnbDlAmcAttribute("AmcModel", EnumValue(NrAmc::ErrorModel));
214 nrHelper->SetGnbUlAmcAttribute("AmcModel", EnumValue(NrAmc::ErrorModel));
215
216 // Beamforming method
217 idealBeamformingHelper->SetAttribute("BeamformingMethod",
218 TypeIdValue(DirectPathBeamforming::GetTypeId()));
219
220 // Antennas for all the UEs
221 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(1));
222 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(1));
223 nrHelper->SetUeAntennaAttribute("AntennaElement",
224 PointerValue(CreateObject<IsotropicAntennaModel>()));
225
226 // Antennas for all the gNbs
227 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(1));
228 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(1));
229 nrHelper->SetGnbAntennaAttribute("AntennaElement",
230 PointerValue(CreateObject<IsotropicAntennaModel>()));
231
232 /*
233 * Setup the configuration of the spectrum. One operation band is deployed
234 * with 1 component carrier (CC), automatically generated by the ccBwpManager
235 */
237 CcBwpCreator ccBwpCreator;
239 const uint8_t numOfCcs = 1;
240
241 /*
242 * The configured spectrum division for TDD is:
243 *
244 * |----Band1----|
245 * |-----CC1-----|
246 * |-----BWP1----|
247 */
248
249 // Create the configuration for the CcBwpHelper. SimpleOperationBandConf creates
250 // a single BWP per CC
251 CcBwpCreator::SimpleOperationBandConf bandConf(centralFrequency, bandwidth, numOfCcs);
252
253 bandConf.m_numBwp = 1;
254 // By using the configuration created, it is time to make the operation band
255 band = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
256 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
257 // Set the spectrum channel
258 channelHelper->ConfigureFactories("UMi", "Default", "ThreeGpp");
259 // Set attributes for the channel
260 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
261 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(MilliSeconds(0)));
262 channelHelper->SetChannelConditionModelAttribute("UpdatePeriod", TimeValue(MilliSeconds(0)));
263 // Set and create the channel to the band
264 channelHelper->AssignChannelsToBands({band});
265 allBwps = CcBwpCreator::GetAllBwps({band});
266
267 double x = pow(10, totalTxPower / 10);
268
269 Packet::EnableChecking();
270 Packet::EnablePrinting();
271
272 uint32_t bwpIdForLowLat = 0;
273 uint32_t bwpIdForVoice = 0;
274
275 // gNb routing between Bearer and bandwidh part
276 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB",
277 UintegerValue(bwpIdForLowLat));
278 nrHelper->SetGnbBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
279
280 // Ue routing between Bearer and bandwidth part
281 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdForLowLat));
282 nrHelper->SetUeBwpManagerAlgorithmAttribute("GBR_CONV_VOICE", UintegerValue(bwpIdForVoice));
283
284 /*
285 * We have configured the attributes we needed. Now, install and get the pointers
286 * to the NetDevices, which contains all the NR stack:
287 */
288 NetDeviceContainer gnbNetDev =
289 nrHelper->InstallGnbDevice(gridScenario.GetBaseStations(), allBwps);
290 NetDeviceContainer ueLowLatNetDev = nrHelper->InstallUeDevice(ueLowLatContainer, allBwps);
291 NetDeviceContainer ueVoiceNetDev = nrHelper->InstallUeDevice(ueVoiceContainer, allBwps);
292
293 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
294 randomStream += nrHelper->AssignStreams(ueLowLatNetDev, randomStream);
295 randomStream += nrHelper->AssignStreams(ueVoiceNetDev, randomStream);
296
297 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("Numerology", UintegerValue(numerology));
298 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("TxPower", DoubleValue(10 * log10(x)));
299
300 // create the internet and install the IP stack on the UEs
301 // get SGW/PGW and create a single RemoteHost
302 auto [remoteHost, remoteHostIpv4Address] =
303 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
304
305 InternetStackHelper internet;
306
307 internet.Install(gridScenario.GetUserTerminals());
308
309 Ipv4InterfaceContainer ueLowLatIpIface;
310 Ipv4InterfaceContainer ueVoiceIpIface;
311 ueLowLatIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueLowLatNetDev));
312 ueVoiceIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueVoiceNetDev));
313
314 // attach UEs to the closest gNB
315 nrHelper->AttachToClosestGnb(ueLowLatNetDev, gnbNetDev);
316 nrHelper->AttachToClosestGnb(ueVoiceNetDev, gnbNetDev);
317
318 /*
319 * Traffic part. Install two kind of traffic: low-latency and voice, each
320 * identified by a particular source port.
321 */
322 uint16_t dlPortLowLat = 1234;
323 uint16_t dlPortVoice = 1235;
324
325 ApplicationContainer serverApps;
326
327 // The sink will always listen to the specified ports
328 UdpServerHelper dlPacketSinkLowLat(dlPortLowLat);
329 UdpServerHelper dlPacketSinkVoice(dlPortVoice);
330
331 // The server, that is the application which is listening, is installed in the UE
332 serverApps.Add(dlPacketSinkLowLat.Install(ueLowLatContainer));
333 serverApps.Add(dlPacketSinkVoice.Install(ueVoiceContainer));
334
335 /*
336 * Configure attributes for the different generators, using user-provided
337 * parameters for generating a CBR traffic
338 *
339 * Low-Latency configuration and object creation:
340 */
341 UdpClientHelper dlClientLowLat;
342 dlClientLowLat.SetAttribute("RemotePort", UintegerValue(dlPortLowLat));
343 dlClientLowLat.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
344 dlClientLowLat.SetAttribute("PacketSize", UintegerValue(udpPacketSizeULL));
345 dlClientLowLat.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaULL)));
346
347 // The bearer that will carry low latency traffic
349
350 // The filter for the low-latency traffic
351 Ptr<NrEpcTft> lowLatTft = Create<NrEpcTft>();
352 NrEpcTft::PacketFilter dlpfLowLat;
353 dlpfLowLat.localPortStart = dlPortLowLat;
354 dlpfLowLat.localPortEnd = dlPortLowLat;
355 lowLatTft->Add(dlpfLowLat);
356
357 // Voice configuration and object creation:
358 UdpClientHelper dlClientVoice;
359 dlClientVoice.SetAttribute("RemotePort", UintegerValue(dlPortVoice));
360 dlClientVoice.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
361 dlClientVoice.SetAttribute("PacketSize", UintegerValue(udpPacketSizeBe));
362 dlClientVoice.SetAttribute("Interval", TimeValue(Seconds(1.0 / lambdaBe)));
363
364 // The bearer that will carry voice traffic
366
367 // The filter for the voice traffic
368 Ptr<NrEpcTft> voiceTft = Create<NrEpcTft>();
369 NrEpcTft::PacketFilter dlpfVoice;
370 dlpfVoice.localPortStart = dlPortVoice;
371 dlpfVoice.localPortEnd = dlPortVoice;
372 voiceTft->Add(dlpfVoice);
373
374 // Install the applications
375 ApplicationContainer clientApps;
376
377 for (uint32_t i = 0; i < ueLowLatContainer.GetN(); ++i)
378 {
379 Ptr<NetDevice> ueDevice = ueLowLatNetDev.Get(i);
380 Address ueAddress = ueLowLatIpIface.GetAddress(i);
381
382 // The client, who is transmitting, is installed in the remote host,
383 // with destination address set to the address of the UE
384 dlClientLowLat.SetAttribute("RemoteAddress", AddressValue(ueAddress));
385 clientApps.Add(dlClientLowLat.Install(remoteHost));
386
387 // Activate a dedicated bearer for the traffic type
388 nrHelper->ActivateDedicatedEpsBearer(ueDevice, lowLatBearer, lowLatTft);
389 }
390
391 for (uint32_t i = 0; i < ueVoiceContainer.GetN(); ++i)
392 {
393 Ptr<NetDevice> ueDevice = ueVoiceNetDev.Get(i);
394 Address ueAddress = ueVoiceIpIface.GetAddress(i);
395
396 // The client, who is transmitting, is installed in the remote host,
397 // with destination address set to the address of the UE
398 dlClientVoice.SetAttribute("RemoteAddress", AddressValue(ueAddress));
399 clientApps.Add(dlClientVoice.Install(remoteHost));
400
401 // Activate a dedicated bearer for the traffic type
402 nrHelper->ActivateDedicatedEpsBearer(ueDevice, voiceBearer, voiceTft);
403 }
404
405 // start UDP server and client apps
406 serverApps.Start(udpAppStartTime);
407 clientApps.Start(udpAppStartTime);
408 serverApps.Stop(simTime);
409 clientApps.Stop(simTime);
410
411 // enable the traces provided by the nr module
412 // nrHelper->EnableTraces();
413
414 FlowMonitorHelper flowmonHelper;
415 NodeContainer endpointNodes;
416 endpointNodes.Add(remoteHost);
417 endpointNodes.Add(gridScenario.GetUserTerminals());
418
419 Ptr<ns3::FlowMonitor> monitor = flowmonHelper.Install(endpointNodes);
420 monitor->SetAttribute("DelayBinWidth", DoubleValue(0.001));
421 monitor->SetAttribute("JitterBinWidth", DoubleValue(0.001));
422 monitor->SetAttribute("PacketSizeBinWidth", DoubleValue(20));
423
424 Simulator::Stop(simTime);
425 Simulator::Run();
426
427 /*
428 * To check what was installed in the memory, i.e., BWPs of gNB Device, and its configuration.
429 * Example is: Node 1 -> Device 0 -> BandwidthPartMap -> {0,1} BWPs -> NrGnbPhy -> Numerology,
430 GtkConfigStore config;
431 config.ConfigureAttributes ();
432 */
433
434 // Print per-flow statistics
435 monitor->CheckForLostPackets();
436 Ptr<Ipv4FlowClassifier> classifier =
437 DynamicCast<Ipv4FlowClassifier>(flowmonHelper.GetClassifier());
438 FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
439
440 double averageFlowThroughput = 0.0;
441 double averageFlowDelay = 0.0;
442
443 std::ofstream outFile;
444 std::string filename = outputDir + "/" + simTag;
445 outFile.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
446 if (!outFile.is_open())
447 {
448 std::cerr << "Can't open file " << filename << std::endl;
449 return 1;
450 }
451
452 outFile.setf(std::ios_base::fixed);
453
454 double flowDuration = (simTime - udpAppStartTime).GetSeconds();
455 for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
456 i != stats.end();
457 ++i)
458 {
459 Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
460 std::stringstream protoStream;
461 protoStream << (uint16_t)t.protocol;
462 if (t.protocol == 6)
463 {
464 protoStream.str("TCP");
465 }
466 if (t.protocol == 17)
467 {
468 protoStream.str("UDP");
469 }
470 outFile << "Flow " << i->first << " (" << t.sourceAddress << ":" << t.sourcePort << " -> "
471 << t.destinationAddress << ":" << t.destinationPort << ") proto "
472 << protoStream.str() << "\n";
473 outFile << " Tx Packets: " << i->second.txPackets << "\n";
474 outFile << " Tx Bytes: " << i->second.txBytes << "\n";
475 outFile << " TxOffered: " << i->second.txBytes * 8.0 / flowDuration / 1000.0 / 1000.0
476 << " Mbps\n";
477 outFile << " Rx Bytes: " << i->second.rxBytes << "\n";
478 if (i->second.rxPackets > 0)
479 {
480 // Measure the duration of the flow from receiver's perspective
481 averageFlowThroughput += i->second.rxBytes * 8.0 / flowDuration / 1000 / 1000;
482 averageFlowDelay += 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets;
483
484 outFile << " Throughput: " << i->second.rxBytes * 8.0 / flowDuration / 1000 / 1000
485 << " Mbps\n";
486 outFile << " Mean delay: "
487 << 1000 * i->second.delaySum.GetSeconds() / i->second.rxPackets << " ms\n";
488 // outFile << " Mean upt: " << i->second.uptSum / i->second.rxPackets / 1000/1000 << "
489 // Mbps \n";
490 outFile << " Mean jitter: "
491 << 1000 * i->second.jitterSum.GetSeconds() / i->second.rxPackets << " ms\n";
492 }
493 else
494 {
495 outFile << " Throughput: 0 Mbps\n";
496 outFile << " Mean delay: 0 ms\n";
497 outFile << " Mean jitter: 0 ms\n";
498 }
499 outFile << " Rx Packets: " << i->second.rxPackets << "\n";
500 }
501
502 outFile << "\n\n Mean flow throughput: " << averageFlowThroughput / stats.size() << "\n";
503 outFile << " Mean flow delay: " << averageFlowDelay / stats.size() << "\n";
504
505 outFile.close();
506
507 std::ifstream f(filename.c_str());
508
509 if (f.is_open())
510 {
511 std::cout << f.rdbuf();
512 }
513
514 Simulator::Destroy();
515 return 0;
516}
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 GridScenarioHelper class.
void SetRows(uint32_t r)
SetRows.
void SetHorizontalBsDistance(double d)
SetHorizontalBsDistance.
void SetVerticalBsDistance(double d)
SetVerticalBsDistance.
void CreateScenario() override
Create the scenario, with the configured parameter.
int64_t AssignStreams(int64_t stream)
void SetColumns(uint32_t c)
SetColumns.
const NodeContainer & GetUserTerminals() const
Get the list of user nodes.
void SetBsNumber(std::size_t n)
Set the number of base stations.
void SetUtNumber(std::size_t n)
Set the number of UT/UE.
const NodeContainer & GetBaseStations() const
Get the list of gnb/base station nodes.
@ ErrorModel
Error Model version (can use different error models, see NrErrorModel)
Definition nr-amc.h:81
This class contains the specification of EPS Bearers.
@ NGBR_LOW_LAT_EMBB
Non-GBR Low Latency eMBB applications.
@ GBR_CONV_VOICE
GBR Conversational Voice.
void SetBsHeight(double h)
SetGnbHeight.
void SetUtHeight(double h)
SetUeHeight.
void SetSectorization(SiteSectorizationType numSectors)
Sets the number of sectors of every site.
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.