Attempt to initial synchronization, cell search, MIB and SIB1
authorBudiarto Herman <budiarto.herman@magister.fi>
Tue, 16 Jul 2013 09:43:01 +0300
changeset 10288 ea6c9b15169c
parent 10286 32d90164bfcc
child 10289 c2a694b5598c
Attempt to initial synchronization, cell search, MIB and SIB1
src/lte/helper/lte-helper.cc
src/lte/model/lte-control-messages.cc
src/lte/model/lte-control-messages.h
src/lte/model/lte-enb-cphy-sap.h
src/lte/model/lte-enb-phy.cc
src/lte/model/lte-enb-phy.h
src/lte/model/lte-rrc-protocol-ideal.cc
src/lte/model/lte-rrc-protocol-ideal.h
src/lte/model/lte-rrc-protocol-real.cc
src/lte/model/lte-rrc-protocol-real.h
src/lte/model/lte-rrc-sap.h
src/lte/model/lte-spectrum-phy.cc
src/lte/model/lte-ue-cphy-sap.h
src/lte/model/lte-ue-phy.cc
src/lte/model/lte-ue-phy.h
src/lte/model/lte-ue-rrc.cc
src/lte/model/lte-ue-rrc.h
src/lte/test/lte-test-cell-selection.cc
src/lte/test/lte-test-cell-selection.h
src/lte/wscript
--- a/src/lte/helper/lte-helper.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/helper/lte-helper.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -328,6 +328,9 @@
   Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
   Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
 
+  dlPhy->SetChannel (m_downlinkChannel);
+  ulPhy->SetChannel (m_uplinkChannel);
+
   Ptr<LteEnbPhy> phy = CreateObject<LteEnbPhy> (dlPhy, ulPhy);
 
   Ptr<LteHarqPhy> harq = Create<LteHarqPhy> ();
@@ -344,9 +347,6 @@
   Ptr<LteInterferencePowerChunkProcessor> pInterf = Create<LteInterferencePowerChunkProcessor> (phy);
   ulPhy->AddInterferenceDataChunkProcessor (pInterf); // for interference power tracing
 
-  dlPhy->SetChannel (m_downlinkChannel);
-  ulPhy->SetChannel (m_uplinkChannel);
-
   Ptr<MobilityModel> mm = n->GetObject<MobilityModel> ();
   NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteHelper::InstallUeDevice ()");
   dlPhy->SetMobility (mm);
@@ -472,6 +472,9 @@
   Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
   Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
 
+  dlPhy->SetChannel (m_downlinkChannel);
+  ulPhy->SetChannel (m_uplinkChannel);
+
   Ptr<LteUePhy> phy = CreateObject<LteUePhy> (dlPhy, ulPhy);
 
   Ptr<LteHarqPhy> harq = Create<LteHarqPhy> ();
@@ -491,9 +494,6 @@
   Ptr<LteDataSinrChunkProcessor> pData = Create<LteDataSinrChunkProcessor> (dlPhy);
   dlPhy->AddDataSinrChunkProcessor (pData);
 
-  dlPhy->SetChannel (m_downlinkChannel);
-  ulPhy->SetChannel (m_uplinkChannel);
-
   Ptr<MobilityModel> mm = n->GetObject<MobilityModel> ();
   NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteHelper::InstallUeDevice ()");
   dlPhy->SetMobility (mm);
--- a/src/lte/model/lte-control-messages.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-control-messages.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -258,11 +258,33 @@
 }
 
 
+// ----------------------------------------------------------------------------------------------------------
+
+
+
+Sib1LteControlMessage::Sib1LteControlMessage (void)
+{
+  SetMessageType (LteControlMessage::SIB1);
+}
+
+
+void
+Sib1LteControlMessage::SetSib1 (LteRrcSap::SystemInformationBlockType1 sib1)
+{
+  m_sib1 = sib1;
+}
+
+LteRrcSap::SystemInformationBlockType1
+Sib1LteControlMessage::GetSib1 () const
+{
+  return m_sib1;
+}
 
 
 // ---------------------------------------------------------------------------
 
 
+
 DlHarqFeedbackLteControlMessage::DlHarqFeedbackLteControlMessage (void)
 {
   SetMessageType (LteControlMessage::DL_HARQ);
--- a/src/lte/model/lte-control-messages.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-control-messages.h	Tue Jul 16 09:43:01 2013 +0300
@@ -58,6 +58,7 @@
     RACH_PREAMBLE, // Random Access Preamble
     RAR, // Random Access Response
     MIB, // Master Information Block
+    SIB1, // System Information Block Type 1
   };
 
   LteControlMessage (void);
@@ -465,3 +466,36 @@
 } // namespace ns3
 
 #endif  // MIB_LTE_CONTROL_MESSAGES_H
+
+
+
+#ifndef SIB1_LTE_CONTROL_MESSAGES_H
+#define SIB1_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+/**
+ * \ingroup lte
+ * \brief Model for broadcasting the System Information Block Type 1
+ */
+class Sib1LteControlMessage : public LteControlMessage
+{
+public:
+
+  Sib1LteControlMessage (void);
+
+  void SetSib1 (LteRrcSap::SystemInformationBlockType1 sib1);
+
+  LteRrcSap::SystemInformationBlockType1 GetSib1 () const;
+
+private:
+
+  LteRrcSap::SystemInformationBlockType1 m_sib1;
+
+};
+
+} // namespace ns3
+
+#endif  // SIB1_LTE_CONTROL_MESSAGES_H
--- a/src/lte/model/lte-enb-cphy-sap.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-enb-cphy-sap.h	Tue Jul 16 09:43:01 2013 +0300
@@ -96,6 +96,12 @@
    * \param mib the Master Information Block to be sent on the BCH
    */
   virtual void SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib) = 0;
+
+  /**
+   *
+   * \param sib1 the System Information Block Type 1 to be sent on the BCH
+   */
+  virtual void SetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1) = 0;
 };
 
 
@@ -137,6 +143,7 @@
   virtual void SetTransmissionMode (uint16_t  rnti, uint8_t txMode);
   virtual void SetSrsConfigurationIndex (uint16_t  rnti, uint16_t srsCi);
   virtual void SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
+  virtual void SetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1);
   
 private:
   MemberLteEnbCphySapProvider ();
@@ -211,6 +218,13 @@
   m_owner->DoSetMasterInformationBlock (mib);
 }
 
