5G-LENA nr-v3.3-161-gad18933f
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-gnb-mac.cc
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#define NS_LOG_APPEND_CONTEXT \
6 do \
7 { \
8 std::clog << " [ CellId " << GetCellId() << ", bwpId " << GetBwpId() << "] "; \
9 } while (false);
10
11#include "nr-gnb-mac.h"
12
13#include "beam-id.h"
14#include "nr-common.h"
15#include "nr-control-messages.h"
16#include "nr-mac-header-fs-ul.h"
17#include "nr-mac-header-vs.h"
18#include "nr-mac-pdu-info.h"
19#include "nr-mac-sched-sap.h"
20#include "nr-mac-scheduler.h"
21#include "nr-mac-short-bsr-ce.h"
22#include "nr-phy-mac-common.h"
23#include "nr-radio-bearer-tag.h"
24
25#include "ns3/log.h"
26#include "ns3/spectrum-model.h"
27#include "ns3/uinteger.h"
28
29#include <algorithm>
30
31namespace ns3
32{
33NS_LOG_COMPONENT_DEFINE("NrGnbMac");
34
35NS_OBJECT_ENSURE_REGISTERED(NrGnbMac);
36
37// //////////////////////////////////////
38// member SAP forwarders
39// //////////////////////////////////////
40
41class NrGnbMacMemberGnbCmacSapProvider : public NrGnbCmacSapProvider
42{
43 public:
44 NrGnbMacMemberGnbCmacSapProvider(NrGnbMac* mac);
45
46 // inherited from NrGnbCmacSapProvider
47 void ConfigureMac(uint16_t ulBandwidth, uint16_t dlBandwidth) override;
48 void AddUe(uint16_t rnti) override;
49 void RemoveUe(uint16_t rnti) override;
50 void AddLc(LcInfo lcinfo, NrMacSapUser* msu) override;
51 void ReconfigureLc(LcInfo lcinfo) override;
52 void ReleaseLc(uint16_t rnti, uint8_t lcid) override;
53 void UeUpdateConfigurationReq(UeConfig params) override;
54 RachConfig GetRachConfig() override;
55 AllocateNcRaPreambleReturnValue AllocateNcRaPreamble(uint16_t rnti) override;
56
57 private:
58 NrGnbMac* m_mac;
59};
60
61NrGnbMacMemberGnbCmacSapProvider::NrGnbMacMemberGnbCmacSapProvider(NrGnbMac* mac)
62 : m_mac(mac)
63{
64}
65
66void
67NrGnbMacMemberGnbCmacSapProvider::ConfigureMac(uint16_t ulBandwidth, uint16_t dlBandwidth)
68{
69 m_mac->DoConfigureMac(ulBandwidth, dlBandwidth);
70}
71
72void
73NrGnbMacMemberGnbCmacSapProvider::AddUe(uint16_t rnti)
74{
75 m_mac->DoAddUe(rnti);
76}
77
78void
79NrGnbMacMemberGnbCmacSapProvider::RemoveUe(uint16_t rnti)
80{
81 m_mac->DoRemoveUe(rnti);
82}
83
84void
85NrGnbMacMemberGnbCmacSapProvider::AddLc(LcInfo lcinfo, NrMacSapUser* msu)
86{
87 m_mac->DoAddLc(lcinfo, msu);
88}
89
90void
91NrGnbMacMemberGnbCmacSapProvider::ReconfigureLc(LcInfo lcinfo)
92{
93 m_mac->DoReconfigureLc(lcinfo);
94}
95
96void
97NrGnbMacMemberGnbCmacSapProvider::ReleaseLc(uint16_t rnti, uint8_t lcid)
98{
99 m_mac->DoReleaseLc(rnti, lcid);
100}
101
102void
103NrGnbMacMemberGnbCmacSapProvider::UeUpdateConfigurationReq(UeConfig params)
104{
105 m_mac->UeUpdateConfigurationReq(params);
106}
107
108NrGnbCmacSapProvider::RachConfig
109NrGnbMacMemberGnbCmacSapProvider::GetRachConfig()
110{
111 return m_mac->DoGetRachConfig();
112}
113
114NrGnbCmacSapProvider::AllocateNcRaPreambleReturnValue
115NrGnbMacMemberGnbCmacSapProvider::AllocateNcRaPreamble(uint16_t rnti)
116{
117 return m_mac->DoAllocateNcRaPreamble(rnti);
118}
119
120// SAP interface between gNB PHY AND MAC
121// PHY is provider and MAC is user of its service following OSI model.
122// However, PHY may request some information from MAC.
123class NrMacGnbMemberPhySapUser : public NrGnbPhySapUser
124{
125 public:
126 NrMacGnbMemberPhySapUser(NrGnbMac* mac);
127
128 void ReceivePhyPdu(Ptr<Packet> p) override;
129
130 void ReceiveControlMessage(Ptr<NrControlMessage> msg) override;
131
132 void SlotDlIndication(const SfnSf&, LteNrTddSlotType) override;
133
134 void SlotUlIndication(const SfnSf&, LteNrTddSlotType) override;
135
136 void SetCurrentSfn(const SfnSf&) override;
137
138 void UlCqiReport(NrMacSchedSapProvider::SchedUlCqiInfoReqParameters cqi) override;
139
140 void ReceiveRachPreamble(uint32_t raId) override;
141
142 void UlHarqFeedback(UlHarqInfo params) override;
143
144 void BeamChangeReport(BeamId beamId, uint8_t rnti) override;
145
146 uint32_t GetNumRbPerRbg() const override;
147
148 std::shared_ptr<DciInfoElementTdma> GetDlCtrlDci() const override;
149 std::shared_ptr<DciInfoElementTdma> GetUlCtrlDci() const override;
150
151 uint8_t GetDlCtrlSymbols() const override;
152
153 private:
154 NrGnbMac* m_mac;
155};
156
157NrMacGnbMemberPhySapUser::NrMacGnbMemberPhySapUser(NrGnbMac* mac)
158 : m_mac(mac)
159{
160}
161
162void
163NrMacGnbMemberPhySapUser::ReceivePhyPdu(Ptr<Packet> p)
164{
165 m_mac->DoReceivePhyPdu(p);
166}
167
168void
169NrMacGnbMemberPhySapUser::ReceiveControlMessage(Ptr<NrControlMessage> msg)
170{
171 m_mac->DoReceiveControlMessage(msg);
172}
173
174void
175NrMacGnbMemberPhySapUser::SlotDlIndication(const SfnSf& sfn, LteNrTddSlotType type)
176{
177 m_mac->DoSlotDlIndication(sfn, type);
178}
179
180void
181NrMacGnbMemberPhySapUser::SlotUlIndication(const SfnSf& sfn, LteNrTddSlotType type)
182{
183 m_mac->DoSlotUlIndication(sfn, type);
184}
185
186void
187NrMacGnbMemberPhySapUser::SetCurrentSfn(const SfnSf& sfn)
188{
189 m_mac->SetCurrentSfn(sfn);
190}
191
192void
193NrMacGnbMemberPhySapUser::UlCqiReport(NrMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
194{
195 m_mac->DoUlCqiReport(ulcqi);
196}
197
198void
199NrMacGnbMemberPhySapUser::ReceiveRachPreamble(uint32_t raId)
200{
201 m_mac->ReceiveRachPreamble(raId);
202}
203
204void
205NrMacGnbMemberPhySapUser::UlHarqFeedback(UlHarqInfo params)
206{
207 m_mac->DoUlHarqFeedback(params);
208}
209
210void
211NrMacGnbMemberPhySapUser::BeamChangeReport(BeamId beamId, uint8_t rnti)
212{
213 m_mac->BeamChangeReport(beamId, rnti);
214}
215
216uint32_t
217NrMacGnbMemberPhySapUser::GetNumRbPerRbg() const
218{
219 return m_mac->GetNumRbPerRbg();
220}
221
222std::shared_ptr<DciInfoElementTdma>
223NrMacGnbMemberPhySapUser::GetDlCtrlDci() const
224{
225 return m_mac->GetDlCtrlDci();
226}
227
228std::shared_ptr<DciInfoElementTdma>
229NrMacGnbMemberPhySapUser::GetUlCtrlDci() const
230{
231 return m_mac->GetUlCtrlDci();
232}
233
234uint8_t
235NrMacGnbMemberPhySapUser::GetDlCtrlSymbols() const
236{
237 return m_mac->GetDlCtrlSyms();
238}
239
240// MAC Sched
241
242class NrMacMemberMacSchedSapUser : public NrMacSchedSapUser
243{
244 public:
245 NrMacMemberMacSchedSapUser(NrGnbMac* mac);
246 void SchedConfigInd(const struct SchedConfigIndParameters& params) override;
247 Ptr<const SpectrumModel> GetSpectrumModel() const override;
248 uint32_t GetNumRbPerRbg() const override;
249 uint8_t GetNumHarqProcess() const override;
250 uint16_t GetBwpId() const override;
251 uint16_t GetCellId() const override;
252 uint32_t GetSymbolsPerSlot() const override;
253 Time GetSlotPeriod() const override;
254 void BuildRarList(SlotAllocInfo& slotAllocInfo) override;
255
256 private:
257 NrGnbMac* m_mac;
258};
259
260NrMacMemberMacSchedSapUser::NrMacMemberMacSchedSapUser(NrGnbMac* mac)
261 : m_mac(mac)
262{
263 // Some blank spaces
264}
265
266void
267NrMacMemberMacSchedSapUser::SchedConfigInd(const struct SchedConfigIndParameters& params)
268{
269 m_mac->DoSchedConfigIndication(params);
270}
271
272Ptr<const SpectrumModel>
273NrMacMemberMacSchedSapUser::GetSpectrumModel() const
274{
275 return m_mac->m_phySapProvider
276 ->GetSpectrumModel(); // MAC forwards the call from scheduler to PHY; i.e. this function
277 // connects two providers of MAC: scheduler and PHY
278}
279
280uint32_t
281NrMacMemberMacSchedSapUser::GetNumRbPerRbg() const
282{
283 return m_mac->GetNumRbPerRbg();
284}
285
286uint8_t
287NrMacMemberMacSchedSapUser::GetNumHarqProcess() const
288{
289 return m_mac->GetNumHarqProcess();
290}
291
292uint16_t
293NrMacMemberMacSchedSapUser::GetBwpId() const
294{
295 return m_mac->GetBwpId();
296}
297
298uint16_t
299NrMacMemberMacSchedSapUser::GetCellId() const
300{
301 return m_mac->GetCellId();
302}
303
304uint32_t
305NrMacMemberMacSchedSapUser::GetSymbolsPerSlot() const
306{
307 return m_mac->m_phySapProvider->GetSymbolsPerSlot();
308}
309
310Time
311NrMacMemberMacSchedSapUser::GetSlotPeriod() const
312{
313 return m_mac->m_phySapProvider->GetSlotPeriod();
314}
315
316void
317NrMacMemberMacSchedSapUser::BuildRarList(ns3::SlotAllocInfo& slotAllocInfo)
318{
319 m_mac->DoBuildRarList(slotAllocInfo);
320}
321
322class NrMacMemberMacCschedSapUser : public NrMacCschedSapUser
323{
324 public:
325 NrMacMemberMacCschedSapUser(NrGnbMac* mac);
326
327 void CschedCellConfigCnf(
328 const struct NrMacCschedSapUser::CschedCellConfigCnfParameters& params) override;
329 void CschedUeConfigCnf(
330 const struct NrMacCschedSapUser::CschedUeConfigCnfParameters& params) override;
331 void CschedLcConfigCnf(
332 const struct NrMacCschedSapUser::CschedLcConfigCnfParameters& params) override;
333 void CschedLcReleaseCnf(
334 const struct NrMacCschedSapUser::CschedLcReleaseCnfParameters& params) override;
335 void CschedUeReleaseCnf(
336 const struct NrMacCschedSapUser::CschedUeReleaseCnfParameters& params) override;
337 void CschedUeConfigUpdateInd(
338 const struct NrMacCschedSapUser::CschedUeConfigUpdateIndParameters& params) override;
339 void CschedCellConfigUpdateInd(
340 const struct NrMacCschedSapUser::CschedCellConfigUpdateIndParameters& params) override;
341
342 private:
343 NrGnbMac* m_mac;
344};
345
346NrMacMemberMacCschedSapUser::NrMacMemberMacCschedSapUser(NrGnbMac* mac)
347 : m_mac(mac)
348{
349}
350
351void
352NrMacMemberMacCschedSapUser::CschedCellConfigCnf(const struct CschedCellConfigCnfParameters& params)
353{
354 m_mac->DoCschedCellConfigCnf(params);
355}
356
357void
358NrMacMemberMacCschedSapUser::CschedUeConfigCnf(const struct CschedUeConfigCnfParameters& params)
359{
360 m_mac->DoCschedUeConfigCnf(params);
361}
362
363void
364NrMacMemberMacCschedSapUser::CschedLcConfigCnf(const struct CschedLcConfigCnfParameters& params)
365{
366 m_mac->DoCschedLcConfigCnf(params);
367}
368
369void
370NrMacMemberMacCschedSapUser::CschedLcReleaseCnf(const struct CschedLcReleaseCnfParameters& params)
371{
372 m_mac->DoCschedLcReleaseCnf(params);
373}
374
375void
376NrMacMemberMacCschedSapUser::CschedUeReleaseCnf(const struct CschedUeReleaseCnfParameters& params)
377{
378 m_mac->DoCschedUeReleaseCnf(params);
379}
380
381void
382NrMacMemberMacCschedSapUser::CschedUeConfigUpdateInd(
383 const struct CschedUeConfigUpdateIndParameters& params)
384{
385 m_mac->DoCschedUeConfigUpdateInd(params);
386}
387
388void
389NrMacMemberMacCschedSapUser::CschedCellConfigUpdateInd(
390 const struct CschedCellConfigUpdateIndParameters& params)
391{
392 m_mac->DoCschedCellConfigUpdateInd(params);
393}
394
395TypeId
396NrGnbMac::GetTypeId()
397{
398 static TypeId tid =
399 TypeId("ns3::NrGnbMac")
400 .SetParent<Object>()
401 .AddConstructor<NrGnbMac>()
402 .AddAttribute(
403 "NumRbPerRbg",
404 "Number of resource blocks per resource block group.",
405 UintegerValue(1),
406 MakeUintegerAccessor(&NrGnbMac::SetNumRbPerRbg, &NrGnbMac::GetNumRbPerRbg),
407 MakeUintegerChecker<uint32_t>())
408 .AddAttribute(
409 "NumHarqProcess",
410 "Number of concurrent stop-and-wait Hybrid ARQ processes per user",
411 UintegerValue(16),
412 MakeUintegerAccessor(&NrGnbMac::SetNumHarqProcess, &NrGnbMac::GetNumHarqProcess),
413 MakeUintegerChecker<uint8_t>())
414 .AddTraceSource("DlScheduling",
415 "Information regarding DL scheduling.",
416 MakeTraceSourceAccessor(&NrGnbMac::m_dlScheduling),
417 "ns3::NrGnbMac::DlSchedulingTracedCallback")
418 .AddTraceSource("UlScheduling",
419 "Information regarding UL scheduling.",
420 MakeTraceSourceAccessor(&NrGnbMac::m_ulScheduling),
421 "ns3::NrGnbMac::SchedulingTracedCallback")
422 .AddTraceSource("SrReq",
423 "Information regarding received scheduling request.",
424 MakeTraceSourceAccessor(&NrGnbMac::m_srCallback),
425 "ns3::NrGnbMac::SrTracedCallback")
426 .AddTraceSource("GnbMacRxedCtrlMsgsTrace",
427 "Gnb MAC Rxed Control Messages Traces.",
428 MakeTraceSourceAccessor(&NrGnbMac::m_macRxedCtrlMsgsTrace),
429 "ns3::NrMacRxTrace::RxedGnbMacCtrlMsgsTracedCallback")
430 .AddTraceSource("GnbMacTxedCtrlMsgsTrace",
431 "Gnb MAC Txed Control Messages Traces.",
432 MakeTraceSourceAccessor(&NrGnbMac::m_macTxedCtrlMsgsTrace),
433 "ns3::NrMacRxTrace::TxedGnbMacCtrlMsgsTracedCallback")
434 .AddTraceSource("DlHarqFeedback",
435 "Harq feedback.",
436 MakeTraceSourceAccessor(&NrGnbMac::m_dlHarqFeedback),
437 "ns3::NrGnbMac::DlHarqFeedbackTracedCallback")
438 .AddAttribute("NumberOfRaPreambles",
439 "How many random access preambles are available for the contention based "
440 "RACH process",
441 UintegerValue(52),
442 MakeUintegerAccessor(&NrGnbMac::SetNumberOfRaPreambles),
443 MakeUintegerChecker<uint8_t>(4, 64))
444 .AddAttribute("PreambleTransMax",
445 "Maximum number of random access preamble transmissions",
446 UintegerValue(50),
447 MakeUintegerAccessor(&NrGnbMac::SetPreambleTransMax),
448 MakeUintegerChecker<uint8_t>(3, 200))
449 .AddAttribute(
450 "RaResponseWindowSize",
451 "Length of the window for the reception of the random access response (RAR); "
452 "the resulting RAR timeout is this value + 5 ms",
453 UintegerValue(3),
454 MakeUintegerAccessor(&NrGnbMac::SetRaResponseWindowSize),
455 MakeUintegerChecker<uint8_t>(2, 10))
456 .AddAttribute("ConnEstFailCount",
457 "How many time T300 timer can expire on the same cell",
458 UintegerValue(1),
459 MakeUintegerAccessor(&NrGnbMac::SetConnEstFailCount),
460 MakeUintegerChecker<uint8_t>(1, 4));
461 return tid;
462}
463
464NrGnbMac::NrGnbMac()
465 : Object()
466{
467 NS_LOG_FUNCTION(this);
468 m_cmacSapProvider = new NrGnbMacMemberGnbCmacSapProvider(this);
469 m_macSapProvider = new GnbMacMemberNrMacSapProvider<NrGnbMac>(this);
470 m_phySapUser = new NrMacGnbMemberPhySapUser(this);
471 m_macSchedSapUser = new NrMacMemberMacSchedSapUser(this);
472 m_macCschedSapUser = new NrMacMemberMacCschedSapUser(this);
473 m_ccmMacSapProvider = new MemberNrCcmMacSapProvider<NrGnbMac>(this);
474}
475
479
480void
482{
483 m_dlCqiReceived.clear();
484 m_ulCqiReceived.clear();
485 m_ulCeReceived.clear();
486 m_miDlHarqProcessesPackets.clear();
487 delete m_macSapProvider;
488 delete m_cmacSapProvider;
489 delete m_macSchedSapUser;
490 delete m_macCschedSapUser;
491 delete m_phySapUser;
492 delete m_ccmMacSapProvider;
493}
494
495void
496NrGnbMac::SetNumberOfRaPreambles(uint8_t numberOfRaPreambles)
497{
498 m_numberOfRaPreambles = numberOfRaPreambles;
499}
500
501void
502NrGnbMac::SetPreambleTransMax(uint8_t preambleTransMax)
503{
504 m_preambleTransMax = preambleTransMax;
505}
506
507void
508NrGnbMac::SetRaResponseWindowSize(uint8_t raResponseWindowSize)
509{
510 m_raResponseWindowSize = raResponseWindowSize;
511}
512
513void
514NrGnbMac::SetConnEstFailCount(uint8_t connEstFailCount)
515{
516 m_connEstFailCount = connEstFailCount;
517}
518
519void
521{
522 NS_ABORT_MSG_IF(m_numRbPerRbg != -1, "This attribute can not be reconfigured");
523 m_numRbPerRbg = rbgSize;
524}
525
526uint32_t
528{
529 return m_numRbPerRbg;
530}
531
532void
533NrGnbMac::SetNumHarqProcess(uint8_t numHarqProcess)
534{
535 m_numHarqProcess = numHarqProcess;
536}
537
541uint8_t
543{
544 return m_numHarqProcess;
545}
546
547uint8_t
549{
550 return m_macSchedSapProvider->GetDlCtrlSyms();
551}
552
553uint8_t
555{
556 return m_macSchedSapProvider->GetUlCtrlSyms();
557}
558
559bool
560NrGnbMac::IsHarqReTxEnable() const
561{
562 return m_macSchedSapProvider->IsHarqReTxEnable();
563}
564
565void
566NrGnbMac::ReceiveRachPreamble(uint32_t raId)
567{
568 Ptr<NrRachPreambleMessage> rachMsg = Create<NrRachPreambleMessage>();
569 rachMsg->SetSourceBwp(GetBwpId());
570 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), raId, GetBwpId(), rachMsg);
571
572 ++m_receivedRachPreambleCount[raId];
573}
574
575NrMacSapProvider*
576NrGnbMac::GetMacSapProvider()
577{
578 return m_macSapProvider;
579}
580
581NrGnbCmacSapProvider*
582NrGnbMac::GetGnbCmacSapProvider()
583{
584 return m_cmacSapProvider;
585}
586
587void
588NrGnbMac::SetGnbCmacSapUser(NrGnbCmacSapUser* s)
589{
590 m_cmacSapUser = s;
591}
592
593void
595{
596 m_ccmMacSapUser = s;
597}
598
601{
602 NS_LOG_FUNCTION(this);
603 return m_ccmMacSapProvider;
604}
605
606void
608{
609 NS_LOG_FUNCTION(this);
610 m_currentSlot = sfnSf;
611}
612
613void
615{
616 NS_LOG_FUNCTION(this);
617 NS_LOG_LOGIC("Perform things on DL, slot on the air: " << sfnSf);
618
619 // --- DOWNLINK ---
620 // Send Dl-CQI info to the scheduler if(m_dlCqiReceived.size () > 0)
621 {
623 dlCqiInfoReq.m_sfnsf = sfnSf;
624
625 dlCqiInfoReq.m_cqiList.insert(dlCqiInfoReq.m_cqiList.begin(),
626 m_dlCqiReceived.begin(),
627 m_dlCqiReceived.end());
628 m_dlCqiReceived.erase(m_dlCqiReceived.begin(), m_dlCqiReceived.end());
629
630 m_macSchedSapProvider->SchedDlCqiInfoReq(dlCqiInfoReq);
631
632 for (const auto& v : dlCqiInfoReq.m_cqiList)
633 {
634 Ptr<NrDlCqiMessage> msg = Create<NrDlCqiMessage>();
635 msg->SetDlCqi(v);
636 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v.m_rnti, GetBwpId(), msg);
637 }
638 }
639
641
642 dlParams.m_slotType = type;
643 dlParams.m_snfSf = sfnSf;
644
645 // Forward DL HARQ feedbacks collected during last subframe TTI
646 if (!m_dlHarqInfoReceived.empty())
647 {
648 dlParams.m_dlHarqInfoList = m_dlHarqInfoReceived;
649 // empty local buffer
650 m_dlHarqInfoReceived.clear();
651
652 for (const auto& v : dlParams.m_dlHarqInfoList)
653 {
654 Ptr<NrDlHarqFeedbackMessage> msg = Create<NrDlHarqFeedbackMessage>();
655 msg->SetDlHarqFeedback(v);
656 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v.m_rnti, GetBwpId(), msg);
657 }
658 }
659
660 {
661 for (const auto& ue : m_rlcAttached)
662 {
664 params.m_rnti = ue.first;
665 params.m_beamId = m_phySapProvider->GetBeamId(ue.first);
666 params.m_transmissionMode = 0; // set to default value (SISO) for avoiding random
667 // initialization (valgrind error)
668 m_macCschedSapProvider->CschedUeConfigReq(params);
669 }
670 }
671
672 m_macSchedSapProvider->SchedDlTriggerReq(dlParams);
673}
674
675void
676NrGnbMac::ProcessRaPreambles(const SfnSf& sfnSf)
677{
678 NS_LOG_FUNCTION(this);
679
680 // process received RACH preambles and notify the scheduler
682
683 for (auto it = m_receivedRachPreambleCount.begin(); it != m_receivedRachPreambleCount.end();
684 ++it)
685 {
686 NS_LOG_INFO(this << " preambleId " << static_cast<uint32_t>(it->first) << ": " << it->second
687 << " received");
688 NS_ASSERT(it->second != 0);
689 if (it->second > 1)
690 {
691 NS_LOG_INFO("preambleId " << static_cast<uint32_t>(it->first) << ": collision"
692 << " at: " << Simulator::Now().As(Time::MS));
693 // in case of collision we assume that no preamble is
694 // successfully received, hence no RAR is sent
695 }
696 else
697 {
698 uint16_t rnti;
699 std::map<uint8_t, NcRaPreambleInfo>::iterator jt =
700 m_allocatedNcRaPreambleMap.find(it->first);
701 if (jt != m_allocatedNcRaPreambleMap.end())
702 {
703 rnti = jt->second.rnti;
704 NS_LOG_INFO("preambleId previously allocated for NC based RA, RNTI ="
705 << static_cast<uint32_t>(rnti) << ", sending RAR"
706 << " at: " << Simulator::Now().As(Time::MS));
707 }
708 else
709 {
710 rnti = m_cmacSapUser->AllocateTemporaryCellRnti();
711 NS_LOG_INFO("preambleId " << static_cast<uint32_t>(it->first)
712 << ": allocated T-C-RNTI " << static_cast<uint32_t>(rnti)
713 << ", sending RAR "
714 << " at: " << Simulator::Now().As(Time::MS));
715 }
716
717 NS_LOG_INFO("Informing MAC scheduler of the RACH preamble for "
718 << static_cast<uint16_t>(it->first) << " in slot " << sfnSf);
719 nr::RachListElement_s rachLe;
720 rachLe.m_rnti = rnti;
721 rachLe.m_estimatedSize = 144; // to be confirmed
722 rachInfoReqParams.m_rachList.push_back(rachLe);
723 m_rapIdRntiMap.insert(std::pair<uint16_t, uint32_t>(rnti, it->first));
724 }
725 }
726
727 m_receivedRachPreambleCount.clear();
728 m_macSchedSapProvider->SchedDlRachInfoReq(rachInfoReqParams);
729}
730
731void
733{
734 NS_LOG_FUNCTION(this);
735 NS_LOG_LOGIC("Perform things on UL, slot on the air: " << sfnSf);
736
737 if (!m_receivedRachPreambleCount.empty())
738 {
739 ProcessRaPreambles(sfnSf);
740 }
741
742 // --- UPLINK ---
743 // Send UL-CQI info to the scheduler
744 for (auto& i : m_ulCqiReceived)
745 {
746 // m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & frameNum) << 16) | ((0xFF & subframeNum) << 8)
747 // | (0xFF & varTtiNum);
748 m_macSchedSapProvider->SchedUlCqiInfoReq(i);
749 }
750 m_ulCqiReceived.clear();
751
752 // Send SR info to the scheduler
753 {
755 params.m_snfSf = m_currentSlot;
756 params.m_srList.insert(params.m_srList.begin(), m_srRntiList.begin(), m_srRntiList.end());
757 m_srRntiList.clear();
758
759 m_macSchedSapProvider->SchedUlSrInfoReq(params);
760
761 for (const auto& v : params.m_srList)
762 {
763 Ptr<NrSRMessage> msg = Create<NrSRMessage>();
764 msg->SetRNTI(v);
765 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v, GetBwpId(), msg);
766 }
767 }
768
769 // Send UL BSR reports to the scheduler
770 if (!m_ulCeReceived.empty())
771 {
773 ulMacReq.m_sfnSf = sfnSf;
774 ulMacReq.m_macCeList.insert(ulMacReq.m_macCeList.begin(),
775 m_ulCeReceived.begin(),
776 m_ulCeReceived.end());
777 m_ulCeReceived.erase(m_ulCeReceived.begin(), m_ulCeReceived.end());
778 m_macSchedSapProvider->SchedUlMacCtrlInfoReq(ulMacReq);
779
780 for (const auto& v : ulMacReq.m_macCeList)
781 {
782 Ptr<NrBsrMessage> msg = Create<NrBsrMessage>();
783 msg->SetBsr(v);
784 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v.m_rnti, GetBwpId(), msg);
785 }
786 }
787
789
790 ulParams.m_snfSf = sfnSf;
791 ulParams.m_slotType = type;
792
793 // Forward UL HARQ feebacks collected during last TTI
794 if (!m_ulHarqInfoReceived.empty())
795 {
796 ulParams.m_ulHarqInfoList = m_ulHarqInfoReceived;
797 // empty local buffer
798 m_ulHarqInfoReceived.clear();
799 }
800
801 m_macSchedSapProvider->SchedUlTriggerReq(ulParams);
802}
803
804void
805NrGnbMac::SetForwardUpCallback(Callback<void, Ptr<Packet>> cb)
806{
807 m_forwardUpCallback = cb;
808}
809
810void
811NrGnbMac::ReceiveBsrMessage(MacCeElement bsr)
812{
813 NS_LOG_FUNCTION(this);
814 // in order to use existing SAP interfaces we need to convert MacCeElement to
815 // nr::MacCeListElement_s
816
817 nr::MacCeListElement_s mcle;
818 mcle.m_rnti = bsr.m_rnti;
819 mcle.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
820 mcle.m_macCeValue.m_crnti = bsr.m_macCeValue.m_crnti;
821 mcle.m_macCeValue.m_phr = bsr.m_macCeValue.m_phr;
822 mcle.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
823
824 if (bsr.m_macCeType == MacCeElement::BSR)
825 {
826 mcle.m_macCeType = nr::MacCeListElement_s::BSR;
827 }
828 else if (bsr.m_macCeType == MacCeElement::CRNTI)
829 {
830 mcle.m_macCeType = nr::MacCeListElement_s::CRNTI;
831 }
832 else if (bsr.m_macCeType == MacCeElement::PHR)
833 {
834 mcle.m_macCeType = nr::MacCeListElement_s::PHR;
835 }
836
837 m_ccmMacSapUser->UlReceiveMacCe(mcle, GetBwpId());
838}
839
840void
841NrGnbMac::DoReportMacCeToScheduler(nr::MacCeListElement_s bsr)
842{
843 NS_LOG_FUNCTION(this);
844 NS_LOG_DEBUG(this << " bsr Size " << (uint16_t)m_ulCeReceived.size());
845 uint32_t size = 0;
846
847 // send to NrCcmMacSapUser
848 // convert nr::MacCeListElement_s to MacCeElement
849
850 MacCeElement mce;
851 mce.m_rnti = bsr.m_rnti;
852 mce.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
853 mce.m_macCeValue.m_crnti = bsr.m_macCeValue.m_crnti;
854 mce.m_macCeValue.m_phr = bsr.m_macCeValue.m_phr;
855 mce.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
856
857 if (bsr.m_macCeType == nr::MacCeListElement_s::BSR)
858 {
859 mce.m_macCeType = MacCeElement::BSR;
860 }
861 else if (bsr.m_macCeType == nr::MacCeListElement_s::CRNTI)
862 {
863 mce.m_macCeType = MacCeElement::CRNTI;
864 }
865 else if (bsr.m_macCeType == nr::MacCeListElement_s::PHR)
866 {
867 mce.m_macCeType = MacCeElement::PHR;
868 }
869
870 for (const auto& v : bsr.m_macCeValue.m_bufferStatus)
871 {
872 size += v;
873 }
874
875 m_ulCeReceived.push_back(
876 mce); // this to called when NrUlCcmSapProvider::ReportMacCeToScheduler is called
877 NS_LOG_DEBUG(" Reported by UE " << static_cast<uint32_t>(bsr.m_macCeValue.m_crnti) << " size "
878 << size << " bsr vector ize after push_back "
879 << static_cast<uint32_t>(m_ulCeReceived.size()));
880}
881
882void
883NrGnbMac::DoReportSrToScheduler(uint16_t rnti)
884{
885 NS_LOG_FUNCTION(this);
886 m_srRntiList.push_back(rnti);
887 m_srCallback(GetBwpId(), rnti);
888}
889
890void
891NrGnbMac::DoReceivePhyPdu(Ptr<Packet> p)
892{
893 NS_LOG_FUNCTION(this);
894
895 NrRadioBearerTag tag;
896 p->RemovePacketTag(tag);
897
898 uint16_t rnti = tag.GetRnti();
899 auto rntiIt = m_rlcAttached.find(rnti);
900
901 NS_ASSERT_MSG(rntiIt != m_rlcAttached.end(), "could not find RNTI" << rnti);
902
903 // Try to peek whatever header; in the first byte there will be the LC ID.
904 NrMacHeaderFsUl header;
905 p->PeekHeader(header);
906
907 // Based on LC ID, we know if it is a CE or simply data.
908 if (header.GetLcId() == NrMacHeaderFsUl::SHORT_BSR)
909 {
910 NrMacShortBsrCe bsrHeader;
911 p->RemoveHeader(bsrHeader); // Really remove the header this time
912
913 // Convert our custom header into the structure that the scheduler expects:
914 MacCeElement bsr;
915
916 bsr.m_macCeType = MacCeElement::BSR;
917 bsr.m_rnti = rnti;
918 bsr.m_macCeValue.m_bufferStatus.resize(4);
919 bsr.m_macCeValue.m_bufferStatus[0] = bsrHeader.m_bufferSizeLevel_0;
920 bsr.m_macCeValue.m_bufferStatus[1] = bsrHeader.m_bufferSizeLevel_1;
921 bsr.m_macCeValue.m_bufferStatus[2] = bsrHeader.m_bufferSizeLevel_2;
922 bsr.m_macCeValue.m_bufferStatus[3] = bsrHeader.m_bufferSizeLevel_3;
923
924 ReceiveBsrMessage(bsr); // Here it will be converted again, but our job is done.
925 return;
926 }
927
928 // Ok, we know it is data, so let's extract and pass to RLC.
929
930 NrMacHeaderVs macHeader;
931 p->RemoveHeader(macHeader);
932
933 auto lcidIt = rntiIt->second.find(macHeader.GetLcId());
934 if (lcidIt == rntiIt->second.end())
935 {
936 NS_LOG_DEBUG("Discarding PDU addressed to non-existent LCID " << macHeader.GetLcId());
937 return;
938 }
939
940 NrMacSapUser::ReceivePduParameters rxParams;
941 rxParams.p = p;
942 rxParams.lcid = macHeader.GetLcId();
943 rxParams.rnti = rnti;
944
945 if (rxParams.p->GetSize())
946 {
947 (*lcidIt).second->ReceivePdu(rxParams);
948 }
949}
950
951NrGnbPhySapUser*
952NrGnbMac::GetPhySapUser()
953{
954 return m_phySapUser;
955}
956
957void
958NrGnbMac::SetPhySapProvider(NrPhySapProvider* ptr)
959{
960 m_phySapProvider = ptr;
961}
962
963NrMacSchedSapUser*
964NrGnbMac::GetNrMacSchedSapUser()
965{
966 return m_macSchedSapUser;
967}
968
969void
970NrGnbMac::SetNrMacSchedSapProvider(NrMacSchedSapProvider* ptr)
971{
972 m_macSchedSapProvider = ptr;
973}
974
975NrMacCschedSapUser*
976NrGnbMac::GetNrMacCschedSapUser()
977{
978 return m_macCschedSapUser;
979}
980
981void
982NrGnbMac::SetNrMacCschedSapProvider(NrMacCschedSapProvider* ptr)
983{
984 m_macCschedSapProvider = ptr;
985}
986
987void
988NrGnbMac::DoUlCqiReport(NrMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
989{
990 if (ulcqi.m_ulCqi.m_type == UlCqiInfo::PUSCH)
991 {
992 NS_LOG_DEBUG(this << " gNB rxed an PUSCH UL-CQI");
993 }
994 else if (ulcqi.m_ulCqi.m_type == UlCqiInfo::SRS)
995 {
996 NS_LOG_DEBUG(this << " gNB rxed an SRS UL-CQI");
997 }
998 NS_LOG_INFO("*** UL CQI report SINR "
999 << nr::FfConverter::fpS11dot3toDouble(ulcqi.m_ulCqi.m_sinr[0])
1000 << " slot: " << m_currentSlot);
1001
1002 // NS_ASSERT (ulcqi.m_sfnSf.m_varTtiNum != 0); Now UL data can be the first TTI..
1003 m_ulCqiReceived.push_back(ulcqi);
1004}
1005
1006void
1007NrGnbMac::DoReceiveControlMessage(Ptr<NrControlMessage> msg)
1008{
1009 NS_LOG_FUNCTION(this << msg);
1010
1011 switch (msg->GetMessageType())
1012 {
1013 case (NrControlMessage::SR): {
1014 // Report it to the CCM. Then he will call the right MAC
1015 Ptr<NrSRMessage> sr = DynamicCast<NrSRMessage>(msg);
1016 m_ccmMacSapUser->UlReceiveSr(sr->GetRNTI(), GetBwpId());
1017 break;
1018 }
1019 case (NrControlMessage::DL_CQI): {
1020 Ptr<NrDlCqiMessage> cqi = DynamicCast<NrDlCqiMessage>(msg);
1021 DlCqiInfo cqiElement = cqi->GetDlCqi();
1022 NS_ASSERT(cqiElement.m_rnti != 0);
1023 m_dlCqiReceived.push_back(cqiElement);
1024 break;
1025 }
1027 Ptr<NrDlHarqFeedbackMessage> dlharq = DynamicCast<NrDlHarqFeedbackMessage>(msg);
1028 DoDlHarqFeedback(dlharq->GetDlHarqFeedback());
1029 break;
1030 }
1031 default:
1032 NS_LOG_WARN("Control message not supported/expected");
1033 }
1034}
1035
1036void
1037NrGnbMac::DoUlHarqFeedback(const UlHarqInfo& params)
1038{
1039 NS_LOG_FUNCTION(this);
1040 m_ulHarqInfoReceived.push_back(params);
1041}
1042
1043void
1044NrGnbMac::DoDlHarqFeedback(const DlHarqInfo& params)
1045{
1046 NS_LOG_FUNCTION(this);
1047 // Update HARQ buffer
1048 std::unordered_map<uint16_t, NrDlHarqProcessesBuffer_t>::iterator it =
1049 m_miDlHarqProcessesPackets.find(params.m_rnti);
1050 NS_ASSERT(it != m_miDlHarqProcessesPackets.end());
1051
1052 if (params.m_harqStatus == DlHarqInfo::ACK)
1053 {
1054 // discard buffer
1055 Ptr<PacketBurst> emptyBuf = CreateObject<PacketBurst>();
1056 (*it).second.at(params.m_harqProcessId).m_pktBurst = emptyBuf;
1057 NS_LOG_DEBUG(this << " HARQ-ACK UE RNTI" << params.m_rnti << " HARQ Process ID "
1058 << (uint16_t)params.m_harqProcessId);
1059 }
1060 else if (params.m_harqStatus == DlHarqInfo::NACK)
1061 {
1062 NS_LOG_DEBUG(this << " HARQ-NACK UE RNTI" << params.m_rnti << " HARQ Process ID "
1063 << (uint16_t)params.m_harqProcessId);
1064 }
1065 else
1066 {
1067 NS_FATAL_ERROR(" HARQ functionality not implemented");
1068 }
1069
1070 /* trace for HARQ feedback*/
1071 m_dlHarqFeedback(params);
1072
1073 m_dlHarqInfoReceived.push_back(params);
1074}
1075
1076void
1077NrGnbMac::DoTransmitBufferStatusReport(NrMacSapProvider::BufferStatusReportParameters params)
1078{
1079 NS_LOG_FUNCTION(this);
1080 NrMacSchedSapProvider::SchedDlRlcBufferReqParameters schedParams;
1081 schedParams.m_logicalChannelIdentity = params.lcid;
1082 schedParams.m_rlcRetransmissionHolDelay = params.retxQueueHolDelay;
1083 schedParams.m_rlcRetransmissionQueueSize = params.retxQueueSize;
1084 schedParams.m_rlcStatusPduSize = params.statusPduSize;
1085 schedParams.m_rlcTransmissionQueueHolDelay = params.txQueueHolDelay;
1086 schedParams.m_rlcTransmissionQueueSize = params.txQueueSize;
1087 schedParams.m_rnti = params.rnti;
1088
1089 NS_LOG_INFO("Reporting RLC buffer status update to MAC Scheduler for RNTI="
1090 << params.rnti << ", LCID=" << (uint32_t)params.lcid << ", Transmission Queue Size="
1091 << params.txQueueSize << ", Transmission Queue HOL Delay=" << params.txQueueHolDelay
1092 << ", Retransmission Queue Size=" << params.retxQueueSize
1093 << ", Retransmission Queue HOL delay=" << params.retxQueueHolDelay
1094 << ", PDU Size=" << params.statusPduSize);
1095
1096 m_macSchedSapProvider->SchedDlRlcBufferReq(schedParams);
1097}
1098
1099// forwarded from NrMacSapProvider
1100void
1101NrGnbMac::DoTransmitPdu(NrMacSapProvider::TransmitPduParameters params)
1102{
1103 // TB UID passed back along with RLC data as HARQ process ID
1104 uint32_t tbMapKey = ((params.rnti & 0xFFFF) << 8) | (params.harqProcessId & 0xFF);
1105 auto harqIt = m_miDlHarqProcessesPackets.find(params.rnti);
1106 auto it = m_macPduMap.find(tbMapKey);
1107
1108 if (it == m_macPduMap.end())
1109 {
1110 NS_FATAL_ERROR("No MAC PDU storage element found for this TB UID/RNTI");
1111 }
1112
1113 NrMacHeaderVs header;
1114 header.SetLcId(params.lcid);
1115 header.SetSize(params.pdu->GetSize());
1116
1117 params.pdu->AddHeader(header);
1118
1119 NrRadioBearerTag bearerTag(params.rnti, params.lcid, 0);
1120 params.pdu->AddPacketTag(bearerTag);
1121
1122 harqIt->second.at(params.harqProcessId).m_pktBurst->AddPacket(params.pdu);
1123
1124 it->second.m_used += params.pdu->GetSize();
1125 NS_ASSERT_MSG(it->second.m_dci->m_tbSize >= it->second.m_used,
1126 "DCI OF " << it->second.m_dci->m_tbSize << " total used " << it->second.m_used);
1127
1128 NS_LOG_INFO("Sending MAC PDU to PHY Layer");
1129 m_phySapProvider->SendMacPdu(params.pdu,
1130 it->second.m_sfnSf,
1131 it->second.m_dci->m_symStart,
1132 params.rnti);
1133}
1134
1135void
1136NrGnbMac::DoBuildRarList(SlotAllocInfo& slotAllocInfo)
1137{
1138 NS_LOG_FUNCTION(this);
1139
1140 if (!HasMsg3Allocations(slotAllocInfo))
1141 {
1142 return;
1143 }
1144
1145 for (const auto& varTti : slotAllocInfo.m_varTtiAllocInfo)
1146 {
1147 if (varTti.m_dci->m_type == DciInfoElementTdma::MSG3)
1148 {
1149 NrBuildRarListElement_s rarElement;
1150 rarElement.ulMsg3Dci = varTti.m_dci;
1151 // set RA preamble ID
1152 auto itRaPreambleId = m_rapIdRntiMap.find(rarElement.ulMsg3Dci->m_rnti);
1153 NS_ABORT_IF(itRaPreambleId == m_rapIdRntiMap.end());
1154 NS_LOG_INFO("In slot " << m_currentSlot
1155 << " gNB MAC pass to PHY the RAR message for RNTI "
1156 << rarElement.ulMsg3Dci->m_rnti << " RA preamble ID "
1157 << itRaPreambleId->second << " at:" << Simulator::Now());
1158 rarElement.raPreambleId = itRaPreambleId->second;
1159 // K2 will be set by phy
1160 slotAllocInfo.m_buildRarList.push_back(rarElement);
1161 }
1162 }
1163
1164 if (!slotAllocInfo.m_buildRarList.empty())
1165 {
1166 m_rapIdRntiMap.clear(); // reset RA preamble to RNTI MAP
1167 NS_LOG_DEBUG("Sending RAR message to UE.");
1168 }
1169 else
1170 {
1171 NS_LOG_DEBUG("No RAR messages to be sent.");
1172 }
1173}
1174
1175bool
1176NrGnbMac::HasMsg3Allocations(const SlotAllocInfo& slotInfo)
1177{
1178 for (const auto& varTti : slotInfo.m_varTtiAllocInfo)
1179 {
1180 if (varTti.m_dci->m_type == DciInfoElementTdma::MSG3)
1181 {
1182 return true;
1183 }
1184 }
1185 return false;
1186}
1187
1188void
1189NrGnbMac::DoSchedConfigIndication(NrMacSchedSapUser::SchedConfigIndParameters ind)
1190{
1191 NS_ASSERT(ind.m_sfnSf.GetNumerology() == m_currentSlot.GetNumerology());
1192 std::stable_sort(ind.m_slotAllocInfo.m_varTtiAllocInfo.begin(),
1193 ind.m_slotAllocInfo.m_varTtiAllocInfo.end());
1194
1195 if (ind.m_slotAllocInfo.ContainsDataAllocation())
1196 {
1197 NS_LOG_INFO("New scheduled allocation: " << ind.m_slotAllocInfo);
1198 }
1199 m_phySapProvider->SetSlotAllocInfo(ind.m_slotAllocInfo);
1200
1201 for (auto& varTtiAllocInfo : ind.m_slotAllocInfo.m_varTtiAllocInfo)
1202 {
1203 if (varTtiAllocInfo.m_dci->m_type != DciInfoElementTdma::CTRL &&
1204 varTtiAllocInfo.m_dci->m_format == DciInfoElementTdma::DL)
1205 {
1206 uint16_t rnti = varTtiAllocInfo.m_dci->m_rnti;
1207 auto rntiIt = m_rlcAttached.find(rnti);
1208 NS_ABORT_MSG_IF(rntiIt == m_rlcAttached.end(),
1209 "Scheduled UE " << rnti << " not attached");
1210
1211 // Call RLC entities to generate RLC PDUs
1212 auto dciElem = varTtiAllocInfo.m_dci;
1213 uint8_t harqId = dciElem->m_harqProcess;
1214
1215 if (ind.m_slotAllocInfo.ContainsDataAllocation())
1216 {
1217 NS_LOG_INFO("New scheduled data TX in DL for HARQ Process ID: "
1218 << (uint32_t)harqId << ", Var. TTI from symbol "
1219 << (uint32_t)varTtiAllocInfo.m_dci->m_symStart << " to "
1220 << (uint32_t)varTtiAllocInfo.m_dci->m_symStart +
1221 (uint32_t)varTtiAllocInfo.m_dci->m_numSym
1222 << ". "
1223 << " TB of size " << varTtiAllocInfo.m_dci->m_tbSize << " with MCS "
1224 << varTtiAllocInfo.m_dci->m_mcs);
1225 }
1226
1227 // update Harq Processes
1228 if (dciElem->m_ndi == 1)
1229 {
1230 NS_ASSERT(dciElem->m_format == DciInfoElementTdma::DL);
1231 std::vector<RlcPduInfo>& rlcPduInfo = varTtiAllocInfo.m_rlcPduInfo;
1232 NS_ASSERT(!rlcPduInfo.empty());
1233 NrMacPduInfo macPduInfo(ind.m_sfnSf, dciElem);
1234 // insert into MAC PDU map
1235 uint32_t tbMapKey = ((rnti & 0xFFFF) << 8) | (harqId & 0xFF);
1236 std::pair<std::unordered_map<uint32_t, struct NrMacPduInfo>::iterator, bool>
1237 mapRet = m_macPduMap.insert(
1238 std::pair<uint32_t, struct NrMacPduInfo>(tbMapKey, macPduInfo));
1239 if (!mapRet.second)
1240 {
1241 NS_FATAL_ERROR("MAC PDU map element exists");
1242 }
1243
1244 // new data -> force emptying correspondent harq pkt buffer
1245 std::unordered_map<uint16_t, NrDlHarqProcessesBuffer_t>::iterator harqIt =
1246 m_miDlHarqProcessesPackets.find(rnti);
1247 NS_ASSERT(harqIt != m_miDlHarqProcessesPackets.end());
1248 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
1249 harqIt->second.at(harqId).m_pktBurst = pb;
1250 harqIt->second.at(harqId).m_lcidList.clear();
1251
1252 std::unordered_map<uint32_t, struct NrMacPduInfo>::iterator pduMapIt = mapRet.first;
1253 // for each LC j
1254 for (auto& j : rlcPduInfo)
1255 {
1256 NS_ASSERT_MSG(rntiIt != m_rlcAttached.end(), "could not find RNTI" << rnti);
1257 std::unordered_map<uint8_t, NrMacSapUser*>::iterator lcidIt =
1258 rntiIt->second.find(j.m_lcid);
1259 NS_ASSERT_MSG(lcidIt != rntiIt->second.end(),
1260 "could not find LCID" << std::to_string(j.m_lcid));
1261 NS_LOG_INFO("Notifying RLC of TX opportunity for HARQ Process ID "
1262 << (unsigned int)harqId << " LC ID " << std::to_string(+j.m_lcid)
1263 << (unsigned int)j.m_size);
1264
1265 (*lcidIt).second->NotifyTxOpportunity(
1266 NrMacSapUser::TxOpportunityParameters((j.m_size),
1267 0,
1268 harqId,
1269 GetBwpId(),
1270 rnti,
1271 j.m_lcid));
1272 harqIt->second.at(harqId).m_lcidList.push_back(j.m_lcid);
1273 }
1274
1275 m_macPduMap.erase(pduMapIt); // delete map entry
1276
1277 NrSchedulingCallbackInfo traceInfo;
1278 traceInfo.m_frameNum = ind.m_sfnSf.GetFrame();
1279 traceInfo.m_subframeNum = ind.m_sfnSf.GetSubframe();
1280 traceInfo.m_slotNum = ind.m_sfnSf.GetSlot();
1281 traceInfo.m_symStart = dciElem->m_symStart;
1282 traceInfo.m_numSym = dciElem->m_numSym;
1283 traceInfo.m_tbSize = dciElem->m_tbSize;
1284 traceInfo.m_mcs = dciElem->m_mcs;
1285 traceInfo.m_rnti = dciElem->m_rnti;
1286 traceInfo.m_bwpId = GetBwpId();
1287 traceInfo.m_ndi = dciElem->m_ndi;
1288 traceInfo.m_rv = dciElem->m_rv;
1289 traceInfo.m_harqId = dciElem->m_harqProcess;
1290 m_dlScheduling(traceInfo);
1291 }
1292 else
1293 {
1294 NS_LOG_INFO("DL retransmission");
1295 if (dciElem->m_tbSize > 0)
1296 {
1297 std::unordered_map<uint16_t, NrDlHarqProcessesBuffer_t>::iterator it =
1298 m_miDlHarqProcessesPackets.find(rnti);
1299 NS_ASSERT(it != m_miDlHarqProcessesPackets.end());
1300 Ptr<PacketBurst> pb = it->second.at(harqId).m_pktBurst;
1301 for (std::list<Ptr<Packet>>::const_iterator j = pb->Begin(); j != pb->End();
1302 ++j)
1303 {
1304 Ptr<Packet> pkt = (*j)->Copy();
1305 m_phySapProvider->SendMacPdu(pkt,
1306 ind.m_sfnSf,
1307 dciElem->m_symStart,
1308 dciElem->m_rnti);
1309 }
1310 }
1311 }
1312 }
1313 else if (varTtiAllocInfo.m_dci->m_type != DciInfoElementTdma::CTRL &&
1314 varTtiAllocInfo.m_dci->m_type != DciInfoElementTdma::SRS &&
1315 varTtiAllocInfo.m_dci->m_format == DciInfoElementTdma::UL)
1316 {
1317 // UL scheduling info trace
1318 // Call RLC entities to generate RLC PDUs
1319 auto dciElem = varTtiAllocInfo.m_dci;
1320 NrSchedulingCallbackInfo traceInfo;
1321 traceInfo.m_frameNum = ind.m_sfnSf.GetFrame();
1322 traceInfo.m_subframeNum = ind.m_sfnSf.GetSubframe();
1323 traceInfo.m_slotNum = ind.m_sfnSf.GetSlot();
1324 traceInfo.m_symStart = dciElem->m_symStart;
1325 traceInfo.m_numSym = dciElem->m_numSym;
1326 traceInfo.m_tbSize = dciElem->m_tbSize;
1327 traceInfo.m_mcs = dciElem->m_mcs;
1328 traceInfo.m_rnti = dciElem->m_rnti;
1329 traceInfo.m_bwpId = GetBwpId();
1330 traceInfo.m_ndi = dciElem->m_ndi;
1331 traceInfo.m_rv = dciElem->m_rv;
1332 traceInfo.m_harqId = dciElem->m_harqProcess;
1333 m_ulScheduling(traceInfo);
1334 }
1335 }
1336}
1337
1338// ////////////////////////////////////////////
1339// CMAC SAP
1340// ////////////////////////////////////////////
1341
1342void
1343NrGnbMac::DoConfigureMac(uint16_t ulBandwidth, uint16_t dlBandwidth)
1344{
1345 NS_LOG_FUNCTION(this);
1346
1347 // The bandwidth arrived in Hz. We need to know it in number of RB, and then
1348 // consider how many RB are inside a single RBG.
1349 uint16_t bw_in_rbg = m_phySapProvider->GetRbNum() / GetNumRbPerRbg();
1350 m_bandwidthInRbg = bw_in_rbg;
1351
1352 NS_LOG_DEBUG("Mac configured. Attributes:"
1353 << std::endl
1354 << "\t NumRbPerRbg: " << m_numRbPerRbg << std::endl
1355 << "\t HarqEnable: " << m_macSchedSapProvider->IsHarqReTxEnable() << std::endl
1356 << "\t NumHarqProcess: " << +m_numHarqProcess << std::endl
1357 << "Physical properties: " << std::endl
1358 << "\t Bandwidth provided: " << ulBandwidth * 1000 * 100 << " Hz" << std::endl
1359 << "\t that corresponds to " << bw_in_rbg << " RBG, as we have "
1360 << m_phySapProvider->GetRbNum() << " RB and " << GetNumRbPerRbg()
1361 << " RB per RBG");
1362
1363 NrMacCschedSapProvider::CschedCellConfigReqParameters params;
1364
1365 params.m_ulBandwidth = m_bandwidthInRbg;
1366 params.m_dlBandwidth = m_bandwidthInRbg;
1367
1368 m_macCschedSapProvider->CschedCellConfigReq(params);
1369}
1370
1371void
1373{
1375 params.m_rnti = rnti;
1376 params.m_beamId = beamId;
1377 params.m_transmissionMode =
1378 0; // set to default value (SISO) for avoiding random initialization (valgrind error)
1379 m_macCschedSapProvider->CschedUeConfigReq(params);
1380}
1381
1382uint16_t
1384{
1385 if (m_phySapProvider)
1386 {
1387 return m_phySapProvider->GetBwpId();
1388 }
1389 else
1390 {
1391 return UINT16_MAX;
1392 }
1393}
1394
1395uint16_t
1397{
1398 if (m_phySapProvider)
1399 {
1400 return m_phySapProvider->GetCellId();
1401 }
1402 else
1403 {
1404 return UINT16_MAX;
1405 }
1406}
1407
1408std::shared_ptr<DciInfoElementTdma>
1410{
1411 NS_LOG_FUNCTION(this);
1412
1413 auto bwInRbg = m_phySapProvider->GetRbNum() / GetNumRbPerRbg();
1414 NS_ASSERT(bwInRbg > 0);
1415 std::vector<bool> rbgBitmask(bwInRbg, true);
1416
1417 return std::make_shared<DciInfoElementTdma>(0,
1418 m_macSchedSapProvider->GetDlCtrlSyms(),
1421 rbgBitmask);
1422}
1423
1424std::shared_ptr<DciInfoElementTdma>
1426{
1427 NS_LOG_FUNCTION(this);
1428
1429 NS_ASSERT(m_bandwidthInRbg > 0);
1430 std::vector<bool> rbgBitmask(m_bandwidthInRbg, true);
1431
1432 return std::make_shared<DciInfoElementTdma>(0,
1433 m_macSchedSapProvider->GetUlCtrlSyms(),
1436 rbgBitmask);
1437}
1438
1439void
1440NrGnbMac::DoAddUe(uint16_t rnti)
1441{
1442 NS_LOG_FUNCTION(this << " rnti=" << rnti);
1443 std::unordered_map<uint8_t, NrMacSapUser*> empty;
1444 std::pair<std::unordered_map<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>::iterator,
1445 bool>
1446 ret = m_rlcAttached.insert(
1447 std::pair<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>(rnti, empty));
1448 NS_ASSERT_MSG(ret.second, "element already present, RNTI already existed");
1449
1451 params.m_rnti = rnti;
1452 params.m_beamId = m_phySapProvider->GetBeamId(rnti);
1453 params.m_transmissionMode =
1454 0; // set to default value (SISO) for avoiding random initialization (valgrind error)
1455 m_macCschedSapProvider->CschedUeConfigReq(params);
1456
1457 // Create DL transmission HARQ buffers
1458 NrDlHarqProcessesBuffer_t buf;
1459 uint16_t harqNum = GetNumHarqProcess();
1460 buf.resize(harqNum);
1461 for (uint16_t i = 0; i < harqNum; i++)
1462 {
1463 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
1464 buf.at(i).m_pktBurst = pb;
1465 }
1466 m_miDlHarqProcessesPackets.insert(std::pair<uint16_t, NrDlHarqProcessesBuffer_t>(rnti, buf));
1467}
1468
1469void
1470NrGnbMac::DoRemoveUe(uint16_t rnti)
1471{
1472 NS_LOG_FUNCTION(this << " rnti=" << rnti);
1473 NrMacCschedSapProvider::CschedUeReleaseReqParameters params;
1474 params.m_rnti = rnti;
1475 m_macCschedSapProvider->CschedUeReleaseReq(params);
1476 m_miDlHarqProcessesPackets.erase(rnti);
1477 m_rlcAttached.erase(rnti);
1478
1479 // remove unprocessed preamble received for RACH during handover
1480 auto jt = m_allocatedNcRaPreambleMap.begin();
1481 while (jt != m_allocatedNcRaPreambleMap.end())
1482 {
1483 if (jt->second.rnti == rnti)
1484 {
1485 auto it = m_receivedRachPreambleCount.find(jt->first);
1486 if (it != m_receivedRachPreambleCount.end())
1487 {
1488 m_receivedRachPreambleCount.erase(it->first);
1489 }
1490 jt = m_allocatedNcRaPreambleMap.erase(jt);
1491 }
1492 else
1493 {
1494 ++jt;
1495 }
1496 }
1497}
1498
1499void
1500NrGnbMac::DoAddLc(NrGnbCmacSapProvider::LcInfo lcinfo, NrMacSapUser* msu)
1501{
1502 NS_LOG_FUNCTION(this);
1503 NS_LOG_FUNCTION(this);
1504
1505 std::unordered_map<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>::iterator rntiIt =
1506 m_rlcAttached.find(lcinfo.rnti);
1507 NS_ASSERT_MSG(rntiIt != m_rlcAttached.end(), "RNTI not found");
1508 std::unordered_map<uint8_t, NrMacSapUser*>::iterator lcidIt = rntiIt->second.find(lcinfo.lcId);
1509 if (lcidIt == rntiIt->second.end())
1510 {
1511 rntiIt->second.insert(std::pair<uint8_t, NrMacSapUser*>(lcinfo.lcId, msu));
1512 }
1513 else
1514 {
1515 NS_LOG_ERROR("LC already exists");
1516 }
1517
1518 // CCCH (LCID 0) is pre-configured
1519 // see FF LTE MAC Scheduler
1520 // Interface Specification v1.11,
1521 // 4.3.4 logicalChannelConfigListElement
1522 if (lcinfo.lcId != 0)
1523 {
1524 struct NrMacCschedSapProvider::CschedLcConfigReqParameters params;
1525 params.m_rnti = lcinfo.rnti;
1526 params.m_reconfigureFlag = false;
1527
1528 struct nr::LogicalChannelConfigListElement_s lccle;
1529 lccle.m_logicalChannelIdentity = lcinfo.lcId;
1530 lccle.m_logicalChannelGroup = lcinfo.lcGroup;
1531 lccle.m_direction = nr::LogicalChannelConfigListElement_s::DIR_BOTH;
1532 lccle.m_qci = lcinfo.qci;
1533 lccle.m_eRabMaximulBitrateUl = lcinfo.mbrUl;
1534 lccle.m_eRabMaximulBitrateDl = lcinfo.mbrDl;
1535 lccle.m_eRabGuaranteedBitrateUl = lcinfo.gbrUl;
1536 lccle.m_eRabGuaranteedBitrateDl = lcinfo.gbrDl;
1537
1538 lccle.m_qosBearerType = static_cast<nr::LogicalChannelConfigListElement_s::QosBearerType_e>(
1539 lcinfo.resourceType);
1540
1541 params.m_logicalChannelConfigList.push_back(lccle);
1542
1543 m_macCschedSapProvider->CschedLcConfigReq(params);
1544 }
1545}
1546
1547void
1548NrGnbMac::DoReconfigureLc(NrGnbCmacSapProvider::LcInfo lcinfo)
1549{
1550 NS_FATAL_ERROR("not implemented");
1551}
1552
1553void
1554NrGnbMac::DoReleaseLc(uint16_t rnti, uint8_t lcid)
1555{
1556 // Find user based on rnti and then erase lcid stored against the same
1557 std::unordered_map<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>::iterator rntiIt =
1558 m_rlcAttached.find(rnti);
1559 rntiIt->second.erase(lcid);
1560
1561 struct NrMacCschedSapProvider::CschedLcReleaseReqParameters params;
1562 params.m_rnti = rnti;
1563 params.m_logicalChannelIdentity.push_back(lcid);
1564 m_macCschedSapProvider->CschedLcReleaseReq(params);
1565}
1566
1567void
1568NrGnbMac::UeUpdateConfigurationReq(NrGnbCmacSapProvider::UeConfig params)
1569{
1570 NS_LOG_FUNCTION(this);
1571 // propagates to scheduler
1572 NrMacCschedSapProvider::CschedUeConfigReqParameters req;
1573 req.m_rnti = params.m_rnti;
1574 req.m_transmissionMode = params.m_transmissionMode;
1575 req.m_beamId = m_phySapProvider->GetBeamId(params.m_rnti);
1576 req.m_reconfigureFlag = true;
1577 m_macCschedSapProvider->CschedUeConfigReq(req);
1578}
1579
1580NrGnbCmacSapProvider::RachConfig
1581NrGnbMac::DoGetRachConfig()
1582{
1583 NS_LOG_FUNCTION(this);
1584 struct NrGnbCmacSapProvider::RachConfig rc;
1585 rc.numberOfRaPreambles = m_numberOfRaPreambles;
1586 rc.preambleTransMax = m_preambleTransMax;
1587 rc.raResponseWindowSize = m_raResponseWindowSize;
1588 rc.connEstFailCount = m_connEstFailCount;
1589 return rc;
1590}
1591
1592NrGnbCmacSapProvider::AllocateNcRaPreambleReturnValue
1593NrGnbMac::DoAllocateNcRaPreamble(uint16_t rnti)
1594{
1595 bool found = false;
1596 uint8_t preambleId;
1597 for (preambleId = m_numberOfRaPreambles; preambleId < 64; ++preambleId)
1598 {
1599 std::map<uint8_t, NcRaPreambleInfo>::iterator it =
1600 m_allocatedNcRaPreambleMap.find(preambleId);
1612 if ((it != m_allocatedNcRaPreambleMap.end()) && (it->second.expiryTime < Simulator::Now()))
1613 {
1614 if (!m_cmacSapUser->IsRandomAccessCompleted(it->second.rnti))
1615 {
1616 // random access of the UE is not completed,
1617 // check other preambles
1618 continue;
1619 }
1620 }
1621 if ((it == m_allocatedNcRaPreambleMap.end()) || (it->second.expiryTime < Simulator::Now()))
1622 {
1623 found = true;
1624 NcRaPreambleInfo preambleInfo;
1625 uint32_t expiryIntervalMs =
1626 (uint32_t)m_preambleTransMax * ((uint32_t)m_raResponseWindowSize + 5);
1627
1628 preambleInfo.expiryTime = Simulator::Now() + MilliSeconds(expiryIntervalMs);
1629 preambleInfo.rnti = rnti;
1630 NS_LOG_INFO("allocated preamble for NC based RA: preamble "
1631 << preambleId << ", RNTI " << preambleInfo.rnti << ", exiryTime "
1632 << preambleInfo.expiryTime);
1633 m_allocatedNcRaPreambleMap[preambleId] =
1634 preambleInfo; // create if not exist, update otherwise
1635 break;
1636 }
1637 }
1638 NrGnbCmacSapProvider::AllocateNcRaPreambleReturnValue ret;
1639 if (found)
1640 {
1641 ret.valid = true;
1642 ret.raPreambleId = preambleId;
1643 ret.raPrachMaskIndex = 0;
1644 }
1645 else
1646 {
1647 ret.valid = false;
1648 ret.raPreambleId = 0;
1649 ret.raPrachMaskIndex = 0;
1650 }
1651 return ret;
1652}
1653
1654// ////////////////////////////////////////////
1655// CSCHED SAP
1656// ////////////////////////////////////////////
1657
1658void
1659NrGnbMac::DoCschedCellConfigCnf(NrMacCschedSapUser::CschedCellConfigCnfParameters params)
1660{
1661 NS_LOG_FUNCTION(this);
1662}
1663
1664void
1665NrGnbMac::DoCschedUeConfigCnf(NrMacCschedSapUser::CschedUeConfigCnfParameters params)
1666{
1667 NS_LOG_FUNCTION(this);
1668}
1669
1670void
1671NrGnbMac::DoCschedLcConfigCnf(NrMacCschedSapUser::CschedLcConfigCnfParameters params)
1672{
1673 NS_LOG_FUNCTION(this);
1674 // Call the CSCHED primitive
1675 // m_cschedSap->LcConfigCompleted();
1676}
1677
1678void
1679NrGnbMac::DoCschedLcReleaseCnf(NrMacCschedSapUser::CschedLcReleaseCnfParameters params)
1680{
1681 NS_LOG_FUNCTION(this);
1682}
1683
1684void
1685NrGnbMac::DoCschedUeReleaseCnf(NrMacCschedSapUser::CschedUeReleaseCnfParameters params)
1686{
1687 NS_LOG_FUNCTION(this);
1688}
1689
1690void
1691NrGnbMac::DoCschedUeConfigUpdateInd(NrMacCschedSapUser::CschedUeConfigUpdateIndParameters params)
1692{
1693 NS_LOG_FUNCTION(this);
1694 // propagates to RRC
1695 NrGnbCmacSapUser::UeConfig ueConfigUpdate;
1696 ueConfigUpdate.m_rnti = params.m_rnti;
1697 ueConfigUpdate.m_transmissionMode = params.m_transmissionMode;
1698 m_cmacSapUser->RrcConfigurationUpdateInd(ueConfigUpdate);
1699}
1700
1701void
1702NrGnbMac::DoCschedCellConfigUpdateInd(
1703 NrMacCschedSapUser::CschedCellConfigUpdateIndParameters params)
1704{
1705 NS_LOG_FUNCTION(this);
1706}
1707
1708} // namespace ns3
Representation of a beam id.
Definition beam-id.h:26
GnbMacMemberNrMacSapProvider class.
Definition nr-mac-sap.h:191
MemberNrCcmMacSapProvider class.
Service Access Point (SAP) offered by the component carrier manager (CCM) by MAC to CCM.
Service Access Point (SAP) offered by MAC to the component carrier manager (CCM).
virtual void UlReceiveSr(uint16_t rnti, uint8_t componentCarrierId)=0
The MAC received a SR.
virtual void UlReceiveMacCe(nr::MacCeListElement_s bsr, uint8_t componentCarrierId)=0
When the Primary Component carrier receive a buffer status report it is sent to the CCM.
@ DL_HARQ
DL HARQ feedback.
@ SR
Scheduling Request: asking for space.
virtual void RrcConfigurationUpdateInd(UeConfig params)=0
virtual uint16_t AllocateTemporaryCellRnti()=0
virtual bool IsRandomAccessCompleted(uint16_t rnti)=0
Is random access completed function.
virtual uint8_t GetUlCtrlSyms() const
Retrieve the number of UL ctrl symbols configured in the scheduler.
uint8_t GetNumHarqProcess() const
NrCcmMacSapProvider * GetNrCcmMacSapProvider()
Get the gNB-ComponentCarrierManager SAP User.
virtual void DoSlotDlIndication(const SfnSf &sfnSf, LteNrTddSlotType type)
Perform DL scheduling decision for the indicated slot.
std::shared_ptr< DciInfoElementTdma > GetUlCtrlDci() const
Get a DCI for the UL CTRL symbol.
uint16_t GetBwpId() const
Get the bwp id of this MAC.
void SetNumRbPerRbg(uint32_t rbgSize)
Sets the number of RBs per RBG. Currently it can be configured by the user, while in the future it wi...
void SetNumHarqProcess(uint8_t numHarqProcess)
Sets the number of HARQ processes.
void SetNrCcmMacSapUser(NrCcmMacSapUser *s)
Set the ComponentCarrierManager SAP user.
~NrGnbMac() override
~NrGnbMac
std::shared_ptr< DciInfoElementTdma > GetDlCtrlDci() const
Get a DCI for the DL CTRL symbol.
void BeamChangeReport(BeamId beamId, uint8_t rnti)
A Beam for a user has changed.
uint16_t GetCellId() const
Get the cell id of this MAC.
uint32_t GetNumRbPerRbg() const
virtual void SetCurrentSfn(const SfnSf &sfn)
Set the current sfn.
virtual void DoSlotUlIndication(const SfnSf &sfnSf, LteNrTddSlotType type)
Perform UL scheduling decision for the indicated slot.
virtual uint8_t GetDlCtrlSyms() const
Retrieve the number of DL ctrl symbols configured in the scheduler.
void DoDispose() override
DoDispose method inherited from Object.
virtual void CschedCellConfigReq(const struct CschedCellConfigReqParameters &params)=0
CSCHED_CELL_CONFIG_REQ.
static const uint8_t SHORT_BSR
Short BSR.
virtual void SchedDlRachInfoReq(const SchedDlRachInfoReqParameters &params)=0
SCHED_DL_RACH_INFO_REQ.
virtual uint8_t GetDlCtrlSyms() const =0
Retrieve the number of DL ctrl symbols configured in the scheduler.
virtual void SchedUlSrInfoReq(const SchedUlSrInfoReqParameters &params)=0
Provides scheduling request reception information to the scheduler.
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &params)=0
Starts the UL MAC scheduler for this subframe.
virtual void SchedDlTriggerReq(const struct SchedDlTriggerReqParameters &params)=0
Starts the DL MAC scheduler for this subframe.
virtual uint8_t GetUlCtrlSyms() const =0
Retrieve the number of UL ctrl symbols configured in the scheduler.
virtual BeamId GetBeamId(uint8_t rnti) const =0
Get the beam ID from the RNTI specified. Not in any standard.
virtual void SendMacPdu(const Ptr< Packet > &p, const SfnSf &sfn, uint8_t symStart, uint16_t rnti)=0
Send a Mac PDU.
virtual uint16_t GetCellId() const =0
Retrieve the cell id.
virtual uint32_t GetRbNum() const =0
Retrieve the number of resource blocks.
virtual void SetSlotAllocInfo(const SlotAllocInfo &slotAllocInfo)=0
Set a SlotAllocInfo inside the PHY allocations.
virtual uint16_t GetBwpId() const =0
Retrieve the bandwidth part id.
The SfnSf class.
Definition sfnsf.h:32
uint8_t GetNumerology() const
GetNumerology.
Definition sfnsf.cc:182
static double fpS11dot3toDouble(uint16_t val)
Definition nr-common.cc:140
LteNrTddSlotType
Available TDD slot types. Ordering is important.
NrSchedulingCallbackInfo structure.
uint8_t m_ndi
New data indicator.
uint8_t m_symStart
starting symbol index
uint8_t m_subframeNum
subframe number
uint16_t m_frameNum
frame number
uint8_t m_bwpId
Bandwidth Part ID.
uint16_t m_slotNum
slot number
uint8_t m_numSym
number of symbols
@ CTRL
Used for DL/UL CTRL.
@ SRS
Used for SRS (it would be like DCI format 2_3)
enum ns3::DlHarqInfo::HarqStatus NACK
HARQ status.
std::vector< struct DlCqiInfo > m_cqiList
cqi list
std::vector< struct nr::RachListElement_s > m_rachList
RACH list.
DL HARQ information to be used when scheduling UL data.
std::vector< struct DlHarqInfo > m_dlHarqInfoList
DL HARQ info list.
LteNrTddSlotType m_slotType
Indicate the type of slot requested.
The SchedUlMacCtrlInfoReqParameters struct.
std::vector< struct MacCeElement > m_macCeList
MacCeElement list.
SR received from MAC, to pass to schedulers.
std::vector< uint16_t > m_srList
List of RNTI which asked for a SR.
SfnSf m_snfSf
SnfSf in which the sr where received.
UL HARQ information to be used when scheduling UL data.
std::vector< struct UlHarqInfo > m_ulHarqInfoList
UL HARQ info list.
LteNrTddSlotType m_slotType
Indicate the type of slot requested.
The SlotAllocInfo struct.