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