+template <class C>
+void
+MemberLteEnbCphySapProvider<C>::SetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1)
+{
+  m_owner->DoSetSystemInformationBlockType1 (sib1);
+}
+
 
 
 /**
--- a/src/lte/model/lte-enb-phy.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-enb-phy.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -525,6 +525,21 @@
   NS_LOG_FUNCTION (this);
 
   ++m_nrSubFrames;
+
+  /*
+   * Send SIB1 at 6th subframe of every odd-numbered radio frame. This is
+   * equivalent with Section 5.2.1.2 of 3GPP TS 36.331, where it is specified
+   * "repetitions are scheduled in subframe #5 of all other radio frames for
+   * which SFN mod 2 = 0," except that 3GPP counts frames and subframes starting
+   * from 0, while ns-3 counts starting from 1.
+   */
+  if ((m_nrSubFrames == 6) && ((m_nrFrames % 2) == 1))
+    {
+      Ptr<Sib1LteControlMessage> msg = Create<Sib1LteControlMessage> ();
+      msg->SetSib1 (m_sib1);
+      m_controlMessagesQueue.at (0).push_back (msg);
+    }
+
   if (m_srsPeriodicity>0)
     { 
       // might be 0 in case the eNB has no UEs attached
@@ -974,6 +989,14 @@
 
 
 void
+LteEnbPhy::DoSetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1)
+{
+  NS_LOG_FUNCTION (this);
+  m_sib1 = sib1;
+}
+
+
+void
 LteEnbPhy::SetHarqPhyModule (Ptr<LteHarqPhy> harq)
 {
   m_harqPhyModule = harq;
--- a/src/lte/model/lte-enb-phy.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-enb-phy.h	Tue Jul 16 09:43:01 2013 +0300
@@ -264,6 +264,7 @@
   void DoSetTransmissionMode (uint16_t  rnti, uint8_t txMode);
   void DoSetSrsConfigurationIndex (uint16_t  rnti, uint16_t srcCi);  
   void DoSetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
+  void DoSetSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1);
 
   // LteEnbPhySapProvider forwarded methods
   void DoSendMacPdu (Ptr<Packet> p);  
@@ -301,6 +302,7 @@
   uint16_t m_currentSrsOffset;
 
   LteRrcSap::MasterInformationBlock m_mib;
+  LteRrcSap::SystemInformationBlockType1 m_sib1;
 
   Ptr<LteHarqPhy> m_harqPhyModule;
 
--- a/src/lte/model/lte-rrc-protocol-ideal.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-rrc-protocol-ideal.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -323,50 +323,6 @@
 }
 
 void 
-LteEnbRrcProtocolIdeal::DoSendMasterInformationBlock (LteRrcSap::MasterInformationBlock msg)
-{
-  NS_LOG_FUNCTION (this);
-  for (std::map<uint16_t, LteUeRrcSapProvider*>::const_iterator it = m_enbRrcSapProviderMap.begin ();
-       it != m_enbRrcSapProviderMap.end ();
-       ++it)
-    {
-      Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
-                           &LteUeRrcSapProvider::RecvMasterInformationBlock,
-                           it->second, 
-                           msg);
-    }
-}
-
-void 
-LteEnbRrcProtocolIdeal::DoSendSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg)
-{
-  NS_LOG_FUNCTION (this << m_cellId);
- // walk list of all nodes to get UEs with this cellId
-  Ptr<LteUeRrc> ueRrc;
-  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
-    {
-      Ptr<Node> node = *i;
-      int nDevs = node->GetNDevices ();
-      for (int j = 0; j < nDevs; ++j)
-        {
-          Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
-          if (ueDev != 0)
-            {
-              NS_LOG_LOGIC ("considering UE " << ueDev->GetImsi ());
-              Ptr<LteUeRrc> ueRrc = ueDev->GetRrc ();              
-              if (ueRrc->GetCellId () == m_cellId)
-                {       
-                  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
-                                       &LteUeRrcSapProvider::RecvSystemInformationBlockType1,
-                                       ueRrc->GetLteUeRrcSapProvider (), 
-                                       msg);          
-                }             
-            }
-        }
-    } 
-}
-
-void 
 LteEnbRrcProtocolIdeal::DoSendSystemInformation (LteRrcSap::SystemInformation msg)
 {
   NS_LOG_FUNCTION (this << m_cellId);
--- a/src/lte/model/lte-rrc-protocol-ideal.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-rrc-protocol-ideal.h	Tue Jul 16 09:43:01 2013 +0300
@@ -116,8 +116,6 @@
   // methods forwarded from LteEnbRrcSapUser
   void DoSetupUe (uint16_t rnti, LteEnbRrcSapUser::SetupUeParameters params);
   void DoRemoveUe (uint16_t rnti);
-  void DoSendMasterInformationBlock (LteRrcSap::MasterInformationBlock msg);
-  void DoSendSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg);
   void DoSendSystemInformation (LteRrcSap::SystemInformation msg);
   void SendSystemInformation (LteRrcSap::SystemInformation msg);
   void DoSendRrcConnectionSetup (uint16_t rnti, LteRrcSap::RrcConnectionSetup msg);
--- a/src/lte/model/lte-rrc-protocol-real.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-rrc-protocol-real.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -503,50 +503,6 @@
 }
 
 void 
-LteEnbRrcProtocolReal::DoSendMasterInformationBlock (LteRrcSap::MasterInformationBlock msg)
-{
-  NS_LOG_FUNCTION (this);
-  for (std::map<uint16_t, LteUeRrcSapProvider*>::const_iterator it = m_enbRrcSapProviderMap.begin ();
-       it != m_enbRrcSapProviderMap.end ();
-       ++it)
-    {
-      Simulator::Schedule (RRC_REAL_MSG_DELAY, 
-                           &LteUeRrcSapProvider::RecvMasterInformationBlock,
-                           it->second, 
-                           msg);
-    }
-}
-
-void 
-LteEnbRrcProtocolReal::DoSendSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg)
-{
-  NS_LOG_FUNCTION (this << m_cellId);
-  // walk list of all nodes to get UEs with this cellId
-  Ptr<LteUeRrc> ueRrc;
-  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
-    {
-      Ptr<Node> node = *i;
-      int nDevs = node->GetNDevices ();
-      for (int j = 0; j < nDevs; ++j)
-        {
-          Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
-          if (ueDev != 0)
-            {
-              NS_LOG_LOGIC ("considering UE " << ueDev->GetImsi ());
-              Ptr<LteUeRrc> ueRrc = ueDev->GetRrc ();
-              if (ueRrc->GetCellId () == m_cellId)
-                {
-                  Simulator::Schedule (RRC_REAL_MSG_DELAY, 
-                                       &LteUeRrcSapProvider::RecvSystemInformationBlockType1,
-                                       ueRrc->GetLteUeRrcSapProvider (), 
-                                       msg);
-                }
-            }
-        }
-    } 
-}
-
-void 
 LteEnbRrcProtocolReal::DoSendSystemInformation (LteRrcSap::SystemInformation msg)
 {
   NS_LOG_FUNCTION (this << m_cellId);
--- a/src/lte/model/lte-rrc-protocol-real.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-rrc-protocol-real.h	Tue Jul 16 09:43:01 2013 +0300
@@ -128,8 +128,6 @@
   // methods forwarded from LteEnbRrcSapUser
   void DoSetupUe (uint16_t rnti, LteEnbRrcSapUser::SetupUeParameters params);
   void DoRemoveUe (uint16_t rnti);
-  void DoSendMasterInformationBlock (LteRrcSap::MasterInformationBlock msg);
-  void DoSendSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg);
   void DoSendSystemInformation (LteRrcSap::SystemInformation msg);
   void SendSystemInformation (LteRrcSap::SystemInformation msg);
   void DoSendRrcConnectionSetup (uint16_t rnti, LteRrcSap::RrcConnectionSetup msg);
