Introduces RACH procedures in the schedulers and UL grant at PHY layer

This commit is contained in:
Marco Miozzo
2012-12-03 18:18:12 +01:00
parent f7e0c5f083
commit edf61b954e
16 changed files with 314 additions and 59 deletions

View File

@@ -236,13 +236,30 @@ struct BuildDataListElement_s
std::vector < std::vector <struct RlcPduListElement_s> > 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;
};

View File

@@ -323,7 +323,7 @@ LteEnbMac::GetTypeId (void)
MakeUintegerChecker<uint8_t> (4, 64))
.AddAttribute ("PreambleTransMax",
"Maximum number of random access preamble transmissions",
UintegerValue (10),
UintegerValue (50),
MakeUintegerAccessor (&LteEnbMac::m_preambleTransMax),
MakeUintegerChecker<uint8_t> (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<RarLteControlMessage> rarMsg = Create<RarLteControlMessage> ();
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<uint8_t, uint32_t>::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 <uint16_t, uint32_t> (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<RarLteControlMessage> rarMsg = Create<RarLteControlMessage> ();
uint16_t raRnti = m_subframeNo - 3;
rarMsg->SetRaRnti (raRnti);
for (unsigned int i = 0; i < ind.m_buildRarList.size (); i++)
{
std::map <uint16_t, uint32_t>::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 ();
}

View File

@@ -255,6 +255,8 @@ private:
std::map<uint8_t, NcRaPreambleInfo> m_allocatedNcRaPreambleMap;
std::map<uint8_t, uint32_t> m_receivedRachPreambleCount;
std::map<uint16_t, uint32_t> m_rapIdRntiMap;
};
} // end namespace ns3

View File

@@ -481,7 +481,6 @@ LteEnbPhy::StartSubFrame (void)
// update info on TB to be received
std::list<UlDciLteControlMessage> uldcilist = DequeueUlDci ();
std::list<UlDciLteControlMessage>::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<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
std::list<DlDciListElement_s> dlDci;
std::list<UlDciListElement_s> ulDci;
// std::vector <int> dlRb;
m_dlDataRbMap.clear ();
if (ctrlMsg.size () > 0)
{
@@ -530,7 +525,6 @@ LteEnbPhy::StartSubFrame (void)
if (msg->GetMessageType () == LteControlMessage::DL_DCI)
{
Ptr<DlDciLteControlMessage> dci = DynamicCast<DlDciLteControlMessage> (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<UlDciLteControlMessage> dci = DynamicCast<UlDciLteControlMessage> (msg);
QueueUlDci (*dci);
ulDci.push_back (dci->GetDci ());
}
else if (msg->GetMessageType () == LteControlMessage::RAR)
{
Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
for (std::list<RarLteControlMessage::Rar>::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++;

View File

@@ -278,8 +278,6 @@ private:
LteEnbCphySapProvider* m_enbCphySapProvider;
LteEnbCphySapUser* m_enbCphySapUser;
std::vector <uint16_t> m_ulRntiRxed;
uint32_t m_nrFrames;
uint32_t m_nrSubFrames;

View File

@@ -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<LteControlMessage> 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)
}
}
}

View File

@@ -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;
};

View File

@@ -71,7 +71,7 @@ public:
// inherited from LtePhySapProvider
virtual void SendMacPdu (Ptr<Packet> p);
virtual void SendLteControlMessage (Ptr<LteControlMessage> 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<LteControlMessage> 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<LteSpectrumPhy> dlPhy, Ptr<LteSpectrumPhy> 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 <LteAmc> ();
@@ -536,13 +538,15 @@ LteUePhy::DoSendLteControlMessage (Ptr<LteControlMessage> 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<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
msg->SetRapId (raPreambleId);
m_raPreambleId = raPreambleId;
m_raRnti = raRnti;
m_controlMessagesQueue.at (0).push_back (msg);
}
@@ -604,7 +608,6 @@ LteUePhy::ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> > msgLi
else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
{
// set the uplink bandwidht according to the UL-CQI
NS_LOG_DEBUG (this << " UL DCI");
Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
UlDciListElement_s dci = msg2->GetDci ();
if (dci.m_rnti != m_rnti)
@@ -612,17 +615,49 @@ LteUePhy::ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> > msgLi
// DCI not for me
continue;
}
NS_LOG_INFO (this << " UL DCI");
std::vector <int> 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<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
if (rarMsg->GetRaRnti () == m_raRnti)
{
for (std::list<RarLteControlMessage::Rar>::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 <int> 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<Ptr<LteControlMessage> > 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<PacketBurst> 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 <int> dlRb;
SetSubChannelsForTransmission (dlRb);
m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
}
else
{
NS_LOG_LOGIC (this << " UE - UL NOTHING TO SEND");
}
}
} // m_configured

