5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-error-model.cc
Go to the documentation of this file.
1// Copyright (c) 2019 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/core-module.h"
8#include "ns3/internet-apps-module.h"
9#include "ns3/internet-module.h"
10#include "ns3/ipv4-global-routing-helper.h"
11#include "ns3/log.h"
12#include "ns3/mobility-module.h"
13#include "ns3/nr-helper.h"
14#include "ns3/nr-module.h"
15#include "ns3/nr-point-to-point-epc-helper.h"
16#include "ns3/point-to-point-helper.h"
17
18#include <chrono>
19
58using namespace ns3;
59
60NS_LOG_COMPONENT_DEFINE("CttcErrorModelExample");
61
62static Ptr<ListPositionAllocator>
63GetGnbPositions(double gNbHeight = 10.0)
64{
65 Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator>();
66 pos->Add(Vector(0.0, 0.0, gNbHeight));
67
68 return pos;
69}
70
71static Ptr<ListPositionAllocator>
72GetUePositions(double ueY, double ueHeight = 1.5)
73{
74 Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator>();
75 pos->Add(Vector(0.0, ueY, ueHeight));
76
77 return pos;
78}
79
80static std::vector<uint64_t> packetsTime;
81
82static void
83PrintRxPkt([[maybe_unused]] std::string context, Ptr<const Packet> pkt)
84{
85 // ASSUMING ONE UE
86 SeqTsHeader seqTs;
87 pkt->PeekHeader(seqTs);
88 packetsTime.push_back((Simulator::Now() - seqTs.GetTs()).GetMicroSeconds());
89}
90
91int
92main(int argc, char* argv[])
93{
94 uint32_t mcs = 13;
95 const uint8_t gNbNum = 1;
96 const uint8_t ueNum = 1;
97 double totalTxPower = 4;
98 uint16_t numerologyBwp = 4;
99 double centralFrequencyBand = 28e9;
100 double bandwidthBand = 100e6;
101 double ueY = 30.0;
102
103 double simTime = 10.0; // 50 seconds: to take statistics
104 uint32_t pktSize = 500;
105 Time udpAppStartTime = MilliSeconds(1000);
106 Time packetInterval = MilliSeconds(200);
107 Time updateChannelInterval = MilliSeconds(150);
108 bool isUl = false;
109
110 std::string errorModel = "ns3::NrEesmCcT1";
111
112 CommandLine cmd(__FILE__);
113
114 cmd.AddValue("simTime", "Simulation time", simTime);
115 cmd.AddValue("mcs", "The MCS that will be used in this example", mcs);
116 cmd.AddValue("errorModelType",
117 "Error model type: ns3::NrEesmCcT1, ns3::NrEesmCcT2, ns3::NrEesmIrT1, "
118 "ns3::NrEesmIrT2, ns3::NrLteMiErrorModel",
119 errorModel);
120 cmd.AddValue("ueY", "Y position of any UE", ueY);
121 cmd.AddValue("pktSize", "Packet Size", pktSize);
122 cmd.AddValue("isUl", "Is this an UL transmission?", isUl);
123
124 cmd.Parse(argc, argv);
125
126 uint32_t packets = (simTime - udpAppStartTime.GetSeconds()) / packetInterval.GetSeconds();
127 NS_ABORT_IF(packets == 0);
128
129 /*
130 * Default values for the simulation. We are progressively removing all
131 * the instances of SetDefault, but we need it for legacy code (LTE)
132 */
133 Config::SetDefault("ns3::NrRlcUm::MaxTxBufferSize", UintegerValue(999999999));
134
135 Config::SetDefault("ns3::NrAmc::ErrorModelType", TypeIdValue(TypeId::LookupByName(errorModel)));
136 Config::SetDefault("ns3::NrAmc::AmcModel",
137 EnumValue(NrAmc::ShannonModel)); // NOT USED in this example. MCS is fixed.
138
139 // create base stations and mobile terminals
140 NodeContainer gNbNodes;
141 NodeContainer ueNodes;
142 MobilityHelper mobility;
143
144 double gNbHeight = 10.0;
145 double ueHeight = 1.5;
146
147 gNbNodes.Create(gNbNum);
148 ueNodes.Create(ueNum);
149
150 Ptr<ListPositionAllocator> gNbPositionAlloc = GetGnbPositions(gNbHeight);
151 Ptr<ListPositionAllocator> uePositionAlloc = GetUePositions(ueY, ueHeight);
152
153 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
154 mobility.SetPositionAllocator(gNbPositionAlloc);
155 mobility.Install(gNbNodes);
156
157 mobility.SetPositionAllocator(uePositionAlloc);
158 mobility.Install(ueNodes);
159
160 /*
161 * Setup the NR module. We create the various helpers needed for the
162 * NR simulation:
163 * - nrEpcHelper, which will setup the core network
164 * - IdealBeamformingHelper, which takes care of the beamforming part
165 * - NrHelper, which takes care of creating and connecting the various
166 * part of the NR stack
167 * - NrChannelHelper, which will setup the spectrum channel
168 */
169 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
170 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
171 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
172 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
173
174 // Put the pointers inside nrHelper
175 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
176 nrHelper->SetEpcHelper(nrEpcHelper);
177
178 // Set the channel using UMi scenario
179 channelHelper->ConfigureFactories("UMi", "Default", "ThreeGpp");
180 /*
181 * Spectrum division. We create one operational band, with one CC, and the CC with a single
182 * bandwidth part.
183 */
185 CcBwpCreator ccBwpCreator;
186 const uint8_t numCcPerBand = 1;
187
188 CcBwpCreator::SimpleOperationBandConf bandConf(centralFrequencyBand,
189 bandwidthBand,
190 numCcPerBand);
191 OperationBandInfo band = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
192 // Set attributes of the channel
193 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(updateChannelInterval));
194 channelHelper->SetChannelConditionModelAttribute("UpdatePeriod", TimeValue(MilliSeconds(0)));
195 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
196
197 // Set and create the channel in the band
198 channelHelper->AssignChannelsToBands({band});
199 allBwps = CcBwpCreator::GetAllBwps({band});
200
201 Packet::EnableChecking();
202 Packet::EnablePrinting();
203
204 /*
205 * Case (i): Attributes valid for all the nodes
206 */
207 // Beamforming method
208 idealBeamformingHelper->SetAttribute("BeamformingMethod",
209 TypeIdValue(DirectPathBeamforming::GetTypeId()));
210
211 // Core latency
212 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
213
214 // Antennas for all the UEs
215 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(2));
216 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(4));
217 nrHelper->SetUeAntennaAttribute("AntennaElement",
218 PointerValue(CreateObject<IsotropicAntennaModel>()));
219
220 // Antennas for all the gNbs
221 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(4));
222 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
223 nrHelper->SetGnbAntennaAttribute("AntennaElement",
224 PointerValue(CreateObject<IsotropicAntennaModel>()));
225
226 // Scheduler
227 nrHelper->SetSchedulerAttribute("FixedMcsDl", BooleanValue(true));
228 nrHelper->SetSchedulerAttribute("FixedMcsUl", BooleanValue(true));
229 nrHelper->SetSchedulerAttribute("StartingMcsDl", UintegerValue(mcs));
230 nrHelper->SetSchedulerAttribute("StartingMcsUl", UintegerValue(mcs));
231
232 // Error Model: UE and GNB with same spectrum error model.
233 nrHelper->SetUlErrorModel(errorModel);
234 nrHelper->SetDlErrorModel(errorModel);
235
236 // Both DL and UL AMC will have the same model behind.
237 // Note: NOT USED in this example. MCS is fixed.
238 nrHelper->SetGnbDlAmcAttribute("AmcModel", EnumValue(NrAmc::ShannonModel));
239 nrHelper->SetGnbUlAmcAttribute("AmcModel", EnumValue(NrAmc::ShannonModel));
240
241 nrHelper->SetUePhyAttribute("TxPower", DoubleValue(totalTxPower));
242
243 uint32_t bwpId = 0;
244
245 // gNb routing between Bearer and bandwidh part
246 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpId));
247
248 // Ue routing between Bearer and bandwidth part
249 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpId));
250
251 NetDeviceContainer gnbNetDev = nrHelper->InstallGnbDevice(gNbNodes, allBwps);
252 NetDeviceContainer ueNetDev = nrHelper->InstallUeDevice(ueNodes, allBwps);
253
254 int64_t randomStream = 1;
255 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
256 randomStream += nrHelper->AssignStreams(ueNetDev, randomStream);
257
258 /*
259 * Case (iii): Go node for node and change the attributes we have to setup
260 * per-node.
261 */
262
263 // Get the first netdevice (gnbNetDev.Get (0)) and the first bandwidth part (0)
264 // and set the attribute.
265 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)
266 ->SetAttribute("Numerology", UintegerValue(numerologyBwp));
267 nrHelper->GetGnbPhy(gnbNetDev.Get(0), 0)->SetAttribute("TxPower", DoubleValue(totalTxPower));
268
269 // create the internet and install the IP stack on the UEs
270 // get SGW/PGW and create a single RemoteHost
271 auto [remoteHost, remoteHostIpv4Address] =
272 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
273 NodeContainer remoteHostContainer(remoteHost);
274
275 InternetStackHelper internet;
276 internet.Install(ueNodes);
277 Ipv4InterfaceContainer ueIpIface;
278 ueIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDev));
279
280 // assign IP address to UEs, and install UDP downlink applications
281 uint16_t dlPort = 1234;
282 UdpServerHelper dlPacketSinkHelper(dlPort);
283 ApplicationContainer txApps;
284 ApplicationContainer sinkApps;
285 NodeContainer txNodes;
286 NodeContainer sinkNodes;
287 std::vector<Ipv4Address> sinkIps;
288
289 if (isUl)
290 {
291 sinkIps.push_back(remoteHostIpv4Address);
292 sinkNodes = remoteHostContainer;
293 txNodes = ueNodes;
294 }
295 else
296 {
297 sinkIps.resize(ueIpIface.GetN());
298 for (uint32_t i = 0; i < ueIpIface.GetN(); i++)
299 {
300 sinkIps[i] = ueIpIface.GetAddress(i);
301 }
302 sinkNodes = ueNodes;
303 txNodes = remoteHostContainer;
304 }
305
306 // configure here UDP traffic
307 for (uint32_t i = 0; i < txNodes.GetN(); ++i)
308 {
309 for (uint32_t j = 0; j < sinkNodes.GetN(); ++j)
310 {
311 UdpClientHelper dlClient(sinkIps[j], dlPort);
312 dlClient.SetAttribute("MaxPackets", UintegerValue(packets));
313 dlClient.SetAttribute("PacketSize", UintegerValue(pktSize));
314 dlClient.SetAttribute("Interval", TimeValue(packetInterval));
315
316 txApps.Add(dlClient.Install(txNodes.Get(i)));
317 }
318 }
319
320 sinkApps.Add(dlPacketSinkHelper.Install(sinkNodes));
321 for (uint32_t j = 0; j < sinkApps.GetN(); ++j)
322 {
323 Ptr<UdpServer> client = DynamicCast<UdpServer>(sinkApps.Get(j));
324 NS_ASSERT(client != nullptr);
325 std::stringstream ss;
326 ss << j;
327 client->TraceConnect("Rx", ss.str(), MakeCallback(&PrintRxPkt));
328 }
329
330 // start UDP server and client apps
331 sinkApps.Start(udpAppStartTime);
332 txApps.Start(udpAppStartTime);
333 sinkApps.Stop(Seconds(simTime));
334 txApps.Stop(Seconds(simTime));
335
336 // attach UEs to the closest g
337 nrHelper->AttachToClosestGnb(ueNetDev, gnbNetDev);
338
339 // enable the traces provided by the nr module
340 // nrHelper->EnableTraces();
341
342 Simulator::Stop(Seconds(simTime));
343
344 auto start = std::chrono::steady_clock::now();
345
346 Simulator::Run();
347
348 auto end = std::chrono::steady_clock::now();
349
350 uint64_t sum = 0;
351 uint32_t cont = 0;
352 for (auto& v : packetsTime)
353 {
354 if (v < 100000)
355 {
356 sum += v;
357 cont++;
358 }
359 }
360 std::cout << "Packets received: " << packetsTime.size() << std::endl;
361 std::cout << "Counter (packets not affected by reordering): " << +cont << std::endl;
362
363 if (!packetsTime.empty() && cont > 0)
364 {
365 std::cout << "Average e2e latency (over all received packets): " << sum / packetsTime.size()
366 << " us" << std::endl;
367 std::cout << "Average e2e latency (over counter): " << sum / cont << " us" << std::endl;
368 }
369 else
370 {
371 std::cout << "Average e2e latency: Not Available" << std::endl;
372 }
373
374 for (auto it = sinkApps.Begin(); it != sinkApps.End(); ++it)
375 {
376 uint64_t recv = DynamicCast<UdpServer>(*it)->GetReceived();
377 std::cout << "Sent: " << packets << " Recv: " << recv << " Lost: " << packets - recv
378 << " pkts, ( " << (static_cast<double>(packets - recv) / packets) * 100.0
379 << " % )" << std::endl;
380 }
381
382 Simulator::Destroy();
383
384 std::cout << "Running time: "
385 << std::chrono::duration_cast<std::chrono::seconds>(end - start).count() << " s."
386 << std::endl;
387 return 0;
388}
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.
@ ShannonModel
Shannon based model (very conservative)
Definition nr-amc.h:80
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
Operation band information structure.