--- a/src/lte/model/lte-rrc-sap.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-rrc-sap.h	Tue Jul 16 09:43:01 2013 +0300
@@ -77,6 +77,12 @@
     uint32_t csgIdentity;
   };
 
+  struct CellSelectionInfo
+  {
+    int8_t qRxLevMin; ///< INTEGER (-70..-22), actual value = IE value * 2 [dBm].
+    int8_t qQualMin; ///< INTEGER (-34..-3), actual value = IE value [dB].
+  };
+
   struct FreqInfo
   {
     uint16_t ulCarrierFreq;
@@ -459,6 +465,7 @@
   struct SystemInformationBlockType1
   {
     CellAccessRelatedInfo cellAccessRelatedInfo;
+    CellSelectionInfo cellSelectionInfo;
   };
 
   struct SystemInformationBlockType2
@@ -633,8 +640,6 @@
   };
 
   virtual void CompleteSetup (CompleteSetupParameters params) = 0;
-  virtual void RecvMasterInformationBlock (MasterInformationBlock msg) = 0;
-  virtual void RecvSystemInformationBlockType1 (SystemInformationBlockType1 msg) = 0;
   virtual void RecvSystemInformation (SystemInformation msg) = 0;
   virtual void RecvRrcConnectionSetup (RrcConnectionSetup msg) = 0;
   virtual void RecvRrcConnectionReconfiguration (RrcConnectionReconfiguration msg) = 0;
@@ -663,7 +668,6 @@
 
   virtual void SetupUe (uint16_t rnti, SetupUeParameters params) = 0;
   virtual void RemoveUe (uint16_t rnti) = 0;
-  virtual void SendSystemInformationBlockType1 (SystemInformationBlockType1 msg) = 0;
   virtual void SendSystemInformation (SystemInformation msg) = 0;
   virtual void SendRrcConnectionSetup (uint16_t rnti, RrcConnectionSetup msg) = 0;
   virtual void SendRrcConnectionReconfiguration (uint16_t rnti, RrcConnectionReconfiguration msg) = 0;
@@ -812,8 +816,6 @@
 
   // methods inherited from LteUeRrcSapProvider go here
   virtual void CompleteSetup (CompleteSetupParameters params);
-  virtual void RecvMasterInformationBlock (MasterInformationBlock msg);
-  virtual void RecvSystemInformationBlockType1 (SystemInformationBlockType1 msg);
   virtual void RecvSystemInformation (SystemInformation msg);
   virtual void RecvRrcConnectionSetup (RrcConnectionSetup msg);
   virtual void RecvRrcConnectionReconfiguration (RrcConnectionReconfiguration msg);
@@ -847,20 +849,6 @@
 
 template <class C>
 void
-MemberLteUeRrcSapProvider<C>::RecvMasterInformationBlock (MasterInformationBlock msg)
-{
-  Simulator::ScheduleNow (&C::DoRecvMasterInformationBlock, m_owner, msg);
-}
-
-template <class C>
-void
-MemberLteUeRrcSapProvider<C>::RecvSystemInformationBlockType1 (SystemInformationBlockType1 msg)
-{
-  Simulator::ScheduleNow (&C::DoRecvSystemInformationBlockType1, m_owner, msg);
-}
-
-template <class C>
-void
 MemberLteUeRrcSapProvider<C>::RecvSystemInformation (SystemInformation msg)
 {
   Simulator::ScheduleNow (&C::DoRecvSystemInformation, m_owner, msg);
@@ -924,8 +912,6 @@
 
   virtual void SetupUe (uint16_t rnti, SetupUeParameters params);
   virtual void RemoveUe (uint16_t rnti);
-  virtual void SendMasterInformationBlock (MasterInformationBlock msg);
-  virtual void SendSystemInformationBlockType1 (SystemInformationBlockType1 msg);
   virtual void SendSystemInformation (SystemInformation msg);
   virtual void SendRrcConnectionSetup (uint16_t rnti, RrcConnectionSetup msg);
   virtual void SendRrcConnectionReconfiguration (uint16_t rnti, RrcConnectionReconfiguration msg);
@@ -970,20 +956,6 @@
 
 template <class C>
 void
-MemberLteEnbRrcSapUser<C>::SendMasterInformationBlock (MasterInformationBlock msg)
-{
-  m_owner->DoSendMasterInformationBlock (msg);
-}
-
-template <class C>
-void
-MemberLteEnbRrcSapUser<C>::SendSystemInformationBlockType1 (SystemInformationBlockType1 msg)
-{
-  m_owner->DoSendSystemInformationBlockType1 (msg);
-}
-
-template <class C>
-void
 MemberLteEnbRrcSapUser<C>::SendSystemInformation (SystemInformation msg)
 {
   m_owner->DoSendSystemInformation (msg);
--- a/src/lte/model/lte-spectrum-phy.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-spectrum-phy.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -114,6 +114,7 @@
 
 LteSpectrumPhy::LteSpectrumPhy ()
   : m_state (IDLE),
+    m_cellId (0),
   m_transmissionMode (0),
   m_layersNum (1)
 {
--- a/src/lte/model/lte-ue-cphy-sap.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-ue-cphy-sap.h	Tue Jul 16 09:43:01 2013 +0300
@@ -54,7 +54,25 @@
   virtual void Reset () = 0;
 
   /** 
-   * tell the PHY to synchronize with a given eNB for communication purposes
+   * \brief Tell the PHY to retry the cell search procedure with a different
+   *        cell.
+   */
+  virtual void RetryCellSearch () = 0;
+
+  /**
+   * \brief Tell the PHY to perform normal communication with the cell that it
+   *        is currently synchronized to.
+   *
+   * \sa SyncronizeWithEnb, SetDlBandwidth
+   */
+  virtual void Attach () = 0;
+
+  /**
+   * \brief Tell the PHY to synchronize with a given eNB for communication
+   *        purposes. Initially, the PHY will be configured to listen to 6 RBs
+   *        for BCH.
+   *
+   * SetDlBandwidth can be called afterwards to change the bandwidth.
    * 
    * \param cellId the ID of the eNB
    * \param dlEarfcn  the carrier frequency (EARFCN) in downlink
@@ -133,6 +151,12 @@
 
   /**
    *
+   * \param sib1 the System Information Block Type 1 received on the BCH
+   */
+  virtual void RecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1) = 0;
+
+  /**
+   *
    * \param params the structure containing the vector of cellId, SRSP and RSRQ
    */
   virtual void ReportUeMeasurements (UeMeasurementsParameters params) = 0;
@@ -154,6 +178,8 @@
 
   // inherited from LteUeCphySapProvider
   virtual void Reset ();
+  virtual void RetryCellSearch ();
+  virtual void Attach ();
   virtual void SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);  
   virtual void SetDlBandwidth (uint8_t ulBandwidth);
   virtual void ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
@@ -186,6 +212,20 @@
 
 template <class C>
 void 
+MemberLteUeCphySapProvider<C>::RetryCellSearch ()
+{
+  m_owner->DoRetryCellSearch ();
+}
+
+template <class C>
+void
+MemberLteUeCphySapProvider<C>::Attach ()
+{
+  m_owner->DoAttach ();
+}
+
+template <class C>
+void
 MemberLteUeCphySapProvider<C>::SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn)
 {
   m_owner->DoSyncronizeWithEnb (cellId, dlEarfcn);
@@ -241,7 +281,7 @@
 
   // methods inherited from LteUeCphySapUser go here
   virtual void RecvMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
-
+  virtual void RecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1);
   virtual void ReportUeMeasurements (LteUeCphySapUser::UeMeasurementsParameters params);
 
 private:
