5G-LENA nr-v3.1-69-g2dd513a7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-helper.cc
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "nr-helper.h"
6
7#include "nr-bearer-stats-calculator.h"
8#include "nr-epc-helper.h"
9#include "nr-mac-rx-trace.h"
10#include "nr-phy-rx-trace.h"
11
12#include <ns3/bandwidth-part-gnb.h>
13#include <ns3/bandwidth-part-ue.h>
14#include <ns3/beam-manager.h>
15#include <ns3/buildings-channel-condition-model.h>
16#include <ns3/bwp-manager-algorithm.h>
17#include <ns3/bwp-manager-gnb.h>
18#include <ns3/bwp-manager-ue.h>
19#include <ns3/config.h>
20#include <ns3/multi-model-spectrum-channel.h>
21#include <ns3/names.h>
22#include <ns3/nr-ch-access-manager.h>
23#include <ns3/nr-chunk-processor.h>
24#include <ns3/nr-epc-gnb-application.h>
25#include <ns3/nr-epc-ue-nas.h>
26#include <ns3/nr-epc-x2.h>
27#include <ns3/nr-gnb-mac.h>
28#include <ns3/nr-gnb-net-device.h>
29#include <ns3/nr-gnb-phy.h>
30#include <ns3/nr-mac-scheduler-tdma-rr.h>
31#include <ns3/nr-pm-search-full.h>
32#include <ns3/nr-rrc-protocol-ideal.h>
33#include <ns3/nr-rrc-protocol-real.h>
34#include <ns3/nr-ue-mac.h>
35#include <ns3/nr-ue-net-device.h>
36#include <ns3/nr-ue-phy.h>
37#include <ns3/nr-ue-rrc.h>
38#include <ns3/pointer.h>
39#include <ns3/three-gpp-channel-model.h>
40#include <ns3/three-gpp-propagation-loss-model.h>
41#include <ns3/three-gpp-spectrum-propagation-loss-model.h>
42#include <ns3/three-gpp-v2v-channel-condition-model.h>
43#include <ns3/three-gpp-v2v-propagation-loss-model.h>
44#include <ns3/uniform-planar-array.h>
45
46#include <algorithm>
47
48namespace ns3
49{
50
51/* ... */
52NS_LOG_COMPONENT_DEFINE("NrHelper");
53
54NS_OBJECT_ENSURE_REGISTERED(NrHelper);
55
57{
58 NS_LOG_FUNCTION(this);
59 m_channelFactory.SetTypeId(MultiModelSpectrumChannel::GetTypeId());
60 m_gnbNetDeviceFactory.SetTypeId(NrGnbNetDevice::GetTypeId());
61 m_ueNetDeviceFactory.SetTypeId(NrUeNetDevice::GetTypeId());
62 m_ueMacFactory.SetTypeId(NrUeMac::GetTypeId());
63 m_gnbMacFactory.SetTypeId(NrGnbMac::GetTypeId());
64 m_ueSpectrumFactory.SetTypeId(NrSpectrumPhy::GetTypeId());
65 m_gnbSpectrumFactory.SetTypeId(NrSpectrumPhy::GetTypeId());
66 m_uePhyFactory.SetTypeId(NrUePhy::GetTypeId());
67 m_gnbPhyFactory.SetTypeId(NrGnbPhy::GetTypeId());
68 m_ueChannelAccessManagerFactory.SetTypeId(NrAlwaysOnAccessManager::GetTypeId());
69 m_gnbChannelAccessManagerFactory.SetTypeId(NrAlwaysOnAccessManager::GetTypeId());
70 m_schedFactory.SetTypeId(NrMacSchedulerTdmaRR::GetTypeId());
71 m_ueAntennaFactory.SetTypeId(UniformPlanarArray::GetTypeId());
72 m_gnbAntennaFactory.SetTypeId(UniformPlanarArray::GetTypeId());
73 m_gnbBwpManagerAlgoFactory.SetTypeId(BwpManagerAlgorithmStatic::GetTypeId());
74 m_ueBwpManagerAlgoFactory.SetTypeId(BwpManagerAlgorithmStatic::GetTypeId());
75 m_gnbUlAmcFactory.SetTypeId(NrAmc::GetTypeId());
76 m_gnbDlAmcFactory.SetTypeId(NrAmc::GetTypeId());
77 m_gnbBeamManagerFactory.SetTypeId(BeamManager::GetTypeId());
78 m_ueBeamManagerFactory.SetTypeId(BeamManager::GetTypeId());
79 m_spectrumPropagationFactory.SetTypeId(ThreeGppSpectrumPropagationLossModel::GetTypeId());
80
81 // Initialization that is there just because the user can configure attribute
82 // through the helper methods without making it sad that no TypeId is set.
83 // When the TypeId is changed, the user-set attribute will be maintained.
84 m_pathlossModelFactory.SetTypeId(ThreeGppPropagationLossModel::GetTypeId());
85 m_channelConditionModelFactory.SetTypeId(ThreeGppChannelConditionModel::GetTypeId());
86
87 Config::SetDefault("ns3::NrEpsBearer::Release", UintegerValue(18));
88}
89
91{
92 NS_LOG_FUNCTION(this);
93 if (m_beamformingHelper)
94 {
95 m_beamformingHelper->Dispose();
96 }
97 m_beamformingHelper = nullptr;
98}
99
100TypeId
102{
103 static TypeId tid =
104 TypeId("ns3::NrHelper")
105 .SetParent<Object>()
106 .AddConstructor<NrHelper>()
107 .AddAttribute("EnableMimoFeedback",
108 "Generate CQI feedback with RI and PMI for MIMO support",
109 BooleanValue(false),
110 MakeBooleanAccessor(&NrHelper::m_enableMimoFeedback),
111 MakeBooleanChecker())
112 .AddAttribute("PmSearchMethod",
113 "Type of the precoding matrix search method.",
114 TypeIdValue(NrPmSearchFull::GetTypeId()),
115 MakeTypeIdAccessor(&NrHelper::SetPmSearchTypeId),
116 MakeTypeIdChecker())
117 .AddAttribute("UseIdealRrc",
118 "If true, NrRrcProtocolIdeal will be used for RRC signaling. "
119 "If false, NrRrcProtocolReal will be used.",
120 BooleanValue(true),
121 MakeBooleanAccessor(&NrHelper::m_useIdealRrc),
122 MakeBooleanChecker())
123 .AddAttribute("HandoverAlgorithm",
124 "The type of handover algorithm to be used for gNBs. "
125 "The allowed values for this attributes are the type names "
126 "of any class inheriting from ns3::LteHandoverAlgorithm.",
127 StringValue("ns3::NrNoOpHandoverAlgorithm"),
128 MakeStringAccessor(&NrHelper::SetHandoverAlgorithmType,
129 &NrHelper::GetHandoverAlgorithmType),
130 MakeStringChecker());
131 return tid;
132}
133
134typedef std::function<void(ObjectFactory*, ObjectFactory*)> InitPathLossFn;
135
136static void
137InitRma(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
138{
139 pathlossModelFactory->SetTypeId(ThreeGppRmaPropagationLossModel::GetTypeId());
140 channelConditionModelFactory->SetTypeId(ThreeGppRmaChannelConditionModel::GetTypeId());
141}
142
143static void
144InitRma_LoS(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
145{
146 pathlossModelFactory->SetTypeId(ThreeGppRmaPropagationLossModel::GetTypeId());
147 channelConditionModelFactory->SetTypeId(AlwaysLosChannelConditionModel::GetTypeId());
148}
149
150static void
151InitRma_nLoS(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
152{
153 pathlossModelFactory->SetTypeId(ThreeGppRmaPropagationLossModel::GetTypeId());
154 channelConditionModelFactory->SetTypeId(NeverLosChannelConditionModel::GetTypeId());
155}
156
157static void
158InitUma(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
159{
160 pathlossModelFactory->SetTypeId(ThreeGppUmaPropagationLossModel::GetTypeId());
161 channelConditionModelFactory->SetTypeId(ThreeGppUmaChannelConditionModel::GetTypeId());
162}
163
164static void
165InitUma_LoS(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
166{
167 pathlossModelFactory->SetTypeId(ThreeGppUmaPropagationLossModel::GetTypeId());
168 channelConditionModelFactory->SetTypeId(AlwaysLosChannelConditionModel::GetTypeId());
169}
170
171static void
172InitUma_nLoS(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
173{
174 pathlossModelFactory->SetTypeId(ThreeGppUmaPropagationLossModel::GetTypeId());
175 channelConditionModelFactory->SetTypeId(NeverLosChannelConditionModel::GetTypeId());
176}
177
178static void
179InitUmi(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
180{
181 pathlossModelFactory->SetTypeId(ThreeGppUmiStreetCanyonPropagationLossModel::GetTypeId());
182 channelConditionModelFactory->SetTypeId(
183 ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId());
184}
185
186static void
187InitUmi_LoS(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
188{
189 pathlossModelFactory->SetTypeId(ThreeGppUmiStreetCanyonPropagationLossModel::GetTypeId());
190 channelConditionModelFactory->SetTypeId(AlwaysLosChannelConditionModel::GetTypeId());
191}
192
193static void
194InitUmi_nLoS(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
195{
196 pathlossModelFactory->SetTypeId(ThreeGppUmiStreetCanyonPropagationLossModel::GetTypeId());
197 channelConditionModelFactory->SetTypeId(NeverLosChannelConditionModel::GetTypeId());
198}
199
200static void
201InitIndoorOpen(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
202{
203 pathlossModelFactory->SetTypeId(ThreeGppIndoorOfficePropagationLossModel::GetTypeId());
204 channelConditionModelFactory->SetTypeId(
205 ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId());
206}
207
208static void
209InitIndoorOpen_LoS(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
210{
211 pathlossModelFactory->SetTypeId(ThreeGppIndoorOfficePropagationLossModel::GetTypeId());
212 channelConditionModelFactory->SetTypeId(AlwaysLosChannelConditionModel::GetTypeId());
213}
214
215static void
216InitIndoorOpen_nLoS(ObjectFactory* pathlossModelFactory,
217 ObjectFactory* channelConditionModelFactory)
218{
219 pathlossModelFactory->SetTypeId(ThreeGppIndoorOfficePropagationLossModel::GetTypeId());
220 channelConditionModelFactory->SetTypeId(NeverLosChannelConditionModel::GetTypeId());
221}
222
223static void
224InitIndoorMixed(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
225{
226 pathlossModelFactory->SetTypeId(ThreeGppIndoorOfficePropagationLossModel::GetTypeId());
227 channelConditionModelFactory->SetTypeId(
228 ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId());
229}
230
231static void
232InitIndoorMixed_LoS(ObjectFactory* pathlossModelFactory,
233 ObjectFactory* channelConditionModelFactory)
234{
235 pathlossModelFactory->SetTypeId(ThreeGppIndoorOfficePropagationLossModel::GetTypeId());
236 channelConditionModelFactory->SetTypeId(AlwaysLosChannelConditionModel::GetTypeId());
237}
238
239static void
240InitIndoorMixed_nLoS(ObjectFactory* pathlossModelFactory,
241 ObjectFactory* channelConditionModelFactory)
242{
243 pathlossModelFactory->SetTypeId(ThreeGppIndoorOfficePropagationLossModel::GetTypeId());
244 channelConditionModelFactory->SetTypeId(NeverLosChannelConditionModel::GetTypeId());
245}
246
247static void
248InitUmaBuildings(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
249{
250 pathlossModelFactory->SetTypeId(ThreeGppUmaPropagationLossModel::GetTypeId());
251 channelConditionModelFactory->SetTypeId(BuildingsChannelConditionModel::GetTypeId());
252}
253
254static void
255InitUmiBuildings(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
256{
257 pathlossModelFactory->SetTypeId(ThreeGppUmiStreetCanyonPropagationLossModel::GetTypeId());
258 channelConditionModelFactory->SetTypeId(BuildingsChannelConditionModel::GetTypeId());
259}
260
261static void
262InitV2VHighway(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
263{
264 pathlossModelFactory->SetTypeId(ThreeGppV2vHighwayPropagationLossModel::GetTypeId());
265 channelConditionModelFactory->SetTypeId(ThreeGppV2vHighwayChannelConditionModel::GetTypeId());
266}
267
268static void
269InitV2VUrban(ObjectFactory* pathlossModelFactory, ObjectFactory* channelConditionModelFactory)
270{
271 pathlossModelFactory->SetTypeId(ThreeGppV2vUrbanPropagationLossModel::GetTypeId());
272 channelConditionModelFactory->SetTypeId(ThreeGppV2vUrbanChannelConditionModel::GetTypeId());
273}
274
275void
277{
278 NS_LOG_FUNCTION(this);
279
280 static std::unordered_map<BandwidthPartInfo::Scenario, InitPathLossFn, std::hash<int>>
281 initLookupTable{
282 {BandwidthPartInfo::RMa,
283 std::bind(&InitRma, std::placeholders::_1, std::placeholders::_2)},
285 std::bind(&InitRma_LoS, std::placeholders::_1, std::placeholders::_2)},
287 std::bind(&InitRma_nLoS, std::placeholders::_1, std::placeholders::_2)},
289 std::bind(&InitUma, std::placeholders::_1, std::placeholders::_2)},
291 std::bind(&InitUma_LoS, std::placeholders::_1, std::placeholders::_2)},
293 std::bind(&InitUma_nLoS, std::placeholders::_1, std::placeholders::_2)},
295 std::bind(&InitUmi, std::placeholders::_1, std::placeholders::_2)},
297 std::bind(&InitUmi_LoS, std::placeholders::_1, std::placeholders::_2)},
299 std::bind(&InitUmi_nLoS, std::placeholders::_1, std::placeholders::_2)},
301 std::bind(&InitIndoorOpen, std::placeholders::_1, std::placeholders::_2)},
303 std::bind(&InitIndoorOpen_LoS, std::placeholders::_1, std::placeholders::_2)},
305 std::bind(&InitIndoorOpen_nLoS, std::placeholders::_1, std::placeholders::_2)},
307 std::bind(&InitIndoorMixed, std::placeholders::_1, std::placeholders::_2)},
309 std::bind(&InitIndoorMixed_LoS, std::placeholders::_1, std::placeholders::_2)},
311 std::bind(&InitIndoorMixed_nLoS, std::placeholders::_1, std::placeholders::_2)},
313 std::bind(&InitUmaBuildings, std::placeholders::_1, std::placeholders::_2)},
315 std::bind(&InitUmiBuildings, std::placeholders::_1, std::placeholders::_2)},
317 std::bind(&InitV2VHighway, std::placeholders::_1, std::placeholders::_2)},
319 std::bind(&InitV2VUrban, std::placeholders::_1, std::placeholders::_2)},
320 };
321
322 // Iterate over all CCs, and instantiate the channel and propagation model
323 for (const auto& cc : band->m_cc)
324 {
325 for (const auto& bwp : cc->m_bwp)
326 {
327 // Initialize the type ID of the factories by calling the relevant
328 // static function defined above and stored inside the lookup table
329 initLookupTable.at(bwp->m_scenario)(&m_pathlossModelFactory,
330 &m_channelConditionModelFactory);
331
332 auto channelConditionModel =
333 m_channelConditionModelFactory.Create<ChannelConditionModel>();
334
335 if (bwp->m_propagation == nullptr && flags & INIT_PROPAGATION)
336 {
337 bwp->m_propagation = m_pathlossModelFactory.Create<ThreeGppPropagationLossModel>();
338 bwp->m_propagation->SetAttributeFailSafe("Frequency",
339 DoubleValue(bwp->m_centralFrequency));
340 DynamicCast<ThreeGppPropagationLossModel>(bwp->m_propagation)
341 ->SetChannelConditionModel(channelConditionModel);
342 }
343
344 if (bwp->m_3gppChannel == nullptr && flags & INIT_FADING)
345 {
346 bwp->m_3gppChannel =
347 m_spectrumPropagationFactory.Create<ThreeGppSpectrumPropagationLossModel>();
348 DynamicCast<ThreeGppSpectrumPropagationLossModel>(bwp->m_3gppChannel)
349 ->SetChannelModelAttribute("Frequency", DoubleValue(bwp->m_centralFrequency));
350 DynamicCast<ThreeGppSpectrumPropagationLossModel>(bwp->m_3gppChannel)
351 ->SetChannelModelAttribute("Scenario", StringValue(bwp->GetScenario()));
352 DynamicCast<ThreeGppSpectrumPropagationLossModel>(bwp->m_3gppChannel)
353 ->SetChannelModelAttribute("ChannelConditionModel",
354 PointerValue(channelConditionModel));
355 }
356
357 if (bwp->m_channel == nullptr && flags & INIT_CHANNEL)
358 {
359 bwp->m_channel = m_channelFactory.Create<SpectrumChannel>();
360 bwp->m_channel->AddPropagationLossModel(bwp->m_propagation);
361 bwp->m_channel->AddPhasedArraySpectrumPropagationLossModel(bwp->m_3gppChannel);
362 }
363 }
364 }
365}
366
367std::pair<double, BandwidthPartInfoPtrVector>
368NrHelper::CreateBandwidthParts(std::vector<CcBwpCreator::SimpleOperationBandConf> bandConfs)
369{
370 CcBwpCreator ccBwpCreator;
371 double totalBandwidth = 0.0;
372 for (auto& bandConf : bandConfs)
373 {
374 m_bands.push_back(ccBwpCreator.CreateOperationBandContiguousCc(bandConf));
375 InitializeOperationBand(&m_bands.back());
376 totalBandwidth += bandConf.m_channelBandwidth;
377 }
378 std::vector<std::reference_wrapper<OperationBandInfo>> bandsRefs(m_bands.rbegin(),
379 m_bands.rbegin() +
380 bandConfs.size());
381
382 return std::make_pair(totalBandwidth, CcBwpCreator::GetAllBwps(bandsRefs));
383}
384
385uint32_t
386NrHelper::GetNumberBwp(const Ptr<const NetDevice>& gnbDevice)
387{
388 NS_LOG_FUNCTION(gnbDevice);
389 Ptr<const NrGnbNetDevice> netDevice = DynamicCast<const NrGnbNetDevice>(gnbDevice);
390 if (netDevice == nullptr)
391 {
392 return 0;
393 }
394 return netDevice->GetCcMapSize();
395}
396
397Ptr<NrGnbPhy>
398NrHelper::GetGnbPhy(const Ptr<NetDevice>& gnbDevice, uint32_t bwpIndex)
399{
400 NS_LOG_FUNCTION(gnbDevice << bwpIndex);
401 NS_ASSERT(bwpIndex < UINT8_MAX);
402 Ptr<NrGnbNetDevice> netDevice = DynamicCast<NrGnbNetDevice>(gnbDevice);
403 if (netDevice == nullptr)
404 {
405 return nullptr;
406 }
407 return netDevice->GetPhy(static_cast<uint8_t>(bwpIndex));
408}
409
410Ptr<NrGnbMac>
411NrHelper::GetGnbMac(const Ptr<NetDevice>& gnbDevice, uint32_t bwpIndex)
412{
413 NS_LOG_FUNCTION(gnbDevice << bwpIndex);
414 NS_ASSERT(bwpIndex < UINT8_MAX);
415 Ptr<NrGnbNetDevice> netDevice = DynamicCast<NrGnbNetDevice>(gnbDevice);
416 if (netDevice == nullptr)
417 {
418 return nullptr;
419 }
420 return netDevice->GetMac(static_cast<uint8_t>(bwpIndex));
421}
422
423Ptr<NrUeMac>
424NrHelper::GetUeMac(const Ptr<NetDevice>& ueDevice, uint32_t bwpIndex)
425{
426 NS_LOG_FUNCTION(ueDevice << bwpIndex);
427 NS_ASSERT(bwpIndex < UINT8_MAX);
428 Ptr<NrUeNetDevice> netDevice = DynamicCast<NrUeNetDevice>(ueDevice);
429 if (netDevice == nullptr)
430 {
431 return nullptr;
432 }
433 return netDevice->GetMac(static_cast<uint8_t>(bwpIndex));
434}
435
436Ptr<NrUePhy>
437NrHelper::GetUePhy(const Ptr<NetDevice>& ueDevice, uint32_t bwpIndex)
438{
439 NS_LOG_FUNCTION(ueDevice << bwpIndex);
440 NS_ASSERT(bwpIndex < UINT8_MAX);
441 Ptr<NrUeNetDevice> netDevice = DynamicCast<NrUeNetDevice>(ueDevice);
442 if (netDevice == nullptr)
443 {
444 return nullptr;
445 }
446 return netDevice->GetPhy(static_cast<uint8_t>(bwpIndex));
447}
448
449Ptr<BwpManagerGnb>
450NrHelper::GetBwpManagerGnb(const Ptr<NetDevice>& gnbDevice)
451{
452 NS_LOG_FUNCTION(gnbDevice);
453
454 Ptr<NrGnbNetDevice> netDevice = DynamicCast<NrGnbNetDevice>(gnbDevice);
455 if (netDevice == nullptr)
456 {
457 return nullptr;
458 }
459
460 return netDevice->GetBwpManager();
461}
462
463Ptr<BwpManagerUe>
464NrHelper::GetBwpManagerUe(const Ptr<NetDevice>& ueDevice)
465{
466 NS_LOG_FUNCTION(ueDevice);
467
468 Ptr<NrUeNetDevice> netDevice = DynamicCast<NrUeNetDevice>(ueDevice);
469 if (netDevice == nullptr)
470 {
471 return nullptr;
472 }
473
474 return netDevice->GetBwpManager();
475}
476
477Ptr<NrMacScheduler>
478NrHelper::GetScheduler(const Ptr<NetDevice>& gnbDevice, uint32_t bwpIndex)
479{
480 NS_LOG_FUNCTION(gnbDevice << bwpIndex);
481
482 Ptr<NrGnbNetDevice> netDevice = DynamicCast<NrGnbNetDevice>(gnbDevice);
483 if (netDevice == nullptr)
484 {
485 return nullptr;
486 }
487
488 return netDevice->GetScheduler(bwpIndex);
489}
490
491void
493{
494 m_snrTest = snrTest;
495}
496
497bool
499{
500 return m_snrTest;
501}
502
503NetDeviceContainer
504NrHelper::InstallUeDevice(const NodeContainer& c,
505 const std::vector<std::reference_wrapper<BandwidthPartInfoPtr>>& allBwps)
506{
507 NS_LOG_FUNCTION(this);
508 Initialize(); // Run DoInitialize (), if necessary
509 NetDeviceContainer devices;
510 for (NodeContainer::Iterator i = c.Begin(); i != c.End(); ++i)
511 {
512 Ptr<Node> node = *i;
513 Ptr<NetDevice> device = InstallSingleUeDevice(node, allBwps);
514 device->SetAddress(Mac48Address::Allocate());
515 devices.Add(device);
516 }
517 return devices;
518}
519
520NetDeviceContainer
521NrHelper::InstallGnbDevice(const NodeContainer& c,
522 const std::vector<std::reference_wrapper<BandwidthPartInfoPtr>> allBwps)
523{
524 NS_LOG_FUNCTION(this);
525 Initialize(); // Run DoInitialize (), if necessary
526 NetDeviceContainer devices;
527 for (NodeContainer::Iterator i = c.Begin(); i != c.End(); ++i)
528 {
529 Ptr<Node> node = *i;
530 Ptr<NetDevice> device = InstallSingleGnbDevice(node, allBwps);
531 device->SetAddress(Mac48Address::Allocate());
532 devices.Add(device);
533 }
534 return devices;
535}
536
537void
538NrHelper::UpdateDeviceConfigs(const NetDeviceContainer& netDevs)
539{
540 for (uint32_t i = 0; i < netDevs.GetN(); i++)
541 {
542 auto ueNetDev = DynamicCast<NrUeNetDevice>(netDevs.Get(i));
543 auto gnbNetDev = DynamicCast<NrGnbNetDevice>(netDevs.Get(i));
544 if (ueNetDev)
545 {
546 ueNetDev->UpdateConfig();
547 }
548 if (gnbNetDev)
549 {
550 gnbNetDev->UpdateConfig();
551 }
552 }
553}
554
555Ptr<NrUeMac>
556NrHelper::CreateUeMac() const
557{
558 NS_LOG_FUNCTION(this);
559 Ptr<NrUeMac> mac = m_ueMacFactory.Create<NrUeMac>();
560 return mac;
561}
562
563Ptr<NrUePhy>
564NrHelper::CreateUePhy(const Ptr<Node>& n,
565 const std::unique_ptr<BandwidthPartInfo>& bwp,
566 const Ptr<NrUeNetDevice>& dev,
567 const NrSpectrumPhy::NrPhyDlHarqFeedbackCallback& dlHarqCallback,
568 const NrSpectrumPhy::NrPhyRxCtrlEndOkCallback& phyRxCtrlCallback)
569{
570 NS_LOG_FUNCTION(this);
571
572 Ptr<NrUePhy> phy = m_uePhyFactory.Create<NrUePhy>();
573
574 NS_ASSERT(bwp->m_channel != nullptr);
575
576 phy->InstallCentralFrequency(bwp->m_centralFrequency);
577
578 phy->ScheduleStartEventLoop(n->GetId(), 0, 0, 0);
579
580 // connect CAM and PHY
581 Ptr<NrChAccessManager> cam =
582 DynamicCast<NrChAccessManager>(m_ueChannelAccessManagerFactory.Create());
583 phy->SetCam(cam);
584 // set device
585 phy->SetDevice(dev);
586
587 Ptr<MobilityModel> mm = n->GetObject<MobilityModel>();
588 NS_ASSERT_MSG(
589 mm,
590 "MobilityModel needs to be set on node before calling NrHelper::InstallUeDevice ()");
591
592 Ptr<NrSpectrumPhy> channelPhy =
593 m_ueSpectrumFactory.Create<NrSpectrumPhy>(); // Create NrSpectrumPhy
594
595 Ptr<NrHarqPhy> harq = Create<NrHarqPhy>(); // Create HARQ instance
596 channelPhy->InstallHarqPhyModule(harq);
597 channelPhy->SetPhyDlHarqFeedbackCallback(dlHarqCallback);
598
599 channelPhy->SetIsGnb(false);
600 channelPhy->SetDevice(dev); // each NrSpectrumPhy should have a pointer to device
601
602 Ptr<UniformPlanarArray> antenna =
603 m_ueAntennaFactory.Create<UniformPlanarArray>(); // Create antenna per panel
604 channelPhy->SetAntenna(antenna);
605
606 cam->SetNrSpectrumPhy(channelPhy); // connect CAM
607
608 Ptr<NrChunkProcessor> pData = Create<NrChunkProcessor>();
609 pData->AddCallback(MakeCallback(&NrSpectrumPhy::UpdateSinrPerceived, channelPhy));
610 channelPhy->AddDataSinrChunkProcessor(pData);
611
612 Ptr<NrMimoChunkProcessor> pDataMimo{nullptr};
613 if (bwp->m_3gppChannel)
614 {
615 pDataMimo = Create<NrMimoChunkProcessor>();
616 pDataMimo->AddCallback(MakeCallback(&NrSpectrumPhy::UpdateMimoSinrPerceived, channelPhy));
617 channelPhy->AddDataMimoChunkProcessor(pDataMimo);
618 }
619 if (bwp->m_3gppChannel && m_enableMimoFeedback)
620 {
621 // Report DL CQI, PMI, RI (channel quality, MIMO precoding matrix and rank indicators)
622 pDataMimo->AddCallback(MakeCallback(&NrUePhy::GenerateDlCqiReportMimo, phy));
623 }
624 else
625 {
626 // SISO CQI feedback
627 pData->AddCallback(MakeCallback(&NrUePhy::GenerateDlCqiReport, phy));
628 }
629
630 Ptr<NrChunkProcessor> pRs = Create<NrChunkProcessor>();
631 pRs->AddCallback(MakeCallback(&NrUePhy::ReportRsReceivedPower, phy));
632 channelPhy->AddRsPowerChunkProcessor(pRs);
633
634 Ptr<NrChunkProcessor> pSinr = Create<NrChunkProcessor>();
635 pSinr->AddCallback(MakeCallback(&NrSpectrumPhy::ReportDlCtrlSinr, channelPhy));
636 channelPhy->AddDlCtrlSinrChunkProcessor(pSinr);
637
638 channelPhy->SetChannel(bwp->m_channel);
639 channelPhy->InstallPhy(phy);
640 channelPhy->SetMobility(mm);
641 channelPhy->SetPhyRxDataEndOkCallback(MakeCallback(&NrUePhy::PhyDataPacketReceived, phy));
642 channelPhy->SetPhyRxCtrlEndOkCallback(phyRxCtrlCallback);
643 channelPhy->SetPhyRxPssCallback(MakeCallback(&NrUePhy::ReceivePss, phy));
644
645 Ptr<BeamManager> beamManager = m_ueBeamManagerFactory.Create<BeamManager>();
646 beamManager->Configure(antenna);
647 channelPhy->SetBeamManager(beamManager);
648 phy->InstallSpectrumPhy(channelPhy);
649 return phy;
650}
651
652Ptr<NetDevice>
653NrHelper::InstallSingleUeDevice(
654 const Ptr<Node>& n,
655 const std::vector<std::reference_wrapper<BandwidthPartInfoPtr>> allBwps)
656{
657 NS_LOG_FUNCTION(this);
658
659 Ptr<NrUeNetDevice> dev = m_ueNetDeviceFactory.Create<NrUeNetDevice>();
660 dev->SetNode(n);
661
662 std::map<uint8_t, Ptr<BandwidthPartUe>> ueCcMap;
663
664 // Create, for each ue, its bandwidth parts
665 for (uint32_t bwpId = 0; bwpId < allBwps.size(); ++bwpId)
666 {
667 Ptr<BandwidthPartUe> cc = CreateObject<BandwidthPartUe>();
668 double bwInKhz = allBwps[bwpId].get()->m_channelBandwidth / 1000.0;
669 NS_ABORT_MSG_IF(bwInKhz / 100.0 > 65535.0,
670 "A bandwidth of " << bwInKhz / 100.0 << " kHz cannot be represented");
671 cc->SetUlBandwidth(static_cast<uint16_t>(bwInKhz / 100));
672 cc->SetDlBandwidth(static_cast<uint16_t>(bwInKhz / 100));
673 cc->SetDlEarfcn(0); // Used for nothing..
674 cc->SetUlEarfcn(0); // Used for nothing..
675
676 auto mac = CreateUeMac();
677 cc->SetMac(mac);
678
679 auto phy = CreateUePhy(
680 n,
681 allBwps[bwpId].get(),
682 dev,
683 MakeCallback(&NrUeNetDevice::EnqueueDlHarqFeedback, dev),
684 std::bind(&NrUeNetDevice::RouteIngoingCtrlMsgs, dev, std::placeholders::_1, bwpId));
685
686 phy->SetBwpId(bwpId);
687 cc->SetPhy(phy);
688
689 if (bwpId == 0)
690 {
691 cc->SetAsPrimary(true);
692 }
693 else
694 {
695 cc->SetAsPrimary(false);
696 }
697
698 ueCcMap.insert(std::make_pair(bwpId, cc));
699 }
700
701 Ptr<NrUeComponentCarrierManager> ccmUe =
702 DynamicCast<NrUeComponentCarrierManager>(CreateObject<BwpManagerUe>());
703 DynamicCast<BwpManagerUe>(ccmUe)->SetBwpManagerAlgorithm(
704 m_ueBwpManagerAlgoFactory.Create<BwpManagerAlgorithm>());
705
706 Ptr<NrUeRrc> rrc = CreateObject<NrUeRrc>();
707 rrc->m_numberOfComponentCarriers = ueCcMap.size();
708 // run InitializeSap to create the proper number of sap provider/users
709 rrc->InitializeSap();
710 rrc->SetNrMacSapProvider(ccmUe->GetNrMacSapProvider());
711 // setting ComponentCarrierManager SAP
712 rrc->SetNrCcmRrcSapProvider(ccmUe->GetNrCcmRrcSapProvider());
713 ccmUe->SetNrCcmRrcSapUser(rrc->GetNrCcmRrcSapUser());
714 ccmUe->SetNumberOfComponentCarriers(ueCcMap.size());
715
716 if (m_useIdealRrc)
717 {
718 Ptr<NrUeRrcProtocolIdeal> rrcProtocol = CreateObject<NrUeRrcProtocolIdeal>();
719 rrcProtocol->SetUeRrc(rrc);
720 rrc->AggregateObject(rrcProtocol);
721 rrcProtocol->SetNrUeRrcSapProvider(rrc->GetNrUeRrcSapProvider());
722 rrc->SetNrUeRrcSapUser(rrcProtocol->GetNrUeRrcSapUser());
723 }
724 else
725 {
726 Ptr<nr::UeRrcProtocolReal> rrcProtocol = CreateObject<nr::UeRrcProtocolReal>();
727 rrcProtocol->SetUeRrc(rrc);
728 rrc->AggregateObject(rrcProtocol);
729 rrcProtocol->SetNrUeRrcSapProvider(rrc->GetNrUeRrcSapProvider());
730 rrc->SetNrUeRrcSapUser(rrcProtocol->GetNrUeRrcSapUser());
731 }
732
733 if (m_nrEpcHelper != nullptr)
734 {
735 rrc->SetUseRlcSm(false);
736 }
737 else
738 {
739 rrc->SetUseRlcSm(true);
740 }
741 Ptr<NrEpcUeNas> nas = CreateObject<NrEpcUeNas>();
742
743 nas->SetAsSapProvider(rrc->GetAsSapProvider());
744 nas->SetDevice(dev);
745 nas->SetForwardUpCallback(MakeCallback(&NrUeNetDevice::Receive, dev));
746
747 rrc->SetAsSapUser(nas->GetAsSapUser());
748
749 for (auto& it : ueCcMap)
750 {
751 rrc->SetNrUeCmacSapProvider(it.second->GetMac()->GetUeCmacSapProvider(), it.first);
752 it.second->GetMac()->SetUeCmacSapUser(rrc->GetNrUeCmacSapUser(it.first));
753
754 it.second->GetPhy()->SetUeCphySapUser(rrc->GetNrUeCphySapUser());
755 rrc->SetNrUeCphySapProvider(it.second->GetPhy()->GetUeCphySapProvider(), it.first);
756
757 it.second->GetPhy()->SetPhySapUser(it.second->GetMac()->GetPhySapUser());
758 it.second->GetMac()->SetPhySapProvider(it.second->GetPhy()->GetPhySapProvider());
759
760 bool ccmTest =
761 ccmUe->SetComponentCarrierMacSapProviders(it.first,
762 it.second->GetMac()->GetUeMacSapProvider());
763
764 if (!ccmTest)
765 {
766 NS_FATAL_ERROR("Error in SetComponentCarrierMacSapProviders");
767 }
768 }
769
770 dev->SetAttribute("Imsi", UintegerValue(n->GetId()));
771 dev->SetCcMap(ueCcMap);
772 dev->SetAttribute("nrUeRrc", PointerValue(rrc));
773 dev->SetAttribute("NrEpcUeNas", PointerValue(nas));
774 dev->SetAttribute("NrUeComponentCarrierManager", PointerValue(ccmUe));
775
776 n->AddDevice(dev);
777
778 if (m_nrEpcHelper != nullptr)
779 {
780 m_nrEpcHelper->AddUe(dev, dev->GetImsi());
781 }
782
783 dev->Initialize();
784 return dev;
785}
786
787Ptr<NrGnbPhy>
788NrHelper::CreateGnbPhy(const Ptr<Node>& n,
789 const std::unique_ptr<BandwidthPartInfo>& bwp,
790 const Ptr<NrGnbNetDevice>& dev,
791 const NrSpectrumPhy::NrPhyRxCtrlEndOkCallback& phyEndCtrlCallback)
792{
793 NS_LOG_FUNCTION(this);
794
795 Ptr<NrGnbPhy> phy = m_gnbPhyFactory.Create<NrGnbPhy>();
796
797 DoubleValue frequency;
798 phy->InstallCentralFrequency(bwp->m_centralFrequency);
799
800 phy->ScheduleStartEventLoop(n->GetId(), 0, 0, 0);
801
802 // PHY <--> CAM
803 Ptr<NrChAccessManager> cam =
804 DynamicCast<NrChAccessManager>(m_gnbChannelAccessManagerFactory.Create());
805 phy->SetCam(cam);
806 phy->SetDevice(dev);
807
808 Ptr<MobilityModel> mm = n->GetObject<MobilityModel>();
809 NS_ASSERT_MSG(
810 mm,
811 "MobilityModel needs to be set on node before calling NrHelper::InstallGnbDevice ()");
812
813 Ptr<NrSpectrumPhy> channelPhy = m_gnbSpectrumFactory.Create<NrSpectrumPhy>();
814 Ptr<UniformPlanarArray> antenna = m_gnbAntennaFactory.Create<UniformPlanarArray>();
815 channelPhy->SetAntenna(antenna);
816 cam->SetNrSpectrumPhy(channelPhy);
817
818 channelPhy->InstallHarqPhyModule(
819 Create<NrHarqPhy>()); // there should be one HARQ instance per NrSpectrumPhy
820 channelPhy->SetIsGnb(true);
821 channelPhy->SetDevice(dev); // each NrSpectrumPhy should have a pointer to device
822 channelPhy->SetChannel(
823 bwp->m_channel); // each NrSpectrumPhy needs to have a pointer to the SpectrumChannel
824 // object of the corresponding spectrum part
825 channelPhy->InstallPhy(phy); // each NrSpectrumPhy should have a pointer to its NrPhy
826
827 Ptr<NrChunkProcessor> pData =
828 Create<NrChunkProcessor>(); // create pData chunk processor per NrSpectrumPhy
829 Ptr<NrChunkProcessor> pSrs =
830 Create<NrChunkProcessor>(); // create pSrs per processor per NrSpectrumPhy
831 if (!m_snrTest)
832 {
833 // TODO: rename to GeneratePuschCqiReport, replace when enabling uplink MIMO
834 pData->AddCallback(MakeCallback(&NrGnbPhy::GenerateDataCqiReport,
835 phy)); // connect DATA chunk processor that will
836 // call GenerateDataCqiReport function
837 pData->AddCallback(MakeCallback(&NrSpectrumPhy::UpdateSinrPerceived,
838 channelPhy)); // connect DATA chunk processor that will
839 // call UpdateSinrPerceived function
840 pSrs->AddCallback(MakeCallback(&NrSpectrumPhy::UpdateSrsSinrPerceived,
841 channelPhy)); // connect SRS chunk processor that will
842 // call UpdateSrsSinrPerceived function
843 if (bwp->m_3gppChannel)
844 {
845 auto pDataMimo = Create<NrMimoChunkProcessor>();
846 pDataMimo->AddCallback(
847 MakeCallback(&NrSpectrumPhy::UpdateMimoSinrPerceived, channelPhy));
848 channelPhy->AddDataMimoChunkProcessor(pDataMimo);
849 }
850 }
851 channelPhy->AddDataSinrChunkProcessor(pData); // set DATA chunk processor to NrSpectrumPhy
852 channelPhy->AddSrsSinrChunkProcessor(pSrs); // set SRS chunk processor to NrSpectrumPhy
853 channelPhy->SetMobility(mm); // set mobility model to this NrSpectrumPhy
854 channelPhy->SetPhyRxDataEndOkCallback(
855 MakeCallback(&NrGnbPhy::PhyDataPacketReceived, phy)); // connect PhyRxDataEndOk callback
856 channelPhy->SetPhyRxCtrlEndOkCallback(phyEndCtrlCallback); // connect PhyRxCtrlEndOk
857 // callback
858 channelPhy->SetPhyUlHarqFeedbackCallback(
859 MakeCallback(&NrGnbPhy::ReportUlHarqFeedback, phy)); // PhyUlHarqFeedback callback
860
861 Ptr<BeamManager> beamManager = m_gnbBeamManagerFactory.Create<BeamManager>();
862 beamManager->Configure(antenna);
863 channelPhy->SetBeamManager(beamManager);
864 phy->InstallSpectrumPhy(channelPhy); // finally let know phy that there is this spectrum phy
865
866 return phy;
867}
868
869Ptr<NrGnbMac>
870NrHelper::CreateGnbMac()
871{
872 NS_LOG_FUNCTION(this);
873
874 Ptr<NrGnbMac> mac = m_gnbMacFactory.Create<NrGnbMac>();
875 return mac;
876}
877
878Ptr<NrMacScheduler>
879NrHelper::CreateGnbSched()
880{
881 NS_LOG_FUNCTION(this);
882
883 auto sched = m_schedFactory.Create<NrMacSchedulerNs3>();
884 auto dlAmc = m_gnbDlAmcFactory.Create<NrAmc>();
885 auto ulAmc = m_gnbUlAmcFactory.Create<NrAmc>();
886
887 sched->InstallDlAmc(dlAmc);
888 sched->InstallUlAmc(ulAmc);
889
890 return sched;
891}
892
893Ptr<NetDevice>
894NrHelper::InstallSingleGnbDevice(
895 const Ptr<Node>& n,
896 const std::vector<std::reference_wrapper<BandwidthPartInfoPtr>> allBwps)
897{
898 NS_ABORT_MSG_IF(m_cellIdCounter == 65535, "max num gNBs exceeded");
899
900 Ptr<NrGnbNetDevice> dev = m_gnbNetDeviceFactory.Create<NrGnbNetDevice>();
901
902 NS_LOG_DEBUG("Creating gNB, cellId = " << m_cellIdCounter);
903 uint16_t cellId = m_cellIdCounter;
904 m_cellIdCounter += allBwps.empty(); // Avoid two gNBs with duplicated cellId
905 dev->SetCellId(cellId);
906 dev->SetNode(n);
907
908 // create component carrier map for this gNB device
909 std::map<uint8_t, Ptr<BandwidthPartGnb>> ccMap;
910
911 for (uint32_t bwpId = 0; bwpId < allBwps.size(); ++bwpId)
912 {
913 NS_LOG_DEBUG("Creating BandwidthPart, id = " << bwpId);
914 Ptr<BandwidthPartGnb> cc = CreateObject<BandwidthPartGnb>();
915 double bwInKhz = allBwps[bwpId].get()->m_channelBandwidth / 1000.0;
916 NS_ABORT_MSG_IF(bwInKhz / 100.0 > 65535.0,
917 "A bandwidth of " << bwInKhz / 100.0 << " kHz cannot be represented");
918
919 cc->SetUlBandwidth(static_cast<uint16_t>(bwInKhz / 100));
920 cc->SetDlBandwidth(static_cast<uint16_t>(bwInKhz / 100));
921 cc->SetDlEarfcn(0); // Argh... handover not working
922 cc->SetUlEarfcn(0); // Argh... handover not working
923 cc->SetCellId(m_cellIdCounter); // First CC of a gNB matches its cellId
924 m_cellIdCounter++; // Other CCs are sequential
925
926 auto phy = CreateGnbPhy(
927 n,
928 allBwps[bwpId].get(),
929 dev,
930 std::bind(&NrGnbNetDevice::RouteIngoingCtrlMsgs, dev, std::placeholders::_1, bwpId));
931 phy->SetBwpId(bwpId);
932 cc->SetPhy(phy);
933
934 auto mac = CreateGnbMac();
935 cc->SetMac(mac);
936 phy->GetCam()->SetNrGnbMac(mac);
937
938 auto sched = CreateGnbSched();
939 cc->SetNrMacScheduler(sched);
940
941 if (bwpId == 0)
942 {
943 cc->SetAsPrimary(true);
944 }
945 else
946 {
947 cc->SetAsPrimary(false);
948 }
949
950 ccMap.insert(std::make_pair(bwpId, cc));
951 }
952
953 Ptr<NrGnbRrc> rrc = CreateObject<NrGnbRrc>();
954 Ptr<NrGnbComponentCarrierManager> ccmGnbManager =
955 DynamicCast<NrGnbComponentCarrierManager>(CreateObject<BwpManagerGnb>());
956 DynamicCast<BwpManagerGnb>(ccmGnbManager)
957 ->SetBwpManagerAlgorithm(m_gnbBwpManagerAlgoFactory.Create<BwpManagerAlgorithm>());
958
959 // Convert Gnb carrier map to only PhyConf map
960 // we want to make RRC to be generic, to be able to work with any type of carriers, not only
961 // strictly LTE carriers
962 std::map<uint8_t, Ptr<BandwidthPartGnb>> ccPhyConfMap;
963 for (const auto& i : ccMap)
964 {
965 Ptr<BandwidthPartGnb> c = i.second;
966 ccPhyConfMap.insert(std::make_pair(i.first, c));
967 }
968
969 // ComponentCarrierManager SAP
970 rrc->SetNrCcmRrcSapProvider(ccmGnbManager->GetNrCcmRrcSapProvider());
971 ccmGnbManager->SetNrCcmRrcSapUser(rrc->GetNrCcmRrcSapUser());
972 // Set number of component carriers. Note: gNB CCM would also set the
973 // number of component carriers in gNB RRC
974
975 ccmGnbManager->SetNumberOfComponentCarriers(ccMap.size());
976 rrc->ConfigureCarriers(ccPhyConfMap);
977
978 // nr module currently uses only RRC ideal mode
979 if (m_useIdealRrc)
980 {
981 Ptr<NrGnbRrcProtocolIdeal> rrcProtocol = CreateObject<NrGnbRrcProtocolIdeal>();
982 rrcProtocol->SetNrGnbRrcSapProvider(rrc->GetNrGnbRrcSapProvider());
983 rrc->SetNrGnbRrcSapUser(rrcProtocol->GetNrGnbRrcSapUser());
984 rrc->AggregateObject(rrcProtocol);
985 }
986 else
987 {
988 Ptr<nr::NrGnbRrcProtocolReal> rrcProtocol = CreateObject<nr::NrGnbRrcProtocolReal>();
989 rrcProtocol->SetNrGnbRrcSapProvider(rrc->GetNrGnbRrcSapProvider());
990 rrc->SetNrGnbRrcSapUser(rrcProtocol->GetNrGnbRrcSapUser());
991 rrc->AggregateObject(rrcProtocol);
992 }
993
994 if (m_nrEpcHelper != nullptr)
995 {
996 EnumValue<NrGnbRrc::NrEpsBearerToRlcMapping_t> epsBearerToRlcMapping;
997 rrc->GetAttribute("EpsBearerToRlcMapping", epsBearerToRlcMapping);
998 // it does not make sense to use RLC/SM when also using the EPC
999 if (epsBearerToRlcMapping.Get() == NrGnbRrc::RLC_SM_ALWAYS)
1000 {
1001 rrc->SetAttribute("EpsBearerToRlcMapping", EnumValue(NrGnbRrc::RLC_UM_ALWAYS));
1002 }
1003 }
1004
1005 // This RRC attribute is used to connect each new RLC instance with the MAC layer
1006 // (for function such as TransmitPdu, ReportBufferStatusReport).
1007 // Since in this new architecture, the component carrier manager acts a proxy, it
1008 // will have its own NrMacSapProvider interface, RLC will see it as through original MAC
1009 // interface NrMacSapProvider, but the function call will go now through
1010 // NrGnbComponentCarrierManager instance that needs to implement functions of this interface,
1011 // and its task will be to forward these calls to the specific MAC of some of the instances of
1012 // component carriers. This decision will depend on the specific implementation of the component
1013 // carrier manager.
1014 rrc->SetNrMacSapProvider(ccmGnbManager->GetNrMacSapProvider());
1015 rrc->SetForwardUpCallback(MakeCallback(&NrGnbNetDevice::Receive, dev));
1016
1017 for (auto& it : ccMap)
1018 {
1019 it.second->GetPhy()->SetGnbCphySapUser(rrc->GetNrGnbCphySapUser(it.first));
1020 rrc->SetNrGnbCphySapProvider(it.second->GetPhy()->GetGnbCphySapProvider(), it.first);
1021
1022 rrc->SetNrGnbCmacSapProvider(it.second->GetMac()->GetGnbCmacSapProvider(), it.first);
1023 it.second->GetMac()->SetGnbCmacSapUser(rrc->GetNrGnbCmacSapUser(it.first));
1024
1025 // PHY <--> MAC SAP
1026 it.second->GetPhy()->SetPhySapUser(it.second->GetMac()->GetPhySapUser());
1027 it.second->GetMac()->SetPhySapProvider(it.second->GetPhy()->GetPhySapProvider());
1028 // PHY <--> MAC SAP END
1029
1030 // Scheduler SAP
1031 it.second->GetMac()->SetNrMacSchedSapProvider(
1032 it.second->GetScheduler()->GetMacSchedSapProvider());
1033 it.second->GetMac()->SetNrMacCschedSapProvider(
1034 it.second->GetScheduler()->GetMacCschedSapProvider());
1035
1036 it.second->GetScheduler()->SetMacSchedSapUser(it.second->GetMac()->GetNrMacSchedSapUser());
1037 it.second->GetScheduler()->SetMacCschedSapUser(
1038 it.second->GetMac()->GetNrMacCschedSapUser());
1039 // Scheduler SAP END
1040
1041 it.second->GetMac()->SetNrCcmMacSapUser(ccmGnbManager->GetNrCcmMacSapUser());
1042 ccmGnbManager->SetCcmMacSapProviders(it.first,
1043 it.second->GetMac()->GetNrCcmMacSapProvider());
1044
1045 // insert the pointer to the NrMacSapProvider interface of the MAC layer of the specific
1046 // component carrier
1047 ccmGnbManager->SetMacSapProvider(it.first, it.second->GetMac()->GetMacSapProvider());
1048 }
1049
1050 dev->SetAttribute("NrGnbComponentCarrierManager", PointerValue(ccmGnbManager));
1051 dev->SetCcMap(ccMap);
1052 dev->SetAttribute("NrGnbRrc", PointerValue(rrc));
1053 dev->Initialize();
1054
1055 n->AddDevice(dev);
1056
1057 if (m_nrEpcHelper != nullptr)
1058 {
1059 NS_LOG_INFO("adding this gNB to the EPC");
1060 m_nrEpcHelper->AddGnb(n, dev, dev->GetCellIds());
1061 Ptr<NrEpcGnbApplication> gnbApp = n->GetApplication(0)->GetObject<NrEpcGnbApplication>();
1062 NS_ASSERT_MSG(gnbApp != nullptr, "cannot retrieve NrEpcGnbApplication");
1063
1064 // S1 SAPs
1065 rrc->SetS1SapProvider(gnbApp->GetS1SapProvider());
1066 gnbApp->SetS1SapUser(rrc->GetS1SapUser());
1067
1068 // X2 SAPs
1069 Ptr<NrEpcX2> x2 = n->GetObject<NrEpcX2>();
1070 x2->SetEpcX2SapUser(rrc->GetEpcX2SapUser());
1071 rrc->SetEpcX2SapProvider(x2->GetEpcX2SapProvider());
1072 }
1073 return dev;
1074}
1075
1076std::string
1077NrHelper::GetHandoverAlgorithmType() const
1078{
1079 return m_handoverAlgorithmFactory.GetTypeId().GetName();
1080}
1081
1082void
1083NrHelper::SetHandoverAlgorithmType(std::string type)
1084{
1085 NS_LOG_FUNCTION(this << type);
1086 m_handoverAlgorithmFactory = ObjectFactory();
1087 m_handoverAlgorithmFactory.SetTypeId(type);
1088}
1089
1090void
1091NrHelper::SetHandoverAlgorithmAttribute(std::string n, const AttributeValue& v)
1092{
1093 NS_LOG_FUNCTION(this << n);
1094 m_handoverAlgorithmFactory.Set(n, v);
1095}
1096
1097void
1098NrHelper::AddX2Interface(NodeContainer gnbNodes)
1099{
1100 NS_LOG_FUNCTION(this);
1101
1102 NS_ASSERT_MSG(m_nrEpcHelper, "X2 interfaces cannot be set up when the EPC is not used");
1103
1104 for (auto i = gnbNodes.Begin(); i != gnbNodes.End(); ++i)
1105 {
1106 for (auto j = i + 1; j != gnbNodes.End(); ++j)
1107 {
1108 AddX2Interface(*i, *j);
1109 }
1110 }
1111}
1112
1113void
1114NrHelper::AddX2Interface(Ptr<Node> gnbNode1, Ptr<Node> gnbNode2)
1115{
1116 NS_LOG_FUNCTION(this);
1117 NS_LOG_INFO("setting up the X2 interface");
1118
1119 m_nrEpcHelper->AddX2Interface(gnbNode1, gnbNode2);
1120}
1121
1122void
1123NrHelper::HandoverRequest(Time hoTime,
1124 Ptr<NetDevice> ueDev,
1125 Ptr<NetDevice> sourceGnbDev,
1126 Ptr<NetDevice> targetGnbDev)
1127{
1128 NS_LOG_FUNCTION(this << ueDev << sourceGnbDev << targetGnbDev);
1129 NS_ASSERT_MSG(m_nrEpcHelper,
1130 "Handover requires the use of the EPC - did you forget to call "
1131 "NrHelper::SetEpcHelper () ?");
1132 uint16_t targetCellId = targetGnbDev->GetObject<NrGnbNetDevice>()->GetCellId();
1133 Simulator::Schedule(hoTime,
1134 &NrHelper::DoHandoverRequest,
1135 this,
1136 ueDev,
1137 sourceGnbDev,
1138 targetCellId);
1139}
1140
1141void
1142NrHelper::HandoverRequest(Time hoTime,
1143 Ptr<NetDevice> ueDev,
1144 Ptr<NetDevice> sourceGnbDev,
1145 uint16_t targetCellId)
1146{
1147 NS_LOG_FUNCTION(this << ueDev << sourceGnbDev << targetCellId);
1148 NS_ASSERT_MSG(m_nrEpcHelper,
1149 "Handover requires the use of the EPC - did you forget to call "
1150 "NrHelper::SetEpcHelper () ?");
1151 Simulator::Schedule(hoTime,
1152 &NrHelper::DoHandoverRequest,
1153 this,
1154 ueDev,
1155 sourceGnbDev,
1156 targetCellId);
1157}
1158
1159void
1160NrHelper::DoHandoverRequest(Ptr<NetDevice> ueDev,
1161 Ptr<NetDevice> sourceGnbDev,
1162 uint16_t targetCellId)
1163{
1164 NS_LOG_FUNCTION(this << ueDev << sourceGnbDev << targetCellId);
1165
1166 Ptr<NrGnbRrc> sourceRrc = sourceGnbDev->GetObject<NrGnbNetDevice>()->GetRrc();
1167 uint16_t rnti = ueDev->GetObject<NrUeNetDevice>()->GetRrc()->GetRnti();
1168 sourceRrc->SendHandoverRequest(rnti, targetCellId);
1169}
1170
1171void
1172NrHelper::AttachToClosestGnb(NetDeviceContainer ueDevices, NetDeviceContainer gnbDevices)
1173{
1174 NS_LOG_FUNCTION(this);
1175
1176 for (NetDeviceContainer::Iterator i = ueDevices.Begin(); i != ueDevices.End(); i++)
1177 {
1178 AttachToClosestGnb(*i, gnbDevices);
1179 }
1180}
1181
1182void
1183NrHelper::AttachToClosestGnb(Ptr<NetDevice> ueDevice, NetDeviceContainer gnbDevices)
1184{
1185 NS_LOG_FUNCTION(this);
1186 NS_ASSERT_MSG(gnbDevices.GetN() > 0, "empty gnb device container");
1187 Vector uepos = ueDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
1188 double minDistance = std::numeric_limits<double>::infinity();
1189 Ptr<NetDevice> closestGnbDevice;
1190 for (NetDeviceContainer::Iterator i = gnbDevices.Begin(); i != gnbDevices.End(); ++i)
1191 {
1192 Vector gnbpos = (*i)->GetNode()->GetObject<MobilityModel>()->GetPosition();
1193 double distance = CalculateDistance(uepos, gnbpos);
1194 if (distance < minDistance)
1195 {
1196 minDistance = distance;
1197 closestGnbDevice = *i;
1198 }
1199 }
1200 NS_ASSERT(closestGnbDevice);
1201
1202 AttachToGnb(ueDevice, closestGnbDevice);
1203}
1204
1205void
1206NrHelper::AttachToGnb(const Ptr<NetDevice>& ueDevice, const Ptr<NetDevice>& gnbDevice)
1207{
1208 Ptr<NrGnbNetDevice> gnbNetDev = gnbDevice->GetObject<NrGnbNetDevice>();
1209 Ptr<NrUeNetDevice> ueNetDev = ueDevice->GetObject<NrUeNetDevice>();
1210
1211 NS_ABORT_IF(gnbNetDev == nullptr || ueNetDev == nullptr);
1212
1213 for (uint32_t i = 0; i < gnbNetDev->GetCcMapSize(); ++i)
1214 {
1215 gnbNetDev->GetPhy(i)->RegisterUe(ueNetDev->GetImsi(), ueNetDev);
1216 ueNetDev->GetPhy(i)->RegisterToGnb(gnbNetDev->GetBwpId(i));
1217 ueNetDev->GetPhy(i)->SetDlAmc(
1218 DynamicCast<NrMacSchedulerNs3>(gnbNetDev->GetScheduler(i))->GetDlAmc());
1219 ueNetDev->GetPhy(i)->SetDlCtrlSyms(gnbNetDev->GetMac(i)->GetDlCtrlSyms());
1220 ueNetDev->GetPhy(i)->SetUlCtrlSyms(gnbNetDev->GetMac(i)->GetUlCtrlSyms());
1221 ueNetDev->GetPhy(i)->SetNumRbPerRbg(gnbNetDev->GetMac(i)->GetNumRbPerRbg());
1222 ueNetDev->GetPhy(i)->SetRbOverhead(gnbNetDev->GetPhy(i)->GetRbOverhead());
1223 ueNetDev->GetPhy(i)->SetSymbolsPerSlot(gnbNetDev->GetPhy(i)->GetSymbolsPerSlot());
1224 ueNetDev->GetPhy(i)->SetNumerology(gnbNetDev->GetPhy(i)->GetNumerology());
1225 ueNetDev->GetPhy(i)->SetPattern(gnbNetDev->GetPhy(i)->GetPattern());
1226 Ptr<NrEpcUeNas> ueNas = ueNetDev->GetNas();
1227 ueNas->Connect(gnbNetDev->GetBwpId(i), gnbNetDev->GetEarfcn(i));
1228
1229 if (m_enableMimoFeedback)
1230 {
1231 // Initialize parameters for MIMO precoding matrix search (PMI feedback)
1232 auto pmSearch = m_pmSearchFactory.Create<NrPmSearch>();
1233 ueNetDev->GetPhy(i)->SetPmSearch(pmSearch);
1234 auto gnbAnt =
1235 gnbNetDev->GetPhy(i)->GetSpectrumPhy()->GetAntenna()->GetObject<PhasedArrayModel>();
1236 auto ueAnt =
1237 ueNetDev->GetPhy(i)->GetSpectrumPhy()->GetAntenna()->GetObject<PhasedArrayModel>();
1238 pmSearch->SetGnbParams(gnbAnt->IsDualPol(),
1239 gnbAnt->GetNumHorizontalPorts(),
1240 gnbAnt->GetNumVerticalPorts());
1241 pmSearch->SetUeParams(ueAnt->GetNumPorts());
1242 pmSearch->InitCodebooks();
1243 }
1244 }
1245
1246 if (m_nrEpcHelper)
1247 {
1248 // activate default EPS bearer
1249 m_nrEpcHelper->ActivateEpsBearer(ueDevice,
1250 ueNetDev->GetImsi(),
1253 }
1254
1255 // tricks needed for the simplified LTE-only simulations
1256 // if (m_nrEpcHelper == 0)
1257 //{
1258 ueNetDev->SetTargetGnb(gnbNetDev);
1259 //}
1260
1261 if (m_beamformingHelper)
1262 {
1263 m_beamformingHelper->AddBeamformingTask(gnbNetDev, ueNetDev);
1264 }
1265}
1266
1267uint8_t
1268NrHelper::ActivateDedicatedEpsBearer(NetDeviceContainer ueDevices,
1269 NrEpsBearer bearer,
1270 Ptr<NrEpcTft> tft)
1271{
1272 NS_LOG_FUNCTION(this);
1273 for (NetDeviceContainer::Iterator i = ueDevices.Begin(); i != ueDevices.End(); ++i)
1274 {
1275 uint8_t bearerId = ActivateDedicatedEpsBearer(*i, bearer, tft);
1276 return bearerId;
1277 }
1278 return 0;
1279}
1280
1281uint8_t
1282NrHelper::ActivateDedicatedEpsBearer(Ptr<NetDevice> ueDevice, NrEpsBearer bearer, Ptr<NrEpcTft> tft)
1283{
1284 NS_LOG_FUNCTION(this);
1285
1286 NS_ASSERT_MSG(m_nrEpcHelper, "dedicated EPS bearers cannot be set up when the EPC is not used");
1287
1288 uint64_t imsi = ueDevice->GetObject<NrUeNetDevice>()->GetImsi();
1289 uint8_t bearerId = m_nrEpcHelper->ActivateEpsBearer(ueDevice, imsi, tft, bearer);
1290 return bearerId;
1291}
1292
1293void
1295 Ptr<NetDevice> gnbDevice,
1296 uint8_t bearerId)
1297{
1298 NS_LOG_FUNCTION(this << ueDevice << bearerId);
1299 NS_ASSERT_MSG(m_nrEpcHelper != nullptr,
1300 "Dedicated EPS bearers cannot be de-activated when the EPC is not used");
1301 NS_ASSERT_MSG(bearerId != 1,
1302 "Default bearer cannot be de-activated until and unless and UE is released");
1303
1304 DoDeActivateDedicatedEpsBearer(ueDevice, gnbDevice, bearerId);
1305}
1306
1307void
1308NrHelper::SetUeMacAttribute(const std::string& n, const AttributeValue& v)
1309{
1310 NS_LOG_FUNCTION(this);
1311 m_ueMacFactory.Set(n, v);
1312}
1313
1314void
1315NrHelper::SetGnbMacAttribute(const std::string& n, const AttributeValue& v)
1316{
1317 NS_LOG_FUNCTION(this);
1318 m_gnbMacFactory.Set(n, v);
1319}
1320
1321void
1322NrHelper::SetGnbSpectrumAttribute(const std::string& n, const AttributeValue& v)
1323{
1324 NS_LOG_FUNCTION(this);
1325 m_gnbSpectrumFactory.Set(n, v);
1326}
1327
1328void
1329NrHelper::SetUeSpectrumAttribute(const std::string& n, const AttributeValue& v)
1330{
1331 NS_LOG_FUNCTION(this);
1332 m_ueSpectrumFactory.Set(n, v);
1333}
1334
1335void
1336NrHelper::SetUeChannelAccessManagerAttribute(const std::string& n, const AttributeValue& v)
1337{
1338 NS_LOG_FUNCTION(this);
1339 m_ueChannelAccessManagerFactory.Set(n, v);
1340}
1341
1342void
1343NrHelper::SetGnbChannelAccessManagerAttribute(const std::string& n, const AttributeValue& v)
1344{
1345 NS_LOG_FUNCTION(this);
1346 m_gnbChannelAccessManagerFactory.Set(n, v);
1347}
1348
1349void
1350NrHelper::SetSchedulerAttribute(const std::string& n, const AttributeValue& v)
1351{
1352 NS_LOG_FUNCTION(this);
1353 m_schedFactory.Set(n, v);
1354}
1355
1356void
1357NrHelper::SetUePhyAttribute(const std::string& n, const AttributeValue& v)
1358{
1359 NS_LOG_FUNCTION(this);
1360 m_uePhyFactory.Set(n, v);
1361}
1362
1363void
1364NrHelper::SetGnbPhyAttribute(const std::string& n, const AttributeValue& v)
1365{
1366 NS_LOG_FUNCTION(this);
1367 m_gnbPhyFactory.Set(n, v);
1368}
1369
1370void
1371NrHelper::SetUeAntennaAttribute(const std::string& n, const AttributeValue& v)
1372{
1373 NS_LOG_FUNCTION(this);
1374 m_ueAntennaFactory.Set(n, v);
1375}
1376
1377void
1378NrHelper::SetGnbAntennaAttribute(const std::string& n, const AttributeValue& v)
1379{
1380 NS_LOG_FUNCTION(this);
1381 m_gnbAntennaFactory.Set(n, v);
1382}
1383
1384void
1386{
1387 NS_LOG_FUNCTION(this);
1388 m_ueChannelAccessManagerFactory.SetTypeId(typeId);
1389}
1390
1391void
1393{
1394 NS_LOG_FUNCTION(this);
1395 m_gnbChannelAccessManagerFactory.SetTypeId(typeId);
1396}
1397
1398void
1399NrHelper::SetSchedulerTypeId(const TypeId& typeId)
1400{
1401 NS_LOG_FUNCTION(this);
1402 m_schedFactory.SetTypeId(typeId);
1403}
1404
1405void
1407{
1408 NS_LOG_FUNCTION(this);
1409 m_ueBwpManagerAlgoFactory.SetTypeId(typeId);
1410}
1411
1412void
1413NrHelper::SetPhasedArraySpectrumPropagationLossModelTypeId(const TypeId& typeId)
1414{
1415 NS_LOG_FUNCTION(this);
1416 m_spectrumPropagationFactory.SetTypeId(typeId);
1417}
1418
1419void
1420NrHelper::SetUeBwpManagerAlgorithmAttribute(const std::string& n, const AttributeValue& v)
1421{
1422 NS_LOG_FUNCTION(this);
1423 m_ueBwpManagerAlgoFactory.Set(n, v);
1424}
1425
1426void
1428 const AttributeValue& v)
1429{
1430 NS_LOG_FUNCTION(this);
1431 m_spectrumPropagationFactory.Set(n, v);
1432}
1433
1434void
1435NrHelper::SetChannelConditionModelAttribute(const std::string& n, const AttributeValue& v)
1436{
1437 NS_LOG_FUNCTION(this);
1438 m_channelConditionModelFactory.Set(n, v);
1439}
1440
1441void
1442NrHelper::SetPathlossAttribute(const std::string& n, const AttributeValue& v)
1443{
1444 NS_LOG_FUNCTION(this);
1445 m_pathlossModelFactory.Set(n, v);
1446}
1447
1448void
1449NrHelper::SetGnbDlAmcAttribute(const std::string& n, const AttributeValue& v)
1450{
1451 NS_LOG_FUNCTION(this);
1452 m_gnbDlAmcFactory.Set(n, v);
1453}
1454
1455void
1456NrHelper::SetGnbUlAmcAttribute(const std::string& n, const AttributeValue& v)
1457{
1458 NS_LOG_FUNCTION(this);
1459 m_gnbUlAmcFactory.Set(n, v);
1460}
1461
1462void
1463NrHelper::SetGnbBeamManagerAttribute(const std::string& n, const AttributeValue& v)
1464{
1465 NS_LOG_FUNCTION(this);
1466 m_gnbBeamManagerFactory.Set(n, v);
1467}
1468
1469void
1471{
1472 NS_LOG_FUNCTION(this);
1473 m_gnbBeamManagerFactory.SetTypeId(typeId);
1474}
1475
1476void
1477NrHelper::SetUlErrorModel(const std::string& errorModelTypeId)
1478{
1479 NS_LOG_FUNCTION(this);
1480
1481 SetGnbUlAmcAttribute("ErrorModelType", TypeIdValue(TypeId::LookupByName(errorModelTypeId)));
1482 SetGnbSpectrumAttribute("ErrorModelType", TypeIdValue(TypeId::LookupByName(errorModelTypeId)));
1483}
1484
1485void
1486NrHelper::SetDlErrorModel(const std::string& errorModelTypeId)
1487{
1488 NS_LOG_FUNCTION(this);
1489
1490 SetGnbDlAmcAttribute("ErrorModelType", TypeIdValue(TypeId::LookupByName(errorModelTypeId)));
1491 SetUeSpectrumAttribute("ErrorModelType", TypeIdValue(TypeId::LookupByName(errorModelTypeId)));
1492}
1493
1494int64_t
1495NrHelper::AssignStreams(NetDeviceContainer c, int64_t stream)
1496{
1497 int64_t currentStream = stream;
1498 Ptr<NetDevice> netDevice;
1499 for (NetDeviceContainer::Iterator i = c.Begin(); i != c.End(); ++i)
1500 {
1501 netDevice = (*i);
1502 Ptr<NrGnbNetDevice> nrGnb = DynamicCast<NrGnbNetDevice>(netDevice);
1503 if (nrGnb)
1504 {
1505 for (uint32_t bwp = 0; bwp < nrGnb->GetCcMapSize(); bwp++)
1506 {
1507 currentStream += nrGnb->GetPhy(bwp)->GetSpectrumPhy()->AssignStreams(currentStream);
1508 currentStream += nrGnb->GetScheduler(bwp)->AssignStreams(currentStream);
1509 currentStream +=
1510 DoAssignStreamsToChannelObjects(nrGnb->GetPhy(bwp)->GetSpectrumPhy(),
1511 currentStream);
1512 }
1513 }
1514
1515 Ptr<NrUeNetDevice> nrUe = DynamicCast<NrUeNetDevice>(netDevice);
1516 if (nrUe)
1517 {
1518 for (uint32_t bwp = 0; bwp < nrUe->GetCcMapSize(); bwp++)
1519 {
1520 currentStream += nrUe->GetPhy(bwp)->GetSpectrumPhy()->AssignStreams(currentStream);
1521 currentStream += nrUe->GetMac(bwp)->AssignStreams(currentStream);
1522 currentStream +=
1523 DoAssignStreamsToChannelObjects(nrUe->GetPhy(bwp)->GetSpectrumPhy(),
1524 currentStream);
1525 }
1526 }
1527 }
1528
1529 return (currentStream - stream);
1530}
1531
1532int64_t
1533NrHelper::DoAssignStreamsToChannelObjects(Ptr<NrSpectrumPhy> phy, int64_t currentStream)
1534{
1535 int64_t initialStream = currentStream;
1536
1537 Ptr<ThreeGppPropagationLossModel> propagationLossModel =
1538 DynamicCast<ThreeGppPropagationLossModel>(
1539 phy->GetSpectrumChannel()->GetPropagationLossModel());
1540 if (!propagationLossModel)
1541 {
1542 currentStream +=
1543 phy->GetSpectrumChannel()->GetPropagationLossModel()->AssignStreams(currentStream);
1544 return currentStream - initialStream;
1545 }
1546
1547 if (std::find(m_channelObjectsWithAssignedStreams.begin(),
1548 m_channelObjectsWithAssignedStreams.end(),
1549 propagationLossModel) == m_channelObjectsWithAssignedStreams.end())
1550 {
1551 currentStream += propagationLossModel->AssignStreams(currentStream);
1552 m_channelObjectsWithAssignedStreams.emplace_back(propagationLossModel);
1553 }
1554
1555 Ptr<ChannelConditionModel> channelConditionModel =
1556 propagationLossModel->GetChannelConditionModel();
1557
1558 if (std::find(m_channelObjectsWithAssignedStreams.begin(),
1559 m_channelObjectsWithAssignedStreams.end(),
1560 channelConditionModel) == m_channelObjectsWithAssignedStreams.end())
1561 {
1562 currentStream += channelConditionModel->AssignStreams(currentStream);
1563 m_channelObjectsWithAssignedStreams.emplace_back(channelConditionModel);
1564 }
1565
1566 Ptr<ThreeGppSpectrumPropagationLossModel> spectrumLossModel =
1567 DynamicCast<ThreeGppSpectrumPropagationLossModel>(
1568 phy->GetSpectrumChannel()->GetPhasedArraySpectrumPropagationLossModel());
1569
1570 if (spectrumLossModel)
1571 {
1572 if (std::find(m_channelObjectsWithAssignedStreams.begin(),
1573 m_channelObjectsWithAssignedStreams.end(),
1574 spectrumLossModel) == m_channelObjectsWithAssignedStreams.end())
1575 {
1576 Ptr<ThreeGppChannelModel> channel =
1577 DynamicCast<ThreeGppChannelModel>(spectrumLossModel->GetChannelModel());
1578 currentStream += channel->AssignStreams(currentStream);
1579 m_channelObjectsWithAssignedStreams.emplace_back(spectrumLossModel);
1580 }
1581 }
1582
1583 return currentStream - initialStream;
1584}
1585
1586void
1588{
1589 NS_LOG_FUNCTION(this);
1590 m_gnbBwpManagerAlgoFactory.SetTypeId(typeId);
1591}
1592
1593void
1594NrHelper::SetGnbBwpManagerAlgorithmAttribute(const std::string& n, const AttributeValue& v)
1595{
1596 NS_LOG_FUNCTION(this);
1597 m_gnbBwpManagerAlgoFactory.Set(n, v);
1598}
1599
1600void
1601NrHelper::DoDeActivateDedicatedEpsBearer(Ptr<NetDevice> ueDevice,
1602 Ptr<NetDevice> gnbDevice,
1603 uint8_t bearerId)
1604{
1605 NS_LOG_FUNCTION(this << ueDevice << bearerId);
1606
1607 // Extract IMSI and rnti
1608 uint64_t imsi = ueDevice->GetObject<NrUeNetDevice>()->GetImsi();
1609 uint16_t rnti = ueDevice->GetObject<NrUeNetDevice>()->GetRrc()->GetRnti();
1610
1611 Ptr<NrGnbRrc> gnbRrc = gnbDevice->GetObject<NrGnbNetDevice>()->GetRrc();
1612
1613 gnbRrc->DoSendReleaseDataRadioBearer(imsi, rnti, bearerId);
1614}
1615
1616void
1618{
1619 m_nrEpcHelper = NrEpcHelper;
1620}
1621
1622void
1623NrHelper::SetBeamformingHelper(Ptr<BeamformingHelperBase> beamformingHelper)
1624{
1625 m_beamformingHelper = beamformingHelper;
1626 m_beamformingHelper->Initialize();
1627}
1628
1629class NrDrbActivator : public SimpleRefCount<NrDrbActivator>
1630{
1631 public:
1632 NrDrbActivator(Ptr<NetDevice> ueDevice, NrEpsBearer bearer);
1633 static void ActivateCallback(Ptr<NrDrbActivator> a,
1634 std::string context,
1635 uint64_t imsi,
1636 uint16_t cellId,
1637 uint16_t rnti);
1638 void ActivateDrb(uint64_t imsi, uint16_t cellId, uint16_t rnti);
1639
1640 private:
1641 bool m_active;
1642 Ptr<NetDevice> m_ueDevice;
1643 NrEpsBearer m_bearer;
1644 uint64_t m_imsi;
1645};
1646
1647NrDrbActivator::NrDrbActivator(Ptr<NetDevice> ueDevice, NrEpsBearer bearer)
1648 : m_active(false),
1649 m_ueDevice(ueDevice),
1650 m_bearer(bearer),
1651 m_imsi(m_ueDevice->GetObject<NrUeNetDevice>()->GetImsi())
1652{
1653}
1654
1655void
1656NrDrbActivator::ActivateCallback(Ptr<NrDrbActivator> a,
1657 std::string context,
1658 uint64_t imsi,
1659 uint16_t cellId,
1660 uint16_t rnti)
1661{
1662 NS_LOG_FUNCTION(a << context << imsi << cellId << rnti);
1663 a->ActivateDrb(imsi, cellId, rnti);
1664}
1665
1666void
1667NrDrbActivator::ActivateDrb(uint64_t imsi, uint16_t cellId, uint16_t rnti)
1668{
1669 NS_LOG_FUNCTION(this << imsi << cellId << rnti << m_active);
1670 if ((!m_active) && (imsi == m_imsi))
1671 {
1672 Ptr<NrUeRrc> ueRrc = m_ueDevice->GetObject<NrUeNetDevice>()->GetRrc();
1673 NS_ASSERT(ueRrc->GetState() == NrUeRrc::CONNECTED_NORMALLY);
1674 uint16_t rnti = ueRrc->GetRnti();
1675 Ptr<const NrGnbNetDevice> nrGnbDevice =
1676 m_ueDevice->GetObject<NrUeNetDevice>()->GetTargetGnb();
1677 Ptr<NrGnbRrc> gnbRrc = nrGnbDevice->GetObject<NrGnbNetDevice>()->GetRrc();
1678 NS_ASSERT(gnbRrc->HasCellId(ueRrc->GetCellId()));
1679 Ptr<NrUeManager> ueManager = gnbRrc->GetUeManager(rnti);
1680 NS_ASSERT(ueManager->GetState() == NrUeManager::CONNECTED_NORMALLY ||
1681 ueManager->GetState() == NrUeManager::CONNECTION_RECONFIGURATION);
1682 NrEpcGnbS1SapUser::DataRadioBearerSetupRequestParameters params;
1683 params.rnti = rnti;
1684 params.bearer = m_bearer;
1685 params.bearerId = 0;
1686 params.gtpTeid = 0; // don't care
1687 gnbRrc->GetS1SapUser()->DataRadioBearerSetupRequest(params);
1688 m_active = true;
1689 }
1690}
1691
1692void
1693NrHelper::ActivateDataRadioBearer(NetDeviceContainer ueDevices, NrEpsBearer bearer)
1694{
1695 NS_LOG_FUNCTION(this);
1696 for (NetDeviceContainer::Iterator i = ueDevices.Begin(); i != ueDevices.End(); ++i)
1697 {
1698 ActivateDataRadioBearer(*i, bearer);
1699 }
1700}
1701
1702void
1703NrHelper::ActivateDataRadioBearer(Ptr<NetDevice> ueDevice, NrEpsBearer bearer)
1704{
1705 NS_LOG_FUNCTION(this << ueDevice);
1706 NS_ASSERT_MSG(!m_nrEpcHelper, "this method must not be used when the EPC is being used");
1707
1708 // Normally it is the EPC that takes care of activating DRBs
1709 // when the UE gets connected. When the EPC is not used, we achieve
1710 // the same behavior by hooking a dedicated DRB activation function
1711 // to the Gnb RRC Connection Established trace source
1712
1713 Ptr<const NrGnbNetDevice> nrGnbDevice = ueDevice->GetObject<NrUeNetDevice>()->GetTargetGnb();
1714
1715 std::ostringstream path;
1716 path << "/NodeList/" << nrGnbDevice->GetNode()->GetId() << "/DeviceList/"
1717 << nrGnbDevice->GetIfIndex() << "/NrGnbRrc/ConnectionEstablished";
1718 Ptr<NrDrbActivator> arg = Create<NrDrbActivator>(ueDevice, bearer);
1719 Config::Connect(path.str(), MakeBoundCallback(&NrDrbActivator::ActivateCallback, arg));
1720}
1721
1722void
1724{
1728 // EnableGnbPacketCountTrace ();
1729 // EnableUePacketCountTrace ();
1730 // EnableTransportBlockTrace ();
1742}
1743
1744Ptr<NrPhyRxTrace>
1746{
1747 if (!m_phyStats)
1748 {
1749 m_phyStats = CreateObject<NrPhyRxTrace>();
1750 }
1751 return m_phyStats;
1752}
1753
1754Ptr<NrMacRxTrace>
1756{
1757 if (!m_macStats)
1758 {
1759 m_macStats = CreateObject<NrMacRxTrace>();
1760 }
1761 return m_macStats;
1762}
1763
1764void
1766{
1767 NS_LOG_FUNCTION(this);
1768 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/DlDataSinr",
1769 MakeBoundCallback(&NrPhyRxTrace::DlDataSinrCallback, GetPhyRxTrace()));
1770
1771 Config::Connect(
1772 "/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/SpectrumPhy/RxPacketTraceUe",
1773 MakeBoundCallback(&NrPhyRxTrace::RxPacketTraceUeCallback, GetPhyRxTrace()));
1774}
1775
1776void
1778{
1779 NS_LOG_FUNCTION(this);
1780 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/DlCtrlSinr",
1781 MakeBoundCallback(&NrPhyRxTrace::DlCtrlSinrCallback, GetPhyRxTrace()));
1782}
1783
1784void
1786{
1787 NS_LOG_FUNCTION(this);
1788 Config::Connect("/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbPhy/GnbPhyRxedCtrlMsgsTrace",
1790 Config::Connect("/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbPhy/GnbPhyTxedCtrlMsgsTrace",
1792}
1793
1794void
1796{
1797 NS_LOG_FUNCTION(this);
1798 Config::Connect("/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbMac/GnbMacRxedCtrlMsgsTrace",
1800 Config::Connect("/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbMac/GnbMacTxedCtrlMsgsTrace",
1802}
1803
1804void
1806{
1807 NS_LOG_FUNCTION(this);
1808 Config::Connect(
1809 "/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/UePhyRxedCtrlMsgsTrace",
1811 Config::Connect(
1812 "/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/UePhyTxedCtrlMsgsTrace",
1814 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/UePhyRxedDlDciTrace",
1816 Config::Connect(
1817 "/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/UePhyTxedHarqFeedbackTrace",
1819}
1820
1821void
1823{
1824 NS_LOG_FUNCTION(this);
1825 Config::Connect(
1826 "/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUeMac/UeMacRxedCtrlMsgsTrace",
1828 Config::Connect(
1829 "/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUeMac/UeMacTxedCtrlMsgsTrace",
1831}
1832
1833void
1835{
1836 NS_LOG_FUNCTION(this);
1837 Config::Connect(
1838 "/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbPhy/SpectrumPhy/RxPacketTraceGnb",
1839 MakeBoundCallback(&NrPhyRxTrace::RxPacketTraceGnbCallback, GetPhyRxTrace()));
1840}
1841
1842void
1844{
1845 NS_LOG_FUNCTION(this);
1846 Config::Connect(
1847 "/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbPhy/SpectrumPhy/ReportGnbTxRxPacketCount",
1848 MakeBoundCallback(&NrPhyRxTrace::ReportPacketCountGnbCallback, GetPhyRxTrace()));
1849}
1850
1851void
1853{
1854 NS_LOG_FUNCTION(this);
1855 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/SpectrumPhy/"
1856 "ReportUeTxRxPacketCount",
1857 MakeBoundCallback(&NrPhyRxTrace::ReportPacketCountUeCallback, GetPhyRxTrace()));
1858}
1859
1860void
1862{
1863 NS_LOG_FUNCTION(this);
1864 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/ReportDownlinkTbSize",
1865 MakeBoundCallback(&NrPhyRxTrace::ReportDownLinkTBSize, GetPhyRxTrace()));
1866}
1867
1868void
1870{
1871 NS_LOG_FUNCTION(this);
1872 Ptr<NrBearerStatsSimple> rlcStats = CreateObject<NrBearerStatsSimple>("RLC");
1873 m_radioBearerStatsConnectorSimpleTraces.EnableRlcStats(rlcStats);
1874}
1875
1876void
1878{
1879 NS_LOG_FUNCTION(this);
1880 Ptr<NrBearerStatsSimple> pdcpStats = CreateObject<NrBearerStatsSimple>("PDCP");
1881 m_radioBearerStatsConnectorSimpleTraces.EnablePdcpStats(pdcpStats);
1882}
1883
1884void
1886{
1887 NS_LOG_FUNCTION(this);
1888 Ptr<NrBearerStatsCalculator> rlcStats = CreateObject<NrBearerStatsCalculator>("RLC");
1889 m_radioBearerStatsConnectorCalculator.EnableRlcStats(rlcStats);
1890}
1891
1892void
1894{
1895 NS_LOG_FUNCTION(this);
1896 Ptr<NrBearerStatsCalculator> pdcpStats = CreateObject<NrBearerStatsCalculator>("PDCP");
1897 m_radioBearerStatsConnectorCalculator.EnablePdcpStats(pdcpStats);
1898}
1899
1900Ptr<NrBearerStatsCalculator>
1902{
1903 return DynamicCast<NrBearerStatsCalculator>(
1904 m_radioBearerStatsConnectorCalculator.GetRlcStats());
1905}
1906
1907Ptr<NrBearerStatsCalculator>
1909{
1910 return DynamicCast<NrBearerStatsCalculator>(
1911 m_radioBearerStatsConnectorCalculator.GetPdcpStats());
1912}
1913
1914void
1916{
1917 NS_LOG_FUNCTION(this);
1918 if (!m_macSchedStats)
1919 {
1920 m_macSchedStats = CreateObject<NrMacSchedulingStats>();
1921 }
1922 Config::Connect(
1923 "/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbMac/DlScheduling",
1924 MakeBoundCallback(&NrMacSchedulingStats::DlSchedulingCallback, m_macSchedStats));
1925}
1926
1927void
1929{
1930 NS_LOG_FUNCTION(this);
1931 if (!m_macSchedStats)
1932 {
1933 m_macSchedStats = CreateObject<NrMacSchedulingStats>();
1934 }
1935 Config::Connect(
1936 "/NodeList/*/DeviceList/*/BandwidthPartMap/*/NrGnbMac/UlScheduling",
1937 MakeBoundCallback(&NrMacSchedulingStats::UlSchedulingCallback, m_macSchedStats));
1938}
1939
1940void
1942{
1943 NS_LOG_FUNCTION(this);
1944 Config::Connect("/ChannelList/*/$ns3::SpectrumChannel/PathLoss",
1945 MakeBoundCallback(&NrPhyRxTrace::PathlossTraceCallback, GetPhyRxTrace()));
1946}
1947
1948void
1949NrHelper::EnableDlCtrlPathlossTraces(NetDeviceContainer& ueDevs)
1950{
1951 NS_LOG_FUNCTION(this);
1952
1953 for (uint32_t i = 0; i < ueDevs.GetN(); i++)
1954 {
1955 Ptr<NrUeNetDevice> ueDev = DynamicCast<NrUeNetDevice>(ueDevs.Get(i));
1956 NS_ASSERT_MSG(ueDev,
1957 "To EnableDlCtrlPathlossTracesfunction is passed device "
1958 "container that contains non UE devices.");
1959 for (uint32_t j = 0; j < ueDev->GetCcMapSize(); j++)
1960 {
1961 Ptr<NrUePhy> nrUePhy = ueDev->GetPhy(j);
1962 Ptr<NrSpectrumPhy> nrSpectrumPhy = nrUePhy->GetSpectrumPhy();
1963 nrSpectrumPhy->EnableDlCtrlPathlossTrace();
1964 }
1965 }
1966
1967 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/NrSpectrumPhy/"
1968 "DlCtrlPathloss",
1969 MakeBoundCallback(&NrPhyRxTrace::ReportDlCtrlPathloss, GetPhyRxTrace()));
1970}
1971
1972void
1973NrHelper::EnableDlDataPathlossTraces(NetDeviceContainer& ueDevs)
1974{
1975 NS_LOG_FUNCTION(this);
1976
1977 NS_ASSERT_MSG(ueDevs.GetN(),
1978 "Passed an empty UE net device container EnableDlDataPathlossTraces function");
1979
1980 for (uint32_t i = 0; i < ueDevs.GetN(); i++)
1981 {
1982 Ptr<NrUeNetDevice> ueDev = DynamicCast<NrUeNetDevice>(ueDevs.Get(i));
1983 NS_ASSERT_MSG(ueDev,
1984 "To EnableDlDataPathlossTracesfunction is passed device "
1985 "container that contains non UE devices.");
1986 for (uint32_t j = 0; j < ueDev->GetCcMapSize(); j++)
1987 {
1988 Ptr<NrUePhy> nrUePhy = ueDev->GetPhy(j);
1989 Ptr<NrSpectrumPhy> nrSpectrumPhy = nrUePhy->GetSpectrumPhy();
1990 nrSpectrumPhy->EnableDlDataPathlossTrace();
1991 }
1992 }
1993
1994 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMapUe/*/NrUePhy/NrSpectrumPhy/"
1995 "DlDataPathloss",
1996 MakeBoundCallback(&NrPhyRxTrace::ReportDlDataPathloss, GetPhyRxTrace()));
1997}
1998
1999void
2000NrHelper::SetPmSearchTypeId(const TypeId& typeId)
2001{
2002 m_pmSearchFactory.SetTypeId(typeId);
2003}
2004
2005void
2006NrHelper::SetPmSearchAttribute(const std::string& name, const AttributeValue& value)
2007{
2008 NS_LOG_FUNCTION(this);
2009 m_pmSearchFactory.Set(name, value);
2010}
2011
2012void
2014{
2015 NS_ASSERT_MSG(((ap.nAntCols % ap.nHorizPorts) == 0),
2016 "The number of horizontal ports of gNB must divide number of element columns");
2017 NS_ASSERT_MSG(((ap.nAntRows % ap.nVertPorts) == 0),
2018 "The number of vertical ports of gNB must divide number of element rows");
2019
2020 auto antFactory = ObjectFactory{};
2021 antFactory.SetTypeId(ap.antennaElem);
2022 SetGnbAntennaAttribute("AntennaElement", PointerValue(antFactory.Create()));
2023 SetGnbAntennaAttribute("NumColumns", UintegerValue(ap.nAntCols));
2024 SetGnbAntennaAttribute("NumRows", UintegerValue(ap.nAntRows));
2025 SetGnbAntennaAttribute("IsDualPolarized", BooleanValue(ap.isDualPolarized));
2026 SetGnbAntennaAttribute("NumHorizontalPorts", UintegerValue(ap.nHorizPorts));
2027 SetGnbAntennaAttribute("NumVerticalPorts", UintegerValue(ap.nVertPorts));
2028 SetGnbAntennaAttribute("BearingAngle", DoubleValue(ap.bearingAngle));
2029 SetGnbAntennaAttribute("PolSlantAngle", DoubleValue(ap.polSlantAngle));
2030}
2031
2032void
2034{
2035 NS_ASSERT_MSG(((ap.nAntCols % ap.nHorizPorts) == 0),
2036 "The number of horizontal ports of UE must divide number of element columns");
2037 NS_ASSERT_MSG(((ap.nAntRows % ap.nVertPorts) == 0),
2038 "The number of vertical ports of UE must divide number of element rows");
2039
2040 auto antFactory = ObjectFactory{};
2041 antFactory.SetTypeId(ap.antennaElem);
2042 SetUeAntennaAttribute("AntennaElement", PointerValue(antFactory.Create()));
2043 SetUeAntennaAttribute("NumColumns", UintegerValue(ap.nAntCols));
2044 SetUeAntennaAttribute("NumRows", UintegerValue(ap.nAntRows));
2045 SetUeAntennaAttribute("IsDualPolarized", BooleanValue(ap.isDualPolarized));
2046 SetUeAntennaAttribute("NumHorizontalPorts", UintegerValue(ap.nHorizPorts));
2047 SetUeAntennaAttribute("NumVerticalPorts", UintegerValue(ap.nVertPorts));
2048 SetUeAntennaAttribute("BearingAngle", DoubleValue(ap.bearingAngle));
2049 SetUeAntennaAttribute("PolSlantAngle", DoubleValue(ap.polSlantAngle));
2050}
2051
2052void
2054{
2055 // Set parameters for MIMO precoding matrix search
2056 SetAttribute("EnableMimoFeedback", BooleanValue(true));
2057 auto searchTypeId = TypeId::LookupByName(mp.pmSearchMethod);
2058 SetPmSearchTypeId(searchTypeId);
2059 SetPmSearchAttribute("RankLimit", UintegerValue(mp.rankLimit));
2060 SetPmSearchAttribute("SubbandSize", UintegerValue(mp.subbandSize));
2061 SetPmSearchAttribute("DownsamplingTechnique", StringValue(mp.downsamplingTechnique));
2062 if (searchTypeId == NrPmSearchFull::GetTypeId())
2063 {
2064 SetPmSearchAttribute("CodebookType", TypeIdValue(TypeId::LookupByName(mp.fullSearchCb)));
2065 }
2066}
2067
2068} // namespace ns3
static TypeId GetTypeId()
GetTypeId.
static TypeId GetTypeId()
GetTypeId.
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.
static TypeId GetTypeId()
GetTypeId.
Definition nr-amc.cc:49
Ptr< NrBearerStatsBase > GetPdcpStats()
void EnablePdcpStats(Ptr< NrBearerStatsBase > pdcpStats)
void EnableRlcStats(Ptr< NrBearerStatsBase > rlcStats)
Ptr< NrBearerStatsBase > GetRlcStats()
Base helper class to handle the creation of the EPC entities.
static Ptr< NrEpcTft > Default()
This class contains the specification of EPS Bearers.
@ NGBR_VIDEO_TCP_DEFAULT
Non-GBR TCP-based Video (Buffered Streaming, e.g., www, e-mail...)
static TypeId GetTypeId()
Get the TypeId.
The NrGnbNetDevice class.
void RouteIngoingCtrlMsgs(const std::list< Ptr< NrControlMessage > > &msgList, uint8_t sourceBwpId)
The gNB received a CTRL message list.
void GenerateDataCqiReport(const SpectrumValue &sinr)
Generate a DL CQI report.
void ReportUlHarqFeedback(const UlHarqInfo &mes)
Get the HARQ feedback from NrSpectrumPhy and forward it to the scheduler.
void PhyDataPacketReceived(const Ptr< Packet > &p)
Receive a PHY data packet.
static TypeId GetTypeId()
Get Type id.
Definition nr-gnb-phy.cc:63
void EnableDlDataPhyTraces()
Enable DL DATA PHY traces.
static Ptr< BwpManagerGnb > GetBwpManagerGnb(const Ptr< NetDevice > &gnbDevice)
Get the BwpManager of the GNB.
Definition nr-helper.cc:450
void AttachToClosestGnb(NetDeviceContainer ueDevices, NetDeviceContainer gnbDevices)
Attach the UE specified to the closest GNB.
void ActivateDataRadioBearer(NetDeviceContainer ueDevices, NrEpsBearer bearer)
Activate a Data Radio Bearer on a given UE devices.
void SetPhasedArraySpectrumPropagationLossModelAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the PhasedArraySpectrumPropagationLossModel before it is created.
int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
void UpdateDeviceConfigs(const NetDeviceContainer &netDevs)
Update netdevice configuration of one or more UEs and/or gNBs.
Definition nr-helper.cc:538
static Ptr< NrUeMac > GetUeMac(const Ptr< NetDevice > &ueDevice, uint32_t bwpIndex)
Get a pointer to the MAC of the UE at the specified BWP.
Definition nr-helper.cc:424
void EnableTraces()
Enables the following traces: Transmitted/Received Control Messages DL/UL Phy Traces RLC traces PDCP ...
NetDeviceContainer InstallGnbDevice(const NodeContainer &c, const std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > allBwps)
Install one (or more) GNBs.
Definition nr-helper.cc:521
void SetBeamformingHelper(Ptr< BeamformingHelperBase > beamformingHelper)
Set an ideal beamforming helper.
void SetGnbDlAmcAttribute(const std::string &n, const AttributeValue &v)
NrHelper()
NrHelper constructor.
Definition nr-helper.cc:56
Ptr< NrBearerStatsCalculator > GetPdcpStatsCalculator()
Get the PDCP stats calculator object.
void DeActivateDedicatedEpsBearer(Ptr< NetDevice > ueDevice, Ptr< NetDevice > gnbDevice, uint8_t bearerId)
Manually trigger dedicated bearer de-activation at specific simulation time.
void EnableUePhyCtrlMsgsTraces()
Enable UE PHY CTRL TX and RX traces.
void EnableRlcSimpleTraces()
Enable RLC simple traces (DL RLC TX, DL RLC RX, UL DL TX, UL DL RX)
void SetUeAntennaAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the UE antenna, before it is created.
void SetUeChannelAccessManagerAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the UE channel access manager, before it is created.
bool GetSnrTest() const
GetSnrTest.
Definition nr-helper.cc:498
void EnableGnbPhyCtrlMsgsTraces()
Enable gNB PHY CTRL TX and RX traces.
~NrHelper() override
~NrHelper
Definition nr-helper.cc:90
void SetGnbBwpManagerAlgorithmTypeId(const TypeId &typeId)
Set the TypeId of the GNB BWP Manager. Works only before it is created.
static Ptr< BwpManagerUe > GetBwpManagerUe(const Ptr< NetDevice > &ueDevice)
Get the BwpManager of the UE.
Definition nr-helper.cc:464
void EnableDlMacSchedTraces()
std::pair< double, BandwidthPartInfoPtrVector > CreateBandwidthParts(std::vector< CcBwpCreator::SimpleOperationBandConf > bandConfs)
Create BandwidthParts from a vector of band configurations.
Definition nr-helper.cc:368
void SetUeMacAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the UE MAC, before it is created.
void SetUlErrorModel(const std::string &errorModelTypeId)
Set the ErrorModel for UL AMC and UE spectrum at the same time.
@ INIT_PROPAGATION
Initialize the propagation loss model.
Definition nr-helper.h:371
@ INIT_FADING
Initialize the fading model.
Definition nr-helper.h:372
@ INIT_CHANNEL
Initialize the channel model.
Definition nr-helper.h:373
void SetUeBwpManagerAlgorithmTypeId(const TypeId &typeId)
Set the TypeId of the UE BWP Manager. Works only before it is created.
void EnableUlPhyTraces()
Enable UL PHY traces.
void EnablePathlossTraces()
Enable trace sinks for DL and UL pathloss.
Ptr< NrMacRxTrace > GetMacRxTrace()
Get the mac stats trace object.
void SetPmSearchAttribute(const std::string &name, const AttributeValue &value)
Set attribute of the precoding matrix search algorithm.
void SetGnbAntennaAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the GNB antenna, before it is created.
void SetupGnbAntennas(const AntennaParams &ap)
Set parameters for gNB and UE antenna arrays.
static Ptr< NrGnbPhy > GetGnbPhy(const Ptr< NetDevice > &gnbDevice, uint32_t bwpIndex)
Get a pointer to the PHY of the GNB at the specified BWP.
Definition nr-helper.cc:398
void AttachToGnb(const Ptr< NetDevice > &ueDevice, const Ptr< NetDevice > &gnbDevice)
Attach a UE to a particular GNB.
void EnableUlMacSchedTraces()
void SetGnbUlAmcAttribute(const std::string &n, const AttributeValue &v)
static uint32_t GetNumberBwp(const Ptr< const NetDevice > &gnbDevice)
Get the number of configured BWP for a specific GNB NetDevice.
Definition nr-helper.cc:386
void EnableGnbMacCtrlMsgsTraces()
Enable gNB MAC CTRL TX and RX traces.
uint8_t ActivateDedicatedEpsBearer(NetDeviceContainer ueDevices, NrEpsBearer bearer, Ptr< NrEpcTft > tft)
void SetUeChannelAccessManagerTypeId(const TypeId &typeId)
Set the TypeId of the UE Channel Access Manager. Works only before it is created.
Ptr< NrBearerStatsCalculator > GetRlcStatsCalculator()
Get the RLC stats calculator object.
void EnableTransportBlockTrace()
Enable transport block trace.
void InitializeOperationBand(OperationBandInfo *band, uint8_t flags=INIT_PROPAGATION|INIT_FADING|INIT_CHANNEL)
Initialize the bandwidth parts by creating and configuring the channel models, if they are not alread...
Definition nr-helper.cc:276
void EnableGnbPacketCountTrace()
Enable gNB packet count trace.
void SetDlErrorModel(const std::string &errorModelTypeId)
Set the ErrorModel for DL AMC and GNB spectrum at the same time.
void EnableRlcE2eTraces()
Enable RLC calculator and end-to-end RCL traces to file.
void EnablePdcpSimpleTraces()
Enable PDCP traces (DL PDCP TX, DL PDCP RX, UL PDCP TX, UL PDCP RX)
static Ptr< NrMacScheduler > GetScheduler(const Ptr< NetDevice > &gnbDevice, uint32_t bwpIndex)
Get the Scheduler from the GNB specified.
Definition nr-helper.cc:478
void SetUeBwpManagerAlgorithmAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the GNB BWP Manager, before it is created.
void SetEpcHelper(Ptr< NrEpcHelper > NrEpcHelper)
void SetGnbMacAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the GNB MAC, before it is created.
void SetGnbPhyAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the GNB PHY, before it is created.
void EnableDlCtrlPhyTraces()
Enable DL CTRL PHY traces.
void SetupUeAntennas(const AntennaParams &ap)
Set parameters for gNB and UE antenna arrays.
static Ptr< NrGnbMac > GetGnbMac(const Ptr< NetDevice > &gnbDevice, uint32_t bwpIndex)
Get a pointer to the MAC of the GNB at the specified BWP.
Definition nr-helper.cc:411
void SetUePhyAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the UE PHY, before it is created.
static Ptr< NrUePhy > GetUePhy(const Ptr< NetDevice > &ueDevice, uint32_t bwpIndex)
Get a pointer to the PHY of the UE at the specified BWP.
Definition nr-helper.cc:437
void SetupMimoPmi(const MimoPmiParams &mp)
Set parameters for PMI search in MIMO operation.
void EnableUePacketCountTrace()
Enable UE packet count trace.
static TypeId GetTypeId()
GetTypeId.
Definition nr-helper.cc:101
void SetUeSpectrumAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the UE spectrum, before it is created.
void SetPathlossAttribute(const std::string &n, const AttributeValue &v)
void SetSchedulerAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the scheduler, before it is created.
void EnableUeMacCtrlMsgsTraces()
Enable UE MAC CTRL TX and RX traces.
void SetSchedulerTypeId(const TypeId &typeId)
Set the Scheduler TypeId. Works only before it is created.
void SetGnbBwpManagerAlgorithmAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the GNB BWP Manager, before it is created.
Ptr< NrPhyRxTrace > GetPhyRxTrace()
Get the phy traces object.
void SetGnbSpectrumAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the GNB spectrum, before it is created.
NetDeviceContainer InstallUeDevice(const NodeContainer &c, const std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > &allBwps)
Install one (or more) UEs.
Definition nr-helper.cc:504
void SetChannelConditionModelAttribute(const std::string &n, const AttributeValue &v)
void SetGnbChannelAccessManagerAttribute(const std::string &n, const AttributeValue &v)
Set an attribute for the GNB channel access manager, before it is created.
void EnablePdcpE2eTraces()
Enable PDCP calculator and end-to-end PDCP traces to file.
void SetGnbChannelAccessManagerTypeId(const TypeId &typeId)
Set the TypeId of the GNB Channel Access Manager. Works only before it is created.
void SetGnbBeamManagerTypeId(const TypeId &typeId)
Set the TypeId of the beam manager.
void SetPmSearchTypeId(const TypeId &typeId)
Set TypeId of the precoding matrix search algorithm.
void SetSnrTest(bool snrTest)
SetSnrTest.
Definition nr-helper.cc:492
static void RxedGnbMacCtrlMsgsCallback(Ptr< NrMacRxTrace > macStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static void TxedGnbMacCtrlMsgsCallback(Ptr< NrMacRxTrace > macStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static void RxedUeMacCtrlMsgsCallback(Ptr< NrMacRxTrace > macStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static void TxedUeMacCtrlMsgsCallback(Ptr< NrMacRxTrace > macStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static TypeId GetTypeId()
GetTypeId.
static void UlSchedulingCallback(Ptr< NrMacSchedulingStats > macStats, std::string path, NrSchedulingCallbackInfo traceInfo)
static void DlSchedulingCallback(Ptr< NrMacSchedulingStats > macStats, std::string path, NrSchedulingCallbackInfo traceInfo)
static void RxedGnbPhyCtrlMsgsCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static void ReportDlDataPathloss(Ptr< NrPhyRxTrace > phyStats, std::string path, uint16_t cellId, uint8_t bwpId, uint32_t ueNodeId, double lossDb, uint8_t cqi)
Write DL DATA pathloss values in a file.
static void PathlossTraceCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, Ptr< const SpectrumPhy > txPhy, Ptr< const SpectrumPhy > rxPhy, double lossDb)
Trace sink for spectrum channel pathloss trace.
static void TxedGnbPhyCtrlMsgsCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static void TxedUePhyCtrlMsgsCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static void TxedUePhyHarqFeedbackCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, uint8_t harqId, uint32_t k1Delay)
static void RxedUePhyCtrlMsgsCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, Ptr< const NrControlMessage > msg)
static void DlCtrlSinrCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, uint16_t cellId, uint16_t rnti, double avgSinr, uint16_t bwpId)
Trace sink for DL Average SINR of CTRL (in dB).
static void RxedUePhyDlDciCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, SfnSf sfn, uint16_t nodeId, uint16_t rnti, uint8_t bwpId, uint8_t harqId, uint32_t k1Delay)
static void DlDataSinrCallback(Ptr< NrPhyRxTrace > phyStats, std::string path, uint16_t cellId, uint16_t rnti, double avgSinr, uint16_t bwpId)
Trace sink for DL Average SINR of DATA (in dB).
static void ReportDlCtrlPathloss(Ptr< NrPhyRxTrace > phyStats, std::string path, uint16_t cellId, uint8_t bwpId, uint32_t ueNodeId, double lossDb)
Write DL CTRL pathloss values in a file.
static TypeId GetTypeId()
Get TypeId.
Base class for searching optimal precoding matrices and creating full CQI/PMI feedback This is a most...
void SetGnbParams(bool isDualPol, size_t numHPorts, size_t numVPorts)
Set the antenna parameters of the gNB antenna.
void UpdateSinrPerceived(const SpectrumValue &sinr)
SpectrumPhy that will be called when the SINR for the received DATA is being calculated by the interf...
static TypeId GetTypeId()
Get the object TypeId.
std::function< void(const std::list< Ptr< NrControlMessage > > &, uint8_t)> NrPhyRxCtrlEndOkCallback
This callback method type is used to notify that CTRL is received.
void UpdateSrsSinrPerceived(const SpectrumValue &srsSinr)
SpectrumPhy that will be called when the SINR for the received SRS at gNB is being calculated by the ...
void UpdateMimoSinrPerceived(const std::vector< MimoSinrChunk > &sinr)
Store the SINR chunks for all received signals at end of interference calculations.
Callback< void, const DlHarqInfo & > NrPhyDlHarqFeedbackCallback
void ReportDlCtrlSinr(const SpectrumValue &sinr)
Called when DlCtrlSinr is fired.
The MAC class for the UE.
Definition nr-ue-mac.h:104
static TypeId GetTypeId()
Get the Type id.
Definition nr-ue-mac.cc:205
The User Equipment NetDevice.
void RouteIngoingCtrlMsgs(const std::list< Ptr< NrControlMessage > > &msgList, uint8_t sourceBwpId)
The UE received a CTRL message list.
static TypeId GetTypeId()
GetTypeId.
void EnqueueDlHarqFeedback(const DlHarqInfo &m) const
Spectrum has calculated the HarqFeedback for one DL transmission, and give it to the NetDevice of the...
void ReceivePss(uint16_t cellId, const Ptr< SpectrumValue > &p)
Receive PSS and calculate RSRQ in dBm.
void GenerateDlCqiReport(const SpectrumValue &sinr)
Generate a DL CQI report.
void GenerateDlCqiReportMimo(const std::vector< MimoSignalChunk > &mimoChunks)
Generate DL CQI, PMI, and RI (channel quality precoding matrix and rank indicators)
void PhyDataPacketReceived(const Ptr< Packet > &p)
Receive a PHY data packet.
void ReportRsReceivedPower(const SpectrumValue &power)
Called when rsReceivedPower is fired.
static TypeId GetTypeId()
Get the object TypeId.
Definition nr-ue-phy.cc:75
@ UMi_Buildings
UMi_StreetCanyon with buildings.
@ UMa_LoS
UMa where all the nodes will be in Line-of-Sight.
@ RMa_LoS
RMa where all the nodes will be in Line-of-Sight.
@ InH_OfficeOpen
InH_OfficeOpen.
@ InH_OfficeOpen_nLoS
indoor office where all the nodes will not be in Line-of-Sight
@ V2V_Highway
V2V_Highway.
@ RMa_nLoS
RMA where all the nodes will not be in Line-of-Sight.
@ InH_OfficeMixed_nLoS
indoor office where all the nodes will not be in Line-of-Sight
@ UMa_Buildings
UMa with buildings.
@ InH_OfficeOpen_LoS
indoor office where all the nodes will be in Line-of-Sight
@ UMa_nLoS
UMa where all the nodes will not be in Line-of-Sight.
@ UMi_StreetCanyon_LoS
UMi_StreetCanyon where all the nodes will be in Line-of-Sight.
@ InH_OfficeMixed
InH_OfficeMixed.
@ UMi_StreetCanyon
UMi_StreetCanyon.
@ InH_OfficeMixed_LoS
indoor office where all the nodes will be in Line-of-Sight
parameters of the gNB or UE antenna arrays
Definition nr-helper.h:855
size_t nAntRows
Number of antenna element rows (vertical height)
Definition nr-helper.h:858
bool isDualPolarized
true if antennas are cross-polarized (dual-polarized)
Definition nr-helper.h:859
double bearingAngle
Bearing angle in radians.
Definition nr-helper.h:862
std::string antennaElem
Antenna type.
Definition nr-helper.h:856
size_t nHorizPorts
Number of antenna ports in horizontal direction.
Definition nr-helper.h:860
size_t nVertPorts
Number of antenna ports in vertical direction.
Definition nr-helper.h:861
size_t nAntCols
Number of antenna element columns (horizontal width)
Definition nr-helper.h:857
double polSlantAngle
Polarization slant angle in radians.
Definition nr-helper.h:863
parameters for the search of optimal rank and precoding matrix indicator (RI, PMI)
Definition nr-helper.h:868
uint8_t rankLimit
Limit maximum MIMO rank to model limited UE capabilities.
Definition nr-helper.h:871
std::string downsamplingTechnique
Sub-band compression technique.
Definition nr-helper.h:873
uint8_t subbandSize
Number of PRBs per subband for downsampling.
Definition nr-helper.h:872
std::string fullSearchCb
Codebook when using full-search algorithm.
Definition nr-helper.h:870
std::string pmSearchMethod
Precoding matrix search algorithm.
Definition nr-helper.h:869
Operation band information structure.
std::vector< ComponentCarrierInfoPtr > m_cc
Operation band component carriers.