25 #include <ns3/pointer.h>
26 #include <ns3/packet.h>
27 #include <ns3/packet-burst.h>
28 #include <ns3/random-variable.h>
30 #include "lte-ue-mac.h"
31 #include "lte-ue-net-device.h"
32 #include "lte-radio-bearer-tag.h"
33 #include <ns3/ff-mac-common.h>
34 #include <ns3/lte-control-messages.h>
35 #include <ns3/simulator.h>
36 #include <ns3/lte-common.h>
44 NS_OBJECT_ENSURE_REGISTERED (LteUeMac);
62 virtual void RemoveLc (uint8_t lcId);
63 virtual void Reset ();
70 UeMemberLteUeCmacSapProvider::UeMemberLteUeCmacSapProvider (
LteUeMac* mac)
76 UeMemberLteUeCmacSapProvider::ConfigureRach (RachConfig rc)
78 m_mac->DoConfigureRach (rc);
84 m_mac->DoStartContentionBasedRandomAccessProcedure ();
90 m_mac->DoStartNonContentionBasedRandomAccessProcedure (rnti, preambleId, prachMask);
97 m_mac->DoAddLc (lcId, lcConfig, msu);
103 m_mac->DoRemoveLc (lcid);
126 UeMemberLteMacSapProvider::UeMemberLteMacSapProvider (
LteUeMac* mac)
134 m_mac->DoTransmitPdu (params);
141 m_mac->DoReportBufferStatus (params);
161 UeMemberLteUePhySapUser::UeMemberLteUePhySapUser (
LteUeMac* mac) : m_mac (mac)
169 m_mac->DoReceivePhyPdu (p);
182 m_mac->DoReceiveLteControlMessage (msg);
194 LteUeMac::GetTypeId (
void)
198 .AddConstructor<LteUeMac> ();
203 LteUeMac::LteUeMac ()
206 m_freshUlBsr (false),
209 m_rachConfigured (false),
210 m_waitingForRaResponse (false)
214 m_miUlHarqProcessesPacket.resize (HARQ_PERIOD);
215 for (uint8_t i = 0; i < m_miUlHarqProcessesPacket.size (); i++)
217 Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
218 m_miUlHarqProcessesPacket.at (i) = pb;
220 m_miUlHarqProcessesPacketTimer.resize (HARQ_PERIOD, 0);
222 m_macSapProvider =
new UeMemberLteMacSapProvider (
this);
223 m_cmacSapProvider =
new UeMemberLteUeCmacSapProvider (
this);
224 m_uePhySapUser =
new UeMemberLteUePhySapUser (
this);
225 m_raPreambleUniformVariable = CreateObject<UniformRandomVariable> ();
229 LteUeMac::~LteUeMac ()
238 m_miUlHarqProcessesPacket.clear ();
239 delete m_macSapProvider;
240 delete m_cmacSapProvider;
241 delete m_uePhySapUser;
249 return m_uePhySapUser;
255 m_uePhySapProvider = s;
260 LteUeMac::GetLteMacSapProvider (
void)
262 return m_macSapProvider;
266 LteUeMac::SetLteUeCmacSapUser (LteUeCmacSapUser* s)
271 LteUeCmacSapProvider*
272 LteUeMac::GetLteUeCmacSapProvider (
void)
274 return m_cmacSapProvider;
279 LteUeMac::DoTransmitPdu (LteMacSapProvider::TransmitPduParameters params)
282 NS_ASSERT_MSG (m_rnti == params.rnti,
"RNTI mismatch between RLC and MAC");
283 LteRadioBearerTag tag (params.rnti, params.lcid, 0 );
284 params.pdu->AddPacketTag (tag);
286 m_miUlHarqProcessesPacket.at (m_harqProcessId)->AddPacket (params.pdu);
287 m_miUlHarqProcessesPacketTimer.at (m_harqProcessId) = HARQ_PERIOD;
292 LteUeMac::DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params)
296 std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
299 it = m_ulBsrReceived.find (params.lcid);
300 if (it!=m_ulBsrReceived.end ())
303 (*it).second = params;
307 m_ulBsrReceived.insert (std::pair<uint8_t, LteMacSapProvider::ReportBufferStatusParameters> (params.lcid, params));
314 LteUeMac::SendReportBufferStatus (
void)
324 if (m_ulBsrReceived.size () == 0)
329 MacCeListElement_s bsr;
331 bsr.m_macCeType = MacCeListElement_s::BSR;
334 std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
335 std::vector<uint32_t> queue (4, 0);
336 for (it = m_ulBsrReceived.begin (); it != m_ulBsrReceived.end (); it++)
338 uint8_t lcid = it->first;
339 std::map <uint8_t, LcInfo>::iterator lcInfoMapIt;
340 lcInfoMapIt = m_lcInfoMap.find (lcid);
341 NS_ASSERT (lcInfoMapIt != m_lcInfoMap.end ());
342 uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
343 queue.at (lcg) += ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
347 bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (0)));
348 bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (1)));
349 bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (2)));
350 bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (3)));
353 Ptr<BsrLteControlMessage> msg = Create<BsrLteControlMessage> ();
360 LteUeMac::RandomlySelectAndSendRaPreamble ()
366 m_raPreambleId = m_raPreambleUniformVariable->
GetInteger (0, m_rachConfig.numberOfRaPreambles - 1);
367 bool contention =
true;
368 SendRaPreamble (contention);
372 LteUeMac::SendRaPreamble (
bool contention)
383 m_raRnti = m_subframeNo - 1;
385 NS_LOG_INFO (
this <<
" sent preamble id " << (uint32_t) m_raPreambleId <<
", RA-RNTI " << (uint32_t) m_raRnti);
388 Time raWindowEnd =
MilliSeconds (3 + m_rachConfig.raResponseWindowSize);
390 m_noRaResponseReceivedEvent =
Simulator::Schedule (raWindowEnd, &LteUeMac::RaResponseTimeout,
this, contention);
394 LteUeMac::StartWaitingForRaResponse ()
397 m_waitingForRaResponse =
true;
401 LteUeMac::RecvRaResponse (BuildRarListElement_s raResponse)
404 m_waitingForRaResponse =
false;
405 m_noRaResponseReceivedEvent.
Cancel ();
406 NS_LOG_INFO (
"got RAR for RAPID " << (uint32_t) m_raPreambleId <<
", setting T-C-RNTI = " << raResponse.m_rnti);
407 m_rnti = raResponse.m_rnti;
417 LteUeMac::RaResponseTimeout (
bool contention)
420 m_waitingForRaResponse =
false;
422 ++m_preambleTransmissionCounter;
423 if (m_preambleTransmissionCounter == m_rachConfig.preambleTransMax + 1)
425 NS_LOG_INFO (
"RAR timeout, preambleTransMax reached => giving up");
433 RandomlySelectAndSendRaPreamble ();
437 SendRaPreamble (contention);
443 LteUeMac::DoConfigureRach (LteUeCmacSapProvider::RachConfig rc)
447 m_rachConfigured =
true;
451 LteUeMac::DoStartContentionBasedRandomAccessProcedure ()
457 m_preambleTransmissionCounter = 0;
458 m_backoffParameter = 0;
459 RandomlySelectAndSendRaPreamble ();
463 LteUeMac::DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
466 NS_ASSERT_MSG (prachMask == 0,
"requested PRACH MASK = " << (uint32_t) prachMask <<
", but only PRACH MASK = 0 is supported");
468 m_raPreambleId = preambleId;
469 bool contention =
false;
470 SendRaPreamble (contention);
474 LteUeMac::DoAddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu)
477 NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (),
"cannot add channel because LCID " << lcId <<
" is already present");
480 lcInfo.lcConfig = lcConfig;
481 lcInfo.macSapUser = msu;
482 m_lcInfoMap[lcId] = lcInfo;
486 LteUeMac::DoRemoveLc (uint8_t lcId)
489 NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (),
"could not find LCID " << lcId);
490 m_lcInfoMap.erase (lcId);
497 std::map <uint8_t, LcInfo>::iterator it = m_lcInfoMap.begin ();
498 while (it != m_lcInfoMap.end ())
508 m_lcInfoMap.erase (it++);
511 m_rachConfigured =
false;
512 m_freshUlBsr =
false;
513 m_ulBsrReceived.clear ();
517 LteUeMac::DoReceivePhyPdu (Ptr<Packet> p)
519 LteRadioBearerTag tag;
520 p->RemovePacketTag (tag);
521 if (tag.GetRnti () == m_rnti)
524 std::map <uint8_t, LcInfo>::const_iterator it = m_lcInfoMap.find (tag.GetLcid ());
525 NS_ASSERT_MSG (it != m_lcInfoMap.end (),
"received packet with unknown lcid");
526 it->second.macSapUser->ReceivePdu (p);
532 LteUeMac::DoReceiveLteControlMessage (Ptr<LteControlMessage> msg)
535 if (msg->GetMessageType () == LteControlMessage::UL_DCI)
537 Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
538 UlDciListElement_s dci = msg2->GetDci ();
542 Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
543 m_miUlHarqProcessesPacket.at (m_harqProcessId) = pb;
545 std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator itBsr;
546 uint16_t activeLcs = 0;
547 uint32_t statusPduMinSize = 0;
548 for (itBsr = m_ulBsrReceived.begin (); itBsr != m_ulBsrReceived.end (); itBsr++)
550 if (((*itBsr).second.statusPduSize > 0) || ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
553 if (((*itBsr).second.statusPduSize!=0)&&((*itBsr).second.statusPduSize < statusPduMinSize))
555 statusPduMinSize = (*itBsr).second.statusPduSize;
557 if (((*itBsr).second.statusPduSize!=0)&&(statusPduMinSize == 0))
559 statusPduMinSize = (*itBsr).second.statusPduSize;
565 NS_LOG_ERROR (
this <<
" No active flows for this UL-DCI");
568 std::map <uint8_t, LcInfo>::iterator it;
569 uint32_t bytesPerActiveLc = dci.m_tbSize / activeLcs;
570 bool statusPduPriority =
false;
571 if ((statusPduMinSize != 0)&&(bytesPerActiveLc < statusPduMinSize))
574 statusPduPriority =
true;
575 NS_LOG_DEBUG (
this <<
" Reduced resource -> send only Status, b ytes " << statusPduMinSize);
576 if (dci.m_tbSize < statusPduMinSize)
578 NS_FATAL_ERROR (
"Insufficient Tx Opportunity for sending a status message");
581 NS_LOG_LOGIC (
this <<
" UE " << m_rnti <<
": UL-CQI notified TxOpportunity of " << dci.m_tbSize <<
" => " << bytesPerActiveLc <<
" bytes per active LC" <<
" statusPduMinSize " << statusPduMinSize);
582 for (it = m_lcInfoMap.begin (); it!=m_lcInfoMap.end (); it++)
584 itBsr = m_ulBsrReceived.find ((*it).first);
585 NS_LOG_DEBUG (
this <<
" Processing LC " << (uint32_t)(*it).first <<
" bytesPerActiveLc " << bytesPerActiveLc);
586 if ( (itBsr!=m_ulBsrReceived.end ()) &&
587 ( ((*itBsr).second.statusPduSize > 0) ||
588 ((*itBsr).second.retxQueueSize > 0) ||
589 ((*itBsr).second.txQueueSize > 0)) )
591 if ((statusPduPriority) && ((*itBsr).second.statusPduSize == statusPduMinSize))
593 (*it).second.macSapUser->NotifyTxOpportunity ((*itBsr).second.statusPduSize, 0, 0);
594 NS_LOG_LOGIC (
this <<
"\t" << bytesPerActiveLc <<
" send " << (*itBsr).second.statusPduSize <<
" status bytes to LC " << (uint32_t)(*it).first <<
" statusQueue " << (*itBsr).second.statusPduSize <<
" retxQueue" << (*itBsr).second.retxQueueSize <<
" txQueue" << (*itBsr).second.txQueueSize);
595 (*itBsr).second.statusPduSize = 0;
600 uint32_t bytesForThisLc = bytesPerActiveLc;
601 NS_LOG_LOGIC (
this <<
"\t" << bytesPerActiveLc <<
" bytes to LC " << (uint32_t)(*it).first <<
" statusQueue " << (*itBsr).second.statusPduSize <<
" retxQueue" << (*itBsr).second.retxQueueSize <<
" txQueue" << (*itBsr).second.txQueueSize);
602 if (((*itBsr).second.statusPduSize > 0) && (bytesForThisLc > (*itBsr).second.statusPduSize))
604 (*it).second.macSapUser->NotifyTxOpportunity ((*itBsr).second.statusPduSize, 0, 0);
605 bytesForThisLc -= (*itBsr).second.statusPduSize;
606 NS_LOG_DEBUG (
this <<
" serve STATUS " << (*itBsr).second.statusPduSize);
607 (*itBsr).second.statusPduSize = 0;
611 if ((*itBsr).second.statusPduSize>bytesForThisLc)
613 NS_FATAL_ERROR (
"Insufficient Tx Opportunity for sending a status message");
617 if ((bytesForThisLc > 7) &&
618 (((*itBsr).second.retxQueueSize > 0) ||
619 ((*itBsr).second.txQueueSize > 0)))
621 if ((*itBsr).second.retxQueueSize > 0)
623 NS_LOG_DEBUG (
this <<
" serve retx DATA, bytes " << bytesForThisLc);
624 (*it).second.macSapUser->NotifyTxOpportunity (bytesForThisLc, 0, 0);
625 if ((*itBsr).second.retxQueueSize >= bytesForThisLc)
627 (*itBsr).second.retxQueueSize -= bytesForThisLc;
631 (*itBsr).second.retxQueueSize = 0;
634 else if ((*itBsr).second.txQueueSize > 0)
636 NS_LOG_DEBUG (
this <<
" serve tx DATA, bytes " << bytesForThisLc);
637 (*it).second.macSapUser->NotifyTxOpportunity (bytesForThisLc, 0, 0);
638 if ((*itBsr).second.txQueueSize >= bytesForThisLc - 2)
640 (*itBsr).second.txQueueSize -= bytesForThisLc - 2;
644 (*itBsr).second.txQueueSize = 0;
650 if ( ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
656 NS_LOG_LOGIC (
this <<
"\t" << bytesPerActiveLc <<
"\t new queues " << (uint32_t)(*it).first <<
" statusQueue " << (*itBsr).second.statusPduSize <<
" retxQueue" << (*itBsr).second.retxQueueSize <<
" txQueue" << (*itBsr).second.txQueueSize);
665 NS_LOG_DEBUG (
this <<
" UE MAC RETX HARQ " << (uint16_t)m_harqProcessId);
666 Ptr<PacketBurst> pb = m_miUlHarqProcessesPacket.at (m_harqProcessId);
667 for (std::list<Ptr<Packet> >::const_iterator j = pb->Begin (); j != pb->End (); ++j)
669 Ptr<Packet> pkt = (*j)->Copy ();
672 m_miUlHarqProcessesPacketTimer.at (m_harqProcessId) = HARQ_PERIOD;
676 else if (msg->GetMessageType () == LteControlMessage::RAR)
678 if (m_waitingForRaResponse)
680 Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
681 uint16_t raRnti = rarMsg->GetRaRnti ();
682 NS_LOG_LOGIC (
this <<
"got RAR with RA-RNTI " << (uint32_t) raRnti <<
", expecting " << (uint32_t) m_raRnti);
683 if (raRnti == m_raRnti)
685 for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin ();
686 it != rarMsg->RarListEnd ();
689 if (it->rapId == m_raPreambleId)
691 RecvRaResponse (it->rarPayload);
702 NS_LOG_WARN (
this <<
" LteControlMessage not recognized");
707 LteUeMac::RefreshHarqProcessesPacketBuffer (
void)
711 for (uint16_t i = 0; i < m_miUlHarqProcessesPacketTimer.size (); i++)
713 if (m_miUlHarqProcessesPacketTimer.at (i) == 0)
715 if (m_miUlHarqProcessesPacket.at (i)->GetSize () > 0)
718 NS_LOG_INFO (
this <<
" HARQ Proc Id " << i <<
" packets buffer expired");
719 Ptr<PacketBurst> emptyPb = CreateObject <PacketBurst> ();
720 m_miUlHarqProcessesPacket.at (i) = emptyPb;
725 m_miUlHarqProcessesPacketTimer.at (i)--;
736 m_subframeNo = subframeNo;
737 RefreshHarqProcessesPacketBuffer ();
738 if ((
Simulator::Now () >= m_bsrLast + m_bsrPeriodicity) && (m_freshUlBsr==
true))
740 SendReportBufferStatus ();
742 m_freshUlBsr =
false;
743 m_harqProcessId = (m_harqProcessId + 1) % HARQ_PERIOD;
751 m_raPreambleUniformVariable->
SetStream (stream);
virtual void AddLc(uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser *msu)
#define NS_LOG_FUNCTION(parameters)
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
virtual void TransmitPdu(TransmitPduParameters params)
#define NS_ASSERT(condition)
#define NS_LOG_COMPONENT_DEFINE(name)
virtual void ReportBufferStatus(ReportBufferStatusParameters params)
virtual void DoDispose(void)
void SetLteUePhySapProvider(LteUePhySapProvider *s)
Set the PHY SAP Provider.
virtual void SendRachPreamble(uint32_t prachId, uint32_t raRnti)=0
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
virtual void SubframeIndication(uint32_t frameNo, uint32_t subframeNo)
Trigger the start from a new frame (input from Phy layer)
#define NS_FATAL_ERROR(msg)
fatal error handling
virtual void StartContentionBasedRandomAccessProcedure()
virtual void SetTemporaryCellRnti(uint16_t rnti)=0
virtual void StartNonContentionBasedRandomAccessProcedure(uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
virtual void SendMacPdu(Ptr< Packet > p)=0
Send the MAC PDU to the channel.
#define NS_LOG_LOGIC(msg)
virtual void NotifyRandomAccessSuccessful()=0
void DoSubframeIndication(uint32_t frameNo, uint32_t subframeNo)
Forwarded from LteUePhySapUser: trigger the start from a new frame.
virtual void SendLteControlMessage(Ptr< LteControlMessage > msg)=0
Send SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel.
LteUePhySapUser * GetLteUePhySapUser()
Get the PHY SAP user.
virtual void ReceivePhyPdu(Ptr< Packet > p)
virtual void RemoveLc(uint8_t lcId)
#define NS_ASSERT_MSG(condition, message)
virtual void NotifyRandomAccessFailed()=0
virtual void DoDispose(void)
#define NS_LOG_DEBUG(msg)
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
virtual void ReceiveLteControlMessage(Ptr< LteControlMessage > msg)
Receive SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel.
#define NS_LOG_ERROR(msg)
a base class which provides memory management and object aggregation
int64_t AssignStreams(int64_t stream)
a unique identifier for an interface.
TypeId SetParent(TypeId tid)