@@ -269,6 +309,13 @@
 
 template <class C>
 void
+MemberLteUeCphySapUser<C>::RecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 sib1)
+{
+  m_owner->DoRecvSystemInformationBlockType1 (sib1);
+}
+
+template <class C>
+void
 MemberLteUeCphySapUser<C>::ReportUeMeasurements (LteUeCphySapUser::UeMeasurementsParameters params)
 {
   m_owner->DoReportUeMeasurements (params);
--- a/src/lte/model/lte-ue-phy.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-ue-phy.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -106,6 +106,18 @@
 // LteUePhy methods
 ////////////////////////////////////////
 
+const char* g_uePhyStateName[LteUePhy::NUM_STATES] =
+  {
+    "CELL_SEARCH",
+    "DECODING_BCH",
+    "ATTACHED"
+  };
+
+std::string ToString (LteUePhy::State s)
+{
+  return std::string (g_uePhyStateName[s]);
+}
+
 
 NS_OBJECT_ENSURE_REGISTERED (LteUePhy);
 
@@ -122,6 +134,7 @@
     m_a30CqiPeriocity (MilliSeconds (1)),  // ideal behavior
     m_uePhySapUser (0),
     m_ueCphySapUser (0),
+    m_state (CELL_SEARCH),
     m_subframeNo (0),
     m_rsReceivedPowerUpdated (false),
     m_rsInterferencePowerUpdated (false),
@@ -255,6 +268,9 @@
     .AddTraceSource ("ReportUeMeasurements",
                      "Report UE measurements RSRP (dBm) and RSRQ (dB).",
                      MakeTraceSourceAccessor (&LteUePhy::m_reportUeMeasurements))
+    .AddTraceSource ("StateTransition",
+                     "Trace fired upon every UE PHY state transition",
+                     MakeTraceSourceAccessor (&LteUePhy::m_stateTransitionTrace))
   ;
   return tid;
 }
@@ -408,12 +424,8 @@
 {
   NS_LOG_FUNCTION (this);
 
-  if ((!(m_dlConfigured && m_ulConfigured)) || (m_rnti == 0))
-    {
-      // abort method, the UE is still not registered
-      m_pssList.clear ();
-      return;
-    }
+  NS_ASSERT (m_state != CELL_SEARCH);
+  NS_ASSERT (m_cellId > 0);
 
   // check periodic wideband CQI
   if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity)
@@ -528,7 +540,7 @@
     }
 
 
-  
+
 }
 
 void
@@ -660,28 +672,68 @@
 {
   NS_LOG_FUNCTION (this << Simulator::Now ());
   NS_LOG_DEBUG (this << " Report UE Measurements ");
+
   LteUeCphySapUser::UeMeasurementsParameters ret;
+  double maxRsrp = -std::numeric_limits<double>::infinity ();
+  uint16_t maxRsrpCellId = 0;
+
   std::map <uint16_t, UeMeasurementsElement>::iterator it;
   for (it = m_UeMeasurementsMap.begin (); it != m_UeMeasurementsMap.end (); it++)
     {
       double avg_rsrp = (*it).second.rsrpSum / (double)(*it).second.rsrpNum;
       double avg_rsrq = (*it).second.rsrqSum / (double)(*it).second.rsrqNum;
-      NS_LOG_DEBUG (this << " CellId " << (*it).first << " RSRP " << avg_rsrp << " (nSamples " << (*it).second.rsrpNum << ") RSRQ " << avg_rsrq << " (nSamples " << (*it).second.rsrpNum << ")");
+      NS_LOG_DEBUG (this << " CellId " << (*it).first
+                    << " RSRP " << avg_rsrp << " (nSamples " << (uint16_t)(*it).second.rsrpNum
+                    << ") RSRQ " << avg_rsrq << " (nSamples " << (uint16_t)(*it).second.rsrpNum << ")");
+
+      if ((m_state == CELL_SEARCH) && (maxRsrp < avg_rsrp))
+        {
+          std::set<uint16_t>::const_iterator itSib1 = m_cellHasDecodedSib1.find (it->first);
+          if (itSib1 == m_cellHasDecodedSib1.end ())
+            {
+              std::set<uint16_t>::const_iterator itMib = m_cellHasDecodedMib.find (it->first);
+              if (itMib == m_cellHasDecodedMib.end ())
+                {
+                  maxRsrp = avg_rsrp;
+                  maxRsrpCellId = it->first;
+                  /*
+                   * The end result of this nested if block is to find a cell
+                   * with strongest RSRP which MIB and SIB1 have not been
+                   * received yet.
+                   */
+                }
+            }
+        }
+
       LteUeCphySapUser::UeMeasurementsElement newEl;
       newEl.m_cellId = (*it).first;
       newEl.m_rsrp = avg_rsrp;
       newEl.m_rsrq = avg_rsrq;
       ret.m_ueMeasurementsList.push_back (newEl);
+
       // report to UE measurements trace
       m_reportUeMeasurements (m_rnti, m_cellId, avg_rsrp, avg_rsrq, ((*it).first == m_cellId ? 1 : 0));
     }
-  m_ueCphySapUser-> ReportUeMeasurements(ret);
+
+  if (m_state == CELL_SEARCH)
+    {
+      if (maxRsrpCellId == 0)
+        {
+          NS_LOG_WARN (this << " Cell search has detected no surrounding cell");
+        }
+      else
+        {
+          DoSyncronizeWithEnb (maxRsrpCellId, m_dlEarfcn);
+        }
+    }
+
+  // report to RRC
+  m_ueCphySapUser-> ReportUeMeasurements (ret);
+
   m_UeMeasurementsMap.clear ();
   Simulator::Schedule (m_ueMeasurementsFilterPeriod, &LteUePhy::ReportUeMeasurements, this);
 }
 
