new LTE RRC model
authorNicola Baldo <nbaldo@cttc.es>
Tue, 30 Oct 2012 16:02:07 +0100
changeset 9406 7f0f9d8f8e20
parent 9399 50e7ff3a0366
child 9407 e261dc294165
new LTE RRC model
src/lte/doc/source/lte-design.rst
src/lte/doc/source/lte-user.rst
src/lte/helper/lte-helper.cc
src/lte/model/epc-enb-application.cc
src/lte/model/epc-enb-application.h
src/lte/model/epc-enb-s1-sap.h
src/lte/model/epc-ue-nas.cc
src/lte/model/epc-ue-nas.h
src/lte/model/eps-bearer-tag.cc
src/lte/model/eps-bearer-tag.h
src/lte/model/lte-as-sap.h
src/lte/model/lte-control-messages.cc
src/lte/model/lte-control-messages.h
src/lte/model/lte-enb-cmac-sap.h
src/lte/model/lte-enb-cphy-sap.h
src/lte/model/lte-enb-mac.cc
src/lte/model/lte-enb-mac.h
src/lte/model/lte-enb-net-device.cc
src/lte/model/lte-enb-phy-sap.h
src/lte/model/lte-enb-phy.cc
src/lte/model/lte-enb-phy.h
src/lte/model/lte-enb-rrc.cc
src/lte/model/lte-enb-rrc.h
src/lte/model/lte-interference.cc
src/lte/model/lte-interference.h
src/lte/model/lte-pdcp-sap.h
src/lte/model/lte-pdcp.cc
src/lte/model/lte-pdcp.h
src/lte/model/lte-radio-bearer-info.cc
src/lte/model/lte-radio-bearer-info.h
src/lte/model/lte-radio-bearer-tag.cc
src/lte/model/lte-rlc-am.h
src/lte/model/lte-rlc-tm.cc
src/lte/model/lte-rlc-tm.h
src/lte/model/lte-rrc-protocol-ideal.cc
src/lte/model/lte-rrc-protocol-ideal.h
src/lte/model/lte-rrc-sap.h
src/lte/model/lte-spectrum-phy.cc
src/lte/model/lte-spectrum-phy.h
src/lte/model/lte-ue-cmac-sap.h
src/lte/model/lte-ue-cphy-sap.h
src/lte/model/lte-ue-mac.cc
src/lte/model/lte-ue-mac.h
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/lte-ue-rrc.cc
src/lte/model/lte-ue-rrc.h
src/lte/model/pf-ff-mac-scheduler.cc
src/lte/model/rr-ff-mac-scheduler.cc
src/lte/test/epc-test-s1u-uplink.cc
src/lte/test/lte-test-entities.cc
src/lte/test/lte-test-entities.h
src/lte/test/lte-test-interference.cc
src/lte/test/lte-test-link-adaptation.cc
src/lte/test/lte-test-mimo.cc
src/lte/test/lte-test-pathloss-model.cc
src/lte/test/lte-test-pf-ff-mac-scheduler.cc
src/lte/test/lte-test-phy-error-model.cc
src/lte/test/lte-test-rr-ff-mac-scheduler.cc
src/lte/test/test-lte-antenna.cc
src/lte/test/test-lte-epc-e2e-data.cc
src/lte/test/test-lte-rrc.cc
src/lte/wscript
src/spectrum/model/multi-model-spectrum-channel.cc
src/spectrum/model/multi-model-spectrum-channel.h
--- a/src/lte/doc/source/lte-design.rst	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/doc/source/lte-design.rst	Tue Oct 30 16:02:07 2012 +0100
@@ -1071,6 +1071,16 @@
    + handover
 
 
+Radio Bearer Configuration
+--------------------------
+
+Some implementation choices have been made in the RRC regarding the setup of radio bearers:
+
+ - three Logical Channel Groups (out of four available) are used, according to the following policy:
+   + LCG 0 is for signaling radio bearers
+   + LCG 1 is for GBR data radio bearers
+   + LCG 2 is for Non-GBR data radio bearers
+
 
 RRC connection establishment
 ----------------------------
--- a/src/lte/doc/source/lte-user.rst	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/doc/source/lte-user.rst	Tue Oct 30 16:02:07 2012 +0100
@@ -48,10 +48,10 @@
 
 #. Initial boilerplate::
        
-    #include "ns3/core-module.h"
-    #include "ns3/network-module.h"
-    #include "ns3/mobility-module.h"
-    #include "ns3/lte-module.h"   
+    #include <ns3/core-module.h>
+    #include <ns3/network-module.h>
+    #include <ns3/mobility-module.h>
+    #include <ns3/lte-module.h>   
 
     using namespace ns3;    
 
@@ -106,14 +106,13 @@
 
       lteHelper->Attach (ueDevs, enbDevs.Get (0));
 
-#. Activate an EPS Bearer including the setup of the Radio Bearer between an eNB and its attached UE::
+#. Activate a data radio bearer between each UE and the eNB it is attached to::
 
       enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
       EpsBearer bearer (q);
-      lteHelper->ActivateEpsBearer (ueDevs, bearer);
+      lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
 
-   In the current version of the ns-3 LTE model, the activation of an
-   EPS Bearer will also activate two saturation traffic generators for
+   this method will also activate two saturation traffic generators for
    that bearer, one in uplink and one in downlink. 
 
 #. Set the stop time::
@@ -707,10 +706,24 @@
           ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
         }
 
-The activation of bearers is done exactly in the same way as for an
-LTE-only simulation. Here is how to activate a default bearer::
+The activation of bearers is done in a slightly different way with
+respect to what done for an LTE-only simulation. First, the method
+ActivateDataRadioBearer is not to be used when the EPC is
+used. Second, when EPC is used, the default EPS bearer will be
+activated automatically when you call LteHelper::Attach (). Third, if
+you want to setup dedicated EPS bearer, you can do so using the method
+LteHelper::ActivateDedicatedEpsBearer (). This method takes as a
+parameter the Traffic Flow Template (TFT), which is a struct that
+identifies the type of traffic that will be mapped to the dedicated
+EPS bearer. Here is an example for how to setup a dedicated bearer
+for an application at the UE communicating on port 1234::
 
-      lteHelper->ActivateEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
+      Ptr<EpcTft> tft = Create<EpcTft> ();
+      EpcTft::PacketFilter pf;
+      pf.localPortStart = 1234;
+      pf.localPortEnd = 1234;
+      tft->Add (pf);  
+      lteHelper->ActivateEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), pf);
 
 you can of course use custom EpsBearer and EpcTft configurations,
 please refer to the doxygen documentation for how to do it.
--- a/src/lte/helper/lte-helper.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/helper/lte-helper.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -36,7 +36,7 @@
 #include <ns3/lte-ue-phy.h>
 #include <ns3/lte-spectrum-phy.h>
 #include <ns3/lte-sinr-chunk-processor.h>
-#include <ns3/single-model-spectrum-channel.h>
+#include <ns3/multi-model-spectrum-channel.h>
 #include <ns3/friis-spectrum-propagation-loss.h>
 #include <ns3/isotropic-antenna-model.h>
 #include <ns3/lte-enb-net-device.h>
@@ -46,6 +46,7 @@
 #include <ns3/lte-rlc-um.h>
 #include <ns3/lte-rlc-am.h>
 #include <ns3/epc-enb-s1-sap.h>
+#include <ns3/lte-rrc-protocol-ideal.h>
 
 #include <ns3/epc-helper.h>
 #include <iostream>
@@ -65,7 +66,7 @@
   m_enbNetDeviceFactory.SetTypeId (LteEnbNetDevice::GetTypeId ());
   m_enbAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
   m_ueAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
-  m_channelFactory.SetTypeId (SingleModelSpectrumChannel::GetTypeId ());
+  m_channelFactory.SetTypeId (MultiModelSpectrumChannel::GetTypeId ());
 }
 
 void 
@@ -330,6 +331,8 @@
   Ptr<LteEnbMac> mac = CreateObject<LteEnbMac> ();
   Ptr<FfMacScheduler> sched = m_schedulerFactory.Create<FfMacScheduler> ();
   Ptr<LteEnbRrc> rrc = CreateObject<LteEnbRrc> ();
+  Ptr<LteEnbRrcProtocolIdeal> rrcProtocol = CreateObject<LteEnbRrcProtocolIdeal> ();
+  rrc->AggregateObject (rrcProtocol);
 
   if (m_epcHelper != 0)
     {
@@ -343,6 +346,9 @@
     }
 
   // connect SAPs
+  rrcProtocol->SetLteEnbRrcSapProvider (rrc->GetLteEnbRrcSapProvider ());
+  rrc->SetLteEnbRrcSapUser (rrcProtocol->GetLteEnbRrcSapUser ());
+
   rrc->SetLteEnbCmacSapProvider (mac->GetLteEnbCmacSapProvider ());
   mac->SetLteEnbCmacSapUser (rrc->GetLteEnbCmacSapUser ());
   rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
@@ -395,6 +401,9 @@
 
   dev->Start ();
 
+  rrcProtocol->SetCellId (dev->GetCellId ());
+  
+
   m_uplinkChannel->AddRx (ulPhy);
 
   if (m_epcHelper != 0)
@@ -447,6 +456,14 @@
 
   Ptr<LteUeMac> mac = CreateObject<LteUeMac> ();
   Ptr<LteUeRrc> rrc = CreateObject<LteUeRrc> ();
+  Ptr<LteUeRrcProtocolIdeal> rrcProtocol = CreateObject<LteUeRrcProtocolIdeal> ();
+  rrc->AggregateObject (rrcProtocol);
+  rrcProtocol->SetUeRrc (rrc);
+
+  if (m_epcHelper != 0)
+    {
+      rrc->SetUseRlcSm (false);
+    }
   Ptr<EpcUeNas> nas = CreateObject<EpcUeNas> ();
  
   nas->SetEpcHelper (m_epcHelper);
@@ -455,6 +472,9 @@
   nas->SetAsSapProvider (rrc->GetAsSapProvider ());
   rrc->SetAsSapUser (nas->GetAsSapUser ());
 
+  rrcProtocol->SetLteUeRrcSapProvider (rrc->GetLteUeRrcSapProvider ());
+  rrc->SetLteUeRrcSapUser (rrcProtocol->GetLteUeRrcSapUser ());
+
   rrc->SetLteUeCmacSapProvider (mac->GetLteUeCmacSapProvider ());
   mac->SetLteUeCmacSapUser (rrc->GetLteUeCmacSapUser ());
   rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
@@ -476,7 +496,6 @@
   dlPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteUePhy::ReceiveLteControlMessageList, phy));
   nas->SetForwardUpCallback (MakeCallback (&LteUeNetDevice::Receive, dev));
 
-
   dev->Start ();
 
   return dev;
@@ -503,8 +522,6 @@
   Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
   ueNas->Connect (enbDevice);
   
-  m_downlinkChannel->AddRx (ueLteDevice->GetPhy ()->GetDownlinkSpectrumPhy ());
-
   // tricks needed for the simplified LTE-only simulations 
   if (m_epcHelper == 0)
     {
@@ -570,14 +587,39 @@
 LteHelper::ActivateDataRadioBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer)
 {
   NS_LOG_FUNCTION (this << ueDevice);
-  NS_ASSERT_MSG (m_epcHelper == 0, "this method must not be used when EPC is being used");
-  Ptr<LteEnbNetDevice> enbDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
-  Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
-  EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
-  params.rnti = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti();
-  params.bearer = bearer;
-  params.teid = 0; // don't care
-  enbRrc->GetS1SapUser ()->DataRadioBearerSetupRequest (params);
+  NS_ASSERT_MSG (m_epcHelper == 0, "this method must not be used when EPC is being used");  
+
+  /*
+   * Note: this method is kind of a hack, just because running
+   * simulations without the EPC is kind of a hack.  
+   */
+
+  Ptr<LteUeRrc> ueRrc = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
+  bool done = false;
+  if (ueRrc->GetState () == LteUeRrc::CONNECTED_NORMALLY)
+    {
+      uint16_t rnti = ueRrc->GetRnti();
+      Ptr<LteEnbNetDevice> enbLteDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
+      Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
+      NS_ASSERT (ueRrc->GetCellId () == enbLteDevice->GetCellId ());
+      Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
+      if (ueManager->GetState () == UeManager::CONNECTED_NORMALLY)
+        {
+          EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
+          params.rnti = rnti;
+          params.bearer = bearer;
+          params.teid = 0; // don't care
+          enbRrc->GetS1SapUser ()->DataRadioBearerSetupRequest (params);
+          done = true;
+        }
+    }
+
+  if (!done) // UE not connected yet, try again later
+    {
+      // use a function pointer to get around overloading
+      void (LteHelper::*functionPtr) (NetDeviceContainer ueDevices,  EpsBearer bearer) = &LteHelper::ActivateDataRadioBearer;
+      Simulator::Schedule (Seconds (0.001), functionPtr, this, ueDevice, bearer);
+    }
 }
 
 void
@@ -686,17 +728,17 @@
 {
   NS_LOG_FUNCTION (path);
   // Sample path input:
-  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
+  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/DataRadioBearerMap/#LCID/LteRlc/RxPDU
 
-  // We retrieve the UeInfo associated to the C-RNTI and perform the IMSI lookup
-  std::string ueMapPath = path.substr (0, path.find ("/RadioBearerMap"));
+  // We retrieve the UeManager associated to the C-RNTI and perform the IMSI lookup
+  std::string ueMapPath = path.substr (0, path.find ("/DataRadioBearerMap"));
   Config::MatchContainer match = Config::LookupMatches (ueMapPath);
 
   if (match.GetN () != 0)
     {
       Ptr<Object> ueInfo = match.Get (0);
-      NS_LOG_LOGIC ("FindImsiFromEnbRlcPath: " << path << ", " << ueInfo->GetObject<UeInfo> ()->GetImsi ());
-      return ueInfo->GetObject<UeInfo> ()->GetImsi ();
+      NS_LOG_LOGIC ("FindImsiFromEnbRlcPath: " << path << ", " << ueInfo->GetObject<UeManager> ()->GetImsi ());
+      return ueInfo->GetObject<UeManager> ()->GetImsi ();
     }
   else
     {
@@ -709,7 +751,7 @@
 {
   NS_LOG_FUNCTION (path);
   // Sample path input:
-  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
+  // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/DataRadioBearerMap/#LCID/LteRlc/RxPDU
 
   // We retrieve the CellId associated to the Enb
   std::string enbNetDevicePath = path.substr (0, path.find ("/LteEnbRrc"));
@@ -830,9 +872,9 @@
 LteHelper::EnableDlRlcTraces (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/TxPDU",
+  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LteRlc/TxPDU",
                    MakeBoundCallback (&DlTxPduCallback, m_rlcStats));
-  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/RxPDU",
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LteRlc/RxPDU",
                    MakeBoundCallback (&DlRxPduCallback, m_rlcStats));
 }
 
@@ -920,9 +962,10 @@
 void
 LteHelper::EnableUlRlcTraces (void)
 {
-  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/TxPDU",
+  NS_LOG_FUNCTION_NOARGS ();
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LteRlc/TxPDU",
                    MakeBoundCallback (&UlTxPduCallback, m_rlcStats));
-  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/RxPDU",
+  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LteRlc/RxPDU",
                    MakeBoundCallback (&UlRxPduCallback, m_rlcStats));
 }
 
@@ -998,18 +1041,18 @@
 LteHelper::EnableDlPdcpTraces (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/TxPDU",
+  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LtePdcp/TxPDU",
                    MakeBoundCallback (&DlTxPduCallback, m_pdcpStats));
-  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/RxPDU",
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LtePdcp/RxPDU",
                    MakeBoundCallback (&DlRxPduCallback, m_pdcpStats));
 }
 
 void
 LteHelper::EnableUlPdcpTraces (void)
 {
-  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/TxPDU",
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LtePdcp/TxPDU",
                    MakeBoundCallback (&UlTxPduCallback, m_pdcpStats));
-  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/RxPDU",
+  Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LtePdcp/RxPDU",
                    MakeBoundCallback (&UlRxPduCallback, m_pdcpStats));
 }
 
--- a/src/lte/model/epc-enb-application.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-enb-application.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -28,7 +28,7 @@
 #include "ns3/uinteger.h"
 
 #include "epc-gtpu-header.h"
-#include "lte-radio-bearer-tag.h"
+#include "eps-bearer-tag.h"
 
 
 namespace ns3 {
@@ -36,6 +36,29 @@
 NS_LOG_COMPONENT_DEFINE ("EpcEnbApplication");
 
 
+EpcEnbApplication::EpsFlowId_t::EpsFlowId_t ()
+{
+}
+
+EpcEnbApplication::EpsFlowId_t::EpsFlowId_t (const uint16_t a, const uint8_t b)
+  : m_rnti (a),
+    m_bid (b)
+{
+}
+
+bool
+operator == (const EpcEnbApplication::EpsFlowId_t &a, const EpcEnbApplication::EpsFlowId_t &b)
+{
+  return ( (a.m_rnti == b.m_rnti) && (a.m_bid == b.m_bid) );
+}
+
+bool
+operator < (const EpcEnbApplication::EpsFlowId_t& a, const EpcEnbApplication::EpsFlowId_t& b)
+{
+  return ( (a.m_rnti < b.m_rnti) || ( (a.m_rnti == b.m_rnti) && (a.m_bid < b.m_bid) ) );
+}
+
+
 TypeId
 EpcEnbApplication::GetTypeId (void)
 {
@@ -93,8 +116,8 @@
 void 
 EpcEnbApplication::DoS1BearerSetupRequest (EpcEnbS1SapProvider::S1BearerSetupRequestParameters params)
 {
-  NS_LOG_FUNCTION (this);
-  LteFlowId_t rbid (params.rnti, params.lcid);
+  NS_LOG_FUNCTION (this << params.rnti << params.bid);
+  EpsFlowId_t rbid (params.rnti, params.bid);
   // side effect: create entries if not exist
   m_rbidTeidMap[rbid] = params.teid;
   m_teidRbidMap[params.teid] = rbid;
@@ -120,14 +143,14 @@
   SocketAddressTag satag;
   packet->RemovePacketTag (satag);
 
-  LteRadioBearerTag tag;
+  EpsBearerTag tag;
   bool found = packet->RemovePacketTag (tag);
   NS_ASSERT (found);
-  LteFlowId_t flowId;
+  EpsFlowId_t flowId;
   flowId.m_rnti = tag.GetRnti ();
-  flowId.m_lcId = tag.GetLcid ();
-  NS_LOG_LOGIC ("received packet with RNTI=" << flowId.m_rnti << ", LCID=" << (uint16_t)  flowId.m_lcId);
-  std::map<LteFlowId_t, uint32_t>::iterator it = m_rbidTeidMap.find (flowId);
+  flowId.m_bid = tag.GetBid ();
+  NS_LOG_LOGIC ("received packet with RNTI=" << flowId.m_rnti << ", BID=" << (uint16_t)  flowId.m_bid);
+  std::map<EpsFlowId_t, uint32_t>::iterator it = m_rbidTeidMap.find (flowId);
   NS_ASSERT (it != m_rbidTeidMap.end ());
   uint32_t teid = it->second;
   SendToS1uSocket (packet, teid);
@@ -142,21 +165,21 @@
   GtpuHeader gtpu;
   packet->RemoveHeader (gtpu);
   uint32_t teid = gtpu.GetTeid ();
-  std::map<uint32_t, LteFlowId_t>::iterator it = m_teidRbidMap.find (teid);
+  std::map<uint32_t, EpsFlowId_t>::iterator it = m_teidRbidMap.find (teid);
   NS_ASSERT (it != m_teidRbidMap.end ());
 
   // workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
   SocketAddressTag tag;
   packet->RemovePacketTag (tag);
   
-  SendToLteSocket (packet, it->second.m_rnti, it->second.m_lcId);
+  SendToLteSocket (packet, it->second.m_rnti, it->second.m_bid);
 }
 
 void 
-EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t lcid)
+EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
 {
-  NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) lcid);  
-  LteRadioBearerTag tag (rnti, lcid);
+  NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) bid);  
+  EpsBearerTag tag (rnti, bid);
   packet->AddPacketTag (tag);
   int sentBytes = m_lteSocket->Send (packet);
   NS_ASSERT (sentBytes > 0);
--- a/src/lte/model/epc-enb-application.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-enb-application.h	Tue Oct 30 16:02:07 2012 +0100
@@ -114,6 +114,20 @@
   void RecvFromS1uSocket (Ptr<Socket> socket);
 
 
+  struct EpsFlowId_t
+  {
+    uint16_t  m_rnti;
+    uint8_t   m_bid;
+
+  public:
+    EpsFlowId_t ();
+    EpsFlowId_t (const uint16_t a, const uint8_t b);
+
+    friend bool operator == (const EpsFlowId_t &a, const EpsFlowId_t &b);
+    friend bool operator < (const EpsFlowId_t &a, const EpsFlowId_t &b);
+  };
+
+
 private:
 
   // S1 SAP provider methods
@@ -124,9 +138,9 @@
    * Send a packet to the UE via the LTE radio interface of the eNB
    * 
    * \param packet t
-   * \param rbid the Radio Bearer IDentifier
+   * \param bid the EPS Bearer IDentifier
    */
-  void SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t lcid);
+  void SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t bid);
 
 
   /** 
@@ -144,9 +158,9 @@
    * 
    * \param teid 
    * \param rnti 
-   * \param lcid 
+   * \param bid 
    */
-  void SetupS1Bearer (uint32_t teid, uint16_t rnti, uint8_t lcid);
+  void SetupS1Bearer (uint32_t teid, uint16_t rnti, uint8_t bid);
 
   /**
    * raw packet socket to send and receive the packets to and from the LTE radio interface
@@ -164,16 +178,16 @@
   Ipv4Address m_sgwAddress;
 
   /**
-   * map telling for each RadioBearer (RNTI,LCID) the corresponding  S1-U TEID
+   * map telling for each EpsBearer (RNTI,BID) the corresponding  S1-U TEID
    * 
    */
-  std::map<LteFlowId_t, uint32_t> m_rbidTeidMap;  
+  std::map<EpsFlowId_t, uint32_t> m_rbidTeidMap;  
 
   /**
-   * map telling for each S1-U TEID the corresponding RadioBearer (RNTI,LCID) 
+   * map telling for each S1-U TEID the corresponding EpsBearer (RNTI,BID) 
    * 
    */
-  std::map<uint32_t, LteFlowId_t> m_teidRbidMap;
+  std::map<uint32_t, EpsFlowId_t> m_teidRbidMap;
  
   /**
    * UDP port to be used for GTP
--- a/src/lte/model/epc-enb-s1-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-enb-s1-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -47,7 +47,7 @@
   {
     uint16_t rnti; /**< the RNTI corresponding to the IMSI for which
                       the radio bearer activation was requested */
-    uint8_t lcid; /**< the LCID of the newly created radio bearer */
+    uint8_t bid; /**< the EPS Bearer ID of the bearer to be created*/
 
     uint32_t teid; /**< context information that was passed upon the
                       corresponding call to
--- a/src/lte/model/epc-ue-nas.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-ue-nas.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -33,10 +33,30 @@
 
 
 
+
+
+const char* g_ueNasStateName[EpcUeNas::NUM_STATES] = 
+  {
+      "OFF",
+      "ATTACHING",
+      "IDLE_REGISTERED",
+      "CONNECTING_TO_EPC",
+      "ACTIVE "    
+  };
+
+std::string ToString (EpcUeNas::State s)
+{
+  return std::string (g_ueNasStateName[s]);
+}
+
+
+
+
 NS_OBJECT_ENSURE_REGISTERED (EpcUeNas);
 
 EpcUeNas::EpcUeNas ()
-  : m_asSapProvider (0),
+  : m_state (OFF),
+    m_asSapProvider (0),
     m_bidCounter (0)
 {
   NS_LOG_FUNCTION (this);
@@ -63,6 +83,9 @@
   static TypeId tid = TypeId ("ns3::EpcUeNas")
     .SetParent<Object> ()
     .AddConstructor<EpcUeNas> ()
+    .AddTraceSource ("StateTransition",
+                     "fired upon every UE NAS state transition",
+                     MakeTraceSourceAccessor (&EpcUeNas::m_stateTransitionCallback))
   ;
   return tid;
 }
@@ -107,6 +130,9 @@
 void 
 EpcUeNas::Connect (Ptr<NetDevice> enbDevice)
 {
+  NS_LOG_FUNCTION (this);
+
+  m_enbDevice = enbDevice;
 
   // since RRC Idle Mode cell selection is not supported yet, we
   // force the UE RRC to be camped on a specific eNB
@@ -115,22 +141,35 @@
 
   // tell RRC to go into connected mode
   m_asSapProvider->Connect ();
+}
 
-  if (m_epcHelper)
-    {
-      m_epcHelper->AttachUe (m_device, m_imsi, enbDevice);
-      // also activate default EPS bearer
-      ActivateEpsBearer (EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
-    }
+
+void 
+EpcUeNas::Disconnect ()
+{
+  NS_LOG_FUNCTION (this);
+  m_asSapProvider->Disconnect ();
+  SwitchToState (OFF);
 }
 
+
 void 
 EpcUeNas::ActivateEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft)
 {
-  NS_ASSERT_MSG (m_bidCounter < 11, "cannot have more than 11 EPS bearers");
-  uint8_t bid = ++m_bidCounter;
-  m_epcHelper->ActivateEpsBearer (m_device, m_imsi, tft, bearer);
-  m_tftClassifier.Add (tft, bid);
+  NS_LOG_FUNCTION (this);
+  switch (m_state)
+    {
+    case ACTIVE:
+      DoActivateEpsBearer (bearer, tft);
+      break;
+
+    default:
+      BearerToBeActivated btba;
+      btba.bearer = bearer;
+      btba.tft = tft;
+      m_bearersToBeActivatedList.push_back (btba);
+      break;
+    }
 }
 
 bool
@@ -138,23 +177,43 @@
 {
   NS_LOG_FUNCTION (this << packet);
   
-  uint32_t id = m_tftClassifier.Classify (packet, EpcTft::UPLINK);
-  NS_ASSERT ((id & 0xFFFFFF00) == 0);
-  uint8_t bid = (uint8_t) (id & 0x000000FF);
-  if (bid == 0)
+  switch (m_state)
     {
+    case ACTIVE:
+      {
+        uint32_t id = m_tftClassifier.Classify (packet, EpcTft::UPLINK);
+        NS_ASSERT ((id & 0xFFFFFF00) == 0);
+        uint8_t bid = (uint8_t) (id & 0x000000FF);
+        if (bid == 0)
+          {
+            return false;
+          }
+        else
+          {
+            m_asSapProvider->SendData (packet, bid); 
+            return true;
+        }
+      }
+      break;
+
+    default:      
+      NS_LOG_WARN (this << " NAS OFF, discarding packet");
       return false;
-    }
-  else
-    {
-      m_asSapProvider->SendData (packet, bid); 
-      return true;
-    }
+      break;
+    }        
 }
 
 void 
 EpcUeNas::DoNotifyConnectionSuccessful ()
 {
+  NS_LOG_FUNCTION (this);
+  if (m_epcHelper)
+    {
+      m_epcHelper->AttachUe (m_device, m_imsi, m_enbDevice);
+      // also activate default EPS bearer
+      DoActivateEpsBearer (EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
+      SwitchToState (ACTIVE);
+    }
 }
 
 void 
@@ -170,7 +229,48 @@
   m_forwardUpCallback (packet);
 }
 
+void 
+EpcUeNas::DoNotifyConnectionReleased ()
+{
+  NS_FATAL_ERROR ("connection failed, it should not happen with the current model");
+}
 
+void 
+EpcUeNas::DoActivateEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft)
+{
+  NS_LOG_FUNCTION (this);
+  NS_ASSERT_MSG (m_bidCounter < 11, "cannot have more than 11 EPS bearers");
+  uint8_t bid = ++m_bidCounter;
+  m_epcHelper->ActivateEpsBearer (m_device, m_imsi, tft, bearer);
+  m_tftClassifier.Add (tft, bid);
+}
+
+void 
+EpcUeNas::SwitchToState (State newState)
+{
+  NS_LOG_FUNCTION (this << newState);
+  State oldState = m_state;
+  m_state = newState;
+  NS_LOG_INFO ("IMSI " << m_imsi << " NAS " << ToString (oldState) << " --> " << ToString (newState));
+  m_stateTransitionCallback (oldState, newState);
+
+  // actions to be done when entering a new state:
+  switch (m_state)
+    {
+    case ACTIVE:
+      for (std::list<BearerToBeActivated>::iterator it = m_bearersToBeActivatedList.begin ();
+           it != m_bearersToBeActivatedList.end ();
+           m_bearersToBeActivatedList.erase (it++))
+        {
+          DoActivateEpsBearer (it->bearer, it->tft);
+        }
+      break;
+
+    default:
+      break;
+    }
+
+}
 
 
 } // namespace ns3
--- a/src/lte/model/epc-ue-nas.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-ue-nas.h	Tue Oct 30 16:02:07 2012 +0100
@@ -93,12 +93,20 @@
   void SetForwardUpCallback (Callback <void, Ptr<Packet> > cb);
  
   /** 
-   * instruct the NAS to go to EMM Registered + ECM Connected
+   * instruct the NAS to go to ACTIVE state, i.e., EMM Registered + ECM Connected
    * 
    * 
-   * \param enbDevice the eNB through which to connect
+   * \param enbDevice the eNB through which to connect. This parameter
+   * might be removed in future versions.
    */
   void Connect (Ptr<NetDevice> enbDevice);
+ 
+  /** 
+   * instruct the NAS to disconnect
+   * 
+   */
+  void Disconnect ();
+
 
   /** 
    * Activate an EPS bearer
@@ -116,17 +124,45 @@
    * \return true if successful, false if an error occurred
    */
   bool Send (Ptr<Packet> p);
+
+
+  /**
+   * Definition of NAS states as per "LTE - From theory to practice",
+   * Section 3.2.3.2 "Connection Establishment and Release"
+   * 
+   */
+  enum State 
+    {
+      OFF = 0,
+      ATTACHING,
+      IDLE_REGISTERED,
+      CONNECTING_TO_EPC,
+      ACTIVE,
+      NUM_STATES
+    };
+
  
 private:
   
   // LTE AS SAP methods
   void DoNotifyConnectionSuccessful ();
   void DoNotifyConnectionFailed ();
+  void DoNotifyConnectionReleased ();
   void DoRecvData (Ptr<Packet> packet);
 
+  // internal methods
+  void DoActivateEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft);
+  void SwitchToState (State s);
+
+  State m_state;
+
+  TracedCallback<State, State> m_stateTransitionCallback;
+
   Ptr<EpcHelper> m_epcHelper;
   Ptr<NetDevice> m_device;
 
+  Ptr<NetDevice> m_enbDevice; // might go away in future versions
+
   uint64_t m_imsi;
   
   LteAsSapProvider* m_asSapProvider;
@@ -137,6 +173,14 @@
 
   Callback <void, Ptr<Packet> > m_forwardUpCallback;
 
+  struct BearerToBeActivated
+  {
+    EpsBearer bearer;
+    Ptr<EpcTft> tft;
+  };
+
+  std::list<BearerToBeActivated> m_bearersToBeActivatedList;
+
 };
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/eps-bearer-tag.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,116 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Marco Miozzo <marco.miozzo@cttc.es>
+ *         Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+#include "eps-bearer-tag.h"
+#include "ns3/tag.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (EpsBearerTag);
+
+TypeId
+EpsBearerTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::EpsBearerTag")
+    .SetParent<Tag> ()
+    .AddConstructor<EpsBearerTag> ()
+    .AddAttribute ("rnti", "The rnti that indicates the UE which packet belongs",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&EpsBearerTag::GetRnti),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("bid", "The EPS bearer id within the UE to which the packet belongs",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&EpsBearerTag::GetBid),
+                   MakeUintegerChecker<uint8_t> ())
+  ;
+  return tid;
+}
+
+TypeId
+EpsBearerTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+EpsBearerTag::EpsBearerTag ()
+  : m_rnti (0),
+    m_bid (0)
+{
+}
+EpsBearerTag::EpsBearerTag (uint16_t rnti, uint8_t bid)
+  : m_rnti (rnti),
+    m_bid (bid)
+{
+}
+
+void
+EpsBearerTag::SetRnti (uint16_t rnti)
+{
+  m_rnti = rnti;
+}
+
+void
+EpsBearerTag::SetBid (uint8_t bid)
+{
+  m_bid = bid;
+}
+
+uint32_t
+EpsBearerTag::GetSerializedSize (void) const
+{
+  return 3;
+}
+
+void
+EpsBearerTag::Serialize (TagBuffer i) const
+{
+  i.WriteU16 (m_rnti);
+  i.WriteU8 (m_bid);
+}
+
+void
+EpsBearerTag::Deserialize (TagBuffer i)
+{
+  m_rnti = (uint16_t) i.ReadU16 ();
+  m_bid = (uint8_t) i.ReadU8 ();
+}
+
+uint16_t
+EpsBearerTag::GetRnti () const
+{
+  return m_rnti;
+}
+
+uint8_t
+EpsBearerTag::GetBid () const
+{
+  return m_bid;
+}
+
+void
+EpsBearerTag::Print (std::ostream &os) const
+{
+  os << "rnti=" << m_rnti << ", bid=" << (uint16_t) m_bid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/eps-bearer-tag.h	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,85 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Marco Miozzo  <marco.miozzo@cttc.es>
+ *         Nicola Baldo <nbaldo@cttc.es>
+ */
+#ifndef EPS_BEARER_TAG_H
+#define EPS_BEARER_TAG_H
+
+#include "ns3/tag.h"
+
+namespace ns3 {
+
+class Tag;
+
+
+/**
+ * Tag used to define the RNTI and EPS bearer ID for packets
+ * interchanged between the EpcEnbApplication and the LteEnbNetDevice 
+ */
+
+class EpsBearerTag : public Tag
+{
+public:
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  /**
+   * Create an empty EpsBearerTag
+   */
+  EpsBearerTag ();
+
+  /**
+   * Create a EpsBearerTag with the given RNTI and bearer id
+   */
+  EpsBearerTag (uint16_t  rnti, uint8_t bid);
+  
+  /**
+   * Set the RNTI to the given value.
+   *
+   * @param rnti the value of the RNTI to set
+   */
+  void SetRnti (uint16_t tid);
+
+  /**
+   * Set the bearer id to the given value.
+   *
+   * @param bid the value of the RNTI to set
+   */
+  void SetBid (uint8_t bid);
+
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual uint32_t GetSerializedSize () const;
+  virtual void Print (std::ostream &os) const;
+
+  uint16_t GetRnti (void) const;
+  uint8_t GetBid (void) const;
+  uint8_t GetLayer (void) const;
+
+private:
+  uint16_t m_rnti;
+  uint8_t m_bid;
+
+};
+
+
+
+} // namespace ns3
+
+#endif /* EPS_BEARER_TAG_H */
--- a/src/lte/model/lte-as-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-as-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -55,7 +55,6 @@
   /** 
    * Tell the RRC to go into Connected Mode
    * 
-   * \param params the parameters
    */
   virtual void Connect (void) = 0;
 
@@ -63,11 +62,17 @@
    * Send a data packet
    * 
    * \param packet the packet
-   * \param drbId the EPS bearer ID
-   * \return true if successful, false otherwise
+   * \param bid the EPS bearer ID
    */
   virtual void SendData (Ptr<Packet> packet, uint8_t bid) = 0;
 
+
+  /** 
+   * Tell the RRC to release the connection
+   * 
+   */
+  virtual void Disconnect () = 0;
+
 };
   
 
@@ -98,6 +103,12 @@
 
 
   /** 
+   * Notify the NAS that RRC Connection was released
+   * 
+   */
+  virtual void NotifyConnectionReleased () = 0;
+
+  /** 
    * receive a data packet
    * 
    * \param packet the packet
@@ -124,6 +135,7 @@
   virtual void Connect (void);
   virtual void ForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
   virtual void SendData (Ptr<Packet> packet, uint8_t bid);
+  virtual void Disconnect ();
 
 private:
   MemberLteAsSapProvider ();
@@ -163,6 +175,13 @@
   m_owner->DoSendData (packet, bid);
 }
 
+template <class C>
+void 
+MemberLteAsSapProvider<C>::Disconnect ()
+{
+  m_owner->DoDisconnect ();
+}
+
 
 /**
  * Template for the implementation of the LteAsSapUser as a member
@@ -179,6 +198,7 @@
   virtual void NotifyConnectionSuccessful ();
   virtual void NotifyConnectionFailed ();
   virtual void RecvData (Ptr<Packet> packet);
+  virtual void NotifyConnectionReleased ();
 
 private:
   MemberLteAsSapUser ();
@@ -217,6 +237,13 @@
   m_owner->DoRecvData (packet);
 }
 
+template <class C>
+void 
+MemberLteAsSapUser<C>::NotifyConnectionReleased ()
+{
+  m_owner->DoNotifyConnectionReleased ();
+}
+
 
 } // namespace ns3
 
--- a/src/lte/model/lte-control-messages.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-control-messages.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -32,16 +32,12 @@
 namespace ns3 {
 
 LteControlMessage::LteControlMessage (void)
-  : m_source (0),
-    m_destination (0)
 {
 }
 
 
 LteControlMessage::~LteControlMessage (void)
 {
-  m_source = 0;
-  m_destination = 0;
 }
 
 
@@ -176,5 +172,87 @@
 }
 
 
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+RachPreambleLteControlMessage::RachPreambleLteControlMessage (void)
+{
+  SetMessageType (LteControlMessage::RACH_PREAMBLE);
+}
+
+void
+RachPreambleLteControlMessage::SetPrachId (uint32_t prachId)
+{
+  m_prachId = prachId;
+}
+
+uint32_t 
+RachPreambleLteControlMessage::GetPrachId () const
+{
+  return m_prachId;
+}
+
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+RarLteControlMessage::RarLteControlMessage (void)
+{
+  SetMessageType (LteControlMessage::RAR);
+}
+
+
+void
+RarLteControlMessage::SetRar (BuildRarListElement_s rar)
+{
+  m_rar = rar;
+}
+
+BuildRarListElement_s 
+RarLteControlMessage::GetRar () const
+{
+  return m_rar;
+}
+
+
+void
+RarLteControlMessage::SetPrachId (uint32_t prachId)
+{
+  m_prachId = prachId;
+}
+
+uint32_t 
+RarLteControlMessage::GetPrachId () const
+{
+  return m_prachId;
+}
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+
+MibLteControlMessage::MibLteControlMessage (void)
+{
+  SetMessageType (LteControlMessage::MIB);
+}
+
+
+void
+MibLteControlMessage::SetMib (LteRrcSap::MasterInformationBlock  mib)
+{
+  m_mib = mib;
+}
+
+LteRrcSap::MasterInformationBlock 
+MibLteControlMessage::GetMib () const
+{
+  return m_mib;
+}
+
+
+
 } // namespace ns3
 
--- a/src/lte/model/lte-control-messages.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-control-messages.h	Tue Oct 30 16:02:07 2012 +0100
@@ -48,7 +48,10 @@
   {
     DL_DCI, UL_DCI, // Downlink/Uplink Data Control Indicator
     DL_CQI, UL_CQI, // Downlink/Uplink Channel Quality Indicator
-    BSR // Buffer Status Report
+    BSR, // Buffer Status Report
+    RACH_PREAMBLE, // Random Access Preamble
+    RAR, // Random Access Response
+    MIB, // Master Information Block
   };
 
   LteControlMessage (void);
@@ -66,8 +69,6 @@
   MessageType GetMessageType (void);
 
 private:
-  Ptr<LteNetDevice> m_source;
-  Ptr<LteNetDevice> m_destination;
   MessageType m_type;
 };
 } // namespace ns3
@@ -251,7 +252,124 @@
 
 
 };
+
+} // namespace ns3
+
+#endif  // BSR_LTE_CONTROL_MESSAGES_H
+
+
+
+#ifndef RACH_PREAMBLE_LTE_CONTROL_MESSAGES_H
+#define RACH_PREAMBLE_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ *
+ * abstract model for the Random Access Preamble
+ */
+class RachPreambleLteControlMessage : public LteControlMessage
+{
+public:
+  RachPreambleLteControlMessage (void);
+
+  void SetPrachId (uint32_t prachId);
+
+  uint32_t GetPrachId () const;
+
+private:
+  
+  uint32_t m_prachId;
+
+
+};
+
 } // namespace ns3
 
-#endif /* LTE_CONTROL_MESSAGES_H */
+#endif  // RACH_PREAMBLE_LTE_CONTROL_MESSAGES_H
+
+
+#ifndef RAR_LTE_CONTROL_MESSAGES_H
+#define RAR_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ *
+ * abstract model for the MAC Random Access Response message
+ */
+class RarLteControlMessage : public LteControlMessage
+{
+public:
+  RarLteControlMessage (void);
+
+  void SetRar (BuildRarListElement_s);
+
+  BuildRarListElement_s GetRar () const;
+  
+  void SetPrachId (uint32_t prachId);
+  
+  uint32_t GetPrachId () const;
+
+
+private:
+  
+  BuildRarListElement_s m_rar;
+  uint32_t m_prachId;
+
+};
+
+} // namespace ns3
 
+#endif  // RAR_LTE_CONTROL_MESSAGES_H
+
+
+
+
+#ifndef MIB_LTE_CONTROL_MESSAGES_H
+#define MIB_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ *
+ * abstract model for broadcasting the Master Information Block
+ */
+class MibLteControlMessage : public LteControlMessage
+{
+public:
+
+  MibLteControlMessage (void);
+
+  void SetMib (LteRrcSap::MasterInformationBlock mib);
+
+  LteRrcSap::MasterInformationBlock GetMib () const;
+  
+private:
+  
+  LteRrcSap::MasterInformationBlock m_mib;
+
+};
+
+} // namespace ns3
+
+#endif  // MIB_LTE_CONTROL_MESSAGES_H
--- a/src/lte/model/lte-enb-cmac-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-cmac-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -135,6 +135,14 @@
 {
 public:
   virtual ~LteEnbCmacSapUser ();
+
+  /** 
+   * request the allocation of a Temporary C-RNTI 
+   *
+   * \return the T-C-RNTI
+   */
+  virtual uint16_t AllocateTemporaryCellRnti () = 0;
+
   /**
    * notify the result of the last LC config operation
    *
--- a/src/lte/model/lte-enb-cphy-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-cphy-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -25,6 +25,8 @@
 #include <stdint.h>
 #include <ns3/ptr.h>
 
+#include <ns3/lte-rrc-sap.h>
+
 namespace ns3 {
 
 class LteEnbNetDevice;
@@ -69,6 +71,13 @@
    * \param rnti the UE id relative to this cell
    */
   virtual void AddUe (uint16_t rnti) = 0;
+
+  /** 
+   * Remove an UE from the the cell
+   * 
+   * \param rnti the UE id relative to this cell
+   */
+  virtual void RemoveUe (uint16_t rnti) = 0;
   
   /**
    * \param rnti the RNTI of the user
@@ -82,6 +91,11 @@
    */
   virtual void SetSrsConfigurationIndex (uint16_t  rnti, uint16_t srsCi) = 0;
 
+  /** 
+   * 
+   * \param mib the Master Information Block to be sent on the BCH
+   */
+  virtual void SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib) = 0;
 };
 
 
@@ -119,9 +133,11 @@
   virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
   virtual void SetEarfcn (uint16_t ulEarfcn, uint16_t dlEarfcn);
   virtual void AddUe (uint16_t rnti);
+  virtual void RemoveUe (uint16_t rnti);
   virtual void SetTransmissionMode (uint16_t  rnti, uint8_t txMode);
   virtual void SetSrsConfigurationIndex (uint16_t  rnti, uint16_t srsCi);
-
+  virtual void SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
+  
 private:
   MemberLteEnbCphySapProvider ();
   C* m_owner;
@@ -167,6 +183,12 @@
   m_owner->DoAddUe (rnti);
 }
 
+template <class C>
+void 
+MemberLteEnbCphySapProvider<C>::RemoveUe (uint16_t rnti)
+{
+  m_owner->DoRemoveUe (rnti);
+}
 
 template <class C>
 void 
@@ -182,6 +204,12 @@
   m_owner->DoSetSrsConfigurationIndex (rnti, srsCi);
 }
 
+template <class C> 
+void 
+MemberLteEnbCphySapProvider<C>::SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib)
+{
+  m_owner->DoSetMasterInformationBlock (mib);
+}
 
 
 
--- a/src/lte/model/lte-enb-mac.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-mac.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -233,6 +233,7 @@
   virtual void ReceivePhyPdu (Ptr<Packet> p);
   virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
   virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
+  virtual void ReceiveRachPreamble (uint32_t prachId);
   virtual void UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi);
 
 private:
@@ -263,6 +264,12 @@
 }
 
 void
+EnbMacMemberLteEnbPhySapUser::ReceiveRachPreamble (uint32_t prachId)
+{
+  m_mac->DoReceiveRachPreamble (prachId);
+}
+
+void
 EnbMacMemberLteEnbPhySapUser::UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
 {
   m_mac->DoUlCqiReport (ulcqi);
@@ -513,10 +520,32 @@
     }
   else
     {
-      NS_LOG_LOGIC (this << " LteControlMessage not recognized");
+      NS_LOG_LOGIC (this << " LteControlMessage type " << msg->GetMessageType () << " not recognized");
     }
 }
 
+void
+LteEnbMac::DoReceiveRachPreamble  (uint32_t prachId)
+{
+  NS_LOG_FUNCTION (this << prachId);
+  uint16_t rnti = m_cmacSapUser->AllocateTemporaryCellRnti ();
+  
+  // todo: should trigger SCHED_DL_RACH_INFO_REQ here
+  // and then wait for DL_SCHEDULE_INDICATION to build the RARs from the RAR_List
+
+  // for now, we take a shortcut and just build the RAR here as an ideal message and without an UL grant
+
+  BuildRarListElement_s rar;
+  rar.m_rnti = rnti;
+  
+  Ptr<RarLteControlMessage> msg = Create<RarLteControlMessage> ();
+  msg->SetPrachId (prachId);
+  msg->SetRar (rar);
+  m_enbPhySapProvider->SendLteControlMessage (msg);
+  
+}
+
+
 
 void
 LteEnbMac::DoUlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
@@ -551,7 +580,6 @@
 }
 
 
-
 void
 LteEnbMac::DoReceivePhyPdu (Ptr<Packet> p)
 {
@@ -602,7 +630,6 @@
 
 
 
-
 // ////////////////////////////////////////////
 // CMAC SAP
 // ////////////////////////////////////////////
@@ -628,6 +655,7 @@
   FfMacCschedSapProvider::CschedUeConfigReqParameters params;
   params.m_rnti = rnti;
   params.m_transmissionMode = 0; // set to default value (SISO) for avoiding random initialization (valgrind error)
+
   m_cschedSapProvider->CschedUeConfigReq (params);
 }
 
@@ -644,10 +672,11 @@
 LteEnbMac::DoAddLc (LteEnbCmacSapProvider::LcInfo lcinfo, LteMacSapUser* msu)
 {
   NS_LOG_FUNCTION (this);
+
   std::map <LteFlowId_t, LteMacSapUser* >::iterator it;
-
+  
   LteFlowId_t flow (lcinfo.rnti, lcinfo.lcId);
-
+  
   it = m_rlcAttached.find (flow);
   if (it == m_rlcAttached.end ())
     {
@@ -658,24 +687,30 @@
       NS_LOG_ERROR ("LC already exists");
     }
 
-
-  struct FfMacCschedSapProvider::CschedLcConfigReqParameters params;
-  params.m_rnti = lcinfo.rnti;
-  params.m_reconfigureFlag = false;
+  // CCCH (LCID 0) is pre-configured 
+  // see FF LTE MAC Scheduler
+  // Interface Specification v1.11, 
+  // 4.3.4 logicalChannelConfigListElement
+  if (lcinfo.lcId != 0)
+    {
+      struct FfMacCschedSapProvider::CschedLcConfigReqParameters params;
+      params.m_rnti = lcinfo.rnti;
+      params.m_reconfigureFlag = false;
 
-  struct LogicalChannelConfigListElement_s lccle;
-  lccle.m_logicalChannelIdentity = lcinfo.lcId;
-  lccle.m_logicalChannelGroup = lcinfo.lcGroup;
-  lccle.m_direction = LogicalChannelConfigListElement_s::DIR_BOTH;
-  lccle.m_qosBearerType = lcinfo.isGbr ? LogicalChannelConfigListElement_s::QBT_GBR : LogicalChannelConfigListElement_s::QBT_NON_GBR;
-  lccle.m_qci = lcinfo.qci;
-  lccle.m_eRabMaximulBitrateUl = lcinfo.mbrUl;
-  lccle.m_eRabMaximulBitrateDl = lcinfo.mbrDl;
-  lccle.m_eRabGuaranteedBitrateUl = lcinfo.gbrUl;
-  lccle.m_eRabGuaranteedBitrateDl = lcinfo.gbrDl;
-  params.m_logicalChannelConfigList.push_back (lccle);
+      struct LogicalChannelConfigListElement_s lccle;
+      lccle.m_logicalChannelIdentity = lcinfo.lcId;
+      lccle.m_logicalChannelGroup = lcinfo.lcGroup;
+      lccle.m_direction = LogicalChannelConfigListElement_s::DIR_BOTH;
+      lccle.m_qosBearerType = lcinfo.isGbr ? LogicalChannelConfigListElement_s::QBT_GBR : LogicalChannelConfigListElement_s::QBT_NON_GBR;
+      lccle.m_qci = lcinfo.qci;
+      lccle.m_eRabMaximulBitrateUl = lcinfo.mbrUl;
+      lccle.m_eRabMaximulBitrateDl = lcinfo.mbrDl;
+      lccle.m_eRabGuaranteedBitrateUl = lcinfo.gbrUl;
+      lccle.m_eRabGuaranteedBitrateDl = lcinfo.gbrDl;
+      params.m_logicalChannelConfigList.push_back (lccle);
 
-  m_cschedSapProvider->CschedLcConfigReq (params);
+      m_cschedSapProvider->CschedLcConfigReq (params);
+    }
 }
 
 void
@@ -875,6 +910,7 @@
   FfMacCschedSapProvider::CschedUeConfigReqParameters req;
   req.m_rnti = params.m_rnti;
   req.m_transmissionMode = params.m_transmissionMode;
+  req.m_reconfigureFlag = true;
   m_cschedSapProvider->CschedUeConfigReq (req);
 }
 
--- a/src/lte/model/lte-enb-mac.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-mac.h	Tue Oct 30 16:02:07 2012 +0100
@@ -119,6 +119,8 @@
   void SetLteEnbPhySapProvider (LteEnbPhySapProvider* s);
 
 
+private:
+
   /**
   * \brief Receive a DL CQI ideal control message
   * \param msg the DL CQI message
@@ -133,11 +135,11 @@
   */
   void ReceiveBsrMessage  (MacCeListElement_s bsr);
 
+ 
   void DoUlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi);
 
 
 
-private:
   // forwarded from LteEnbCmacSapProvider
   void DoConfigureMac (uint8_t ulBandwidth, uint8_t dlBandwidth);
   void DoAddUe (uint16_t rnti);
@@ -166,25 +168,15 @@
   
   void DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params);
 
-  /**
-  * \brief Forwarded from LteEnbPhySapUser: trigger the start from a new frame
-  *
-  * \param frameNo frame number
-  * \param subframeNo subframe number
-  */
+  // forwarded from LteEnbPhySapUser
   void DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo);
+  void DoReceiveRachPreamble (uint32_t prachId);
 
-  /**
-  * \brief Forwarded from LtePhySapUser: receive a PHY-PDU
-  *
-  * \param p PHY-PDU received
-  */
 public:
   // legacy public for use the Phy callback
   void DoReceivePhyPdu (Ptr<Packet> p);
 
 private:
-private:
   std::map <LteFlowId_t, LteMacSapUser*> m_rlcAttached;
 
   std::vector <CqiListElement_s> m_dlCqiReceived; // DL-CQI received
--- a/src/lte/model/lte-enb-net-device.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-net-device.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -265,7 +265,7 @@
 {
   NS_LOG_FUNCTION (this << packet   << dest << protocolNumber);
   NS_ASSERT_MSG (protocolNumber == Ipv4L3Protocol::PROT_NUMBER, "unsupported protocol " << protocolNumber << ", only IPv4 is supported");
-  return m_rrc->Send (packet);
+  return m_rrc->SendData (packet);
 }
 
 
--- a/src/lte/model/lte-enb-phy-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-phy-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -97,6 +97,13 @@
    */
   virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg) = 0;
 
+  /** 
+   * notify the reception of a RACH preamble on the PRACH 
+   * 
+   * \param prachId the ID of the preamble
+   */
+  virtual void ReceiveRachPreamble (uint32_t prachId) = 0;
+
   /**
    * \brief Returns to MAC level the UL-CQI evaluated
    * \param ulcqi the UL-CQI (see FF MAC API 4.3.29)
--- a/src/lte/model/lte-enb-phy.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-phy.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -72,8 +72,6 @@
   virtual void SetCellId (uint16_t cellId);
   virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
   virtual uint8_t GetMacChTtiDelay ();
-  virtual void SetTransmissionMode (uint16_t  rnti, uint8_t txMode);
-  virtual void SetSrsConfigurationIndex (uint16_t  rnti, uint16_t srcCi);
   
 
 private:
@@ -85,7 +83,6 @@
 
 }
 
-
 void
 EnbMemberLteEnbPhySapProvider::SendMacPdu (Ptr<Packet> p)
 {
@@ -116,18 +113,6 @@
   return (m_phy->DoGetMacChTtiDelay ());
 }
 
-void
-EnbMemberLteEnbPhySapProvider::SetTransmissionMode (uint16_t  rnti, uint8_t txMode)
-{
-  m_phy->DoSetTransmissionMode (rnti, txMode);
-}
-
-void
-EnbMemberLteEnbPhySapProvider::SetSrsConfigurationIndex (uint16_t  rnti, uint16_t srcCi)
-{
-  m_phy->DoSetSrsConfigurationIndex (rnti, srcCi);
-}
-
 
 ////////////////////////////////////////
 // generic LteEnbPhy methods
@@ -419,9 +404,20 @@
   std::list<Ptr<LteControlMessage> >::iterator it;
   for (it = msgList.begin (); it != msgList.end(); it++)
     {
-      m_enbPhySapUser->ReceiveLteControlMessage (*it);
+      switch ((*it)->GetMessageType ())
+        {
+        case LteControlMessage::RACH_PREAMBLE:
+          {
+            Ptr<RachPreambleLteControlMessage> rachPreamble = DynamicCast<RachPreambleLteControlMessage> (*it);
+            m_enbPhySapUser->ReceiveRachPreamble (rachPreamble->GetPrachId ());
+          }
+          break;
+          
+        default:
+          m_enbPhySapUser->ReceiveLteControlMessage (*it);
+          break;
+        }
     }
-    
 }
 
 
@@ -434,6 +430,13 @@
   ++m_nrFrames;
   NS_LOG_INFO ("-----frame " << m_nrFrames << "-----");
   m_nrSubFrames = 0;
+
+  // send MIB at beginning of every frame
+  m_mib.systemFrameNumber = m_nrSubFrames;
+  Ptr<MibLteControlMessage> mibMsg = Create<MibLteControlMessage> ();
+  mibMsg->SetMib (m_mib);
+  m_controlMessagesQueue.at (0).push_back (mibMsg);
+
   StartSubFrame ();
 }
 
@@ -447,7 +450,9 @@
   if (m_srsPeriodicity>0)
     { 
       // might be 0 in case the eNB has no UEs attached
-      m_currentSrsOffset = (m_currentSrsOffset + 1) % m_srsPeriodicity;
+        NS_ASSERT_MSG (m_nrFrames > 1, "the SRS index check code assumes that frameNo starts at 1");
+      NS_ASSERT_MSG (m_nrSubFrames > 0 && m_nrSubFrames <= 10, "the SRS index check code assumes that subframeNo starts at 1");
+      m_currentSrsOffset = (((m_nrFrames-1)*10 + (m_nrSubFrames-1)) % m_srsPeriodicity);
     }
   NS_LOG_INFO ("-----sub frame " << m_nrSubFrames << "-----");
   
@@ -677,6 +682,15 @@
   NS_ASSERT_MSG (success, "AddUePhy() failed");
 }
 
+void 
+LteEnbPhy::DoRemoveUe (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << rnti);
+ 
+  bool success = DeleteUePhy (rnti);
+  NS_ASSERT_MSG (success, "DeleteUePhy() failed");
+}
+
 
 FfMacSchedSapProvider::SchedUlCqiInfoReqParameters
 LteEnbPhy::CreateSrsCqiReport (const SpectrumValue& sinr)
@@ -754,7 +768,6 @@
       m_srsUeOffset.clear ();
       m_srsUeOffset.resize (p, 0);
       m_srsPeriodicity = p;
-      m_currentSrsOffset = p - 1; // for starting from 0 next subframe
     }
     
   NS_LOG_DEBUG (this << " ENB SRS P " << m_srsPeriodicity << " RNTI " << rnti << " offset " << GetSrsSubframeOffset (srcCi) << " CI " << srcCi);
@@ -772,4 +785,12 @@
 }
 
 
+void 
+LteEnbPhy::DoSetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib)
+{
+  NS_LOG_FUNCTION (this);
+  m_mib = mib;
+}
+
+
 };
--- a/src/lte/model/lte-enb-phy.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-phy.h	Tue Oct 30 16:02:07 2012 +0100
@@ -237,12 +237,13 @@
   void DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
   void DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
   void DoAddUe (uint16_t rnti);  
+  void DoRemoveUe (uint16_t rnti);  
   void DoSetTransmissionMode (uint16_t  rnti, uint8_t txMode);
-
+  void DoSetSrsConfigurationIndex (uint16_t  rnti, uint16_t srcCi);  
+  void DoSetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
 
   // LteEnbPhySapProvider forwarded methods
   void DoSendMacPdu (Ptr<Packet> p);  
-  void DoSetSrsConfigurationIndex (uint16_t  rnti, uint16_t srcCi);  
   void DoSendLteControlMessage (Ptr<LteControlMessage> msg);  
   uint8_t DoGetMacChTtiDelay ();  
 
@@ -274,6 +275,8 @@
   std::map <uint16_t,uint16_t> m_srsCounter;
   std::vector <uint16_t> m_srsUeOffset;
   uint16_t m_currentSrsOffset;
+
+  LteRrcSap::MasterInformationBlock m_mib;
   
 };
 
--- a/src/lte/model/lte-enb-rrc.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -28,32 +28,29 @@
 #include "ns3/object-factory.h"
 #include "ns3/simulator.h"
 
-#include "ns3/lte-enb-rrc.h"
-#include "ns3/lte-enb-net-device.h"
-#include "ns3/lte-rlc.h"
-#include "ns3/lte-pdcp.h"
-#include "ns3/lte-pdcp-sap.h"
-#include "ns3/lte-radio-bearer-info.h"
-#include "lte-radio-bearer-tag.h"
+#include "lte-enb-rrc.h"
+
+#include "lte-enb-net-device.h"
+#include "lte-radio-bearer-info.h"
+#include "eps-bearer-tag.h"
 #include "ff-mac-csched-sap.h"
 #include "epc-enb-s1-sap.h"
 
 #include "lte-rlc.h"
+#include "lte-rlc-tm.h"
 #include "lte-rlc-um.h"
 #include "lte-rlc-am.h"
+#include "lte-pdcp.h"
+#include "lte-pdcp-sap.h"
 
 #include <ns3/simulator.h>
 
-// WILD HACK for UE-RRC direct communications
-#include <ns3/node-list.h>
-#include <ns3/node.h>
-#include <ns3/lte-ue-net-device.h>
-#include <ns3/lte-ue-rrc.h>
 
 
 
 NS_LOG_COMPONENT_DEFINE ("LteEnbRrc");
 
+
 namespace ns3 {
 
 
@@ -66,6 +63,7 @@
 public:
   EnbRrcMemberLteEnbCmacSapUser (LteEnbRrc* rrc);
 
+  virtual uint16_t AllocateTemporaryCellRnti ();
   virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
   virtual void RrcConfigurationUpdateInd (UeConfig params);
 
@@ -78,6 +76,12 @@
 {
 }
 
+uint16_t
+EnbRrcMemberLteEnbCmacSapUser::AllocateTemporaryCellRnti ()
+{
+  return m_rrc->DoAllocateTemporaryCellRnti ();
+}
+
 void
 EnbRrcMemberLteEnbCmacSapUser::NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
 {
@@ -91,115 +95,659 @@
 }
 
 
+const char* g_ueManagerStateName[UeManager::NUM_STATES] = 
+  {
+    "INITIAL_RANDOM_ACCESS",
+    "CONNECTION_SETUP",
+    "CONNECTED_NORMALLY",
+    "CONNECTION_RECONFIGURATION",
+    "CONNECTION_REESTABLISHMENT",
+    "HANDOVER_JOINING",
+    "HANDOVER_LEAVING",
+  };
+
+std::string ToString (UeManager::State s)
+{
+  return std::string (g_ueManagerStateName[s]);
+}
+
+
+
 ///////////////////////////////////////////
-// UeInfo 
+// UeManager 
 ///////////////////////////////////////////
 
 
-NS_OBJECT_ENSURE_REGISTERED (UeInfo);
+NS_OBJECT_ENSURE_REGISTERED (UeManager);
+
 
-UeInfo::UeInfo (void)
-  : m_lastAllocatedId (0)
+UeManager::UeManager ()
 {
-  m_imsi = 0;
-  m_srsConfigurationIndex = 0;
-  m_transmissionMode = 0;
+  NS_FATAL_ERROR ("this constructor is not espected to be used");
 }
 
 
-UeInfo::~UeInfo (void)
-{
-  // Nothing to do here
+UeManager::UeManager (Ptr<LteEnbRrc> rrc, uint16_t rnti, State s)
+  : m_lastAllocatedDrbid (0),
+    m_rnti (rnti),
+    m_imsi (0),
+    m_lastRrcTransactionIdentifier (0),
+    m_rrc (rrc),
+    m_state (s),
+    m_pendingRrcConnectionReconfiguration (false)
+{ 
+  NS_LOG_FUNCTION (this);
+
+  m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<UeManager> (this);
+
+  m_physicalConfigDedicated.haveAntennaInfoDedicated = true;
+  m_physicalConfigDedicated.antennaInfo.transmissionMode = m_rrc->m_defaultTransmissionMode;
+  m_physicalConfigDedicated.haveSoundingRsUlConfigDedicated = true;
+  m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = m_rrc->GetNewSrsConfigurationIndex ();
+
+  m_rrc->m_cmacSapProvider->AddUe (rnti);
+  m_rrc->m_cphySapProvider->AddUe (rnti);
+
+  // setup the eNB side of SRB0
+  {
+    uint8_t lcid = 0;
+
+    Ptr<LteRlc> rlc = CreateObject<LteRlcTm> ()->GetObject<LteRlc> ();
+    rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
+    rlc->SetRnti (m_rnti);
+    rlc->SetLcId (lcid);
+
+    m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();  
+    m_srb0->m_rlc = rlc;
+    m_srb0->m_srbIdentity = 1;
+    // no need to store logicalChannelConfig as SRB0 is pre-configured
+
+    LteEnbCmacSapProvider::LcInfo lcinfo;
+    lcinfo.rnti = m_rnti;
+    lcinfo.lcId = lcid;
+    // leave the rest of lcinfo empty as CCCH (LCID 0) is pre-configured
+    m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
+    
+  }
+
+  // setup the eNB side of SRB1; the UE side will be set up upon RRC connection establishment
+  {
+    uint8_t lcid = 1;
+
+    Ptr<LteRlc> rlc = CreateObject<LteRlcAm> ()->GetObject<LteRlc> ();
+    rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
+    rlc->SetRnti (m_rnti);
+    rlc->SetLcId (lcid);
+
+    Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+    pdcp->SetRnti (m_rnti);
+    pdcp->SetLcId (lcid);
+    pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+    pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+    rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+
+    m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();  
+    m_srb1->m_rlc = rlc;
+    m_srb1->m_pdcp = pdcp;
+    m_srb1->m_srbIdentity = 1;
+    m_srb1->m_logicalChannelConfig.priority = 0;
+    m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = 100;
+    m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = 100;
+    m_srb1->m_logicalChannelConfig.logicalChannelGroup = 0;
+    
+    LteEnbCmacSapProvider::LcInfo lcinfo;
+    lcinfo.rnti = m_rnti;
+    lcinfo.lcId = lcid;
+    lcinfo.lcGroup = 0; // all SRBs always mapped to LCG 0
+    lcinfo.qci = EpsBearer::GBR_CONV_VOICE; // not sure why the FF API requires a CQI even for SRBs...
+    lcinfo.isGbr = true;
+    lcinfo.mbrUl = 1e6;
+    lcinfo.mbrDl = 1e6;
+    lcinfo.gbrUl = 1e4;
+    lcinfo.gbrDl = 1e4;
+    m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
+  }
+
+  LteEnbRrcSapUser::SetupUeParameters ueParams;
+  ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider ();
+  ueParams.srb1SapProvider = m_srb1->m_pdcp->GetLtePdcpSapProvider ();
+  m_rrc->m_rrcSapUser->SetupUe (m_rnti, ueParams);
+
+  // configure MAC (and scheduler)
+  LteEnbCmacSapProvider::UeConfig req;
+  req.m_rnti = rnti;
+  req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
+  m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
+  
+  // configure PHY
+  m_rrc->m_cphySapProvider->SetTransmissionMode (rnti, m_physicalConfigDedicated.antennaInfo.transmissionMode);
+  m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (rnti, m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex);
 }
 
-TypeId UeInfo::GetTypeId (void)
+
+UeManager::~UeManager (void)
+{
+}
+
+void
+UeManager::DoDispose ()
 {
-  static TypeId  tid = TypeId ("ns3::UeInfo")
+  delete m_pdcpSapUser;
+  
+  m_rrc->m_cmacSapProvider->RemoveUe (m_rnti);
+  m_rrc->m_cphySapProvider->RemoveUe (m_rnti);
+}
+
+TypeId UeManager::GetTypeId (void)
+{
+  static TypeId  tid = TypeId ("ns3::UeManager")
     .SetParent<Object> ()
-    .AddConstructor<UeInfo> ()
-    .AddAttribute ("RadioBearerMap", "List of UE RadioBearerInfo by LCID.",
+    .AddConstructor<UeManager> ()
+    .AddAttribute ("DataRadioBearerMap", "List of UE RadioBearerInfo by DRBID.",
                    ObjectMapValue (),
-                   MakeObjectMapAccessor (&UeInfo::m_rbMap),
-                   MakeObjectMapChecker<LteRadioBearerInfo> ())
+                   MakeObjectMapAccessor (&UeManager::m_drbMap),
+                   MakeObjectMapChecker<LteDataRadioBearerInfo> ())
+    .AddTraceSource ("StateTransition",
+                     "fired upon every UE state transition seen by the UeManager at the eNB RRC",
+                     MakeTraceSourceAccessor (&UeManager::m_stateTransitionCallback))
   ;
   return tid;
 }
 
+
+uint8_t
+UeManager::SetupDataRadioBearer (EpsBearer bearer)
+{
+  NS_LOG_FUNCTION (this << (uint32_t) m_rnti);
+
+  Ptr<LteDataRadioBearerInfo> drbInfo = CreateObject<LteDataRadioBearerInfo> ();
+  uint8_t drbid = AddDataRadioBearerInfo (drbInfo);
+  uint8_t lcid = Drbid2Lcid (drbid); 
+  uint8_t bid = Drbid2Bid (drbid);  
+  drbInfo->m_epsBearerIdentity = bid;
+  drbInfo->m_drbIdentity = drbid;
+  drbInfo->m_logicalChannelIdentity = lcid;
+
+  TypeId rlcTypeId = m_rrc->GetRlcType (bearer);
+
+  ObjectFactory rlcObjectFactory;
+  rlcObjectFactory.SetTypeId (rlcTypeId);
+  Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
+  rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
+  rlc->SetRnti (m_rnti);
+
+  drbInfo->m_rlc = rlc;
+
+  rlc->SetLcId (lcid);
+
+  // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
+  // if we are using RLC/SM we don't care of anything above RLC
+  if (rlcTypeId != LteRlcSm::GetTypeId ())
+    {
+      Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+      pdcp->SetRnti (m_rnti);
+      pdcp->SetLcId (lcid);
+      pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+      pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+      rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+      drbInfo->m_pdcp = pdcp;
+    }
+    
+  LteEnbCmacSapProvider::LcInfo lcinfo;
+  lcinfo.rnti = m_rnti;
+  lcinfo.lcId = lcid;
+  lcinfo.lcGroup = m_rrc->GetLogicalChannelGroup (bearer);
+  lcinfo.qci = bearer.qci;
+  lcinfo.isGbr = bearer.IsGbr ();
+  lcinfo.mbrUl = bearer.gbrQosInfo.mbrUl;
+  lcinfo.mbrDl = bearer.gbrQosInfo.mbrDl;
+  lcinfo.gbrUl = bearer.gbrQosInfo.gbrUl;
+  lcinfo.gbrDl = bearer.gbrQosInfo.gbrDl;
+  m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
+  
+  if (drbInfo->m_rlc->GetTypeId () == LteRlcAm::GetTypeId ())
+    {
+      drbInfo->m_rlcConfig.choice =  LteRrcSap::RlcConfig::AM;
+    }
+  else
+    {
+      drbInfo->m_rlcConfig.choice =  LteRrcSap::RlcConfig::UM_BI_DIRECTIONAL;
+    }
+
+  drbInfo->m_logicalChannelIdentity = lcid;
+  drbInfo->m_logicalChannelConfig.priority =  m_rrc->GetLogicalChannelPriority (bearer);
+  drbInfo->m_logicalChannelConfig.logicalChannelGroup = m_rrc->GetLogicalChannelGroup (bearer);
+  if (bearer.IsGbr ())
+    {
+      drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = bearer.gbrQosInfo.gbrUl;      
+    }
+  else
+    {
+      drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = 0;
+    }
+  drbInfo->m_logicalChannelConfig.bucketSizeDurationMs = 1000;
+
+  return drbid;
+}
+
+
+void
+UeManager::ReleaseDataRadioBearer (uint8_t drbid)
+{
+  NS_LOG_FUNCTION (this << (uint32_t) m_rnti << (uint32_t) drbid);
+  uint8_t lcid = Drbid2Lcid (drbid);
+  std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+  NS_ASSERT_MSG (it != m_drbMap.end (), "request to remove radio bearer with unknown drbid " << drbid);
+  m_drbMap.erase (it);
+  m_rrc->m_cmacSapProvider->ReleaseLc (m_rnti, lcid);
+
+  LteRrcSap::RadioResourceConfigDedicated rrcd;
+  rrcd.havePhysicalConfigDedicated = false;
+  rrcd.drbToReleaseList.push_back (drbid);
+ 
+  LteRrcSap::RrcConnectionReconfiguration msg;
+  msg.haveMeasConfig = false;
+  msg.haveMobilityControlInfo = false;
+ 
+  m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, msg);
+}
+
+
+void 
+UeManager::ScheduleRrcConnectionReconfiguration ()
+{
+  NS_LOG_FUNCTION (this);
+  switch (m_state)
+    {
+    case INITIAL_RANDOM_ACCESS:
+    case CONNECTION_SETUP:
+    case CONNECTION_RECONFIGURATION:
+    case CONNECTION_REESTABLISHMENT:
+    case HANDOVER_JOINING:
+    case HANDOVER_LEAVING:
+      // a previous reconfiguration still ongoing, we need to wait for it to be finished
+      m_pendingRrcConnectionReconfiguration = true;
+      break;
+      
+    case CONNECTED_NORMALLY:      
+      {
+        m_pendingRrcConnectionReconfiguration = false;
+        LteRrcSap::RrcConnectionReconfiguration msg = BuildRrcConnectionReconfiguration ();
+        m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, msg);
+        SwitchToState (CONNECTION_RECONFIGURATION);
+      }
+      break;      
+      
+    default:
+      NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+      break;      
+    }
+}
+
+void 
+UeManager::SendHandoverCommand (LteRrcSap::RrcConnectionReconfiguration rcr)
+{
+  NS_LOG_FUNCTION (this);
+  m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, rcr);
+  SwitchToState (HANDOVER_LEAVING);
+}
+
+LteRrcSap::RadioResourceConfigDedicated
+UeManager::GetRadioResourceConfigForHandoverPreparationInfo ()
+{
+  NS_LOG_FUNCTION (this);
+  return BuildRadioResourceConfigDedicated ();
+}
+
+LteRrcSap::RrcConnectionReconfiguration 
+UeManager::GetHandoverCommand ()
+{
+  NS_LOG_FUNCTION (this);
+  return BuildRrcConnectionReconfiguration ();
+}
+
+void
+UeManager::SendData (uint8_t bid, Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << p << (uint16_t) bid);
+  LtePdcpSapProvider::TransmitPdcpSduParameters params;
+  params.pdcpSdu = p;
+  params.rnti = m_rnti;
+  params.lcid = Bid2Lcid (bid);
+  uint8_t drbid = Bid2Drbid (bid);
+  LtePdcpSapProvider* pdcpSapProvider = GetDataRadioBearerInfo (drbid)->m_pdcp->GetLtePdcpSapProvider ();
+  pdcpSapProvider->TransmitPdcpSdu (params);
+}
+
+std::vector<EpcX2Sap::ErabToBeSetupItem>   
+UeManager::GetErabList ()
+{
+  NS_LOG_FUNCTION (this);
+  std::vector<EpcX2Sap::ErabToBeSetupItem> ret;
+  for (std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it =  m_drbMap.begin ();
+       it != m_drbMap.end ();
+       ++it)
+    {
+      NS_FATAL_ERROR ("filling of each ErabToBeSetupItem is not implemented yet");
+    }
+  return ret;
+}
+
+void 
+UeManager::CompleteSetupUe (LteEnbRrcSapProvider::CompleteSetupUeParameters params)
+{
+  NS_LOG_FUNCTION (this);
+  m_srb0->m_rlc->SetLteRlcSapUser (params.srb0SapUser);
+  m_srb1->m_pdcp->SetLtePdcpSapUser (params.srb1SapUser);
+}
+
+void
+UeManager::RecvRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg)
+{
+  NS_LOG_FUNCTION (this);
+  m_imsi = msg.ueIdentity;
+
+  if (m_rrc->m_s1SapProvider != 0)
+    {
+      m_rrc->m_s1SapProvider->InitialUeMessage (m_imsi, m_rnti);
+    }
+
+  LteRrcSap::RrcConnectionSetup msg2;
+  msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+  msg2.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
+  m_rrc->m_rrcSapUser->SendRrcConnectionSetup (m_rnti, msg2);
+  SwitchToState (CONNECTION_SETUP);
+}
+
+void
+UeManager::RecvRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg)
+{
+  NS_LOG_FUNCTION (this);
+  SwitchToState (CONNECTED_NORMALLY);
+}
+
+void
+UeManager::RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg)
+{
+  NS_LOG_FUNCTION (this);
+  SwitchToState (CONNECTED_NORMALLY);
+}
+  
+void 
+UeManager::RecvRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg)
+{
+  NS_LOG_FUNCTION (this);
+  LteRrcSap::RrcConnectionReestablishment msg2;
+  msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+  msg2.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
+  m_rrc->m_rrcSapUser->SendRrcConnectionReestablishment (m_rnti, msg2);
+  SwitchToState (CONNECTION_REESTABLISHMENT);
+}
+
+void 
+UeManager::RecvRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg)
+{
+  NS_LOG_FUNCTION (this);
+  SwitchToState (CONNECTED_NORMALLY);
+}
+
+
+void
+UeManager::CmacUeConfigUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
+{
+  NS_LOG_FUNCTION (this << m_rnti);
+  // at this stage used only by the scheduler for updating txMode
+  
+  m_physicalConfigDedicated.antennaInfo.transmissionMode = cmacParams.m_transmissionMode;
+
+  // configure MAC (and scheduler)
+  LteEnbCmacSapProvider::UeConfig req;
+  req.m_rnti = m_rnti;
+  req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
+  m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);  
+          
+  // configure PHY
+  m_rrc->m_cphySapProvider->SetTransmissionMode (req.m_rnti, req.m_transmissionMode);
+
+  // reconfigure the UE RRC
+  ScheduleRrcConnectionReconfiguration ();
+}
+
+
+void
+UeManager::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
+{
+  NS_LOG_FUNCTION (this);
+  if (params.lcid > 2)
+    {
+      // data radio bearer
+      EpsBearerTag tag;
+      tag.SetRnti (params.rnti);
+      tag.SetBid (Lcid2Bid (params.lcid));
+      params.pdcpSdu->AddPacketTag (tag);
+      m_rrc->m_forwardUpCallback (params.pdcpSdu);
+    }
+}
+
+
+uint16_t
+UeManager::GetRnti (void)
+{
+  return m_rnti;
+}
+
 uint64_t
-UeInfo::GetImsi (void)
+UeManager::GetImsi (void)
 {
   return m_imsi;
 }
 
-void
-UeInfo::SetImsi (uint64_t imsi)
-{
-  m_imsi = imsi;
-}
-
 uint16_t
-UeInfo::GetSrsConfigurationIndex (void)
+UeManager::GetSrsConfigurationIndex (void)
 {
-  return m_srsConfigurationIndex;
-}
-
-void
-UeInfo::SetSrsConfigurationIndex (uint16_t srsConfIndex)
-{
-  m_srsConfigurationIndex = srsConfIndex;
-}
-
-uint8_t
-UeInfo::GetTransmissionMode (void)
-{
-  return m_transmissionMode;
+  return m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex;
 }
 
 void
-UeInfo::SetTransmissionMode (uint8_t txMode)
+UeManager::SetSrsConfigurationIndex (uint16_t srsConfIndex)
 {
-  m_transmissionMode = txMode;
+  NS_LOG_FUNCTION (this);
+  m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = srsConfIndex;
+  m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (m_rnti, srsConfIndex);
+  switch (m_state)
+    {
+    case INITIAL_RANDOM_ACCESS:
+      // do nothing, srs conf index will be correctly enforced upon
+      // RRC connection establishment
+      break;
+      
+    default:
+      ScheduleRrcConnectionReconfiguration ();
+      break;
+    }
+}
+
+UeManager::State
+UeManager::GetState (void)
+{
+  return m_state;
 }
 
 uint8_t
-UeInfo::AddRadioBearer (Ptr<LteRadioBearerInfo> rbi)
+UeManager::AddDataRadioBearerInfo (Ptr<LteDataRadioBearerInfo> drbInfo)
 {
   NS_LOG_FUNCTION (this);
-  for (uint8_t lcid = m_lastAllocatedId; lcid != m_lastAllocatedId - 1; ++lcid)
+  const uint8_t MAX_DRB_ID = 32;  
+  for (uint8_t drbid = (m_lastAllocatedDrbid + 1) % MAX_DRB_ID; 
+       drbid != m_lastAllocatedDrbid; 
+       drbid = (drbid + 1) % MAX_DRB_ID)
     {
-      if (lcid != 0)
+      if (drbid != 0) // 0 is not allowed
         {
-          if (m_rbMap.find (lcid) == m_rbMap.end ())
+          if (m_drbMap.find (drbid) == m_drbMap.end ())
             {
-              m_rbMap.insert (std::pair<uint8_t, Ptr<LteRadioBearerInfo> > (lcid, rbi));
-              m_lastAllocatedId = lcid;
-              return lcid;
+              m_drbMap.insert (std::pair<uint8_t, Ptr<LteDataRadioBearerInfo> > (drbid, drbInfo));
+              drbInfo->m_drbIdentity = drbid;
+              m_lastAllocatedDrbid = drbid;
+              return drbid;
             }
         }
     }
-  NS_LOG_WARN ("no more logical channel ids available");
+  NS_FATAL_ERROR ("no more data radio bearer ids available");
   return 0;
 }
 
-Ptr<LteRadioBearerInfo>
-UeInfo::GetRadioBearer (uint8_t lcid)
+Ptr<LteDataRadioBearerInfo>
+UeManager::GetDataRadioBearerInfo (uint8_t drbid)
 {
-  NS_LOG_FUNCTION (this << (uint32_t) lcid);
-  NS_ASSERT (0 != lcid);
-  std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.find (lcid);  
-  NS_ABORT_IF (it == m_rbMap.end ());
+  NS_LOG_FUNCTION (this << (uint32_t) drbid);
+  NS_ASSERT (0 != drbid);
+  std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);  
+  NS_ABORT_IF (it == m_drbMap.end ());
   return it->second;
 }
 
 
 void
-UeInfo::RemoveRadioBearer (uint8_t lcid)
+UeManager::RemoveDataRadioBearerInfo (uint8_t drbid)
+{
+  NS_LOG_FUNCTION (this << (uint32_t) drbid);
+  std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+  NS_ASSERT_MSG (it != m_drbMap.end (), "request to remove radio bearer with unknown drbid " << drbid);
+  m_drbMap.erase (it);
+}
+
+
+LteRrcSap::RrcConnectionReconfiguration
+UeManager::BuildRrcConnectionReconfiguration ()
+{
+  LteRrcSap::RrcConnectionReconfiguration msg;
+  msg.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+  msg.haveRadioResourceConfigDedicated = true;
+  msg.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
+  msg.haveMobilityControlInfo = false;
+  msg.haveMeasConfig = false;
+  return msg;
+}
+
+LteRrcSap::RadioResourceConfigDedicated
+UeManager::BuildRadioResourceConfigDedicated ()
+{
+  LteRrcSap::RadioResourceConfigDedicated rrcd;
+
+  if (m_srb1 != 0)
+    {
+      LteRrcSap::SrbToAddMod stam;
+      stam.srbIdentity = m_srb1->m_srbIdentity;
+      stam.logicalChannelConfig = m_srb1->m_logicalChannelConfig;
+      rrcd.srbToAddModList.push_back (stam);
+    }
+    
+  for (std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.begin ();
+       it != m_drbMap.end ();
+       ++it)
+    {
+      LteRrcSap::DrbToAddMod dtam;
+      dtam.epsBearerIdentity = it->second->m_epsBearerIdentity;
+      dtam.drbIdentity = it->second->m_drbIdentity;
+      dtam.rlcConfig = it->second->m_rlcConfig;
+      dtam.logicalChannelIdentity = it->second->m_logicalChannelIdentity;
+      dtam.logicalChannelConfig = it->second->m_logicalChannelConfig;
+      rrcd.drbToAddModList.push_back (dtam);
+    }
+
+  rrcd.havePhysicalConfigDedicated = true;
+  rrcd.physicalConfigDedicated = m_physicalConfigDedicated;
+  return rrcd;
+}
+
+uint8_t 
+UeManager::GetNewRrcTransactionIdentifier ()
+{
+  return ++m_lastRrcTransactionIdentifier;
+}
+
+uint8_t 
+UeManager::Lcid2Drbid (uint8_t lcid)
+{
+  NS_ASSERT (lcid > 2);
+  return lcid - 2;
+}
+
+uint8_t 
+UeManager::Drbid2Lcid (uint8_t drbid)
 {
-  NS_LOG_FUNCTION (this << (uint32_t) lcid);
-  std::map <uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.find (lcid);
-  NS_ASSERT_MSG (it != m_rbMap.end (), "request to remove radio bearer with unknown lcid " << lcid);
-  m_rbMap.erase (it);
+  return drbid + 2;
+}
+uint8_t 
+UeManager::Lcid2Bid (uint8_t lcid)
+{
+  NS_ASSERT (lcid > 2);
+  return lcid - 2;
+}
+
+uint8_t 
+UeManager::Bid2Lcid (uint8_t bid)
+{
+  return bid + 2;
+}
+
+uint8_t 
+UeManager::Drbid2Bid (uint8_t drbid)
+{
+  return drbid;
+}
+
+uint8_t 
+UeManager::Bid2Drbid (uint8_t bid)
+{
+  return bid;
 }
+
+
+void 
+UeManager::SwitchToState (State newState)
+{
+  NS_LOG_FUNCTION (this << newState);
+  State oldState = m_state;
+  m_state = newState;
+  NS_LOG_INFO ("IMSI " << m_imsi << " RNTI " << m_rnti << " UeManager " << ToString (oldState) << " --> " << ToString (newState));
+  m_stateTransitionCallback (oldState, newState);
+  
+  switch (newState)
+    {
+    case INITIAL_RANDOM_ACCESS:
+    case HANDOVER_JOINING:
+      NS_FATAL_ERROR ("cannot switch to an initial state");      
+      break;
+
+    case CONNECTION_SETUP:
+      break;
+
+    case CONNECTED_NORMALLY:    
+      {
+        if (m_pendingRrcConnectionReconfiguration == true)
+          {
+            ScheduleRrcConnectionReconfiguration ();
+          }
+      }
+      break;
+
+    case CONNECTION_RECONFIGURATION:
+      break;
+
+    case CONNECTION_REESTABLISHMENT:
+      break;
+      
+    case HANDOVER_LEAVING:
+      break;      
+
+    default:
+      break;
+    }
+}
+
+
   
 // ///////////////////////////
 // eNB RRC methods
@@ -210,7 +758,7 @@
 LteEnbRrc::LteEnbRrc ()
   : m_x2SapProvider (0),
     m_cmacSapProvider (0),
-    m_ffMacSchedSapProvider (0),
+    m_rrcSapUser (0),
     m_macSapProvider (0),
     m_s1SapProvider (0),
     m_cphySapProvider (0),
@@ -222,10 +770,12 @@
 {
   NS_LOG_FUNCTION (this);
   m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this);
-  m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<LteEnbRrc> (this);
+  m_rrcSapProvider = new MemberLteEnbRrcSapProvider<LteEnbRrc> (this);
   m_x2SapUser = new EpcX2SpecificEpcX2SapUser<LteEnbRrc> (this);
   m_s1SapUser = new MemberEpcEnbS1SapUser<LteEnbRrc> (this);
   m_cphySapUser = new MemberLteEnbCphySapUser<LteEnbRrc> (this);
+
+ 
 }
 
 
@@ -240,7 +790,7 @@
 {
   NS_LOG_FUNCTION (this);
   delete m_cmacSapUser;
-  delete m_pdcpSapUser;
+  delete m_rrcSapProvider;
   delete m_x2SapUser;
   delete m_s1SapUser;
   delete m_cphySapUser;
@@ -253,10 +803,10 @@
   static TypeId tid = TypeId ("ns3::LteEnbRrc")
     .SetParent<Object> ()
     .AddConstructor<LteEnbRrc> ()
-    .AddAttribute ("UeMap", "List of UE Info by C-RNTI.",
+    .AddAttribute ("UeMap", "List of UeManager by C-RNTI.",
                    ObjectMapValue (),
                    MakeObjectMapAccessor (&LteEnbRrc::m_ueMap),
-                   MakeObjectMapChecker<UeInfo> ())
+                   MakeObjectMapChecker<UeManager> ())
     .AddAttribute ("DefaultTransmissionMode",
                   "The default UEs' transmission mode (0: SISO)",
                   UintegerValue (0),  // default tx-mode
@@ -269,50 +819,16 @@
                    MakeEnumChecker (RLC_SM_ALWAYS, "RlcSmAlways",
                                     RLC_UM_ALWAYS, "RlcUmAlways",
                                     RLC_AM_ALWAYS, "RlcAmAlways",
-                                    PER_BASED,     "PacketErrorRateBased"))             
+                                    PER_BASED,     "PacketErrorRateBased"))
+    .AddAttribute ("SystemInformationPeriodicity",
+                   "The interval for sending system information",
+                   TimeValue (MilliSeconds (80)),  
+                   MakeTimeAccessor (&LteEnbRrc::m_systemInformationPeriodicity),
+                   MakeTimeChecker ())         
   ;
   return tid;
 }
 
-uint16_t
-LteEnbRrc::GetLastAllocatedRnti () const
-{
-  NS_LOG_FUNCTION (this);
-  return m_lastAllocatedRnti;
-}
-std::map<uint16_t,Ptr<UeInfo> > LteEnbRrc::GetUeMap (void) const
-{
-  return m_ueMap;
-}
-
-void LteEnbRrc::SetUeMap (std::map<uint16_t,Ptr<UeInfo> > ueMap)
-{
-  this->m_ueMap = ueMap;
-}
-
-
-void
-LteEnbRrc::SetLastAllocatedRnti (uint16_t lastAllocatedRnti)
-{
-  NS_LOG_FUNCTION (this << lastAllocatedRnti);
-  m_lastAllocatedRnti = lastAllocatedRnti;
-}
-
-
-void
-LteEnbRrc::SetLteEnbCphySapProvider (LteEnbCphySapProvider * s)
-{
-  NS_LOG_FUNCTION (this << s);
-  m_cphySapProvider = s;
-}
-
-LteEnbCphySapUser*
-LteEnbRrc::GetLteEnbCphySapUser ()
-{
-  NS_LOG_FUNCTION (this);
-  return m_cphySapUser;
-}
-
 void
 LteEnbRrc::SetEpcX2SapProvider (EpcX2SapProvider * s)
 {
@@ -327,7 +843,6 @@
   return m_x2SapUser;
 }
 
-
 void
 LteEnbRrc::SetLteEnbCmacSapProvider (LteEnbCmacSapProvider * s)
 {
@@ -343,13 +858,19 @@
 }
 
 void
-LteEnbRrc::SetFfMacSchedSapProvider (FfMacSchedSapProvider * s)
+LteEnbRrc::SetLteEnbRrcSapUser (LteEnbRrcSapUser * s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_rrcSapUser = s;
+}
+
+LteEnbRrcSapProvider*
+LteEnbRrc::GetLteEnbRrcSapProvider ()
 {
   NS_LOG_FUNCTION (this);
-  m_ffMacSchedSapProvider = s;
+  return m_rrcSapProvider;
 }
 
-
 void
 LteEnbRrc::SetLteMacSapProvider (LteMacSapProvider * s)
 {
@@ -370,10 +891,28 @@
   return m_s1SapUser;
 }
 
-LtePdcpSapProvider* 
-LteEnbRrc::GetLtePdcpSapProvider (uint16_t rnti, uint8_t lcid)
+void
+LteEnbRrc::SetLteEnbCphySapProvider (LteEnbCphySapProvider * s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_cphySapProvider = s;
+}
+
+LteEnbCphySapUser*
+LteEnbRrc::GetLteEnbCphySapUser ()
 {
-  return GetUeInfo (rnti)->GetRadioBearer (lcid)->m_pdcp->GetLtePdcpSapProvider ();
+  NS_LOG_FUNCTION (this);
+  return m_cphySapUser;
+}
+
+Ptr<UeManager>
+LteEnbRrc::GetUeManager (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << (uint32_t) rnti);
+  NS_ASSERT (0 != rnti);
+  std::map<uint16_t, Ptr<UeManager> >::iterator it = m_ueMap.find (rnti);  
+  NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
+  return it->second;
 }
 
 void
@@ -384,69 +923,254 @@
   m_cmacSapProvider->ConfigureMac (ulBandwidth, dlBandwidth);
   m_cphySapProvider->SetBandwidth (ulBandwidth, dlBandwidth);
   m_cphySapProvider->SetEarfcn (ulEarfcn, dlEarfcn);
+  m_dlEarfcn = dlEarfcn;
+  m_ulEarfcn = ulEarfcn;
+  m_dlBandwidth = dlBandwidth;
+  m_ulBandwidth = ulBandwidth;
   m_cellId = cellId;
   m_cphySapProvider->SetCellId (cellId);
+  LteRrcSap::MasterInformationBlock mib;
+  mib.dlBandwidth = m_dlBandwidth;
+  m_cphySapProvider->SetMasterInformationBlock (mib);
   m_configured = true;
+
+  // the first time System Information is sent
+  Simulator::Schedule (MilliSeconds (16), &LteEnbRrc::SendSystemInformation, this);
+}
+
+
+void
+LteEnbRrc::SetCellId (uint16_t cellId)
+{
+  m_cellId = cellId;
+}
+
+bool
+LteEnbRrc::SendData (Ptr<Packet> packet)
+{
+  NS_LOG_FUNCTION (this << packet);
+
+  EpsBearerTag tag;
+  bool found = packet->RemovePacketTag (tag);
+  NS_ASSERT_MSG (found, "no EpsBearerTag found in packet to be sent");
+  Ptr<UeManager> ueManager = GetUeManager (tag.GetRnti ());
+  ueManager->SendData (tag.GetBid (), packet);
+  
+  return true;
+}
+
+void 
+LteEnbRrc::SetForwardUpCallback (Callback <void, Ptr<Packet> > cb)
+{
+  m_forwardUpCallback = cb;
 }
 
-uint16_t
-LteEnbRrc::DoRecvConnectionRequest (uint64_t imsi)
+
+void
+LteEnbRrc::SendHandoverRequest (uint16_t rnti, uint16_t cellId)
 {
-  NS_LOG_FUNCTION (this);
-  // no Call Admission Control for now
-  uint16_t rnti = AddUe ();
-  std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
-  NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
-  it->second->SetImsi (imsi);
+  NS_LOG_FUNCTION (this << rnti << cellId);
+  NS_LOG_LOGIC ("Request to send HANDOVER REQUEST");
+  NS_ASSERT (m_configured);
+
+  Ptr<UeManager> ueManager = GetUeManager (rnti);
 
-  if (m_s1SapProvider != 0)
-    {
-      m_s1SapProvider->InitialUeMessage (imsi, rnti);
-    }
+  EpcX2SapProvider::HandoverRequestParams params;
+  params.oldEnbUeX2apId = rnti;
+  params.cause          = EpcX2SapProvider::HandoverDesirableForRadioReason;
+  params.sourceCellId   = m_cellId;
+  params.targetCellId   = cellId;
+  params.ueAggregateMaxBitRateDownlink = 200 * 1000;
+  params.ueAggregateMaxBitRateUplink = 100 * 1000;
+  params.bearers = ueManager->GetErabList ();
+  
+  LteRrcSap::HandoverPreparationInfo hpi;
+  hpi.asConfig.sourceUeIdentity = rnti;
+  hpi.asConfig.sourceDlCarrierFreq = m_dlEarfcn;
+  hpi.asConfig.sourceRadioResourceConfig = ueManager->GetRadioResourceConfigForHandoverPreparationInfo ();
+  params.rrcContext = m_rrcSapUser->EncodeHandoverPreparationInformation (hpi);
 
-  // send RRC connection setup
-  LteUeConfig_t ueConfig;
-  ueConfig.m_rnti = rnti;
-  ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
-  ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
-  ueConfig.m_reconfigureFlag = false;
-  Ptr<LteUeRrc> ueRrc = GetUeRrcByImsi (imsi);
-  ueRrc->DoRecvConnectionSetup (ueConfig);
-  
-  // configure MAC (and scheduler)
-  FfMacCschedSapProvider::CschedUeConfigReqParameters req;
-  req.m_rnti = rnti;
-  req.m_transmissionMode = (*it).second->GetTransmissionMode ();
+  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+  NS_LOG_LOGIC ("rrcContext   = " << params.rrcContext);
+
+  m_x2SapProvider->SendHandoverRequest (params);
+}
 
-  // configure PHY
-  m_cphySapProvider->SetTransmissionMode (rnti, (*it).second->GetTransmissionMode ());
-  m_cphySapProvider->SetSrsConfigurationIndex (rnti, (*it).second->GetSrsConfigurationIndex ());
+void 
+LteEnbRrc::DoCompleteSetupUe (uint16_t rnti, LteEnbRrcSapProvider::CompleteSetupUeParameters params)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  GetUeManager (rnti)->CompleteSetupUe (params);
+}
 
-  return rnti;
+void
+LteEnbRrc::DoRecvRrcConnectionRequest (uint16_t rnti, LteRrcSap::RrcConnectionRequest msg)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  GetUeManager (rnti)->RecvRrcConnectionRequest (msg);
+}
+
+void
+LteEnbRrc::DoRecvRrcConnectionSetupCompleted (uint16_t rnti, LteRrcSap::RrcConnectionSetupCompleted msg)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  GetUeManager (rnti)->RecvRrcConnectionSetupCompleted (msg);
 }
 
 void
-LteEnbRrc::DoRecvConnectionSetupCompleted (uint16_t rnti)
+LteEnbRrc::DoRecvRrcConnectionReconfigurationCompleted (uint16_t rnti, LteRrcSap::RrcConnectionReconfigurationCompleted msg)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  GetUeManager (rnti)->RecvRrcConnectionReconfigurationCompleted (msg);
+}
+  
+void 
+LteEnbRrc::DoRecvRrcConnectionReestablishmentRequest (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentRequest msg)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  GetUeManager (rnti)->RecvRrcConnectionReestablishmentRequest (msg);  
+}
+
+void 
+LteEnbRrc::DoRecvRrcConnectionReestablishmentComplete (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentComplete msg)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  GetUeManager (rnti)->RecvRrcConnectionReestablishmentComplete (msg);
+}
+
+
+void 
+LteEnbRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
+{
+  EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;
+  Ptr<UeManager> ueManager = GetUeManager (request.rnti);
+  response.rnti = request.rnti;
+  response.bid = ueManager->SetupDataRadioBearer (request.bearer);       
+  response.teid = request.teid;
+  if (m_s1SapProvider)
+    {          
+      m_s1SapProvider->S1BearerSetupRequest (response);
+    }
+  ueManager->ScheduleRrcConnectionReconfiguration ();
+}
+
+
+void
+LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params)
 {
   NS_LOG_FUNCTION (this);
+
+  NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST");
+
+  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+  
+  uint16_t rnti = AddUe (UeManager::HANDOVER_JOINING);
+  Ptr<UeManager> ueManager = GetUeManager (rnti);  
+
+  for (std::vector <EpcX2Sap::ErabToBeSetupItem>::iterator it = params.bearers.begin ();
+       it != params.bearers.end ();
+       ++it)
+    {
+      ueManager->SetupDataRadioBearer (it->erabLevelQosParameters);
+    }
+
+  LteRrcSap::RrcConnectionReconfiguration handoverCommand = ueManager->GetHandoverCommand ();
+  Ptr<Packet> encodedHandoverCommand = m_rrcSapUser->EncodeHandoverCommand (handoverCommand);
+
+  NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
+
+  EpcX2SapProvider::HandoverRequestAckParams ackParams;
+  ackParams.oldEnbUeX2apId = params.oldEnbUeX2apId;
+  ackParams.newEnbUeX2apId = rnti;
+  ackParams.sourceCellId = params.sourceCellId;
+  ackParams.targetCellId = params.targetCellId;
+  ackParams.rrcContext = encodedHandoverCommand;
+
+  NS_LOG_LOGIC ("oldEnbUeX2apId = " << ackParams.oldEnbUeX2apId);
+  NS_LOG_LOGIC ("newEnbUeX2apId = " << ackParams.newEnbUeX2apId);
+  NS_LOG_LOGIC ("sourceCellId = " << ackParams.sourceCellId);
+  NS_LOG_LOGIC ("targetCellId = " << ackParams.targetCellId);
+
+  m_x2SapProvider->SendHandoverRequestAck (ackParams);
 }
 
 void
-LteEnbRrc::DoRecvConnectionReconfigurationCompleted (uint16_t rnti)
+LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params)
 {
   NS_LOG_FUNCTION (this);
+  
+  NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK");
+  
+  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
+  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+
+  uint16_t rnti = params.oldEnbUeX2apId;
+  Ptr<UeManager> ueManager = GetUeManager (rnti);  
+  
+  // note: the Handover command from the target eNB to the source eNB
+  // is expected to be sent transparently tothe UE; however, here we
+  // decode the message and eventually reencode it. This way we can
+  // support both a real RRC protocol implementation and an ideal one
+  // without actual RRC protocol encoding. 
+
+  Ptr<Packet> encodedHandoverCommand = params.rrcContext;
+  LteRrcSap::RrcConnectionReconfiguration handoverCommand = m_rrcSapUser->DecodeHandoverCommand (encodedHandoverCommand);
+  ueManager->SendHandoverCommand (handoverCommand);
+
 }
 
 
+uint16_t 
+LteEnbRrc::DoAllocateTemporaryCellRnti ()
+{
+  NS_LOG_FUNCTION (this);
+  return AddUe (UeManager::INITIAL_RANDOM_ACCESS);
+}
+
+void
+LteEnbRrc::DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
+{
+  Ptr<UeManager> ueManager = GetUeManager (cmacParams.m_rnti);
+  ueManager->CmacUeConfigUpdateInd (cmacParams);
+}
+
+void
+LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
+{
+  NS_LOG_FUNCTION (this << (uint32_t) rnti);
+  NS_FATAL_ERROR ("not implemented");
+}
+
+
+
 uint16_t
-LteEnbRrc::AddUe ()
+LteEnbRrc::AddUe (UeManager::State state)
 {
   NS_LOG_FUNCTION (this);
+  bool found = false;
+  uint16_t rnti;
+  for (rnti = m_lastAllocatedRnti; 
+       (rnti != m_lastAllocatedRnti - 1) && (!found);
+       ++rnti)
+    {
+      if ((rnti != 0) && (m_ueMap.find (rnti) == m_ueMap.end ()))
+        {
+          found = true;
+          break;        
+        }
+    }
 
-  uint16_t rnti = CreateUeInfo (); // side effect: create UeInfo for this UE
-  NS_ASSERT_MSG (rnti != 0, "CreateUeInfo returned RNTI==0");
-  m_cmacSapProvider->AddUe (rnti);
-  m_cphySapProvider->AddUe (rnti);
+  NS_ASSERT_MSG (found, "no more RNTIs available (do you have more than 65535 UEs in a cell?)");
+  m_lastAllocatedRnti = rnti;
+  Ptr<UeManager> ueManager = CreateObject<UeManager> (this, rnti, state);
+  m_ueMap.insert (std::pair<uint16_t, Ptr<UeManager> > (rnti, ueManager));
+  NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueManager->GetSrsConfigurationIndex ());              
   return rnti;
 }
 
@@ -454,9 +1178,14 @@
 LteEnbRrc::RemoveUe (uint16_t rnti)
 {
   NS_LOG_FUNCTION (this << (uint32_t) rnti);
-  RemoveUeInfo (rnti);
-  NS_FATAL_ERROR ("missing RemoveUe method in CMAC SAP");
-}
+  NS_FATAL_ERROR ("I though this method was unused so far...");
+  std::map <uint16_t, Ptr<UeManager> >::iterator it = m_ueMap.find (rnti);
+  NS_ASSERT_MSG (it != m_ueMap.end (), "request to remove UE info with unknown rnti " << rnti);
+  uint16_t srsCi = (*it).second->GetSrsConfigurationIndex ();
+  m_ueMap.erase (it);
+  // need to do this after UeManager has been deleted
+  RemoveSrsConfigurationIndex (srsCi); 
+ }
 
 TypeId
 LteEnbRrc::GetRlcType (EpsBearer bearer)
@@ -493,268 +1222,14 @@
 }
 
 
-void 
-LteEnbRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
-{
-  EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;
-  std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (request.rnti);
-  NS_ASSERT_MSG (it != m_ueMap.end (), "unknown RNTI");
-  response.rnti = request.rnti;
-  response.lcid = SetupRadioBearer (response.rnti, request.bearer, request.teid);      
-  NS_ASSERT_MSG (response.lcid > 0, "SetupRadioBearer() returned LCID == 0. Too many LCs?");
-  response.teid = request.teid;
-  if (m_s1SapProvider)
-    {          
-      m_s1SapProvider->S1BearerSetupRequest (response);
-    }
-}
-
-uint8_t
-LteEnbRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint32_t teid)
-{
-  NS_LOG_FUNCTION (this << (uint32_t) rnti);
-
-  TypeId rlcTypeId = GetRlcType (bearer);
-  Ptr<UeInfo> ueInfo = GetUeInfo (rnti);
-
-  // create RLC instance
-
-  ObjectFactory rlcObjectFactory;
-  rlcObjectFactory.SetTypeId (rlcTypeId);
-  Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
-  rlc->SetLteMacSapProvider (m_macSapProvider);
-  rlc->SetRnti (rnti);
-
-  Ptr<LteRadioBearerInfo> rbInfo = CreateObject<LteRadioBearerInfo> ();
-  rbInfo->m_epsBearer = bearer;
-  rbInfo->m_teid = teid;
-  rbInfo->m_rlc = rlc;
-  uint8_t lcid = ueInfo->AddRadioBearer (rbInfo);
-  if (lcid == 0)
-    {
-      NS_LOG_WARN ("cannot setup radio bearer");
-      return 0;
-    }
-  rlc->SetLcId (lcid);
-
-  // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
-  // if we are using RLC/SM we don't care of anything above RLC
-  if (rlcTypeId != LteRlcSm::GetTypeId ())
-    {
-      Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
-      pdcp->SetRnti (rnti);
-      pdcp->SetLcId (lcid);
-      pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
-      pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
-      rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
-      rbInfo->m_pdcp = pdcp;
-    }
-    
-  LteEnbCmacSapProvider::LcInfo lcinfo;
-  lcinfo.rnti = rnti;
-  lcinfo.lcId = lcid;
-  lcinfo.lcGroup = 0; // TBD
-  lcinfo.qci = bearer.qci;
-  lcinfo.isGbr = bearer.IsGbr ();
-  lcinfo.mbrUl = bearer.gbrQosInfo.mbrUl;
-  lcinfo.mbrDl = bearer.gbrQosInfo.mbrDl;
-  lcinfo.gbrUl = bearer.gbrQosInfo.gbrUl;
-  lcinfo.gbrDl = bearer.gbrQosInfo.gbrDl;
-  m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
-
-  GetUeRrcByRnti (rnti)->SetupRadioBearer (bearer, rlcTypeId, lcid);
-  
-  return lcid;
-}
-
-void
-LteEnbRrc::ReleaseRadioBearer (uint16_t rnti, uint8_t lcId)
-{
-  NS_LOG_FUNCTION (this << (uint32_t) rnti << (uint32_t) lcId);
-  Ptr<UeInfo> ueInfo = GetUeInfo (rnti);
-  ueInfo->RemoveRadioBearer (lcId);
-}
-
-
-
-bool
-LteEnbRrc::Send (Ptr<Packet> packet)
-{
-  NS_LOG_FUNCTION (this << packet);
-
-  LteRadioBearerTag tag;
-  bool found = packet->RemovePacketTag (tag);
-  NS_ASSERT (found);
-  
-  LtePdcpSapProvider::TransmitRrcPduParameters params;
-  params.rrcPdu = packet;
-  params.rnti = tag.GetRnti ();
-  params.lcid = tag.GetLcid ();
-  LtePdcpSapProvider* pdcpSapProvider = GetLtePdcpSapProvider (tag.GetRnti (), tag.GetLcid ());
-  pdcpSapProvider->TransmitRrcPdu (params);
-  
-  return true;
-}
-
-void 
-LteEnbRrc::SetForwardUpCallback (Callback <void, Ptr<Packet> > cb)
-{
-  m_forwardUpCallback = cb;
-}
 
 
-//
-// User API
-//
-void
-LteEnbRrc::SendHandoverRequest (uint16_t rnti, uint16_t cellId)
-{
-  NS_LOG_FUNCTION (this << rnti << cellId);
-  NS_LOG_LOGIC ("Request to send HANDOVER REQUEST");
-
-  std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
-  NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
-
-  EpcX2SapProvider::HandoverRequestParams params;
-  params.oldEnbUeX2apId = rnti;
-  params.cause          = EpcX2SapProvider::HandoverDesirableForRadioReason;
-  params.sourceCellId   = m_cellId;
-  params.targetCellId   = cellId;
-  params.ueAggregateMaxBitRateDownlink = 200 * 1000;
-  params.ueAggregateMaxBitRateUplink = 100 * 1000;
-  
-  std::string rrcData ("abcdefghijklmnopqrstuvwxyz");
-  params.rrcContext = Create<Packet> ((uint8_t const *) rrcData.data (), rrcData.length ());
-
-  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
-  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
-  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
-  NS_LOG_LOGIC ("rrcContext   = " << params.rrcContext << " : " << rrcData);
-
-  m_x2SapProvider->SendHandoverRequest (params);
-}
-
-
-//
-// X2 User SAP
-//
-void
-LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params)
-{
-  NS_LOG_FUNCTION (this);
-
-  NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST");
-
-  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
-  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
-  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
-  
-  // this crashes, apparently EpcX2 is not correctly filling in the params yet
-  //  uint8_t rrcData [100];
-  // params.rrcContext->CopyData (rrcData, params.rrcContext->GetSize ());
-  // NS_LOG_LOGIC ("rrcContext   = " << rrcData);
-
-  uint16_t rnti = AddUe ();
-
-  for (std::vector <EpcX2Sap::ErabToBeSetupItem>::iterator it = params.bearers.begin ();
-       it != params.bearers.end ();
-       ++it)
-    {
-      SetupRadioBearer (rnti, it->erabLevelQosParameters, it->gtpTeid);
-    }
-
-  NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
-
-  EpcX2SapProvider::HandoverRequestAckParams ackParams;
-  ackParams.oldEnbUeX2apId = params.oldEnbUeX2apId;
-  ackParams.newEnbUeX2apId = params.oldEnbUeX2apId + 100;
-  ackParams.sourceCellId = params.sourceCellId;
-  ackParams.targetCellId = params.targetCellId;
-
-  NS_LOG_LOGIC ("oldEnbUeX2apId = " << ackParams.oldEnbUeX2apId);
-  NS_LOG_LOGIC ("newEnbUeX2apId = " << ackParams.newEnbUeX2apId);
-  NS_LOG_LOGIC ("sourceCellId = " << ackParams.sourceCellId);
-  NS_LOG_LOGIC ("targetCellId = " << ackParams.targetCellId);
-
-  m_x2SapProvider->SendHandoverRequestAck (ackParams);
-}
-
-void
-LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params)
-{
-  NS_LOG_FUNCTION (this);
-  
-  NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK");
-  
-  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
-  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
-  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
-  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
-}
-
-
-void
-LteEnbRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params)
-{
-  NS_LOG_FUNCTION (this);
-  // this tag is needed by the EpcEnbApplication to determine the S1 bearer that corresponds to this radio bearer
-  LteRadioBearerTag tag;
-  tag.SetRnti (params.rnti);
-  tag.SetLcid (params.lcid);
-  params.rrcPdu->AddPacketTag (tag);
-  m_forwardUpCallback (params.rrcPdu);
-}
-
-
-
-void
-LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
-{
-  NS_LOG_FUNCTION (this << (uint32_t) rnti);
-  NS_FATAL_ERROR ("not implemented");
-}
-
-
-
-// /////////////////////////////////////////
-// management of multiple UE info instances
-// /////////////////////////////////////////
-
 // from 3GPP TS 36.213 table 8.2-1 UE Specific SRS Periodicity
-#define SRS_ENTRIES 9
+const uint8_t SRS_ENTRIES = 9;
 uint16_t g_srsPeriodicity[SRS_ENTRIES] = {0, 2, 5, 10, 20, 40, 80, 160, 320};
 uint16_t g_srsCiLow[SRS_ENTRIES] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
 uint16_t g_srsCiHigh[SRS_ENTRIES] = {0, 1, 6, 16, 36, 76, 156, 316, 636};
 
-void
-LteEnbRrc::SetCellId (uint16_t cellId)
-{
-  m_cellId = cellId;
-}
-
-uint16_t
-LteEnbRrc::CreateUeInfo ()
-{
-  NS_LOG_FUNCTION (this);
-  for (uint16_t rnti = m_lastAllocatedRnti; rnti != m_lastAllocatedRnti - 1; ++rnti)
-    {
-      if (rnti != 0)
-        {
-          if (m_ueMap.find (rnti) == m_ueMap.end ())
-            {
-              m_lastAllocatedRnti = rnti;
-              Ptr<UeInfo> ueInfo = CreateObject<UeInfo> ();
-              ueInfo->SetSrsConfigurationIndex (GetNewSrsConfigurationIndex ());
-              m_ueMap.insert (std::pair<uint16_t, Ptr<UeInfo> > (rnti, ueInfo));
-              NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueInfo->GetSrsConfigurationIndex ());
-              return rnti;
-            }
-        }
-    }
-    
-  return 0;
-}
-
 uint16_t
 LteEnbRrc::GetNewSrsConfigurationIndex ()
 {
@@ -773,28 +1248,27 @@
   NS_LOG_DEBUG (this << " SRS p " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " set " << m_ueSrsConfigurationIndexSet.size ());
   if (m_ueSrsConfigurationIndexSet.size () == g_srsPeriodicity[m_srsCurrentPeriodicityId])
     {
-//       NS_LOG_DEBUG (this << " SRS reconfigure CIs " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " to " << g_srsPeriodicity[m_srsCurrentPeriodicityId+1] << " at " << Simulator::Now ());
+      NS_LOG_DEBUG (this << " SRS reconfigure CIs " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " to " << g_srsPeriodicity[m_srsCurrentPeriodicityId+1] << " at " << Simulator::Now ());
       // increase the current periocity for having enough CIs
       m_ueSrsConfigurationIndexSet.clear ();
       m_srsCurrentPeriodicityId++;
       NS_ASSERT (m_srsCurrentPeriodicityId < SRS_ENTRIES);
       // update all the UE's CI
       uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
-      std::map<uint16_t, Ptr<UeInfo> >::iterator it;
+      std::map<uint16_t, Ptr<UeManager> >::iterator it;
       for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
         {
           (*it).second->SetSrsConfigurationIndex (srcCi);
           m_ueSrsConfigurationIndexSet.insert (srcCi);
           m_lastAllocatedConfigurationIndex = srcCi;
+
+          // update UeManager and trigger/update RRC connection reconfiguration
+          (*it).second->SetSrsConfigurationIndex (srcCi);
+          
+          // configure PHY
+          m_cphySapProvider->SetSrsConfigurationIndex ((*it).first, srcCi);
+          
           srcCi++;
-          // send update to peer RRC
-          LteUeConfig_t ueConfig;
-          ueConfig.m_rnti = (*it).first;
-          ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
-          ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
-          ueConfig.m_reconfigureFlag = true;
-          NS_LOG_DEBUG (this << "\t rnti "<<ueConfig.m_rnti<< " CI " << ueConfig.m_srsConfigurationIndex);
-          PropagateRrcConnectionReconfiguration (ueConfig);
         }
       m_ueSrsConfigurationIndexSet.insert (m_lastAllocatedConfigurationIndex + 1);
       m_lastAllocatedConfigurationIndex++;
@@ -853,162 +1327,57 @@
         {
           // update all the UE's CI
           uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
-          std::map<uint16_t, Ptr<UeInfo> >::iterator it;
+          std::map<uint16_t, Ptr<UeManager> >::iterator it;
           for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
             {
               (*it).second->SetSrsConfigurationIndex (srcCi);
               m_ueSrsConfigurationIndexSet.insert (srcCi);
               m_lastAllocatedConfigurationIndex = srcCi;
+
+
+              // update UeManager and trigger/update RRC connection reconfiguration
+              (*it).second->SetSrsConfigurationIndex (srcCi);
+          
+              // configure PHY
+              m_cphySapProvider->SetSrsConfigurationIndex ((*it).first, (*it).second->GetSrsConfigurationIndex ());
+
               srcCi++;
-              // send update to peer RRC
-              LteUeConfig_t ueConfig;
-              ueConfig.m_rnti = (*it).first;
-              ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
-              ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
-              ueConfig.m_reconfigureFlag = false;
-              NS_LOG_DEBUG (this << "\t rnti "<<ueConfig.m_rnti<< " CI " << ueConfig.m_srsConfigurationIndex);
-
-              // avoid multiple reconfiguration during initialization
-              if (Simulator::Now ().GetNanoSeconds () != 0)
-                {                 
-                  PropagateRrcConnectionReconfiguration (ueConfig);
-                }
             }
         }
     }
 }
 
-Ptr<UeInfo>
-LteEnbRrc::GetUeInfo (uint16_t rnti)
+uint8_t 
+LteEnbRrc::GetLogicalChannelGroup (EpsBearer bearer)
 {
-  NS_LOG_FUNCTION (this << (uint32_t) rnti);
-  NS_ASSERT (0 != rnti);
-  std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);  
-  NS_ABORT_IF (it == m_ueMap.end ());
-  return it->second;
+  if (bearer.IsGbr ())
+    {
+      return 1;
+    }
+  else
+    {
+      return 2;
+    }
+}
+
+uint8_t 
+LteEnbRrc::GetLogicalChannelPriority (EpsBearer bearer)
+{
+  return bearer.qci;
 }
 
 void
-LteEnbRrc::RemoveUeInfo (uint16_t rnti)
-{
-  NS_LOG_FUNCTION (this << (uint32_t) rnti);
-  NS_FATAL_ERROR ("I though this method was unused so far...");
-  std::map <uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
-  NS_ASSERT_MSG (it != m_ueMap.end (), "request to remove UE info with unknown rnti " << rnti);
-  RemoveSrsConfigurationIndex ((*it).second->GetSrsConfigurationIndex ());
-  m_ueMap.erase (it);
-  // remove SRS configuration index
-}
-
-
-void
-LteEnbRrc::DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
-{
-  NS_LOG_FUNCTION (this);
-  // at this stage used only by the scheduler for updating txMode
-
-  LteUeConfig_t rrcParams;
-  rrcParams.m_rnti = cmacParams.m_rnti;
-  rrcParams.m_reconfigureFlag = true;
-  rrcParams.m_transmissionMode = cmacParams.m_transmissionMode;
-
-  // for now, the SRS CI is passed every time, so we need to overwrite the value
-  std::map<uint16_t, Ptr<UeInfo> >::iterator it;
-  it = m_ueMap.find (cmacParams.m_rnti);
-  NS_ASSERT_MSG (it!=m_ueMap.end (), "Unable to find UeInfo");
-  rrcParams.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
-
-  // update Tx Mode info at eNB
-  (*it).second->SetTransmissionMode (cmacParams.m_transmissionMode);
-
-  rrcParams.m_reconfigureFlag = true;
-  PropagateRrcConnectionReconfiguration (rrcParams);
-}
-
-
-void 
-LteEnbRrc::PropagateRrcConnectionReconfiguration (LteUeConfig_t params)
-{
-
-  Ptr<LteUeRrc> ueRrc = GetUeRrcByRnti (params.m_rnti);
-  ueRrc->DoRecvConnectionReconfiguration (params);
-
-  // configure MAC (and scheduler)
-  LteEnbCmacSapProvider::UeConfig req;
-  req.m_rnti = params.m_rnti;
-  req.m_transmissionMode = params.m_transmissionMode;
-  m_cmacSapProvider->UeUpdateConfigurationReq (req);  
-
-  // configure PHY
-  m_cphySapProvider->SetTransmissionMode (params.m_rnti, params.m_transmissionMode);
-  m_cphySapProvider->SetSrsConfigurationIndex (params.m_rnti, params.m_srsConfigurationIndex);
-}
-
-
-Ptr<LteUeRrc> 
-LteEnbRrc::GetUeRrcByImsi (uint64_t imsi)
+LteEnbRrc::SendSystemInformation ()
 {
   NS_LOG_FUNCTION (this);
- 
-  NodeList::Iterator listEnd = NodeList::End ();
-  bool found = false;
-  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; 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)
-            {
-              continue;
-            }
-          else
-            {
-              if (ueDev->GetImsi () == imsi)
-                {
-                  found = true;
-                  return ueDev->GetRrc ();
-                }
-            }
-        }
-    }
-  NS_ASSERT_MSG (found , " Unable to find UE with IMSI =" << imsi);
-  return 0;
-}
- 
-
-
-Ptr<LteUeRrc> 
-LteEnbRrc::GetUeRrcByRnti (uint16_t rnti)
-{
-  NS_LOG_FUNCTION (this);
-
-  NodeList::Iterator listEnd = NodeList::End ();
-  bool found = false;
-  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; 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)
-            {
-              continue;
-            }
-          else
-            {
-              Ptr<LteUeRrc> rrc = ueDev->GetRrc ();
-              if ((rrc->GetRnti () == rnti) && (rrc->GetCellId () == m_cellId))
-                {                 
-                  return rrc;
-                }
-            }
-        }
-    }
-  NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId);
-  return 0;
+  // for simplicity, we use the same periodicity for all sibs
+  // note that in real systems the periodicy of each sibs could be different
+  LteRrcSap::SystemInformation si;
+  si.haveSib2 = true;
+  si.sib2.freqInfo.ulCarrierFreq = m_ulEarfcn;
+  si.sib2.freqInfo.ulBandwidth = m_ulBandwidth;
+  m_rrcSapUser->SendSystemInformation (si);
+  Simulator::Schedule (m_systemInformationPeriodicity, &LteEnbRrc::SendSystemInformation, this);
 }
 
 } // namespace ns3
--- a/src/lte/model/lte-enb-rrc.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.h	Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
  *
  * 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
@@ -23,15 +23,18 @@
 #ifndef LTE_ENB_RRC_H
 #define LTE_ENB_RRC_H
 
-#include "ns3/object.h"
-#include "ns3/packet.h"
-#include "ns3/lte-enb-cmac-sap.h"
-#include "ns3/lte-mac-sap.h"
-#include "ns3/ff-mac-sched-sap.h"
-#include "ns3/lte-pdcp-sap.h"
-#include "ns3/epc-x2-sap.h"
+#include <ns3/nstime.h>
+#include <ns3/object.h>
+#include <ns3/packet.h>
+#include <ns3/lte-enb-cmac-sap.h>
+#include <ns3/lte-mac-sap.h>
+#include <ns3/ff-mac-sched-sap.h>
+#include <ns3/lte-pdcp-sap.h>
+#include <ns3/epc-x2-sap.h>
 #include <ns3/epc-enb-s1-sap.h>
 #include <ns3/lte-enb-cphy-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <ns3/traced-callback.h>
 
 #include <map>
 #include <set>
@@ -39,79 +42,285 @@
 namespace ns3 {
 
 class LteRadioBearerInfo;
+class LteSignalingRadioBearerInfo;
+class LteDataRadioBearerInfo;
 class EpcEnbS1SapUser;
 class EpcEnbS1SapProvider;
 class LteUeRrc;
+class LteEnbRrc;
 
 /**
  * Manages all the radio bearer information possessed by the ENB RRC for a single UE
  *
  */
-class UeInfo : public Object
+class UeManager : public Object
 {
+  friend class LtePdcpSpecificLtePdcpSapUser<UeManager>;
+
 public:
-  /**
-   *
-   *
-   * \param radioBearerInfo
-   *
-   * \return the allocated logical channel id; 0 is returned if it is not possible to allocate a channel id (e.g., id space exausted).
-   */
-  uint8_t AddRadioBearer (Ptr<LteRadioBearerInfo> radioBearerInfo);
-
-  /**
-   *
-   *
-   * \param uint8_t the logical channel id
-   *
-   * \return the LteRadioBearerInfo of the selected radio bearer
-   */
-  Ptr<LteRadioBearerInfo> GetRadioBearer (uint8_t lcid);
 
 
   /**
-   * delete the entry of the given radio bearer
+   * The state of the UeManager at the eNB RRC
+   * 
+   */
+  enum State
+    {
+      INITIAL_RANDOM_ACCESS = 0,
+      CONNECTION_SETUP,
+      CONNECTED_NORMALLY,
+      CONNECTION_RECONFIGURATION,
+      CONNECTION_REESTABLISHMENT,
+      HANDOVER_JOINING,
+      HANDOVER_LEAVING,
+      NUM_STATES
+    };
+
+  UeManager ();
+ 
+  /** 
+   * UeManager constructor
+   * 
+   * \param rrc pointer to the LteEnbRrc holding this UeManager
+   * \param rnti RNTI of the UE
+   * \param s initial state of the UeManager
+   * 
+   * \return 
+   */
+  UeManager (Ptr<LteEnbRrc> rrc, uint16_t rnti, State s);
+
+  virtual ~UeManager (void);
+
+  // inherited from Object
+protected:
+  virtual void DoDispose ();
+public: 
+  static TypeId GetTypeId (void);
+
+
+  /** 
+   * Setup a new data radio bearer, including both the configuration
+   * within the eNB and the necessary RRC signaling with the UE
+   * 
+   * \param bearer 
+   * 
+   * \return the EPS Bearer Id
+   */
+  uint8_t SetupDataRadioBearer (EpsBearer bearer);
+  
+  /**
    *
-   * \param lcid the logical channel id of the radio bearer
+   * Release a given radio bearer
+   *
+   * \param drbid the data radio bearer id of the bearer to be released
+   */
+  void ReleaseDataRadioBearer (uint8_t drbid);
+
+  /** 
+   * schedule an RRC Connection Reconfiguration procedure with the UE
+   * 
    */
-  void RemoveRadioBearer (uint8_t lcid);
+  void ScheduleRrcConnectionReconfiguration ();
+
+  /** 
+   * In the X2-based handover procedure, at the source eNB, trigger
+   * handover by sending to the UE a RRC Connection 
+   * Reconfiguration message including Mobility Control Info
+   * 
+   * \param rcr the RrcConnectionReconfiguration message including the
+   * Mobility Control Info. The content of this struct shall be
+   * provided by the target eNB.
+   */
+  void SendHandoverCommand (LteRrcSap::RrcConnectionReconfiguration rcr);
+  
+  /** 
+   * 
+   * \return the HandoverPreparationInfo sent by the source eNB to the
+   * target eNB in the X2-based handover procedure
+   */
+  LteRrcSap::RadioResourceConfigDedicated GetRadioResourceConfigForHandoverPreparationInfo ();
 
   /** 
    * 
-   * \return a const iterator pointing to the beginning of the embedded map of radio bearers 
+   * \return retrieve the data that the target eNB needs to send to the source
+   * eNB as the Handover Command in the X2-based handover
+   * procedure.
+   */
+  LteRrcSap::RrcConnectionReconfiguration GetHandoverCommand ();
+
+  /** 
+   * Send a data packet over the appropriate Data Radio Bearer
+   * 
+   * \param bid the corresponding EPS Bearer ID
+   * \param p the packet
+   */
+  void SendData (uint8_t bid, Ptr<Packet> p);
+
+  /** 
+   * 
+   * \return a list of ERAB-to-be-setup items to be put in a X2 HO REQ message
+   */
+  std::vector<EpcX2Sap::ErabToBeSetupItem> GetErabList ();
+  
+
+  // methods forwarded from RRC SAP
+  void CompleteSetupUe (LteEnbRrcSapProvider::CompleteSetupUeParameters params);
+  void RecvRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg);
+  void RecvRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg);
+  void RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg);
+  void RecvRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg);
+  void RecvRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg);
+
+
+  // methods forwarded from CMAC SAP
+  void CmacUeConfigUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams);
+
+
+  // methods forwarded from PDCP SAP
+  void DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params);
+  
+  /** 
+   * 
+   * \return the RNTI, i.e., an UE identifier that is unique within
+   * the cell
+   */
+  uint16_t GetRnti (void);
+
+  /** 
+   *
+   * \return the IMSI, i.e., a globally unique UE identifier
+   */
+  uint64_t GetImsi (void);
+
+  /** 
+   * 
+   * \return the SRS Configuration Index
    */
-  std::map <uint8_t, Ptr<LteRadioBearerInfo> >::const_iterator RadioBearerMapBegin ();
+  uint16_t GetSrsConfigurationIndex (void);  
+
+  /** 
+   * Set the SRS configuration index and do the necessary reconfiguration
+   * 
+   * \param srsConfIndex 
+   */
+  void SetSrsConfigurationIndex (uint16_t srsConfIndex);
+
+  /** 
+   * 
+   * \return the current state
+   */
+  State GetState ();
+
+
+private:
+
+  /** 
+   * Add a new LteDataRadioBearerInfo structure to the UeManager
+   * 
+   * \param radioBearerInfo 
+   * 
+   * \return the id of the newly added data radio bearer structure
+   */
+  uint8_t AddDataRadioBearerInfo (Ptr<LteDataRadioBearerInfo> radioBearerInfo);
+
+  /** 
+   * \param drbid the Data Radio Bearer id
+   * 
+   * \return the corresponding LteDataRadioBearerInfo
+   */
+  Ptr<LteDataRadioBearerInfo> GetDataRadioBearerInfo (uint8_t drbid);
+
+  /** 
+   * remove the LteDataRadioBearerInfo corresponding to a bearer being released
+   *
+   * \param drbid the Data Radio Bearer id
+   */
+  void RemoveDataRadioBearerInfo (uint8_t drbid);
+
+  /** 
+   * 
+   * \return an RrcConnectionReconfiguration struct built based on the
+   * current configuration
+   */
+  LteRrcSap::RrcConnectionReconfiguration BuildRrcConnectionReconfiguration ();
+  
+  /** 
+   * 
+   * \return a RadioResourceConfigDedicated struct built based on the
+   * current configuration
+   */
+  LteRrcSap::RadioResourceConfigDedicated BuildRadioResourceConfigDedicated ();
 
 
   /** 
    * 
-   * \return a const iterator pointing to the end of the embedded map of radio bearers 
+   * \return a newly allocated identifier for a new RRC transaction
    */
-  std::map <uint8_t, Ptr<LteRadioBearerInfo> >::const_iterator RadioBearerMapEnd ();
+  uint8_t GetNewRrcTransactionIdentifier ();
+
+  /** 
+   * \param lcid a Logical Channel Identifier
+   * 
+   * \return the corresponding Data Radio Bearer Id
+   */
+  uint8_t Lcid2Drbid (uint8_t lcid);
 
-  UeInfo ();
+  /** 
+   * \param drbid a Data Radio Bearer Id
+   * 
+   * \return the corresponding  Logical Channel Identifier
+   */
+  uint8_t Drbid2Lcid (uint8_t drbid);
 
-  virtual ~UeInfo (void);
+  /** 
+   * \param lcid a  Logical Channel Identifier
+   * 
+   * \return the corresponding EPS Bearer Identifier
+   */
+  uint8_t Lcid2Bid (uint8_t lcid);
 
-  static TypeId GetTypeId (void);
+  /** 
+   * \param bid  an EPS Bearer Identifier
+   * 
+   * \return the corresponding Logical Channel Identifier
+   */
+  uint8_t Bid2Lcid (uint8_t bid);
 
-  uint64_t GetImsi (void);
-  void SetImsi (uint64_t imsi);
+  /** 
+   * \param drbid Data Radio Bearer Id
+   * 
+   * \return the corresponding EPS Bearer Identifier
+   */
+  uint8_t Drbid2Bid (uint8_t drbid);
 
-  uint8_t GetTransmissionMode (void);  
-  void SetTransmissionMode (uint8_t txMode);
-
-  uint16_t GetSrsConfigurationIndex (void);  
-  void SetSrsConfigurationIndex (uint16_t srsConfIndex);
+  /** 
+   * \param bid an EPS Bearer Identifier
+   * 
+   * \return the corresponding Data Radio Bearer Id
+   */
+  uint8_t Bid2Drbid (uint8_t bid);
+  
+  /** 
+   * Switch the UeManager to the given state
+   * 
+   * \param s the given state
+   */
+  void SwitchToState (State s);
 
 
-
-private:
-  std::map <uint8_t, Ptr<LteRadioBearerInfo> > m_rbMap;
-  uint8_t m_lastAllocatedId;
+  std::map <uint8_t, Ptr<LteDataRadioBearerInfo> > m_drbMap;
+  Ptr<LteSignalingRadioBearerInfo> m_srb0;
+  Ptr<LteSignalingRadioBearerInfo> m_srb1;
+  uint8_t m_lastAllocatedDrbid;
+  uint16_t m_rnti;
   uint64_t m_imsi;
-  uint16_t m_srsConfigurationIndex;
-  uint8_t  m_transmissionMode;
+  uint8_t m_lastRrcTransactionIdentifier;
+  LteRrcSap::PhysicalConfigDedicated m_physicalConfigDedicated;
+  Ptr<LteEnbRrc> m_rrc;
+  State m_state;
+  LtePdcpSapUser* m_pdcpSapUser;
+  bool m_pendingRrcConnectionReconfiguration;
+  TracedCallback<State, State> m_stateTransitionCallback;
 };
 
 
@@ -124,9 +333,10 @@
 {
 
   friend class EnbRrcMemberLteEnbCmacSapUser;
-  friend class LtePdcpSpecificLtePdcpSapUser<LteEnbRrc>;
+  friend class MemberLteEnbRrcSapProvider<LteEnbRrc>;
   friend class MemberEpcEnbS1SapUser<LteEnbRrc>;
   friend class EpcX2SpecificEpcX2SapUser<LteEnbRrc>;
+  friend class UeManager;
 
 public:
   /**
@@ -142,7 +352,9 @@
 
 
   // inherited from Object
+protected:
   virtual void DoDispose (void);
+public:
   static TypeId GetTypeId (void);
 
 
@@ -174,14 +386,18 @@
 
 
   /**
-   * set the FF MAC SCHED SAP provider. The eNB RRC does not use this
-   * directly, but it needs to provide it to newly created RLC instances.
+   * set the RRC SAP this RRC should interact with
    *
-   * \param s the FF MAC SCHED SAP provider that will be used by all
-   * newly created RLC instances
+   * \param s the RRC SAP User to be used by this RRC
    */
-  void SetFfMacSchedSapProvider (FfMacSchedSapProvider* s);
+  void SetLteEnbRrcSapUser (LteEnbRrcSapUser * s);
 
+  /**
+   *
+   *
+   * \return s the RRC SAP Provider interface offered to the MAC by this RRC
+   */
+  LteEnbRrcSapProvider* GetLteEnbRrcSapProvider ();
 
   /**
    * set the MAC SAP provider. The eNB RRC does not use this
@@ -221,6 +437,14 @@
    */
   LteEnbCphySapUser* GetLteEnbCphySapUser ();
 
+  /** 
+   * 
+   * 
+   * \param rnti the identifier of an UE
+   * 
+   * \return the corresponding UeManager instance
+   */
+  Ptr<UeManager> GetUeManager (uint16_t rnti);
 
   /**
    * configure cell-specific parameters
@@ -236,73 +460,24 @@
                       uint16_t ulEarfcn, 
                       uint16_t dlEarfcn,
                       uint16_t cellId);
-
-
-  /** 
-   * receive RRC Connection Request from an UE
-   * 
-   * \param imsi the id of the UE
-   * 
-   * \return the RNTI identifying the UE in this cell
-   */
-  uint16_t DoRecvConnectionRequest (uint64_t imsi);
-
-  /** 
-   * receive RRC Connection Setup Completed from an UE
-   * 
-   * \param rnti the RNTI identifying the UE in this cell
-   */
-  void DoRecvConnectionSetupCompleted (uint16_t rnti);
   
   /** 
-   * receive RRC Connection Reconfiguration Completed message from UE
-   * 
-   * \param rnti 
+   * set the cell id of this eNB
    * 
+   * \param m_cellId 
    */
-  void DoRecvConnectionReconfigurationCompleted (uint16_t rnti);
-  
   void SetCellId (uint16_t m_cellId);
 
-  /**
-   * remove a UE from the cell
-   *
-   * \param rnti the C-RNTI identiftying the user
-   */
-  void RemoveUe (uint16_t rnti);
-
-  uint16_t GetLastAllocatedRnti () const;
-  void SetLastAllocatedRnti (uint16_t lastAllocatedRnti);
-  void SetUeMap (std::map<uint16_t,Ptr<UeInfo> > ueMap);
-  std::map<uint16_t,Ptr<UeInfo> > GetUeMap (void) const;
-
   /** 
-   * 
-   * \param bearer the specification of an EPS bearer
-   * 
-   * \return the type of RLC that is to be created for the given EPS bearer
-   */
-  TypeId GetRlcType (EpsBearer bearer);
-
-
-  /**
-   *
-   * Release the given radio bearer
-   *
-   * \param rnti the C-RNTI  of the user owning the bearer
-   * \param lcId the logical channel id of the bearer to be released
-   */
-  void ReleaseRadioBearer (uint16_t rnti, uint8_t lcId);
-
-  
-  /** 
-   * Enqueue an IP packet on the proper bearer for downlink transmission
+   * Enqueue an IP data packet on the proper bearer for downlink
+   * transmission. Normally expected to be called by the NetDevice
+   * forwarding a packet coming from the EpcEnbApplication 
    * 
    * \param p the packet
    * 
    * \return true if successful, false if an error occurred
    */
-  bool Send (Ptr<Packet> p);
+  bool SendData (Ptr<Packet> p);
 
   /** 
    * set the callback used to forward data packets up the stack
@@ -334,58 +509,108 @@
                                    PER_BASED = 4};
 private:
 
+
+  // methods forwarded from RRC SAP
+  
+  void DoCompleteSetupUe (uint16_t rnti, LteEnbRrcSapProvider::CompleteSetupUeParameters params);
+  void DoRecvRrcConnectionRequest (uint16_t rnti, LteRrcSap::RrcConnectionRequest msg);
+  void DoRecvRrcConnectionSetupCompleted (uint16_t rnti, LteRrcSap::RrcConnectionSetupCompleted msg);
+  void DoRecvRrcConnectionReconfigurationCompleted (uint16_t rnti, LteRrcSap::RrcConnectionReconfigurationCompleted msg);
+  void DoRecvRrcConnectionReestablishmentRequest (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentRequest msg);
+  void DoRecvRrcConnectionReestablishmentComplete (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentComplete msg);
+
+
+  // S1 SAP methods
+  void DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params);
+
+
+  // methods forwarded from X2 SAP
+  void DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params);
+  void DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params);
+
+
+  // CMAC SAP methods
+  uint16_t DoAllocateTemporaryCellRnti ();
+  void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
+  void DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig params);
+  
+
+
+
   /**
    * Allocate a new RNTI for a new UE. This is done in the following cases:
    *   * T-C-RNTI allocation upon contention-based MAC Random Access procedure
    *   * target cell RNTI allocation upon handover
    *
+   * \param state the initial state of the UeManager
+   *
    * \return the newly allocated RNTI
    */
-  uint16_t AddUe ();
-
-
+  uint16_t AddUe (UeManager::State state);
 
   /**
-   * Setup a new radio bearer for the given user
-   *
-   * \param rnti the RNTI of the user
-   * \param bearer the characteristics of the bearer to be activated
-   * \param teid the S1-U Tunnel Endpoint Identifier for this bearer
+   * remove a UE from the cell
    *
-   * \return the logical channel identifier of the radio bearer for the considered user
+   * \param rnti the C-RNTI identiftying the user
    */
-  uint8_t SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint32_t teid);
-
-
-  void DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params);
-  void DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params);
+  void RemoveUe (uint16_t rnti);
 
 
-  LtePdcpSapProvider* GetLtePdcpSapProvider (uint16_t rnti, uint8_t lcid);
+  /** 
+   * 
+   * \param bearer the specification of an EPS bearer
+   * 
+   * \return the type of RLC that is to be created for the given EPS bearer
+   */
+  TypeId GetRlcType (EpsBearer bearer);
 
-  // PDCP SAP methods
-  void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
+  /** 
+   * Allocate a new SRS configuration index for a new UE. 
+   *
+   * \note this method can have the side effect of updating the SRS
+   * configuration index of all UEs
+   * 
+   * \return the newly allocated SRS configuration index
+   */
+  uint16_t GetNewSrsConfigurationIndex (void);
 
-  // CMAC SAP methods
-  void DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig params);
-  void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
+  /** 
+   * remove a previously allocated SRS configuration index
+   *
+   * \note this method can have the side effect of updating the SRS
+   * configuration index of all UEs
+   * 
+   * \param srcCi the indext to be removed
+   */
+  void RemoveSrsConfigurationIndex (uint16_t srcCi);
+
+ 
 
-  // S1 SAP methods
-  void DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params);
+  /** 
+   * 
+   * \param bearer the characteristics of the bearer
+   * 
+   * \return the Logical Channel Group in a bearer with these
+   * characteristics is put. Used for MAC Buffer Status Reporting purposes. 
+   */
+  uint8_t GetLogicalChannelGroup (EpsBearer bearer);
 
-  void PropagateRrcConnectionReconfiguration (LteUeConfig_t ueConfig);
+  /** 
+   * 
+   * \param bearer the characteristics of the bearer
+   * 
+   * \return the priority level of a bearer with these
+   * characteristics is put. Used for the part of UL MAC Scheduling
+   * carried out by the UE
+   */
+  uint8_t GetLogicalChannelPriority (EpsBearer bearer);
 
 
-  // management of multiple UE info instances
-  uint16_t CreateUeInfo ();
-  Ptr<UeInfo> GetUeInfo (uint16_t rnti);
-  void RemoveUeInfo (uint16_t rnti);
-  uint16_t GetNewSrsConfigurationIndex (void);
-  void RemoveSrsConfigurationIndex (uint16_t srcCi);
-
-  // methods used to talk to UE RRC directly in absence of real RRC protocol
-  Ptr<LteUeRrc> GetUeRrcByImsi (uint64_t imsi);
-  Ptr<LteUeRrc> GetUeRrcByRnti (uint16_t rnti);
+  /** 
+   * method used to periodically send System Information
+   * 
+   */
+  void SendSystemInformation ();
 
   Callback <void, Ptr<Packet> > m_forwardUpCallback;
 
@@ -395,9 +620,10 @@
   LteEnbCmacSapUser* m_cmacSapUser;
   LteEnbCmacSapProvider* m_cmacSapProvider;
 
-  FfMacSchedSapProvider* m_ffMacSchedSapProvider;
+  LteEnbRrcSapUser* m_rrcSapUser;
+  LteEnbRrcSapProvider* m_rrcSapProvider;
+
   LteMacSapProvider* m_macSapProvider;
-  LtePdcpSapUser* m_pdcpSapUser;
 
   EpcEnbS1SapProvider* m_s1SapProvider;
   EpcEnbS1SapUser* m_s1SapUser;
@@ -407,13 +633,19 @@
 
   bool m_configured;
   uint16_t m_cellId;
+  uint16_t m_dlEarfcn;
+  uint16_t m_ulEarfcn;
+  uint16_t m_dlBandwidth;
+  uint16_t m_ulBandwidth;
   uint16_t m_lastAllocatedRnti;
 
-  std::map<uint16_t, Ptr<UeInfo> > m_ueMap;  
+  std::map<uint16_t, Ptr<UeManager> > m_ueMap;  
   
   uint8_t m_defaultTransmissionMode;
 
   enum LteEpsBearerToRlcMapping_t m_epsBearerToRlcMapping;
+
+  Time m_systemInformationPeriodicity;
   
   // SRS related attributes
   uint16_t m_srsCurrentPeriodicityId;
--- a/src/lte/model/lte-interference.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-interference.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -32,7 +32,9 @@
 
 
 LteInterference::LteInterference ()
-  : m_receiving (false)
+  : m_receiving (false),
+    m_lastSignalId (0),
+    m_lastSignalIdBeforeReset (0)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -95,11 +97,18 @@
 LteInterference::EndRx ()
 {
   NS_LOG_FUNCTION (this);
-  ConditionallyEvaluateChunk ();
-  m_receiving = false;
-  for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
+  if (m_receiving != true)
+    {
+      NS_LOG_INFO ("EndRx was already evaluated or RX was aborted");
+    }
+  else
     {
-      (*it)->End (); 
+      ConditionallyEvaluateChunk ();
+      m_receiving = false;
+      for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
+        {
+          (*it)->End (); 
+        }
     }
 }
 
@@ -108,13 +117,18 @@
 LteInterference::AddSignal (Ptr<const SpectrumValue> spd, const Time duration)
 {
   NS_LOG_FUNCTION (this << *spd << duration);
-  // if this is the first signal that we see, we need to initialize the interference calculation
-  if (m_allSignals == 0) 
+  DoAddSignal (spd);
+  uint32_t signalId = ++m_lastSignalId;
+  if (signalId == m_lastSignalIdBeforeReset)
     {
-      m_allSignals = Create<SpectrumValue> (spd->GetSpectrumModel ());
+      // This happens when m_lastSignalId eventually wraps around. Given that so
+      // many signals have elapsed since the last reset, we hope that by now there is
+      // no stale pending signal (i.e., a signal that was scheduled
+      // for subtraction before the reset). So we just move the
+      // boundary further.
+      m_lastSignalIdBeforeReset += 0x10000000;
     }
-  DoAddSignal (spd);
-  Simulator::Schedule (duration, &LteInterference::DoSubtractSignal, this, spd);
+  Simulator::Schedule (duration, &LteInterference::DoSubtractSignal, this, spd, signalId);
 }
 
 
@@ -124,16 +138,22 @@
   NS_LOG_FUNCTION (this << *spd);
   ConditionallyEvaluateChunk ();
   (*m_allSignals) += (*spd);
-  m_lastChangeTime = Now ();
 }
 
 void
-LteInterference::DoSubtractSignal  (Ptr<const SpectrumValue> spd)
+LteInterference::DoSubtractSignal  (Ptr<const SpectrumValue> spd, uint32_t signalId)
 { 
   NS_LOG_FUNCTION (this << *spd);
-  ConditionallyEvaluateChunk ();
-  (*m_allSignals) -= (*spd);
-  m_lastChangeTime = Now ();
+  ConditionallyEvaluateChunk ();   
+  int32_t deltaSignalId = signalId - m_lastSignalIdBeforeReset;
+  if (deltaSignalId > 0)
+    {   
+      (*m_allSignals) -= (*spd);
+    }
+  else
+    {
+      NS_LOG_INFO ("ignoring signal scheduled for subtraction before last reset");
+    }
 }
 
 
@@ -156,6 +176,7 @@
         {
           (*it)->EvaluateSinrChunk (sinr, duration);
         }
+      m_lastChangeTime = Now ();
     }
   else
     {
@@ -167,12 +188,19 @@
 LteInterference::SetNoisePowerSpectralDensity (Ptr<const SpectrumValue> noisePsd)
 {
   NS_LOG_FUNCTION (this << *noisePsd);
+  ConditionallyEvaluateChunk ();
   m_noise = noisePsd;
-  // we can initialize m_allSignal only now, because earlier we
-  // didn't know what spectrum model was going to be used.
-  // we'll now create a zeroed SpectrumValue using the same
-  // SpectrumModel which is being specified for the noise.
+  // reset m_allSignals (will reset if already set previously)
+  // this is needed since this method can potentially change the SpectrumModel
   m_allSignals = Create<SpectrumValue> (noisePsd->GetSpectrumModel ());
+  if (m_receiving == true)
+    {
+      // abort rx
+      m_receiving = false;
+    }
+  // record the last SignalId so that we can ignore all signals that
+  // were scheduled for subtraction before m_allSignal 
+  m_lastSignalIdBeforeReset = m_lastSignalId;
 }
 
 void
--- a/src/lte/model/lte-interference.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-interference.h	Tue Oct 30 16:02:07 2012 +0100
@@ -99,7 +99,7 @@
 private:
   void ConditionallyEvaluateChunk ();
   void DoAddSignal  (Ptr<const SpectrumValue> spd);
-  void DoSubtractSignal  (Ptr<const SpectrumValue> spd);
+  void DoSubtractSignal  (Ptr<const SpectrumValue> spd, uint32_t signalId);
 
 
 
@@ -120,12 +120,14 @@
   Time m_lastChangeTime;     /**< the time of the last change in
                                 m_TotalPower */
 
+  uint32_t m_lastSignalId;
+  uint32_t m_lastSignalIdBeforeReset;
+
   /** all the processor instances that need to be notified whenever
       a new SINR chunk is calculated */
   std::list<Ptr<LteSinrChunkProcessor> > m_sinrChunkProcessorList; 
 
 
-
 };
 
 
--- a/src/lte/model/lte-pdcp-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-pdcp-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -38,11 +38,11 @@
   virtual ~LtePdcpSapProvider ();
 
   /**
-   * Parameters for LtePdcpSapProvider::TransmitRrcPdu
+   * Parameters for LtePdcpSapProvider::TransmitPdcpSdu
    */
-  struct TransmitRrcPduParameters
+  struct TransmitPdcpSduParameters
   {
-    Ptr<Packet> rrcPdu;  /**< the RRC PDU */
+    Ptr<Packet> pdcpSdu;  /**< the RRC PDU */
     uint16_t    rnti; /**< the C-RNTI identifying the UE */
     uint8_t     lcid; /**< the logical channel id corresponding to the sending RLC instance */
   };
@@ -54,7 +54,7 @@
    * 
    * \param params 
    */
-  virtual void TransmitRrcPdu (TransmitRrcPduParameters params) = 0;
+  virtual void TransmitPdcpSdu (TransmitPdcpSduParameters params) = 0;
 };
 
 
@@ -71,11 +71,11 @@
   virtual ~LtePdcpSapUser ();
 
   /**
-   * Parameters for LtePdcpSapUser::ReceiveRrcPdu
+   * Parameters for LtePdcpSapUser::ReceivePdcpSdu
    */
-  struct ReceiveRrcPduParameters
+  struct ReceivePdcpSduParameters
   {
-    Ptr<Packet> rrcPdu;  /**< the RRC PDU */
+    Ptr<Packet> pdcpSdu;  /**< the RRC PDU */
     uint16_t    rnti; /**< the C-RNTI identifying the UE */
     uint8_t     lcid; /**< the logical channel id corresponding to the sending RLC instance */
   };
@@ -85,7 +85,7 @@
   *
   * \param params
   */
-  virtual void ReceiveRrcPdu (ReceiveRrcPduParameters params) = 0;
+  virtual void ReceivePdcpSdu (ReceivePdcpSduParameters params) = 0;
 };
 
 ///////////////////////////////////////
@@ -97,7 +97,7 @@
   LtePdcpSpecificLtePdcpSapProvider (C* pdcp);
 
   // Interface implemented from LtePdcpSapProvider
-  virtual void TransmitRrcPdu (TransmitRrcPduParameters params);
+  virtual void TransmitPdcpSdu (TransmitPdcpSduParameters params);
 
 private:
   LtePdcpSpecificLtePdcpSapProvider ();
@@ -116,9 +116,9 @@
 }
 
 template <class C>
-void LtePdcpSpecificLtePdcpSapProvider<C>::TransmitRrcPdu (TransmitRrcPduParameters params)
+void LtePdcpSpecificLtePdcpSapProvider<C>::TransmitPdcpSdu (TransmitPdcpSduParameters params)
 {
-  m_pdcp->DoTransmitRrcPdu (params.rrcPdu);
+  m_pdcp->DoTransmitPdcpSdu (params.pdcpSdu);
 }
 
 ///////////////////////////////////////
@@ -130,7 +130,7 @@
   LtePdcpSpecificLtePdcpSapUser (C* rrc);
 
   // Interface implemented from LtePdcpSapUser
-  virtual void ReceiveRrcPdu (ReceiveRrcPduParameters params);
+  virtual void ReceivePdcpSdu (ReceivePdcpSduParameters params);
 
 private:
   LtePdcpSpecificLtePdcpSapUser ();
@@ -149,9 +149,9 @@
 }
 
 template <class C>
-void LtePdcpSpecificLtePdcpSapUser<C>::ReceiveRrcPdu (ReceiveRrcPduParameters params)
+void LtePdcpSpecificLtePdcpSapUser<C>::ReceivePdcpSdu (ReceivePdcpSduParameters params)
 {
-  m_rrc->DoReceiveRrcPdu (params);
+  m_rrc->DoReceivePdcpSdu (params);
 }
 
 
--- a/src/lte/model/lte-pdcp.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-pdcp.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -145,7 +145,7 @@
 ////////////////////////////////////////
 
 void
-LtePdcp::DoTransmitRrcPdu (Ptr<Packet> p)
+LtePdcp::DoTransmitPdcpSdu (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
 
@@ -200,11 +200,11 @@
       m_rxSequenceNumber = 0;
     }
 
-  LtePdcpSapUser::ReceiveRrcPduParameters params;
-  params.rrcPdu = p;
+  LtePdcpSapUser::ReceivePdcpSduParameters params;
+  params.pdcpSdu = p;
   params.rnti = m_rnti;
   params.lcid = m_lcid;
-  m_pdcpSapUser->ReceiveRrcPdu (params);
+  m_pdcpSapUser->ReceivePdcpSdu (params);
 }
 
 void
--- a/src/lte/model/lte-pdcp.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-pdcp.h	Tue Oct 30 16:02:07 2012 +0100
@@ -90,7 +90,7 @@
 
 protected:
   // Interface provided to upper RRC entity
-  virtual void DoTransmitRrcPdu (Ptr<Packet> p);
+  virtual void DoTransmitPdcpSdu (Ptr<Packet> p);
 
   LtePdcpSapUser* m_pdcpSapUser;
   LtePdcpSapProvider* m_pdcpSapProvider;
--- a/src/lte/model/lte-radio-bearer-info.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-info.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -38,14 +38,43 @@
 LteRadioBearerInfo::~LteRadioBearerInfo (void)
 {
 }
-
-TypeId LteRadioBearerInfo::GetTypeId (void)
+  
+TypeId 
+LteRadioBearerInfo::GetTypeId (void)
 {
   static TypeId
-  tid =
+    tid =
     TypeId ("ns3::LteRadioBearerInfo")
     .SetParent<Object> ()
     .AddConstructor<LteRadioBearerInfo> ()
+    ;
+  return tid;
+}
+  
+  
+TypeId 
+LteDataRadioBearerInfo::GetTypeId (void)
+{
+  static TypeId
+    tid =
+    TypeId ("ns3::LteDataRadioBearerInfo")
+    .SetParent<LteRadioBearerInfo> ()
+    .AddConstructor<LteDataRadioBearerInfo> ()
+    .AddAttribute ("DrbIdentity", "The id of this Data Radio Bearer",
+                   TypeId::ATTR_GET, // allow only getting it.
+                   UintegerValue (0), // unused (attribute is read-only
+                   MakeUintegerAccessor (&LteDataRadioBearerInfo::m_drbIdentity),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("EpsBearerIdentity", "The id of the EPS bearer corresponding to this Data Radio Bearer",
+                   TypeId::ATTR_GET, // allow only getting it.
+                   UintegerValue (0), // unused (attribute is read-only
+                   MakeUintegerAccessor (&LteDataRadioBearerInfo::m_epsBearerIdentity),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("logicalChannelIdentity", "The id of the Logical Channel corresponding to this Data Radio Bearer",
+                   TypeId::ATTR_GET, // allow only getting it.
+                   UintegerValue (0), // unused (attribute is read-only
+                   MakeUintegerAccessor (&LteDataRadioBearerInfo::m_logicalChannelIdentity),
+                   MakeUintegerChecker<uint8_t> ())
     .AddAttribute ("LteRlc", "RLC instance of the radio bearer.",
                    PointerValue (),
                    MakePointerAccessor (&LteRadioBearerInfo::m_rlc),
@@ -54,11 +83,36 @@
                    PointerValue (),
                    MakePointerAccessor (&LteRadioBearerInfo::m_pdcp),
                    MakePointerChecker<LtePdcp> ())
-  ;
+    ;
+  return tid;
+}
+
+
+TypeId 
+LteSignalingRadioBearerInfo::GetTypeId (void)
+{
+  static TypeId
+    tid =
+    TypeId ("ns3::LteSignalingRadioBearerInfo")
+    .SetParent<LteRadioBearerInfo> ()
+    .AddConstructor<LteSignalingRadioBearerInfo> ()
+    .AddAttribute ("SrbIdentity", "The id of this Signaling Radio Bearer",
+                   TypeId::ATTR_GET, // allow only getting it.
+                   UintegerValue (0), // unused (attribute is read-only
+                   MakeUintegerAccessor (&LteSignalingRadioBearerInfo::m_srbIdentity),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("LteRlc", "RLC instance of the radio bearer.",
+                   PointerValue (),
+                   MakePointerAccessor (&LteRadioBearerInfo::m_rlc),
+                   MakePointerChecker<LteRlc> ())
+    .AddAttribute ("LtePdcp", "PDCP instance of the radio bearer.",
+                   PointerValue (),
+                   MakePointerAccessor (&LteRadioBearerInfo::m_pdcp),
+                   MakePointerChecker<LtePdcp> ())
+    ;
   return tid;
 }
 
 
 
-
 } // namespace ns3
--- a/src/lte/model/lte-radio-bearer-info.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-info.h	Tue Oct 30 16:02:07 2012 +0100
@@ -24,6 +24,7 @@
 #include <ns3/object.h>
 #include <ns3/pointer.h>
 #include <ns3/eps-bearer.h>
+#include <ns3/lte-rrc-sap.h>
 
 namespace ns3 {
 
@@ -44,11 +45,46 @@
 
   Ptr<LteRlc> m_rlc;
   Ptr<LtePdcp> m_pdcp;  
+};
+
+
+/**
+ * store information on active signaling radio bearer instance
+ * 
+ */
+class LteSignalingRadioBearerInfo : public LteRadioBearerInfo
+{
+
+public:
+  static TypeId GetTypeId (void);
+
+  uint8_t m_srbIdentity;   
+  LteRrcSap::LogicalChannelConfig m_logicalChannelConfig;  
+};
+
+
+/**
+ * store information on active data radio bearer instance
+ * 
+ */
+class LteDataRadioBearerInfo : public LteRadioBearerInfo
+{
+
+public:
+  static TypeId GetTypeId (void);
+
   EpsBearer m_epsBearer;
-  uint32_t m_teid;
+  uint8_t m_epsBearerIdentity;
+  uint8_t m_drbIdentity;
+  LteRrcSap::RlcConfig m_rlcConfig;
+  uint8_t m_logicalChannelIdentity;
+  LteRrcSap::LogicalChannelConfig m_logicalChannelConfig;
 };
 
 
+
+
+
 } // namespace ns3
 
 
--- a/src/lte/model/lte-radio-bearer-tag.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-tag.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -33,11 +33,11 @@
   static TypeId tid = TypeId ("ns3::LteRadioBearerTag")
     .SetParent<Tag> ()
     .AddConstructor<LteRadioBearerTag> ()
-    .AddAttribute ("rnti", "The rnti that indicates the UE which packet belongs",
+    .AddAttribute ("rnti", "The rnti that indicates the UE to which packet belongs",
                    UintegerValue (0),
                    MakeUintegerAccessor (&LteRadioBearerTag::GetRnti),
                    MakeUintegerChecker<uint16_t> ())
-    .AddAttribute ("lcid", "The LC id that indicates the UE which packet belongs",
+    .AddAttribute ("lcid", "The id whithin the UE identifying the logical channel to which the packet belongs",
                    UintegerValue (0),
                    MakeUintegerAccessor (&LteRadioBearerTag::GetLcid),
                    MakeUintegerChecker<uint8_t> ())
--- a/src/lte/model/lte-rlc-am.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-rlc-am.h	Tue Oct 30 16:02:07 2012 +0100
@@ -21,9 +21,9 @@
 #ifndef LTE_RLC_AM_H
 #define LTE_RLC_AM_H
 
-#include "ns3/lte-rlc-sequence-number.h"
-
-#include "ns3/lte-rlc.h"
+#include <ns3/event-id.h>
+#include <ns3/lte-rlc-sequence-number.h>
+#include <ns3/lte-rlc.h>
 
 #include <vector>
 #include <map>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rlc-tm.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,231 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Manuel Requena <manuel.requena@cttc.es>
+ *         Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+
+#include "ns3/lte-rlc-tm.h"
+#include "ns3/lte-rlc-tag.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteRlcTm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteRlcTm);
+
+LteRlcTm::LteRlcTm ()
+  : m_maxTxBufferSize (0),
+    m_txBufferSize (0)
+{
+  NS_LOG_FUNCTION (this);
+
+  Simulator::ScheduleNow (&LteRlcTm::Start, this);
+}
+
+LteRlcTm::~LteRlcTm ()
+{
+}
+
+TypeId
+LteRlcTm::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LteRlcTm")
+    .SetParent<LteRlc> ()
+    .AddConstructor<LteRlcTm> ()
+    .AddAttribute ("MaxTxBufferSize",
+                   "Maximum Size of the Transmission Buffer (in Bytes)",
+                   UintegerValue (2 * 1024 * 1024),
+                   MakeUintegerAccessor (&LteRlcTm::m_maxTxBufferSize),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+
+/**
+ * RLC SAP
+ */
+
+void
+LteRlcTm::DoTransmitPdcpPdu (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
+
+  if (m_txBufferSize + p->GetSize () <= m_maxTxBufferSize)
+    {
+      /** Store arrival time */
+      RlcTag timeTag (Simulator::Now ());
+      p->AddPacketTag (timeTag);
+
+      NS_LOG_LOGIC ("Tx Buffer: New packet added");
+      m_txBuffer.push_back (p);
+      m_txBufferSize += p->GetSize ();
+      NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
+      NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
+    }
+  else
+    {
+      // Discard full RLC SDU
+      NS_LOG_LOGIC ("TxBuffer is full. RLC SDU discarded");
+      NS_LOG_LOGIC ("MaxTxBufferSize = " << m_maxTxBufferSize);
+      NS_LOG_LOGIC ("txBufferSize    = " << m_txBufferSize);
+      NS_LOG_LOGIC ("packet size     = " << p->GetSize ());
+    }
+
+  /** Report Buffer Status */
+  DoReportBufferStatus ();
+  m_rbsTimer.Cancel ();
+}
+
+
+/**
+ * MAC SAP
+ */
+
+void
+LteRlcTm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer)
+{
+  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes);
+
+  // 5.1.1.1 Transmit operations 
+  // 5.1.1.1.1 General
+  // When submitting a new TMD PDU to lower layer, the transmitting TM RLC entity shall:
+  // - submit a RLC SDU without any modification to lower layer.
+
+
+  if ( m_txBuffer.size () == 0 )
+    {
+      NS_LOG_LOGIC ("No data pending");
+      return;
+    }
+
+  Ptr<Packet> packet = (*(m_txBuffer.begin ()))->Copy ();
+
+  if (bytes < packet->GetSize ())
+    {
+      // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
+      NS_LOG_WARN ("TX opportunity too small = " << bytes << " (PDU size: " << packet->GetSize () << ")");
+      return;
+    }
+
+  m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
+  m_txBuffer.erase (m_txBuffer.begin ());
+ 
+  // Sender timestamp
+  RlcTag rlcTag (Simulator::Now ());
+  packet->AddByteTag (rlcTag);
+  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
+
+  // Send RLC PDU to MAC layer
+  LteMacSapProvider::TransmitPduParameters params;
+  params.pdu = packet;
+  params.rnti = m_rnti;
+  params.lcid = m_lcid;
+  params.layer = layer;
+
+  m_macSapProvider->TransmitPdu (params);
+
+  if (! m_txBuffer.empty ())
+    {
+      m_rbsTimer.Cancel ();
+      m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcTm::ExpireRbsTimer, this);
+    }
+}
+
+void
+LteRlcTm::DoNotifyHarqDeliveryFailure ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteRlcTm::DoReceivePdu (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
+
+  // Receiver timestamp
+  RlcTag rlcTag;
+  Time delay;
+  if (p->FindFirstMatchingByteTag (rlcTag))
+    {
+      delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
+    }
+  m_rxPdu (m_rnti, m_lcid, p->GetSize (), delay.GetNanoSeconds ());
+
+  // 5.1.1.2 Receive operations 
+  // 5.1.1.2.1  General
+  // When receiving a new TMD PDU from lower layer, the receiving TM RLC entity shall:
+  // - deliver the TMD PDU without any modification to upper layer.
+
+   m_rlcSapUser->ReceivePdcpPdu (p);
+}
+
+
+void
+LteRlcTm::Start ()
+{
+  NS_LOG_FUNCTION (this);
+
+  DoReportBufferStatus ();
+}
+
+
+void
+LteRlcTm::DoReportBufferStatus (void)
+{
+  Time holDelay (0);
+  uint32_t queueSize = 0;
+
+  if (! m_txBuffer.empty ())
+    {
+      RlcTag holTimeTag;
+      m_txBuffer.front ()->PeekPacketTag (holTimeTag);
+      holDelay = Simulator::Now () - holTimeTag.GetSenderTimestamp ();
+
+      queueSize = m_txBufferSize; // just data in tx queue (no header overhead for RLC TM)
+    }
+
+  LteMacSapProvider::ReportBufferStatusParameters r;
+  r.rnti = m_rnti;
+  r.lcid = m_lcid;
+  r.txQueueSize = queueSize;
+  r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
+  r.retxQueueSize = 0;
+  r.retxQueueHolDelay = 0;
+  r.statusPduSize = 0;
+
+  NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
+  m_macSapProvider->ReportBufferStatus (r);
+}
+
+void
+LteRlcTm::ExpireRbsTimer (void)
+{
+  NS_LOG_LOGIC ("RBS Timer expires");
+
+  if (! m_txBuffer.empty ())
+    {
+      DoReportBufferStatus ();
+      m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcTm::ExpireRbsTimer, this);
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rlc-tm.h	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,72 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Manuel Requena <manuel.requena@cttc.es> 
+ *         Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#ifndef LTE_RLC_TM_H
+#define LTE_RLC_TM_H
+
+#include "ns3/lte-rlc.h"
+
+#include <ns3/event-id.h>
+#include <map>
+
+namespace ns3 {
+
+/**
+ * LTE RLC Transparent Mode (TM), see 3GPP TS 36.322
+ */
+class LteRlcTm : public LteRlc
+{
+public:
+  LteRlcTm ();
+  virtual ~LteRlcTm ();
+  static TypeId GetTypeId (void);
+
+  /**
+   * RLC SAP
+   */
+  virtual void DoTransmitPdcpPdu (Ptr<Packet> p);
+
+  /**
+   * MAC SAP
+   */
+  virtual void DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer);
+  virtual void DoNotifyHarqDeliveryFailure ();
+  virtual void DoReceivePdu (Ptr<Packet> p);
+
+  void Start ();
+
+private:
+  void ExpireRbsTimer (void);
+  void DoReportBufferStatus ();
+
+private:
+  uint32_t m_maxTxBufferSize;
+  uint32_t m_txBufferSize;
+  std::vector < Ptr<Packet> > m_txBuffer;       // Transmission buffer
+
+  EventId m_rbsTimer;
+
+};
+
+
+} // namespace ns3
+
+#endif // LTE_RLC_TM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rrc-protocol-ideal.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,687 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include <ns3/fatal-error.h>
+#include <ns3/log.h>
+#include <ns3/nstime.h>
+#include <ns3/node-list.h>
+#include <ns3/node.h>
+#include <ns3/simulator.h>
+
+#include "lte-rrc-protocol-ideal.h"
+#include "lte-ue-rrc.h"
+#include "lte-enb-rrc.h"
+#include "lte-enb-net-device.h"
+#include "lte-ue-net-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteRrcProtocolIdeal");
+
+
+namespace ns3 {
+
+
+const Time RRC_IDEAL_MSG_DELAY = MilliSeconds (0); 
+
+NS_OBJECT_ENSURE_REGISTERED (LteUeRrcProtocolIdeal);
+
+LteUeRrcProtocolIdeal::LteUeRrcProtocolIdeal ()
+  :  m_ueRrcSapProvider (0),
+     m_enbRrcSapProvider (0)
+{
+  m_ueRrcSapUser = new MemberLteUeRrcSapUser<LteUeRrcProtocolIdeal> (this);
+}
+
+LteUeRrcProtocolIdeal::~LteUeRrcProtocolIdeal ()
+{
+}
+
+void
+LteUeRrcProtocolIdeal::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_ueRrcSapUser;
+  m_rrc = 0;
+}
+
+TypeId
+LteUeRrcProtocolIdeal::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LteUeRrcProtocolIdeal")
+    .SetParent<Object> ()
+    .AddConstructor<LteUeRrcProtocolIdeal> ()
+    ;
+  return tid;
+}
+
+void 
+LteUeRrcProtocolIdeal::SetLteUeRrcSapProvider (LteUeRrcSapProvider* p)
+{
+  m_ueRrcSapProvider = p;
+}
+
+LteUeRrcSapUser* 
+LteUeRrcProtocolIdeal::GetLteUeRrcSapUser ()
+{
+  return m_ueRrcSapUser;
+}
+
+void 
+LteUeRrcProtocolIdeal::SetUeRrc (Ptr<LteUeRrc> rrc)
+{
+  m_rrc = rrc;
+}
+
+void 
+LteUeRrcProtocolIdeal::DoSetup (LteUeRrcSapUser::SetupParameters params)
+{
+  NS_LOG_FUNCTION (this);
+  // Trick: we use this as a trigger to initialize the RNTI and cellID,
+  // and to make sure we are talking to the appropriate eNB (e.g.,
+  // after handover). We don't care about SRB0/SRB1 since we use ideal
+  // RRC messages.
+  DoReestablish ();
+}
+
+void 
+LteUeRrcProtocolIdeal::DoReestablish ()
+{
+  NS_LOG_FUNCTION (this);
+  // // initialize the RNTI and get the EnbLteRrcSapProvider for the
+  // // eNB we are currently attached to
+  // m_rnti = m_rrc->GetRnti ();
+  // SetEnbRrcSapProvider ();
+  
+
+  // if (m_havePendingRrcConnectionRequest == true)
+  //   {      
+  //     Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+  //                          &LteEnbRrcSapProvider::RecvRrcConnectionRequest,
+  //                          m_enbRrcSapProvider,
+  //                          m_rnti, 
+  //                          m_pendingRrcConnectionRequest);
+  //   }
+}
+
+void 
+LteUeRrcProtocolIdeal::DoSendRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg)
+{
+  // initialize the RNTI and get the EnbLteRrcSapProvider for the
+  // eNB we are currently attached to
+  m_rnti = m_rrc->GetRnti ();
+  SetEnbRrcSapProvider ();
+    
+  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+                       &LteEnbRrcSapProvider::RecvRrcConnectionRequest,
+                       m_enbRrcSapProvider,
+                       m_rnti, 
+                       msg);
+}
+
+void 
+LteUeRrcProtocolIdeal::DoSendRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg)
+{
+  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteEnbRrcSapProvider::RecvRrcConnectionSetupCompleted,
+                       m_enbRrcSapProvider,
+		       m_rnti, 
+		       msg);
+}
+
+void 
+LteUeRrcProtocolIdeal::DoSendRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg)
+{
+  // re-initialize the RNTI and get the EnbLteRrcSapProvider for the
+  // eNB we are currently attached to
+  m_rnti = m_rrc->GetRnti ();
+  SetEnbRrcSapProvider ();
+    
+   Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+                        &LteEnbRrcSapProvider::RecvRrcConnectionReconfigurationCompleted,
+                        m_enbRrcSapProvider,
+                        m_rnti, 
+                        msg);
+}
+
+void 
+LteUeRrcProtocolIdeal::DoSendRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg)
+{
+   Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentRequest,
+                       m_enbRrcSapProvider,
+		       m_rnti, 
+                        msg);
+}
+
+void 
+LteUeRrcProtocolIdeal::DoSendRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg)
+{
+   Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentComplete,
+                       m_enbRrcSapProvider,
+		       m_rnti, 
+msg);
+}
+
+
+void 
+LteUeRrcProtocolIdeal::SetEnbRrcSapProvider ()
+{
+  uint16_t cellId = m_rrc->GetCellId ();  
+
+  // walk list of all nodes to get the peer eNB
+  Ptr<LteEnbNetDevice> enbDev;
+  NodeList::Iterator listEnd = NodeList::End ();
+  bool found = false;
+  for (NodeList::Iterator i = NodeList::Begin (); 
+       (i != listEnd) && (!found); 
+       ++i)
+    {
+      Ptr<Node> node = *i;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; 
+           (j < nDevs) && (!found);
+           j++)
+        {
+          enbDev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
+          if (enbDev == 0)
+            {
+              continue;
+            }
+          else
+            {
+              if (enbDev->GetCellId () == cellId)
+                {
+                  found = true;          
+                  break;
+                }
+            }
+        }
+    }
+  NS_ASSERT_MSG (found, " Unable to find eNB with CellId =" << cellId);
+  m_enbRrcSapProvider = enbDev->GetRrc ()->GetLteEnbRrcSapProvider ();  
+  Ptr<LteEnbRrcProtocolIdeal> enbRrcProtocolIdeal = enbDev->GetRrc ()->GetObject<LteEnbRrcProtocolIdeal> ();
+  enbRrcProtocolIdeal->SetUeRrcSapProvider (m_rnti, m_ueRrcSapProvider);
+}
+
+
+NS_OBJECT_ENSURE_REGISTERED (LteEnbRrcProtocolIdeal);
+
+LteEnbRrcProtocolIdeal::LteEnbRrcProtocolIdeal ()
+  :  m_enbRrcSapProvider (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_enbRrcSapUser = new MemberLteEnbRrcSapUser<LteEnbRrcProtocolIdeal> (this);
+}
+
+LteEnbRrcProtocolIdeal::~LteEnbRrcProtocolIdeal ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+LteEnbRrcProtocolIdeal::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_enbRrcSapUser;  
+}
+
+TypeId
+LteEnbRrcProtocolIdeal::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LteEnbRrcProtocolIdeal")
+    .SetParent<Object> ()
+    .AddConstructor<LteEnbRrcProtocolIdeal> ()
+    ;
+  return tid;
+}
+
+void 
+LteEnbRrcProtocolIdeal::SetLteEnbRrcSapProvider (LteEnbRrcSapProvider* p)
+{
+  m_enbRrcSapProvider = p;
+}
+
+LteEnbRrcSapUser* 
+LteEnbRrcProtocolIdeal::GetLteEnbRrcSapUser ()
+{
+  return m_enbRrcSapUser;
+}
+
+void 
+LteEnbRrcProtocolIdeal::SetCellId (uint16_t cellId)
+{
+  m_cellId = cellId;
+}
+
+LteUeRrcSapProvider* 
+LteEnbRrcProtocolIdeal::GetUeRrcSapProvider (uint16_t rnti)
+{
+  std::map<uint16_t, LteUeRrcSapProvider*>::const_iterator it;
+  it = m_enbRrcSapProviderMap.find (rnti);
+  NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "could not find RNTI = " << rnti);
+  return it->second;
+}
+
+void 
+LteEnbRrcProtocolIdeal::SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider* p)
+{
+  std::map<uint16_t, LteUeRrcSapProvider*>::iterator it;
+  it = m_enbRrcSapProviderMap.find (rnti);
+  NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "could not find RNTI = " << rnti);
+  it->second = p;
+}
+
+void 
+LteEnbRrcProtocolIdeal::DoSetupUe (uint16_t rnti, LteEnbRrcSapUser::SetupUeParameters params)
+{
+  NS_LOG_FUNCTION (this << rnti);
+
+  // // walk list of all nodes to get the peer UE RRC SAP Provider
+  // Ptr<LteUeRrc> ueRrc;
+  // NodeList::Iterator listEnd = NodeList::End ();
+  // bool found = false;
+  // for (NodeList::Iterator i = NodeList::Begin (); (i != listEnd) && (found == false); 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)
+  //           {
+  //             continue;
+  //           }
+  //         else
+  //           {
+  //             ueRrc = ueDev->GetRrc ();
+  //             if ((ueRrc->GetRnti () == rnti) && (ueRrc->GetCellId () == m_cellId))
+  //               {                 
+  //       	  found = true;
+  //       	  break;
+  //               }
+  //           }
+  //       }
+  //   }
+  // NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId);
+  // m_enbRrcSapProviderMap[rnti] = ueRrc->GetLteUeRrcSapProvider ();
+
+
+  // just create empty entry, the UeRrcSapProvider will be set by the
+  // ue upon connection request or connection reconfiguration
+  // completed 
+  m_enbRrcSapProviderMap[rnti] = 0;
+
+}
+
+void 
+LteEnbRrcProtocolIdeal::DoRemoveUe (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  m_enbRrcSapProviderMap.erase (rnti);
+}
+
+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);
+  // 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)
+            {
+              Ptr<LteUeRrc> ueRrc = ueDev->GetRrc ();              
+              NS_LOG_LOGIC ("considering UE IMSI " << ueDev->GetImsi () << " that has cellId " << ueRrc->GetCellId ());
+              if (ueRrc->GetCellId () == m_cellId)
+                {       
+                  NS_LOG_LOGIC ("sending SI to IMSI " << ueDev->GetImsi ());
+                  ueRrc->GetLteUeRrcSapProvider ()->RecvSystemInformation (msg);
+                  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+                                       &LteUeRrcSapProvider::RecvSystemInformation,
+                                       ueRrc->GetLteUeRrcSapProvider (), 
+                                       msg);          
+                }             
+            }
+        }
+    } 
+}
+
+void 
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionSetup (uint16_t rnti, LteRrcSap::RrcConnectionSetup msg)
+{
+  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteUeRrcSapProvider::RecvRrcConnectionSetup,
+		       GetUeRrcSapProvider (rnti), 
+		       msg);
+}
+
+void 
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionReconfiguration (uint16_t rnti, LteRrcSap::RrcConnectionReconfiguration msg)
+{
+  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteUeRrcSapProvider::RecvRrcConnectionReconfiguration,
+		       GetUeRrcSapProvider (rnti), 
+		       msg);
+}
+
+void 
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionReestablishment (uint16_t rnti, LteRrcSap::RrcConnectionReestablishment msg)
+{
+  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteUeRrcSapProvider::RecvRrcConnectionReestablishment,
+		       GetUeRrcSapProvider (rnti), 
+		       msg);
+}
+
+void 
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionReestablishmentReject (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentReject msg)
+{
+  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteUeRrcSapProvider::RecvRrcConnectionReestablishmentReject,
+		       GetUeRrcSapProvider (rnti), 
+		       msg);
+}
+
+void 
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionRelease (uint16_t rnti, LteRrcSap::RrcConnectionRelease msg)
+{
+  Simulator::Schedule (RRC_IDEAL_MSG_DELAY, 
+		       &LteUeRrcSapProvider::RecvRrcConnectionRelease,
+		       GetUeRrcSapProvider (rnti), 
+		       msg);
+}
+
+
+/*
+ * The purpose of LteEnbRrcProtocolIdeal is to avoid encoding
+ * messages. In order to do so, we need to have some form of encoding for
+ * inter-node RRC messages like HandoverPreparationInfo and HandoverCommand. Doing so
+ * directly is not practical (these messages includes a lot of
+ * information elements, so encoding all of them would defeat the
+ * purpose of LteEnbRrcProtocolIdeal. The workaround is to store the
+ * actual message in a global map, so that then we can just encode the
+ * key in a header and send that between eNBs over X2.
+ * 
+ */
+
+std::map<uint32_t, LteRrcSap::HandoverPreparationInfo> g_handoverPreparationInfoMsgMap;
+uint32_t g_handoverPreparationInfoMsgIdCounter = 0;
+
+/*
+ * This header encodes the map key discussed above. We keep this
+ * private since it should not be used outside this file.
+ * 
+ */
+class IdealHandoverPreparationInfoHeader : public Header
+{
+public:
+  uint32_t GetMsgId ();
+  void SetMsgId (uint32_t id);
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+  uint32_t m_msgId;
+};
+
+uint32_t 
+IdealHandoverPreparationInfoHeader::GetMsgId ()
+{
+  return m_msgId;
+}  
+
+void 
+IdealHandoverPreparationInfoHeader::SetMsgId (uint32_t id)
+{
+  m_msgId = id;
+}  
+
+
+TypeId
+IdealHandoverPreparationInfoHeader::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IdealHandoverPreparationInfoHeader")
+    .SetParent<Header> ()
+    .AddConstructor<IdealHandoverPreparationInfoHeader> ()
+  ;
+  return tid;
+}
+
+TypeId
+IdealHandoverPreparationInfoHeader::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void IdealHandoverPreparationInfoHeader::Print (std::ostream &os)  const
+{
+  os << " msgId=" << m_msgId;
+}
+
+uint32_t IdealHandoverPreparationInfoHeader::GetSerializedSize (void) const
+{
+  return 4;
+}
+
+void IdealHandoverPreparationInfoHeader::Serialize (Buffer::Iterator start) const
+{  
+  start.WriteU32 (m_msgId);
+}
+
+uint32_t IdealHandoverPreparationInfoHeader::Deserialize (Buffer::Iterator start)
+{
+  m_msgId = start.ReadU32 ();
+  return GetSerializedSize ();
+}
+
+
+
+Ptr<Packet> 
+LteEnbRrcProtocolIdeal::DoEncodeHandoverPreparationInformation (LteRrcSap::HandoverPreparationInfo msg)
+{
+  uint32_t msgId = ++g_handoverPreparationInfoMsgIdCounter;
+  NS_ASSERT_MSG (g_handoverPreparationInfoMsgMap.find (msgId) == g_handoverPreparationInfoMsgMap.end (), "msgId " << msgId << " already in use");
+  NS_LOG_INFO (" encoding msgId = " << msgId);
+  g_handoverPreparationInfoMsgMap.insert (std::pair<uint32_t, LteRrcSap::HandoverPreparationInfo> (msgId, msg));
+  IdealHandoverPreparationInfoHeader h;
+  h.SetMsgId (msgId);
+  Ptr<Packet> p = Create<Packet> ();
+  p->AddHeader (h);
+  return p;
+}
+
+LteRrcSap::HandoverPreparationInfo 
+LteEnbRrcProtocolIdeal::DoDecodeHandoverPreparationInformation (Ptr<Packet> p)
+{
+  IdealHandoverPreparationInfoHeader h;
+  p->RemoveHeader (h);
+  uint32_t msgId = h.GetMsgId ();
+  NS_LOG_INFO (" decoding msgId = " << msgId);
+  std::map<uint32_t, LteRrcSap::HandoverPreparationInfo>::iterator it = g_handoverPreparationInfoMsgMap.find (msgId);
+  NS_ASSERT_MSG (it != g_handoverPreparationInfoMsgMap.end (), "msgId " << msgId << " not found");
+  LteRrcSap::HandoverPreparationInfo msg = it->second;
+  g_handoverPreparationInfoMsgMap.erase (it);
+  return msg;
+}
+
+
+
+std::map<uint32_t, LteRrcSap::RrcConnectionReconfiguration> g_handoverCommandMsgMap;
+uint32_t g_handoverCommandMsgIdCounter = 0;
+
+/*
+ * This header encodes the map key discussed above. We keep this
+ * private since it should not be used outside this file.
+ * 
+ */
+class IdealHandoverCommandHeader : public Header
+{
+public:
+  uint32_t GetMsgId ();
+  void SetMsgId (uint32_t id);
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+  uint32_t m_msgId;
+};
+
+uint32_t 
+IdealHandoverCommandHeader::GetMsgId ()
+{
+  return m_msgId;
+}  
+
+void 
+IdealHandoverCommandHeader::SetMsgId (uint32_t id)
+{
+  m_msgId = id;
+}  
+
+
+TypeId
+IdealHandoverCommandHeader::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IdealHandoverCommandHeader")
+    .SetParent<Header> ()
+    .AddConstructor<IdealHandoverCommandHeader> ()
+  ;
+  return tid;
+}
+
+TypeId
+IdealHandoverCommandHeader::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void IdealHandoverCommandHeader::Print (std::ostream &os)  const
+{
+  os << " msgId=" << m_msgId;
+}
+
+uint32_t IdealHandoverCommandHeader::GetSerializedSize (void) const
+{
+  return 4;
+}
+
+void IdealHandoverCommandHeader::Serialize (Buffer::Iterator start) const
+{  
+  start.WriteU32 (m_msgId);
+}
+
+uint32_t IdealHandoverCommandHeader::Deserialize (Buffer::Iterator start)
+{
+  m_msgId = start.ReadU32 ();
+  return GetSerializedSize ();
+}
+
+
+
+Ptr<Packet> 
+LteEnbRrcProtocolIdeal::DoEncodeHandoverCommand (LteRrcSap::RrcConnectionReconfiguration msg)
+{
+  uint32_t msgId = ++g_handoverCommandMsgIdCounter;
+  NS_ASSERT_MSG (g_handoverCommandMsgMap.find (msgId) == g_handoverCommandMsgMap.end (), "msgId " << msgId << " already in use");
+  NS_LOG_INFO (" encoding msgId = " << msgId);
+  g_handoverCommandMsgMap.insert (std::pair<uint32_t, LteRrcSap::RrcConnectionReconfiguration> (msgId, msg));
+  IdealHandoverCommandHeader h;
+  h.SetMsgId (msgId);
+  Ptr<Packet> p = Create<Packet> ();
+  p->AddHeader (h);
+  return p;
+}
+
+LteRrcSap::RrcConnectionReconfiguration
+LteEnbRrcProtocolIdeal::DoDecodeHandoverCommand (Ptr<Packet> p)
+{
+  IdealHandoverCommandHeader h;
+  p->RemoveHeader (h);
+  uint32_t msgId = h.GetMsgId ();
+  NS_LOG_INFO (" decoding msgId = " << msgId);
+  std::map<uint32_t, LteRrcSap::RrcConnectionReconfiguration>::iterator it = g_handoverCommandMsgMap.find (msgId);
+  NS_ASSERT_MSG (it != g_handoverCommandMsgMap.end (), "msgId " << msgId << " not found");
+  LteRrcSap::RrcConnectionReconfiguration msg = it->second;
+  g_handoverCommandMsgMap.erase (it);
+  return msg;
+}
+
+
+
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rrc-protocol-ideal.h	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,147 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+#ifndef LTE_RRC_PROTOCOL_IDEAL_H
+#define LTE_RRC_PROTOCOL_IDEAL_H
+
+#include <stdint.h>
+#include <map>
+
+#include <ns3/ptr.h>
+#include <ns3/object.h>
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+class LteUeRrcSapProvider;
+class LteUeRrcSapUser;
+class LteEnbRrcSapProvider;
+class LteUeRrc;
+
+
+/**
+ * Models the transmission of RRC messages from the UE to the eNB in
+ * an ideal fashion, without errors and without consuming any radio
+ * resources. 
+ * 
+ */
+class LteUeRrcProtocolIdeal : public Object
+{
+  friend class MemberLteUeRrcSapUser<LteUeRrcProtocolIdeal>;
+
+public:
+
+  LteUeRrcProtocolIdeal ();
+  virtual ~LteUeRrcProtocolIdeal ();
+
+  // inherited from Object
+  virtual void DoDispose (void);
+  static TypeId GetTypeId (void);
+
+  void SetLteUeRrcSapProvider (LteUeRrcSapProvider* p);
+  LteUeRrcSapUser* GetLteUeRrcSapUser ();
+  
+  void SetUeRrc (Ptr<LteUeRrc> rrc);
+  
+
+private:
+
+  // methods forwarded from LteUeRrcSapUser
+  void DoSetup (LteUeRrcSapUser::SetupParameters params);
+  void DoReestablish ();
+  void DoSendRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg);
+  void DoSendRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg);
+  void DoSendRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg);
+  void DoSendRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg);
+  void DoSendRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg);
+
+  void SetEnbRrcSapProvider ();
+
+  Ptr<LteUeRrc> m_rrc;
+  uint16_t m_rnti;
+  LteUeRrcSapProvider* m_ueRrcSapProvider;
+  LteUeRrcSapUser* m_ueRrcSapUser;
+  LteEnbRrcSapProvider* m_enbRrcSapProvider;
+  
+};
+
+
+/**
+ * Models the transmission of RRC messages from the UE to the eNB in
+ * an ideal fashion, without errors and without consuming any radio
+ * resources. 
+ * 
+ */
+class LteEnbRrcProtocolIdeal : public Object
+{
+  friend class MemberLteEnbRrcSapUser<LteEnbRrcProtocolIdeal>;
+
+public:
+
+  LteEnbRrcProtocolIdeal ();
+  virtual ~LteEnbRrcProtocolIdeal ();
+
+  // inherited from Object
+  virtual void DoDispose (void);
+  static TypeId GetTypeId (void);
+
+  void SetLteEnbRrcSapProvider (LteEnbRrcSapProvider* p);
+  LteEnbRrcSapUser* GetLteEnbRrcSapUser ();
+
+  void SetCellId (uint16_t cellId);
+
+  LteUeRrcSapProvider* GetUeRrcSapProvider (uint16_t rnti);
+  void SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider* p);
+
+private:
+
+  // 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);
+  void DoSendRrcConnectionReconfiguration (uint16_t rnti, LteRrcSap::RrcConnectionReconfiguration msg);
+  void DoSendRrcConnectionReestablishment (uint16_t rnti, LteRrcSap::RrcConnectionReestablishment msg);
+  void DoSendRrcConnectionReestablishmentReject (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentReject msg);
+  void DoSendRrcConnectionRelease (uint16_t rnti, LteRrcSap::RrcConnectionRelease msg);
+  Ptr<Packet> DoEncodeHandoverPreparationInformation (LteRrcSap::HandoverPreparationInfo msg);
+  LteRrcSap::HandoverPreparationInfo DoDecodeHandoverPreparationInformation (Ptr<Packet> p);
+  Ptr<Packet> DoEncodeHandoverCommand (LteRrcSap::RrcConnectionReconfiguration msg);
+  LteRrcSap::RrcConnectionReconfiguration DoDecodeHandoverCommand (Ptr<Packet> p);
+
+
+  uint16_t m_rnti;
+  uint16_t m_cellId;
+  LteEnbRrcSapProvider* m_enbRrcSapProvider;
+  LteEnbRrcSapUser* m_enbRrcSapUser;
+  std::map<uint16_t, LteUeRrcSapProvider*> m_enbRrcSapProviderMap;
+  
+};
+
+
+
+}
+
+
+#endif // LTE_RRC_PROTOCOL_IDEAL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rrc-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,848 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+#ifndef LTE_RRC_SAP_H
+#define LTE_RRC_SAP_H
+
+#include <stdint.h>
+#include <list>
+
+#include <ns3/ptr.h>
+
+namespace ns3 {
+
+
+class LteRlcSapUser;
+class LtePdcpSapUser;
+class LteRlcSapProvider;
+class LtePdcpSapProvider;
+class Packet;  
+
+/**
+ * Class holding definition common to all Ue/Enb SAP
+ * Users/Providers. See 3GPP TS 36.331 for reference. 
+ * Note that only those values that are (expected to be) used by the
+ * ns-3 model are mentioned here. The naming of the variables that are
+ * defined here is the same of 36.331, except for removal of "-" and
+ * conversion to CamelCase or ALL_CAPS where needed in order to follow
+ * the ns-3 coding style. Due to the 1-to-1 mapping with TS 36.311, 
+ * detailed doxygen documentation is omitted, so please refer to
+ * 36.311 for the meaning of these data structures / fields.
+ * 
+ */
+class LteRrcSap
+{
+public:
+
+  // Information Elements
+  
+  struct PlmnIdentityInfo
+  {
+    uint32_t plmnIdentity;
+  };
+
+  struct CellAccessRelatedInfo
+  {
+    PlmnIdentityInfo plmnIdentityInfo;
+    uint32_t cellIdentity;
+    bool csgIndication;
+    uint32_t csgIdentity;
+  };
+  
+  struct FreqInfo
+  {
+    uint16_t ulCarrierFreq;
+    uint8_t ulBandwidth;
+  };
+
+  struct RlcConfig
+  {
+    enum
+      {
+        AM, 
+        UM_BI_DIRECTIONAL,
+        UM_UNI_DIRECTIONAL_UL,
+        UM_UNI_DIRECTIONAL_DL
+      } choice;    
+  };
+
+  struct LogicalChannelConfig
+  {
+    uint8_t priority;
+    uint16_t prioritizedBitRateKbps;
+    uint16_t bucketSizeDurationMs;
+    uint8_t logicalChannelGroup;
+  };
+
+  struct SoundingRsUlConfigCommon
+  {
+    enum {SETUP, RESET} type;
+    uint8_t srsBandwidthConfig;
+    uint8_t srsSubframeConfig;
+  };
+
+  struct SoundingRsUlConfigDedicated
+  {
+    enum {SETUP, RESET} type;
+    uint8_t srsBandwidth;
+    uint8_t srsConfigIndex;
+  };
+
+  struct AntennaInfoDedicated
+  {
+    uint8_t transmissionMode;
+  };
+
+
+  struct PhysicalConfigDedicated
+  {
+    bool haveSoundingRsUlConfigDedicated;
+    SoundingRsUlConfigDedicated soundingRsUlConfigDedicated;
+    bool haveAntennaInfoDedicated;
+    AntennaInfoDedicated antennaInfo;
+  };
+
+
+  struct SrbToAddMod
+  {
+    uint8_t srbIdentity;   
+    LogicalChannelConfig logicalChannelConfig;
+  };
+  
+  struct DrbToAddMod
+  {
+    uint8_t epsBearerIdentity;
+    uint8_t drbIdentity;
+    RlcConfig rlcConfig;
+    uint8_t logicalChannelIdentity;
+    LogicalChannelConfig logicalChannelConfig;
+  };
+
+  struct RadioResourceConfigCommon
+  {    
+  };
+
+  struct RadioResourceConfigCommonSib
+  {    
+  };
+
+  struct RadioResourceConfigDedicated
+  {
+    std::list<SrbToAddMod> srbToAddModList;
+    std::list<DrbToAddMod> drbToAddModList;    
+    std::list<uint8_t> drbToReleaseList;
+    bool havePhysicalConfigDedicated;
+    PhysicalConfigDedicated physicalConfigDedicated;
+  };
+
+  struct MeasConfig
+  {
+
+  };
+
+  struct CarrierFreqEutra
+  {
+    uint16_t dlCarrierFreq;
+    uint16_t ulCarrierFreq;
+  };
+
+  struct CarrierBandwidthEutra
+  {
+    uint8_t dlBandwidth;
+    uint8_t ulBandwidth;
+  };
+
+  struct RachConfigDedicated 
+  {
+    uint8_t raPreambleIndex;
+    uint8_t raPrachMaskIndex;
+  };
+
+  struct MobilityControlInfo
+  {
+    uint16_t targetPhysCellId;
+    bool haveCarrierFreq;
+    CarrierFreqEutra carrierFreq;    
+    bool haveCarrierBandwidth;
+    CarrierBandwidthEutra carrierBandwidth;   
+    uint16_t newUeIdentity;
+    RadioResourceConfigCommon radioResourceConfigCommon;
+    bool haveRachConfigDedicated;
+    RachConfigDedicated rachConfigDedicated;
+  };
+
+  struct ReestabUeIdentity
+  {
+    uint16_t cRnti;
+    uint16_t physCellId;    
+  };
+
+  enum ReestablishmentCause 
+    { 
+      RECONFIGURATION_FAILURE,
+      HANDOVER_FAILURE,
+      OTHER_FAILURE
+    };
+
+  struct MasterInformationBlock
+  {
+    uint8_t dlBandwidth;
+    uint8_t systemFrameNumber;
+  };
+  
+  struct SystemInformationBlockType1
+  {
+    CellAccessRelatedInfo cellAccessRelatedInfo;
+  };
+
+  struct SystemInformationBlockType2
+  {
+    RadioResourceConfigCommonSib radioResourceConfigCommon;
+    FreqInfo freqInfo;    
+  };
+
+  struct SystemInformation
+  {
+    bool haveSib2;
+    SystemInformationBlockType2 sib2;
+  }
+    ;
+  struct AsConfig
+  {
+    MeasConfig sourceMeasConfig;
+    RadioResourceConfigDedicated sourceRadioResourceConfig;
+    uint16_t sourceUeIdentity;      
+    MasterInformationBlock sourceMasterInformationBlock;
+    SystemInformationBlockType1 sourceSystemInformationBlockType1;
+    uint16_t sourceDlCarrierFreq;
+  };
+
+
+  // Messages
+
+  struct RrcConnectionRequest
+  {
+    uint64_t ueIdentity;
+  };
+
+  struct RrcConnectionSetup
+  {
+    uint8_t rrcTransactionIdentifier;
+    RadioResourceConfigDedicated radioResourceConfigDedicated;
+  };
+   
+  struct RrcConnectionSetupCompleted
+  {
+    uint8_t rrcTransactionIdentifier;
+  };
+
+  struct RrcConnectionReconfiguration
+  {
+    uint8_t rrcTransactionIdentifier;
+    bool haveMeasConfig;
+    MeasConfig measConfig;
+    bool haveMobilityControlInfo;
+    MobilityControlInfo mobilityControlInfo;
+    bool haveRadioResourceConfigDedicated;
+    RadioResourceConfigDedicated radioResourceConfigDedicated;
+  };
+    
+  struct RrcConnectionReconfigurationCompleted
+  {
+    uint8_t rrcTransactionIdentifier;
+  };
+    
+      
+  struct RrcConnectionReestablishmentRequest
+  {
+    ReestabUeIdentity ueIdentity;
+    ReestablishmentCause reestablishmentCause;
+  };
+    
+  struct RrcConnectionReestablishment
+  {
+    uint8_t rrcTransactionIdentifier;
+    RadioResourceConfigDedicated radioResourceConfigDedicated;
+  };
+      
+  struct RrcConnectionReestablishmentComplete
+  {
+    uint8_t rrcTransactionIdentifier;
+  };
+
+  struct RrcConnectionReestablishmentReject
+  {
+  };
+
+  struct RrcConnectionRelease
+  {
+  };
+
+  struct HandoverPreparationInfo
+  {
+    AsConfig asConfig;
+  };
+  
+};
+
+
+
+/**
+ * Service Access Point (SAP) used by the UE RRC to send messages to
+ * the eNB. Each method defined in this class correspond to the
+ * transmission of a message that is defined in section 6.2.2 of TS
+ * 36.331. 
+ */
+class LteUeRrcSapUser : public LteRrcSap
+{
+public:
+
+  struct SetupParameters 
+  {
+    LteRlcSapProvider* srb0SapProvider;
+    LtePdcpSapProvider* srb1SapProvider;       
+  };
+
+  virtual void Setup (SetupParameters params) = 0;
+  virtual void Reestablish () = 0;
+  virtual void SendRrcConnectionRequest (RrcConnectionRequest msg) = 0;
+  virtual void SendRrcConnectionSetupCompleted (RrcConnectionSetupCompleted msg) = 0;
+  virtual void SendRrcConnectionReconfigurationCompleted (RrcConnectionReconfigurationCompleted msg) = 0;
+  virtual void SendRrcConnectionReestablishmentRequest (RrcConnectionReestablishmentRequest msg) = 0;
+  virtual void SendRrcConnectionReestablishmentComplete (RrcConnectionReestablishmentComplete msg) = 0;
+
+};
+
+
+/**
+ * Service Access Point (SAP) used to let the UE RRC receive a message
+ * from the eNB RRC. Each method defined in this class correspond to
+ * the reception of a message that is defined in section 6.2.2 of TS
+ * 36.331. 
+ */
+class LteUeRrcSapProvider : public LteRrcSap
+{
+public:
+
+  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;
+  virtual void RecvRrcConnectionReestablishment (RrcConnectionReestablishment msg) = 0;
+  virtual void RecvRrcConnectionReestablishmentReject (RrcConnectionReestablishmentReject msg) = 0;
+  virtual void RecvRrcConnectionRelease (RrcConnectionRelease msg) = 0;
+
+};
+
+
+/**
+ * Service Access Point (SAP) used by the eNB RRC to send messages to
+ * the UE RC.  Each method defined in this class correspond to
+ * the transmission of a message that is defined in section 6.2.2 of TS
+ * 36.331. 
+ */
+class LteEnbRrcSapUser : public LteRrcSap
+{
+public:
+
+  struct SetupUeParameters 
+  {
+    LteRlcSapProvider* srb0SapProvider;
+    LtePdcpSapProvider* srb1SapProvider;       
+  };
+
+  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;
+  virtual void SendRrcConnectionReestablishment (uint16_t rnti, RrcConnectionReestablishment msg) = 0;
+  virtual void SendRrcConnectionReestablishmentReject (uint16_t rnti, RrcConnectionReestablishmentReject msg) = 0;
+  virtual void SendRrcConnectionRelease (uint16_t rnti, RrcConnectionRelease msg) = 0;
+  virtual Ptr<Packet> EncodeHandoverPreparationInformation (HandoverPreparationInfo msg) = 0;
+  virtual HandoverPreparationInfo DecodeHandoverPreparationInformation (Ptr<Packet> p) = 0;
+  virtual Ptr<Packet> EncodeHandoverCommand (RrcConnectionReconfiguration msg) = 0;
+  virtual RrcConnectionReconfiguration DecodeHandoverCommand (Ptr<Packet> p) = 0;
+
+};
+
+
+/**
+ * Service Access Point (SAP) used to let the eNB RRC receive a
+ * message from a UE RRC.  Each method defined in this class correspond to
+ * the reception of a message that is defined in section 6.2.2 of TS
+ * 36.331. 
+ */
+class LteEnbRrcSapProvider : public LteRrcSap
+{
+public:
+   
+
+  struct CompleteSetupUeParameters 
+  {
+    LteRlcSapUser* srb0SapUser;
+    LtePdcpSapUser* srb1SapUser;       
+  };
+
+  virtual void CompleteSetupUe (uint16_t rnti, CompleteSetupUeParameters params) = 0;
+  virtual void RecvRrcConnectionRequest (uint16_t rnti, RrcConnectionRequest msg) = 0;
+  virtual void RecvRrcConnectionSetupCompleted (uint16_t rnti, RrcConnectionSetupCompleted msg) = 0;
+  virtual void RecvRrcConnectionReconfigurationCompleted (uint16_t rnti, RrcConnectionReconfigurationCompleted msg) = 0;
+  virtual void RecvRrcConnectionReestablishmentRequest (uint16_t rnti, RrcConnectionReestablishmentRequest msg) = 0;
+  virtual void RecvRrcConnectionReestablishmentComplete (uint16_t rnti, RrcConnectionReestablishmentComplete msg) = 0;
+
+};
+
+
+
+
+
+
+////////////////////////////////////
+//   templates
+////////////////////////////////////
+
+
+/**
+ * Template for the implementation of the LteUeRrcSapUser as a member
+ * of an owner class of type C to which all methods are forwarded
+ * 
+ */
+template <class C>
+class MemberLteUeRrcSapUser : public LteUeRrcSapUser
+{
+public:
+  MemberLteUeRrcSapUser (C* owner);
+
+  // inherited from LteUeRrcSapUser
+  virtual void Setup (SetupParameters params);
+  virtual void Reestablish ();
+  virtual void SendRrcConnectionRequest (RrcConnectionRequest msg);
+  virtual void SendRrcConnectionSetupCompleted (RrcConnectionSetupCompleted msg);
+  virtual void SendRrcConnectionReconfigurationCompleted (RrcConnectionReconfigurationCompleted msg);
+  virtual void SendRrcConnectionReestablishmentRequest (RrcConnectionReestablishmentRequest msg);
+  virtual void SendRrcConnectionReestablishmentComplete (RrcConnectionReestablishmentComplete msg);
+
+private:
+  MemberLteUeRrcSapUser ();
+  C* m_owner;
+};
+
+template <class C>
+MemberLteUeRrcSapUser<C>::MemberLteUeRrcSapUser (C* owner)
+  : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteUeRrcSapUser<C>::MemberLteUeRrcSapUser ()
+{
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapUser<C>::Setup (SetupParameters params)
+{
+  m_owner->DoSetup (params);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapUser<C>::Reestablish ()
+{
+  m_owner->DoReestablish ();
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapUser<C>::SendRrcConnectionRequest (RrcConnectionRequest msg)
+{
+  m_owner->DoSendRrcConnectionRequest (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapUser<C>::SendRrcConnectionSetupCompleted (RrcConnectionSetupCompleted msg)
+{
+  m_owner->DoSendRrcConnectionSetupCompleted (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapUser<C>::SendRrcConnectionReconfigurationCompleted (RrcConnectionReconfigurationCompleted msg) 
+{
+  m_owner->DoSendRrcConnectionReconfigurationCompleted (msg) ;
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapUser<C>::SendRrcConnectionReestablishmentRequest (RrcConnectionReestablishmentRequest msg)
+{
+  m_owner->DoSendRrcConnectionReestablishmentRequest (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapUser<C>::SendRrcConnectionReestablishmentComplete (RrcConnectionReestablishmentComplete msg)
+{
+  m_owner->DoSendRrcConnectionReestablishmentComplete (msg);
+}
+
+/**
+ * Template for the implementation of the LteUeRrcSapProvider as a member
+ * of an owner class of type C to which all methods are forwarded
+ * 
+ */
+template <class C>
+class MemberLteUeRrcSapProvider : public LteUeRrcSapProvider
+{
+public:
+  MemberLteUeRrcSapProvider (C* owner);
+
+  // methods inherited from LteUeRrcSapProvider go here  
+  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);
+  virtual void RecvRrcConnectionReestablishment (RrcConnectionReestablishment msg);
+  virtual void RecvRrcConnectionReestablishmentReject (RrcConnectionReestablishmentReject msg);
+  virtual void RecvRrcConnectionRelease (RrcConnectionRelease msg);
+
+private:
+  MemberLteUeRrcSapProvider ();
+  C* m_owner;
+};
+
+template <class C>
+MemberLteUeRrcSapProvider<C>::MemberLteUeRrcSapProvider (C* owner)
+  : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteUeRrcSapProvider<C>::MemberLteUeRrcSapProvider ()
+{
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvMasterInformationBlock (MasterInformationBlock msg)
+{
+  m_owner->DoRecvMasterInformationBlock (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvSystemInformationBlockType1 (SystemInformationBlockType1 msg)
+{
+  m_owner->DoRecvSystemInformationBlockType1 (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvSystemInformation (SystemInformation msg)
+{
+  m_owner->DoRecvSystemInformation (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionSetup (RrcConnectionSetup msg)
+{
+  m_owner->DoRecvRrcConnectionSetup (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionReconfiguration (RrcConnectionReconfiguration msg)
+{
+  m_owner->DoRecvRrcConnectionReconfiguration (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionReestablishment (RrcConnectionReestablishment msg)
+{
+  m_owner->DoRecvRrcConnectionReestablishment (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionReestablishmentReject (RrcConnectionReestablishmentReject msg)
+{
+  m_owner->DoRecvRrcConnectionReestablishmentReject (msg);
+}
+
+template <class C>
+void 
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionRelease (RrcConnectionRelease msg)
+{
+  m_owner->DoRecvRrcConnectionRelease (msg);
+}
+
+
+
+/**
+ * Template for the implementation of the LteEnbRrcSapUser as a member
+ * of an owner class of type C to which all methods are forwarded
+ * 
+ */
+template <class C>
+class MemberLteEnbRrcSapUser : public LteEnbRrcSapUser
+{
+public:
+  MemberLteEnbRrcSapUser (C* owner);
+
+  // inherited from LteEnbRrcSapUser
+
+  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);
+  virtual void SendRrcConnectionReestablishment (uint16_t rnti, RrcConnectionReestablishment msg);
+  virtual void SendRrcConnectionReestablishmentReject (uint16_t rnti, RrcConnectionReestablishmentReject msg);
+  virtual void SendRrcConnectionRelease (uint16_t rnti, RrcConnectionRelease msg);
+  virtual Ptr<Packet> EncodeHandoverPreparationInformation (HandoverPreparationInfo msg);
+  virtual HandoverPreparationInfo DecodeHandoverPreparationInformation (Ptr<Packet> p);
+  virtual Ptr<Packet> EncodeHandoverCommand (RrcConnectionReconfiguration msg);
+  virtual RrcConnectionReconfiguration DecodeHandoverCommand (Ptr<Packet> p);
+
+private:
+  MemberLteEnbRrcSapUser ();
+  C* m_owner;
+};
+
+template <class C>
+MemberLteEnbRrcSapUser<C>::MemberLteEnbRrcSapUser (C* owner)
+  : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteEnbRrcSapUser<C>::MemberLteEnbRrcSapUser ()
+{
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapUser<C>::SetupUe (uint16_t rnti, SetupUeParameters params)
+{
+  m_owner->DoSetupUe (rnti, params);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapUser<C>::RemoveUe (uint16_t rnti)
+{
+  m_owner->DoRemoveUe (rnti);
+}
+
+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);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionSetup (uint16_t rnti, RrcConnectionSetup msg) 
+{
+  m_owner->DoSendRrcConnectionSetup (rnti, msg) ;
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionReconfiguration (uint16_t rnti, RrcConnectionReconfiguration msg)
+{
+  m_owner->DoSendRrcConnectionReconfiguration (rnti, msg);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionReestablishment (uint16_t rnti, RrcConnectionReestablishment msg)
+{
+  m_owner->DoSendRrcConnectionReestablishment (rnti, msg);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionReestablishmentReject (uint16_t rnti, RrcConnectionReestablishmentReject msg)
+{
+  m_owner->DoSendRrcConnectionReestablishmentReject (rnti, msg);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionRelease (uint16_t rnti, RrcConnectionRelease msg)
+{
+  m_owner->DoSendRrcConnectionRelease (rnti, msg);
+}
+
+template <class C>
+Ptr<Packet> 
+MemberLteEnbRrcSapUser<C>::EncodeHandoverPreparationInformation (HandoverPreparationInfo msg)
+{
+  return m_owner->DoEncodeHandoverPreparationInformation (msg);
+}
+
+template <class C>
+LteRrcSap::HandoverPreparationInfo 
+MemberLteEnbRrcSapUser<C>::DecodeHandoverPreparationInformation (Ptr<Packet> p)
+{
+  return m_owner->DoDecodeHandoverPreparationInformation (p);
+}
+
+
+template <class C>
+Ptr<Packet>  
+MemberLteEnbRrcSapUser<C>::EncodeHandoverCommand (RrcConnectionReconfiguration msg)
+{
+  return m_owner->DoEncodeHandoverCommand (msg);
+}
+
+template <class C>
+LteRrcSap::RrcConnectionReconfiguration  
+MemberLteEnbRrcSapUser<C>::DecodeHandoverCommand (Ptr<Packet> p)
+{
+  return m_owner->DoDecodeHandoverCommand (p);
+}
+
+/**
+ * Template for the implementation of the LteEnbRrcSapProvider as a member
+ * of an owner class of type C to which all methods are forwarded
+ * 
+ */
+template <class C>
+class MemberLteEnbRrcSapProvider : public LteEnbRrcSapProvider
+{
+public:
+  MemberLteEnbRrcSapProvider (C* owner);
+
+  // methods inherited from LteEnbRrcSapProvider go here  
+  
+  virtual void CompleteSetupUe (uint16_t rnti, CompleteSetupUeParameters params);
+  virtual void RecvRrcConnectionRequest (uint16_t rnti, RrcConnectionRequest msg);
+  virtual void RecvRrcConnectionSetupCompleted (uint16_t rnti, RrcConnectionSetupCompleted msg);
+  virtual void RecvRrcConnectionReconfigurationCompleted (uint16_t rnti, RrcConnectionReconfigurationCompleted msg);
+  virtual void RecvRrcConnectionReestablishmentRequest (uint16_t rnti, RrcConnectionReestablishmentRequest msg);
+  virtual void RecvRrcConnectionReestablishmentComplete (uint16_t rnti, RrcConnectionReestablishmentComplete msg);
+
+private:
+  MemberLteEnbRrcSapProvider ();
+  C* m_owner;
+};
+
+template <class C>
+MemberLteEnbRrcSapProvider<C>::MemberLteEnbRrcSapProvider (C* owner)
+  : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteEnbRrcSapProvider<C>::MemberLteEnbRrcSapProvider ()
+{
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapProvider<C>::CompleteSetupUe (uint16_t rnti, CompleteSetupUeParameters params)
+{
+  m_owner->DoCompleteSetupUe (rnti, params);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionRequest (uint16_t rnti, RrcConnectionRequest msg)
+{
+  m_owner->DoRecvRrcConnectionRequest (rnti, msg);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionSetupCompleted (uint16_t rnti, RrcConnectionSetupCompleted msg)
+{
+  m_owner->DoRecvRrcConnectionSetupCompleted (rnti, msg);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionReconfigurationCompleted (uint16_t rnti, RrcConnectionReconfigurationCompleted msg)
+{
+  m_owner->DoRecvRrcConnectionReconfigurationCompleted (rnti, msg);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionReestablishmentRequest (uint16_t rnti, RrcConnectionReestablishmentRequest msg)
+{
+  m_owner->DoRecvRrcConnectionReestablishmentRequest (rnti, msg);
+}
+
+template <class C>
+void 
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionReestablishmentComplete (uint16_t rnti, RrcConnectionReestablishmentComplete msg)
+{
+  m_owner->DoRecvRrcConnectionReestablishmentComplete (rnti, msg);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+} // namespace ns3
+
+
+#endif // LTE_RRC_SAP_H
+
+
+
+
--- a/src/lte/model/lte-spectrum-phy.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-spectrum-phy.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -217,6 +217,12 @@
   m_channel = c;
 }
 
+Ptr<SpectrumChannel> 
+LteSpectrumPhy::GetChannel ()
+{
+  return m_channel;
+}
+
 Ptr<const SpectrumModel>
 LteSpectrumPhy::GetRxSpectrumModel () const
 {
@@ -451,6 +457,7 @@
       (ii) the power transmission
       */
       NS_ASSERT (m_txPsd);
+      NS_LOG_LOGIC (this << " m_txPsd: " << *m_txPsd);
       
       // we need to convey some PHY meta information to the receiver
       // to be used for simulation purposes (e.g., the CellId). This
--- a/src/lte/model/lte-spectrum-phy.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-spectrum-phy.h	Tue Oct 30 16:02:07 2012 +0100
@@ -307,6 +307,13 @@
   */
   void SetTransmissionMode (uint8_t txMode);
   
+
+  /** 
+   * 
+   * \return the previously set channel
+   */
+  Ptr<SpectrumChannel> GetChannel ();
+
   friend class LteUePhy;
   
 
--- a/src/lte/model/lte-ue-cmac-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-cmac-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -41,16 +41,54 @@
 {
 public:
   virtual ~LteUeCmacSapProvider ();
-  /**
-   * called by the RRC after going to RRC connected
-   *
+
+  /** 
+   * tell the MAC to start a contention-based random access procedure,
+   * e.g., to perform RRC connection establishment 
+   * 
+   */
+  virtual void StartContentionBasedRandomAccessProcedure () = 0;
+
+  /** 
+   * tell the MAC to start a non-contention-based random access
+   * procedure, e.g., as a consequence of handover
+   * 
    * \param rnti
+   * \param preambleId 
+   * \param prachMask 
    */
-  virtual void ConfigureUe (uint16_t rnti) = 0;
+  virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask) = 0;
+
 
-  virtual void AddLc (uint8_t lcId, LteMacSapUser* msu) = 0;
+  struct LogicalChannelConfig
+  {
+    uint8_t priority;
+    uint16_t prioritizedBitRateKbps;
+    uint16_t bucketSizeDurationMs;
+    uint8_t logicalChannelGroup;
+  };
+  
+  /** 
+   * add a new Logical Channel (LC) 
+   * 
+   * \param lcId the ID of the LC
+   * \param lcConfig the LC configuration provided by the RRC
+   * \param msu the corresponding LteMacSapUser
+   */
+  virtual void AddLc (uint8_t lcId, LogicalChannelConfig lcConfig, LteMacSapUser* msu) = 0;
 
+  /** 
+   * remove an existing LC
+   * 
+   * \param lcId 
+   */
   virtual void RemoveLc (uint8_t lcId) = 0;
+
+  /** 
+   * reset the MAC
+   * 
+   */
+  virtual void Reset () = 0;
   
 };
 
@@ -64,8 +102,27 @@
 class LteUeCmacSapUser
 {
 public:
+
   virtual ~LteUeCmacSapUser ();
-  virtual void LcConfigCompleted () = 0;
+
+  /** 
+   * 
+   * 
+   * \param rnti the T-C-RNTI, which will eventually become the C-RNTI after contention resolution
+   */
+  virtual void SetTemporaryCellRnti (uint16_t rnti) = 0;
+
+  /** 
+   * Notify the RRC that the MAC Random Access procedure completed successfully
+   * 
+   */
+  virtual void NotifyRandomAccessSuccessful () = 0;
+
+  /** 
+   * Notify the RRC that the MAC Random Access procedure failed
+   * 
+   */
+  virtual void NotifyRandomAccessFailed () = 0;
 };
 
 
--- a/src/lte/model/lte-ue-cphy-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-cphy-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -25,6 +25,8 @@
 #include <stdint.h>
 #include <ns3/ptr.h>
 
+#include <ns3/lte-rrc-sap.h>
+
 namespace ns3 {
 
 
@@ -48,24 +50,24 @@
   /** 
    * tell the PHY to synchronize with a given eNB for communication purposes
    * 
-   * \param enbPhy a pointer to the PHY of the eNB (wild hack, might go away in later versions)
    * \param cellId the ID of the eNB
+   * \param dlEarfcn  the carrier frequency (EARFCN) in downlink
    */
-  virtual void SyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId) = 0;
+  virtual void SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn) = 0;
   
   /**
-   *
-   * \param dlEarfcn the carrier frequency (EARFCN) in downlink
-   * \param ulEarfcn the carrier frequency (EARFCN) in downlink
-   */
-  virtual void SetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn) = 0;
-
-  /**
-   * \param ulBandwidth the UL bandwidth in PRBs
    * \param dlBandwidth the DL bandwidth in PRBs
    */
-  virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth) = 0;
-  
+  virtual void SetDlBandwidth (uint8_t dlBandwidth) = 0;
+
+  /** 
+   * Configure uplink (normally done after reception of SIB2)
+   * 
+   * \param ulEarfcn the carrier frequency (EARFCN) in uplink
+   * \param ulBandwidth the UL bandwidth in PRBs
+   */
+  virtual void ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth) = 0;
+
   /** 
    * 
    * \param rnti the cell-specific UE identifier
@@ -99,6 +101,13 @@
    * destructor
    */
   virtual ~LteUeCphySapUser ();
+
+
+  /** 
+   * 
+   * \param mib the Master Information Block received on the BCH
+   */
+  virtual void RecvMasterInformationBlock (LteRrcSap::MasterInformationBlock mib) = 0;
 };
 
 
@@ -116,9 +125,9 @@
   MemberLteUeCphySapProvider (C* owner);
 
   // inherited from LteUeCphySapProvider
-  virtual void SyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
-  virtual void SetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
-  virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
+  virtual void SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);  
+  virtual void SetDlBandwidth (uint8_t ulBandwidth);
+  virtual void ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
   virtual void SetRnti (uint16_t rnti);
   virtual void SetTransmissionMode (uint8_t txMode);
   virtual void SetSrsConfigurationIndex (uint16_t srcCi);
@@ -141,23 +150,23 @@
 
 template <class C>
 void 
-MemberLteUeCphySapProvider<C>::SyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId)
+MemberLteUeCphySapProvider<C>::SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn)
 {
-  m_owner->DoSyncronizeWithEnb (enbDevice, cellId);
+  m_owner->DoSyncronizeWithEnb (cellId, dlEarfcn);
 }
 
 template <class C>
 void 
-MemberLteUeCphySapProvider<C>::SetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn)
+MemberLteUeCphySapProvider<C>::SetDlBandwidth (uint8_t dlBandwidth)
 {
-  m_owner->DoSetEarfcn (dlEarfcn, ulEarfcn);
+  m_owner->DoSetDlBandwidth (dlBandwidth);
 }
 
 template <class C>
 void 
-MemberLteUeCphySapProvider<C>::SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
+MemberLteUeCphySapProvider<C>::ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth)
 {
-  m_owner->DoSetBandwidth (ulBandwidth, dlBandwidth);
+  m_owner->DoConfigureUplink (ulEarfcn, ulBandwidth);
 }
 
 template <class C>
@@ -195,6 +204,7 @@
   MemberLteUeCphySapUser (C* owner);
 
   // methods inherited from LteUeCphySapUser go here
+  virtual void RecvMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
 
 private:
   MemberLteUeCphySapUser ();
@@ -212,6 +222,13 @@
 {
 }
 
+template <class C> 
+void 
+MemberLteUeCphySapUser<C>::RecvMasterInformationBlock (LteRrcSap::MasterInformationBlock mib)
+{
+  m_owner->DoRecvMasterInformationBlock (mib);
+}
+
 
 
 
--- a/src/lte/model/lte-ue-mac.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-mac.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -53,9 +53,11 @@
   UeMemberLteUeCmacSapProvider (LteUeMac* mac);
 
   // inherited from LteUeCmacSapProvider
-  virtual void ConfigureUe (uint16_t rnti);
-  virtual void AddLc (uint8_t lcId, LteMacSapUser* msu);
+  virtual void StartContentionBasedRandomAccessProcedure ();
+  virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask);
+  virtual void AddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu);
   virtual void RemoveLc (uint8_t lcId);
+  virtual void Reset ();
 
 private:
   LteUeMac* m_mac;
@@ -67,16 +69,23 @@
 {
 }
 
-void
-UeMemberLteUeCmacSapProvider::ConfigureUe (uint16_t rnti)
+  void 
+UeMemberLteUeCmacSapProvider::StartContentionBasedRandomAccessProcedure ()
 {
-  m_mac->DoConfigureUe (rnti);
+  m_mac->DoStartContentionBasedRandomAccessProcedure ();
 }
 
+ void 
+UeMemberLteUeCmacSapProvider::StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
+{
+  m_mac->DoStartNonContentionBasedRandomAccessProcedure (rnti, preambleId, prachMask);
+}
+
+
 void
-UeMemberLteUeCmacSapProvider::AddLc (uint8_t lcId, LteMacSapUser* msu)
+UeMemberLteUeCmacSapProvider::AddLc (uint8_t lcId, LogicalChannelConfig lcConfig, LteMacSapUser* msu)
 {
-  m_mac->DoAddLc (lcId, msu);
+  m_mac->DoAddLc (lcId, lcConfig, msu);
 }
 
 void
@@ -85,6 +94,12 @@
   m_mac->DoRemoveLc (lcid);
 }
 
+void
+UeMemberLteUeCmacSapProvider::Reset ()
+{
+  m_mac->DoReset ();
+}
+
 class UeMemberLteMacSapProvider : public LteMacSapProvider
 {
 public:
@@ -178,8 +193,9 @@
 
 LteUeMac::LteUeMac ()
   :  m_bsrPeriodicity (MilliSeconds (1)), // ideal behavior
-  m_bsrLast (MilliSeconds (0)),
-  m_freshUlBsr (false)
+     m_bsrLast (MilliSeconds (0)),
+     m_freshUlBsr (false),
+     m_rnti (0)
   
 {
   NS_LOG_FUNCTION (this);
@@ -277,29 +293,40 @@
 LteUeMac::SendReportBufferStatus (void)
 {
   NS_LOG_FUNCTION (this);
+
+  if (m_rnti == 0)
+    {
+      NS_LOG_INFO ("MAC not initialized, BSR deferred");
+      return; 
+    }
+
   if (m_ulBsrReceived.size () == 0)
     {
-      return;  // No BSR report to transmit
+      NS_LOG_INFO ("No BSR report to transmit");
+      return; 
     }
   MacCeListElement_s bsr;
   bsr.m_rnti = m_rnti;
   bsr.m_macCeType = MacCeListElement_s::BSR;
 
-  // BSR is reported for each LCG. As a simplification, we consider that all LCs belong to the first LCG.
+  // BSR is reported for each LCG
   std::map <uint8_t, uint64_t>::iterator it;  
-  int queue = 0;
+  std::vector<uint32_t> queue (4, 0); // one value per each of the 4 LCGs, initialized to 0
   for (it = m_ulBsrReceived.begin (); it != m_ulBsrReceived.end (); it++)
     {
-      queue += (*it).second;
-  
+      uint8_t lcid = it->first;
+      std::map <uint8_t, LcInfo>::iterator lcInfoMapIt;
+      lcInfoMapIt = m_lcInfoMap.find (lcid);
+      NS_ASSERT (lcInfoMapIt !=  m_lcInfoMap.end ());
+      uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
+      queue.at (lcg) += (*it).second;
     }
-  int index = BufferSizeLevelBsr::BufferSize2BsrId (queue);
-  bsr.m_macCeValue.m_bufferStatus.push_back (index);
+
   // FF API says that all 4 LCGs are always present
-  // we do so but reporting a 0 size for all other LCGs
-  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (0));
-  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (0));
-  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (0));
+  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (0)));
+  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (1)));
+  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (2)));
+  bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (3)));
 
   // create the feedback to eNB
   Ptr<BsrLteControlMessage> msg = Create<BsrLteControlMessage> ();
@@ -308,27 +335,74 @@
 
 }
 
-void
-LteUeMac::DoConfigureUe (uint16_t rnti)
+void 
+LteUeMac::DoStartContentionBasedRandomAccessProcedure ()
+{
+  NS_LOG_FUNCTION (this);
+  static uint32_t prachIdCounter = 256;
+  prachIdCounter += 2;
+  m_prachId = prachIdCounter;
+  NS_LOG_INFO ("sending RACH preamble " << m_prachId);
+
+
+  // Since regular UL LteControlMessages need m_ulConfigured = true in
+  // order to be sent by the UE, the rach preamble needs to be sent
+  // with a dedicated primitive (not
+  // m_uePhySapProvider->SendLteControlMessage (msg)) so that it can
+  // 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. 
+
+  Ptr<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
+  msg->SetPrachId (m_prachId);
+  m_uePhySapProvider->SendRachPreamble (m_prachId);
+}
+
+void 
+LteUeMac::DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
 {
   NS_LOG_FUNCTION (this << " rnti" << rnti);
   m_rnti = rnti;
 }
 
 void
-LteUeMac::DoAddLc (uint8_t lcId, LteMacSapUser* msu)
+LteUeMac::DoAddLc (uint8_t lcId,  LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu)
 {
   NS_LOG_FUNCTION (this << " lcId" << (uint16_t) lcId);
-  NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "cannot add channel because LCID " << lcId << " is already present");
-  m_macSapUserMap[lcId] = msu;
+  NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "cannot add channel because LCID " << lcId << " is already present");
+  
+  LcInfo lcInfo;
+  lcInfo.lcConfig = lcConfig;
+  lcInfo.macSapUser = msu;
+  m_lcInfoMap[lcId] = lcInfo;
 }
 
 void
 LteUeMac::DoRemoveLc (uint8_t lcId)
 {
   NS_LOG_FUNCTION (this << " lcId" << lcId);
-  NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "could not find LCID " << lcId);
-  m_macSapUserMap.erase (lcId);
+  NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "could not find LCID " << lcId);
+  m_lcInfoMap.erase (lcId);
+}
+
+void
+LteUeMac::DoReset ()
+{
+  NS_LOG_FUNCTION (this);
+  std::map <uint8_t, LcInfo>::iterator it = m_lcInfoMap.begin ();
+  while (it != m_lcInfoMap.end ())
+    {
+      // don't delete CCCH)
+      if (it->first == 0)
+        {          
+          ++it;
+        }
+      else
+        {
+          // note: use of postfix operator preserves validity of iterator
+          m_lcInfoMap.erase (it++);
+        }
+    }
 }
 
 void
@@ -339,9 +413,9 @@
   if (tag.GetRnti () == m_rnti)
     {
       // packet is for the current user
-      std::map <uint8_t, LteMacSapUser*>::const_iterator it = m_macSapUserMap.find (tag.GetLcid ());
-      NS_ASSERT_MSG (it != m_macSapUserMap.end (), "received packet with unknown lcid");
-      it->second->ReceivePdu (p);
+      std::map <uint8_t, LcInfo>::const_iterator it = m_lcInfoMap.find (tag.GetLcid ());
+      NS_ASSERT_MSG (it != m_lcInfoMap.end (), "received packet with unknown lcid");
+      it->second.macSapUser->ReceivePdu (p);
     }
 }
 
@@ -355,7 +429,6 @@
       Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
       UlDciListElement_s dci = msg2->GetDci ();
       std::map <uint8_t, uint64_t>::iterator itBsr;
-      NS_ASSERT_MSG (m_ulBsrReceived.size () <=4, " Too many LCs (max is 4)");
       uint16_t activeLcs = 0;
       for (itBsr = m_ulBsrReceived.begin (); itBsr != m_ulBsrReceived.end (); itBsr++)
         {
@@ -369,18 +442,19 @@
           NS_LOG_ERROR (this << " No active flows for this UL-DCI");
           return;
         }
-      std::map <uint8_t, LteMacSapUser*>::iterator it;
-      NS_LOG_FUNCTION (this << " UE: UL-CQI notified TxOpportunity of " << dci.m_tbSize);
-      for (it = m_macSapUserMap.begin (); it!=m_macSapUserMap.end (); it++)
+      std::map <uint8_t, LcInfo>::iterator it;
+      uint32_t bytesPerActiveLc = dci.m_tbSize / activeLcs;
+      NS_LOG_LOGIC (this << " UE: UL-CQI notified TxOpportunity of " << dci.m_tbSize << " => " << bytesPerActiveLc << " bytes per active LC");
+      for (it = m_lcInfoMap.begin (); it!=m_lcInfoMap.end (); it++)
         {
           itBsr = m_ulBsrReceived.find ((*it).first);
-          if (itBsr!=m_ulBsrReceived.end ())
+          if (((itBsr!=m_ulBsrReceived.end ()) && ((*itBsr).second > 0)))
             {
-              NS_LOG_FUNCTION (this << "\t" << dci.m_tbSize / m_macSapUserMap.size () << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second);
-              (*it).second->NotifyTxOpportunity (dci.m_tbSize / activeLcs, 0);
-              if ((*itBsr).second >=  static_cast<uint64_t> (dci.m_tbSize / activeLcs))
+              NS_LOG_LOGIC (this << "\t" << bytesPerActiveLc << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second);
+              (*it).second.macSapUser->NotifyTxOpportunity (bytesPerActiveLc, 0);
+              if ((*itBsr).second >=  static_cast<uint64_t> (bytesPerActiveLc))
                 {
-                  (*itBsr).second -= dci.m_tbSize / activeLcs;
+                  (*itBsr).second -= bytesPerActiveLc;
                 }
               else
                 {
@@ -390,9 +464,26 @@
         }
 
     }
+  else if (msg->GetMessageType () == LteControlMessage::RAR)
+    {
+      Ptr<RarLteControlMessage> msg2 = DynamicCast<RarLteControlMessage> (msg);
+      
+      if (msg2->GetPrachId () == m_prachId)
+        {
+          m_rnti = msg2->GetRar ().m_rnti;
+          NS_LOG_INFO ("got RAR for PRACH ID " << m_prachId << ", setting T-C-RNTI = " << m_rnti);
+          m_cmacSapUser->SetTemporaryCellRnti (m_rnti);
+            
+          // in principle we should wait for contention resolution,
+          // but, since we don't model RACH PREAMBLE collisions, we
+          // just stop here
+          m_cmacSapUser->NotifyRandomAccessSuccessful ();
+        }
+      // else the RAR is not for me
+    }
   else
     {
-      NS_LOG_FUNCTION (this << " LteControlMessage not recognized");
+      NS_LOG_WARN (this << " LteControlMessage not recognized");
     }
 }
 
--- a/src/lte/model/lte-ue-mac.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-mac.h	Tue Oct 30 16:02:07 2012 +0100
@@ -78,10 +78,12 @@
   void DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params);
 
   // forwarded from UE CMAC SAP
-  void DoConfigureUe (uint16_t rnti);
-  void DoAddLc (uint8_t lcId, LteMacSapUser* msu);
+
+  void DoStartContentionBasedRandomAccessProcedure ();
+  void DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask);
+  void DoAddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu);
   void DoRemoveLc (uint8_t lcId);
-  void DoRrcUpdateConfigurationReq (LteUeConfig_t params);
+  void DoReset ();
 
   // forwarded from PHY SAP
   void DoReceivePhyPdu (Ptr<Packet> p);
@@ -90,8 +92,15 @@
   void SendReportBufferStatus (void);
 
 private:
-  // end of temporary hack
-  std::map <uint8_t, LteMacSapUser*> m_macSapUserMap;
+
+  struct LcInfo
+  {
+    LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+    LteMacSapUser* macSapUser;
+  };
+
+  std::map <uint8_t, LcInfo> m_lcInfoMap;
+
   LteMacSapProvider* m_macSapProvider;
 
   LteUeCmacSapUser* m_cmacSapUser;
@@ -107,8 +116,9 @@
   
   bool m_freshUlBsr; // true when a BSR has been received in the last TTI
 
+  uint16_t m_rnti;
 
-  uint16_t m_rnti;
+  uint32_t m_prachId;
 
 };
 
--- a/src/lte/model/lte-ue-phy-sap.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-phy-sap.h	Tue Oct 30 16:02:07 2012 +0100
@@ -53,6 +53,12 @@
   */
   virtual void SendLteControlMessage (Ptr<LteControlMessage> msg) = 0;
 
+  /** 
+   * send a preamble on the PRACH
+   * 
+   * \param prachId the ID of the preamble
+   */
+  virtual void SendRachPreamble (uint32_t prachId) = 0;
 
 };
 
--- a/src/lte/model/lte-ue-phy.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-phy.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -71,7 +71,7 @@
   // inherited from LtePhySapProvider
   virtual void SendMacPdu (Ptr<Packet> p);
   virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
-  virtual void SetSrsConfigurationIndex (uint16_t srcCi);
+  virtual void SendRachPreamble (uint32_t prachId);
 
 private:
   LteUePhy* m_phy;
@@ -82,7 +82,6 @@
 
 }
 
-
 void
 UeMemberLteUePhySapProvider::SendMacPdu (Ptr<Packet> p)
 {
@@ -96,9 +95,9 @@
 }
 
 void
-UeMemberLteUePhySapProvider::SetSrsConfigurationIndex (uint16_t   srcCi)
+UeMemberLteUePhySapProvider::SendRachPreamble (uint32_t prachId)
 {
-  m_phy->DoSetSrsConfigurationIndex (srcCi);
+  m_phy->DoSendRachPreamble (prachId);
 }
 
 
@@ -127,7 +126,12 @@
     m_uePhySapUser (0),
     m_ueCphySapUser (0),
     m_rnti (0),
-    m_srsPeriodicity (0)
+    m_transmissionMode (0),
+    m_srsPeriodicity (0),
+    m_srsConfigured (false),
+    m_dlConfigured (false),
+    m_ulConfigured (false),
+    m_addedToDlChannel (false)
 {
   m_amc = CreateObject <LteAmc> ();
   m_uePhySapProvider = new UeMemberLteUePhySapProvider (this);
@@ -364,6 +368,12 @@
 LteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
 {
   NS_LOG_FUNCTION (this);
+
+  if (!(m_dlConfigured && m_ulConfigured))
+    {
+      return;
+    }
+
   // check periodic wideband CQI
   if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity)
     {
@@ -501,6 +511,17 @@
   SetControlMessages (msg);
 }
 
+void 
+LteUePhy::DoSendRachPreamble (uint32_t prachId)
+{
+  NS_LOG_FUNCTION (this << prachId);
+
+  // unlike other control messages, RACH preamble is sent ASAP
+  Ptr<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
+  msg->SetPrachId (prachId);
+  m_controlMessagesQueue.at (0).push_back (msg);
+}
+
 
 void
 LteUePhy::ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> > msgList)
@@ -578,6 +599,12 @@
       // pass the info to the MAC
       m_uePhySapUser->ReceiveLteControlMessage (msg);
     }
+    else if (msg->GetMessageType () == LteControlMessage::MIB) 
+      {
+        NS_LOG_INFO ("received MIB");
+        Ptr<MibLteControlMessage> msg2 = DynamicCast<MibLteControlMessage> (msg);
+        m_ueCphySapUser->RecvMasterInformationBlock (msg2->GetMib ());
+      }
     else
     {
       // pass the message to UE-MAC
@@ -601,78 +628,76 @@
 LteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
 {
   NS_LOG_FUNCTION (this << frameNo << subframeNo);
-  
-  // update uplink transmission mask according to previous UL-CQIs
-  SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0));
-  // shift the queue
-  for (uint8_t i = 1; i < m_macChTtiDelay; i++)
-    {
-      m_subChannelsForTransmissionQueue.at (i-1) = m_subChannelsForTransmissionQueue.at (i);
-    }
-  m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear ();
+
+  NS_ASSERT_MSG (frameNo > 0, "the SRS index check code assumes that frameNo starts at 1");
   
-  bool srs = false;
-  // check SRS periodicity
-  if (m_srsCounter==1)
-    {
-      srs = true;
-      m_srsCounter = m_srsPeriodicity;
-    }
-  else
-    {
-      m_srsCounter--;
-    }
-
-  if (srs)
+  if (m_ulConfigured)
     {
-      Simulator::Schedule (UL_SRS_DELAY_FROM_SUBFRAME_START, 
-                           &LteUePhy::SendSrs,
-                           this);
-    }
-
+      // update uplink transmission mask according to previous UL-CQIs
+      SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0));
+   
+      // shift the queue
+      for (uint8_t i = 1; i < m_macChTtiDelay; i++)
+        {
+          m_subChannelsForTransmissionQueue.at (i-1) = m_subChannelsForTransmissionQueue.at (i);
+        }
+      m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear ();
+  
+      if (m_srsConfigured)
+        {
 
-  std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
-  // send packets in queue
-  // send the current burts of packets
-  Ptr<PacketBurst> pb = GetPacketBurst ();
-  if (pb)
-    {
-      NS_LOG_LOGIC (this << " UE - start TX PUSCH + PUCCH");
-      m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
-    }
-  else
-    {
-      // send only PUCCH (ideal: fake full bandwidth signal)
-      if (ctrlMsg.size ()>0)
+          NS_ASSERT_MSG (subframeNo > 0 && subframeNo <= 10, "the SRS index check code assumes that subframeNo starts at 1");
+          if ((((frameNo-1)*10 + (subframeNo-1)) % m_srsPeriodicity) == m_srsSubframeOffset)
+            {
+              NS_LOG_INFO ("frame " << frameNo << " subframe " << subframeNo << " sending SRS (offset=" << m_srsSubframeOffset << ", period=" << m_srsPeriodicity << ")");
+              Simulator::Schedule (UL_SRS_DELAY_FROM_SUBFRAME_START, 
+                                   &LteUePhy::SendSrs,
+                                   this);
+            }
+        }
+      
+      std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
+      // send packets in queue
+      // send the current burts of packets
+      Ptr<PacketBurst> pb = GetPacketBurst ();
+      if (pb)
         {
-          std::vector <int> dlRb;
-          for (uint8_t i = 0; i < m_ulBandwidth; i++)
-            {
-              dlRb.push_back (i);
-            }
-          SetSubChannelsForTransmission (dlRb);
+          NS_LOG_LOGIC (this << " UE - start TX PUSCH + PUCCH");
           m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
         }
-    }
+      else
+        {
+          // send only PUCCH (ideal: fake full bandwidth signal)
+          if (ctrlMsg.size ()>0)
+            {
+              std::vector <int> dlRb;
+              for (uint8_t i = 0; i < m_ulBandwidth; i++)
+                {
+                  dlRb.push_back (i);
+                }
+              SetSubChannelsForTransmission (dlRb);
+              m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
+            }
+        }
+    }  // m_configured
   
-    
   // trigger the MAC
   m_uePhySapUser->SubframeIndication (frameNo, subframeNo);
-
-
+  
+  
   ++subframeNo;
   if (subframeNo > 10)
     {
       ++frameNo;
       subframeNo = 1;
     }
-
+  
   // schedule next subframe indication
   Simulator::Schedule (Seconds (GetTti ()), &LteUePhy::SubframeIndication, this, frameNo, subframeNo);  
 }
-
+  
 void
-LteUePhy::SendSrs ()
+  LteUePhy::SendSrs ()
 {
   NS_LOG_FUNCTION (this << " UE " << m_rnti << " start tx SRS, cell Id " << m_cellId);
   // set the current tx power spectral density (full bandwidth)
@@ -688,17 +713,28 @@
 
 
 void
-LteUePhy::DoSetRnti (uint16_t rnti)
+LteUePhy::DoSyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn)
 {
-  NS_LOG_FUNCTION (this << rnti);
-  m_rnti = rnti;
+  NS_LOG_FUNCTION (this << cellId);
+  m_enbCellId = cellId;
+  m_dlEarfcn = dlEarfcn;
+  m_downlinkSpectrumPhy->SetCellId (cellId);
+  m_uplinkSpectrumPhy->SetCellId (cellId);
+
+  // configure DL for receing the BCH with the minimum bandwith
+  const uint8_t minDlBandwidth = 6;
+  Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, minDlBandwidth, m_noiseFigure);
+  m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
+  m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);  
+  
+  m_dlConfigured = false;
+  m_ulConfigured = false;
 }
 
+void
+LteUePhy::DoSetDlBandwidth (uint8_t dlBandwidth)
+{
 
-void
-LteUePhy::DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
-{
-  m_ulBandwidth = ulBandwidth;
   m_dlBandwidth = dlBandwidth;
 
   int Type0AllocationRbg[4] = {
@@ -715,29 +751,31 @@
           break;
         }
     }
-  UpdateNoisePsd ();
-}
+  
+  Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
+  m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
+  m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);  
 
-void 
-LteUePhy::DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn)
-{
-  m_dlEarfcn = dlEarfcn;
-  m_ulEarfcn = ulEarfcn;
-  UpdateNoisePsd ();
+  m_dlConfigured = true;
 }
 
 
-void
-LteUePhy::DoSyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId)
+void 
+LteUePhy::DoConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth)
 {
-  NS_LOG_FUNCTION (this << enbDevice << cellId);
-  m_enbCellId = cellId;
-  m_enbDevice = enbDevice;
-  
-  m_downlinkSpectrumPhy->SetCellId (cellId);
-  m_uplinkSpectrumPhy->SetCellId (cellId);
+  m_ulEarfcn = ulEarfcn;
+  m_ulBandwidth = ulBandwidth;
+  m_ulConfigured = true;
 }
 
+ 
+void
+LteUePhy::DoSetRnti (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  m_rnti = rnti;
+}
+ 
 void
 LteUePhy::DoSetTransmissionMode (uint8_t txMode)
 {
@@ -751,8 +789,9 @@
 {
   NS_LOG_FUNCTION (this << srcCi);
   m_srsPeriodicity = GetSrsPeriodicity (srcCi);
-  m_srsCounter = GetSrsSubframeOffset (srcCi) + 1;
-  NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << GetSrsSubframeOffset (srcCi) << " cellId " << m_cellId << " CI " << srcCi);
+  m_srsSubframeOffset = GetSrsSubframeOffset (srcCi);
+  m_srsConfigured = true;
+  NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << m_srsSubframeOffset << " cellId " << m_cellId << " CI " << srcCi);
 }
 
 
@@ -827,12 +866,5 @@
   m_downlinkSpectrumPhy->SetTxModeGain (txMode, gain);
 }
 
-void 
-LteUePhy::UpdateNoisePsd ()
-{
-  Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
-  m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
-}
-
 
 } // namespace ns3
--- a/src/lte/model/lte-ue-phy.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-phy.h	Tue Oct 30 16:02:07 2012 +0100
@@ -37,7 +37,6 @@
 namespace ns3 {
 
 class PacketBurst;
-class LteNetDevice;
 class LteEnbPhy;
 
 /**
@@ -120,11 +119,6 @@
    */
   uint8_t GetMacChDelay (void) const;
 
-  /**
-   * \brief Queue the MAC PDU to be sent
-   * \param p the MAC PDU to sent
-   */
-  virtual void DoSendMacPdu (Ptr<Packet> p);
 
   /**
    * \brief Create the PSD for the TX
@@ -168,11 +162,8 @@
   virtual void GenerateCtrlCqiReport (const SpectrumValue& sinr);
   virtual void GenerateDataCqiReport (const SpectrumValue& sinr);
 
-  virtual void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
   virtual void ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> >);
   
-  virtual void DoSetSrsConfigurationIndex (uint16_t srcCi);
-  
 
 
 
@@ -210,16 +201,20 @@
   void SetTxMode7Gain (double gain);
   void SetTxModeGain (uint8_t txMode, double gain);
 
-  void UpdateNoisePsd ();
-  
   void QueueSubChannelsForTransmission (std::vector <int> rbMap);
 
-  // CPHY SAP methods
-  void DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
-  void DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
+  // UE CPHY SAP methods
+  void DoSyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);  
+  void DoSetDlBandwidth (uint8_t ulBandwidth);
+  void DoConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
+  void DoSetRnti (uint16_t rnti);
   void DoSetTransmissionMode (uint8_t txMode);
-  void DoSetRnti (uint16_t rnti);
-  void DoSyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
+  void DoSetSrsConfigurationIndex (uint16_t srcCi);
+
+  // UE PHY SAP methods 
+  virtual void DoSendMacPdu (Ptr<Packet> p);  
+  virtual void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
+  virtual void DoSendRachPreamble (uint32_t prachId);
   
   std::vector <int> m_subChannelsForTransmission;
   std::vector <int> m_subChannelsForReception;
@@ -246,13 +241,17 @@
   uint16_t  m_rnti;
 
   uint16_t m_enbCellId;
-  Ptr<LteEnbNetDevice> m_enbDevice; // wild hack, might go away in later versions
-  
+ 
   uint8_t m_transmissionMode;
   std::vector <double> m_txModeGain;
   
   uint16_t m_srsPeriodicity;
-  uint16_t m_srsCounter;
+  uint16_t m_srsSubframeOffset;
+  uint16_t m_srsConfigured;
+
+  bool m_dlConfigured;
+  bool m_ulConfigured;
+  bool m_addedToDlChannel;
 
 };
 
--- a/src/lte/model/lte-ue-rrc.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
  *
  * 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
@@ -20,14 +20,17 @@
 
 #include <ns3/fatal-error.h>
 #include <ns3/log.h>
-#include "ns3/object-map.h"
-#include "ns3/object-factory.h"
-#include "ns3/node-list.h"
-#include "ns3/node.h"
+#include <ns3/object-map.h>
+#include <ns3/object-factory.h>
+#include <ns3/node-list.h>
+#include <ns3/node.h>
 
 #include "lte-ue-rrc.h"
 #include "lte-enb-rrc.h"
 #include "lte-rlc.h"
+#include "lte-rlc-tm.h"
+#include "lte-rlc-um.h"
+#include "lte-rlc-am.h"
 #include "lte-pdcp.h"
 #include "lte-pdcp-sap.h"
 #include "lte-radio-bearer-info.h"
@@ -49,8 +52,10 @@
 public:
   UeMemberLteUeCmacSapUser (LteUeRrc* rrc);
 
-  virtual void LcConfigCompleted ();
-
+  virtual void SetTemporaryCellRnti (uint16_t rnti);
+  virtual void NotifyRandomAccessSuccessful ();
+  virtual void NotifyRandomAccessFailed ();
+  
 private:
   LteUeRrc* m_rrc;
 };
@@ -61,31 +66,75 @@
 }
 
 void
-UeMemberLteUeCmacSapUser::LcConfigCompleted ()
+UeMemberLteUeCmacSapUser::SetTemporaryCellRnti (uint16_t rnti)
 {
-  m_rrc->DoLcConfigCompleted ();
+  m_rrc->DoSetTemporaryCellRnti (rnti);
+}
+
+
+void
+UeMemberLteUeCmacSapUser::NotifyRandomAccessSuccessful ()
+{
+  m_rrc->DoNotifyRandomAccessSuccessful ();
+}
+
+void
+UeMemberLteUeCmacSapUser::NotifyRandomAccessFailed ()
+{
+  m_rrc->DoNotifyRandomAccessFailed ();
 }
 
 
 
 
 
+
+
+const char* g_ueRrcStateName[LteUeRrc::NUM_STATES] = 
+  {
+    "IDLE_CELL_SELECTION",
+    "IDLE_WAIT_SYSTEM_INFO",
+    "IDLE_CAMPED_NORMALLY",
+    "IDLE_RANDOM_ACCESS",
+    "IDLE_CONNECTING",
+    "CONNECTED_NORMALLY",
+    "CONNECTED_REESTABLISHING",
+    "CONNECTED_HANDOVER"
+  };
+
+std::string ToString (LteUeRrc::State s)
+{
+  return std::string (g_ueRrcStateName[s]);
+}
+
+
 /////////////////////////////
 // ue RRC methods
 /////////////////////////////
 
 NS_OBJECT_ENSURE_REGISTERED (LteUeRrc);
 
+
 LteUeRrc::LteUeRrc ()
   : m_cphySapProvider (0),
     m_cmacSapProvider (0),
+    m_rrcSapUser (0),
     m_macSapProvider (0),
     m_asSapUser (0),
-    m_cellId (0)
+    m_state (IDLE_CELL_SELECTION),
+    m_imsi (0),
+    m_rnti (0),
+    m_cellId (0),
+    m_useRlcSm (true),
+    m_connectionPending (0),
+    m_receivedMib (0),
+    m_receivedSib2 (0)
+
 {
   NS_LOG_FUNCTION (this);
   m_cphySapUser = new MemberLteUeCphySapUser<LteUeRrc> (this);
   m_cmacSapUser = new UeMemberLteUeCmacSapUser (this);
+  m_rrcSapProvider = new MemberLteUeRrcSapProvider<LteUeRrc> (this);
   m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<LteUeRrc> (this);
   m_asSapProvider = new MemberLteAsSapProvider<LteUeRrc> (this);
 }
@@ -104,7 +153,7 @@
   delete m_cmacSapUser;
   delete m_pdcpSapUser;
   delete m_asSapProvider;
-  m_rbMap.clear ();
+  m_drbMap.clear ();
 }
 
 TypeId
@@ -113,10 +162,10 @@
   static TypeId tid = TypeId ("ns3::LteUeRrc")
     .SetParent<Object> ()
     .AddConstructor<LteUeRrc> ()
-    .AddAttribute ("RadioBearerMap", "List of UE RadioBearerInfo by LCID.",
+    .AddAttribute ("DataRadioBearerMap", "List of UE RadioBearerInfo for Data Radio Bearers by LCID.",
                    ObjectMapValue (),
-                   MakeObjectMapAccessor (&LteUeRrc::m_rbMap),
-                   MakeObjectMapChecker<LteRadioBearerInfo> ())
+                   MakeObjectMapAccessor (&LteUeRrc::m_drbMap),
+                   MakeObjectMapChecker<LteDataRadioBearerInfo> ())
     .AddAttribute ("CellId",
                    "Serving cell identifier",
                    UintegerValue (0), // unused, read-only attribute
@@ -127,6 +176,9 @@
                    UintegerValue (0), // unused, read-only attribute
                    MakeUintegerAccessor (&LteUeRrc::GetRnti),
                    MakeUintegerChecker<uint16_t> ())
+    .AddTraceSource ("StateTransition",
+                     "fired upon every UE RRC state transition",
+                     MakeTraceSourceAccessor (&LteUeRrc::m_stateTransitionCallback))
     ;
   return tid;
 }
@@ -161,6 +213,20 @@
 }
 
 void
+LteUeRrc::SetLteUeRrcSapUser (LteUeRrcSapUser * s)
+{
+  NS_LOG_FUNCTION (this << s);
+  m_rrcSapUser = s;
+}
+
+LteUeRrcSapProvider*
+LteUeRrc::GetLteUeRrcSapProvider ()
+{
+  NS_LOG_FUNCTION (this);
+  return m_rrcSapProvider;
+}
+
+void
 LteUeRrc::SetLteMacSapProvider (LteMacSapProvider * s)
 {
   NS_LOG_FUNCTION (this << s);
@@ -182,120 +248,10 @@
 void 
 LteUeRrc::SetImsi (uint64_t imsi)
 {
+  NS_LOG_FUNCTION (this << imsi);
   m_imsi = imsi;
 }
 
-void
-LteUeRrc::SetupRadioBearer (EpsBearer bearer, TypeId rlcTypeId, uint8_t lcid)
-{
-  NS_LOG_FUNCTION (this << (uint32_t) lcid);
-
-  ObjectFactory rlcObjectFactory;
-  rlcObjectFactory.SetTypeId (rlcTypeId);
-  Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
-  rlc->SetLteMacSapProvider (m_macSapProvider);
-  rlc->SetRnti (m_rnti);
-  rlc->SetLcId (lcid);
-
-  Ptr<LteRadioBearerInfo> rbInfo = CreateObject<LteRadioBearerInfo> ();
-  rbInfo->m_rlc = rlc;
-
-  // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
-  // if we are using RLC/SM we don't care of anything above RLC
-  if (rlcTypeId != LteRlcSm::GetTypeId ())
-    {
-      Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
-      pdcp->SetRnti (m_rnti);
-      pdcp->SetLcId (lcid);
-      pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
-      pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
-      rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
-      rbInfo->m_pdcp = pdcp;
-    }
-  
-  NS_ASSERT_MSG (m_rbMap.find (lcid) == m_rbMap.end (), "bearer with same lcid already existing");
-  m_rbMap.insert (std::pair<uint8_t, Ptr<LteRadioBearerInfo> > (lcid, rbInfo));
-  
-  m_cmacSapProvider->AddLc (lcid, rlc->GetLteMacSapUser ());
-}
-
-void
-LteUeRrc::ReleaseRadioBearer (uint8_t lcid)
-{
-  NS_LOG_FUNCTION (this << (uint32_t) lcid);
-  std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it =   m_rbMap.find (lcid);
-  NS_ASSERT_MSG (it != m_rbMap.end (), "could not find bearer with given lcid");
-  m_rbMap.erase (it);
-  NS_FATAL_ERROR ("need to remove entry from TFT classifier, but this is not implemented yet");
-}
-
-
-void
-LteUeRrc::DoSendData (Ptr<Packet> packet, uint8_t bid)
-{
-  NS_LOG_FUNCTION (this << packet);
-
-  // this is true until we implement Signaling Radio Bearers
-  uint8_t lcid = bid;
-  LtePdcpSapProvider::TransmitRrcPduParameters params;
-  params.rrcPdu = packet;
-  params.rnti = m_rnti;
-  params.lcid = lcid;
-  std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it =   m_rbMap.find (lcid);
-  NS_ASSERT_MSG (it != m_rbMap.end (), "could not find bearer with lcid == " << lcid);
-  
-  NS_LOG_LOGIC (this << " RNTI=" << m_rnti << " sending " << packet << "on LCID " << (uint32_t) lcid << " (" << packet->GetSize () << " bytes)");
-  it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitRrcPdu (params);  
-}
-
-void
-LteUeRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params)
-{
-  NS_LOG_FUNCTION (this);
-  m_asSapUser->RecvData (params.rrcPdu);
-}
-
-
-
-
-void
-LteUeRrc::DoLcConfigCompleted ()
-{
-  NS_LOG_FUNCTION (this);
-  NS_FATAL_ERROR ("not implemented");
-}
-
-
-void 
-LteUeRrc::DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbLteDevice, uint16_t cellId)
-{
-  NS_LOG_FUNCTION (this << cellId);
-  
-  m_cphySapProvider->SetEarfcn (enbLteDevice->GetDlEarfcn (),
-                               enbLteDevice->GetUlEarfcn ());
-  
-  m_cellId = cellId;
-  m_cphySapProvider->SyncronizeWithEnb (enbLteDevice, cellId);
-
-  // the bandwidth setting should be done upon receiving the MIB, but
-  // MIB is not implemented for the time being. 
-  m_cphySapProvider->SetBandwidth (enbLteDevice->GetUlBandwidth (),
-                                   enbLteDevice->GetDlBandwidth ());
-
-  // this is used for RRC interactions until the RRC protocol is implemented
-  m_enbRrc = enbLteDevice->GetRrc ();
-}
-
-void 
-LteUeRrc::DoConnect ()
-{
-  NS_LOG_FUNCTION (this);
-  
-  m_rnti = m_enbRrc->DoRecvConnectionRequest (m_imsi);
-  m_cmacSapProvider->ConfigureUe (m_rnti);
-  m_cphySapProvider->SetRnti (m_rnti);
-}
-
 uint16_t
 LteUeRrc::GetRnti () const
 {
@@ -310,74 +266,631 @@
   return m_cellId;
 }
 
-std::vector<uint8_t>
-LteUeRrc::GetLcIdVector ()
+
+uint8_t 
+LteUeRrc::GetUlBandwidth () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_ulBandwidth;
+}
+
+uint8_t 
+LteUeRrc::GetDlBandwidth () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_dlBandwidth;
+}
+
+uint16_t 
+LteUeRrc::GetDlEarfcn () const
 {
-  std::vector<uint8_t> v;
-  for (std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.begin (); it != m_rbMap.end (); ++it)
-    {
-      v.push_back (it->first);
-    }
-  return v;
+  return m_dlEarfcn;
+}
+
+uint16_t 
+LteUeRrc::GetUlEarfcn () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_ulEarfcn;
+}
+
+
+LteUeRrc::State
+LteUeRrc::GetState (void)
+{
+  NS_LOG_FUNCTION (this);
+  return m_state;
+}
+
+void
+LteUeRrc::SetUseRlcSm (bool val) 
+{
+  NS_LOG_FUNCTION (this);
+  m_useRlcSm = val;
 }
 
-void 
-LteUeRrc::DoRecvConnectionSetup (LteUeConfig_t params)
-{    
-  m_cphySapProvider->SetTransmissionMode (params.m_transmissionMode);
-  m_cphySapProvider->SetSrsConfigurationIndex (params.m_srsConfigurationIndex);
+
+void
+LteUeRrc::DoStart (void)
+{
+  NS_LOG_FUNCTION (this);
+
+  // setup the UE side of SRB0
+  uint8_t lcid = 0;
+
+  Ptr<LteRlc> rlc = CreateObject<LteRlcTm> ()->GetObject<LteRlc> ();
+  rlc->SetLteMacSapProvider (m_macSapProvider);
+  rlc->SetRnti (m_rnti);
+  rlc->SetLcId (lcid);
+
+  m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();  
+  m_srb0->m_rlc = rlc;
+  m_srb0->m_srbIdentity = 1;
+
+  // CCCH (LCID 0) is pre-configured, here is the hardcoded configuration:
+  LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+  lcConfig.priority = 0; // highest priority
+  lcConfig.prioritizedBitRateKbps = 65535; // maximum
+  lcConfig.bucketSizeDurationMs = 65535; // maximum
+  lcConfig.logicalChannelGroup = 0; // all SRBs mapped to LCG 0
+
+  m_cmacSapProvider->AddLc (lcid, lcConfig, rlc->GetLteMacSapUser ());
+    
+}
 
 
-  m_enbRrc->DoRecvConnectionSetupCompleted (m_rnti);  
+void
+LteUeRrc::DoSendData (Ptr<Packet> packet, uint8_t bid)
+{
+  NS_LOG_FUNCTION (this << packet);
+
+
+  uint8_t drbid = Bid2Drbid (bid);
+
+  std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it =   m_drbMap.find (drbid);
+  NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with drbid == " << drbid);
+
+  LtePdcpSapProvider::TransmitPdcpSduParameters params;
+  params.pdcpSdu = packet;
+  params.rnti = m_rnti;
+  params.lcid = it->second->m_logicalChannelIdentity;
+  
+  NS_LOG_LOGIC (this << " RNTI=" << m_rnti << " sending " << packet << "on DRBID " << (uint32_t) drbid << " (LCID" << params.lcid << ")" << " (" << packet->GetSize () << " bytes)");
+  it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitPdcpSdu (params);  
 }
 
 void
-LteUeRrc::DoRecvConnectionReconfiguration (LteUeConfig_t params)
+LteUeRrc::DoDisconnect ()
+{
+  NS_LOG_FUNCTION (this);
+
+  switch (m_state)
+    {      
+    case IDLE_CELL_SELECTION:
+    case IDLE_CAMPED_NORMALLY:
+      NS_LOG_INFO ("already disconnected");
+      break;
+
+    case IDLE_CONNECTING:
+      NS_LOG_INFO ("aborting connection setup procedure");
+      SwitchToState (IDLE_CAMPED_NORMALLY);
+      break;
+      
+    case CONNECTED_NORMALLY:
+    case CONNECTED_REESTABLISHING:
+    case CONNECTED_HANDOVER:
+      LeaveConnectedMode ();
+      break;
+      
+    default:
+      NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+      break;
+    }
+}
+
+void
+LteUeRrc::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
+{
+  NS_LOG_FUNCTION (this);
+  m_asSapUser->RecvData (params.pdcpSdu);
+}
+
+
+void
+LteUeRrc::DoSetTemporaryCellRnti (uint16_t rnti)
 {
-  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
-  
-  m_cphySapProvider->SetTransmissionMode (params.m_transmissionMode);
-  m_cphySapProvider->SetSrsConfigurationIndex (params.m_srsConfigurationIndex);
+  NS_LOG_FUNCTION (this << rnti);
+  m_rnti = rnti;
+  m_rrcSapUser->Reestablish ();
+  m_cphySapProvider->SetRnti (m_rnti);
+}
 
+void
+LteUeRrc::DoNotifyRandomAccessSuccessful ()
+{
+  NS_LOG_FUNCTION (this << m_imsi << ToString (m_state));
+  switch (m_state)
+    {
+    case IDLE_RANDOM_ACCESS:     
+      {
+        // we just received a RAR with a T-C-RNTI and an UL grant
+        // send RRC connection request as message 3 of the random access procedure 
+        SwitchToState (IDLE_CONNECTING);
+        LteRrcSap::RrcConnectionRequest msg;
+        msg.ueIdentity = m_imsi;
+        m_rrcSapUser->SendRrcConnectionRequest (msg); 
+      }
+      break;
+      
+    case CONNECTED_HANDOVER:     
+      {
+        LteRrcSap::RrcConnectionReconfigurationCompleted msg;
+        msg.rrcTransactionIdentifier = m_lastRrcTransactionIdentifier;
+        m_rrcSapUser->SendRrcConnectionReconfigurationCompleted (msg);
+        SwitchToState (CONNECTED_NORMALLY);
+      }
+      break;
+          
+    default:
+      NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state));
+      break; 
+    } 
+}
+
+void
+LteUeRrc::DoNotifyRandomAccessFailed ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+void 
+LteUeRrc::DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbLteDevice, uint16_t cellId)
+{
+  NS_LOG_FUNCTION (this << cellId);
+    
+  m_cellId = cellId;
+  m_dlEarfcn = enbLteDevice->GetDlEarfcn ();
+  m_cphySapProvider->SyncronizeWithEnb (m_cellId, m_dlEarfcn); 
+  SwitchToState (IDLE_WAIT_SYSTEM_INFO);
 }
 
 void 
-LteUeRrc::DoRecvConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti)
+LteUeRrc::DoConnect ()
 {
-  Ptr<LteEnbNetDevice> enbDev;
-  // WILD HACK - eventually we'll get rid of all these Ptr<Device> around
-  NodeList::Iterator listEnd = NodeList::End ();
-  bool found = false;
-  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
+  NS_LOG_FUNCTION (this);
+  switch (m_state)
+    {
+    case IDLE_CELL_SELECTION:
+    case IDLE_WAIT_SYSTEM_INFO:
+      m_connectionPending = true;
+      break;
+
+    case IDLE_CAMPED_NORMALLY:     
+      StartConnection ();
+      break;
+
+    case IDLE_RANDOM_ACCESS:
+    case IDLE_CONNECTING:
+      NS_LOG_WARN ("already connecting (state " << ToString (m_state) << ")");      
+      break;
+
+    case CONNECTED_NORMALLY:
+    case CONNECTED_REESTABLISHING:
+    case CONNECTED_HANDOVER:
+      NS_LOG_WARN ("already connected (state " << ToString (m_state) << ")");      
+      break;  
+      
+    default:
+      NS_FATAL_ERROR ("cannot connect while in state " << ToString (m_state));
+      break;
+    }
+
+
+}
+
+
+
+// CPHY SAP methods
+
+void 
+LteUeRrc::DoRecvMasterInformationBlock (LteRrcSap::MasterInformationBlock msg)  
+{ 
+  NS_LOG_FUNCTION (this);
+  m_dlBandwidth = msg.dlBandwidth;
+  m_cphySapProvider->SetDlBandwidth (msg.dlBandwidth);
+  m_receivedMib = true;
+  if (m_state == IDLE_WAIT_SYSTEM_INFO && m_receivedMib && m_receivedSib2)
+    {
+       SwitchToState (IDLE_CAMPED_NORMALLY);
+    }
+}
+
+
+
+// RRC SAP methods
+
+void 
+LteUeRrc::DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg)
+{
+  NS_LOG_FUNCTION (this);
+  // to be implemented
+}
+
+ 
+void 
+LteUeRrc::DoRecvSystemInformation (LteRrcSap::SystemInformation msg)
+{
+  NS_LOG_FUNCTION (this);
+  if (msg.haveSib2)
+    {
+      m_receivedSib2 = true;
+      m_ulBandwidth = msg.sib2.freqInfo.ulBandwidth;
+      m_ulEarfcn = msg.sib2.freqInfo.ulCarrierFreq;
+      m_cphySapProvider->ConfigureUplink (m_ulEarfcn, m_ulBandwidth);
+    }
+  if (m_state == IDLE_WAIT_SYSTEM_INFO && m_receivedMib && m_receivedSib2)
+    {
+       SwitchToState (IDLE_CAMPED_NORMALLY);
+    }
+}
+
+
+void 
+LteUeRrc::DoRecvRrcConnectionSetup (LteRrcSap::RrcConnectionSetup msg)
+{    
+  NS_LOG_FUNCTION (this);
+  switch (m_state)
+    {
+    case IDLE_CONNECTING:
+      {
+        ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
+        SwitchToState (CONNECTED_NORMALLY);
+        LteRrcSap::RrcConnectionSetupCompleted msg2;
+        msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
+        m_rrcSapUser->SendRrcConnectionSetupCompleted (msg2);
+        m_asSapUser->NotifyConnectionSuccessful ();
+      }
+      break;
+      
+    default:
+      NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+      break;
+    }
+}
+
+void
+LteUeRrc::DoRecvRrcConnectionReconfiguration (LteRrcSap::RrcConnectionReconfiguration msg)
+{
+  NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
+  switch (m_state)
     {
-      Ptr<Node> node = *i;
-      int nDevs = node->GetNDevices ();
-      for (int j = 0; j < nDevs; j++)
+    case CONNECTED_NORMALLY:
+      if (msg.haveRadioResourceConfigDedicated)
+        {
+          ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
+        }      
+      if (msg.haveMobilityControlInfo)
+        {
+          SwitchToState (CONNECTED_HANDOVER);
+          const LteRrcSap::MobilityControlInfo& mci = msg.mobilityControlInfo;
+          m_cellId = mci.targetPhysCellId;
+          NS_ASSERT (mci.haveCarrierFreq);
+          NS_ASSERT (mci.haveCarrierBandwidth);
+          m_cphySapProvider->SyncronizeWithEnb (m_cellId, mci.carrierFreq.dlCarrierFreq); 
+          m_cphySapProvider->SetDlBandwidth ( mci.carrierBandwidth.dlBandwidth); 
+          m_cphySapProvider->ConfigureUplink (mci.carrierFreq.ulCarrierFreq, mci.carrierBandwidth.ulBandwidth); 
+          m_rnti = msg.mobilityControlInfo.newUeIdentity;
+          NS_ASSERT_MSG (mci.haveRachConfigDedicated, "handover is only supported with non-contention-based random access procedure");
+          m_cmacSapProvider->StartNonContentionBasedRandomAccessProcedure (m_rnti, mci.rachConfigDedicated.raPreambleIndex, mci.rachConfigDedicated.raPrachMaskIndex);
+          m_cphySapProvider->SetRnti (m_rnti);
+          m_lastRrcTransactionIdentifier = msg.rrcTransactionIdentifier;
+          // RRC connection reconfiguration completed will be sent
+          // after handover is completed
+        }
+      else
         {
-          enbDev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
-          if (!enbDev)
+          LteRrcSap::RrcConnectionReconfigurationCompleted msg2;
+          msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
+          m_rrcSapUser->SendRrcConnectionReconfigurationCompleted (msg2);
+        }
+      break;
+
+    default:
+      NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+      break;
+    }
+}
+
+void 
+LteUeRrc::DoRecvRrcConnectionReestablishment (LteRrcSap::RrcConnectionReestablishment msg)
+{
+  switch (m_state)
+    {
+    case CONNECTED_REESTABLISHING:
+      {
+      }
+      break;
+      
+    default:
+      NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+      break;
+    }
+}
+
+void 
+LteUeRrc::DoRecvRrcConnectionReestablishmentReject (LteRrcSap::RrcConnectionReestablishmentReject msg)
+{
+  NS_LOG_FUNCTION (this);
+  switch (m_state)
+    {
+    case CONNECTED_REESTABLISHING:
+      {
+        LeaveConnectedMode ();
+      }
+      break;
+      
+    default:
+      NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+      break;
+    }
+}
+
+void 
+LteUeRrc::DoRecvRrcConnectionRelease (LteRrcSap::RrcConnectionRelease msg)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+
+
+
+void 
+LteUeRrc::ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd)
+{
+  NS_LOG_FUNCTION (this);
+  const struct LteRrcSap::PhysicalConfigDedicated& pcd = rrcd.physicalConfigDedicated;
+  
+  if (pcd.haveAntennaInfoDedicated)
+    {
+      m_cphySapProvider->SetTransmissionMode (pcd.antennaInfo.transmissionMode);
+    }
+  if (pcd.haveSoundingRsUlConfigDedicated)
+    {
+      m_cphySapProvider->SetSrsConfigurationIndex (pcd.soundingRsUlConfigDedicated.srsConfigIndex);
+    }
+
+  std::list<LteRrcSap::SrbToAddMod>::const_iterator stamIt = rrcd.srbToAddModList.begin ();
+  if (stamIt != rrcd.srbToAddModList.end ())
+    {
+      if (m_srb1 == 0)
+        {
+          // SRB1 not setup yet        
+          NS_ASSERT_MSG (m_state == IDLE_CONNECTING, "expected state IDLE_CONNECTING, actual state " << ToString (m_state));
+          NS_ASSERT_MSG (stamIt->srbIdentity == 1, "only SRB1 supported");
+
+          const uint8_t lcid = 1; // fixed LCID for SRB1
+
+          Ptr<LteRlc> rlc = CreateObject<LteRlcAm> ();
+          rlc->SetLteMacSapProvider (m_macSapProvider);
+          rlc->SetRnti (m_rnti);
+          rlc->SetLcId (lcid);      
+
+          Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+          pdcp->SetRnti (m_rnti);
+          pdcp->SetLcId (lcid);
+          pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+          pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+          rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+
+          m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();
+          m_srb1->m_rlc = rlc;
+          m_srb1->m_pdcp = pdcp;
+          m_srb1->m_srbIdentity = 1;
+          
+          m_srb1->m_logicalChannelConfig.priority = stamIt->logicalChannelConfig.priority;
+          m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
+          m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
+          m_srb1->m_logicalChannelConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
+
+          struct LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+          lcConfig.priority = stamIt->logicalChannelConfig.priority;
+          lcConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
+          lcConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
+          lcConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
+      
+          m_cmacSapProvider->AddLc (lcid, lcConfig, rlc->GetLteMacSapUser ());
+      
+          ++stamIt;
+          NS_ASSERT_MSG (stamIt == rrcd.srbToAddModList.end (), "at most one SrbToAdd supported");     
+        }
+      else
+        {
+          NS_LOG_INFO ("request to modify SRB1 (skipping as currently not implemented)");
+          // would need to modify m_srb1, and then propagate changes to the MAC
+        }
+    }
+
+
+  std::list<LteRrcSap::DrbToAddMod>::const_iterator dtamIt;
+  for (dtamIt = rrcd.drbToAddModList.begin ();
+       dtamIt != rrcd.drbToAddModList.end ();
+       ++dtamIt)
+    {
+      NS_LOG_INFO (this << " IMSI " << m_imsi << " adding/modifying DRBID " << dtamIt->drbIdentity << " LC " << (uint32_t) dtamIt->logicalChannelIdentity);
+      NS_ASSERT_MSG (dtamIt->logicalChannelIdentity > 2, "LCID value " << dtamIt->logicalChannelIdentity << " is reserved for SRBs");
+
+      std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator drbMapIt = m_drbMap.find (dtamIt->drbIdentity);
+      if (drbMapIt == m_drbMap.end ())
+        {
+          NS_LOG_INFO ("New Data Radio Bearer");
+        
+          TypeId rlcTypeId;
+          if (m_useRlcSm)
             {
-              continue;
+              rlcTypeId = LteRlcSm::GetTypeId ();
             }
           else
             {
-              if (enbDev->GetCellId () == targetCellId)
+              switch (dtamIt->rlcConfig.choice)
                 {
-                  found = true;                  
+                case LteRrcSap::RlcConfig::AM: 
+                  rlcTypeId = LteRlcAm::GetTypeId ();
+                  break;
+          
+                case LteRrcSap::RlcConfig::UM_BI_DIRECTIONAL: 
+                  rlcTypeId = LteRlcUm::GetTypeId ();
+                  break;
+          
+                default:
+                  NS_FATAL_ERROR ("unsupported RLC configuration");
+                  break;                
                 }
             }
+  
+          ObjectFactory rlcObjectFactory;
+          rlcObjectFactory.SetTypeId (rlcTypeId);
+          Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
+          rlc->SetLteMacSapProvider (m_macSapProvider);
+          rlc->SetRnti (m_rnti);
+          rlc->SetLcId (dtamIt->logicalChannelIdentity);
+
+          Ptr<LteDataRadioBearerInfo> rbInfo = CreateObject<LteDataRadioBearerInfo> ();
+          rbInfo->m_rlc = rlc;
+
+          // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
+          // if we are using RLC/SM we don't care of anything above RLC
+          if (rlcTypeId != LteRlcSm::GetTypeId ())
+            {
+              Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+              pdcp->SetRnti (m_rnti);
+              pdcp->SetLcId (dtamIt->logicalChannelIdentity);
+              pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+              pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+              rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+              rbInfo->m_pdcp = pdcp;
+            }
+
+          m_bid2DrbidMap[dtamIt->epsBearerIdentity] = dtamIt->drbIdentity;
+  
+          m_drbMap.insert (std::pair<uint8_t, Ptr<LteDataRadioBearerInfo> > (dtamIt->drbIdentity, rbInfo));
+  
+
+          struct LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+          lcConfig.priority = dtamIt->logicalChannelConfig.priority;
+          lcConfig.prioritizedBitRateKbps = dtamIt->logicalChannelConfig.prioritizedBitRateKbps;
+          lcConfig.bucketSizeDurationMs = dtamIt->logicalChannelConfig.bucketSizeDurationMs;
+          lcConfig.logicalChannelGroup = dtamIt->logicalChannelConfig.logicalChannelGroup;      
+
+          m_cmacSapProvider->AddLc (dtamIt->logicalChannelIdentity,
+                                    lcConfig,
+                                    rlc->GetLteMacSapUser ());
+        }
+      else
+        {
+          NS_LOG_INFO ("request to modify existing DRBID (skipping as currently not implemented)");
+          Ptr<LteDataRadioBearerInfo> rbInfo = drbMapIt->second;
+          // would need to modify rbInfo, and then propagate changes to the MAC
         }
     }
-  NS_ASSERT_MSG (found , " Unable to find eNB with CellId =" << targetCellId);
-  m_enbRrc = enbDev->GetObject<LteEnbRrc> ();
+  
+  std::list<uint8_t>::iterator dtdmIt;
+  for (dtdmIt = rrcd.drbToReleaseList.begin ();
+       dtdmIt != rrcd.drbToReleaseList.end ();
+       ++dtdmIt)
+    {
+      uint8_t drbid = *dtdmIt;
+      NS_LOG_INFO (this << " IMSI " << m_imsi << " releasing DRB " << (uint32_t) drbid << drbid);
+      std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it =   m_drbMap.find (drbid);
+      NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with given lcid");
+      m_drbMap.erase (it);      
+      m_bid2DrbidMap.erase (drbid);
+    }
+}
+
+
+void 
+LteUeRrc::StartConnection ()
+{
+  NS_LOG_FUNCTION (this);
+  m_connectionPending = false;
+  SwitchToState (IDLE_RANDOM_ACCESS);        
+  m_cmacSapProvider->StartContentionBasedRandomAccessProcedure ();
+}
+
+void 
+LteUeRrc::LeaveConnectedMode ()
+{
+  NS_LOG_FUNCTION (this << m_imsi);
+  m_asSapUser->NotifyConnectionReleased ();
+  m_cmacSapProvider->RemoveLc (1);
+  std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it;
+  for (it = m_drbMap.begin (); it != m_drbMap.end (); ++it)
+    {
+      m_cmacSapProvider->RemoveLc (it->second->m_logicalChannelIdentity);
+    }
+  m_drbMap.clear ();
+  m_bid2DrbidMap.clear ();
+  m_srb1 = 0;
+  SwitchToState (IDLE_CAMPED_NORMALLY);
+}
+
 
-  DoForceCampedOnEnb (enbDev, targetCellId);
-  m_rnti = newRnti;
-  m_cmacSapProvider->ConfigureUe (m_rnti);
-  m_cphySapProvider->SetRnti (m_rnti);
-  m_enbRrc->DoRecvConnectionReconfigurationCompleted (m_rnti);
+uint8_t 
+LteUeRrc::Bid2Drbid (uint8_t bid)
+{
+  std::map<uint8_t, uint8_t>::iterator it = m_bid2DrbidMap.find (bid);
+  NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid);
+  return it->second;
+}
+
+
+void 
+LteUeRrc::SwitchToState (State newState)
+{
+  NS_LOG_FUNCTION (this << newState);
+  State oldState = m_state;
+  m_state = newState;
+  NS_LOG_INFO ("IMSI " << m_imsi << " RNTI " << m_rnti << " UeRrc " << ToString (oldState) << " --> " << ToString (newState));
+  m_stateTransitionCallback (oldState, newState);
+
+  switch (newState)
+    {
+    case IDLE_CELL_SELECTION:
+      break;
+
+    case IDLE_WAIT_SYSTEM_INFO:
+      break;
+
+    case IDLE_CAMPED_NORMALLY:
+      if (m_connectionPending)
+        {
+          StartConnection ();
+        }
+      break;
+
+    case IDLE_RANDOM_ACCESS:
+      break;
+
+    case IDLE_CONNECTING:
+      break;
+ 
+    case CONNECTED_NORMALLY:
+      break;
+
+    case CONNECTED_REESTABLISHING:
+      break;
+
+    case CONNECTED_HANDOVER:
+      break;
+ 
+    default:
+      break;
+    }
+}
   
-}
+
+    
   
 } // namespace ns3
 
--- a/src/lte/model/lte-ue-rrc.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.h	Tue Oct 30 16:02:07 2012 +0100
@@ -27,6 +27,8 @@
 #include <ns3/lte-pdcp-sap.h>
 #include <ns3/lte-as-sap.h>
 #include <ns3/lte-ue-cphy-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <ns3/traced-callback.h>
 
 #include <map>
 
@@ -36,7 +38,8 @@
 class LteMacSapProvider;
 class LteUeCmacSapUser;
 class LteUeCmacSapProvider;
-class LteRadioBearerInfo;
+class LteDataRadioBearerInfo;
+class LteSignalingRadioBearerInfo;
 class LteEnbRrc;
 
 /**
@@ -51,8 +54,28 @@
   friend class LtePdcpSpecificLtePdcpSapUser<LteUeRrc>;
   friend class MemberLteAsSapProvider<LteUeRrc>;
   friend class MemberLteUeCphySapUser<LteUeRrc>;
+  friend class MemberLteUeRrcSapProvider<LteUeRrc>;
 
 public:
+
+  /**
+   * The states of the UE RRC entity
+   * 
+   */
+  enum State
+    {
+      IDLE_CELL_SELECTION = 0,
+      IDLE_WAIT_SYSTEM_INFO,
+      IDLE_CAMPED_NORMALLY,
+      IDLE_RANDOM_ACCESS,
+      IDLE_CONNECTING,
+      CONNECTED_NORMALLY,
+      CONNECTED_REESTABLISHING,
+      CONNECTED_HANDOVER,
+      NUM_STATES
+    };
+
+
   /**
    * create an RRC instance for use within an ue
    *
@@ -67,7 +90,10 @@
 
 
   // inherited from Object
+private:
+  virtual void DoStart (void);
   virtual void DoDispose (void);
+public:
   static TypeId GetTypeId (void);
 
 
@@ -99,6 +125,21 @@
    */
   LteUeCmacSapUser* GetLteUeCmacSapUser ();
 
+
+  /**
+   * set the RRC SAP this RRC should interact with
+   *
+   * \param s the RRC SAP User to be used by this RRC
+   */
+  void SetLteUeRrcSapUser (LteUeRrcSapUser * s);
+
+  /**
+   *
+   *
+   * \return s the RRC SAP Provider interface offered to the MAC by this RRC
+   */
+  LteUeRrcSapProvider* GetLteUeRrcSapProvider ();
+
   /**
    * set the MAC SAP provider. The ue RRC does not use this
    * directly, but it needs to provide it to newly created RLC instances.
@@ -130,37 +171,6 @@
   void SetImsi (uint64_t imsi);
 
   /**
-   * Set UE RRC parameters
-   *
-   * \param rnti  C-RNTI of the UE
-   * \param cellId Serving cell identifier
-   */
-  void ConfigureUe (uint16_t rnti, uint16_t cellId);
-
-
-
-  /**
-   * Setup a new radio bearer for the given user
-   *
-   * \param bearer the characteristics of the bearer to be activated
-   * \param rlcTypeId the TypeId identifying the type of RLC to be used for this bearer.
-   * \param lcid the logical channel id allocated for this bearer by the eNB
-   * \param tft the Traffic Flow Template identifying this bearer
-   *
-   */
-  void SetupRadioBearer (EpsBearer bearer, TypeId rlcTypeId, uint8_t lcid);
-
-
-  /**
-   *
-   * Release the given radio bearer
-   *
-   * \param lcId the logical channel id of the bearer to be released
-   */
-  void ReleaseRadioBearer (uint8_t lcId);
-
-
-  /**
    *
    * \return the C-RNTI of the user
    */
@@ -173,46 +183,79 @@
    */
   uint16_t GetCellId () const;
 
-  /**
-   *
-   * @return a vector with the allocated LCID
+
+  /** 
+   * \return the uplink bandwidth in RBs
    */
-  std::vector<uint8_t> GetLcIdVector ();
-
+  uint8_t GetUlBandwidth () const;
 
   /** 
-   * reception of the RRC ConnectionReconfiguration message
-   *
+   * \return the downlink bandwidth in RBs
+   */
+  uint8_t GetDlBandwidth () const;
+
+  /** 
+   * \return the downlink carrier frequency (EARFCN)
    */
-  void DoRecvConnectionSetup (LteUeConfig_t params);
+  uint16_t GetDlEarfcn () const;
+
+  /** 
+   * \return the uplink carrier frequency (EARFCN)
+   */
+  uint16_t GetUlEarfcn () const;
 
   /** 
-   * reception of the RRC ConnectionReconfiguration message
-   *
+   * 
+   * \return the current state
    */
-  void DoRecvConnectionReconfiguration (LteUeConfig_t params);
-
+  State GetState ();
 
   /** 
-   * Execute a handover
+   * 
    * 
-   * \param targetCellId 
-   * \param newRnti 
+   * \param val true if RLC SM is to be used, false if RLC UM/AM are to be used
    */
-  void DoRecvConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti);
-  
+  void SetUseRlcSm (bool val);
+
+
 private:
 
+
   // PDCP SAP methods
-  void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
+  void DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params);
 
   // CMAC SAP methods
-  void DoLcConfigCompleted ();
-
+  void DoSetTemporaryCellRnti (uint16_t rnti);
+  void DoNotifyRandomAccessSuccessful ();
+  void DoNotifyRandomAccessFailed ();
+ 
   // LTE AS SAP methods
   void DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
   void DoConnect ();
   void DoSendData (Ptr<Packet> packet, uint8_t bid);
+  void DoDisconnect ();
+
+  // CPHY SAP methods
+  void DoRecvMasterInformationBlock (LteRrcSap::MasterInformationBlock msg);
+
+  // RRC SAP methods
+  void DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg);
+  void DoRecvSystemInformation (LteRrcSap::SystemInformation msg);
+  void DoRecvRrcConnectionSetup (LteRrcSap::RrcConnectionSetup msg);
+  void DoRecvRrcConnectionReconfiguration (LteRrcSap::RrcConnectionReconfiguration msg);
+  void DoRecvRrcConnectionReestablishment (LteRrcSap::RrcConnectionReestablishment msg);
+  void DoRecvRrcConnectionReestablishmentReject (LteRrcSap::RrcConnectionReestablishmentReject msg);
+  void DoRecvRrcConnectionRelease (LteRrcSap::RrcConnectionRelease msg);
+
+ 
+  // internal methods
+  void ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd);
+  void StartConnection ();
+  void LeaveConnectedMode ();
+  uint8_t Bid2Drbid (uint8_t bid);
+  void SwitchToState (State s);
+
+  std::map<uint8_t, uint8_t> m_bid2DrbidMap;
 
   LteUeCphySapUser* m_cphySapUser;
   LteUeCphySapProvider* m_cphySapProvider;
@@ -220,20 +263,41 @@
   LteUeCmacSapUser* m_cmacSapUser;
   LteUeCmacSapProvider* m_cmacSapProvider;
 
+  LteUeRrcSapUser* m_rrcSapUser;
+  LteUeRrcSapProvider* m_rrcSapProvider;
+
   LteMacSapProvider* m_macSapProvider;
   LtePdcpSapUser* m_pdcpSapUser;
   
   LteAsSapProvider* m_asSapProvider;
   LteAsSapUser* m_asSapUser;
 
+  State m_state;
+
   uint64_t m_imsi;
   uint16_t m_rnti;
   uint16_t m_cellId;
 
-  std::map <uint8_t, Ptr<LteRadioBearerInfo> > m_rbMap;  
+  Ptr<LteSignalingRadioBearerInfo> m_srb0;
+  Ptr<LteSignalingRadioBearerInfo> m_srb1;
+  std::map <uint8_t, Ptr<LteDataRadioBearerInfo> > m_drbMap;
+  
+  bool m_useRlcSm;
+
+  uint8_t m_lastRrcTransactionIdentifier;
 
-  Ptr<LteEnbRrc> m_enbRrc; // wild hack, might go away in future versions
-  
+  uint8_t m_dlBandwidth; /**< downlink bandwidth in RBs */
+  uint8_t m_ulBandwidth; /**< uplink bandwidth in RBs */
+
+  uint16_t m_dlEarfcn;  /**< downlink carrier frequency */
+  uint16_t m_ulEarfcn;  /**< uplink carrier frequency */
+
+  TracedCallback<State, State> m_stateTransitionCallback;
+
+  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_receivedSib2; /**< true if SIB2 was received for the current cell  */
+
 };
 
 
--- a/src/lte/model/pf-ff-mac-scheduler.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/pf-ff-mac-scheduler.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -1021,28 +1021,37 @@
   std::map <uint16_t,uint32_t>::iterator it;
   
   for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
-  {
-    if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
     {
-      // buffer status report
-      // note that we only consider LCG 0, the other three LCGs are neglected
-      // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
-      uint16_t rnti = params.m_macCeList.at (i).m_rnti;
-      it = m_ceBsrRxed.find (rnti);
-      if (it == m_ceBsrRxed.end ())
-      {
-        // create the new entry
-        uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
-        int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
-        m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer)); 
-      }
-      else
-      {
-        // update the buffer size value
-        (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
-      }
+      if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
+        {
+          // buffer status report          
+          // note that this scheduler does not differentiate the
+          // allocation according to which LCGs have more/less bytes
+          // to send.
+          // Hence the BSR of different LCGs are just summed up to get
+          // a total queue size that is used for allocation purposes.
+
+          uint32_t buffer = 0;
+          for (uint8_t lcg = 0; lcg < 4; ++lcg)
+            {
+              uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
+              buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
+            }
+
+          uint16_t rnti = params.m_macCeList.at (i).m_rnti;
+          it = m_ceBsrRxed.find (rnti);
+          if (it == m_ceBsrRxed.end ())
+            {
+              // create the new entry
+              m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
+            }
+          else
+            {
+              // update the buffer size value
+              (*it).second = buffer;
+            }
+        }
     }
-  }
   
   return;
 }
--- a/src/lte/model/rr-ff-mac-scheduler.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/rr-ff-mac-scheduler.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -415,11 +415,11 @@
   m_rlcBufferReq.sort (SortRlcBufferReq);
   int nflows = 0;
   int nTbs = 0;
-  std::map <uint16_t,uint8_t> lcActivesPerRnti;
+  std::map <uint16_t,uint8_t> lcActivesPerRnti; // tracks how many active LCs per RNTI there are
   std::map <uint16_t,uint8_t>::iterator itLcRnti;
   for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
     {
-//       NS_LOG_INFO (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
+      NS_LOG_LOGIC (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
       // remove old entries of this UE-LC
       if ( ((*it).m_rlcTransmissionQueueSize > 0)
            || ((*it).m_rlcRetransmissionQueueSize > 0)
@@ -542,16 +542,24 @@
       int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
       NS_LOG_DEBUG (this << " DL - Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " <<  rbgAllocated * rbgSize << "..." << (rbgAllocated* rbgSize) + (rbgPerTb * rbgSize) - 1 << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " layers " << nLayer);
       uint16_t rlcPduSize = tbSize / lcNum;
-      for (int i = 0; i < lcNum ; i++)
+      while (lcNum>0)
         {
-          for (uint8_t j = 0; j < nLayer; j++)
+          if ( ((*it).m_rlcTransmissionQueueSize > 0)
+               || ((*it).m_rlcRetransmissionQueueSize > 0)
+               || ((*it).m_rlcStatusPduSize > 0) )
             {
-              RlcPduListElement_s newRlcEl;
-              newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
-//               NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
-              newRlcEl.m_size = rlcPduSize;
-              UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
-              newRlcPduLe.push_back (newRlcEl);
+              std::vector <struct RlcPduListElement_s> newRlcPduLe;
+              for (uint8_t j = 0; j < nLayer; j++)
+                {
+                  RlcPduListElement_s newRlcEl;
+                  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
+                  //               NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
+                  newRlcEl.m_size = rlcPduSize;
+                  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
+                  newRlcPduLe.push_back (newRlcEl);
+                }
+              newEl.m_rlcPduList.push_back (newRlcPduLe);
+              lcNum--;
             }
           it++;
           if (it == m_rlcBufferReq.end ())
@@ -827,22 +835,31 @@
     {
       if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
         {
-          // buffer status report
-          // note that we only consider LCG 0, the other three LCGs are neglected
-          // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
+          // buffer status report          
+          // note that this scheduler does not differentiate the
+          // allocation according to which LCGs have more/less bytes
+          // to send.
+          // Hence the BSR of different LCGs are just summed up to get
+          // a total queue size that is used for allocation purposes.
+
+          uint32_t buffer = 0;
+          for (uint8_t lcg = 0; lcg < 4; ++lcg)
+            {
+              uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
+              buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
+            }
+
           uint16_t rnti = params.m_macCeList.at (i).m_rnti;
           it = m_ceBsrRxed.find (rnti);
           if (it == m_ceBsrRxed.end ())
             {
               // create the new entry
-              uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
-              int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
               m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
             }
           else
             {
               // update the buffer size value
-              (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
+              (*it).second = buffer;
             }
         }
     }
--- a/src/lte/test/epc-test-s1u-uplink.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/epc-test-s1u-uplink.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -19,7 +19,7 @@
  * The original version of UdpClient is by  Amine Ismail
  * <amine.ismail@sophia.inria.fr> <amine.ismail@udcast.com> 
  * The rest of the code (including modifying UdpClient into
- *  LteRadioBearerTagUdpClient) is by Nicola Baldo <nbaldo@cttc.es> 
+ *  EpsBearerTagUdpClient) is by Nicola Baldo <nbaldo@cttc.es> 
  */
 
 
@@ -41,7 +41,7 @@
 #include <ns3/ipv4-interface.h>
 #include <ns3/mac48-address.h>
 #include "ns3/seq-ts-header.h"
-#include "ns3/lte-radio-bearer-tag.h"
+#include "ns3/eps-bearer-tag.h"
 #include "ns3/arp-cache.h"
 #include "ns3/boolean.h"
 #include "ns3/uinteger.h"
@@ -56,23 +56,23 @@
 
 /*
  * A Udp client. Sends UDP packet carrying sequence number and time
- * stamp but also including the LteRadioBearerTag. This tag is normally
+ * stamp but also including the EpsBearerTag. This tag is normally
  * generated by the LteEnbNetDevice when forwarding packet in the
  * uplink. But in this test we don't have the LteEnbNetDevice, because
  * we test the S1-U interface with simpler devices to make sure it
  * just works.
  * 
  */
-class LteRadioBearerTagUdpClient : public Application
+class EpsBearerTagUdpClient : public Application
 {
 public:
   static TypeId
   GetTypeId (void);
 
-  LteRadioBearerTagUdpClient ();
-  LteRadioBearerTagUdpClient (uint16_t rnti, uint8_t lcid);
+  EpsBearerTagUdpClient ();
+  EpsBearerTagUdpClient (uint16_t rnti, uint8_t bid);
 
-  virtual ~LteRadioBearerTagUdpClient ();
+  virtual ~EpsBearerTagUdpClient ();
 
   /**
    * \brief set the remote address and port
@@ -103,49 +103,49 @@
   EventId m_sendEvent;
 
   uint16_t m_rnti;
-  uint8_t m_lcid;
+  uint8_t m_bid;
 
 };
 
 
 
 TypeId
-LteRadioBearerTagUdpClient::GetTypeId (void)
+EpsBearerTagUdpClient::GetTypeId (void)
 {
-  static TypeId tid = TypeId ("ns3::LteRadioBearerTagUdpClient")
+  static TypeId tid = TypeId ("ns3::EpsBearerTagUdpClient")
     .SetParent<Application> ()
-    .AddConstructor<LteRadioBearerTagUdpClient> ()
+    .AddConstructor<EpsBearerTagUdpClient> ()
     .AddAttribute ("MaxPackets",
                    "The maximum number of packets the application will send",
                    UintegerValue (100),
-                   MakeUintegerAccessor (&LteRadioBearerTagUdpClient::m_count),
+                   MakeUintegerAccessor (&EpsBearerTagUdpClient::m_count),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("Interval",
                    "The time to wait between packets", TimeValue (Seconds (1.0)),
-                   MakeTimeAccessor (&LteRadioBearerTagUdpClient::m_interval),
+                   MakeTimeAccessor (&EpsBearerTagUdpClient::m_interval),
                    MakeTimeChecker ())
     .AddAttribute (
       "RemoteAddress",
       "The destination Ipv4Address of the outbound packets",
       Ipv4AddressValue (),
-      MakeIpv4AddressAccessor (&LteRadioBearerTagUdpClient::m_peerAddress),
+      MakeIpv4AddressAccessor (&EpsBearerTagUdpClient::m_peerAddress),
       MakeIpv4AddressChecker ())
     .AddAttribute ("RemotePort", "The destination port of the outbound packets",
                    UintegerValue (100),
-                   MakeUintegerAccessor (&LteRadioBearerTagUdpClient::m_peerPort),
+                   MakeUintegerAccessor (&EpsBearerTagUdpClient::m_peerPort),
                    MakeUintegerChecker<uint16_t> ())
     .AddAttribute ("PacketSize",
                    "Size of packets generated. The minimum packet size is 12 bytes which is the size of the header carrying the sequence number and the time stamp.",
                    UintegerValue (1024),
-                   MakeUintegerAccessor (&LteRadioBearerTagUdpClient::m_size),
+                   MakeUintegerAccessor (&EpsBearerTagUdpClient::m_size),
                    MakeUintegerChecker<uint32_t> ())
   ;
   return tid;
 }
 
-LteRadioBearerTagUdpClient::LteRadioBearerTagUdpClient ()
+EpsBearerTagUdpClient::EpsBearerTagUdpClient ()
   : m_rnti (0),
-    m_lcid (0)
+    m_bid (0)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_sent = 0;
@@ -153,9 +153,9 @@
   m_sendEvent = EventId ();
 }
 
-LteRadioBearerTagUdpClient::LteRadioBearerTagUdpClient (uint16_t rnti, uint8_t lcid)
+EpsBearerTagUdpClient::EpsBearerTagUdpClient (uint16_t rnti, uint8_t bid)
   : m_rnti (rnti),
-    m_lcid (lcid)
+    m_bid (bid)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_sent = 0;
@@ -163,27 +163,27 @@
   m_sendEvent = EventId ();
 }
 
-LteRadioBearerTagUdpClient::~LteRadioBearerTagUdpClient ()
+EpsBearerTagUdpClient::~EpsBearerTagUdpClient ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
 void
-LteRadioBearerTagUdpClient::SetRemote (Ipv4Address ip, uint16_t port)
+EpsBearerTagUdpClient::SetRemote (Ipv4Address ip, uint16_t port)
 {
   m_peerAddress = ip;
   m_peerPort = port;
 }
 
 void
-LteRadioBearerTagUdpClient::DoDispose (void)
+EpsBearerTagUdpClient::DoDispose (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
   Application::DoDispose ();
 }
 
 void
-LteRadioBearerTagUdpClient::StartApplication (void)
+EpsBearerTagUdpClient::StartApplication (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
 
@@ -196,18 +196,18 @@
     }
 
   m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
-  m_sendEvent = Simulator::Schedule (Seconds (0.0), &LteRadioBearerTagUdpClient::Send, this);
+  m_sendEvent = Simulator::Schedule (Seconds (0.0), &EpsBearerTagUdpClient::Send, this);
 }
 
 void
-LteRadioBearerTagUdpClient::StopApplication ()
+EpsBearerTagUdpClient::StopApplication ()
 {
   NS_LOG_FUNCTION_NOARGS ();
   Simulator::Cancel (m_sendEvent);
 }
 
 void
-LteRadioBearerTagUdpClient::Send (void)
+EpsBearerTagUdpClient::Send (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
   NS_ASSERT (m_sendEvent.IsExpired ());
@@ -216,7 +216,7 @@
   Ptr<Packet> p = Create<Packet> (m_size-(8+4)); // 8+4 : the size of the seqTs header
   p->AddHeader (seqTs);
 
-  LteRadioBearerTag tag (m_rnti, m_lcid);
+  EpsBearerTag tag (m_rnti, m_bid);
   p->AddPacketTag (tag);
 
   if ((m_socket->Send (p)) >= 0)
@@ -235,7 +235,7 @@
 
   if (m_sent < m_count)
     {
-      m_sendEvent = Simulator::Schedule (m_interval, &LteRadioBearerTagUdpClient::Send, this);
+      m_sendEvent = Simulator::Schedule (m_interval, &EpsBearerTagUdpClient::Send, this);
     }
 }
 
@@ -248,7 +248,7 @@
   uint32_t numPkts;
   uint32_t pktSize;
   uint16_t rnti;
-  uint8_t lcid;
+  uint8_t bid;
  
   Ptr<PacketSink> serverApp;
   Ptr<Application> clientApp;
@@ -258,7 +258,7 @@
   : numPkts (n),
     pktSize (s),
     rnti (r),
-    lcid (l)
+    bid (l)
 {
 }
 
@@ -410,7 +410,7 @@
           enbit->ues[u].serverApp = sinkApp.Get (0)->GetObject<PacketSink> ();
           
           Time interPacketInterval = Seconds (0.01);
-          Ptr<LteRadioBearerTagUdpClient> client = CreateObject<LteRadioBearerTagUdpClient> (enbit->ues[u].rnti, enbit->ues[u].lcid);
+          Ptr<EpsBearerTagUdpClient> client = CreateObject<EpsBearerTagUdpClient> (enbit->ues[u].rnti, enbit->ues[u].bid);
           client->SetAttribute ("RemoteAddress", Ipv4AddressValue (internetNodesIpIfaceContainer.GetAddress (1)));
           client->SetAttribute ("RemotePort", UintegerValue (udpSinkPort));          
           client->SetAttribute ("MaxPackets", UintegerValue (enbit->ues[u].numPkts));
--- a/src/lte/test/lte-test-entities.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-entities.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -156,10 +156,10 @@
  */
 
 void
-LteTestRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params)
+LteTestRrc::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
 {
-  NS_LOG_FUNCTION (this << params.rrcPdu->GetSize ());
-  Ptr<Packet> p = params.rrcPdu;
+  NS_LOG_FUNCTION (this << params.pdcpSdu->GetSize ());
+  Ptr<Packet> p = params.pdcpSdu;
 //   NS_LOG_LOGIC ("PDU received = " << (*p));
 
   uint32_t dataLen = p->GetSize ();
@@ -193,12 +193,12 @@
   m_txBytes += m_pduSize;
   m_txLastTime = Simulator::Now ();
 
-  LtePdcpSapProvider::TransmitRrcPduParameters p;
+  LtePdcpSapProvider::TransmitPdcpSduParameters p;
   p.rnti = 1111;
   p.lcid = 222;
-  p.rrcPdu = Create<Packet> (m_pduSize);
+  p.pdcpSdu = Create<Packet> (m_pduSize);
 
-  Simulator::ScheduleNow (&LtePdcpSapProvider::TransmitRrcPdu, m_pdcpSapProvider, p);
+  Simulator::ScheduleNow (&LtePdcpSapProvider::TransmitPdcpSdu, m_pdcpSapProvider, p);
   m_nextPdu = Simulator::Schedule (m_arrivalTime, &LteTestRrc::Start, this);
 //   Simulator::Run ();
 }
@@ -219,15 +219,15 @@
   m_txPdus++;
   m_txBytes += dataToSend.length ();
 
-  LtePdcpSapProvider::TransmitRrcPduParameters p;
+  LtePdcpSapProvider::TransmitPdcpSduParameters p;
   p.rnti = 1111;
   p.lcid = 222;
 
   NS_LOG_LOGIC ("Data(" << dataToSend.length () << ") = " << dataToSend.data ());
-  p.rrcPdu = Create<Packet> ((uint8_t *) dataToSend.data (), dataToSend.length ());
+  p.pdcpSdu = Create<Packet> ((uint8_t *) dataToSend.data (), dataToSend.length ());
 
-  NS_LOG_LOGIC ("Packet(" << p.rrcPdu->GetSize () << ")");
-  Simulator::Schedule (at, &LtePdcpSapProvider::TransmitRrcPdu, m_pdcpSapProvider, p);
+  NS_LOG_LOGIC ("Packet(" << p.pdcpSdu->GetSize () << ")");
+  Simulator::Schedule (at, &LtePdcpSapProvider::TransmitPdcpSdu, m_pdcpSapProvider, p);
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -659,7 +659,7 @@
 {
   EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;   
   response.rnti = request.rnti;
-  response.lcid = 1;      
+  response.bid = 1;      
   response.teid = request.teid;
   m_s1SapProvider->S1BearerSetupRequest (response);
 }
--- a/src/lte/test/lte-test-entities.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-entities.h	Tue Oct 30 16:02:07 2012 +0100
@@ -84,7 +84,7 @@
 
   private:
     // Interface forwarded by LtePdcpSapUser
-    virtual void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
+    virtual void DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params);
 
     LtePdcpSapUser* m_pdcpSapUser;
     LtePdcpSapProvider* m_pdcpSapProvider;
--- a/src/lte/test/lte-test-interference.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-interference.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -119,9 +119,6 @@
   Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
   Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
-//   lteHelper->EnableLogComponents ();
-  lteHelper->EnableMacTraces ();
-  lteHelper->EnableRlcTraces ();
   lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
 
   // Create Nodes: eNodeB and UE
@@ -190,7 +187,7 @@
 
 
   // same as above for eNB2 and UE2
-  
+
   Ptr<LtePhy> ue2Phy = ueDevs2.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
   Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> (ue2Phy);
   ue2Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr2);
@@ -205,10 +202,10 @@
   Config::Connect ("/NodeList/1/DeviceList/0/LteEnbMac/UlScheduling",
                    MakeBoundCallback (&LteTestUlSchedulingCallback, this));
 
+// need to allow for RRC connection establishment + SRS
+  Simulator::Stop (Seconds (0.040));
+  Simulator::Run ();
 
-  Simulator::Stop (Seconds (0.020));
-  Simulator::Run ();
-  
 
   double dlSinr1Db = 10.0 * log10 (testDlSinr1->GetSinr ()->operator[] (0));
   NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr1Db, m_dlSinrDb, 0.01, "Wrong SINR in DL! (eNB1 --> UE1)");
@@ -218,12 +215,12 @@
 
   double dlSinr2Db = 10.0 * log10 (testDlSinr2->GetSinr ()->operator[] (0));
   NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr2Db, m_dlSinrDb, 0.01, "Wrong SINR in DL! (eNB2 --> UE2)");
-  
+
   double ulSinr2Db = 10.0 * log10 (testUlSinr2->GetSinr ()->operator[] (0));
   NS_TEST_ASSERT_MSG_EQ_TOL (ulSinr2Db, m_ulSinrDb, 0.01, "Wrong SINR in UL!  (UE2 --> eNB2)");
 
   Simulator::Destroy ();
- 
+
 }
 
 
@@ -231,14 +228,10 @@
 LteInterferenceTestCase::DlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
                                        uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2)
 {
-  /**
-   * Note:
-   *    For first 4 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
-   *    because CQI feedback is still not available at the eNB.
-   */
-  if ( (frameNo > 1) || (subframeNo > 9) )
+  // need to allow for RRC connection establishment + CQI feedback reception
+  if (Simulator::Now () > MilliSeconds (35))
     {
-      NS_TEST_ASSERT_MSG_EQ ((uint16_t)mcsTb1, m_dlMcs, "Wrong DL MCS ");
+      NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcsTb1, (uint32_t)m_dlMcs, "Wrong DL MCS ");
     }
 }
 
@@ -246,14 +239,10 @@
 LteInterferenceTestCase::UlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
                                        uint8_t mcs, uint16_t sizeTb)
 {
-  /**
-   * Note:
-   *    For first 5 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
-   *    because CQI feedback is still not available at the eNB.
-   */
-  if ( (frameNo > 1) && (subframeNo > 6) )
+  // need to allow for RRC connection establishment + SRS transmission
+  if (Simulator::Now () > MilliSeconds (35))
     {
-      NS_TEST_ASSERT_MSG_EQ ((uint16_t)mcs, m_ulMcs, "Wrong UL MCS");
+      NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcs, (uint32_t)m_ulMcs, "Wrong UL MCS");
     }
 }
 
--- a/src/lte/test/lte-test-link-adaptation.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-link-adaptation.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -201,12 +201,12 @@
   // It will be used to test that the SNR is as intended
   Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
   Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
-  uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testSinr);
+  uePhy->GetDownlinkSpectrumPhy ()->AddCtrlSinrChunkProcessor (testSinr);
 
   Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
                    MakeBoundCallback (&LteTestDlSchedulingCallback, this));
 
-  Simulator::Stop (Seconds (0.007));
+  Simulator::Stop (Seconds (0.026));
   Simulator::Run ();
 
   double calculatedSinrDb = 10.0 * log10 (testSinr->GetSinr ()->operator[] (0));
@@ -229,10 +229,11 @@
 
   /**
    * Note:
-   *    For first 4 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
-   *    because CQI feedback is still not available at the eNB.
+   * the MCS can only be properly evaluated after:
+   * RRC connection has been completed and
+   * CQI feedback is available at the eNB.
    */
-  if ( (frameNo > 1) || (subframeNo > 8) )
+  if (Simulator::Now ().GetSeconds () > 0.024)
     {
       NS_LOG_INFO (m_snrDb << "\t" << m_mcsIndex << "\t" << (uint16_t)mcsTb1);
 
--- a/src/lte/test/lte-test-mimo.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-mimo.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -168,13 +168,13 @@
   uePhy->SetAttribute ("TxPower", DoubleValue (23.0));
   uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
   
-
-  lteHelper->EnableRlcTraces ();
+  // need to allow for RRC connection establishment + SRS before enabling traces
+  Simulator::Schedule (Seconds (0.050), &LteHelper::EnableRlcTraces, lteHelper);
   lteHelper->EnableMacTraces ();
   double simulationTime = 0.401;
   double tolerance = 0.1;
   
-  uint8_t rnti = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti ();
+  uint8_t rnti = 1;
   Ptr<LteEnbNetDevice> enbNetDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
   
   PointerValue ptrval;
@@ -212,7 +212,6 @@
   Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
   rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.1)));
 
-
   /**
    * Check that the assignation is done in a RR fashion
    */
@@ -223,8 +222,7 @@
       NS_LOG_INFO ("\t test with user at distance " << m_dist << " time " << sampleTime);
       // get the imsi
       uint64_t imsi = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetImsi ();
-      // get the lcId
-      uint8_t lcId = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 3;
       Time t = Seconds (sampleTime);
       Simulator::Schedule(t, &LenaMimoTestCase::GetRlcBufferSample, this, rlcStats, imsi, lcId);
       sampleTime += 0.1;
--- a/src/lte/test/lte-test-pathloss-model.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-pathloss-model.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -158,10 +158,18 @@
     //     double sinrDb = txPowerDbm- noisePowerDbm - receiverNoiseFigureDb - loss[i];
     double sinrDb = 10*log10(sinrLin);
     NS_LOG_INFO (" Ptx " << txPowerDbm << " Pn " << noisePowerDbm << " Fn " << receiverNoiseFigureDb << " Pl " << loss[i] << " dist " << dist[i]);
+
+    int mcs = -1;
+    int numSnrEfficiencyMcsEntries = sizeof (snrEfficiencyMcs) / sizeof (SnrEfficiencyMcs);
+    for (int j = 0; j < numSnrEfficiencyMcsEntries && snrEfficiencyMcs[j].snrDb < sinrDb; ++j)
+      {
+        mcs = snrEfficiencyMcs[j].mcsIndex;
+      }
+
     std::ostringstream name;
     name << " snr= " << sinrDb << " dB, "
-    << " mcs= " << snrEfficiencyMcs[i].mcsIndex;
-    AddTestCase (new LtePathlossModelSystemTestCase (name.str (),  sinrDb, dist[i], snrEfficiencyMcs[i].mcsIndex));
+         << " mcs= " << snrEfficiencyMcs[i].mcsIndex;
+    AddTestCase (new LtePathlossModelSystemTestCase (name.str (),  sinrDb, dist[i], mcs));
   }
 
 
@@ -198,17 +206,7 @@
   /**
   * Simulation Topology
   */
-//   LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("SingleModelSpectrumChannel", LOG_LEVEL_ALL);
-  LogComponentEnable ("BuildingsPropagationLossModel", LOG_LEVEL_ALL);
-  LogComponentEnable ("HybridBuildingsPropagationLossModel", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteHelper", LOG_LEVEL_ALL);
 
-//   
   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
   //   lteHelper->EnableLogComponents ();
   lteHelper->EnableMacTraces ();
@@ -272,12 +270,12 @@
   // It will be used to test that the SNR is as intended
   //Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
   Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
-  uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testSinr);
+  uePhy->GetDownlinkSpectrumPhy ()->AddCtrlSinrChunkProcessor (testSinr);
    
 //   Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
 //                    MakeBoundCallback (&LteTestPathlossDlSchedCallback, this));
                    
-  Simulator::Stop (Seconds (0.005));
+  Simulator::Stop (Seconds (0.035));
   Simulator::Run ();
   
   double calculatedSinrDb = 10.0 * log10 (testSinr->GetSinr ()->operator[] (0));
@@ -299,12 +297,9 @@
     NS_LOG_INFO ("SNR\tRef_MCS\tCalc_MCS");
   }
   
-  /**
-  * Note:
-  *    For first 4 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
-  *    because CQI feedback is still not available at the eNB.
-  */
-  if ( (frameNo > 1) || (subframeNo > 4) )
+  
+  // need to allow for RRC connection establishment + SRS transmission
+  if (Simulator::Now () > MilliSeconds (21))
   {
     NS_LOG_INFO (m_snrDb << "\t" << m_mcsIndex << "\t" << (uint16_t)mcsTb1);
     
--- a/src/lte/test/lte-test-pf-ff-mac-scheduler.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-pf-ff-mac-scheduler.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
  *
  * 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
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author: Marco Miozzo <marco.miozzo@cttc.es>,
+ * Author: Marco Miozzo <marco.miozzo@cttc.es>
  *         Nicola Baldo <nbaldo@cttc.es>
  */
 
@@ -207,44 +207,17 @@
 void
 LenaPfFfMacSchedulerTestCase1::DoRun (void)
 {
+  NS_LOG_FUNCTION (this << m_nUser << m_nLc << m_dist);
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));  
   Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
   Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
-  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
-  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));  LogComponentDisableAll (LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
-//     LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
-//
-//   LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
-
-  //   LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
-  // 
-  //   LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
-  // 
-  //   LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
-
-//     LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
-  LogComponentEnable ("LenaTestPfFfMacCheduler", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
-//     LogComponentEnable ("RadioBearerStatsCalculator", LOG_LEVEL_ALL);
 
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
    */
 
+
   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
   
   lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
@@ -276,7 +249,8 @@
   enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
   EpsBearer bearer (q);
   lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
-
+  
+ 
   Ptr<LteEnbNetDevice> lteEnbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
   Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy ();
   enbPhy->SetAttribute ("TxPower", DoubleValue (30.0));
@@ -293,14 +267,18 @@
       uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
     }
 
-  lteHelper->EnableRlcTraces ();
 
-  double simulationTime = 1.0;
+  double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS 
+  double statsDuration = 0.4;
   double tolerance = 0.1;
-  Simulator::Stop (Seconds (simulationTime));
+  Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001));
 
+  lteHelper->EnableMacTraces ();
+  Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnableRlcTraces, lteHelper);
   Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
-  rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (simulationTime)));
+  rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
+  rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration)));
+
 
   Simulator::Run ();
 
@@ -313,10 +291,9 @@
     {
       // get the imsi
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
-      // get the lcId
-      uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 3;
       dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
-      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << "  thr " << (double)dlDataRxed.at (i) / simulationTime << " ref " << m_thrRefDl);
+      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << "  thr " << (double)dlDataRxed.at (i) / statsDuration << " ref " << m_thrRefDl);
     }
   /**
   * Check that the assignation is done in a "proportional fair" manner among users
@@ -326,7 +303,7 @@
   */
   for (int i = 0; i < m_nUser; i++)
     {
-      NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / simulationTime, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
+      NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / statsDuration, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
     }
 
   /**
@@ -339,9 +316,9 @@
       // get the imsi
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
       // get the lcId
-      uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 3;
       ulDataRxed.push_back (rlcStats->GetUlRxData (imsi, lcId));
-      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << m_thrRefUl);
+      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / statsDuration << " ref " << m_thrRefUl);
     }
   /**
   * Check that the assignation is done in a "proportional fair" manner among users
@@ -351,7 +328,7 @@
   */
   for (int i = 0; i < m_nUser; i++)
     {
-      NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / simulationTime, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
+      NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / statsDuration, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
     }
   Simulator::Destroy ();
 
@@ -392,35 +369,12 @@
 void
 LenaPfFfMacSchedulerTestCase2::DoRun (void)
 {
-  //   LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
-  // 
-  //   LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
+  NS_LOG_FUNCTION (this);
 
-  //   LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
-  // 
-  //   LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
-  // 
-  //   LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
-
-//     LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
-  LogComponentEnable ("LenaTestPfFfMacCheduler", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
-  //   LogComponentEnable ("RadioBearerStatsCalculator", LOG_LEVEL_ALL);
+  Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));  
+  Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+  Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
 
   /**
   * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
@@ -474,14 +428,16 @@
       uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
     }
 
-  lteHelper->EnableRlcTraces ();
-
-  double simulationTime = 0.4;
+  double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS 
+  double statsDuration = 0.4;
   double tolerance = 0.1;
-  Simulator::Stop (Seconds (simulationTime));
+  Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001));
 
+  Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnableRlcTraces, lteHelper);
   Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
-  rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (simulationTime)));
+  rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
+  rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration)));
+
 
   Simulator::Run ();
 
@@ -494,10 +450,10 @@
       // get the imsi
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
       // get the lcId
-      uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 3;
       dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
       totalData += (double)dlDataRxed.at (i);
-      NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << "  thr " << (double)dlDataRxed.at (i) / simulationTime << " ref " << m_nUser);
+      NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << "  thr " << (double)dlDataRxed.at (i) / statsDuration);
       totalEstThrPf += m_estThrPfDl.at (i);
     }
 
@@ -525,10 +481,10 @@
       // get the imsi
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
       // get the lcId
-      uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 3;
       ulDataRxed.push_back (rlcStats->GetUlRxData (imsi, lcId));
-      NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " bytes rxed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << (double)m_estThrPfUl.at (i));
-      NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / simulationTime, (double)m_estThrPfUl.at (i), (double)m_estThrPfUl.at (i) * tolerance, " Unfair Throughput!");
+      NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " bytes rxed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / statsDuration << " ref " << (double)m_estThrPfUl.at (i));
+      NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / statsDuration, (double)m_estThrPfUl.at (i), (double)m_estThrPfUl.at (i) * tolerance, " Unfair Throughput!");
     }
   Simulator::Destroy ();
 
--- a/src/lte/test/lte-test-phy-error-model.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-phy-error-model.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -252,7 +252,7 @@
       // get the imsi
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
       // get the lcId
-      uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 1;
       dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
       double txed = rlcStats->GetDlTxData (imsi, lcId);
       int n = txed / m_tbSize;
@@ -438,7 +438,7 @@
     // get the imsi
     uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
     // get the lcId
-    uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+    uint8_t lcId = 1;
     dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
     double txed = rlcStats->GetDlTxData (imsi, lcId);
     double ber = 1.0 - ((double)dlDataRxed.at (i)/txed);
--- a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
  *
  * 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
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Marco Miozzo <marco.miozzo@cttc.es>
+ *         Nicola Baldo <nbaldo@cttc.es>
  */
 
 #include <ns3/object.h>
@@ -43,6 +44,7 @@
 #include <ns3/lte-ue-phy.h>
 #include <ns3/boolean.h>
 #include <ns3/enum.h>
+#include <ns3/config-store-module.h>
 
 #include "lte-test-rr-ff-mac-scheduler.h"
 
@@ -191,41 +193,11 @@
 void
 LenaRrFfMacSchedulerTestCase::DoRun (void)
 {
+  NS_LOG_FUNCTION (this << m_nUser << m_nLc << m_dist);
   Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
-  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));  Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+  Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));  
+  Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
   Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
-  LogComponentDisableAll (LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
-// 
-//   LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
-
-//   LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
-// 
-//   LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
-//   LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
-//   LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
-//   LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
-//   LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
-// 
-//   LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
-
-//   LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
-  LogComponentEnable ("LenaTestRrFfMacCheduler", LOG_LEVEL_ALL);
-//     LogComponentEnable ("LteMiErrorModel", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LenaHelper", LOG_LEVEL_ALL);
-//   LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-
 
   /**
    * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
@@ -264,7 +236,7 @@
   EpsBearer bearer (q);
   lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
   
-
+ 
   Ptr<LteEnbNetDevice> lteEnbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
   Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy ();
   enbPhy->SetAttribute ("TxPower", DoubleValue (30.0));
@@ -281,13 +253,16 @@
       uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
     }
 
-  lteHelper->EnableRlcTraces ();
-  double simulationTime = 0.4;
+
+  double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS 
+  double statsDuration = 0.4;
   double tolerance = 0.1;
-  Simulator::Stop (Seconds (simulationTime));
+  Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001));
 
+  Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnableRlcTraces, lteHelper);
   Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
-  rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (simulationTime)));
+  rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
+  rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration)));
 
 
   Simulator::Run ();
@@ -301,11 +276,10 @@
     {
       // get the imsi
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
-      // get the lcId
-      uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 3;
       dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
-      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " lcid " << (uint16_t) lcId << " bytes rxed " << (double)dlDataRxed.at (i) << "  thr " << (double)dlDataRxed.at (i) / simulationTime << " ref " << m_thrRefDl);
-      NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / simulationTime, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
+      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " lcid " << (uint16_t) lcId << " bytes rxed " << (double)dlDataRxed.at (i) << "  thr " << (double)dlDataRxed.at (i) / statsDuration << " ref " << m_thrRefDl);
+      NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / statsDuration, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
     }
 
   NS_LOG_INFO ("UL - Test with " << m_nUser << " user(s) at distance " << m_dist);
@@ -315,10 +289,10 @@
       // get the imsi
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
       // get the lcId
-      uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+      uint8_t lcId = 3;
       ulDataRxed.push_back (rlcStats->GetUlRxData (imsi, lcId));
-      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes txed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << m_thrRefUl << " txed " << rlcStats->GetUlTxData (imsi, lcId) / simulationTime);
-      NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / simulationTime, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
+      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " lcid " << (uint16_t) lcId << " bytes rxed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / statsDuration << " ref " << m_thrRefUl << " txed " << rlcStats->GetUlTxData (imsi, lcId) / statsDuration);
+      NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / statsDuration, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
     }
 
   Simulator::Destroy ();
--- a/src/lte/test/test-lte-antenna.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/test-lte-antenna.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -149,7 +149,7 @@
   enbphy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr);
 
 
-  Simulator::Stop (Seconds (0.020));
+  Simulator::Stop (Seconds (0.035));
   Simulator::Run ();
 
 
--- a/src/lte/test/test-lte-epc-e2e-data.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/test-lte-epc-e2e-data.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -214,7 +214,7 @@
                 ++dlPort;
                 PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), dlPort));
                 ApplicationContainer apps = packetSinkHelper.Install (ue);
-                apps.Start (Seconds (0.01));
+                apps.Start (Seconds (0.04));
                 bearerTestData.dlServerApp = apps.Get (0)->GetObject<PacketSink> ();
           
                 UdpEchoClientHelper client (ueIpIface.GetAddress (0), dlPort);
@@ -222,7 +222,7 @@
                 client.SetAttribute ("Interval", TimeValue (bearerTestData.interPacketInterval));
                 client.SetAttribute ("PacketSize", UintegerValue (bearerTestData.pktSize));
                 apps = client.Install (remoteHost);
-                apps.Start (Seconds (0.01));
+                apps.Start (Seconds (0.04));
                 bearerTestData.dlClientApp = apps.Get (0);
               }
 
@@ -230,7 +230,7 @@
                 ++ulPort;
                 PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), ulPort));
                 ApplicationContainer apps = packetSinkHelper.Install (remoteHost);
-                apps.Start (Seconds (0.5));
+                apps.Start (Seconds (0.8));
                 bearerTestData.ulServerApp = apps.Get (0)->GetObject<PacketSink> ();
           
                 UdpEchoClientHelper client (remoteHostAddr, ulPort);
@@ -238,7 +238,7 @@
                 client.SetAttribute ("Interval", TimeValue (bearerTestData.interPacketInterval));
                 client.SetAttribute ("PacketSize", UintegerValue (bearerTestData.pktSize));
                 apps = client.Install (ue);
-                apps.Start (Seconds (0.5));
+                apps.Start (Seconds (0.8));
                 bearerTestData.ulClientApp = apps.Get (0);
               }
 
@@ -266,9 +266,13 @@
   Config::Set ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/MaxTxBufferSize",
                UintegerValue (2 * 1024 * 1024));
 
-  lteHelper->EnableRlcTraces ();
-  lteHelper->EnablePdcpTraces ();
+
   Time simulationTime = Seconds (2.0);
+
+  double statsStartTime = 0.040; // need to allow for RRC connection establishment + SRS 
+  Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnablePdcpTraces, lteHelper);
+
+  lteHelper->GetPdcpStats ()->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
   lteHelper->GetPdcpStats ()->SetAttribute ("EpochDuration", TimeValue (simulationTime));
   
   
@@ -288,9 +292,9 @@
           uint64_t imsi = ++imsiCounter;
           for (uint32_t b = 0; b < ueit->bearers.size (); ++b)
             {
-              // LCID 0 is unused 
-              // LCID 1 is (at the moment) the Default EPS bearer, and is unused in this test program
-              uint8_t lcid = b+2;
+              // LCID 0, 1, 2 are for SRBs
+              // LCID 3 is (at the moment) the Default EPS bearer, and is unused in this test program
+              uint8_t lcid = b+4;
               NS_TEST_ASSERT_MSG_EQ (lteHelper->GetPdcpStats ()->GetDlTxPackets (imsi, lcid), 
                                      ueit->bearers.at (b).numPkts, 
                                      "wrong TX PDCP packets in downlink for IMSI=" << imsi << " LCID=" << (uint16_t) lcid);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/test-lte-rrc.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,227 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+#include <ns3/core-module.h>
+#include <ns3/network-module.h>
+#include <ns3/mobility-module.h>
+#include <ns3/lte-module.h>
+
+
+NS_LOG_COMPONENT_DEFINE ("LteRrcTest");
+
+namespace ns3 {
+
+class LteRrcConnectionEstablishmentTestCase : public TestCase
+{
+public:
+
+  /** 
+   * 
+   * 
+   * \param nUes number of UEs in the test
+   * \param tc connection time base value for all UEs in ms
+   * \param tConnIncrPerUe additional connection time increment for each UE index (0...nUes-1) in ms
+   * \param delayDiscStart expected duration to perform connection establishment in ms
+   * 
+   */
+  LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart);
+  
+private:
+  static std::string BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart);
+  virtual void DoRun (void);
+  void Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
+  void CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
+
+
+  uint32_t m_nUes; // number of UEs in the test
+  uint32_t m_nBearers; // number of UEs in the test
+  uint32_t m_tConnBase;  // connection time base value for all UEs in ms
+  uint32_t m_tConnIncrPerUe; // additional connection time increment for each UE index (0...nUes-1) in ms
+  uint32_t m_delayConnEnd;  // expected duration to perform connection establishment in ms
+  uint32_t m_delayDiscStart;  // delay between connection completed and disconnection request in ms
+  uint32_t m_delayDiscEnd; // expected duration to complete disconnection in ms
+  Ptr<LteHelper> m_lteHelper;
+
+};
+
+
+std::string LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart)
+{
+  std::ostringstream oss;
+  oss << "nUes=" << nUes 
+      << "nBearers=" << nBearers 
+      << ", tConnBase=" << tConnBase
+      << ", tConnIncrPerUe=" << tConnIncrPerUe
+      << ", delayDiscStart=" << delayDiscStart;
+  return oss.str ();
+}
+
+LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart)
+  : TestCase ("RRC connection establishment"),
+    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_delayDiscStart (delayDiscStart),
+    m_delayDiscEnd (10)
+{
+}
+
+void
+LteRrcConnectionEstablishmentTestCase::DoRun ()
+{
+  // normal code
+  
+  m_lteHelper = CreateObject<LteHelper> ();
+
+  NodeContainer enbNodes;
+  enbNodes.Create (1);
+  NodeContainer ueNodes;
+  ueNodes.Create (m_nUes);
+
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (enbNodes);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (ueNodes);
+
+  NetDeviceContainer enbDevs;
+  enbDevs = m_lteHelper->InstallEnbDevice (enbNodes);
+
+  NetDeviceContainer ueDevs;
+  ueDevs = m_lteHelper->InstallUeDevice (ueNodes);
+
+  // custom code used for testing purposes
+  // instead of lteHelper->Attach () and lteHelper->ActivateXxx
+
+  uint32_t i = 0;
+  uint32_t tmax = 0;
+  for (NetDeviceContainer::Iterator it = ueDevs.Begin (); it != ueDevs.End (); ++it)
+    {
+      Ptr<NetDevice> ueDevice = *it;
+      Ptr<NetDevice> enbDevice = enbDevs.Get (0);      
+      Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+      Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
+      
+      uint32_t tc = m_tConnBase + m_tConnIncrPerUe * i; // time connection start
+      uint32_t tcc = tc + m_delayConnEnd; // time check connection completed;
+      uint32_t td =  tcc + m_delayDiscStart; // time disconnect start
+      uint32_t tcd = td + m_delayDiscEnd; // time check disconnection completed
+      tmax = std::max (tmax, tcd);
+      
+      // trick to resolve overloading
+      //void (LteHelper::* overloadedAttachFunctionPointer) (Ptr<NetDevice>, Ptr<NetDevice>) = &LteHelper::Attach;      
+      //Simulator::Schedule (MilliSeconds (tc), overloadedAttachFunctionPointer, lteHelper, *it, enbDevice);
+      Simulator::Schedule (MilliSeconds (tc), &LteRrcConnectionEstablishmentTestCase::Connect, this, ueDevice, enbDevice);
+
+      Simulator::Schedule (MilliSeconds (tcc), &LteRrcConnectionEstablishmentTestCase::CheckConnected, this, *it, enbDevice);
+
+      // disconnection not supported yet
+
+      ++i;
+    }
+
+
+  Simulator::Stop (MilliSeconds (tmax+1));
+
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+
+}
+
+void 
+LteRrcConnectionEstablishmentTestCase::Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
+{
+  m_lteHelper->Attach (ueDevice, enbDevice);
+}
+void 
+LteRrcConnectionEstablishmentTestCase::CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
+{
+  Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+  Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc ();
+  NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!");
+
+
+  Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
+  Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc ();
+  uint16_t rnti = ueRrc->GetRnti ();
+  Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);  
+  NS_TEST_ASSERT_MSG_NE (ueManager, 0, "RNTI " << rnti << " not found in eNB");
+
+  NS_TEST_ASSERT_MSG_EQ (ueManager->GetState (), UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
+
+  uint16_t ueCellId = ueRrc->GetCellId ();
+  uint16_t enbCellId = enbLteDevice->GetCellId ();
+  uint16_t ueImsi = ueLteDevice->GetImsi ();
+  uint16_t enbImsi = ueManager->GetImsi ();
+  uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth ();
+  uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth ();
+  uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth ();
+  uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth ();
+  uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn ();
+  uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn ();
+  uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn ();
+  uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn ();
+
+
+  NS_TEST_ASSERT_MSG_EQ (ueCellId, enbCellId, "inconsistent CellId");
+  NS_TEST_ASSERT_MSG_EQ (ueImsi, enbImsi, "inconsistent Imsi");
+  NS_TEST_ASSERT_MSG_EQ (ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth");
+  NS_TEST_ASSERT_MSG_EQ (ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth");
+  NS_TEST_ASSERT_MSG_EQ (ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn");
+  NS_TEST_ASSERT_MSG_EQ (ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn");
+  
+}
+
+
+
+class LteRrcTestSuite : public TestSuite
+{
+public:
+  LteRrcTestSuite ();
+};
+
+
+LteRrcTestSuite::LteRrcTestSuite ()
+  : TestSuite ("lte-rrc", SYSTEM)
+{
+  NS_LOG_FUNCTION (this);
+
+  //                                                             <----- all times in ms ----------------->
+  //                                                     nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart
+  AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        0,          0,              0,              1));
+  AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        1,          0,              0,              1));
+  AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        0,         0,              0,              1));
+  AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        0,        20,              0,              1));
+  AddTestCase (new LteRrcConnectionEstablishmentTestCase (  3,        0,        20,              0,              1));
+  // AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,        0,        20,              0,              1));
+  // AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,        0,        20,            300,              1));
+  // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100,        0,        10,              1,              1));
+
+}
+
+static LteRrcTestSuite g_lteRrcTestSuiteInstance;
+
+
+
+} // namespace ns3
--- a/src/lte/wscript	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/wscript	Tue Oct 30 16:02:07 2012 +0100
@@ -14,11 +14,13 @@
         'model/lte-amc.cc',
         'model/lte-enb-rrc.cc',
         'model/lte-ue-rrc.cc',
+        'model/lte-rrc-protocol-ideal.cc',
         'model/lte-rlc-sap.cc',
         'model/lte-rlc.cc',
         'model/lte-rlc-sequence-number.cc',
         'model/lte-rlc-header.cc',
         'model/lte-rlc-am-header.cc',
+        'model/lte-rlc-tm.cc',
         'model/lte-rlc-um.cc',
         'model/lte-rlc-am.cc',
         'model/lte-rlc-tag.cc',
@@ -52,6 +54,7 @@
         'model/lte-enb-mac.cc',
         'model/lte-ue-mac.cc',
         'model/lte-radio-bearer-tag.cc',
+        'model/eps-bearer-tag.cc',
         'model/lte-phy-tag.cc',
         'model/lte-enb-phy-sap.cc',
         'model/lte-enb-cphy-sap.cc',
@@ -103,7 +106,8 @@
         'test/test-lte-epc-e2e-data.cc',
         'test/test-lte-antenna.cc',
         'test/lte-test-phy-error-model.cc',
-        'test/lte-test-mimo.cc'
+        'test/lte-test-mimo.cc',
+        'test/test-lte-rrc.cc'
         ]
 
     headers = bld.new_task_gen(features=['ns3header'])
@@ -119,11 +123,14 @@
         'model/lte-amc.h',
         'model/lte-enb-rrc.h',
         'model/lte-ue-rrc.h',
+        'model/lte-rrc-sap.h',
+        'model/lte-rrc-protocol-ideal.h',
         'model/lte-rlc-sap.h',
         'model/lte-rlc.h',
         'model/lte-rlc-header.h',
         'model/lte-rlc-sequence-number.h',
         'model/lte-rlc-am-header.h',
+        'model/lte-rlc-tm.h',
         'model/lte-rlc-um.h',
         'model/lte-rlc-am.h',
         'model/lte-rlc-tag.h',
@@ -157,6 +164,7 @@
         'model/lte-enb-mac.h',
         'model/lte-ue-mac.h',
         'model/lte-radio-bearer-tag.h',
+        'model/eps-bearer-tag.h',
         'model/lte-phy-tag.h',
         'model/lte-enb-phy-sap.h',
         'model/lte-enb-cphy-sap.h',
--- a/src/spectrum/model/multi-model-spectrum-channel.cc	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/spectrum/model/multi-model-spectrum-channel.cc	Tue Oct 30 16:02:07 2012 +0100
@@ -91,7 +91,6 @@
   m_spectrumPropagationLoss = 0;
   m_txSpectrumModelInfoMap.clear ();
   m_rxSpectrumModelInfoMap.clear ();
-  m_phyVector.clear ();
   SpectrumChannel::DoDispose ();
 }
 
@@ -142,12 +141,24 @@
 
   std::vector<Ptr<SpectrumPhy> >::const_iterator it;
 
-  // make sure this phy had not been already added
-  for ( it = m_phyVector.begin (); it != m_phyVector.end (); ++it)
+  // remove a previous entry of this phy if it exists
+  // we need to scan for all rxSpectrumModel values since we don't
+  // know which spectrum model the phy had when it was previously added
+  // (it's probably different than the current one)
+  for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
+       rxInfoIterator !=  m_rxSpectrumModelInfoMap.end ();
+       ++rxInfoIterator)
     {
-      NS_ASSERT (*it != phy);
+      std::set<Ptr<SpectrumPhy> >::iterator phyIt = rxInfoIterator->second.m_rxPhySet.find (phy);
+      if (phyIt !=  rxInfoIterator->second.m_rxPhySet.end ())
+        {
+          rxInfoIterator->second.m_rxPhySet.erase (phyIt);
+          --m_numDevices;
+          break; // there should be at most one entry
+        }       
     }
-  m_phyVector.push_back (phy);
+
+  ++m_numDevices;
 
   RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
 
@@ -157,8 +168,9 @@
       std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
       ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
       NS_ASSERT (ret.second);
-      // also add the phy to the newly created list of SpectrumPhy for this RxSpectrumModel
-      ret.first->second.m_rxPhyList.push_back (phy);
+      // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
+      std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = ret.first->second.m_rxPhySet.insert (phy);
+      NS_ASSERT (ret2.second);
 
       // and create the necessary converters for all the TX spectrum models that we know of
       for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
@@ -176,7 +188,8 @@
   else
     {
       // spectrum model is already known, just add the device to the corresponding list
-      rxInfoIterator->second.m_rxPhyList.push_back (phy);
+      std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = rxInfoIterator->second.m_rxPhySet.insert (phy);
+      NS_ASSERT (ret2.second);
     }
 
 }
@@ -223,7 +236,7 @@
     }
   return txInfoIterator;
 }
-
+    
 
 void
 MultiModelSpectrumChannel::StartTx (Ptr<SpectrumSignalParameters> txParams)
@@ -268,14 +281,12 @@
         }
 
 
-      for (std::list<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin ();
-           rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end ();
+      for (std::set<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhySet.begin ();
+           rxPhyIterator != rxInfoIterator->second.m_rxPhySet.end ();
            ++rxPhyIterator)
         {
           NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
-                         "MultiModelSpectrumChannel only supports devices that use a single RxSpectrumModel that does not change for the whole simulation");
-
-
+                         "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
 
           if ((*rxPhyIterator) != txParams->txPhy)
             {
@@ -364,7 +375,7 @@
 uint32_t
 MultiModelSpectrumChannel::GetNDevices (void) const
 {
-  return m_phyVector.size ();
+  return m_numDevices;
 
 }
 
@@ -372,7 +383,32 @@
 Ptr<NetDevice>
 MultiModelSpectrumChannel::GetDevice (uint32_t i) const
 {
-  return m_phyVector.at (i)->GetDevice ();
+  NS_ASSERT (i < m_numDevices);
+  // this method implementation is computationally intensive. This
+  // method would be faster if we actually used a std::vector for
+  // storing devices, which we don't due to the need to have fast 
+  // SpectrumModel conversions and to allow PHY devices to changea
+  // SpectrumModel at run time. Note that having this method slow is
+  // acceptable as it is not used much at run time (often not at all).
+  // On the other hand, having slow SpectrumModel conversion would be
+  // less acceptable. 
+  uint32_t j = 0;
+  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
+       rxInfoIterator !=  m_rxSpectrumModelInfoMap.end ();
+       ++rxInfoIterator)
+    {
+      for (std::set<Ptr<SpectrumPhy> >::const_iterator phyIt = rxInfoIterator->second.m_rxPhySet.begin ();
+           phyIt != rxInfoIterator->second.m_rxPhySet.end ();
+           ++phyIt)        
+        {
+          if (j == i)
+            {
+              return (*phyIt)->GetDevice ();
+            }
+        }
+    }
+  NS_FATAL_ERROR ("m_numDevice > actual number of devices");
+  return 0;
 }
 
 
--- a/src/spectrum/model/multi-model-spectrum-channel.h	Tue Aug 28 15:46:47 2012 +0200
+++ b/src/spectrum/model/multi-model-spectrum-channel.h	Tue Oct 30 16:02:07 2012 +0100
@@ -28,7 +28,7 @@
 #include <ns3/spectrum-propagation-loss-model.h>
 #include <ns3/propagation-delay-model.h>
 #include <map>
-#include <list>
+#include <set>
 
 namespace ns3 {
 
@@ -62,7 +62,7 @@
   RxSpectrumModelInfo (Ptr<const SpectrumModel> rxSpectrumModel);
 
   Ptr<const SpectrumModel> m_rxSpectrumModel;
-  std::list<Ptr<SpectrumPhy> > m_rxPhyList;
+  std::set<Ptr<SpectrumPhy> > m_rxPhySet;
 };
 
 typedef std::map<SpectrumModelUid_t, RxSpectrumModelInfo> RxSpectrumModelInfoMap_t;
@@ -75,9 +75,13 @@
  *
  * This SpectrumChannel implementation can handle the presence of
  * SpectrumPhy instances which can use
- * different spectrum models, i.e.,  different SpectrumModel. The only
- * requirement is that every SpectrumPhy instance uses the same
- * SpectrumModel for the whole simulation.
+ * different spectrum models, i.e.,  different SpectrumModel. 
+ *
+ * \note It is allowed for a receiving SpectrumPhy to switch to a
+ * different SpectrumModel during the simulation. The requirement
+ * for this to work is that, after the SpectrumPhy switched its
+ * SpectrumModel,  MultiModelSpectrumChannel::AddRx () is
+ * called again passing the pointer to that SpectrumPhy.
  */
 class MultiModelSpectrumChannel : public SpectrumChannel
 {
@@ -120,18 +124,6 @@
    */
   TxSpectrumModelInfoMap_t::const_iterator FindAndEventuallyAddTxSpectrumModel (Ptr<const SpectrumModel> txSpectrumModel);
 
-
-  /**
-   * make sure that there are SpectrumConverters from any
-   * SpectrumPhy being used for TX to the given SpectrumModel being used for RX
-   *
-   * @param rxPhy the RXing SpectrumPhy
-   * @param rxSpectrumModel the SpectrumModel used for RX by rxPhy
-   */
-  void CheckAddRxSpectrumModel (Ptr<SpectrumPhy> rxPhy, Ptr<const SpectrumModel> rxSpectrumModel);
-
-
-
   /**
    * used internally to reschedule transmission after the propagation delay
    *
@@ -177,13 +169,7 @@
    */
   RxSpectrumModelInfoMap_t m_rxSpectrumModelInfoMap;
 
-  /**
-   * this is only used to provide a straighforward implementation of
-   * GetNDevices() and GetDevice()
-   *
-   */
-  std::vector<Ptr<SpectrumPhy> > m_phyVector;
-
+  uint32_t m_numDevices;
 
   double m_maxLossDb;