25 #include <ns3/pointer.h>
26 #include <ns3/packet.h>
27 #include <ns3/packet-burst.h>
28 #include <ns3/random-variable.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>
63 virtual void RemoveLc (uint8_t lcId);
64 virtual void Reset ();
199 .AddConstructor<LteUeMac> ();
205 : m_bsrPeriodicity (MilliSeconds (1)),
206 m_bsrLast (MilliSeconds (0)),
207 m_freshUlBsr (false),
210 m_rachConfigured (false),
211 m_waitingForRaResponse (false)
297 std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
304 (*it).second = params;
308 m_ulBsrReceived.insert (std::pair<uint8_t, LteMacSapProvider::ReportBufferStatusParameters> (params.
lcid, params));
335 std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator it;
336 std::vector<uint32_t> queue (4, 0);
339 uint8_t lcid = it->first;
340 std::map <uint8_t, LcInfo>::iterator lcInfoMapIt;
343 NS_ASSERT_MSG ((lcid != 0) || (((*it).second.txQueueSize == 0)
344 && ((*it).second.retxQueueSize == 0)
345 && ((*it).second.statusPduSize == 0)),
346 "BSR should not be used for LCID 0");
347 uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
348 queue.at (lcg) += ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
372 bool contention =
true;
392 Time raWindowBegin = MilliSeconds (3);
421 const uint8_t lc0Lcid = 0;
422 std::map <uint8_t, LcInfo>::iterator lc0InfoIt =
m_lcInfoMap.find (lc0Lcid);
424 std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator lc0BsrIt
427 && (lc0BsrIt->second.txQueueSize > 0))
430 "segmentation of Message 3 is not allowed");
431 lc0InfoIt->second.macSapUser->NotifyTxOpportunity (raResponse.
m_grant.
m_tbSize, 0, 0);
432 lc0BsrIt->second.txQueueSize = 0;
445 NS_LOG_INFO (
"RAR timeout, preambleTransMax reached => giving up");
486 NS_ASSERT_MSG (prachMask == 0,
"requested PRACH MASK = " << (uint32_t) prachMask <<
", but only PRACH MASK = 0 is supported");
489 bool contention =
false;
501 lcInfo.macSapUser = msu;
517 std::map <uint8_t, LcInfo>::iterator it =
m_lcInfoMap.begin ();
546 it->second.macSapUser->ReceivePdu (p);
565 std::map <uint8_t, LteMacSapProvider::ReportBufferStatusParameters>::iterator itBsr;
566 uint16_t activeLcs = 0;
567 uint32_t statusPduMinSize = 0;
570 if (((*itBsr).second.statusPduSize > 0) || ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
573 if (((*itBsr).second.statusPduSize!=0)&&((*itBsr).second.statusPduSize < statusPduMinSize))
575 statusPduMinSize = (*itBsr).second.statusPduSize;
577 if (((*itBsr).second.statusPduSize!=0)&&(statusPduMinSize == 0))
579 statusPduMinSize = (*itBsr).second.statusPduSize;
585 NS_LOG_ERROR (
this <<
" No active flows for this UL-DCI");
588 std::map <uint8_t, LcInfo>::iterator it;
589 uint32_t bytesPerActiveLc = dci.m_tbSize / activeLcs;
590 bool statusPduPriority =
false;
591 if ((statusPduMinSize != 0)&&(bytesPerActiveLc < statusPduMinSize))
594 statusPduPriority =
true;
595 NS_LOG_DEBUG (
this <<
" Reduced resource -> send only Status, b ytes " << statusPduMinSize);
596 if (dci.m_tbSize < statusPduMinSize)
598 NS_FATAL_ERROR (
"Insufficient Tx Opportunity for sending a status message");
601 NS_LOG_LOGIC (
this <<
" UE " <<
m_rnti <<
": UL-CQI notified TxOpportunity of " << dci.m_tbSize <<
" => " << bytesPerActiveLc <<
" bytes per active LC" <<
" statusPduMinSize " << statusPduMinSize);
605 NS_LOG_DEBUG (
this <<
" Processing LC " << (uint32_t)(*it).first <<
" bytesPerActiveLc " << bytesPerActiveLc);
607 ( ((*itBsr).second.statusPduSize > 0) ||
608 ((*itBsr).second.retxQueueSize > 0) ||
609 ((*itBsr).second.txQueueSize > 0)) )
611 if ((statusPduPriority) && ((*itBsr).second.statusPduSize == statusPduMinSize))
613 (*it).second.macSapUser->NotifyTxOpportunity ((*itBsr).second.statusPduSize, 0, 0);
614 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);
615 (*itBsr).second.statusPduSize = 0;
620 uint32_t bytesForThisLc = bytesPerActiveLc;
621 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);
622 if (((*itBsr).second.statusPduSize > 0) && (bytesForThisLc > (*itBsr).second.statusPduSize))
624 (*it).second.macSapUser->NotifyTxOpportunity ((*itBsr).second.statusPduSize, 0, 0);
625 bytesForThisLc -= (*itBsr).second.statusPduSize;
626 NS_LOG_DEBUG (
this <<
" serve STATUS " << (*itBsr).second.statusPduSize);
627 (*itBsr).second.statusPduSize = 0;
631 if ((*itBsr).second.statusPduSize>bytesForThisLc)
633 NS_FATAL_ERROR (
"Insufficient Tx Opportunity for sending a status message");
637 if ((bytesForThisLc > 7) &&
638 (((*itBsr).second.retxQueueSize > 0) ||
639 ((*itBsr).second.txQueueSize > 0)))
641 if ((*itBsr).second.retxQueueSize > 0)
643 NS_LOG_DEBUG (
this <<
" serve retx DATA, bytes " << bytesForThisLc);
644 (*it).second.macSapUser->NotifyTxOpportunity (bytesForThisLc, 0, 0);
645 if ((*itBsr).second.retxQueueSize >= bytesForThisLc)
647 (*itBsr).second.retxQueueSize -= bytesForThisLc;
651 (*itBsr).second.retxQueueSize = 0;
654 else if ((*itBsr).second.txQueueSize > 0)
656 uint16_t lcid = (*it).first;
657 uint32_t rlcOverhead;
671 NS_LOG_DEBUG (
this <<
" serve tx DATA, bytes " << bytesForThisLc <<
", RLC overhead " << rlcOverhead);
672 (*it).second.macSapUser->NotifyTxOpportunity (bytesForThisLc, 0, 0);
673 if ((*itBsr).second.txQueueSize >= bytesForThisLc - rlcOverhead)
675 (*itBsr).second.txQueueSize -= bytesForThisLc - rlcOverhead;
679 (*itBsr).second.txQueueSize = 0;
685 if ( ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0))
691 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);
716 uint16_t raRnti = rarMsg->GetRaRnti ();
717 NS_LOG_LOGIC (
this <<
"got RAR with RA-RNTI " << (uint32_t) raRnti <<
", expecting " << (uint32_t)
m_raRnti);
718 if (raRnti == m_raRnti)
720 for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin ();
721 it != rarMsg->RarListEnd ();
737 NS_LOG_WARN (
this <<
" LteControlMessage not recognized");
753 NS_LOG_INFO (
this <<
" HARQ Proc Id " << i <<
" packets buffer expired");
uint8_t numberOfRaPreambles
virtual void AddLc(uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser *msu)
add a new Logical Channel (LC)
void DoStartNonContentionBasedRandomAccessProcedure(uint16_t rnti, uint8_t rapId, uint8_t prachMask)
LteUeCmacSapProvider::LogicalChannelConfig lcConfig
uint8_t GetLcid(void) const
keep track of time values and allow control of global simulation resolution
uint8_t raResponseWindowSize
#define NS_LOG_FUNCTION(parameters)
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
virtual void TransmitPdu(TransmitPduParameters params)
send an RLC PDU to the MAC for transmission.
void SendRaPreamble(bool contention)
void StartWaitingForRaResponse()
void DoReceivePhyPdu(Ptr< Packet > p)
Ptr< UniformRandomVariable > m_raPreambleUniformVariable
uint16_t GetRnti(void) const
LteUePhySapUser * m_uePhySapUser
void AddPacketTag(const Tag &tag) const
Add a packet tag.
#define NS_ASSERT(condition)
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
void RaResponseTimeout(bool contention)
See section 4.3.2 ulDciListElement.
virtual void ReportBufferStatus(ReportBufferStatusParameters params)
Report the RLC buffer status to the MAC.
struct MacCeValue_u m_macCeValue
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
See section 4.3.10 buildRARListElement.
void DoAddLc(uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser *msu)
void SetLteUePhySapProvider(LteUePhySapProvider *s)
Set the PHY SAP Provider.
virtual void SendRachPreamble(uint32_t prachId, uint32_t raRnti)=0
send a preamble on the PRACH
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Service Access Point (SAP) offered by the PHY to the MAC.
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
void DoStartContentionBasedRandomAccessProcedure()
void SendReportBufferStatus(void)
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()
tell the MAC to start a contention-based random access procedure, e.g., to perform RRC connection est...
void DoRemoveLc(uint8_t lcId)
Parameters for LteMacSapProvider::ReportBufferStatus.
std::vector< uint8_t > m_miUlHarqProcessesPacketTimer
friend class UeMemberLteUePhySapUser
void SetLteUeCmacSapUser(LteUeCmacSapUser *s)
void DoTransmitPdu(LteMacSapProvider::TransmitPduParameters params)
virtual void ConfigureRach(RachConfig rc)
virtual void SetTemporaryCellRnti(uint16_t rnti)=0
friend class UeMemberLteMacSapProvider
static uint8_t BufferSize2BsrId(uint32_t val)
virtual void Reset()
reset the MAC
bool m_waitingForRaResponse
void DoReportBufferStatus(LteMacSapProvider::ReportBufferStatusParameters params)
virtual void StartNonContentionBasedRandomAccessProcedure(uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
tell the MAC to start a non-contention-based random access procedure, e.g., as a consequence of hando...
virtual void SendMacPdu(Ptr< Packet > p)=0
Send the MAC PDU to the channel.
LteUeCmacSapProvider * m_cmacSapProvider
uint16_t rnti
the C-RNTI identifying the UE
std::vector< Ptr< PacketBurst > > m_miUlHarqProcessesPacket
LteUeCmacSapProvider * GetLteUeCmacSapProvider(void)
Service Access Point (SAP) offered by the UE MAC to the UE RRC.
#define NS_LOG_LOGIC(msg)
void DoConfigureRach(LteUeCmacSapProvider::RachConfig rc)
virtual void NotifyRandomAccessSuccessful()=0
Notify the RRC that the MAC Random Access procedure completed successfully.
See section 4.3.14 macCEListElement.
void DoSubframeIndication(uint32_t frameNo, uint32_t subframeNo)
Forwarded from LteUePhySapUser: trigger the start from a new frame.
UeMemberLteUeCmacSapProvider(LteUeMac *mac)
void DoReceiveLteControlMessage(Ptr< LteControlMessage > msg)
Ptr< Packet > Copy(void) const
std::map< uint8_t, LcInfo > m_lcInfoMap
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.
LteMacSapProvider * GetLteMacSapProvider(void)
uint16_t m_backoffParameter
static TypeId GetTypeId(void)
UeMemberLteUePhySapUser(LteUeMac *mac)
LteMacSapProvider * m_macSapProvider
Service Access Point (SAP) offered by the UE MAC to the UE RRC.
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
virtual void ReceivePhyPdu(Ptr< Packet > p)
Called by the Phy to notify the MAC of the reception of a new PHY-PDU.
LteUePhySapProvider * m_uePhySapProvider
static Time Now(void)
Return the "current simulation time".
virtual void RemoveLc(uint8_t lcId)
remove an existing LC
#define NS_ASSERT_MSG(condition, message)
std::vector< uint8_t > m_bufferStatus
NS_LOG_COMPONENT_DEFINE("LteUeMac")
virtual void NotifyRandomAccessFailed()=0
Notify the RRC that the MAC Random Access procedure failed.
void RandomlySelectAndSendRaPreamble()
void RecvRaResponse(BuildRarListElement_s raResponse)
uint8_t m_preambleTransmissionCounter
Service Access Point (SAP) offered by the MAC to the RLC See Femto Forum MAC Scheduler Interface Spec...
EventId m_noRaResponseReceivedEvent
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
LteUeCmacSapProvider::RachConfig m_rachConfig
Service Access Point (SAP) offered by the UE-PHY to the UE-MAC.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
#define NS_LOG_DEBUG(msg)
Ptr< Packet > pdu
the RLC PDU
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::cancel method.
Service Access Point (SAP) offered by the MAC to the RLC See Femto Forum MAC Scheduler Interface Spec...
Tag used to define the RNTI and LC id for each MAC packet trasmitted.
enum ns3::MacCeListElement_s::MacCeType_e m_macCeType
virtual void ReceiveLteControlMessage(Ptr< LteControlMessage > msg)
Receive SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel.
#define NS_LOG_ERROR(msg)
std::map< uint8_t, LteMacSapProvider::ReportBufferStatusParameters > m_ulBsrReceived
a base class which provides memory management and object aggregation
friend class UeMemberLteUeCmacSapProvider
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
void RefreshHarqProcessesPacketBuffer(void)
UeMemberLteMacSapProvider(LteUeMac *mac)
LteUeCmacSapUser * m_cmacSapUser
Parameters for LteMacSapProvider::TransmitPdu.