-
-
 void
 LteUePhy::DoSendLteControlMessage (Ptr<LteControlMessage> msg)
 {
@@ -828,9 +880,25 @@
     else if (msg->GetMessageType () == LteControlMessage::MIB) 
       {
         NS_LOG_INFO ("received MIB");
+        NS_ASSERT (m_cellId > 0);
+        if (m_state == DECODING_BCH)
+          {
+            m_cellHasDecodedMib.insert (m_cellId);
+          }
         Ptr<MibLteControlMessage> msg2 = DynamicCast<MibLteControlMessage> (msg);
         m_ueCphySapUser->RecvMasterInformationBlock (msg2->GetMib ());
       }
+    else if (msg->GetMessageType () == LteControlMessage::SIB1)
+      {
+        NS_LOG_INFO ("received SIB1");
+        NS_ASSERT (m_cellId > 0);
+        if (m_state == DECODING_BCH)
+          {
+            m_cellHasDecodedSib1.insert (m_cellId);
+          }
+        Ptr<Sib1LteControlMessage> msg2 = DynamicCast<Sib1LteControlMessage> (msg);
+        m_ueCphySapUser->RecvSystemInformationBlockType1 (msg2->GetSib1 ());
+      }
     else
     {
       // pass the message to UE-MAC
@@ -847,14 +915,7 @@
 LteUePhy::ReceivePss (uint16_t cellId, Ptr<SpectrumValue> p)
 {
   NS_LOG_FUNCTION (this << cellId << (*p));
-  if (!m_dlConfigured)
-    {
-      // LteUePhy not yet configured -> skip measurement
-      return;
-    }
-  m_pssReceived = true;
-  PssElement el;
-  el.cellId = cellId;
+
   double sum = 0.0;
   uint16_t nRB = 0;
   Values::const_iterator itPi;
@@ -865,10 +926,57 @@
       sum += powerTxW;
       nRB++;
     }
-  el.pssPsdSum = sum;
-  el.nRB = nRB;
-  m_pssList.push_back (el);
-}
+
+  if (m_cellId == 0)
+    {
+      /*
+       * PHY is not synchronized to any cell, no RX is running, so interference
+       * value is not available and GenerateCtrlCqiReport will not be called.
+       * Utilize the PSS now for calculating RSRP measurements.
+       */
+      NS_LOG_DEBUG (this << " Process PSS RNTI 0 cellId 0");
+      double rsrp_dBm = 10 * log10 (1000 * (sum / (double)nRB));
+      NS_LOG_INFO (this << " PSS received from CellId " << cellId
+                        << " has RSRP " << rsrp_dBm << " and RBnum " << nRB);
+      // Note that m_pssReceptionThreshold does not apply here
+
+      // store measurements
+      std::map <uint16_t, UeMeasurementsElement>::iterator itMeasMap = m_UeMeasurementsMap.find (cellId);
+      if (itMeasMap == m_UeMeasurementsMap.end ())
+        {
+          // insert new entry
+          UeMeasurementsElement newEl;
+          newEl.rsrpSum = rsrp_dBm;
+          newEl.rsrpNum = 1;
+          newEl.rsrqSum = 0; // RSRQ is not available
+          newEl.rsrqNum = 1;
+          m_UeMeasurementsMap.insert (std::pair <uint16_t, UeMeasurementsElement> (cellId, newEl));
+        }
+      else
+        {
+          (*itMeasMap).second.rsrpSum += rsrp_dBm;
+          (*itMeasMap).second.rsrpNum++;
+          (*itMeasMap).second.rsrqSum += 0; // RSRQ is not available
+          (*itMeasMap).second.rsrqNum++;
+        }
+
+    } // end of if (m_cellId == 0)
+  else
+    {
+      /*
+       * Collect the PSS for later processing in GenerateCtrlCqiReport
+       * (to be called from ChunkProcessor after RX is finished).
+       */
+      m_pssReceived = true;
+      PssElement el;
+      el.cellId = cellId;
+      el.pssPsdSum = sum;
+      el.nRB = nRB;
+      m_pssList.push_back (el);
+
+    } // end of else of if (m_cellId == 0)
+
+} // end of void LteUePhy::ReceivePss (uint16_t cellId, Ptr<SpectrumValue> p)
 
 
 void
@@ -1005,25 +1113,50 @@
   m_sendSrsEvent.Cancel ();
   m_downlinkSpectrumPhy->Reset ();
   m_uplinkSpectrumPhy->Reset ();
+
+  // configure DL for receiving PSS
+  m_dlEarfcn = 100; // TODO hardcoded value
+  m_noiseFigure = 9.0; // TODO hardcoded value
+  NS_ASSERT (m_downlinkSpectrumPhy->GetChannel () != 0);
+  DoSetDlBandwidth (6);
+
+  SwitchToState (CELL_SEARCH);
+
+} // end of void LteUePhy::DoReset ()
+
+void
+LteUePhy::DoRetryCellSearch ()
+{
+  NS_LOG_FUNCTION (this);
+  SwitchToState (CELL_SEARCH);
+}
+
+void
+LteUePhy::DoAttach ()
+{
+  NS_ASSERT_MSG (m_state == DECODING_BCH, "Unable to attach from state " << ToString (m_state));
+  m_cellHasDecodedMib.clear ();
+  m_cellHasDecodedSib1.clear ();
+  SwitchToState (ATTACHED);
 }
 
 void
 LteUePhy::DoSyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn)
 {
-  NS_LOG_FUNCTION (this << cellId);
+  NS_LOG_FUNCTION (this << cellId << dlEarfcn);
+
   m_cellId = cellId;
   m_dlEarfcn = dlEarfcn;
   m_downlinkSpectrumPhy->SetCellId (cellId);
   m_uplinkSpectrumPhy->SetCellId (cellId);
 
-  // configure DL for receing the BCH with the minimum bandwith
-  m_dlBandwidth = 6;
-  Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
-  m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
-  m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);  
-  
+  // configure DL for receiving the BCH with the minimum bandwidth
+  DoSetDlBandwidth (6);
+
   m_dlConfigured = false;
   m_ulConfigured = false;
+
+  SwitchToState (DECODING_BCH);
 }
 
 void
@@ -1186,4 +1319,25 @@
 }
 
 
+LteUePhy::State
+LteUePhy::GetState ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_state;
+}
+
+
+void
+LteUePhy::SwitchToState (State newState)
+{
+  NS_LOG_FUNCTION (this << newState);
+  State oldState = m_state;
+  m_state = newState;
+  NS_LOG_INFO (this << " cellId=" << m_cellId << " rnti=" << m_rnti
+                    << " UePhy " << ToString (oldState)
+                    << " --> " << ToString (newState));
+  m_stateTransitionTrace (m_cellId, m_rnti, oldState, newState);
+}
+
+
 } // namespace ns3
--- a/src/lte/model/lte-ue-phy.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-ue-phy.h	Tue Jul 16 09:43:01 2013 +0300
@@ -32,6 +32,7 @@
 #include <ns3/lte-ue-cphy-sap.h>
 #include <ns3/ptr.h>
 #include <ns3/lte-amc.h>