View File

@@ -226,7 +226,7 @@ private:
// UE PHY SAP methods
virtual void DoSendMacPdu (Ptr<Packet> p);
virtual void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
virtual void DoSendRachPreamble (uint32_t prachId);
virtual void DoSendRachPreamble (uint32_t prachId, uint32_t raRnti);
std::vector <int> m_subChannelsForTransmission;
std::vector <int> m_subChannelsForReception;
@@ -267,6 +267,9 @@ private:
Ptr<LteHarqPhy> 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

View File

@@ -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<uint8_t> ())
;
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 <struct RachListElement_s>::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 <uint16_t> rntiAllocated;
std::vector <uint16_t> 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 <uint16_t>::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 <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
m_schedSapUser->SchedUlConfigInd (ret);
return;
}
@@ -1640,6 +1715,7 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
{
std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
std::map <uint16_t, std::vector <double> >::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 <uint16_t, uint32_t>::iterator itTimers;
itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
@@ -1762,7 +1839,7 @@ PfFfMacScheduler::RefreshDlCqiMaps (void)
// delete correspondent entries
std::map <uint16_t,uint8_t>::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 <uint16_t,uint32_t>::iterator temp = itP10;
itP10++;
@@ -1785,7 +1862,7 @@ PfFfMacScheduler::RefreshDlCqiMaps (void)
// delete correspondent entries
std::map <uint16_t,SbMeasResult_s>::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 <uint16_t,uint32_t>::iterator temp = itA30;
itA30++;

View File

@@ -269,6 +269,12 @@ private:
std::map <uint16_t, UlHarqProcessesStatus_t> m_ulHarqProcessesStatus;
std::map <uint16_t, UlHarqProcessesDciBuffer_t> m_ulHarqProcessesDciBuffer;
// RACH attributes
std::vector <struct RachListElement_s> m_rachList;
std::vector <uint16_t> m_rachAllocationMap;
uint8_t m_ulGrantMcs; // MCS for UL grant (default 0)
};
} // namespace ns3

View File

@@ -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<uint8_t> ())
;
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 <uint16_t> 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 <struct RachListElement_s>::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 <uint16_t> rntiAllocated;
std::vector <uint16_t> 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 <uint16_t>::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 <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
m_schedSapUser->SchedUlConfigInd (ret);
return;

View File

@@ -211,6 +211,7 @@ private:
uint32_t m_cqiTimersThreshold; // # of TTIs for which a CQI canbe considered valid
std::map <uint16_t,uint8_t> m_uesTxMode; // txMode of the UEs
// HARQ attributes
@@ -233,6 +234,12 @@ private:
// x>0: process Id equal to `x` trasmission count
std::map <uint16_t, UlHarqProcessesStatus_t> m_ulHarqProcessesStatus;
std::map <uint16_t, UlHarqProcessesDciBuffer_t> m_ulHarqProcessesDciBuffer;
// RACH attributes
std::vector <struct RachListElement_s> m_rachList;
std::vector <uint16_t> m_rachAllocationMap;
uint8_t m_ulGrantMcs; // MCS for UL grant (default 0)
};
} // namespace ns3

View File

@@ -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));

View File

@@ -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));

View File

@@ -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));