5G-LENA nr-v3.3-120-gdac69c56
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-ue-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() << ", rnti " \
9 << m_rnti << "] "; \
10 } while (false);
11
12#include "nr-ue-mac.h"
13
14#include "nr-control-messages.h"
15#include "nr-mac-header-vs.h"
16#include "nr-mac-short-bsr-ce.h"
17#include "nr-phy-sap.h"
18#include "nr-radio-bearer-tag.h"
19
20#include "ns3/boolean.h"
21#include "ns3/log.h"
22#include "ns3/random-variable-stream.h"
23#include "ns3/uinteger.h"
24
25namespace ns3
26{
27
28NS_LOG_COMPONENT_DEFINE("NrUeMac");
29NS_OBJECT_ENSURE_REGISTERED(NrUeMac);
30
31uint8_t NrUeMac::g_raPreambleId = 0;
32
34// SAP forwarders
36
37class UeMemberNrUeCmacSapProvider : public NrUeCmacSapProvider
38{
39 public:
40 UeMemberNrUeCmacSapProvider(NrUeMac* mac);
41
42 // inherited from NrUeCmacSapProvider
43 void ConfigureRach(RachConfig rc) override;
44 void StartContentionBasedRandomAccessProcedure() override;
45 void StartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
46 uint8_t preambleId,
47 uint8_t prachMask) override;
48 void AddLc(uint8_t lcId,
49 NrUeCmacSapProvider::LogicalChannelConfig lcConfig,
50 NrMacSapUser* msu) override;
51 void RemoveLc(uint8_t lcId) override;
52 void Reset() override;
53 void SetRnti(uint16_t rnti) override;
54 void NotifyConnectionSuccessful() override;
55 void SetImsi(uint64_t imsi) override;
56
57 private:
58 NrUeMac* m_mac;
59};
60
61UeMemberNrUeCmacSapProvider::UeMemberNrUeCmacSapProvider(NrUeMac* mac)
62 : m_mac(mac)
63{
64}
65
66void
67UeMemberNrUeCmacSapProvider::ConfigureRach(RachConfig rc)
68{
69 m_mac->DoConfigureRach(rc);
70}
71
72void
73UeMemberNrUeCmacSapProvider::StartContentionBasedRandomAccessProcedure()
74{
75 m_mac->DoStartContentionBasedRandomAccessProcedure();
76}
77
78void
79UeMemberNrUeCmacSapProvider::StartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
80 uint8_t preambleId,
81 uint8_t prachMask)
82{
83 m_mac->DoStartNonContentionBasedRandomAccessProcedure(rnti, preambleId, prachMask);
84}
85
86void
87UeMemberNrUeCmacSapProvider::AddLc(uint8_t lcId, LogicalChannelConfig lcConfig, NrMacSapUser* msu)
88{
89 m_mac->AddLc(lcId, lcConfig, msu);
90}
91
92void
93UeMemberNrUeCmacSapProvider::RemoveLc(uint8_t lcid)
94{
95 m_mac->DoRemoveLc(lcid);
96}
97
98void
99UeMemberNrUeCmacSapProvider::Reset()
100{
101 m_mac->DoReset();
102}
103
104void
105UeMemberNrUeCmacSapProvider::SetRnti(uint16_t rnti)
106{
107 m_mac->SetRnti(rnti);
108}
109
110void
111UeMemberNrUeCmacSapProvider::NotifyConnectionSuccessful()
112{
113 m_mac->DoNotifyConnectionSuccessful();
114}
115
116void
117UeMemberNrUeCmacSapProvider::SetImsi(uint64_t imsi)
118{
119 m_mac->DoSetImsi(imsi);
120}
121
122class UeMemberNrMacSapProvider : public NrMacSapProvider
123{
124 public:
125 UeMemberNrMacSapProvider(NrUeMac* mac);
126
127 // inherited from NrMacSapProvider
128 void TransmitPdu(TransmitPduParameters params) override;
129 void ReportBufferStatus(ReportBufferStatusParameters params) override;
130
131 private:
132 NrUeMac* m_mac;
133};
134
135UeMemberNrMacSapProvider::UeMemberNrMacSapProvider(NrUeMac* mac)
136 : m_mac(mac)
137{
138}
139
140void
141UeMemberNrMacSapProvider::TransmitPdu(TransmitPduParameters params)
142{
143 m_mac->DoTransmitPdu(params);
144}
145
146void
147UeMemberNrMacSapProvider::ReportBufferStatus(ReportBufferStatusParameters params)
148{
149 m_mac->DoReportBufferStatus(params);
150}
151
152class NrUePhySapUser;
153
154class MacUeMemberPhySapUser : public NrUePhySapUser
155{
156 public:
157 MacUeMemberPhySapUser(NrUeMac* mac);
158
159 void ReceivePhyPdu(Ptr<Packet> p) override;
160
161 void ReceiveControlMessage(Ptr<NrControlMessage> msg) override;
162
163 void SlotIndication(SfnSf sfn) override;
164
165 // virtual void NotifyHarqDeliveryFailure (uint8_t harqId);
166
167 uint8_t GetNumHarqProcess() const override;
168
169 private:
170 NrUeMac* m_mac;
171};
172
173MacUeMemberPhySapUser::MacUeMemberPhySapUser(NrUeMac* mac)
174 : m_mac(mac)
175{
176}
177
178void
179MacUeMemberPhySapUser::ReceivePhyPdu(Ptr<Packet> p)
180{
181 m_mac->DoReceivePhyPdu(p);
182}
183
184void
185MacUeMemberPhySapUser::ReceiveControlMessage(Ptr<NrControlMessage> msg)
186{
187 m_mac->DoReceiveControlMessage(msg);
188}
189
190void
191MacUeMemberPhySapUser::SlotIndication(SfnSf sfn)
192{
193 m_mac->DoSlotIndication(sfn);
194}
195
196uint8_t
197MacUeMemberPhySapUser::GetNumHarqProcess() const
198{
199 return m_mac->GetNumHarqProcess();
200}
201
202//-----------------------------------------------------------------------
203
204TypeId
205NrUeMac::GetTypeId()
206{
207 static TypeId tid =
208 TypeId("ns3::NrUeMac")
209 .SetParent<Object>()
210 .AddConstructor<NrUeMac>()
211 .AddAttribute(
212 "NumHarqProcess",
213 "Number of concurrent stop-and-wait Hybrid ARQ processes per user",
214 UintegerValue(16),
215 MakeUintegerAccessor(&NrUeMac::SetNumHarqProcess, &NrUeMac::GetNumHarqProcess),
216 MakeUintegerChecker<uint8_t>())
217 .AddTraceSource("UeMacRxedCtrlMsgsTrace",
218 "Ue MAC Control Messages Traces.",
219 MakeTraceSourceAccessor(&NrUeMac::m_macRxedCtrlMsgsTrace),
220 "ns3::NrMacRxTrace::RxedUeMacCtrlMsgsTracedCallback")
221 .AddTraceSource("UeMacTxedCtrlMsgsTrace",
222 "Ue MAC Control Messages Traces.",
223 MakeTraceSourceAccessor(&NrUeMac::m_macTxedCtrlMsgsTrace),
224 "ns3::NrMacRxTrace::TxedUeMacCtrlMsgsTracedCallback")
225 .AddTraceSource("RaResponseTimeout",
226 "Trace fired upon RA response timeout",
227 MakeTraceSourceAccessor(&NrUeMac::m_raResponseTimeoutTrace),
228 "ns3::NrUeMac::RaResponseTimeoutTracedCallback");
229 return tid;
230}
231
232NrUeMac::NrUeMac()
233 : Object()
234{
235 NS_LOG_FUNCTION(this);
236 m_cmacSapProvider = new UeMemberNrUeCmacSapProvider(this);
237 m_macSapProvider = new UeMemberNrMacSapProvider(this);
238 m_phySapUser = new MacUeMemberPhySapUser(this);
239 m_raPreambleUniformVariable = CreateObject<UniformRandomVariable>();
240}
241
245
246void
248{
249 m_miUlHarqProcessesPacket.clear();
250 m_miUlHarqProcessesPacketTimer.clear();
251 m_ulBsrReceived.clear();
252 m_lcInfoMap.clear();
253 m_raPreambleUniformVariable = nullptr;
254 delete m_macSapProvider;
255 delete m_cmacSapProvider;
256 delete m_phySapUser;
257}
258
259void
260NrUeMac::SetRnti(uint16_t rnti)
261{
262 NS_LOG_FUNCTION(this);
263 m_rnti = rnti;
264}
265
266void
267NrUeMac::DoNotifyConnectionSuccessful()
268{
269 NS_LOG_FUNCTION(this);
270 m_phySapProvider->NotifyConnectionSuccessful();
271}
272
273void
274NrUeMac::DoSetImsi(uint64_t imsi)
275{
276 NS_LOG_FUNCTION(this);
277 m_imsi = imsi;
278}
279
280uint16_t
282{
283 if (m_phySapProvider)
284 {
285 return m_phySapProvider->GetBwpId();
286 }
287 else
288 {
289 return UINT16_MAX;
290 }
291}
292
293uint16_t
295{
296 if (m_phySapProvider)
297 {
298 return m_phySapProvider->GetCellId();
299 }
300 else
301 {
302 return UINT16_MAX;
303 }
304}
305
306uint16_t
308{
309 return m_rnti;
310}
311
312uint64_t
314{
315 return m_imsi;
316}
317
318void
320{
321 m_currentSlot = sfn;
322}
323
324uint32_t
325NrUeMac::GetTotalBufSize() const
326{
327 uint32_t ret = 0;
328 for (const auto& it : m_ulBsrReceived)
329 {
330 ret += (it.second.txQueueSize + it.second.retxQueueSize + it.second.statusPduSize);
331 }
332 return ret;
333}
334
339void
340NrUeMac::SetNumHarqProcess(uint8_t numHarqProcess)
341{
342 m_numHarqProcess = numHarqProcess;
343
344 m_miUlHarqProcessesPacket.resize(GetNumHarqProcess());
345 for (auto& i : m_miUlHarqProcessesPacket)
346 {
347 if (i.m_pktBurst == nullptr)
348 {
349 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
350 i.m_pktBurst = pb;
351 }
352 }
353 m_miUlHarqProcessesPacketTimer.resize(GetNumHarqProcess(), 0);
354}
355
359uint8_t
361{
362 return m_numHarqProcess;
363}
364
365// forwarded from MAC SAP
366void
367NrUeMac::DoTransmitPdu(NrMacSapProvider::TransmitPduParameters params)
368{
369 NS_LOG_FUNCTION(this);
370 if (m_ulDci == nullptr)
371 {
372 return;
373 }
374 NS_ASSERT(m_ulDci);
375 NS_ASSERT(m_ulDci->m_harqProcess == params.harqProcessId);
376
377 m_miUlHarqProcessesPacket.at(params.harqProcessId).m_lcidList.push_back(params.lcid);
378
379 NrMacHeaderVs header;
380 header.SetLcId(params.lcid);
381 header.SetSize(params.pdu->GetSize());
382
383 params.pdu->AddHeader(header);
384
385 NrRadioBearerTag bearerTag(params.rnti, params.lcid, 0);
386 params.pdu->AddPacketTag(bearerTag);
387
388 if (!m_miUlHarqProcessesPacket.at(params.harqProcessId).m_pktBurst)
389 {
390 m_miUlHarqProcessesPacket.at(params.harqProcessId).m_pktBurst = CreateObject<PacketBurst>();
391 }
392 m_miUlHarqProcessesPacket.at(params.harqProcessId).m_pktBurst->AddPacket(params.pdu);
393 m_miUlHarqProcessesPacketTimer.at(params.harqProcessId) = GetNumHarqProcess();
394
395 m_ulDciTotalUsed += params.pdu->GetSize();
396
397 NS_ASSERT_MSG(m_ulDciTotalUsed <= m_ulDci->m_tbSize,
398 "We used more data than the DCI allowed us.");
399
400 m_phySapProvider->SendMacPdu(params.pdu, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
401}
402
403void
404NrUeMac::DoReportBufferStatus(NrMacSapProvider::ReportBufferStatusParameters params)
405{
406 NS_LOG_FUNCTION(this << static_cast<uint32_t>(params.lcid));
407
408 auto it = m_ulBsrReceived.find(params.lcid);
409
410 NS_LOG_INFO("Received BSR for LC Id" << static_cast<uint32_t>(params.lcid));
411
412 if (it != m_ulBsrReceived.end())
413 {
414 // update entry
415 (*it).second = params;
416 }
417 else
418 {
419 it = m_ulBsrReceived.insert(std::make_pair(params.lcid, params)).first;
420 }
421
422 if (m_srState == INACTIVE || (params.expRbsTimer && m_srState == ACTIVE))
423 {
424 NS_LOG_INFO("INACTIVE -> TO_SEND, bufSize " << GetTotalBufSize());
425 m_srState = TO_SEND;
426 }
427}
428
429void
430NrUeMac::SendReportBufferStatus(const SfnSf& dataSfn, uint8_t symStart)
431{
432 NS_LOG_FUNCTION(this);
433
434 if (m_rnti == 0)
435 {
436 NS_LOG_INFO("MAC not initialized, BSR deferred");
437 return;
438 }
439
440 if (m_ulBsrReceived.empty())
441 {
442 NS_LOG_INFO("No BSR report to transmit");
443 return;
444 }
445 MacCeElement bsr = MacCeElement();
446 bsr.m_rnti = m_rnti;
447 bsr.m_macCeType = MacCeElement::BSR;
448
449 // BSR is reported for each LCG
450 std::unordered_map<uint8_t, NrMacSapProvider::ReportBufferStatusParameters>::iterator it;
451 std::vector<uint32_t> queue(4, 0); // one value per each of the 4 LCGs, initialized to 0
452 for (it = m_ulBsrReceived.begin(); it != m_ulBsrReceived.end(); it++)
453 {
454 uint8_t lcid = it->first;
455 std::unordered_map<uint8_t, LcInfo>::iterator lcInfoMapIt;
456 lcInfoMapIt = m_lcInfoMap.find(lcid);
457 NS_ASSERT(lcInfoMapIt != m_lcInfoMap.end());
458 NS_ASSERT_MSG((lcid != 0) ||
459 (((*it).second.txQueueSize == 0) && ((*it).second.retxQueueSize == 0) &&
460 ((*it).second.statusPduSize == 0)),
461 "BSR should not be used for LCID 0");
462 uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
463 queue.at(lcg) +=
464 ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
465
466 if (queue.at(lcg) != 0)
467 {
468 NS_LOG_DEBUG("Adding 5 bytes for SHORT_BSR.");
469 queue.at(lcg) += 5;
470 }
471 if ((*it).second.txQueueSize > 0)
472 {
473 NS_LOG_DEBUG("Adding 3 bytes for TX subheader.");
474 queue.at(lcg) += 3;
475 }
476 if ((*it).second.retxQueueSize > 0)
477 {
478 NS_LOG_DEBUG("Adding 3 bytes for RX subheader.");
479 queue.at(lcg) += 3;
480 }
481 }
482
483 NS_LOG_INFO("Sending BSR with this info for the LCG: "
484 << queue.at(0) << " " << queue.at(1) << " " << queue.at(2) << " " << queue.at(3));
485 // FF API says that all 4 LCGs are always present
486 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(0)));
487 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(1)));
488 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(2)));
489 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(3)));
490
491 // create the message. It is used only for tracing, but we don't send it...
492 Ptr<NrBsrMessage> msg = Create<NrBsrMessage>();
493 msg->SetSourceBwp(GetBwpId());
494 msg->SetBsr(bsr);
495
496 m_macTxedCtrlMsgsTrace(m_currentSlot, GetCellId(), bsr.m_rnti, GetBwpId(), msg);
497
498 // Here we send the real SHORT_BSR, as a subpdu.
499 Ptr<Packet> p = Create<Packet>();
500
501 // Please note that the levels are defined from the standard. In this case,
502 // we have 5 bit available, so use such standard levels. In the future,
503 // when LONG BSR will be implemented, this have to change.
504 NrMacShortBsrCe header;
505 header.m_bufferSizeLevel_0 = NrMacShortBsrCe::FromBytesToLevel(queue.at(0));
506 header.m_bufferSizeLevel_1 = NrMacShortBsrCe::FromBytesToLevel(queue.at(1));
507 header.m_bufferSizeLevel_2 = NrMacShortBsrCe::FromBytesToLevel(queue.at(2));
508 header.m_bufferSizeLevel_3 = NrMacShortBsrCe::FromBytesToLevel(queue.at(3));
509
510 p->AddHeader(header);
511
512 NrRadioBearerTag bearerTag(m_rnti, NrMacHeaderFsUl::SHORT_BSR, 0);
513 p->AddPacketTag(bearerTag);
514
515 m_ulDciTotalUsed += p->GetSize();
516 NS_ASSERT_MSG(m_ulDciTotalUsed <= m_ulDci->m_tbSize,
517 "We used more data than the DCI allowed us.");
518
519 m_phySapProvider->SendMacPdu(p, dataSfn, symStart, m_ulDci->m_rnti);
520}
521
522void
524{
525 m_cmacSapUser = s;
526}
527
530{
531 return m_cmacSapProvider;
532}
533
534void
535NrUeMac::RefreshHarqProcessesPacketBuffer()
536{
537 NS_LOG_FUNCTION(this);
538
539 for (std::size_t i = 0; i < m_miUlHarqProcessesPacketTimer.size(); i++)
540 {
541 if (m_miUlHarqProcessesPacketTimer.at(i) == 0 && m_miUlHarqProcessesPacket.at(i).m_pktBurst)
542 {
543 if (m_miUlHarqProcessesPacket.at(i).m_pktBurst->GetSize() > 0)
544 {
545 // timer expired: drop packets in buffer for this process
546 NS_LOG_INFO("HARQ Proc Id " << i << " packets buffer expired");
547 Ptr<PacketBurst> emptyPb = CreateObject<PacketBurst>();
548 m_miUlHarqProcessesPacket.at(i).m_pktBurst = emptyPb;
549 m_miUlHarqProcessesPacket.at(i).m_lcidList.clear();
550 }
551 }
552 else
553 {
554 // m_miUlHarqProcessesPacketTimer.at (i)--; // ignore HARQ timeout
555 }
556 }
557}
558
559void
560NrUeMac::DoSlotIndication(const SfnSf& sfn)
561{
562 NS_LOG_FUNCTION(this);
563 m_currentSlot = sfn;
564 NS_LOG_INFO("Slot " << m_currentSlot);
565
566 RefreshHarqProcessesPacketBuffer();
567
568 if (m_srState == TO_SEND)
569 {
570 NS_LOG_INFO("Sending SR to PHY in slot " << sfn);
571 SendSR();
572 m_srState = ACTIVE;
573 }
574
575 // Feedback missing
576}
577
578void
579NrUeMac::SendSR() const
580{
581 NS_LOG_FUNCTION(this);
582
583 if (m_rnti == 0)
584 {
585 NS_LOG_INFO("MAC not initialized, SR deferred");
586 return;
587 }
588
589 // create the SR to send to the gNB
590 Ptr<NrSRMessage> msg = Create<NrSRMessage>();
591 msg->SetSourceBwp(GetBwpId());
592 msg->SetRNTI(m_rnti);
593
594 m_macTxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), msg);
595 m_phySapProvider->SendControlMessage(msg);
596}
597
598void
599NrUeMac::DoReceivePhyPdu(Ptr<Packet> p)
600{
601 NS_LOG_FUNCTION(this);
602
603 NrRadioBearerTag tag;
604 p->RemovePacketTag(tag);
605
606 if (tag.GetRnti() != m_rnti) // Packet is for another user
607 {
608 return;
609 }
610
611 NrMacHeaderVs header;
612 p->RemoveHeader(header);
613
614 NrMacSapUser::ReceivePduParameters rxParams;
615 rxParams.p = p;
616 rxParams.rnti = m_rnti;
617 rxParams.lcid = header.GetLcId();
618
619 auto it = m_lcInfoMap.find(header.GetLcId());
620 // Ignore non-existing lcids
621 if (it == m_lcInfoMap.end())
622 {
623 return;
624 }
625
626 // p can be empty. Well, right now no, but when someone will add CE in downlink,
627 // then p can be empty.
628 if (rxParams.p->GetSize() > 0)
629 {
630 it->second.macSapUser->ReceivePdu(rxParams);
631 }
632}
633
634void
635NrUeMac::RecvRaResponse(NrBuildRarListElement_s raResponse)
636{
637 NS_LOG_FUNCTION(this);
638 m_waitingForRaResponse = false;
639 m_noRaResponseReceivedEvent.Cancel();
640 NS_LOG_INFO(" IMSI " << m_imsi << " RNTI " << m_rnti << " received RAR for RA preamble ID "
641 << +m_raPreambleId
642 << ", setting T-C-RNTI = " << raResponse.ulMsg3Dci->m_rnti
643 << " at: " << Simulator::Now().As(Time::MS));
644 m_rnti = raResponse.ulMsg3Dci->m_rnti;
645 m_cmacSapUser->SetTemporaryCellRnti(m_rnti);
646 // in principle we should wait for contention resolution,
647 // but in the current NR model when two or more identical
648 // preambles are sent no one is received, so there is no need
649 // for contention resolution
650 m_cmacSapUser->NotifyRandomAccessSuccessful();
651 // Trigger Tx opportunity for Message 3 over LC 0
652 // this is needed since Message 3's UL GRANT is in the RAR, not in UL-DCIs
653 const uint8_t lc0Lcid = 0;
654 auto lc0InfoIt = m_lcInfoMap.find(lc0Lcid);
655 NS_ASSERT_MSG(lc0InfoIt != m_lcInfoMap.end(),
656 "LC0 not mapped to this UE MAC with bwpId:" << GetBwpId());
657 auto lc0BsrIt = m_ulBsrReceived.find(lc0Lcid);
658 if ((lc0BsrIt != m_ulBsrReceived.end()) && (lc0BsrIt->second.txQueueSize > 0))
659 {
660 NS_LOG_INFO(
661 "Notify RLC about transmission opportunity for sending RRC CONNECTION REQUEST.");
662 NS_ASSERT_MSG(raResponse.ulMsg3Dci->m_tbSize > lc0BsrIt->second.txQueueSize,
663 "segmentation of Message 3 is not allowed");
664 NrMacSapUser::TxOpportunityParameters txOpParams;
665 txOpParams.lcid = lc0Lcid;
666 txOpParams.rnti = m_rnti;
667 txOpParams.bytes = raResponse.ulMsg3Dci->m_tbSize;
668 txOpParams.layer = 0;
669 txOpParams.harqId = 0;
670 txOpParams.componentCarrierId = GetBwpId();
671
672 lc0InfoIt->second.macSapUser->NotifyTxOpportunity(txOpParams);
673 lc0BsrIt->second.txQueueSize = 0;
674 lc0BsrIt->second.retxQueueSize = 0;
675 lc0BsrIt->second.statusPduSize = 0;
676 m_ulBsrReceived.erase(lc0BsrIt);
677 }
678}
679
680void
681NrUeMac::ProcessUlDci(const Ptr<NrUlDciMessage>& dciMsg)
682{
683 NS_LOG_FUNCTION(this);
684
685 SfnSf dataSfn = m_currentSlot;
686 dataSfn.Add(dciMsg->GetKDelay());
687
688 // Saving the data we need in DoTransmitPdu
689 m_ulDciSfnsf = dataSfn;
690 m_ulDciTotalUsed = 0;
691 m_ulDci = dciMsg->GetDciInfoElement();
692
693 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), dciMsg);
694
695 NS_LOG_INFO("UL DCI received, transmit data in slot "
696 << dataSfn << " Harq Process " << +m_ulDci->m_harqProcess << " TBS "
697 << m_ulDci->m_tbSize << " total queue " << GetTotalBufSize());
698
699 if (m_ulDci->m_ndi == 0)
700 {
701 // This method will retransmit the data saved in the harq buffer
702 TransmitRetx();
703
704 // This method will transmit a new BSR.
705 SendReportBufferStatus(dataSfn, m_ulDci->m_symStart);
706 }
707 else if (m_ulDci->m_ndi == 1)
708 {
709 SendNewData();
710
711 NS_LOG_INFO("After sending NewData, bufSize " << GetTotalBufSize());
712
713 // Send a new BSR. SendNewData() already took into account the size of
714 // the BSR.
715 SendReportBufferStatus(dataSfn, m_ulDci->m_symStart);
716
717 NS_LOG_INFO("UL DCI processing done, sent to PHY a total of "
718 << m_ulDciTotalUsed << " B out of " << m_ulDci->m_tbSize
719 << " allocated bytes ");
720
721 if (GetTotalBufSize() == 0)
722 {
723 m_srState = INACTIVE;
724 NS_LOG_INFO("ACTIVE -> INACTIVE, bufSize " << GetTotalBufSize());
725
726 // the UE may have been scheduled, but we didn't use a single byte
727 // of the allocation. So send an empty PDU. This happens because the
728 // byte reporting in the BSR is not accurate, due to RLC and/or
729 // BSR quantization.
730 if (m_ulDciTotalUsed == 0)
731 {
732 NS_LOG_WARN("No byte used for this UL-DCI, sending empty PDU");
733
734 NrMacSapProvider::TransmitPduParameters txParams;
735
736 txParams.pdu = Create<Packet>();
737 txParams.lcid = 3;
738 txParams.rnti = m_rnti;
739 txParams.layer = 0;
740 txParams.harqProcessId = m_ulDci->m_harqProcess;
741 txParams.componentCarrierId = GetBwpId();
742
743 DoTransmitPdu(txParams);
744 }
745 }
746 }
747}
748
749void
750NrUeMac::TransmitRetx()
751{
752 NS_LOG_FUNCTION(this);
753
754 Ptr<PacketBurst> pb = m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst;
755
756 if (pb == nullptr)
757 {
758 NS_LOG_WARN(
759 "The previous transmission did not contain any new data; "
760 "probably it was BSR only. To not send an old BSR to the scheduler, "
761 "we don't send anything back in this allocation. Eventually, "
762 "the Harq timer at gnb will expire, and soon this allocation will be forgotten.");
763 return;
764 }
765
766 NS_LOG_DEBUG("UE MAC RETX HARQ " << +m_ulDci->m_harqProcess);
767
768 NS_ASSERT(pb->GetNPackets() > 0);
769
770 for (std::list<Ptr<Packet>>::const_iterator j = pb->Begin(); j != pb->End(); ++j)
771 {
772 Ptr<Packet> pkt = (*j)->Copy();
773 NrRadioBearerTag bearerTag;
774 if (!pkt->PeekPacketTag(bearerTag))
775 {
776 NS_FATAL_ERROR("No radio bearer tag");
777 }
778 m_phySapProvider->SendMacPdu(pkt, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
779 }
780
781 m_miUlHarqProcessesPacketTimer.at(m_ulDci->m_harqProcess) = GetNumHarqProcess();
782}
783
784void
785NrUeMac::SendRetxData(uint32_t usefulTbs, uint32_t activeLcsRetx)
786{
787 NS_LOG_FUNCTION(this);
788
789 if (activeLcsRetx == 0)
790 {
791 return;
792 }
793
794 uint32_t bytesPerLcId = usefulTbs / activeLcsRetx;
795
796 for (auto& itBsr : m_ulBsrReceived)
797 {
798 auto& bsr = itBsr.second;
799
800 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
801 {
802 NrMacSapUser::TxOpportunityParameters txParams;
803 txParams.lcid = bsr.lcid;
804 txParams.rnti = m_rnti;
805 txParams.bytes = bytesPerLcId;
806 txParams.layer = 0;
807 txParams.harqId = m_ulDci->m_harqProcess;
808 txParams.componentCarrierId = GetBwpId();
809
810 NS_LOG_INFO("Notifying RLC of LCID " << +bsr.lcid
811 << " of a TxOpp "
812 "of "
813 << bytesPerLcId << " B for a RETX PDU");
814
815 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
816 // After this call, m_ulDciTotalUsed has been updated with the
817 // correct amount of bytes... but it is up to us in updating the BSR
818 // value, subtracting the amount of bytes transmitted
819
820 // We need to use std::min here because bytesPerLcId can be
821 // greater than bsr.txQueueSize because scheduler can assign
822 // more bytes than needed due to how TB size is computed.
823 bsr.retxQueueSize -= std::min(bytesPerLcId, bsr.retxQueueSize);
824 }
825 else
826 {
827 NS_LOG_DEBUG("Something wrong with the calculation of overhead."
828 "Active LCS Retx: "
829 << activeLcsRetx << " assigned to this: " << bytesPerLcId
830 << ", with TBS of " << m_ulDci->m_tbSize << " usefulTbs " << usefulTbs
831 << " and total used " << m_ulDciTotalUsed);
832 }
833 }
834}
835
836void
837NrUeMac::SendTxData(uint32_t usefulTbs, uint32_t activeTx)
838{
839 NS_LOG_FUNCTION(this);
840
841 if (activeTx == 0)
842 {
843 return;
844 }
845
846 uint32_t bytesPerLcId = usefulTbs / activeTx;
847
848 for (auto& itBsr : m_ulBsrReceived)
849 {
850 auto& bsr = itBsr.second;
851
852 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
853 {
854 NrMacSapUser::TxOpportunityParameters txParams;
855 txParams.lcid = bsr.lcid;
856 txParams.rnti = m_rnti;
857 txParams.bytes = bytesPerLcId;
858 txParams.layer = 0;
859 txParams.harqId = m_ulDci->m_harqProcess;
860 txParams.componentCarrierId = GetBwpId();
861
862 NS_LOG_INFO("Notifying RLC of LCID " << +bsr.lcid
863 << " of a TxOpp "
864 "of "
865 << bytesPerLcId << " B for a TX PDU");
866
867 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
868 // After this call, m_ulDciTotalUsed has been updated with the
869 // correct amount of bytes... but it is up to us in updating the BSR
870 // value, subtracting the amount of bytes transmitted
871
872 // We need to use std::min here because bytesPerLcId can be
873 // greater than bsr.txQueueSize because scheduler can assign
874 // more bytes than needed due to how TB size is computed.
875 bsr.txQueueSize -= std::min(bytesPerLcId, bsr.txQueueSize);
876 }
877 else
878 {
879 NS_LOG_DEBUG("Something wrong with the calculation of overhead."
880 "Active LCS TX: "
881 << activeTx << " assigned to this: " << bytesPerLcId << ", with TBS of "
882 << m_ulDci->m_tbSize << " usefulTbs " << usefulTbs << " and total used "
883 << m_ulDciTotalUsed);
884 }
885 }
886}
887
888void
889NrUeMac::SendNewData()
890{
891 NS_LOG_FUNCTION(this);
892 // New transmission -> empty pkt buffer queue (for deleting eventual pkts not acked )
893 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
894 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst = pb;
895 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_lcidList.clear();
896 NS_LOG_INFO("Reset HARQP " << +m_ulDci->m_harqProcess);
897
898 // Sending the status data has no boundary: let's try to send the ACK as
899 // soon as possible, filling the TBS, if necessary.
900 SendNewStatusData();
901
902 // Let's count how many LC we have, that are waiting with some data
903 uint16_t activeLcsRetx = 0;
904 uint16_t activeLcsTx = 0;
905 for (const auto& itBsr : m_ulBsrReceived)
906 {
907 if (itBsr.second.retxQueueSize > 0)
908 {
909 activeLcsRetx++;
910 }
911 if (itBsr.second.txQueueSize > 0)
912 {
913 activeLcsTx++;
914 }
915 }
916
917 // Of the TBS we received in the DCI, one part is gone for the status pdu,
918 // where we didn't check much as it is the most important data, that has to go
919 // out. For the rest that we have left, we can use only a part of it because of
920 // the overhead of the SHORT_BSR, which is 5 bytes.
921 NS_ASSERT_MSG(m_ulDciTotalUsed + 5 <= m_ulDci->m_tbSize,
922 "The StatusPDU used " << m_ulDciTotalUsed
923 << " B, we don't have any for the SHORT_BSR.");
924 // reserve some data for the SHORT_BSR
925 uint32_t usefulTbs = m_ulDci->m_tbSize - m_ulDciTotalUsed - 5;
926
927 // Now, we have 3 bytes of overhead for each subPDU. Let's try to serve all
928 // the queues with some RETX data.
929 if (activeLcsRetx == 0 && activeLcsTx == 0 && usefulTbs > 0)
930 {
931 NS_LOG_LOGIC("This UE tx opportunity will be wasted: " << usefulTbs << " bytes.");
932 }
933
934 // this check is needed, because if there are no active LCS we should not
935 // enter into else and call the function SendRetxData
936 if (activeLcsRetx > 0 && usefulTbs > 0) // the queues with some RETX data.
937 {
938 // 10 because 3 bytes will go for MAC subheader
939 // and we should ensure to pass to RLC AM at least 7 bytes
940 if (activeLcsRetx * 10 > usefulTbs)
941 {
942 NS_LOG_DEBUG("The overhead for transmitting retx data is greater than the space for "
943 "transmitting it."
944 "Ignore the TBS of "
945 << usefulTbs << " B.");
946 }
947 else
948 {
949 usefulTbs -= activeLcsRetx * 3;
950 SendRetxData(usefulTbs, activeLcsRetx);
951 }
952 }
953
954 // Now we have to update our useful TBS for the next transmission.
955 // Remember that m_ulDciTotalUsed keep count of data and overhead that we
956 // used till now.
957 NS_ASSERT_MSG(
958 m_ulDciTotalUsed + 5 <= m_ulDci->m_tbSize,
959 "The StatusPDU and RETX sending required all space, we don't have any for the SHORT_BSR.");
960 usefulTbs = m_ulDci->m_tbSize - m_ulDciTotalUsed - 5; // Update the usefulTbs.
961
962 // The last part is for the queues with some non-RETX data. If there is no space left,
963 // then nothing.
964 if (activeLcsTx > 0 && usefulTbs > 0) // the queues with some TX data.
965 {
966 // 10 because 3 bytes will go for MAC subheader
967 // and we should ensure to pass to RLC AM at least 7 bytes
968 if (activeLcsTx * 10 > usefulTbs)
969 {
970 NS_LOG_DEBUG("The overhead for transmitting new data is greater than the space for "
971 "transmitting it."
972 "Ignore the TBS of "
973 << usefulTbs << " B.");
974 }
975 else
976 {
977 usefulTbs -= activeLcsTx * 3;
978 SendTxData(usefulTbs, activeLcsTx);
979 }
980 }
981
982 // If we did not used the packet burst, explicitly signal it to the HARQ
983 // retx, if any.
984 if (m_ulDciTotalUsed == 0)
985 {
986 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst = nullptr;
987 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_lcidList.clear();
988 }
989}
990
991void
992NrUeMac::SendNewStatusData()
993{
994 NS_LOG_FUNCTION(this);
995
996 bool hasStatusPdu = false;
997 bool sentOneStatusPdu = false;
998
999 for (auto& bsrIt : m_ulBsrReceived)
1000 {
1001 auto& bsr = bsrIt.second;
1002
1003 if (bsr.statusPduSize > 0)
1004 {
1005 hasStatusPdu = true;
1006
1007 // Check if we have room to transmit the statusPdu
1008 if (m_ulDciTotalUsed + bsr.statusPduSize <= m_ulDci->m_tbSize)
1009 {
1010 NrMacSapUser::TxOpportunityParameters txParams;
1011 txParams.lcid = bsr.lcid;
1012 txParams.rnti = m_rnti;
1013 txParams.bytes = bsr.statusPduSize;
1014 txParams.layer = 0;
1015 txParams.harqId = m_ulDci->m_harqProcess;
1016 txParams.componentCarrierId = GetBwpId();
1017
1018 NS_LOG_INFO("Notifying RLC of LCID " << +bsr.lcid
1019 << " of a TxOpp "
1020 "of "
1021 << bsr.statusPduSize << " B for a status PDU");
1022
1023 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
1024 // After this call, m_ulDciTotalUsed has been updated with the
1025 // correct amount of bytes... but it is up to us in updating the BSR
1026 // value, subtracting the amount of bytes transmitted
1027 bsr.statusPduSize = 0;
1028 sentOneStatusPdu = true;
1029 }
1030 else
1031 {
1032 NS_LOG_INFO("Cannot send StatusPdu of " << bsr.statusPduSize
1033 << " B, we already used all the TBS");
1034 }
1035 }
1036 }
1037
1038 NS_ABORT_MSG_IF(hasStatusPdu && !sentOneStatusPdu,
1039 "The TBS of size " << m_ulDci->m_tbSize
1040 << " doesn't allow us "
1041 "to send one status PDU...");
1042}
1043
1044void
1045NrUeMac::DoReceiveControlMessage(Ptr<NrControlMessage> msg)
1046{
1047 NS_LOG_FUNCTION(this << msg);
1048
1049 switch (msg->GetMessageType())
1050 {
1051 case (NrControlMessage::UL_DCI): {
1052 ProcessUlDci(DynamicCast<NrUlDciMessage>(msg));
1053 break;
1054 }
1055 case (NrControlMessage::RAR): {
1056 NS_LOG_INFO("Received RAR in slot " << m_currentSlot);
1057
1058 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), msg);
1059
1060 if (m_waitingForRaResponse)
1061 {
1062 Ptr<NrRarMessage> rarMsg = DynamicCast<NrRarMessage>(msg);
1063 NS_LOG_LOGIC("got RAR with RA-RNTI " << +rarMsg->GetRaRnti() << ", expecting "
1064 << +m_raRnti);
1065 for (auto it = rarMsg->RarListBegin(); it != rarMsg->RarListEnd(); ++it)
1066 {
1067 if (it->rarPayload.raPreambleId == m_raPreambleId)
1068 {
1069 RecvRaResponse(it->rarPayload);
1070 }
1071 }
1072 }
1073 break;
1074 }
1075
1076 default:
1077 NS_LOG_LOGIC("Control message not supported/expected");
1078 }
1079}
1080
1081NrUePhySapUser*
1083{
1084 return m_phySapUser;
1085}
1086
1087void
1089{
1090 m_phySapProvider = ptr;
1091}
1092
1093void
1094NrUeMac::RaResponseTimeout(bool contention)
1095{
1096 NS_LOG_FUNCTION(this << contention);
1097 m_waitingForRaResponse = false;
1098 // 3GPP 36.321 5.1.4
1099 ++m_preambleTransmissionCounter;
1100 // fire RA response timeout trace
1101 m_raResponseTimeoutTrace(m_imsi,
1102 contention,
1103 m_preambleTransmissionCounter,
1104 m_rachConfig.preambleTransMax + 1);
1105 if (m_preambleTransmissionCounter == m_rachConfig.preambleTransMax + 1)
1106 {
1107 NS_LOG_INFO("RAR timeout, preambleTransMax reached => giving up");
1108 m_cmacSapUser->NotifyRandomAccessFailed();
1109 }
1110 else
1111 {
1112 NS_LOG_INFO("RAR timeout while waiting for raPreambleId " << +m_raPreambleId
1113 << " re-send preamble");
1114 if (contention)
1115 {
1116 RandomlySelectAndSendRaPreamble();
1117 }
1118 else
1119 {
1120 SendRaPreamble(contention);
1121 }
1122 }
1123}
1124
1125void
1126NrUeMac::DoConfigureRach(NrUeCmacSapProvider::RachConfig rc)
1127{
1128 NS_LOG_FUNCTION(this);
1129 m_rachConfig = rc;
1130 m_rachConfigured = true;
1131}
1132
1133void
1134NrUeMac::DoStartContentionBasedRandomAccessProcedure()
1135{
1136 NS_LOG_FUNCTION(this);
1137 RandomlySelectAndSendRaPreamble();
1138}
1139
1140void
1141NrUeMac::RandomlySelectAndSendRaPreamble()
1142{
1143 NS_LOG_FUNCTION(this);
1144 // 3GPP 36.321 5.1.1
1145 NS_ASSERT_MSG(m_rachConfigured, "RACH not configured");
1146 // assume that there is no Random Access Preambles group B
1147 m_raPreambleId =
1148 m_raPreambleUniformVariable->GetInteger(0, m_rachConfig.numberOfRaPreambles - 1);
1149 NS_LOG_DEBUG(m_currentSlot << " Received System Information, send to PHY the "
1150 "RA preamble: "
1151 << m_raPreambleId);
1152 SendRaPreamble(true);
1153}
1154
1155void
1156NrUeMac::SendRaPreamble(bool contention)
1157{
1158 NS_LOG_FUNCTION(this << (uint32_t)m_raPreambleId << contention);
1159
1160 if (contention)
1161 {
1162 // m_raPreambleId = m_raPreambleUniformVariable->GetInteger (0, 64 - 1);
1163 m_raPreambleId = g_raPreambleId++;
1164 bool preambleOverflow = m_raPreambleId == 255;
1165 m_raPreambleId += preambleOverflow;
1166 g_raPreambleId += preambleOverflow;
1167 }
1168 /*raRnti should be subframeNo -1 */
1169 m_raRnti = 1;
1170
1171 // 3GPP 36.321 5.1.4
1172 m_phySapProvider->SendRachPreamble(m_raPreambleId, m_raRnti);
1173 NS_LOG_INFO(" Sent preamble id " << +m_raPreambleId
1174 << " at: " << Simulator::Now().As(Time::MS));
1175 Time raWindowBegin = m_phySapProvider->GetSlotPeriod();
1176 Time raWindowEnd = m_phySapProvider->GetSlotPeriod() * (6 + m_rachConfig.raResponseWindowSize);
1177 Simulator::Schedule(raWindowBegin, &NrUeMac::StartWaitingForRaResponse, this);
1178 m_noRaResponseReceivedEvent =
1179 Simulator::Schedule(raWindowEnd, &NrUeMac::RaResponseTimeout, this, contention);
1180
1181 // Tracing purposes
1182 Ptr<NrRachPreambleMessage> rachMsg = Create<NrRachPreambleMessage>();
1183 rachMsg->SetSourceBwp(GetBwpId());
1184 m_macTxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), rachMsg);
1185}
1186
1187void
1188NrUeMac::StartWaitingForRaResponse()
1189{
1190 NS_LOG_FUNCTION(this);
1191 m_waitingForRaResponse = true;
1192}
1193
1194void
1195NrUeMac::DoStartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
1196 [[maybe_unused]] uint8_t preambleId,
1197 uint8_t prachMask)
1198{
1199 NS_LOG_FUNCTION(this << rnti << (uint16_t)preambleId << (uint16_t)prachMask);
1200 NS_ASSERT_MSG(prachMask == 0,
1201 "requested PRACH MASK = " << (uint32_t)prachMask
1202 << ", but only PRACH MASK = 0 is supported");
1203 m_rnti = rnti;
1204 m_raPreambleId = preambleId;
1205 m_preambleTransmissionCounter = 0;
1206 bool contention = false;
1207 SendRaPreamble(contention);
1208}
1209
1210void
1211NrUeMac::AddLc(uint8_t lcId, NrUeCmacSapProvider::LogicalChannelConfig lcConfig, NrMacSapUser* msu)
1212{
1213 NS_LOG_FUNCTION(this << " lcId" << (uint32_t)lcId);
1214 NS_ASSERT_MSG(m_lcInfoMap.find(lcId) == m_lcInfoMap.end(),
1215 "cannot add channel because LCID " << (uint16_t)lcId << " is already present");
1216
1217 LcInfo lcInfo;
1218 lcInfo.lcConfig = lcConfig;
1219 lcInfo.macSapUser = msu;
1220 m_lcInfoMap[lcId] = lcInfo;
1221}
1222
1223void
1224NrUeMac::DoRemoveLc(uint8_t lcId)
1225{
1226 NS_LOG_FUNCTION(this << " lcId" << lcId);
1227 NS_ASSERT_MSG(m_lcInfoMap.find(lcId) != m_lcInfoMap.end(),
1228 "could not find LCID " << (uint16_t)lcId);
1229 m_lcInfoMap.erase(lcId);
1230 m_ulBsrReceived.erase(lcId); // empty BSR buffer for this lcId
1231 // for (auto& harqProcess: m_miUlHarqProcessesPacket)
1232 //{
1233 // uint32_t packets = harqProcess.m_pktBurst->GetNPackets();
1234 // auto itPackets = harqProcess.m_pktBurst->GetPackets();
1235 // for (uint32_t p = 0; p < packets; p++)
1236 // {
1237 // uint32_t i = packets-p-1;
1238 // if (harqProcess.m_lcidList.at(i) == lcId)
1239 // {
1240 // // how to erase from packetburst?
1241 // //auto it = itPackets.begin();
1242 // //std::advance(it, i);
1243 // //harqProcess.m_pktBurst->GetPackets().erase(it);
1244 // auto it2 = harqProcess.m_lcidList.begin();
1245 // std::advance(it2, i);
1246 // harqProcess.m_lcidList.erase(it2);
1247 // }
1248 // }
1249 // }
1250}
1251
1252NrMacSapProvider*
1254{
1255 return m_macSapProvider;
1256}
1257
1258void
1259NrUeMac::DoReset()
1260{
1261 NS_LOG_FUNCTION(this);
1262 auto it = m_lcInfoMap.begin();
1263 while (it != m_lcInfoMap.end())
1264 {
1265 // don't delete CCCH)
1266 if (it->first == 0)
1267 {
1268 ++it;
1269 }
1270 else
1271 {
1272 // note: use of postfix operator preserves validity of iterator
1273 m_lcInfoMap.erase(it++);
1274 }
1275 }
1276 // note: rnti will be assigned by the gNB using RA response message
1277 m_rnti = 0;
1278 m_noRaResponseReceivedEvent.Cancel();
1279 m_rachConfigured = false;
1280 m_ulBsrReceived.clear();
1281}
1282
1284
1285int64_t
1287{
1288 return DoAssignStreams(stream);
1289}
1290
1291int64_t
1293{
1294 NS_LOG_FUNCTION(this << stream);
1295 m_raPreambleUniformVariable->SetStream(stream);
1296 return 1;
1297}
1298
1299} // namespace ns3
@ UL_DCI
The resources allocation map from the BS to the attached UEs (UL)
@ RAR
Random Access Response.
static const uint8_t SHORT_BSR
Short BSR.
static uint8_t FromBytesToLevel(uint64_t bufferSize)
Convert a bytes value into the 3GPP-standard level to write in the BSR.
SAP interface between the MAC and the PHY.
Definition nr-phy-sap.h:36
virtual Time GetSlotPeriod() const =0
Retrieve the slot period.
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 void SendControlMessage(Ptr< NrControlMessage > msg)=0
Send a control message.
virtual void NotifyConnectionSuccessful()=0
Notify PHY about the successful RRC connection establishment.
virtual uint16_t GetBwpId() const =0
Retrieve the bandwidth part id.
virtual void SendRachPreamble(uint8_t PreambleId, uint8_t Rnti)=0
Send the RACH preamble.
virtual void NotifyRandomAccessSuccessful()=0
virtual void SetTemporaryCellRnti(uint16_t rnti)=0
virtual void NotifyRandomAccessFailed()=0
void SetCurrentSlot(const SfnSf &sfn)
Set the frame/subframe/slot counter.
Definition nr-ue-mac.cc:319
NrUePhySapUser * GetPhySapUser()
Get the PHY SAP User (AKA the MAC representation for the PHY)
uint64_t GetImsi() const
Get the IMSI.
Definition nr-ue-mac.cc:313
void DoDispose() override
DoDispose method inherited from Object.
Definition nr-ue-mac.cc:247
void SetPhySapProvider(NrPhySapProvider *ptr)
Set PHY SAP provider (AKA the PHY representation for the MAC)
uint8_t GetNumHarqProcess() const
Please remember that this number is obtained by the GNB, the UE cannot configure it.
Definition nr-ue-mac.cc:360
NrMacSapProvider * GetUeMacSapProvider()
Get the Mac SAP provider (AKA the MAC representation for the RLC)
virtual int64_t DoAssignStreams(int64_t stream)
void SetNumHarqProcess(uint8_t numHarqProcesses)
Sets the number of HARQ processes. Called by the helper at the moment of UE attachment.
Definition nr-ue-mac.cc:340
NrUeCmacSapProvider * GetUeCmacSapProvider()
Get the C MAC SAP provider (AKA the MAC representation for the RRC)
Definition nr-ue-mac.cc:529
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model....
uint16_t GetCellId() const
Get the cell id of this MAC.
Definition nr-ue-mac.cc:294
uint16_t GetBwpId() const
Get the bwp id of this MAC.
Definition nr-ue-mac.cc:281
uint16_t GetRnti() const
Get the RNTI.
Definition nr-ue-mac.cc:307
void SetUeCmacSapUser(NrUeCmacSapUser *s)
Set the C MAC SAP user (AKA the RRC representation for the MAC)
Definition nr-ue-mac.cc:523
~NrUeMac() override
Deconstructor.
Definition nr-ue-mac.cc:242
The SfnSf class.
Definition sfnsf.h:32
void Add(uint32_t slotN)
Add to this SfnSf a number of slot indicated by the first parameter.
Definition sfnsf.cc:117
uint8_t preambleTransMax
preamble transmit maximum
uint8_t raResponseWindowSize
RA response window size.
uint8_t numberOfRaPreambles
number of RA preambles