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 BufferStatusReport(BufferStatusReportParameters params)
override;
135UeMemberNrMacSapProvider::UeMemberNrMacSapProvider(NrUeMac* mac)
141UeMemberNrMacSapProvider::TransmitPdu(TransmitPduParameters params)
143 m_mac->DoTransmitPdu(params);
147UeMemberNrMacSapProvider::BufferStatusReport(BufferStatusReportParameters params)
149 m_mac->DoTransmitBufferStatusReport(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")
229 .AddTraceSource(
"UeMacStateMachineTrace",
230 "UE MAC state machine trace",
231 MakeTraceSourceAccessor(&NrUeMac::m_macUeStateMachine),
232 "ns3::NrUeMac::UeMacStateMachineTracedCallback");
239 NS_LOG_FUNCTION(
this);
240 m_cmacSapProvider =
new UeMemberNrUeCmacSapProvider(
this);
241 m_macSapProvider =
new UeMemberNrMacSapProvider(
this);
242 m_phySapUser =
new MacUeMemberPhySapUser(
this);
243 m_raPreambleUniformVariable = CreateObject<UniformRandomVariable>();
253 m_miUlHarqProcessesPacket.clear();
254 m_miUlHarqProcessesPacketTimer.clear();
255 m_ulBsrReceived.clear();
257 m_raPreambleUniformVariable =
nullptr;
258 delete m_macSapProvider;
259 delete m_cmacSapProvider;
264NrUeMac::SetRnti(uint16_t rnti)
266 NS_LOG_FUNCTION(
this);
271NrUeMac::DoNotifyConnectionSuccessful()
273 NS_LOG_FUNCTION(
this);
278NrUeMac::DoSetImsi(uint64_t imsi)
280 NS_LOG_FUNCTION(
this);
287 if (m_phySapProvider)
289 return m_phySapProvider->
GetBwpId();
300 if (m_phySapProvider)
329NrUeMac::GetTotalBufSize()
const
332 for (
const auto& it : m_ulBsrReceived)
334 ret += (it.second.txQueueSize + it.second.retxQueueSize + it.second.statusPduSize);
346 m_numHarqProcess = numHarqProcess;
349 for (
auto& i : m_miUlHarqProcessesPacket)
351 if (i.m_pktBurst ==
nullptr)
353 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
366 return m_numHarqProcess;
373 NS_LOG_FUNCTION(
this);
374 if (m_ulDci ==
nullptr)
381 m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_lcidList.push_back(params.
lcid);
383 NrMacHeaderVs header;
384 header.SetLcId(params.
lcid);
385 header.SetSize(params.
pdu->GetSize());
387 params.
pdu->AddHeader(header);
389 NrRadioBearerTag bearerTag(params.
rnti, params.
lcid, 0);
390 params.
pdu->AddPacketTag(bearerTag);
392 if (!m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_pktBurst)
394 m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_pktBurst = CreateObject<PacketBurst>();
396 m_miUlHarqProcessesPacket.at(params.
harqProcessId).m_pktBurst->AddPacket(params.
pdu);
399 m_ulDciTotalUsed += params.
pdu->GetSize();
401 NS_ASSERT_MSG(m_ulDciTotalUsed <= m_ulDci->m_tbSize,
402 "We used more data than the DCI allowed us.");
404 m_phySapProvider->
SendMacPdu(params.
pdu, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
408NrUeMac::DoTransmitBufferStatusReport(NrMacSapProvider::BufferStatusReportParameters params)
410 NS_LOG_FUNCTION(
this <<
static_cast<uint32_t
>(params.lcid));
412 auto it = m_ulBsrReceived.find(params.lcid);
414 NS_LOG_INFO(
"Received BSR for LC Id" <<
static_cast<uint32_t
>(params.lcid));
416 if (it != m_ulBsrReceived.end())
419 (*it).second = params;
423 it = m_ulBsrReceived.insert(std::make_pair(params.lcid, params)).first;
427 (params.expBsrTimer && m_srState ==
ACTIVE && m_ulDci->m_harqProcess > 0 &&
428 m_ulDci->m_rv == 3) ||
429 (params.expBsrTimer && m_srState ==
ACTIVE && m_ulDci->m_harqProcess == 0))
433 NS_LOG_INFO(
"m_srState = INACTIVE -> TO_SEND, bufSize " << GetTotalBufSize());
434 m_macUeStateMachine(m_currentSlot,
441 "DoTransmitBufferStatusReport");
445 NS_LOG_INFO(
"m_srState = ACTIVE (BSR Timer expired) -> TO_SEND, bufSize "
446 << GetTotalBufSize());
447 m_macUeStateMachine(m_currentSlot,
454 "DoTransmitBufferStatusReport");
461NrUeMac::SendBufferStatusReport(
const SfnSf& dataSfn, uint8_t symStart)
463 NS_LOG_FUNCTION(
this);
467 NS_LOG_INFO(
"MAC not initialized, BSR deferred");
471 if (m_ulBsrReceived.empty())
473 NS_LOG_INFO(
"No BSR report to transmit");
476 MacCeElement bsr = MacCeElement();
478 bsr.m_macCeType = MacCeElement::BSR;
481 std::unordered_map<uint8_t, NrMacSapProvider::BufferStatusReportParameters>::iterator it;
482 std::vector<uint32_t> queue(4, 0);
483 for (it = m_ulBsrReceived.begin(); it != m_ulBsrReceived.end(); it++)
485 uint8_t lcid = it->first;
486 std::unordered_map<uint8_t, LcInfo>::iterator lcInfoMapIt;
487 lcInfoMapIt = m_lcInfoMap.find(lcid);
488 NS_ASSERT(lcInfoMapIt != m_lcInfoMap.end());
489 NS_ASSERT_MSG((lcid != 0) ||
490 (((*it).second.txQueueSize == 0) && ((*it).second.retxQueueSize == 0) &&
491 ((*it).second.statusPduSize == 0)),
492 "BSR should not be used for LCID 0");
493 uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
495 ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
497 if (queue.at(lcg) != 0)
499 NS_LOG_DEBUG(
"Adding 5 bytes for SHORT_BSR.");
502 if ((*it).second.txQueueSize > 0)
504 NS_LOG_DEBUG(
"Adding 3 bytes for TX subheader.");
507 if ((*it).second.retxQueueSize > 0)
509 NS_LOG_DEBUG(
"Adding 3 bytes for RX subheader.");
514 NS_LOG_INFO(
"Sending BSR with this info for the LCG: "
515 << queue.at(0) <<
" " << queue.at(1) <<
" " << queue.at(2) <<
" " << queue.at(3));
523 Ptr<NrBsrMessage> msg = Create<NrBsrMessage>();
530 Ptr<Packet> p = Create<Packet>();
535 NrMacShortBsrCe header;
541 p->AddHeader(header);
544 p->AddPacketTag(bearerTag);
546 m_ulDciTotalUsed += p->GetSize();
547 NS_ASSERT_MSG(m_ulDciTotalUsed <= m_ulDci->m_tbSize,
548 "We used more data than the DCI allowed us.");
550 m_phySapProvider->
SendMacPdu(p, dataSfn, symStart, m_ulDci->m_rnti);
552 m_macUeStateMachine(m_currentSlot,
559 "SendBufferStatusReport");
571 return m_cmacSapProvider;
575NrUeMac::RefreshHarqProcessesPacketBuffer()
577 NS_LOG_FUNCTION(
this);
579 for (std::size_t i = 0; i < m_miUlHarqProcessesPacketTimer.size(); i++)
581 if (m_miUlHarqProcessesPacketTimer.at(i) == 0 && m_miUlHarqProcessesPacket.at(i).m_pktBurst)
583 if (m_miUlHarqProcessesPacket.at(i).m_pktBurst->GetSize() > 0)
586 NS_LOG_INFO(
"HARQ Proc Id " << i <<
" packets buffer expired");
587 Ptr<PacketBurst> emptyPb = CreateObject<PacketBurst>();
588 m_miUlHarqProcessesPacket.at(i).m_pktBurst = emptyPb;
589 m_miUlHarqProcessesPacket.at(i).m_lcidList.clear();
600NrUeMac::DoSlotIndication(
const SfnSf& sfn)
602 NS_LOG_FUNCTION(
this);
604 NS_LOG_INFO(
"Slot " << m_currentSlot);
606 RefreshHarqProcessesPacketBuffer();
610 NS_LOG_INFO(
"Sending SR to PHY in slot " << sfn);
613 NS_LOG_INFO(
"m_srState = TO_SEND -> ACTIVE");
614 m_macUeStateMachine(m_currentSlot,
628NrUeMac::SendSR()
const
630 NS_LOG_FUNCTION(
this);
634 NS_LOG_INFO(
"MAC not initialized, SR deferred");
639 Ptr<NrSRMessage> msg = Create<NrSRMessage>();
641 msg->SetRNTI(m_rnti);
648NrUeMac::DoReceivePhyPdu(Ptr<Packet> p)
650 NS_LOG_FUNCTION(
this);
652 NrRadioBearerTag tag;
653 p->RemovePacketTag(tag);
655 if (tag.GetRnti() != m_rnti)
660 NrMacHeaderVs header;
661 p->RemoveHeader(header);
663 NrMacSapUser::ReceivePduParameters rxParams;
665 rxParams.rnti = m_rnti;
666 rxParams.lcid = header.GetLcId();
668 auto it = m_lcInfoMap.find(header.GetLcId());
670 if (it == m_lcInfoMap.end())
677 if (rxParams.p->GetSize() > 0)
679 it->second.macSapUser->ReceivePdu(rxParams);
684NrUeMac::RecvRaResponse(NrBuildRarListElement_s raResponse)
686 NS_LOG_FUNCTION(
this);
687 m_waitingForRaResponse =
false;
688 m_noRaResponseReceivedEvent.Cancel();
689 NS_LOG_INFO(
" IMSI " << m_imsi <<
" RNTI " << m_rnti <<
" received RAR for RA preamble ID "
691 <<
", setting T-C-RNTI = " << raResponse.ulMsg3Dci->m_rnti
692 <<
" at: " << Simulator::Now().As(Time::MS));
693 m_rnti = raResponse.ulMsg3Dci->m_rnti;
702 const uint8_t lc0Lcid = 0;
703 auto lc0InfoIt = m_lcInfoMap.find(lc0Lcid);
704 NS_ASSERT_MSG(lc0InfoIt != m_lcInfoMap.end(),
705 "LC0 not mapped to this UE MAC with bwpId:" <<
GetBwpId());
706 auto lc0BsrIt = m_ulBsrReceived.find(lc0Lcid);
707 if ((lc0BsrIt != m_ulBsrReceived.end()) && (lc0BsrIt->second.txQueueSize > 0))
710 "Notify RLC about transmission opportunity for sending RRC CONNECTION REQUEST.");
711 NS_ASSERT_MSG(raResponse.ulMsg3Dci->m_tbSize > lc0BsrIt->second.txQueueSize,
712 "segmentation of Message 3 is not allowed");
713 NrMacSapUser::TxOpportunityParameters txOpParams;
714 txOpParams.lcid = lc0Lcid;
715 txOpParams.rnti = m_rnti;
716 txOpParams.bytes = raResponse.ulMsg3Dci->m_tbSize;
717 txOpParams.layer = 0;
718 txOpParams.harqId = 0;
719 txOpParams.componentCarrierId =
GetBwpId();
721 lc0InfoIt->second.macSapUser->NotifyTxOpportunity(txOpParams);
722 lc0BsrIt->second.txQueueSize = 0;
723 lc0BsrIt->second.retxQueueSize = 0;
724 lc0BsrIt->second.statusPduSize = 0;
725 m_ulBsrReceived.erase(lc0BsrIt);
730NrUeMac::ProcessUlDci(
const Ptr<NrUlDciMessage>& dciMsg)
732 NS_LOG_FUNCTION(
this);
734 SfnSf dataSfn = m_currentSlot;
735 dataSfn.
Add(dciMsg->GetKDelay());
738 m_ulDciSfnsf = dataSfn;
739 m_ulDciTotalUsed = 0;
740 m_ulDci = dciMsg->GetDciInfoElement();
744 NS_LOG_INFO(
"UL DCI received, transmit data in slot "
745 << dataSfn <<
" Harq Process " << +m_ulDci->m_harqProcess <<
" TBS "
746 << m_ulDci->m_tbSize <<
" total queue " << GetTotalBufSize());
748 if (m_ulDci->m_ndi == 0)
752 m_macUeStateMachine(m_currentSlot,
762 SendBufferStatusReport(dataSfn, m_ulDci->m_symStart);
764 else if (m_ulDci->m_ndi == 1)
767 m_macUeStateMachine(m_currentSlot,
776 NS_LOG_INFO(
"After sending NewData, bufSize " << GetTotalBufSize());
780 SendBufferStatusReport(dataSfn, m_ulDci->m_symStart);
782 NS_LOG_INFO(
"UL DCI processing done, sent to PHY a total of "
783 << m_ulDciTotalUsed <<
" B out of " << m_ulDci->m_tbSize
784 <<
" allocated bytes ");
786 if (GetTotalBufSize() == 0)
789 NS_LOG_INFO(
"m_srState = ACTIVE -> INACTIVE, bufSize " << GetTotalBufSize());
795 if (m_ulDciTotalUsed == 0)
797 NS_LOG_WARN(
"No byte used for this UL-DCI, sending empty PDU");
799 NrMacSapProvider::TransmitPduParameters txParams;
801 txParams.pdu = Create<Packet>();
803 txParams.rnti = m_rnti;
805 txParams.harqProcessId = m_ulDci->m_harqProcess;
806 txParams.componentCarrierId =
GetBwpId();
808 DoTransmitPdu(txParams);
815NrUeMac::TransmitRetx()
817 NS_LOG_FUNCTION(
this);
819 Ptr<PacketBurst> pb = m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst;
824 "The previous transmission did not contain any new data; "
825 "probably it was BSR only. To not send an old BSR to the scheduler, "
826 "we don't send anything back in this allocation. Eventually, "
827 "the Harq timer at gnb will expire, and soon this allocation will be forgotten.");
831 NS_LOG_DEBUG(
"UE MAC RETX HARQ " << +m_ulDci->m_harqProcess);
833 NS_ASSERT(pb->GetNPackets() > 0);
835 for (std::list<Ptr<Packet>>::const_iterator j = pb->Begin(); j != pb->End(); ++j)
837 Ptr<Packet> pkt = (*j)->Copy();
838 NrRadioBearerTag bearerTag;
839 if (!pkt->PeekPacketTag(bearerTag))
841 NS_FATAL_ERROR(
"No radio bearer tag");
843 m_phySapProvider->
SendMacPdu(pkt, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
850NrUeMac::SendRetxData(uint32_t usefulTbs, uint32_t activeLcsRetx)
852 NS_LOG_FUNCTION(
this);
854 if (activeLcsRetx == 0)
859 uint32_t bytesPerLcId = usefulTbs / activeLcsRetx;
861 for (
auto& itBsr : m_ulBsrReceived)
863 auto& bsr = itBsr.second;
865 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
867 NrMacSapUser::TxOpportunityParameters txParams;
868 txParams.lcid = bsr.lcid;
869 txParams.rnti = m_rnti;
870 txParams.bytes = bytesPerLcId;
872 txParams.harqId = m_ulDci->m_harqProcess;
873 txParams.componentCarrierId =
GetBwpId();
875 NS_LOG_INFO(
"Notifying RLC of LCID " << +bsr.lcid
878 << bytesPerLcId <<
" B for a RETX PDU");
880 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
888 bsr.retxQueueSize -= std::min(bytesPerLcId, bsr.retxQueueSize);
892 NS_LOG_DEBUG(
"Something wrong with the calculation of overhead."
894 << activeLcsRetx <<
" assigned to this: " << bytesPerLcId
895 <<
", with TBS of " << m_ulDci->m_tbSize <<
" usefulTbs " << usefulTbs
896 <<
" and total used " << m_ulDciTotalUsed);
902NrUeMac::SendTxData(uint32_t usefulTbs, uint32_t activeTx)
904 NS_LOG_FUNCTION(
this);
911 uint32_t bytesPerLcId = usefulTbs / activeTx;
913 for (
auto& itBsr : m_ulBsrReceived)
915 auto& bsr = itBsr.second;
917 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
919 NrMacSapUser::TxOpportunityParameters txParams;
920 txParams.lcid = bsr.lcid;
921 txParams.rnti = m_rnti;
922 txParams.bytes = bytesPerLcId;
924 txParams.harqId = m_ulDci->m_harqProcess;
925 txParams.componentCarrierId =
GetBwpId();
927 NS_LOG_INFO(
"Notifying RLC of LCID " << +bsr.lcid
930 << bytesPerLcId <<
" B for a TX PDU");
932 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
940 bsr.txQueueSize -= std::min(bytesPerLcId, bsr.txQueueSize);
944 NS_LOG_DEBUG(
"Something wrong with the calculation of overhead."
946 << activeTx <<
" assigned to this: " << bytesPerLcId <<
", with TBS of "
947 << m_ulDci->m_tbSize <<
" usefulTbs " << usefulTbs <<
" and total used "
948 << m_ulDciTotalUsed);
954NrUeMac::SendNewData()
956 NS_LOG_FUNCTION(
this);
958 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
959 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst = pb;
960 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_lcidList.clear();
961 NS_LOG_INFO(
"Reset HARQP " << +m_ulDci->m_harqProcess);
968 uint16_t activeLcsRetx = 0;
969 uint16_t activeLcsTx = 0;
970 for (
const auto& itBsr : m_ulBsrReceived)
972 if (itBsr.second.retxQueueSize > 0)
976 if (itBsr.second.txQueueSize > 0)
986 NS_ASSERT_MSG(m_ulDciTotalUsed + 5 <= m_ulDci->m_tbSize,
987 "The StatusPDU used " << m_ulDciTotalUsed
988 <<
" B, we don't have any for the SHORT_BSR.");
990 uint32_t usefulTbs = m_ulDci->m_tbSize - m_ulDciTotalUsed - 5;
994 if (activeLcsRetx == 0 && activeLcsTx == 0 && usefulTbs > 0)
996 NS_LOG_LOGIC(
"This UE tx opportunity will be wasted: " << usefulTbs <<
" bytes.");
1001 if (activeLcsRetx > 0 && usefulTbs > 0)
1005 if (activeLcsRetx * 10 > usefulTbs)
1007 NS_LOG_DEBUG(
"The overhead for transmitting retx data is greater than the space for "
1009 "Ignore the TBS of "
1010 << usefulTbs <<
" B.");
1014 usefulTbs -= activeLcsRetx * 3;
1015 SendRetxData(usefulTbs, activeLcsRetx);
1023 m_ulDciTotalUsed + 5 <= m_ulDci->m_tbSize,
1024 "The StatusPDU and RETX sending required all space, we don't have any for the SHORT_BSR.");
1025 usefulTbs = m_ulDci->m_tbSize - m_ulDciTotalUsed - 5;
1029 if (activeLcsTx > 0 && usefulTbs > 0)
1033 if (activeLcsTx * 10 > usefulTbs)
1035 NS_LOG_DEBUG(
"The overhead for transmitting new data is greater than the space for "
1037 "Ignore the TBS of "
1038 << usefulTbs <<
" B.");
1042 usefulTbs -= activeLcsTx * 3;
1043 SendTxData(usefulTbs, activeLcsTx);
1049 if (m_ulDciTotalUsed == 0)
1051 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst =
nullptr;
1052 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_lcidList.clear();
1057NrUeMac::SendNewStatusData()
1059 NS_LOG_FUNCTION(
this);
1061 bool hasStatusPdu =
false;
1062 bool sentOneStatusPdu =
false;
1064 for (
auto& bsrIt : m_ulBsrReceived)
1066 auto& bsr = bsrIt.second;
1068 if (bsr.statusPduSize > 0)
1070 hasStatusPdu =
true;
1073 if (m_ulDciTotalUsed + bsr.statusPduSize <= m_ulDci->m_tbSize)
1075 NrMacSapUser::TxOpportunityParameters txParams;
1076 txParams.lcid = bsr.lcid;
1077 txParams.rnti = m_rnti;
1078 txParams.bytes = bsr.statusPduSize;
1080 txParams.harqId = m_ulDci->m_harqProcess;
1081 txParams.componentCarrierId =
GetBwpId();
1083 NS_LOG_INFO(
"Notifying RLC of LCID " << +bsr.lcid
1086 << bsr.statusPduSize <<
" B for a status PDU");
1088 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
1092 bsr.statusPduSize = 0;
1093 sentOneStatusPdu =
true;
1097 NS_LOG_INFO(
"Cannot send StatusPdu of " << bsr.statusPduSize
1098 <<
" B, we already used all the TBS");
1103 NS_ABORT_MSG_IF(hasStatusPdu && !sentOneStatusPdu,
1104 "The TBS of size " << m_ulDci->m_tbSize
1105 <<
" doesn't allow us "
1106 "to send one status PDU...");
1110NrUeMac::DoReceiveControlMessage(Ptr<NrControlMessage> msg)
1112 NS_LOG_FUNCTION(
this << msg);
1114 switch (msg->GetMessageType())
1117 ProcessUlDci(DynamicCast<NrUlDciMessage>(msg));
1121 NS_LOG_INFO(
"Received RAR in slot " << m_currentSlot);
1125 if (m_waitingForRaResponse)
1127 Ptr<NrRarMessage> rarMsg = DynamicCast<NrRarMessage>(msg);
1128 NS_LOG_LOGIC(
"got RAR with RA-RNTI " << +rarMsg->GetRaRnti() <<
", expecting "
1130 for (
auto it = rarMsg->RarListBegin(); it != rarMsg->RarListEnd(); ++it)
1132 if (it->rarPayload.raPreambleId == m_raPreambleId)
1134 RecvRaResponse(it->rarPayload);
1142 NS_LOG_LOGIC(
"Control message not supported/expected");
1149 return m_phySapUser;
1155 m_phySapProvider = ptr;
1159NrUeMac::RaResponseTimeout(
bool contention)
1161 NS_LOG_FUNCTION(
this << contention);
1162 m_waitingForRaResponse =
false;
1164 ++m_preambleTransmissionCounter;
1166 m_raResponseTimeoutTrace(m_imsi,
1168 m_preambleTransmissionCounter,
1172 NS_LOG_INFO(
"RAR timeout, preambleTransMax reached => giving up");
1177 NS_LOG_INFO(
"RAR timeout while waiting for raPreambleId " << +m_raPreambleId
1178 <<
" re-send preamble");
1181 RandomlySelectAndSendRaPreamble();
1185 SendRaPreamble(contention);
1191NrUeMac::DoConfigureRach(NrUeCmacSapProvider::RachConfig rc)
1193 NS_LOG_FUNCTION(
this);
1195 m_rachConfigured =
true;
1199NrUeMac::DoStartContentionBasedRandomAccessProcedure()
1201 NS_LOG_FUNCTION(
this);
1202 RandomlySelectAndSendRaPreamble();
1206NrUeMac::RandomlySelectAndSendRaPreamble()
1208 NS_LOG_FUNCTION(
this);
1210 NS_ASSERT_MSG(m_rachConfigured,
"RACH not configured");
1214 NS_LOG_DEBUG(m_currentSlot <<
" Received System Information, send to PHY the "
1217 SendRaPreamble(
true);
1221NrUeMac::SendRaPreamble(
bool contention)
1223 NS_LOG_FUNCTION(
this << (uint32_t)m_raPreambleId << contention);
1228 m_raPreambleId = g_raPreambleId++;
1229 bool preambleOverflow = m_raPreambleId == 255;
1230 m_raPreambleId += preambleOverflow;
1231 g_raPreambleId += preambleOverflow;
1238 NS_LOG_INFO(
" Sent preamble id " << +m_raPreambleId
1239 <<
" at: " << Simulator::Now().As(Time::MS));
1242 Simulator::Schedule(raWindowBegin, &NrUeMac::StartWaitingForRaResponse,
this);
1243 m_noRaResponseReceivedEvent =
1244 Simulator::Schedule(raWindowEnd, &NrUeMac::RaResponseTimeout,
this, contention);
1247 Ptr<NrRachPreambleMessage> rachMsg = Create<NrRachPreambleMessage>();
1249 m_macTxedCtrlMsgsTrace(m_currentSlot,
GetCellId(), m_rnti,
GetBwpId(), rachMsg);
1253NrUeMac::StartWaitingForRaResponse()
1255 NS_LOG_FUNCTION(
this);
1256 m_waitingForRaResponse =
true;
1260NrUeMac::DoStartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
1261 [[maybe_unused]] uint8_t preambleId,
1264 NS_LOG_FUNCTION(
this << rnti << (uint16_t)preambleId << (uint16_t)prachMask);
1265 NS_ASSERT_MSG(prachMask == 0,
1266 "requested PRACH MASK = " << (uint32_t)prachMask
1267 <<
", but only PRACH MASK = 0 is supported");
1269 m_raPreambleId = preambleId;
1270 m_preambleTransmissionCounter = 0;
1271 bool contention =
false;
1272 SendRaPreamble(contention);
1276NrUeMac::AddLc(uint8_t lcId, NrUeCmacSapProvider::LogicalChannelConfig lcConfig, NrMacSapUser* msu)
1278 NS_LOG_FUNCTION(
this <<
" lcId" << (uint32_t)lcId);
1279 NS_ASSERT_MSG(m_lcInfoMap.find(lcId) == m_lcInfoMap.end(),
1280 "cannot add channel because LCID " << (uint16_t)lcId <<
" is already present");
1283 lcInfo.lcConfig = lcConfig;
1284 lcInfo.macSapUser = msu;
1285 m_lcInfoMap[lcId] = lcInfo;
1289NrUeMac::DoRemoveLc(uint8_t lcId)
1291 NS_LOG_FUNCTION(
this <<
" lcId" << lcId);
1292 NS_ASSERT_MSG(m_lcInfoMap.find(lcId) != m_lcInfoMap.end(),
1293 "could not find LCID " << (uint16_t)lcId);
1294 m_lcInfoMap.erase(lcId);
1295 m_ulBsrReceived.erase(lcId);
1320 return m_macSapProvider;
1326 NS_LOG_FUNCTION(
this);
1327 auto it = m_lcInfoMap.begin();
1328 while (it != m_lcInfoMap.end())
1338 m_lcInfoMap.erase(it++);
1343 m_noRaResponseReceivedEvent.Cancel();
1344 m_rachConfigured =
false;
1345 m_ulBsrReceived.clear();
1359 NS_LOG_FUNCTION(
this << stream);
1360 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.
@ INACTIVE
no SR nor BSR.. initial state
@ TO_SEND
We have to send the BSR when possible.
@ ACTIVE
SR or BSR sent; now the source of information is the vector m_bsrReservedSpace.
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