5#define NS_LOG_APPEND_CONTEXT \
8 std::clog << " [ CellId " << GetCellId() << ", bwpId " << GetBwpId() << ", rnti " \
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"
20#include "ns3/boolean.h"
22#include "ns3/random-variable-stream.h"
23#include "ns3/uinteger.h"
28NS_LOG_COMPONENT_DEFINE(
"NrUeMac");
29NS_OBJECT_ENSURE_REGISTERED(NrUeMac);
31uint8_t NrUeMac::g_raPreambleId = 0;
37class UeMemberNrUeCmacSapProvider :
public NrUeCmacSapProvider
40 UeMemberNrUeCmacSapProvider(NrUeMac* mac);
43 void ConfigureRach(RachConfig rc)
override;
44 void StartContentionBasedRandomAccessProcedure()
override;
45 void StartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
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;
61UeMemberNrUeCmacSapProvider::UeMemberNrUeCmacSapProvider(NrUeMac* mac)
67UeMemberNrUeCmacSapProvider::ConfigureRach(RachConfig rc)
69 m_mac->DoConfigureRach(rc);
73UeMemberNrUeCmacSapProvider::StartContentionBasedRandomAccessProcedure()
75 m_mac->DoStartContentionBasedRandomAccessProcedure();
79UeMemberNrUeCmacSapProvider::StartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
83 m_mac->DoStartNonContentionBasedRandomAccessProcedure(rnti, preambleId, prachMask);
87UeMemberNrUeCmacSapProvider::AddLc(uint8_t lcId, LogicalChannelConfig lcConfig, NrMacSapUser* msu)
89 m_mac->AddLc(lcId, lcConfig, msu);
93UeMemberNrUeCmacSapProvider::RemoveLc(uint8_t lcid)
95 m_mac->DoRemoveLc(lcid);
99UeMemberNrUeCmacSapProvider::Reset()
105UeMemberNrUeCmacSapProvider::SetRnti(uint16_t rnti)
107 m_mac->SetRnti(rnti);
111UeMemberNrUeCmacSapProvider::NotifyConnectionSuccessful()
113 m_mac->DoNotifyConnectionSuccessful();
117UeMemberNrUeCmacSapProvider::SetImsi(uint64_t imsi)
119 m_mac->DoSetImsi(imsi);
122class UeMemberNrMacSapProvider :
public NrMacSapProvider
125 UeMemberNrMacSapProvider(NrUeMac* mac);
128 void TransmitPdu(TransmitPduParameters params)
override;
129 void ReportBufferStatus(ReportBufferStatusParameters params)
override;
135UeMemberNrMacSapProvider::UeMemberNrMacSapProvider(NrUeMac* mac)
141UeMemberNrMacSapProvider::TransmitPdu(TransmitPduParameters params)
143 m_mac->DoTransmitPdu(params);
147UeMemberNrMacSapProvider::ReportBufferStatus(ReportBufferStatusParameters params)
149 m_mac->DoReportBufferStatus(params);
154class MacUeMemberPhySapUser :
public NrUePhySapUser
157 MacUeMemberPhySapUser(NrUeMac* mac);
159 void ReceivePhyPdu(Ptr<Packet> p)
override;
161 void ReceiveControlMessage(Ptr<NrControlMessage> msg)
override;
163 void SlotIndication(SfnSf sfn)
override;
167 uint8_t GetNumHarqProcess()
const override;
173MacUeMemberPhySapUser::MacUeMemberPhySapUser(NrUeMac* mac)
179MacUeMemberPhySapUser::ReceivePhyPdu(Ptr<Packet> p)
181 m_mac->DoReceivePhyPdu(p);
185MacUeMemberPhySapUser::ReceiveControlMessage(Ptr<NrControlMessage> msg)
187 m_mac->DoReceiveControlMessage(msg);
191MacUeMemberPhySapUser::SlotIndication(SfnSf sfn)
193 m_mac->DoSlotIndication(sfn);
197MacUeMemberPhySapUser::GetNumHarqProcess()
const
199 return m_mac->GetNumHarqProcess();
208 TypeId(
"ns3::NrUeMac")
210 .AddConstructor<NrUeMac>()
213 "Number of concurrent stop-and-wait Hybrid ARQ processes per user",
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");
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>();
249 m_miUlHarqProcessesPacket.clear();
250 m_miUlHarqProcessesPacketTimer.clear();
251 m_ulBsrReceived.clear();
253 m_raPreambleUniformVariable =
nullptr;
254 delete m_macSapProvider;
255 delete m_cmacSapProvider;
260NrUeMac::SetRnti(uint16_t rnti)
262 NS_LOG_FUNCTION(
this);
267NrUeMac::DoNotifyConnectionSuccessful()
269 NS_LOG_FUNCTION(
this);
274NrUeMac::DoSetImsi(uint64_t imsi)
276 NS_LOG_FUNCTION(
this);
283 if (m_phySapProvider)
285 return m_phySapProvider->
GetBwpId();
296 if (m_phySapProvider)
325NrUeMac::GetTotalBufSize()
const
328 for (
const auto& it : m_ulBsrReceived)
330 ret += (it.second.txQueueSize + it.second.retxQueueSize + it.second.statusPduSize);
342 m_numHarqProcess = numHarqProcess;
345 for (
auto& i : m_miUlHarqProcessesPacket)
347 if (i.m_pktBurst ==
nullptr)
349 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
362 return m_numHarqProcess;
369 NS_LOG_FUNCTION(
this);
370 if (m_ulDci ==
nullptr)
377 m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_lcidList.push_back(params.
lcid);
379 NrMacHeaderVs header;
380 header.SetLcId(params.
lcid);
381 header.SetSize(params.
pdu->GetSize());
383 params.
pdu->AddHeader(header);
385 NrRadioBearerTag bearerTag(params.
rnti, params.
lcid, 0);
386 params.
pdu->AddPacketTag(bearerTag);
388 if (!m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_pktBurst)
390 m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_pktBurst = CreateObject<PacketBurst>();
392 m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_pktBurst->AddPacket(params.
pdu);
395 m_ulDciTotalUsed += params.
pdu->GetSize();
397 NS_ASSERT_MSG(m_ulDciTotalUsed <= m_ulDci->m_tbSize,
398 "We used more data than the DCI allowed us.");
400 m_phySapProvider->
SendMacPdu(params.
pdu, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
404NrUeMac::DoReportBufferStatus(NrMacSapProvider::ReportBufferStatusParameters params)
406 NS_LOG_FUNCTION(
this <<
static_cast<uint32_t
>(params.lcid));
408 auto it = m_ulBsrReceived.find(params.lcid);
410 NS_LOG_INFO(
"Received BSR for LC Id" <<
static_cast<uint32_t
>(params.lcid));
412 if (it != m_ulBsrReceived.end())
415 (*it).second = params;
419 it = m_ulBsrReceived.insert(std::make_pair(params.lcid, params)).first;
422 if (m_srState == INACTIVE || (params.expRbsTimer && m_srState == ACTIVE))
424 NS_LOG_INFO(
"INACTIVE -> TO_SEND, bufSize " << GetTotalBufSize());
430NrUeMac::SendReportBufferStatus(
const SfnSf& dataSfn, uint8_t symStart)
432 NS_LOG_FUNCTION(
this);
436 NS_LOG_INFO(
"MAC not initialized, BSR deferred");
440 if (m_ulBsrReceived.empty())
442 NS_LOG_INFO(
"No BSR report to transmit");
445 MacCeElement bsr = MacCeElement();
447 bsr.m_macCeType = MacCeElement::BSR;
450 std::unordered_map<uint8_t, NrMacSapProvider::ReportBufferStatusParameters>::iterator it;
451 std::vector<uint32_t> queue(4, 0);
452 for (it = m_ulBsrReceived.begin(); it != m_ulBsrReceived.end(); it++)
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;
464 ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
466 if (queue.at(lcg) != 0)
468 NS_LOG_DEBUG(
"Adding 5 bytes for SHORT_BSR.");
471 if ((*it).second.txQueueSize > 0)
473 NS_LOG_DEBUG(
"Adding 3 bytes for TX subheader.");
476 if ((*it).second.retxQueueSize > 0)
478 NS_LOG_DEBUG(
"Adding 3 bytes for RX subheader.");
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));
492 Ptr<NrBsrMessage> msg = Create<NrBsrMessage>();
499 Ptr<Packet> p = Create<Packet>();
504 NrMacShortBsrCe header;
510 p->AddHeader(header);
513 p->AddPacketTag(bearerTag);
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.");
519 m_phySapProvider->
SendMacPdu(p, dataSfn, symStart, m_ulDci->m_rnti);
531 return m_cmacSapProvider;
535NrUeMac::RefreshHarqProcessesPacketBuffer()
537 NS_LOG_FUNCTION(
this);
539 for (std::size_t i = 0; i < m_miUlHarqProcessesPacketTimer.size(); i++)
541 if (m_miUlHarqProcessesPacketTimer.at(i) == 0 && m_miUlHarqProcessesPacket.at(i).m_pktBurst)
543 if (m_miUlHarqProcessesPacket.at(i).m_pktBurst->GetSize() > 0)
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();
560NrUeMac::DoSlotIndication(
const SfnSf& sfn)
562 NS_LOG_FUNCTION(
this);
564 NS_LOG_INFO(
"Slot " << m_currentSlot);
566 RefreshHarqProcessesPacketBuffer();
568 if (m_srState == TO_SEND)
570 NS_LOG_INFO(
"Sending SR to PHY in slot " << sfn);
579NrUeMac::SendSR()
const
581 NS_LOG_FUNCTION(
this);
585 NS_LOG_INFO(
"MAC not initialized, SR deferred");
590 Ptr<NrSRMessage> msg = Create<NrSRMessage>();
592 msg->SetRNTI(m_rnti);
599NrUeMac::DoReceivePhyPdu(Ptr<Packet> p)
601 NS_LOG_FUNCTION(
this);
603 NrRadioBearerTag tag;
604 p->RemovePacketTag(tag);
606 if (tag.GetRnti() != m_rnti)
611 NrMacHeaderVs header;
612 p->RemoveHeader(header);
614 NrMacSapUser::ReceivePduParameters rxParams;
616 rxParams.rnti = m_rnti;
617 rxParams.lcid = header.GetLcId();
619 auto it = m_lcInfoMap.find(header.GetLcId());
621 if (it == m_lcInfoMap.end())
628 if (rxParams.p->GetSize() > 0)
630 it->second.macSapUser->ReceivePdu(rxParams);
635NrUeMac::RecvRaResponse(NrBuildRarListElement_s raResponse)
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 "
642 <<
", setting T-C-RNTI = " << raResponse.ulMsg3Dci->m_rnti
643 <<
" at: " << Simulator::Now().As(Time::MS));
644 m_rnti = raResponse.ulMsg3Dci->m_rnti;
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))
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();
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);
681NrUeMac::ProcessUlDci(
const Ptr<NrUlDciMessage>& dciMsg)
683 NS_LOG_FUNCTION(
this);
685 SfnSf dataSfn = m_currentSlot;
686 dataSfn.
Add(dciMsg->GetKDelay());
689 m_ulDciSfnsf = dataSfn;
690 m_ulDciTotalUsed = 0;
691 m_ulDci = dciMsg->GetDciInfoElement();
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());
699 if (m_ulDci->m_ndi == 0)
705 SendReportBufferStatus(dataSfn, m_ulDci->m_symStart);
707 else if (m_ulDci->m_ndi == 1)
711 NS_LOG_INFO(
"After sending NewData, bufSize " << GetTotalBufSize());
715 SendReportBufferStatus(dataSfn, m_ulDci->m_symStart);
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 ");
721 if (GetTotalBufSize() == 0)
723 m_srState = INACTIVE;
724 NS_LOG_INFO(
"ACTIVE -> INACTIVE, bufSize " << GetTotalBufSize());
730 if (m_ulDciTotalUsed == 0)
732 NS_LOG_WARN(
"No byte used for this UL-DCI, sending empty PDU");
734 NrMacSapProvider::TransmitPduParameters txParams;
736 txParams.pdu = Create<Packet>();
738 txParams.rnti = m_rnti;
740 txParams.harqProcessId = m_ulDci->m_harqProcess;
741 txParams.componentCarrierId =
GetBwpId();
743 DoTransmitPdu(txParams);
750NrUeMac::TransmitRetx()
752 NS_LOG_FUNCTION(
this);
754 Ptr<PacketBurst> pb = m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst;
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.");
766 NS_LOG_DEBUG(
"UE MAC RETX HARQ " << +m_ulDci->m_harqProcess);
768 NS_ASSERT(pb->GetNPackets() > 0);
770 for (std::list<Ptr<Packet>>::const_iterator j = pb->Begin(); j != pb->End(); ++j)
772 Ptr<Packet> pkt = (*j)->Copy();
773 NrRadioBearerTag bearerTag;
774 if (!pkt->PeekPacketTag(bearerTag))
776 NS_FATAL_ERROR(
"No radio bearer tag");
778 m_phySapProvider->
SendMacPdu(pkt, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
785NrUeMac::SendRetxData(uint32_t usefulTbs, uint32_t activeLcsRetx)
787 NS_LOG_FUNCTION(
this);
789 if (activeLcsRetx == 0)
794 uint32_t bytesPerLcId = usefulTbs / activeLcsRetx;
796 for (
auto& itBsr : m_ulBsrReceived)
798 auto& bsr = itBsr.second;
800 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
802 NrMacSapUser::TxOpportunityParameters txParams;
803 txParams.lcid = bsr.lcid;
804 txParams.rnti = m_rnti;
805 txParams.bytes = bytesPerLcId;
807 txParams.harqId = m_ulDci->m_harqProcess;
808 txParams.componentCarrierId =
GetBwpId();
810 NS_LOG_INFO(
"Notifying RLC of LCID " << +bsr.lcid
813 << bytesPerLcId <<
" B for a RETX PDU");
815 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
823 bsr.retxQueueSize -= std::min(bytesPerLcId, bsr.retxQueueSize);
827 NS_LOG_DEBUG(
"Something wrong with the calculation of overhead."
829 << activeLcsRetx <<
" assigned to this: " << bytesPerLcId
830 <<
", with TBS of " << m_ulDci->m_tbSize <<
" usefulTbs " << usefulTbs
831 <<
" and total used " << m_ulDciTotalUsed);
837NrUeMac::SendTxData(uint32_t usefulTbs, uint32_t activeTx)
839 NS_LOG_FUNCTION(
this);
846 uint32_t bytesPerLcId = usefulTbs / activeTx;
848 for (
auto& itBsr : m_ulBsrReceived)
850 auto& bsr = itBsr.second;
852 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
854 NrMacSapUser::TxOpportunityParameters txParams;
855 txParams.lcid = bsr.lcid;
856 txParams.rnti = m_rnti;
857 txParams.bytes = bytesPerLcId;
859 txParams.harqId = m_ulDci->m_harqProcess;
860 txParams.componentCarrierId =
GetBwpId();
862 NS_LOG_INFO(
"Notifying RLC of LCID " << +bsr.lcid
865 << bytesPerLcId <<
" B for a TX PDU");
867 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
875 bsr.txQueueSize -= std::min(bytesPerLcId, bsr.txQueueSize);
879 NS_LOG_DEBUG(
"Something wrong with the calculation of overhead."
881 << activeTx <<
" assigned to this: " << bytesPerLcId <<
", with TBS of "
882 << m_ulDci->m_tbSize <<
" usefulTbs " << usefulTbs <<
" and total used "
883 << m_ulDciTotalUsed);
889NrUeMac::SendNewData()
891 NS_LOG_FUNCTION(
this);
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);
903 uint16_t activeLcsRetx = 0;
904 uint16_t activeLcsTx = 0;
905 for (
const auto& itBsr : m_ulBsrReceived)
907 if (itBsr.second.retxQueueSize > 0)
911 if (itBsr.second.txQueueSize > 0)
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.");
925 uint32_t usefulTbs = m_ulDci->m_tbSize - m_ulDciTotalUsed - 5;
929 if (activeLcsRetx == 0 && activeLcsTx == 0 && usefulTbs > 0)
931 NS_LOG_LOGIC(
"This UE tx opportunity will be wasted: " << usefulTbs <<
" bytes.");
936 if (activeLcsRetx > 0 && usefulTbs > 0)
940 if (activeLcsRetx * 10 > usefulTbs)
942 NS_LOG_DEBUG(
"The overhead for transmitting retx data is greater than the space for "
945 << usefulTbs <<
" B.");
949 usefulTbs -= activeLcsRetx * 3;
950 SendRetxData(usefulTbs, activeLcsRetx);
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;
964 if (activeLcsTx > 0 && usefulTbs > 0)
968 if (activeLcsTx * 10 > usefulTbs)
970 NS_LOG_DEBUG(
"The overhead for transmitting new data is greater than the space for "
973 << usefulTbs <<
" B.");
977 usefulTbs -= activeLcsTx * 3;
978 SendTxData(usefulTbs, activeLcsTx);
984 if (m_ulDciTotalUsed == 0)
986 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst =
nullptr;
987 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_lcidList.clear();
992NrUeMac::SendNewStatusData()
994 NS_LOG_FUNCTION(
this);
996 bool hasStatusPdu =
false;
997 bool sentOneStatusPdu =
false;
999 for (
auto& bsrIt : m_ulBsrReceived)
1001 auto& bsr = bsrIt.second;
1003 if (bsr.statusPduSize > 0)
1005 hasStatusPdu =
true;
1008 if (m_ulDciTotalUsed + bsr.statusPduSize <= m_ulDci->m_tbSize)
1010 NrMacSapUser::TxOpportunityParameters txParams;
1011 txParams.lcid = bsr.lcid;
1012 txParams.rnti = m_rnti;
1013 txParams.bytes = bsr.statusPduSize;
1015 txParams.harqId = m_ulDci->m_harqProcess;
1016 txParams.componentCarrierId =
GetBwpId();
1018 NS_LOG_INFO(
"Notifying RLC of LCID " << +bsr.lcid
1021 << bsr.statusPduSize <<
" B for a status PDU");
1023 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
1027 bsr.statusPduSize = 0;
1028 sentOneStatusPdu =
true;
1032 NS_LOG_INFO(
"Cannot send StatusPdu of " << bsr.statusPduSize
1033 <<
" B, we already used all the TBS");
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...");
1045NrUeMac::DoReceiveControlMessage(Ptr<NrControlMessage> msg)
1047 NS_LOG_FUNCTION(
this << msg);
1049 switch (msg->GetMessageType())
1052 ProcessUlDci(DynamicCast<NrUlDciMessage>(msg));
1056 NS_LOG_INFO(
"Received RAR in slot " << m_currentSlot);
1060 if (m_waitingForRaResponse)
1062 Ptr<NrRarMessage> rarMsg = DynamicCast<NrRarMessage>(msg);
1063 NS_LOG_LOGIC(
"got RAR with RA-RNTI " << +rarMsg->GetRaRnti() <<
", expecting "
1065 for (
auto it = rarMsg->RarListBegin(); it != rarMsg->RarListEnd(); ++it)
1067 if (it->rarPayload.raPreambleId == m_raPreambleId)
1069 RecvRaResponse(it->rarPayload);
1077 NS_LOG_LOGIC(
"Control message not supported/expected");
1084 return m_phySapUser;
1090 m_phySapProvider = ptr;
1094NrUeMac::RaResponseTimeout(
bool contention)
1096 NS_LOG_FUNCTION(
this << contention);
1097 m_waitingForRaResponse =
false;
1099 ++m_preambleTransmissionCounter;
1101 m_raResponseTimeoutTrace(m_imsi,
1103 m_preambleTransmissionCounter,
1107 NS_LOG_INFO(
"RAR timeout, preambleTransMax reached => giving up");
1112 NS_LOG_INFO(
"RAR timeout while waiting for raPreambleId " << +m_raPreambleId
1113 <<
" re-send preamble");
1116 RandomlySelectAndSendRaPreamble();
1120 SendRaPreamble(contention);
1126NrUeMac::DoConfigureRach(NrUeCmacSapProvider::RachConfig rc)
1128 NS_LOG_FUNCTION(
this);
1130 m_rachConfigured =
true;
1134NrUeMac::DoStartContentionBasedRandomAccessProcedure()
1136 NS_LOG_FUNCTION(
this);
1137 RandomlySelectAndSendRaPreamble();
1141NrUeMac::RandomlySelectAndSendRaPreamble()
1143 NS_LOG_FUNCTION(
this);
1145 NS_ASSERT_MSG(m_rachConfigured,
"RACH not configured");
1149 NS_LOG_DEBUG(m_currentSlot <<
" Received System Information, send to PHY the "
1152 SendRaPreamble(
true);
1156NrUeMac::SendRaPreamble(
bool contention)
1158 NS_LOG_FUNCTION(
this << (uint32_t)m_raPreambleId << contention);
1163 m_raPreambleId = g_raPreambleId++;
1164 bool preambleOverflow = m_raPreambleId == 255;
1165 m_raPreambleId += preambleOverflow;
1166 g_raPreambleId += preambleOverflow;
1173 NS_LOG_INFO(
" Sent preamble id " << +m_raPreambleId
1174 <<
" at: " << Simulator::Now().As(Time::MS));
1177 Simulator::Schedule(raWindowBegin, &NrUeMac::StartWaitingForRaResponse,
this);
1178 m_noRaResponseReceivedEvent =
1179 Simulator::Schedule(raWindowEnd, &NrUeMac::RaResponseTimeout,
this, contention);
1182 Ptr<NrRachPreambleMessage> rachMsg = Create<NrRachPreambleMessage>();
1184 m_macTxedCtrlMsgsTrace(m_currentSlot,
GetCellId(), m_rnti,
GetBwpId(), rachMsg);
1188NrUeMac::StartWaitingForRaResponse()
1190 NS_LOG_FUNCTION(
this);
1191 m_waitingForRaResponse =
true;
1195NrUeMac::DoStartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
1196 [[maybe_unused]] uint8_t preambleId,
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");
1204 m_raPreambleId = preambleId;
1205 m_preambleTransmissionCounter = 0;
1206 bool contention =
false;
1207 SendRaPreamble(contention);
1211NrUeMac::AddLc(uint8_t lcId, NrUeCmacSapProvider::LogicalChannelConfig lcConfig, NrMacSapUser* msu)
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");
1218 lcInfo.lcConfig = lcConfig;
1219 lcInfo.macSapUser = msu;
1220 m_lcInfoMap[lcId] = lcInfo;
1224NrUeMac::DoRemoveLc(uint8_t lcId)
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);
1255 return m_macSapProvider;
1261 NS_LOG_FUNCTION(
this);
1262 auto it = m_lcInfoMap.begin();
1263 while (it != m_lcInfoMap.end())
1273 m_lcInfoMap.erase(it++);
1278 m_noRaResponseReceivedEvent.Cancel();
1279 m_rachConfigured =
false;
1280 m_ulBsrReceived.clear();
1294 NS_LOG_FUNCTION(
this << stream);
1295 m_raPreambleUniformVariable->SetStream(stream);
@ UL_DCI
The resources allocation map from the BS to the attached UEs (UL)
@ RAR
Random Access Response.
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.
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.
NrUePhySapUser * GetPhySapUser()
Get the PHY SAP User (AKA the MAC representation for the PHY)
uint64_t GetImsi() const
Get the IMSI.
void DoDispose() override
DoDispose method inherited from Object.
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.
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.
NrUeCmacSapProvider * GetUeCmacSapProvider()
Get the C MAC SAP provider (AKA the MAC representation for the RRC)
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.
uint16_t GetBwpId() const
Get the bwp id of this MAC.
uint16_t GetRnti() const
Get the RNTI.
void SetUeCmacSapUser(NrUeCmacSapUser *s)
Set the C MAC SAP user (AKA the RRC representation for the MAC)
~NrUeMac() override
Deconstructor.
void Add(uint32_t slotN)
Add to this SfnSf a number of slot indicated by the first parameter.
uint8_t preambleTransMax
preamble transmit maximum
uint8_t raResponseWindowSize
RA response window size.
uint8_t numberOfRaPreambles
number of RA preambles