Introduces RACH procedures in the schedulers and UL grant at PHY layer
authorMarco Miozzo <marco.miozzo@cttc.es>
Mon, 03 Dec 2012 18:18:12 +0100
changeset 9460 0674e66ee483
parent 9429 5696cb87fb88
child 9461 5b0730a0764a
Introduces RACH procedures in the schedulers and UL grant at PHY layer
src/lte/model/ff-mac-common.h
src/lte/model/lte-enb-mac.cc
src/lte/model/lte-enb-mac.h
src/lte/model/lte-enb-phy.cc
src/lte/model/lte-enb-phy.h
src/lte/model/lte-ue-mac.cc
src/lte/model/lte-ue-phy-sap.h
src/lte/model/lte-ue-phy.cc
src/lte/model/lte-ue-phy.h
src/lte/model/pf-ff-mac-scheduler.cc
src/lte/model/pf-ff-mac-scheduler.h
src/lte/model/rr-ff-mac-scheduler.cc
src/lte/model/rr-ff-mac-scheduler.h
src/lte/test/lte-test-pf-ff-mac-scheduler.cc
src/lte/test/lte-test-rr-ff-mac-scheduler.cc
src/lte/test/test-lte-rrc.cc
--- a/src/lte/model/ff-mac-common.h	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/ff-mac-common.h	Mon Dec 03 18:18:12 2012 +0100
@@ -237,12 +237,29 @@
 };
 
 /**
+ * \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;
 };
 
--- a/src/lte/model/lte-enb-mac.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-enb-mac.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -323,7 +323,7 @@
                    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 @@
     {
       // 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 @@
               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 @@
     {
       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 @@
           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 ();
 }
 
 
--- a/src/lte/model/lte-enb-mac.h	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-enb-mac.h	Mon Dec 03 18:18:12 2012 +0100
@@ -255,6 +255,8 @@
   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
--- a/src/lte/model/lte-enb-phy.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-enb-phy.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -481,7 +481,6 @@
   // 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 @@
             {
               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 @@
           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 @@
             {
               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++;
 
--- a/src/lte/model/lte-enb-phy.h	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-enb-phy.h	Mon Dec 03 18:18:12 2012 +0100
@@ -278,8 +278,6 @@
   LteEnbCphySapProvider* m_enbCphySapProvider;
   LteEnbCphySapUser* m_enbCphySapUser;
   
-  std::vector <uint16_t> m_ulRntiRxed;
-
   uint32_t m_nrFrames;
   uint32_t m_nrSubFrames;
   
--- a/src/lte/model/lte-ue-mac.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-ue-mac.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -371,9 +371,9 @@
   // 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 @@
                   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)
                     }
                 }
             }
--- a/src/lte/model/lte-ue-phy-sap.h	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-ue-phy-sap.h	Mon Dec 03 18:18:12 2012 +0100
@@ -58,7 +58,7 @@
    * 
    * \param prachId the ID of the preamble
    */
-  virtual void SendRachPreamble (uint32_t prachId) = 0;
+  virtual void SendRachPreamble (uint32_t prachId, uint32_t raRnti) = 0;
 
 };
 
--- a/src/lte/model/lte-ue-phy.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-ue-phy.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -71,7 +71,7 @@
   // 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 @@
 }
 
 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 @@
     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 @@
 }
 
 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 @@
     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 @@
           // 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 @@
       
       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 @@
       // 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
   
--- a/src/lte/model/lte-ue-phy.h	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/lte-ue-phy.h	Mon Dec 03 18:18:12 2012 +0100
@@ -226,7 +226,7 @@
   // 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 @@
 
   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
--- a/src/lte/model/pf-ff-mac-scheduler.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/pf-ff-mac-scheduler.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -260,6 +260,11 @@
                    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 @@
   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 @@
   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 @@
 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 @@
   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 @@
                 }
               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 @@
 
   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 @@
 
   if (nflows == 0)
     {
+      if (ret.m_dciList.size () > 0)
+        {
+          m_schedSapUser->SchedUlConfigInd (ret);
+        }
+        
       return;  // no flows to be scheduled
     }
 
@@ -1372,7 +1445,8 @@
       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 @@
           (*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 @@
           break;
         }
     }
-  while ((*it).first != m_nextRntiUl);
+  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
 
 
   // Update global UE stats
@@ -1541,6 +1615,7 @@
     }
   m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
   m_schedSapUser->SchedUlConfigInd (ret);
+
   return;
 }
 
@@ -1640,6 +1715,7 @@
       {
         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 @@
               {
                 // 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 @@
           // 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 @@
           // 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++;
--- a/src/lte/model/pf-ff-mac-scheduler.h	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/pf-ff-mac-scheduler.h	Mon Dec 03 18:18:12 2012 +0100
@@ -269,6 +269,12 @@
   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
--- a/src/lte/model/rr-ff-mac-scheduler.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/rr-ff-mac-scheduler.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -262,6 +262,11 @@
                    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 @@
   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 @@
     }
   // 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 @@
   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 @@
 
   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 @@
     }
   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 @@
 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 @@
   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 @@
                 }
               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 @@
 
   if (nflows == 0)
     {
+      if (ret.m_dciList.size () > 0)
+        {
+          m_schedSapUser->SchedUlConfigInd (ret);
+        }
       return;  // no flows to be scheduled
     }
 
@@ -1199,7 +1270,7 @@
       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 @@
       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 @@
           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;
--- a/src/lte/model/rr-ff-mac-scheduler.h	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/model/rr-ff-mac-scheduler.h	Mon Dec 03 18:18:12 2012 +0100
@@ -211,6 +211,7 @@
   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 @@
   // 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
--- a/src/lte/test/lte-test-pf-ff-mac-scheduler.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/test/lte-test-pf-ff-mac-scheduler.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -268,7 +268,7 @@
     }
 
 
-  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 @@
       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));
--- a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -254,7 +254,7 @@
     }
 
 
-  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));
--- a/src/lte/test/test-lte-rrc.cc	Tue Nov 27 10:48:00 2012 +0100
+++ b/src/lte/test/test-lte-rrc.cc	Mon Dec 03 18:18:12 2012 +0100
@@ -75,12 +75,12 @@
 }
 
 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 @@
   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));