+#include <set>
 
 
 namespace ns3 {
@@ -54,6 +55,17 @@
 
 public:
   /**
+   * \brief The states of the UE PHY entity
+   */
+  enum State
+  {
+    CELL_SEARCH = 0,
+    DECODING_BCH,
+    ATTACHED,
+    NUM_STATES
+  };
+
+  /**
    * @warning the default constructor should not be used
    */
   LteUePhy ();
@@ -179,8 +191,6 @@
   // callbacks for LteSpectrumPhy
   virtual void ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> >);
   virtual void ReceivePss (uint16_t cellId, Ptr<SpectrumValue> p);
-  
-  
 
 
 
@@ -214,6 +224,10 @@
   */
   void SetHarqPhyModule (Ptr<LteHarqPhy> harq);
 
+  /**
+   * \return The current state
+   */
+  State GetState ();
 
 
 
@@ -232,8 +246,12 @@
 
   void ReportUeMeasurements ();
 
+  void SwitchToState (State s);
+
   // UE CPHY SAP methods
   void DoReset ();  
+  void DoRetryCellSearch ();
+  void DoAttach ();
   void DoSyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);  
   void DoSetDlBandwidth (uint8_t ulBandwidth);
   void DoConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
@@ -281,6 +299,10 @@
   bool m_dlConfigured;
   bool m_ulConfigured;
 
+  State m_state;
+  //             cellid    rnti
+  TracedCallback<uint16_t, uint16_t, State, State> m_stateTransitionTrace;
+
   uint8_t m_subframeNo;
 
   bool m_rsReceivedPowerUpdated;
@@ -312,6 +334,16 @@
   Time m_ueMeasurementsFilterPeriod;
   Time m_ueMeasurementsFilterLast;
 
+  /**
+   * \brief List of cell ID which MIB has been decoded by this UE PHY instance.
+   */
+  std::set<uint16_t> m_cellHasDecodedMib;
+
+  /**
+   * \brief List of cell ID which SIB1 has been decoded by this UE PHY instance.
+   */
+  std::set<uint16_t> m_cellHasDecodedSib1;
+
   Ptr<LteHarqPhy> m_harqPhyModule;
 
   uint32_t m_raPreambleId;
--- a/src/lte/model/lte-ue-rrc.cc	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-ue-rrc.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -187,6 +187,17 @@
                    UintegerValue (0), // unused, read-only attribute
                    MakeUintegerAccessor (&LteUeRrc::GetRnti),
                    MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("CellSearchRetryTimeout",
+                   "Maximum number of retry attempts during the initial cell selection procedure to find a suitable cell",
+                   UintegerValue (3),
+                   MakeUintegerAccessor (&LteUeRrc::m_cellSearchRetryTimeout),
+                   MakeUintegerChecker<uint16_t> (0))
+    .AddTraceSource ("MibReceived",
+                     "trace fired upon reception of Master Information Block",
+                     MakeTraceSourceAccessor (&LteUeRrc::m_mibReceivedTrace))
+    .AddTraceSource ("Sib1Received",
+                     "trace fired upon reception of System Information Block Type 1",
+                     MakeTraceSourceAccessor (&LteUeRrc::m_sib1ReceivedTrace))
     .AddTraceSource ("StateTransition",
                      "trace fired upon every UE RRC state transition",
                      MakeTraceSourceAccessor (&LteUeRrc::m_stateTransitionTrace))
@@ -489,7 +500,8 @@
     
   m_cellId = cellId;
   m_dlEarfcn = earfcn;
-  m_cphySapProvider->SyncronizeWithEnb (m_cellId, m_dlEarfcn); 
+  m_cphySapProvider->SyncronizeWithEnb (m_cellId, m_dlEarfcn);
+  m_cphySapProvider->Attach ();
   SwitchToState (IDLE_WAIT_SYSTEM_INFO);
 }
 
@@ -535,9 +547,36 @@
 LteUeRrc::DoRecvMasterInformationBlock (LteRrcSap::MasterInformationBlock msg)  
 { 
   NS_LOG_FUNCTION (this);
+  // TODO may speed up a bit if only execute the following when bandwidth changes?
   m_dlBandwidth = msg.dlBandwidth;
   m_cphySapProvider->SetDlBandwidth (msg.dlBandwidth);
   m_receivedMib = true;
+  m_mibReceivedTrace (m_imsi, m_cellId, m_rnti);
+
+  if (m_state == IDLE_CELL_SELECTION && m_receivedMib && m_receivedSib1)
+    {
+      InitialCellSelection ();
+    }
+
+  if (m_state == IDLE_WAIT_SYSTEM_INFO && m_receivedMib && m_receivedSib2)
+    {
+      SwitchToState (IDLE_CAMPED_NORMALLY);
+    }
+}
+
+void
+LteUeRrc::DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg)
+{
+  NS_LOG_FUNCTION (this);
+  m_receivedSib1 = true;
+  m_lastSib1 = msg;
+  m_sib1ReceivedTrace (m_imsi, m_cellId, m_rnti);
+
+  if (m_state == IDLE_CELL_SELECTION && m_receivedMib && m_receivedSib1)
+    {
+      InitialCellSelection ();
+    }
+
   if (m_state == IDLE_WAIT_SYSTEM_INFO && m_receivedMib && m_receivedSib2)
     {
       SwitchToState (IDLE_CAMPED_NORMALLY);
@@ -581,14 +620,6 @@
 
 
 void 
-LteUeRrc::DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg)
-{
-  NS_LOG_FUNCTION (this);
-  // to be implemented
-}
-
- 
-void 
 LteUeRrc::DoRecvSystemInformation (LteRrcSap::SystemInformation msg)
 {
   NS_LOG_FUNCTION (this);
@@ -756,6 +787,25 @@
 
 
 
+void
+LteUeRrc::InitialCellSelection ()
+{
+  NS_LOG_FUNCTION (this);
+  uint16_t cellId = m_lastSib1.cellAccessRelatedInfo.cellIdentity;
+  // TODO evaluate cell selection criteria
+  // TODO if passed, camp to that cell and switch to IDLE_CAMPED_NORMALLY
+  // TODO if not, call m_cphySapProvider->RetryCellSearch
+  // TODO if retry timeout is exceeded, stop the procedure here (in reality UE will connect to an acceptable cell, but we don't model it here)
+
+  m_cellId = cellId;
+  m_cphySapProvider->SyncronizeWithEnb (m_cellId, 100); // TODO hardcoded value
+  m_cphySapProvider->SetDlBandwidth (m_dlBandwidth);
+  m_cphySapProvider->Attach ();
+  SwitchToState (IDLE_CAMPED_NORMALLY);
+
+}
+
+
 void 
 LteUeRrc::ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd)
 {
--- a/src/lte/model/lte-ue-rrc.h	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/model/lte-ue-rrc.h	Tue Jul 16 09:43:01 2013 +0300
@@ -264,11 +264,11 @@
 
   // CPHY SAP methods
   void DoRecvMasterInformationBlock (LteRrcSap::MasterInformationBlock msg);
+  void DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg);
   void DoReportUeMeasurements (LteUeCphySapUser::UeMeasurementsParameters params);
 
   // RRC SAP methods
   void DoCompleteSetup (LteUeRrcSapProvider::CompleteSetupParameters params);
-  void DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg);
   void DoRecvSystemInformation (LteRrcSap::SystemInformation msg);
   void DoRecvRrcConnectionSetup (LteRrcSap::RrcConnectionSetup msg);
   void DoRecvRrcConnectionReconfiguration (LteRrcSap::RrcConnectionReconfiguration msg);
