From edf61b954e516c1d23974362dd3dcac1681e1fff Mon Sep 17 00:00:00 2001 From: Marco Miozzo Date: Mon, 3 Dec 2012 18:18:12 +0100 Subject: [PATCH] Introduces RACH procedures in the schedulers and UL grant at PHY layer --- src/lte/model/ff-mac-common.h | 19 +++- src/lte/model/lte-enb-mac.cc | 40 +++++--- src/lte/model/lte-enb-mac.h | 2 + src/lte/model/lte-enb-phy.cc | 33 +++++-- src/lte/model/lte-enb-phy.h | 2 - src/lte/model/lte-ue-mac.cc | 5 +- src/lte/model/lte-ue-phy-sap.h | 2 +- src/lte/model/lte-ue-phy.cc | 55 +++++++++-- src/lte/model/lte-ue-phy.h | 5 +- src/lte/model/pf-ff-mac-scheduler.cc | 97 ++++++++++++++++++-- src/lte/model/pf-ff-mac-scheduler.h | 6 ++ src/lte/model/rr-ff-mac-scheduler.cc | 88 ++++++++++++++++-- src/lte/model/rr-ff-mac-scheduler.h | 7 ++ src/lte/test/lte-test-pf-ff-mac-scheduler.cc | 4 +- src/lte/test/lte-test-rr-ff-mac-scheduler.cc | 2 +- src/lte/test/test-lte-rrc.cc | 6 +- 16 files changed, 314 insertions(+), 59 deletions(-) diff --git a/src/lte/model/ff-mac-common.h b/src/lte/model/ff-mac-common.h index 556f85849..58438cfe3 100644 --- a/src/lte/model/ff-mac-common.h +++ b/src/lte/model/ff-mac-common.h @@ -236,13 +236,30 @@ struct BuildDataListElement_s std::vector < std::vector > m_rlcPduList; }; +/** + * \brief Substitutive structure for specifying BuildRarListElement_s::m_grant field + */ +struct UlGrant_s +{ + uint16_t m_rnti; + uint8_t m_rbStart; + uint8_t m_rbLen; + uint16_t m_tbSize; + uint8_t m_mcs; + bool m_hopping; + int8_t m_tpc; + bool m_cqiRequest; + bool m_ulDelay; +}; + /** * \brief See section 4.3.10 buildRARListElement */ struct BuildRarListElement_s { uint16_t m_rnti; - uint32_t m_grant; + //uint32_t m_grant; // Substituted with type UlGrant_s + UlGrant_s m_grant; struct DlDciListElement_s m_dci; }; diff --git a/src/lte/model/lte-enb-mac.cc b/src/lte/model/lte-enb-mac.cc index db3337e81..845fa3516 100644 --- a/src/lte/model/lte-enb-mac.cc +++ b/src/lte/model/lte-enb-mac.cc @@ -323,7 +323,7 @@ LteEnbMac::GetTypeId (void) MakeUintegerChecker (4, 64)) .AddAttribute ("PreambleTransMax", "Maximum number of random access preamble transmissions", - UintegerValue (10), + UintegerValue (50), MakeUintegerAccessor (&LteEnbMac::m_preambleTransMax), MakeUintegerChecker (3, 200)) .AddAttribute ("RaResponseWindowSize", @@ -473,16 +473,10 @@ LteEnbMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo) { // process received RACH preambles and notify the scheduler FfMacSchedSapProvider::SchedDlRachInfoReqParameters rachInfoReqParams; - // TODO: we should wait for DL_SCHEDULE_INDICATION to build the RARs - // from the RAR_List; this requires proper support from the scheduler. - // For now, we take a shortcut and just build the RAR here - // as an ideal message and without an UL grant. - Ptr rarMsg = Create (); NS_ASSERT (subframeNo > 0 && subframeNo <= 10); // subframe in 1..10 // see TS 36.321 5.1.4; preambles were sent two frames ago // (plus 3GPP counts subframes from 0, not 1) uint16_t raRnti = subframeNo - 3; - rarMsg->SetRaRnti (raRnti); for (std::map::const_iterator it = m_receivedRachPreambleCount.begin (); it != m_receivedRachPreambleCount.end (); ++it) @@ -515,15 +509,10 @@ LteEnbMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo) rachLe.m_rnti = rnti; rachLe.m_estimatedSize = 144; // to be confirmed rachInfoReqParams.m_rachList.push_back (rachLe); - RarLteControlMessage::Rar rar; - rar.rapId = it->first; - rar.rarPayload.m_rnti = rnti; - // no UL grant for now - rarMsg->AddRar (rar); + m_rapIdRntiMap.insert (std::pair (rnti, it->first)); } } m_schedSapProvider->SchedDlRachInfoReq (rachInfoReqParams); - m_enbPhySapProvider->SendLteControlMessage (rarMsg); m_receivedRachPreambleCount.clear (); } // Get downlink transmission opportunities @@ -560,7 +549,7 @@ LteEnbMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo) { if (subframeNo>1) { - m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & frameNo) << 4) | (0xF & subframeNo); + m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & frameNo) << 4) | (0xF & (subframeNo - 1)); } else { @@ -1007,6 +996,29 @@ LteEnbMac::DoSchedDlConfigInd (FfMacSchedSapUser::SchedDlConfigIndParameters ind NS_FATAL_ERROR ("Found element with more than two transport blocks"); } } + + // RACH + Ptr rarMsg = Create (); + uint16_t raRnti = m_subframeNo - 3; + rarMsg->SetRaRnti (raRnti); + for (unsigned int i = 0; i < ind.m_buildRarList.size (); i++) + { + std::map ::iterator itRapId = m_rapIdRntiMap.find (ind.m_buildRarList.at (i).m_rnti); + if (itRapId == m_rapIdRntiMap.end ()) + { + NS_FATAL_ERROR ("Unable to find rapId of RNTI " << ind.m_buildRarList.at (i).m_rnti); + } + RarLteControlMessage::Rar rar; + rar.rapId = itRapId->second; + rar.rarPayload = ind.m_buildRarList.at (i); + rarMsg->AddRar (rar); + NS_LOG_INFO (this << " Send RAR message to RNTI " << ind.m_buildRarList.at (i).m_rnti << " rapId " << itRapId->second); + } + if (ind.m_buildRarList.size () > 0) + { + m_enbPhySapProvider->SendLteControlMessage (rarMsg); + } + m_rapIdRntiMap.clear (); } diff --git a/src/lte/model/lte-enb-mac.h b/src/lte/model/lte-enb-mac.h index 6d826521b..84a7828a4 100644 --- a/src/lte/model/lte-enb-mac.h +++ b/src/lte/model/lte-enb-mac.h @@ -255,6 +255,8 @@ private: std::map m_allocatedNcRaPreambleMap; std::map m_receivedRachPreambleCount; + + std::map m_rapIdRntiMap; }; } // end namespace ns3 diff --git a/src/lte/model/lte-enb-phy.cc b/src/lte/model/lte-enb-phy.cc index 4a2bded27..0a5b7364b 100644 --- a/src/lte/model/lte-enb-phy.cc +++ b/src/lte/model/lte-enb-phy.cc @@ -481,7 +481,6 @@ LteEnbPhy::StartSubFrame (void) // update info on TB to be received std::list uldcilist = DequeueUlDci (); std::list::iterator dciIt = uldcilist.begin (); - m_ulRntiRxed.clear (); NS_LOG_DEBUG (this << " eNB Expected TBs " << uldcilist.size ()); for (dciIt = uldcilist.begin (); dciIt!=uldcilist.end (); dciIt++) { @@ -510,15 +509,11 @@ LteEnbPhy::StartSubFrame (void) { NS_LOG_DEBUG (this << " RNTI " << (*dciIt).GetDci ().m_rnti << " HARQ RETX"); } - m_ulRntiRxed.push_back ((*dciIt).GetDci ().m_rnti); } } // process the current burst of control messages std::list > ctrlMsg = GetControlMessages (); - std::list dlDci; - std::list ulDci; -// std::vector dlRb; m_dlDataRbMap.clear (); if (ctrlMsg.size () > 0) { @@ -530,7 +525,6 @@ LteEnbPhy::StartSubFrame (void) if (msg->GetMessageType () == LteControlMessage::DL_DCI) { Ptr dci = DynamicCast (msg); - dlDci.push_back (dci->GetDci ()); // get the tx power spectral density according to DL-DCI(s) // translate the DCI to Spectrum framework uint32_t mask = 0x1; @@ -551,7 +545,32 @@ LteEnbPhy::StartSubFrame (void) { Ptr dci = DynamicCast (msg); QueueUlDci (*dci); - ulDci.push_back (dci->GetDci ()); + } + else if (msg->GetMessageType () == LteControlMessage::RAR) + { + Ptr rarMsg = DynamicCast (msg); + for (std::list::const_iterator it = rarMsg->RarListBegin (); it != rarMsg->RarListEnd (); ++it) + { + if (it->rarPayload.m_grant.m_ulDelay == true) + { + NS_FATAL_ERROR (" RAR delay is not yet implemented"); + } + UlGrant_s ulGrant = it->rarPayload.m_grant; + // translate the UL grant in a standard UL-DCI and queue it + UlDciListElement_s dci; + dci.m_rnti = ulGrant.m_rnti; + dci.m_rbStart = ulGrant.m_rbStart; + dci.m_rbLen = ulGrant.m_rbLen; + dci.m_tbSize = ulGrant.m_tbSize; + dci.m_mcs = ulGrant.m_mcs; + dci.m_hopping = ulGrant.m_hopping; + dci.m_tpc = ulGrant.m_tpc; + dci.m_cqiRequest = ulGrant.m_cqiRequest; + dci.m_ndi = 1; + UlDciLteControlMessage msg; + msg.SetDci (dci); + QueueUlDci (msg); + } } it++; diff --git a/src/lte/model/lte-enb-phy.h b/src/lte/model/lte-enb-phy.h index 4ad3487f6..ec441cd5f 100644 --- a/src/lte/model/lte-enb-phy.h +++ b/src/lte/model/lte-enb-phy.h @@ -278,8 +278,6 @@ private: LteEnbCphySapProvider* m_enbCphySapProvider; LteEnbCphySapUser* m_enbCphySapUser; - std::vector m_ulRntiRxed; - uint32_t m_nrFrames; uint32_t m_nrSubFrames; diff --git a/src/lte/model/lte-ue-mac.cc b/src/lte/model/lte-ue-mac.cc index e75e6c842..a2abe6127 100644 --- a/src/lte/model/lte-ue-mac.cc +++ b/src/lte/model/lte-ue-mac.cc @@ -371,9 +371,9 @@ LteUeMac::SendRaPreamble (bool contention) // bypass the m_ulConfigured flag. This is reasonable, since In fact // the RACH preamble is sent on 6RB bandwidth so the uplink // bandwidth does not need to be configured. - m_uePhySapProvider->SendRachPreamble (m_raPreambleId); NS_ASSERT (m_subframeNo > 0); // sanity check for subframe starting at 1 m_raRnti = m_subframeNo - 1; + m_uePhySapProvider->SendRachPreamble (m_raPreambleId, m_raRnti); NS_LOG_INFO (this << " sent preamble id " << (uint32_t) m_raPreambleId << ", RA-RNTI " << (uint32_t) m_raRnti); // 3GPP 36.321 5.1.4 Time raWindowBegin = MilliSeconds (3); @@ -590,6 +590,9 @@ LteUeMac::DoReceiveLteControlMessage (Ptr msg) if (it->rapId == m_raPreambleId) // RAR is for me { RecvRaResponse (it->rarPayload); + // TODO:: RRC generates the RecvRaResponse messaged + // for avoiding holes in transmission at PHY layer + // (which produce erroneous UL CQI evaluation) } } } diff --git a/src/lte/model/lte-ue-phy-sap.h b/src/lte/model/lte-ue-phy-sap.h index 7a496c052..b9e0a0e4d 100644 --- a/src/lte/model/lte-ue-phy-sap.h +++ b/src/lte/model/lte-ue-phy-sap.h @@ -58,7 +58,7 @@ public: * * \param prachId the ID of the preamble */ - virtual void SendRachPreamble (uint32_t prachId) = 0; + virtual void SendRachPreamble (uint32_t prachId, uint32_t raRnti) = 0; }; diff --git a/src/lte/model/lte-ue-phy.cc b/src/lte/model/lte-ue-phy.cc index f410fbf67..fcf1fac77 100644 --- a/src/lte/model/lte-ue-phy.cc +++ b/src/lte/model/lte-ue-phy.cc @@ -71,7 +71,7 @@ public: // inherited from LtePhySapProvider virtual void SendMacPdu (Ptr p); virtual void SendLteControlMessage (Ptr msg); - virtual void SendRachPreamble (uint32_t prachId); + virtual void SendRachPreamble (uint32_t prachId, uint32_t raRnti); private: LteUePhy* m_phy; @@ -95,9 +95,9 @@ UeMemberLteUePhySapProvider::SendLteControlMessage (Ptr msg) } void -UeMemberLteUePhySapProvider::SendRachPreamble (uint32_t prachId) +UeMemberLteUePhySapProvider::SendRachPreamble (uint32_t prachId, uint32_t raRnti) { - m_phy->DoSendRachPreamble (prachId); + m_phy->DoSendRachPreamble (prachId, raRnti); } @@ -132,6 +132,8 @@ LteUePhy::LteUePhy (Ptr dlPhy, Ptr ulPhy) m_dlConfigured (false), m_ulConfigured (false), m_addedToDlChannel (false), + m_raPreambleId (255), // value out of range + m_raRnti (11), // value out of range m_rsrpRsrqSampleCounter (0) { m_amc = CreateObject (); @@ -536,13 +538,15 @@ LteUePhy::DoSendLteControlMessage (Ptr msg) } void -LteUePhy::DoSendRachPreamble (uint32_t raPreambleId) +LteUePhy::DoSendRachPreamble (uint32_t raPreambleId, uint32_t raRnti) { NS_LOG_FUNCTION (this << raPreambleId); // unlike other control messages, RACH preamble is sent ASAP Ptr msg = Create (); msg->SetRapId (raPreambleId); + m_raPreambleId = raPreambleId; + m_raRnti = raRnti; m_controlMessagesQueue.at (0).push_back (msg); } @@ -604,7 +608,6 @@ LteUePhy::ReceiveLteControlMessageList (std::list > msgLi else if (msg->GetMessageType () == LteControlMessage::UL_DCI) { // set the uplink bandwidht according to the UL-CQI - NS_LOG_DEBUG (this << " UL DCI"); Ptr msg2 = DynamicCast (msg); UlDciListElement_s dci = msg2->GetDci (); if (dci.m_rnti != m_rnti) @@ -612,17 +615,49 @@ LteUePhy::ReceiveLteControlMessageList (std::list > msgLi // DCI not for me continue; } + NS_LOG_INFO (this << " UL DCI"); std::vector ulRb; for (int i = 0; i < dci.m_rbLen; i++) { ulRb.push_back (i + dci.m_rbStart); //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart); } - QueueSubChannelsForTransmission (ulRb); // pass the info to the MAC m_uePhySapUser->ReceiveLteControlMessage (msg); } + else if (msg->GetMessageType () == LteControlMessage::RAR) + { + Ptr rarMsg = DynamicCast (msg); + if (rarMsg->GetRaRnti () == m_raRnti) + { + for (std::list::const_iterator it = rarMsg->RarListBegin (); it != rarMsg->RarListEnd (); ++it) + { + if (it->rapId != m_raPreambleId) + { + // UL grant not for me + continue; + } + else + { + NS_LOG_INFO ("received RAR RNTI " << m_raRnti); + // set the uplink bandwidht according to the UL grant + std::vector ulRb; + for (int i = 0; i < it->rarPayload.m_grant.m_rbLen; i++) + { + ulRb.push_back (i + it->rarPayload.m_grant.m_rbStart); + } + + QueueSubChannelsForTransmission (ulRb); + // pass the info to the MAC + m_uePhySapUser->ReceiveLteControlMessage (msg); + // reset RACH variables with out of range values + m_raPreambleId = 255; + m_raRnti = 11; + } + } + } + } else if (msg->GetMessageType () == LteControlMessage::MIB) { NS_LOG_INFO ("received MIB"); @@ -682,7 +717,7 @@ LteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo) std::list > ctrlMsg = GetControlMessages (); // send packets in queue - NS_LOG_LOGIC (this << " UE - start TX PUSCH + PUCCH"); + NS_LOG_LOGIC (this << " UE - start slot for PUSCH + PUCCH - RNTI " << m_rnti); // send the current burts of packets Ptr pb = GetPacketBurst (); if (pb) @@ -694,11 +729,15 @@ LteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo) // send only PUCCH (ideal: fake null bandwidth signal) if (ctrlMsg.size ()>0) { - NS_LOG_LOGIC (this << " UE - start TX PUCCH (NO PUSCH)"); + NS_LOG_LOGIC (this << " UE - start TX PUCCH (NO PUSCH)"); std::vector dlRb; SetSubChannelsForTransmission (dlRb); m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION); } + else + { + NS_LOG_LOGIC (this << " UE - UL NOTHING TO SEND"); + } } } // m_configured diff --git a/src/lte/model/lte-ue-phy.h b/src/lte/model/lte-ue-phy.h index 48facaa63..53ea0d653 100644 --- a/src/lte/model/lte-ue-phy.h +++ b/src/lte/model/lte-ue-phy.h @@ -226,7 +226,7 @@ private: // UE PHY SAP methods virtual void DoSendMacPdu (Ptr p); virtual void DoSendLteControlMessage (Ptr msg); - virtual void DoSendRachPreamble (uint32_t prachId); + virtual void DoSendRachPreamble (uint32_t prachId, uint32_t raRnti); std::vector m_subChannelsForTransmission; std::vector m_subChannelsForReception; @@ -267,6 +267,9 @@ private: Ptr m_harqPhyModule; + uint32_t m_raPreambleId; + uint32_t m_raRnti; + /** * Trace information regarding RSRP and RSRQ (see TS 36.214) * uint16_t rnti, uint16_t cellId, double rsrp, double rsrq diff --git a/src/lte/model/pf-ff-mac-scheduler.cc b/src/lte/model/pf-ff-mac-scheduler.cc index 9f143536e..03937246a 100644 --- a/src/lte/model/pf-ff-mac-scheduler.cc +++ b/src/lte/model/pf-ff-mac-scheduler.cc @@ -260,6 +260,11 @@ PfFfMacScheduler::GetTypeId (void) BooleanValue (true), MakeBooleanAccessor (&PfFfMacScheduler::m_harqOn), MakeBooleanChecker ()) + .AddAttribute ("UlGrantMcs", + "The MCS of the UL grant, must be [0..15] (default 0)", + UintegerValue (0), + MakeUintegerAccessor (&PfFfMacScheduler::m_ulGrantMcs), + MakeUintegerChecker ()) ; return tid; } @@ -296,6 +301,7 @@ PfFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::Cs NS_LOG_FUNCTION (this); // Read the subset of parameters used m_cschedCellConfig = params; + m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); FfMacCschedSapUser::CschedUeConfigCnfParameters cnf; cnf.m_result = SUCCESS; m_cschedSapUser->CschedUeConfigCnf (cnf); @@ -563,6 +569,51 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false); FfMacSchedSapUser::SchedDlConfigIndParameters ret; + // RACH Allocation + m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); + uint16_t rbStart = 0; + std::vector ::iterator itRach; + for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++) + { + NS_ASSERT_MSG (m_amc->GetTbSizeFromMcs (m_ulGrantMcs, m_cschedCellConfig.m_ulBandwidth) > (*itRach).m_estimatedSize, " Default UL Grant MCS does not allow to send RACH messages"); + BuildRarListElement_s newRar; + newRar.m_rnti = (*itRach).m_rnti; + // DL-RACH Allocation + // Ideal: no needs of configuring m_dci + // UL-RACH Allocation + newRar.m_grant.m_rnti = newRar.m_rnti; + newRar.m_grant.m_mcs = m_ulGrantMcs; + uint16_t rbLen = 1; + uint16_t tbSizeBits = 0; + // find lowest TB size that fits UL grant estimated size + while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth)) + { + rbLen++; + tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen); + } + if (tbSizeBits < (*itRach).m_estimatedSize) + { + // no more allocation space: finish allocation + break; + } + newRar.m_grant.m_rbStart = rbStart; + newRar.m_grant.m_rbLen = rbLen; + newRar.m_grant.m_tbSize = tbSizeBits / 8; + newRar.m_grant.m_hopping = false; + newRar.m_grant.m_tpc = 0; + newRar.m_grant.m_cqiRequest = false; + newRar.m_grant.m_ulDelay = false; + NS_LOG_INFO (this << " UL grant allocated to RNTI " << (*itRach).m_rnti << " rbStart " << rbStart << " rbLen " << rbLen << " MCS " << m_ulGrantMcs << " tbSize " << newRar.m_grant.m_tbSize); + for (uint16_t i = rbStart; i < rbStart + rbLen; i++) + { + m_rachAllocationMap.at (i) = (*itRach).m_rnti; + } + rbStart = rbStart + rbLen; + + ret.m_buildRarList.push_back (newRar); + } + m_rachList.clear (); + // Process DL HARQ feedback // retrieve past HARQ retx buffered @@ -1113,7 +1164,9 @@ void PfFfMacScheduler::DoSchedDlRachInfoReq (const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters& params) { NS_LOG_FUNCTION (this); - // TODO: Implementation of the API + + m_rachList = params.m_rachList; + return; } @@ -1222,9 +1275,22 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched uint16_t rbAllocatedNum = 0; std::set rntiAllocated; std::vector rbgAllocationMap; - rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); + // update with RACH allocation map + rbgAllocationMap = m_rachAllocationMap; + //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); + m_rachAllocationMap.clear (); + m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false); + // remove RACH allocation + for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++) + { + if (rbgAllocationMap.at (i) != 0) + { + rbMap.at (i) = true; + NS_LOG_DEBUG (this << " Allocated for RACH " << i); + } + } if (m_harqOn == true) @@ -1288,7 +1354,8 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched } else { - NS_FATAL_ERROR ("Cannot allocare retx for UE " << rnti); + NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti); + continue; } dci.m_ndi = 0; // Update HARQ buffers with new HarqId @@ -1307,8 +1374,9 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++) { - // remove old entries of this UE-LC - if ((*it).second > 0) + std::set ::iterator itRnti = rntiAllocated.find ((*it).first); + // select UEs with queues not empty and not yet allocated for HARQ + if (((*it).second > 0)&&(itRnti == rntiAllocated.end ())) { nflows++; } @@ -1316,6 +1384,11 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched if (nflows == 0) { + if (ret.m_dciList.size () > 0) + { + m_schedSapUser->SchedUlConfigInd (ret); + } + return; // no flows to be scheduled } @@ -1372,7 +1445,8 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched uldci.m_rnti = (*it).first; uldci.m_rbLen = rbPerFlow; bool allocated = false; - while ((!allocated)&&((rbAllocated + rbPerFlow - 1) < m_cschedCellConfig.m_ulBandwidth)) + NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow); + while ((!allocated)&&((rbAllocated + rbPerFlow - 1) < m_cschedCellConfig.m_ulBandwidth) && (rbPerFlow != 0)) { // check availability bool free = true; @@ -1498,7 +1572,7 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched (*itDci).second.at (harqId) = uldci; } - NS_LOG_INFO (this << " UE " << (*it).first << " startPRB " << (uint32_t)uldci.m_rbStart << " nPRB " << (uint32_t)uldci.m_rbLen << " CQI " << cqi << " MCS " << (uint32_t)uldci.m_mcs << " TBsize " << uldci.m_tbSize << " RbAlloc " << rbAllocated << " harqId " << (uint16_t)harqId); + NS_LOG_INFO (this << " UE Allocation RNTI " << (*it).first << " startPRB " << (uint32_t)uldci.m_rbStart << " nPRB " << (uint32_t)uldci.m_rbLen << " CQI " << cqi << " MCS " << (uint32_t)uldci.m_mcs << " TBsize " << uldci.m_tbSize << " RbAlloc " << rbAllocated << " harqId " << (uint16_t)harqId); // update TTI UE stats itStats = m_flowStatsUl.find ((*it).first); @@ -1525,7 +1599,7 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched break; } } - while ((*it).first != m_nextRntiUl); + while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0)); // Update global UE stats @@ -1541,6 +1615,7 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched } m_allocationMaps.insert (std::pair > (params.m_sfnSf, rbgAllocationMap)); m_schedSapUser->SchedUlConfigInd (ret); + return; } @@ -1640,6 +1715,7 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched { std::map >::iterator itMap; std::map >::iterator itCqi; + NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf)); itMap = m_allocationMaps.find (params.m_sfnSf); if (itMap == m_allocationMaps.end ()) { @@ -1675,6 +1751,7 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched { // update the value (*itCqi).second.at (i) = sinr; + NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr); // update correspondent timer std::map ::iterator itTimers; itTimers = m_ueCqiTimers.find ((*itMap).second.at (i)); @@ -1762,7 +1839,7 @@ PfFfMacScheduler::RefreshDlCqiMaps (void) // delete correspondent entries std::map ::iterator itMap = m_p10CqiRxed.find ((*itP10).first); NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first); - NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first); + NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first); m_p10CqiRxed.erase (itMap); std::map ::iterator temp = itP10; itP10++; @@ -1785,7 +1862,7 @@ PfFfMacScheduler::RefreshDlCqiMaps (void) // delete correspondent entries std::map ::iterator itMap = m_a30CqiRxed.find ((*itA30).first); NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first); - NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first); + NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first); m_a30CqiRxed.erase (itMap); std::map ::iterator temp = itA30; itA30++; diff --git a/src/lte/model/pf-ff-mac-scheduler.h b/src/lte/model/pf-ff-mac-scheduler.h index c85e67ae3..ace36b9aa 100644 --- a/src/lte/model/pf-ff-mac-scheduler.h +++ b/src/lte/model/pf-ff-mac-scheduler.h @@ -269,6 +269,12 @@ private: std::map m_ulHarqProcessesStatus; std::map m_ulHarqProcessesDciBuffer; + + // RACH attributes + std::vector m_rachList; + std::vector m_rachAllocationMap; + uint8_t m_ulGrantMcs; // MCS for UL grant (default 0) + }; } // namespace ns3 diff --git a/src/lte/model/rr-ff-mac-scheduler.cc b/src/lte/model/rr-ff-mac-scheduler.cc index 7925720f1..6802ab1fb 100644 --- a/src/lte/model/rr-ff-mac-scheduler.cc +++ b/src/lte/model/rr-ff-mac-scheduler.cc @@ -262,6 +262,11 @@ RrFfMacScheduler::GetTypeId (void) BooleanValue (true), MakeBooleanAccessor (&RrFfMacScheduler::m_harqOn), MakeBooleanChecker ()) + .AddAttribute ("UlGrantMcs", + "The MCS of the UL grant, must be [0..15] (default 0)", + UintegerValue (0), + MakeUintegerAccessor (&RrFfMacScheduler::m_ulGrantMcs), + MakeUintegerChecker ()) ; return tid; } @@ -298,6 +303,7 @@ RrFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::Cs NS_LOG_FUNCTION (this); // Read the subset of parameters used m_cschedCellConfig = params; + m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); FfMacCschedSapUser::CschedUeConfigCnfParameters cnf; cnf.m_result = SUCCESS; m_cschedSapUser->CschedUeConfigCnf (cnf); @@ -387,6 +393,7 @@ RrFfMacScheduler::DoSchedDlRlcBufferReq (const struct FfMacSchedSapProvider::Sch } // add the new parameters m_rlcBufferReq.insert (it, params); + NS_LOG_INFO (this << " RNTI " << params.m_rnti << " LC " << (uint16_t)params.m_logicalChannelIdentity << " RLC tx size " << params.m_rlcTransmissionQueueHolDelay << " RLC retx size " << params.m_rlcRetransmissionQueueSize << " RLC stat size " << params.m_rlcStatusPduSize); // initialize statistics of the flow in case of new flows if (newLc == true) { @@ -526,6 +533,51 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched std::set rntiAllocated; rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false); + // RACH Allocation + m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); + uint16_t rbStart = 0; + std::vector ::iterator itRach; + for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++) + { + NS_ASSERT_MSG (m_amc->GetTbSizeFromMcs (m_ulGrantMcs, m_cschedCellConfig.m_ulBandwidth) > (*itRach).m_estimatedSize, " Default UL Grant MCS does not allow to send RACH messages"); + BuildRarListElement_s newRar; + newRar.m_rnti = (*itRach).m_rnti; + // DL-RACH Allocation + // Ideal: no needs of configuring m_dci + // UL-RACH Allocation + newRar.m_grant.m_rnti = newRar.m_rnti; + newRar.m_grant.m_mcs = m_ulGrantMcs; + uint16_t rbLen = 1; + uint16_t tbSizeBits = 0; + // find lowest TB size that fits UL grant estimated size + while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth)) + { + rbLen++; + tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen); + } + if (tbSizeBits < (*itRach).m_estimatedSize) + { + // no more allocation space: finish allocation + break; + } + newRar.m_grant.m_rbStart = rbStart; + newRar.m_grant.m_rbLen = rbLen; + newRar.m_grant.m_tbSize = tbSizeBits / 8; + newRar.m_grant.m_hopping = false; + newRar.m_grant.m_tpc = 0; + newRar.m_grant.m_cqiRequest = false; + newRar.m_grant.m_ulDelay = false; + NS_LOG_INFO (this << " UL grant allocated to RNTI " << (*itRach).m_rnti << " rbStart " << rbStart << " rbLen " << rbLen << " MCS " << (uint16_t) m_ulGrantMcs << " tbSize " << newRar.m_grant.m_tbSize); + for (uint16_t i = rbStart; i < rbStart + rbLen; i++) + { + m_rachAllocationMap.at (i) = (*itRach).m_rnti; + } + rbStart = rbStart + rbLen; + + ret.m_buildRarList.push_back (newRar); + } + m_rachList.clear (); + // Process DL HARQ feedback // retrieve past HARQ retx buffered if (m_dlInfoListBuffered.size () > 0) @@ -826,7 +878,7 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched if (nflows == 0) { - if (ret.m_buildDataList.size () > 0) + if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0)) { m_schedSapUser->SchedDlConfigInd (ret); } @@ -1002,7 +1054,7 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched } while ((*it).m_rnti != m_nextRntiDl); - ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed + ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed m_schedSapUser->SchedDlConfigInd (ret); return; @@ -1012,7 +1064,9 @@ void RrFfMacScheduler::DoSchedDlRachInfoReq (const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters& params) { NS_LOG_FUNCTION (this); - // TODO: Implementation of the API + + m_rachList = params.m_rachList; + return; } @@ -1075,9 +1129,21 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched uint16_t rbAllocatedNum = 0; std::set rntiAllocated; std::vector rbgAllocationMap; - rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); + // update with RACH allocation map + rbgAllocationMap = m_rachAllocationMap; + //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); + m_rachAllocationMap.clear (); + m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0); rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false); + // remove RACH allocation + for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++) + { + if (rbgAllocationMap.at (i) != 0) + { + rbMap.at (i) = true; + } + } if (m_harqOn == true) { @@ -1140,7 +1206,8 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched } else { - NS_FATAL_ERROR ("Cannot allocare retx for UE " << rnti); + NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti); + continue; } dci.m_ndi = 0; // Update HARQ buffers with new HarqId @@ -1168,6 +1235,10 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched if (nflows == 0) { + if (ret.m_dciList.size () > 0) + { + m_schedSapUser->SchedUlConfigInd (ret); + } return; // no flows to be scheduled } @@ -1199,7 +1270,7 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched it = m_ceBsrRxed.begin (); m_nextRntiUl = (*it).first; } - NS_LOG_INFO (this << " RB per Flow " << rbPerFlow); + NS_LOG_INFO (this << " NFlows " << nflows << " RB per Flow " << rbPerFlow); do { std::set ::iterator itRnti = rntiAllocated.find ((*it).first); @@ -1224,7 +1295,7 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched uldci.m_rnti = (*it).first; uldci.m_rbLen = rbPerFlow; bool allocated = false; - while ((!allocated)&&((rbAllocated + rbPerFlow - 1) < m_cschedCellConfig.m_ulBandwidth)) + while ((!allocated)&&((rbAllocated + rbPerFlow - 1) < m_cschedCellConfig.m_ulBandwidth) && (rbPerFlow != 0)) { // check availability bool free = true; @@ -1355,7 +1426,8 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched break; } } - while ((*it).first != m_nextRntiUl); + while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0)); + m_allocationMaps.insert (std::pair > (params.m_sfnSf, rbgAllocationMap)); m_schedSapUser->SchedUlConfigInd (ret); return; diff --git a/src/lte/model/rr-ff-mac-scheduler.h b/src/lte/model/rr-ff-mac-scheduler.h index 11f636eb0..b34d8ec0c 100644 --- a/src/lte/model/rr-ff-mac-scheduler.h +++ b/src/lte/model/rr-ff-mac-scheduler.h @@ -211,6 +211,7 @@ private: uint32_t m_cqiTimersThreshold; // # of TTIs for which a CQI canbe considered valid std::map m_uesTxMode; // txMode of the UEs + // HARQ attributes @@ -233,6 +234,12 @@ private: // x>0: process Id equal to `x` trasmission count std::map m_ulHarqProcessesStatus; std::map m_ulHarqProcessesDciBuffer; + + + // RACH attributes + std::vector m_rachList; + std::vector m_rachAllocationMap; + uint8_t m_ulGrantMcs; // MCS for UL grant (default 0) }; } // namespace ns3 diff --git a/src/lte/test/lte-test-pf-ff-mac-scheduler.cc b/src/lte/test/lte-test-pf-ff-mac-scheduler.cc index 86be27e57..e7f0fc98e 100644 --- a/src/lte/test/lte-test-pf-ff-mac-scheduler.cc +++ b/src/lte/test/lte-test-pf-ff-mac-scheduler.cc @@ -268,7 +268,7 @@ LenaPfFfMacSchedulerTestCase1::DoRun (void) } - double statsStartTime = 0.060; // need to allow for RRC connection establishment + SRS + double statsStartTime = 0.100; // need to allow for RRC connection establishment + SRS double statsDuration = 0.6; double tolerance = 0.1; Simulator::Stop (Seconds (statsStartTime + statsDuration - 0.000001)); @@ -428,7 +428,7 @@ LenaPfFfMacSchedulerTestCase2::DoRun (void) uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0)); } - double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS + double statsStartTime = 0.100; // need to allow for RRC connection establishment + SRS double statsDuration = 0.4; double tolerance = 0.1; Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001)); diff --git a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc index 782b35cc5..2841db144 100644 --- a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc +++ b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc @@ -254,7 +254,7 @@ LenaRrFfMacSchedulerTestCase::DoRun (void) } - double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS + double statsStartTime = 0.100; // need to allow for RRC connection establishment + SRS double statsDuration = 0.4; double tolerance = 0.1; Simulator::Stop (Seconds (statsStartTime + statsDuration - 0.0001)); diff --git a/src/lte/test/test-lte-rrc.cc b/src/lte/test/test-lte-rrc.cc index 55404a308..b49c4254f 100644 --- a/src/lte/test/test-lte-rrc.cc +++ b/src/lte/test/test-lte-rrc.cc @@ -75,12 +75,12 @@ std::string LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUe } LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart) - : TestCase ("RRC connection establishment"), + : TestCase (BuildNameString (nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart)), m_nUes (nUes), m_nBearers (nBearers), m_tConnBase (tConnBase), m_tConnIncrPerUe (tConnIncrPerUe), - m_delayConnEnd (150), // includes: time to receive system information, time for Random Access (RACH preamble, RAR response), time to send and receive RRC connection request+setup+completed. Value should be slightly higher than T300 in TS 36.331 + m_delayConnEnd (140+nUes*8/4), // includes: time to receive system information, time for Random Access (RACH preamble, RAR response), time to send and receive RRC connection request+setup+completed. Value should be slightly higher than T300 in TS 36.331 m_delayDiscStart (delayDiscStart), m_delayDiscEnd (10) { @@ -263,7 +263,7 @@ LteRrcTestSuite::LteRrcTestSuite () AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 4, 0, 20, 0, 1)); AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 4, 0, 20, 300, 1)); AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 20, 0, 10, 1, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 50, 0, 10, 0, 1)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 50, 0, 0, 0, 1)); // // time consuming tests with a lot of UEs // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100, 0, 10, 0, 1));