5G-LENA nr-v3.1-69-g2dd513a7
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
559void
560NrGnbMac::ReceiveRachPreamble(uint32_t raId)
561{
562 Ptr<NrRachPreambleMessage> rachMsg = Create<NrRachPreambleMessage>();
563 rachMsg->SetSourceBwp(GetBwpId());
564 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), raId, GetBwpId(), rachMsg);
565
566 ++m_receivedRachPreambleCount[raId];
567}
568
569NrMacSapProvider*
570NrGnbMac::GetMacSapProvider()
571{
572 return m_macSapProvider;
573}
574
575NrGnbCmacSapProvider*
576NrGnbMac::GetGnbCmacSapProvider()
577{
578 return m_cmacSapProvider;
579}
580
581void
582NrGnbMac::SetGnbCmacSapUser(NrGnbCmacSapUser* s)
583{
584 m_cmacSapUser = s;
585}
586
587void
589{
590 m_ccmMacSapUser = s;
591}
592
595{
596 NS_LOG_FUNCTION(this);
597 return m_ccmMacSapProvider;
598}
599
600void
602{
603 NS_LOG_FUNCTION(this);
604 m_currentSlot = sfnSf;
605}
606
607void
609{
610 NS_LOG_FUNCTION(this);
611 NS_LOG_LOGIC("Perform things on DL, slot on the air: " << sfnSf);
612
613 // --- DOWNLINK ---
614 // Send Dl-CQI info to the scheduler if(m_dlCqiReceived.size () > 0)
615 {
617 dlCqiInfoReq.m_sfnsf = sfnSf;
618
619 dlCqiInfoReq.m_cqiList.insert(dlCqiInfoReq.m_cqiList.begin(),
620 m_dlCqiReceived.begin(),
621 m_dlCqiReceived.end());
622 m_dlCqiReceived.erase(m_dlCqiReceived.begin(), m_dlCqiReceived.end());
623
624 m_macSchedSapProvider->SchedDlCqiInfoReq(dlCqiInfoReq);
625
626 for (const auto& v : dlCqiInfoReq.m_cqiList)
627 {
628 Ptr<NrDlCqiMessage> msg = Create<NrDlCqiMessage>();
629 msg->SetDlCqi(v);
630 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v.m_rnti, GetBwpId(), msg);
631 }
632 }
633
635
636 dlParams.m_slotType = type;
637 dlParams.m_snfSf = sfnSf;
638
639 // Forward DL HARQ feedbacks collected during last subframe TTI
640 if (!m_dlHarqInfoReceived.empty())
641 {
642 dlParams.m_dlHarqInfoList = m_dlHarqInfoReceived;
643 // empty local buffer
644 m_dlHarqInfoReceived.clear();
645
646 for (const auto& v : dlParams.m_dlHarqInfoList)
647 {
648 Ptr<NrDlHarqFeedbackMessage> msg = Create<NrDlHarqFeedbackMessage>();
649 msg->SetDlHarqFeedback(v);
650 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v.m_rnti, GetBwpId(), msg);
651 }
652 }
653
654 {
655 for (const auto& ue : m_rlcAttached)
656 {
658 params.m_rnti = ue.first;
659 params.m_beamId = m_phySapProvider->GetBeamId(ue.first);
660 params.m_transmissionMode = 0; // set to default value (SISO) for avoiding random
661 // initialization (valgrind error)
662 m_macCschedSapProvider->CschedUeConfigReq(params);
663 }
664 }
665
666 m_macSchedSapProvider->SchedDlTriggerReq(dlParams);
667}
668
669void
670NrGnbMac::ProcessRaPreambles(const SfnSf& sfnSf)
671{
672 NS_LOG_FUNCTION(this);
673
674 // process received RACH preambles and notify the scheduler
676
677 for (auto it = m_receivedRachPreambleCount.begin(); it != m_receivedRachPreambleCount.end();
678 ++it)
679 {
680 NS_LOG_INFO(this << " preambleId " << static_cast<uint32_t>(it->first) << ": " << it->second
681 << " received");
682 NS_ASSERT(it->second != 0);
683 if (it->second > 1)
684 {
685 NS_LOG_INFO("preambleId " << static_cast<uint32_t>(it->first) << ": collision"
686 << " at: " << Simulator::Now().As(Time::MS));
687 // in case of collision we assume that no preamble is
688 // successfully received, hence no RAR is sent
689 }
690 else
691 {
692 uint16_t rnti;
693 std::map<uint8_t, NcRaPreambleInfo>::iterator jt =
694 m_allocatedNcRaPreambleMap.find(it->first);
695 if (jt != m_allocatedNcRaPreambleMap.end())
696 {
697 rnti = jt->second.rnti;
698 NS_LOG_INFO("preambleId previously allocated for NC based RA, RNTI ="
699 << static_cast<uint32_t>(rnti) << ", sending RAR"
700 << " at: " << Simulator::Now().As(Time::MS));
701 }
702 else
703 {
704 rnti = m_cmacSapUser->AllocateTemporaryCellRnti();
705 NS_LOG_INFO("preambleId " << static_cast<uint32_t>(it->first)
706 << ": allocated T-C-RNTI " << static_cast<uint32_t>(rnti)
707 << ", sending RAR "
708 << " at: " << Simulator::Now().As(Time::MS));
709 }
710
711 NS_LOG_INFO("Informing MAC scheduler of the RACH preamble for "
712 << static_cast<uint16_t>(it->first) << " in slot " << sfnSf);
713 nr::RachListElement_s rachLe;
714 rachLe.m_rnti = rnti;
715 rachLe.m_estimatedSize = 144; // to be confirmed
716 rachInfoReqParams.m_rachList.push_back(rachLe);
717 m_rapIdRntiMap.insert(std::pair<uint16_t, uint32_t>(rnti, it->first));
718 }
719 }
720
721 m_receivedRachPreambleCount.clear();
722 m_macSchedSapProvider->SchedDlRachInfoReq(rachInfoReqParams);
723}
724
725void
727{
728 NS_LOG_FUNCTION(this);
729 NS_LOG_LOGIC("Perform things on UL, slot on the air: " << sfnSf);
730
731 if (!m_receivedRachPreambleCount.empty())
732 {
733 ProcessRaPreambles(sfnSf);
734 }
735
736 // --- UPLINK ---
737 // Send UL-CQI info to the scheduler
738 for (auto& i : m_ulCqiReceived)
739 {
740 // m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & frameNum) << 16) | ((0xFF & subframeNum) << 8)
741 // | (0xFF & varTtiNum);
742 m_macSchedSapProvider->SchedUlCqiInfoReq(i);
743 }
744 m_ulCqiReceived.clear();
745
746 // Send SR info to the scheduler
747 {
749 params.m_snfSf = m_currentSlot;
750 params.m_srList.insert(params.m_srList.begin(), m_srRntiList.begin(), m_srRntiList.end());
751 m_srRntiList.clear();
752
753 m_macSchedSapProvider->SchedUlSrInfoReq(params);
754
755 for (const auto& v : params.m_srList)
756 {
757 Ptr<NrSRMessage> msg = Create<NrSRMessage>();
758 msg->SetRNTI(v);
759 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v, GetBwpId(), msg);
760 }
761 }
762
763 // Send UL BSR reports to the scheduler
764 if (!m_ulCeReceived.empty())
765 {
767 ulMacReq.m_sfnSf = sfnSf;
768 ulMacReq.m_macCeList.insert(ulMacReq.m_macCeList.begin(),
769 m_ulCeReceived.begin(),
770 m_ulCeReceived.end());
771 m_ulCeReceived.erase(m_ulCeReceived.begin(), m_ulCeReceived.end());
772 m_macSchedSapProvider->SchedUlMacCtrlInfoReq(ulMacReq);
773
774 for (const auto& v : ulMacReq.m_macCeList)
775 {
776 Ptr<NrBsrMessage> msg = Create<NrBsrMessage>();
777 msg->SetBsr(v);
778 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), v.m_rnti, GetBwpId(), msg);
779 }
780 }
781
783
784 ulParams.m_snfSf = sfnSf;
785 ulParams.m_slotType = type;
786
787 // Forward UL HARQ feebacks collected during last TTI
788 if (!m_ulHarqInfoReceived.empty())
789 {
790 ulParams.m_ulHarqInfoList = m_ulHarqInfoReceived;
791 // empty local buffer
792 m_ulHarqInfoReceived.clear();
793 }
794
795 m_macSchedSapProvider->SchedUlTriggerReq(ulParams);
796}
797
798void
799NrGnbMac::SetForwardUpCallback(Callback<void, Ptr<Packet>> cb)
800{
801 m_forwardUpCallback = cb;
802}
803
804void
805NrGnbMac::ReceiveBsrMessage(MacCeElement bsr)
806{
807 NS_LOG_FUNCTION(this);
808 // in order to use existing SAP interfaces we need to convert MacCeElement to
809 // nr::MacCeListElement_s
810
811 nr::MacCeListElement_s mcle;
812 mcle.m_rnti = bsr.m_rnti;
813 mcle.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
814 mcle.m_macCeValue.m_crnti = bsr.m_macCeValue.m_crnti;
815 mcle.m_macCeValue.m_phr = bsr.m_macCeValue.m_phr;
816 mcle.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
817
818 if (bsr.m_macCeType == MacCeElement::BSR)
819 {
820 mcle.m_macCeType = nr::MacCeListElement_s::BSR;
821 }
822 else if (bsr.m_macCeType == MacCeElement::CRNTI)
823 {
824 mcle.m_macCeType = nr::MacCeListElement_s::CRNTI;
825 }
826 else if (bsr.m_macCeType == MacCeElement::PHR)
827 {
828 mcle.m_macCeType = nr::MacCeListElement_s::PHR;
829 }
830
831 m_ccmMacSapUser->UlReceiveMacCe(mcle, GetBwpId());
832}
833
834void
835NrGnbMac::DoReportMacCeToScheduler(nr::MacCeListElement_s bsr)
836{
837 NS_LOG_FUNCTION(this);
838 NS_LOG_DEBUG(this << " bsr Size " << (uint16_t)m_ulCeReceived.size());
839 uint32_t size = 0;
840
841 // send to NrCcmMacSapUser
842 // convert nr::MacCeListElement_s to MacCeElement
843
844 MacCeElement mce;
845 mce.m_rnti = bsr.m_rnti;
846 mce.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
847 mce.m_macCeValue.m_crnti = bsr.m_macCeValue.m_crnti;
848 mce.m_macCeValue.m_phr = bsr.m_macCeValue.m_phr;
849 mce.m_macCeValue.m_bufferStatus = bsr.m_macCeValue.m_bufferStatus;
850
851 if (bsr.m_macCeType == nr::MacCeListElement_s::BSR)
852 {
853 mce.m_macCeType = MacCeElement::BSR;
854 }
855 else if (bsr.m_macCeType == nr::MacCeListElement_s::CRNTI)
856 {
857 mce.m_macCeType = MacCeElement::CRNTI;
858 }
859 else if (bsr.m_macCeType == nr::MacCeListElement_s::PHR)
860 {
861 mce.m_macCeType = MacCeElement::PHR;
862 }
863
864 for (const auto& v : bsr.m_macCeValue.m_bufferStatus)
865 {
866 size += v;
867 }
868
869 m_ulCeReceived.push_back(
870 mce); // this to called when NrUlCcmSapProvider::ReportMacCeToScheduler is called
871 NS_LOG_DEBUG(" Reported by UE " << static_cast<uint32_t>(bsr.m_macCeValue.m_crnti) << " size "
872 << size << " bsr vector ize after push_back "
873 << static_cast<uint32_t>(m_ulCeReceived.size()));
874}
875
876void
877NrGnbMac::DoReportSrToScheduler(uint16_t rnti)
878{
879 NS_LOG_FUNCTION(this);
880 m_srRntiList.push_back(rnti);
881 m_srCallback(GetBwpId(), rnti);
882}
883
884void
885NrGnbMac::DoReceivePhyPdu(Ptr<Packet> p)
886{
887 NS_LOG_FUNCTION(this);
888
889 NrRadioBearerTag tag;
890 p->RemovePacketTag(tag);
891
892 uint16_t rnti = tag.GetRnti();
893 auto rntiIt = m_rlcAttached.find(rnti);
894
895 NS_ASSERT_MSG(rntiIt != m_rlcAttached.end(), "could not find RNTI" << rnti);
896
897 // Try to peek whatever header; in the first byte there will be the LC ID.
898 NrMacHeaderFsUl header;
899 p->PeekHeader(header);
900
901 // Based on LC ID, we know if it is a CE or simply data.
902 if (header.GetLcId() == NrMacHeaderFsUl::SHORT_BSR)
903 {
904 NrMacShortBsrCe bsrHeader;
905 p->RemoveHeader(bsrHeader); // Really remove the header this time
906
907 // Convert our custom header into the structure that the scheduler expects:
908 MacCeElement bsr;
909
910 bsr.m_macCeType = MacCeElement::BSR;
911 bsr.m_rnti = rnti;
912 bsr.m_macCeValue.m_bufferStatus.resize(4);
913 bsr.m_macCeValue.m_bufferStatus[0] = bsrHeader.m_bufferSizeLevel_0;
914 bsr.m_macCeValue.m_bufferStatus[1] = bsrHeader.m_bufferSizeLevel_1;
915 bsr.m_macCeValue.m_bufferStatus[2] = bsrHeader.m_bufferSizeLevel_2;
916 bsr.m_macCeValue.m_bufferStatus[3] = bsrHeader.m_bufferSizeLevel_3;
917
918 ReceiveBsrMessage(bsr); // Here it will be converted again, but our job is done.
919 return;
920 }
921
922 // Ok, we know it is data, so let's extract and pass to RLC.
923
924 NrMacHeaderVs macHeader;
925 p->RemoveHeader(macHeader);
926
927 auto lcidIt = rntiIt->second.find(macHeader.GetLcId());
928 if (lcidIt == rntiIt->second.end())
929 {
930 NS_LOG_DEBUG("Discarding PDU addressed to non-existent LCID " << macHeader.GetLcId());
931 return;
932 }
933
934 NrMacSapUser::ReceivePduParameters rxParams;
935 rxParams.p = p;
936 rxParams.lcid = macHeader.GetLcId();
937 rxParams.rnti = rnti;
938
939 if (rxParams.p->GetSize())
940 {
941 (*lcidIt).second->ReceivePdu(rxParams);
942 }
943}
944
945NrGnbPhySapUser*
946NrGnbMac::GetPhySapUser()
947{
948 return m_phySapUser;
949}
950
951void
952NrGnbMac::SetPhySapProvider(NrPhySapProvider* ptr)
953{
954 m_phySapProvider = ptr;
955}
956
957NrMacSchedSapUser*
958NrGnbMac::GetNrMacSchedSapUser()
959{
960 return m_macSchedSapUser;
961}
962
963void
964NrGnbMac::SetNrMacSchedSapProvider(NrMacSchedSapProvider* ptr)
965{
966 m_macSchedSapProvider = ptr;
967}
968
969NrMacCschedSapUser*
970NrGnbMac::GetNrMacCschedSapUser()
971{
972 return m_macCschedSapUser;
973}
974
975void
976NrGnbMac::SetNrMacCschedSapProvider(NrMacCschedSapProvider* ptr)
977{
978 m_macCschedSapProvider = ptr;
979}
980
981void
982NrGnbMac::DoUlCqiReport(NrMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
983{
984 if (ulcqi.m_ulCqi.m_type == UlCqiInfo::PUSCH)
985 {
986 NS_LOG_DEBUG(this << " gNB rxed an PUSCH UL-CQI");
987 }
988 else if (ulcqi.m_ulCqi.m_type == UlCqiInfo::SRS)
989 {
990 NS_LOG_DEBUG(this << " gNB rxed an SRS UL-CQI");
991 }
992 NS_LOG_INFO("*** UL CQI report SINR "
993 << nr::FfConverter::fpS11dot3toDouble(ulcqi.m_ulCqi.m_sinr[0])
994 << " slot: " << m_currentSlot);
995
996 // NS_ASSERT (ulcqi.m_sfnSf.m_varTtiNum != 0); Now UL data can be the first TTI..
997 m_ulCqiReceived.push_back(ulcqi);
998}
999
1000void
1001NrGnbMac::DoReceiveControlMessage(Ptr<NrControlMessage> msg)
1002{
1003 NS_LOG_FUNCTION(this << msg);
1004
1005 switch (msg->GetMessageType())
1006 {
1007 case (NrControlMessage::SR): {
1008 // Report it to the CCM. Then he will call the right MAC
1009 Ptr<NrSRMessage> sr = DynamicCast<NrSRMessage>(msg);
1010 m_ccmMacSapUser->UlReceiveSr(sr->GetRNTI(), GetBwpId());
1011 break;
1012 }
1013 case (NrControlMessage::DL_CQI): {
1014 Ptr<NrDlCqiMessage> cqi = DynamicCast<NrDlCqiMessage>(msg);
1015 DlCqiInfo cqiElement = cqi->GetDlCqi();
1016 NS_ASSERT(cqiElement.m_rnti != 0);
1017 m_dlCqiReceived.push_back(cqiElement);
1018 break;
1019 }
1021 Ptr<NrDlHarqFeedbackMessage> dlharq = DynamicCast<NrDlHarqFeedbackMessage>(msg);
1022 DoDlHarqFeedback(dlharq->GetDlHarqFeedback());
1023 break;
1024 }
1025 default:
1026 NS_LOG_WARN("Control message not supported/expected");
1027 }
1028}
1029
1030void
1031NrGnbMac::DoUlHarqFeedback(const UlHarqInfo& params)
1032{
1033 NS_LOG_FUNCTION(this);
1034 m_ulHarqInfoReceived.push_back(params);
1035}
1036
1037void
1038NrGnbMac::DoDlHarqFeedback(const DlHarqInfo& params)
1039{
1040 NS_LOG_FUNCTION(this);
1041 // Update HARQ buffer
1042 std::unordered_map<uint16_t, NrDlHarqProcessesBuffer_t>::iterator it =
1043 m_miDlHarqProcessesPackets.find(params.m_rnti);
1044 NS_ASSERT(it != m_miDlHarqProcessesPackets.end());
1045
1046 if (params.m_harqStatus == DlHarqInfo::ACK)
1047 {
1048 // discard buffer
1049 Ptr<PacketBurst> emptyBuf = CreateObject<PacketBurst>();
1050 (*it).second.at(params.m_harqProcessId).m_pktBurst = emptyBuf;
1051 NS_LOG_DEBUG(this << " HARQ-ACK UE RNTI" << params.m_rnti << " HARQ Process ID "
1052 << (uint16_t)params.m_harqProcessId);
1053 }
1054 else if (params.m_harqStatus == DlHarqInfo::NACK)
1055 {
1056 NS_LOG_DEBUG(this << " HARQ-NACK UE RNTI" << params.m_rnti << " HARQ Process ID "
1057 << (uint16_t)params.m_harqProcessId);
1058 }
1059 else
1060 {
1061 NS_FATAL_ERROR(" HARQ functionality not implemented");
1062 }
1063
1064 /* trace for HARQ feedback*/
1065 m_dlHarqFeedback(params);
1066
1067 m_dlHarqInfoReceived.push_back(params);
1068}
1069
1070void
1071NrGnbMac::DoReportBufferStatus(NrMacSapProvider::ReportBufferStatusParameters params)
1072{
1073 NS_LOG_FUNCTION(this);
1074 NrMacSchedSapProvider::SchedDlRlcBufferReqParameters schedParams;
1075 schedParams.m_logicalChannelIdentity = params.lcid;
1076 schedParams.m_rlcRetransmissionHolDelay = params.retxQueueHolDelay;
1077 schedParams.m_rlcRetransmissionQueueSize = params.retxQueueSize;
1078 schedParams.m_rlcStatusPduSize = params.statusPduSize;
1079 schedParams.m_rlcTransmissionQueueHolDelay = params.txQueueHolDelay;
1080 schedParams.m_rlcTransmissionQueueSize = params.txQueueSize;
1081 schedParams.m_rnti = params.rnti;
1082
1083 NS_LOG_INFO("Reporting RLC buffer status update to MAC Scheduler for RNTI="
1084 << params.rnti << ", LCID=" << (uint32_t)params.lcid << ", Transmission Queue Size="
1085 << params.txQueueSize << ", Transmission Queue HOL Delay=" << params.txQueueHolDelay
1086 << ", Retransmission Queue Size=" << params.retxQueueSize
1087 << ", Retransmission Queue HOL delay=" << params.retxQueueHolDelay
1088 << ", PDU Size=" << params.statusPduSize);
1089
1090 m_macSchedSapProvider->SchedDlRlcBufferReq(schedParams);
1091}
1092
1093// forwarded from NrMacSapProvider
1094void
1095NrGnbMac::DoTransmitPdu(NrMacSapProvider::TransmitPduParameters params)
1096{
1097 // TB UID passed back along with RLC data as HARQ process ID
1098 uint32_t tbMapKey = ((params.rnti & 0xFFFF) << 8) | (params.harqProcessId & 0xFF);
1099 auto harqIt = m_miDlHarqProcessesPackets.find(params.rnti);
1100 auto it = m_macPduMap.find(tbMapKey);
1101
1102 if (it == m_macPduMap.end())
1103 {
1104 NS_FATAL_ERROR("No MAC PDU storage element found for this TB UID/RNTI");
1105 }
1106
1107 NrMacHeaderVs header;
1108 header.SetLcId(params.lcid);
1109 header.SetSize(params.pdu->GetSize());
1110
1111 params.pdu->AddHeader(header);
1112
1113 NrRadioBearerTag bearerTag(params.rnti, params.lcid, 0);
1114 params.pdu->AddPacketTag(bearerTag);
1115
1116 harqIt->second.at(params.harqProcessId).m_pktBurst->AddPacket(params.pdu);
1117
1118 it->second.m_used += params.pdu->GetSize();
1119 NS_ASSERT_MSG(it->second.m_dci->m_tbSize >= it->second.m_used,
1120 "DCI OF " << it->second.m_dci->m_tbSize << " total used " << it->second.m_used);
1121
1122 NS_LOG_INFO("Sending MAC PDU to PHY Layer");
1123 m_phySapProvider->SendMacPdu(params.pdu,
1124 it->second.m_sfnSf,
1125 it->second.m_dci->m_symStart,
1126 params.rnti);
1127}
1128
1129void
1130NrGnbMac::DoBuildRarList(SlotAllocInfo& slotAllocInfo)
1131{
1132 NS_LOG_FUNCTION(this);
1133
1134 if (!HasMsg3Allocations(slotAllocInfo))
1135 {
1136 return;
1137 }
1138
1139 for (const auto& varTti : slotAllocInfo.m_varTtiAllocInfo)
1140 {
1141 if (varTti.m_dci->m_type == DciInfoElementTdma::MSG3)
1142 {
1143 NrBuildRarListElement_s rarElement;
1144 rarElement.ulMsg3Dci = varTti.m_dci;
1145 // set RA preamble ID
1146 auto itRaPreambleId = m_rapIdRntiMap.find(rarElement.ulMsg3Dci->m_rnti);
1147 NS_ABORT_IF(itRaPreambleId == m_rapIdRntiMap.end());
1148 NS_LOG_INFO("In slot " << m_currentSlot
1149 << " gNB MAC pass to PHY the RAR message for RNTI "
1150 << rarElement.ulMsg3Dci->m_rnti << " RA preamble ID "
1151 << itRaPreambleId->second << " at:" << Simulator::Now());
1152 rarElement.raPreambleId = itRaPreambleId->second;
1153 // K2 will be set by phy
1154 slotAllocInfo.m_buildRarList.push_back(rarElement);
1155 }
1156 }
1157
1158 if (!slotAllocInfo.m_buildRarList.empty())
1159 {
1160 m_rapIdRntiMap.clear(); // reset RA preamble to RNTI MAP
1161 NS_LOG_DEBUG("Sending RAR message to UE.");
1162 }
1163 else
1164 {
1165 NS_LOG_DEBUG("No RAR messages to be sent.");
1166 }
1167}
1168
1169bool
1170NrGnbMac::HasMsg3Allocations(const SlotAllocInfo& slotInfo)
1171{
1172 for (const auto& varTti : slotInfo.m_varTtiAllocInfo)
1173 {
1174 if (varTti.m_dci->m_type == DciInfoElementTdma::MSG3)
1175 {
1176 return true;
1177 }
1178 }
1179 return false;
1180}
1181
1182void
1183NrGnbMac::DoSchedConfigIndication(NrMacSchedSapUser::SchedConfigIndParameters ind)
1184{
1185 NS_ASSERT(ind.m_sfnSf.GetNumerology() == m_currentSlot.GetNumerology());
1186 std::stable_sort(ind.m_slotAllocInfo.m_varTtiAllocInfo.begin(),
1187 ind.m_slotAllocInfo.m_varTtiAllocInfo.end());
1188
1189 if (ind.m_slotAllocInfo.ContainsDataAllocation())
1190 {
1191 NS_LOG_INFO("New scheduled allocation: " << ind.m_slotAllocInfo);
1192 }
1193 m_phySapProvider->SetSlotAllocInfo(ind.m_slotAllocInfo);
1194
1195 for (auto& varTtiAllocInfo : ind.m_slotAllocInfo.m_varTtiAllocInfo)
1196 {
1197 if (varTtiAllocInfo.m_dci->m_type != DciInfoElementTdma::CTRL &&
1198 varTtiAllocInfo.m_dci->m_format == DciInfoElementTdma::DL)
1199 {
1200 uint16_t rnti = varTtiAllocInfo.m_dci->m_rnti;
1201 auto rntiIt = m_rlcAttached.find(rnti);
1202 NS_ABORT_MSG_IF(rntiIt == m_rlcAttached.end(),
1203 "Scheduled UE " << rnti << " not attached");
1204
1205 // Call RLC entities to generate RLC PDUs
1206 auto dciElem = varTtiAllocInfo.m_dci;
1207 uint8_t harqId = dciElem->m_harqProcess;
1208
1209 if (ind.m_slotAllocInfo.ContainsDataAllocation())
1210 {
1211 NS_LOG_INFO("New scheduled data TX in DL for HARQ Process ID: "
1212 << (uint32_t)harqId << ", Var. TTI from symbol "
1213 << (uint32_t)varTtiAllocInfo.m_dci->m_symStart << " to "
1214 << (uint32_t)varTtiAllocInfo.m_dci->m_symStart +
1215 (uint32_t)varTtiAllocInfo.m_dci->m_numSym
1216 << ". "
1217 << " TB of size " << varTtiAllocInfo.m_dci->m_tbSize << " with MCS "
1218 << varTtiAllocInfo.m_dci->m_mcs);
1219 }
1220
1221 // update Harq Processes
1222 if (dciElem->m_ndi == 1)
1223 {
1224 NS_ASSERT(dciElem->m_format == DciInfoElementTdma::DL);
1225 std::vector<RlcPduInfo>& rlcPduInfo = varTtiAllocInfo.m_rlcPduInfo;
1226 NS_ASSERT(!rlcPduInfo.empty());
1227 NrMacPduInfo macPduInfo(ind.m_sfnSf, dciElem);
1228 // insert into MAC PDU map
1229 uint32_t tbMapKey = ((rnti & 0xFFFF) << 8) | (harqId & 0xFF);
1230 std::pair<std::unordered_map<uint32_t, struct NrMacPduInfo>::iterator, bool>
1231 mapRet = m_macPduMap.insert(
1232 std::pair<uint32_t, struct NrMacPduInfo>(tbMapKey, macPduInfo));
1233 if (!mapRet.second)
1234 {
1235 NS_FATAL_ERROR("MAC PDU map element exists");
1236 }
1237
1238 // new data -> force emptying correspondent harq pkt buffer
1239 std::unordered_map<uint16_t, NrDlHarqProcessesBuffer_t>::iterator harqIt =
1240 m_miDlHarqProcessesPackets.find(rnti);
1241 NS_ASSERT(harqIt != m_miDlHarqProcessesPackets.end());
1242 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
1243 harqIt->second.at(harqId).m_pktBurst = pb;
1244 harqIt->second.at(harqId).m_lcidList.clear();
1245
1246 std::unordered_map<uint32_t, struct NrMacPduInfo>::iterator pduMapIt = mapRet.first;
1247 // for each LC j
1248 for (auto& j : rlcPduInfo)
1249 {
1250 NS_ASSERT_MSG(rntiIt != m_rlcAttached.end(), "could not find RNTI" << rnti);
1251 std::unordered_map<uint8_t, NrMacSapUser*>::iterator lcidIt =
1252 rntiIt->second.find(j.m_lcid);
1253 NS_ASSERT_MSG(lcidIt != rntiIt->second.end(),
1254 "could not find LCID" << std::to_string(j.m_lcid));
1255 NS_LOG_INFO("Notifying RLC of TX opportunity for HARQ Process ID "
1256 << (unsigned int)harqId << " LC ID " << std::to_string(+j.m_lcid)
1257 << (unsigned int)j.m_size);
1258
1259 (*lcidIt).second->NotifyTxOpportunity(
1260 NrMacSapUser::TxOpportunityParameters((j.m_size),
1261 0,
1262 harqId,
1263 GetBwpId(),
1264 rnti,
1265 j.m_lcid));
1266 harqIt->second.at(harqId).m_lcidList.push_back(j.m_lcid);
1267 }
1268
1269 m_macPduMap.erase(pduMapIt); // delete map entry
1270
1271 NrSchedulingCallbackInfo traceInfo;
1272 traceInfo.m_frameNum = ind.m_sfnSf.GetFrame();
1273 traceInfo.m_subframeNum = ind.m_sfnSf.GetSubframe();
1274 traceInfo.m_slotNum = ind.m_sfnSf.GetSlot();
1275 traceInfo.m_symStart = dciElem->m_symStart;
1276 traceInfo.m_numSym = dciElem->m_numSym;
1277 traceInfo.m_tbSize = dciElem->m_tbSize;
1278 traceInfo.m_mcs = dciElem->m_mcs;
1279 traceInfo.m_rnti = dciElem->m_rnti;
1280 traceInfo.m_bwpId = GetBwpId();
1281 traceInfo.m_ndi = dciElem->m_ndi;
1282 traceInfo.m_rv = dciElem->m_rv;
1283 traceInfo.m_harqId = dciElem->m_harqProcess;
1284 m_dlScheduling(traceInfo);
1285 }
1286 else
1287 {
1288 NS_LOG_INFO("DL retransmission");
1289 if (dciElem->m_tbSize > 0)
1290 {
1291 std::unordered_map<uint16_t, NrDlHarqProcessesBuffer_t>::iterator it =
1292 m_miDlHarqProcessesPackets.find(rnti);
1293 NS_ASSERT(it != m_miDlHarqProcessesPackets.end());
1294 Ptr<PacketBurst> pb = it->second.at(harqId).m_pktBurst;
1295 for (std::list<Ptr<Packet>>::const_iterator j = pb->Begin(); j != pb->End();
1296 ++j)
1297 {
1298 Ptr<Packet> pkt = (*j)->Copy();
1299 m_phySapProvider->SendMacPdu(pkt,
1300 ind.m_sfnSf,
1301 dciElem->m_symStart,
1302 dciElem->m_rnti);
1303 }
1304 }
1305 }
1306 }
1307 else if (varTtiAllocInfo.m_dci->m_type != DciInfoElementTdma::CTRL &&
1308 varTtiAllocInfo.m_dci->m_type != DciInfoElementTdma::SRS &&
1309 varTtiAllocInfo.m_dci->m_format == DciInfoElementTdma::UL)
1310 {
1311 // UL scheduling info trace
1312 // Call RLC entities to generate RLC PDUs
1313 auto dciElem = varTtiAllocInfo.m_dci;
1314 NrSchedulingCallbackInfo traceInfo;
1315 traceInfo.m_frameNum = ind.m_sfnSf.GetFrame();
1316 traceInfo.m_subframeNum = ind.m_sfnSf.GetSubframe();
1317 traceInfo.m_slotNum = ind.m_sfnSf.GetSlot();
1318 traceInfo.m_symStart = dciElem->m_symStart;
1319 traceInfo.m_numSym = dciElem->m_numSym;
1320 traceInfo.m_tbSize = dciElem->m_tbSize;
1321 traceInfo.m_mcs = dciElem->m_mcs;
1322 traceInfo.m_rnti = dciElem->m_rnti;
1323 traceInfo.m_bwpId = GetBwpId();
1324 traceInfo.m_ndi = dciElem->m_ndi;
1325 traceInfo.m_rv = dciElem->m_rv;
1326 traceInfo.m_harqId = dciElem->m_harqProcess;
1327 m_ulScheduling(traceInfo);
1328 }
1329 }
1330}
1331
1332// ////////////////////////////////////////////
1333// CMAC SAP
1334// ////////////////////////////////////////////
1335
1336void
1337NrGnbMac::DoConfigureMac(uint16_t ulBandwidth, uint16_t dlBandwidth)
1338{
1339 NS_LOG_FUNCTION(this);
1340
1341 // The bandwidth arrived in Hz. We need to know it in number of RB, and then
1342 // consider how many RB are inside a single RBG.
1343 uint16_t bw_in_rbg = m_phySapProvider->GetRbNum() / GetNumRbPerRbg();
1344 m_bandwidthInRbg = bw_in_rbg;
1345
1346 NS_LOG_DEBUG("Mac configured. Attributes:"
1347 << std::endl
1348 << "\t NumRbPerRbg: " << m_numRbPerRbg << std::endl
1349 << "\t NumHarqProcess: " << +m_numHarqProcess << std::endl
1350 << "Physical properties: " << std::endl
1351 << "\t Bandwidth provided: " << ulBandwidth * 1000 * 100 << " Hz" << std::endl
1352 << "\t that corresponds to " << bw_in_rbg << " RBG, as we have "
1353 << m_phySapProvider->GetRbNum() << " RB and " << GetNumRbPerRbg()
1354 << " RB per RBG");
1355
1356 NrMacCschedSapProvider::CschedCellConfigReqParameters params;
1357
1358 params.m_ulBandwidth = m_bandwidthInRbg;
1359 params.m_dlBandwidth = m_bandwidthInRbg;
1360
1361 m_macCschedSapProvider->CschedCellConfigReq(params);
1362}
1363
1364void
1366{
1368 params.m_rnti = rnti;
1369 params.m_beamId = beamId;
1370 params.m_transmissionMode =
1371 0; // set to default value (SISO) for avoiding random initialization (valgrind error)
1372 m_macCschedSapProvider->CschedUeConfigReq(params);
1373}
1374
1375uint16_t
1377{
1378 if (m_phySapProvider)
1379 {
1380 return m_phySapProvider->GetBwpId();
1381 }
1382 else
1383 {
1384 return UINT16_MAX;
1385 }
1386}
1387
1388uint16_t
1390{
1391 if (m_phySapProvider)
1392 {
1393 return m_phySapProvider->GetCellId();
1394 }
1395 else
1396 {
1397 return UINT16_MAX;
1398 }
1399}
1400
1401std::shared_ptr<DciInfoElementTdma>
1403{
1404 NS_LOG_FUNCTION(this);
1405
1406 auto bwInRbg = m_phySapProvider->GetRbNum() / GetNumRbPerRbg();
1407 NS_ASSERT(bwInRbg > 0);
1408 std::vector<uint8_t> rbgBitmask(bwInRbg, 1);
1409
1410 return std::make_shared<DciInfoElementTdma>(0,
1411 m_macSchedSapProvider->GetDlCtrlSyms(),
1414 rbgBitmask);
1415}
1416
1417std::shared_ptr<DciInfoElementTdma>
1419{
1420 NS_LOG_FUNCTION(this);
1421
1422 NS_ASSERT(m_bandwidthInRbg > 0);
1423 std::vector<uint8_t> rbgBitmask(m_bandwidthInRbg, 1);
1424
1425 return std::make_shared<DciInfoElementTdma>(0,
1426 m_macSchedSapProvider->GetUlCtrlSyms(),
1429 rbgBitmask);
1430}
1431
1432void
1433NrGnbMac::DoAddUe(uint16_t rnti)
1434{
1435 NS_LOG_FUNCTION(this << " rnti=" << rnti);
1436 std::unordered_map<uint8_t, NrMacSapUser*> empty;
1437 std::pair<std::unordered_map<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>::iterator,
1438 bool>
1439 ret = m_rlcAttached.insert(
1440 std::pair<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>(rnti, empty));
1441 NS_ASSERT_MSG(ret.second, "element already present, RNTI already existed");
1442
1444 params.m_rnti = rnti;
1445 params.m_beamId = m_phySapProvider->GetBeamId(rnti);
1446 params.m_transmissionMode =
1447 0; // set to default value (SISO) for avoiding random initialization (valgrind error)
1448 m_macCschedSapProvider->CschedUeConfigReq(params);
1449
1450 // Create DL transmission HARQ buffers
1451 NrDlHarqProcessesBuffer_t buf;
1452 uint16_t harqNum = GetNumHarqProcess();
1453 buf.resize(harqNum);
1454 for (uint16_t i = 0; i < harqNum; i++)
1455 {
1456 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
1457 buf.at(i).m_pktBurst = pb;
1458 }
1459 m_miDlHarqProcessesPackets.insert(std::pair<uint16_t, NrDlHarqProcessesBuffer_t>(rnti, buf));
1460}
1461
1462void
1463NrGnbMac::DoRemoveUe(uint16_t rnti)
1464{
1465 NS_LOG_FUNCTION(this << " rnti=" << rnti);
1466 NrMacCschedSapProvider::CschedUeReleaseReqParameters params;
1467 params.m_rnti = rnti;
1468 m_macCschedSapProvider->CschedUeReleaseReq(params);
1469 m_miDlHarqProcessesPackets.erase(rnti);
1470 m_rlcAttached.erase(rnti);
1471
1472 // remove unprocessed preamble received for RACH during handover
1473 auto jt = m_allocatedNcRaPreambleMap.begin();
1474 while (jt != m_allocatedNcRaPreambleMap.end())
1475 {
1476 if (jt->second.rnti == rnti)
1477 {
1478 auto it = m_receivedRachPreambleCount.find(jt->first);
1479 if (it != m_receivedRachPreambleCount.end())
1480 {
1481 m_receivedRachPreambleCount.erase(it->first);
1482 }
1483 jt = m_allocatedNcRaPreambleMap.erase(jt);
1484 }
1485 else
1486 {
1487 ++jt;
1488 }
1489 }
1490}
1491
1492void
1493NrGnbMac::DoAddLc(NrGnbCmacSapProvider::LcInfo lcinfo, NrMacSapUser* msu)
1494{
1495 NS_LOG_FUNCTION(this);
1496 NS_LOG_FUNCTION(this);
1497
1498 std::unordered_map<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>::iterator rntiIt =
1499 m_rlcAttached.find(lcinfo.rnti);
1500 NS_ASSERT_MSG(rntiIt != m_rlcAttached.end(), "RNTI not found");
1501 std::unordered_map<uint8_t, NrMacSapUser*>::iterator lcidIt = rntiIt->second.find(lcinfo.lcId);
1502 if (lcidIt == rntiIt->second.end())
1503 {
1504 rntiIt->second.insert(std::pair<uint8_t, NrMacSapUser*>(lcinfo.lcId, msu));
1505 }
1506 else
1507 {
1508 NS_LOG_ERROR("LC already exists");
1509 }
1510
1511 // CCCH (LCID 0) is pre-configured
1512 // see FF LTE MAC Scheduler
1513 // Interface Specification v1.11,
1514 // 4.3.4 logicalChannelConfigListElement
1515 if (lcinfo.lcId != 0)
1516 {
1517 struct NrMacCschedSapProvider::CschedLcConfigReqParameters params;
1518 params.m_rnti = lcinfo.rnti;
1519 params.m_reconfigureFlag = false;
1520
1521 struct nr::LogicalChannelConfigListElement_s lccle;
1522 lccle.m_logicalChannelIdentity = lcinfo.lcId;
1523 lccle.m_logicalChannelGroup = lcinfo.lcGroup;
1524 lccle.m_direction = nr::LogicalChannelConfigListElement_s::DIR_BOTH;
1525 lccle.m_qci = lcinfo.qci;
1526 lccle.m_eRabMaximulBitrateUl = lcinfo.mbrUl;
1527 lccle.m_eRabMaximulBitrateDl = lcinfo.mbrDl;
1528 lccle.m_eRabGuaranteedBitrateUl = lcinfo.gbrUl;
1529 lccle.m_eRabGuaranteedBitrateDl = lcinfo.gbrDl;
1530
1531 lccle.m_qosBearerType = static_cast<nr::LogicalChannelConfigListElement_s::QosBearerType_e>(
1532 lcinfo.resourceType);
1533
1534 params.m_logicalChannelConfigList.push_back(lccle);
1535
1536 m_macCschedSapProvider->CschedLcConfigReq(params);
1537 }
1538}
1539
1540void
1541NrGnbMac::DoReconfigureLc(NrGnbCmacSapProvider::LcInfo lcinfo)
1542{
1543 NS_FATAL_ERROR("not implemented");
1544}
1545
1546void
1547NrGnbMac::DoReleaseLc(uint16_t rnti, uint8_t lcid)
1548{
1549 // Find user based on rnti and then erase lcid stored against the same
1550 std::unordered_map<uint16_t, std::unordered_map<uint8_t, NrMacSapUser*>>::iterator rntiIt =
1551 m_rlcAttached.find(rnti);
1552 rntiIt->second.erase(lcid);
1553
1554 struct NrMacCschedSapProvider::CschedLcReleaseReqParameters params;
1555 params.m_rnti = rnti;
1556 params.m_logicalChannelIdentity.push_back(lcid);
1557 m_macCschedSapProvider->CschedLcReleaseReq(params);
1558}
1559
1560void
1561NrGnbMac::UeUpdateConfigurationReq(NrGnbCmacSapProvider::UeConfig params)
1562{
1563 NS_LOG_FUNCTION(this);
1564 // propagates to scheduler
1565 NrMacCschedSapProvider::CschedUeConfigReqParameters req;
1566 req.m_rnti = params.m_rnti;
1567 req.m_transmissionMode = params.m_transmissionMode;
1568 req.m_beamId = m_phySapProvider->GetBeamId(params.m_rnti);
1569 req.m_reconfigureFlag = true;
1570 m_macCschedSapProvider->CschedUeConfigReq(req);
1571}
1572
1573NrGnbCmacSapProvider::RachConfig
1574NrGnbMac::DoGetRachConfig()
1575{
1576 NS_LOG_FUNCTION(this);
1577 struct NrGnbCmacSapProvider::RachConfig rc;
1578 rc.numberOfRaPreambles = m_numberOfRaPreambles;
1579 rc.preambleTransMax = m_preambleTransMax;
1580 rc.raResponseWindowSize = m_raResponseWindowSize;
1581 rc.connEstFailCount = m_connEstFailCount;
1582 return rc;
1583}
1584
1585NrGnbCmacSapProvider::AllocateNcRaPreambleReturnValue
1586NrGnbMac::DoAllocateNcRaPreamble(uint16_t rnti)
1587{
1588 bool found = false;
1589 uint8_t preambleId;
1590 for (preambleId = m_numberOfRaPreambles; preambleId < 64; ++preambleId)
1591 {
1592 std::map<uint8_t, NcRaPreambleInfo>::iterator it =
1593 m_allocatedNcRaPreambleMap.find(preambleId);
1605 if ((it != m_allocatedNcRaPreambleMap.end()) && (it->second.expiryTime < Simulator::Now()))
1606 {
1607 if (!m_cmacSapUser->IsRandomAccessCompleted(it->second.rnti))
1608 {
1609 // random access of the UE is not completed,
1610 // check other preambles
1611 continue;
1612 }
1613 }
1614 if ((it == m_allocatedNcRaPreambleMap.end()) || (it->second.expiryTime < Simulator::Now()))
1615 {
1616 found = true;
1617 NcRaPreambleInfo preambleInfo;
1618 uint32_t expiryIntervalMs =
1619 (uint32_t)m_preambleTransMax * ((uint32_t)m_raResponseWindowSize + 5);
1620
1621 preambleInfo.expiryTime = Simulator::Now() + MilliSeconds(expiryIntervalMs);
1622 preambleInfo.rnti = rnti;
1623 NS_LOG_INFO("allocated preamble for NC based RA: preamble "
1624 << preambleId << ", RNTI " << preambleInfo.rnti << ", exiryTime "
1625 << preambleInfo.expiryTime);
1626 m_allocatedNcRaPreambleMap[preambleId] =
1627 preambleInfo; // create if not exist, update otherwise
1628 break;
1629 }
1630 }
1631 NrGnbCmacSapProvider::AllocateNcRaPreambleReturnValue ret;
1632 if (found)
1633 {
1634 ret.valid = true;
1635 ret.raPreambleId = preambleId;
1636 ret.raPrachMaskIndex = 0;
1637 }
1638 else
1639 {
1640 ret.valid = false;
1641 ret.raPreambleId = 0;
1642 ret.raPrachMaskIndex = 0;
1643 }
1644 return ret;
1645}
1646
1647// ////////////////////////////////////////////
1648// CSCHED SAP
1649// ////////////////////////////////////////////
1650
1651void
1652NrGnbMac::DoCschedCellConfigCnf(NrMacCschedSapUser::CschedCellConfigCnfParameters params)
1653{
1654 NS_LOG_FUNCTION(this);
1655}
1656
1657void
1658NrGnbMac::DoCschedUeConfigCnf(NrMacCschedSapUser::CschedUeConfigCnfParameters params)
1659{
1660 NS_LOG_FUNCTION(this);
1661}
1662
1663void
1664NrGnbMac::DoCschedLcConfigCnf(NrMacCschedSapUser::CschedLcConfigCnfParameters params)
1665{
1666 NS_LOG_FUNCTION(this);
1667 // Call the CSCHED primitive
1668 // m_cschedSap->LcConfigCompleted();
1669}
1670
1671void
1672NrGnbMac::DoCschedLcReleaseCnf(NrMacCschedSapUser::CschedLcReleaseCnfParameters params)
1673{
1674 NS_LOG_FUNCTION(this);
1675}
1676
1677void
1678NrGnbMac::DoCschedUeReleaseCnf(NrMacCschedSapUser::CschedUeReleaseCnfParameters params)
1679{
1680 NS_LOG_FUNCTION(this);
1681}
1682
1683void
1684NrGnbMac::DoCschedUeConfigUpdateInd(NrMacCschedSapUser::CschedUeConfigUpdateIndParameters params)
1685{
1686 NS_LOG_FUNCTION(this);
1687 // propagates to RRC
1688 NrGnbCmacSapUser::UeConfig ueConfigUpdate;
1689 ueConfigUpdate.m_rnti = params.m_rnti;
1690 ueConfigUpdate.m_transmissionMode = params.m_transmissionMode;
1691 m_cmacSapUser->RrcConfigurationUpdateInd(ueConfigUpdate);
1692}
1693
1694void
1695NrGnbMac::DoCschedCellConfigUpdateInd(
1696 NrMacCschedSapUser::CschedCellConfigUpdateIndParameters params)
1697{
1698 NS_LOG_FUNCTION(this);
1699}
1700
1701} // namespace ns3
Representation of a beam id.
Definition beam-id.h:26
GnbMacMemberNrMacSapProvider class.
Definition nr-mac-sap.h:190
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:170
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.