@@ -279,6 +279,7 @@
 
  
   // internal methods
+  void InitialCellSelection ();
   void ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd);
   /// 3GPP TS 36.331 section 5.5.2 Measurement configuration
   void ApplyMeasConfig (LteRrcSap::MeasConfig mc);
@@ -322,6 +323,8 @@
   Ptr<LteSignalingRadioBearerInfo> m_srb1Old;
   std::map <uint8_t, Ptr<LteDataRadioBearerInfo> > m_drbMap;
   
+  uint8_t m_cellSearchRetryTimeout;
+
   bool m_useRlcSm;
 
   uint8_t m_lastRrcTransactionIdentifier;
@@ -333,6 +336,10 @@
   uint16_t m_ulEarfcn;  /**< uplink carrier frequency */
 
   //             imsi      cellid    rnti
+  TracedCallback<uint64_t, uint16_t, uint16_t> m_mibReceivedTrace;
+  //             imsi      cellid    rnti
+  TracedCallback<uint64_t, uint16_t, uint16_t> m_sib1ReceivedTrace;
+  //             imsi      cellid    rnti
   TracedCallback<uint64_t, uint16_t, uint16_t, State, State> m_stateTransitionTrace;
   //             imsi      cellid    rnti
   TracedCallback<uint64_t, uint16_t, uint16_t> m_randomAccessSuccessfulTrace;
@@ -347,8 +354,10 @@
 
   bool m_connectionPending; /**< true if a connection request by upper layers is pending */
   bool m_receivedMib; /**< true if MIB was received for the current cell  */
+  bool m_receivedSib1; /**< true if SIB1 was received for the current cell  */
   bool m_receivedSib2; /**< true if SIB2 was received for the current cell  */
 
