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