+  LteRrcSap::SystemInformationBlockType1 m_lastSib1;
 
   /**
    * \brief Includes the accumulated configuration of the measurements to be
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-cell-selection.cc	Tue Jul 16 09:43:01 2013 +0300
@@ -0,0 +1,276 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 University of Jyväskylä
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Budiarto Herman <buherman@student.jyu.fi>
+ *
+ */
+
+#include "lte-test-cell-selection.h"
+
+#include <ns3/simulator.h>
+#include <ns3/log.h>
+#include <ns3/boolean.h>
+
+#include <ns3/mobility-helper.h>
+#include <ns3/lte-helper.h>
+#include <ns3/epc-helper.h>
+#include <ns3/internet-stack-helper.h>
+#include <ns3/point-to-point-helper.h>
+#include <ns3/ipv4-address-helper.h>
+#include <ns3/ipv4-static-routing-helper.h>
+
+#include <ns3/node-container.h>
+#include <ns3/net-device-container.h>
+#include <ns3/ipv4-interface-container.h>
+
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-ue-net-device.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteCellSelectionTest");
+
+namespace ns3 {
+
+
+/*
+ * Test Suite
+ */
+
+
+LteCellSelectionTestSuite::LteCellSelectionTestSuite ()
+  : TestSuite ("lte-cell-selection", SYSTEM)
+{
+  LogComponentEnableAll (LOG_PREFIX_ALL);
+  LogComponentEnable ("LteCellSelectionTest", LOG_FUNCTION);
+  //LogComponentEnable ("LteUePhy", LOG_INFO);
+  //LogComponentEnable ("LteUePhy", LOG_WARN);
+  //LogComponentEnable ("LteUePhy", LOG_DEBUG);
+  //LogComponentEnable ("LteUePhy", LOG_FUNCTION);
+  //LogComponentEnable ("LteSpectrumPhy", LOG_LOGIC);
+  //LogComponentEnable ("LteSpectrumPhy", LOG_FUNCTION);
+  //LogComponentEnable ("LteEnbPhy", LOG_FUNCTION);
+  LogComponentEnable ("LteUeRrc", LOG_FUNCTION);
+
+  std::vector<LteCellSelectionTestCase::UeSetup_t> x;
+
+  x.clear ();
+  x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (0, 0, 0), 0, 0, 1));
+  AddTestCase (new LteCellSelectionTestCase ("First test with EPC", true, x),
+               TestCase::QUICK);
+
+//  x.clear ();
+//  x.push_back (LteCellSelectionTestCase::UeSetup_t (Vector (0, 0, 0), 0, 0, 1));
+//  AddTestCase (new LteCellSelectionTestCase ("First test without EPC", false, x),
+//               TestCase::QUICK);
+
+} // end of LteCellSelectionTestSuite::LteCellSelectionTestSuite ()
+
+
+static LteCellSelectionTestSuite g_lteCellSelectionTestSuite;
+
+
+
+/*
+ * Test Case
+ */
+
+
+LteCellSelectionTestCase::UeSetup_t::UeSetup_t (Vector position,
+                                                uint32_t plmnIdentity,
+                                                uint32_t csgIdentity,
+                                                uint16_t expectedCellId)
+  : position (position), plmnIdentity (plmnIdentity), csgIdentity (csgIdentity),
+    expectedCellId (expectedCellId)
+{
+}
+
+
+LteCellSelectionTestCase::LteCellSelectionTestCase (
+  std::string name, bool isEpcMode, std::vector<UeSetup_t> ueSetupList)
+  : TestCase (name), m_isEpcMode (isEpcMode), m_ueSetupList (ueSetupList)
+{
+  NS_LOG_FUNCTION (this << GetName ());
+}
+
+
+LteCellSelectionTestCase::~LteCellSelectionTestCase ()
+{
+  NS_LOG_FUNCTION (this << GetName ());
+}
+
+
+void
+LteCellSelectionTestCase::DoRun ()
+{
+  NS_LOG_FUNCTION (this << GetName ());
+
+  Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+  lteHelper->SetAttribute ("PathlossModel",
+                           StringValue ("ns3::FriisSpectrumPropagationLossModel"));
+  lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (true));
+
+  Ptr<EpcHelper> epcHelper;
+
+  if (m_isEpcMode)
+    {
+      epcHelper = CreateObject<EpcHelper> ();
+      lteHelper->SetEpcHelper (epcHelper);
+    }
+
+  /*
+   * The topology is the following:
+   *
+   *        <--x eNodeB 2    - Both cells are separated by 10 m
+   *           |             - Parabolic antenna model is used
+   *           | 10 m        - eNodeB 1 at (0, 10, 0) is facing east
+   *           |             - eNodeB 2 at (0, 20, 0) is facing west
+   *  eNodeB 1 x-->          - UEs are placed according to input
+   *                         - UEs do not move during simulation
+   */
+
+  // Create Nodes: eNodeB
+  NodeContainer enbNodes;
+  enbNodes.Create (2);
+
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 10.0, 0.0));
+  positionAlloc->Add (Vector (0.0, 20.0, 0.0));
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (enbNodes);
+
+  // Create Nodes: UE
+  NodeContainer ueNodes;
+  uint16_t nUe = m_ueSetupList.size ();
+  ueNodes.Create (nUe);
+
+  std::vector<UeSetup_t>::const_iterator it;
+  for (it = m_ueSetupList.begin (); it != m_ueSetupList.end (); it++)
+    {
+      positionAlloc->Add (it->position);
+    }
+
+  mobility.Install (ueNodes);
+
+  // Create Devices and install them in the Nodes (eNB and UE)
+  NetDeviceContainer enbDevs;
+  NetDeviceContainer ueDevs;
+  enbDevs = lteHelper->InstallEnbDevice (enbNodes);
+  ueDevs = lteHelper->InstallUeDevice (ueNodes);
+
+  // Set the PLMN and CSG ID
+  for (it = m_ueSetupList.begin (); it != m_ueSetupList.end (); it++)
+    {
+      // TODO
+    }
+
+  if (m_isEpcMode)
+    {
+      // Create P-GW node
+      Ptr<Node> pgw = epcHelper->GetPgwNode ();
+
+      // Create a single RemoteHost
+      NodeContainer remoteHostContainer;
+      remoteHostContainer.Create (1);
+      Ptr<Node> remoteHost = remoteHostContainer.Get (0);
+      InternetStackHelper internet;
+      internet.Install (remoteHostContainer);
+
+      // Create the Internet
+      PointToPointHelper p2ph;
+      p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
+      p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
+      p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
+      NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
+      Ipv4AddressHelper ipv4h;
+      ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
+      Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
+
+      // Routing of the Internet Host (towards the LTE network)
+      Ipv4StaticRoutingHelper ipv4RoutingHelper;
+      Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
+      remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
+
+      // Install the IP stack on the UEs
+      internet.Install (ueNodes);
+      Ipv4InterfaceContainer ueIpIfaces;
+      ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevs));
+
+      // Assign IP address to UEs
+      for (uint32_t u = 0; u < ueNodes.GetN (); ++u)
+        {
+          Ptr<Node> ueNode = ueNodes.Get (u);
+          // Set the default gateway for the UE
+          Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
+          ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
+        }
+
+      // // TODO remove this
+      //lteHelper->Attach (ueDevs, enbDevs.Get (0));
+
+    } // end of if (m_isEpcMode)
+  else
+    {
+      // // TODO remove this
+      // lteHelper->Attach (ueDevs, enbDevs.Get (0));
+      //
+      // // Activate an EPS bearer
+      // enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+      // EpsBearer bearer (q);
+      // lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
+    }
+
+  // Connect to trace sources in UEs
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/MibReceived",
+                   MakeCallback (&LteCellSelectionTestCase::MibReceivedCallback,
+                                 this));
+
+  // Connect to trace sources in UEs
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/Sib1Received",
+                   MakeCallback (&LteCellSelectionTestCase::Sib1ReceivedCallback,
+                                 this));
+
+  // Run simulation
+  Simulator::Stop (MilliSeconds (400));
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // Tests
+
+  // TODO
+
+} // end of void LteCellSelectionTestCase::DoRun ()
+
+
+void
+LteCellSelectionTestCase::MibReceivedCallback (
+  std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << context << imsi << cellId << rnti);
+}
+
+
+void
+LteCellSelectionTestCase::Sib1ReceivedCallback (
+  std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << context << imsi << cellId << rnti);
+}
+
+
+} // end of namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-cell-selection.h	Tue Jul 16 09:43:01 2013 +0300
@@ -0,0 +1,105 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 University of Jyväskylä
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Budiarto Herman <buherman@student.jyu.fi>
+ *
+ */
+
+#ifndef LTE_TEST_CELL_SELECTION_H
+#define LTE_TEST_CELL_SELECTION_H
+
+#include <ns3/test.h>
+#include <ns3/node-container.h>
+#include <ns3/vector.h>
+#include <vector>
+
+namespace ns3 {
+
+
+/**
+ * \brief Test suite for executing the cell selection test cases in without-EPC
+ *        and with-EPC scenarios.
+ *
+ * \sa ns3::LteCellSelectionTestCase
+ */
+class LteCellSelectionTestSuite : public TestSuite
+{
+public:
+  LteCellSelectionTestSuite ();
+};
+
+
+/**
+ * \brief Testing the initial cell selection procedure by UE at IDLE state in
+ *        the beginning of simulation.
+ */
+class LteCellSelectionTestCase : public TestCase
+{
+public:
+  /**
+   * \brief A set of input parameters for setting up a UE in the simulation.
+   */
+  struct UeSetup_t
+  {
+    Vector position; ///< The position where the UE will be spawned in the simulation.
+    uint32_t plmnIdentity; ///< Public Land Mobile Network identity of the UE.
+    uint32_t csgIdentity; ///< Closed Subscriber Group identity of the UE.
+    uint16_t expectedCellId; ///< The cell ID that the UE is expected to attach to (0 means that the UE should not attach to any cell).
+    UeSetup_t (Vector position, uint32_t plmnIdentity, uint32_t csgIdentity,
+               uint16_t expectedCellId);
+  };
+
+  /**
+   * \brief Creates an instance of the initial cell selection test case.
+   * \param name name of this test
+   * \param isEpcMode set to true for setting up simulation with EPC enabled
+   * \param ueSetupList an array of UE setup parameters
+   */
+  LteCellSelectionTestCase (std::string name, bool isEpcMode,
+                            std::vector<UeSetup_t> ueSetupList);
+
+  virtual ~LteCellSelectionTestCase ();
+
+private:
+  /**
+   * \brief Setup the simulation according to the configuration set by the
+   *        class constructor, run it, and verify the result.
+   */
+  virtual void DoRun ();
+
+  void MibReceivedCallback (std::string context, uint64_t imsi,
+                            uint16_t cellId, uint16_t rnti);
+  void Sib1ReceivedCallback (std::string context, uint64_t imsi,
+                             uint16_t cellId, uint16_t rnti);
+
+  /**
+   * \brief If true, then the simulation should be set up with EPC enabled.
+   */
+  bool m_isEpcMode;
+
+  /**
+   * \brief The list of UE setups to be used during the test execution.
+   */
+  std::vector<UeSetup_t> m_ueSetupList;
+
+}; // end of class LteCellSelectionTestCase
+
+
+} // end of namespace ns3
+
+
+#endif /* LTE_TEST_CELL_SELECTION_H */
--- a/src/lte/wscript	Wed Jul 10 14:59:00 2013 +0300
+++ b/src/lte/wscript	Tue Jul 16 09:43:01 2013 +0300
@@ -142,6 +142,7 @@
         'test/test-lte-x2-handover-measures.cc',
         'test/test-asn1-encoding.cc',
         'test/lte-test-ue-measurements.cc',
+        'test/lte-test-cell-selection.cc',
         'test/test-lte-handover-delay.cc',
         ]