add/remove UEs and bearers upon handover
authorNicola Baldo <nicola@baldo.biz>
Sun, 29 Jul 2012 14:29:41 +0200
changeset 9345 8290ae6cab62
parent 9344 cb9379b7f069
child 9346 00e674a0d567
child 9401 6479c153fe24
add/remove UEs and bearers upon handover
src/lte/examples/lena-x2-handover.cc
src/lte/helper/epc-helper.cc
src/lte/helper/epc-helper.h
src/lte/helper/lte-helper.cc
src/lte/helper/lte-helper.h
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-x2.cc
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-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-radio-bearer-info.h
src/lte/model/lte-ue-rrc.cc
src/lte/model/lte-ue-rrc.h
src/lte/test/epc-test-s1u-downlink.cc
src/lte/test/epc-test-s1u-uplink.cc
src/lte/test/lte-test-entities.cc
--- a/src/lte/examples/lena-x2-handover.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/examples/lena-x2-handover.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -145,7 +145,7 @@
   lteHelper->AddX2Interface (enbNodes);
 
   // X2-based Handover
-  lteHelper->HandoverRequest (Seconds (2.0), ueNodes.Get (0), enbNodes.Get (0), enbNodes.Get (1));
+  lteHelper->HandoverRequest (Seconds (2.0), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));
 
   
   Simulator::Stop(Seconds(simTime));
--- a/src/lte/helper/epc-helper.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/helper/epc-helper.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -267,17 +267,6 @@
 }
 
 
-void
-EpcHelper::SendHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode)
-{
-  NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode);
-
-  Ptr<LteEnbRrc> sourceRrc = sourceEnbNode->GetDevice (0)->GetObject<LteEnbNetDevice> ()->GetRrc ();
-
-  sourceRrc->SendHandoverRequest (ueNode, sourceEnbNode, targetEnbNode);
-}
-
-
 void 
 EpcHelper::AttachUe (Ptr<NetDevice> ueLteDevice, uint64_t imsi, Ptr<NetDevice> enbDevice)
 {
--- a/src/lte/helper/epc-helper.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/helper/epc-helper.h	Sun Jul 29 14:29:41 2012 +0200
@@ -90,9 +90,6 @@
    */
   void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2);
 
-  void SendHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode);
-
-
   /** 
    * Activate an EPS bearer, setting up the corresponding S1-U tunnel.
    * 
--- a/src/lte/helper/lte-helper.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/helper/lte-helper.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -571,7 +571,7 @@
   Ptr<LteEnbNetDevice> enbDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
   Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
   EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
-  params.imsi = ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ();
+  params.rnti = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti();
   params.bearer = bearer;
   params.teid = 0; // don't care
   enbRrc->GetS1SapUser ()->DataRadioBearerSetupRequest (params);
@@ -601,25 +601,21 @@
 }
 
 void
-LteHelper::HandoverRequest (Time hoTime, Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode)
+LteHelper::HandoverRequest (Time hoTime, Ptr<NetDevice> ueDev, Ptr<NetDevice> sourceEnbDev, Ptr<NetDevice> targetEnbDev)
 {
-  NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode);
-  Simulator::Schedule (hoTime, &LteHelper::DoHandoverRequest, this, ueNode, sourceEnbNode, targetEnbNode);
+  NS_LOG_FUNCTION (this << ueDev << sourceEnbDev << targetEnbDev);
+  Simulator::Schedule (hoTime, &LteHelper::DoHandoverRequest, this, ueDev, sourceEnbDev, targetEnbDev);
 }
 
 void
-LteHelper::DoHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode)
+LteHelper::DoHandoverRequest (Ptr<NetDevice> ueDev, Ptr<NetDevice> sourceEnbDev, Ptr<NetDevice> targetEnbDev)
 {
-  NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode);
-  
-  m_epcHelper->SendHandoverRequest (ueNode, sourceEnbNode, targetEnbNode);
-  
-  // lteHelper->Attach (ueNode, targetEnbNode);
-  // lteHelper->ActivateEpsBearer (ueNode, *);
+  NS_LOG_FUNCTION (this << ueDev << sourceEnbDev << targetEnbDev);
 
-  // lteHelper->DeactivateEpsBearer (ueNode, *);
-  // lteHelper->Deattach (ueNode, sourceEnbNode);
-  
+  uint16_t targetCellId = targetEnbDev->GetObject<LteEnbNetDevice> ()->GetCellId ();
+  Ptr<LteEnbRrc> sourceRrc = sourceEnbDev->GetObject<LteEnbNetDevice> ()->GetRrc ();
+  uint64_t imsi = ueDev->GetObject<LteUeNetDevice> ()->GetImsi ();
+  sourceRrc->SendHandoverRequest (imsi, targetCellId);  
 }
 
 
--- a/src/lte/helper/lte-helper.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/helper/lte-helper.h	Sun Jul 29 14:29:41 2012 +0200
@@ -245,11 +245,11 @@
    * Trigger an X2-based handover of a UE between two eNBs
    *
    * \param hoTime when the Handover is initiated
-   * \param ueNode the UE that hands off
-   * \param enbNode1 source eNB, originally the UE is attached to this eNB
-   * \param enbNode2 target eNB, the UE is finally connected to this eNB
+   * \param ueDev the UE that hands off
+   * \param enbDev1 source eNB, originally the UE is attached to this eNB
+   * \param enbDev2 target eNB, the UE is finally connected to this eNB
    */
-  void HandoverRequest (Time hoTime, Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode);
+  void HandoverRequest (Time hoTime, Ptr<NetDevice> ueDev, Ptr<NetDevice> sourceEnbDev, Ptr<NetDevice> targetEnbDev);
 
 
   /** 
@@ -360,7 +360,7 @@
   Ptr<NetDevice> InstallSingleEnbDevice (Ptr<Node> n);
   Ptr<NetDevice> InstallSingleUeDevice (Ptr<Node> n);
 
-  void DoHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode);
+  void DoHandoverRequest (Ptr<NetDevice> ueDev, Ptr<NetDevice> sourceEnbDev, Ptr<NetDevice> targetEnbDev);
 
   Ptr<SpectrumChannel> m_downlinkChannel;
   Ptr<SpectrumChannel> m_uplinkChannel;
--- a/src/lte/model/epc-enb-application.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/epc-enb-application.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -82,22 +82,33 @@
   NS_LOG_FUNCTION (this << teid << imsi);
   // request the RRC to setup a radio bearer
   struct EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
-  params.imsi = imsi;
   params.bearer = bearer;
   params.teid = teid;
+  std::map<uint64_t, uint16_t>::iterator it = m_imsiRntiMap.find (imsi);
+  NS_ASSERT_MSG (it != m_imsiRntiMap.end (), "unknown IMSI");
+  params.rnti = it->second;
   m_s1SapUser->DataRadioBearerSetupRequest (params);
 }
 
 void 
-EpcEnbApplication::DoDataRadioBearerSetupResponse (EpcEnbS1SapProvider::DataRadioBearerSetupResponseParameters params)
+EpcEnbApplication::DoS1BearerSetupRequest (EpcEnbS1SapProvider::S1BearerSetupRequestParameters params)
 {
-  NS_ASSERT_MSG (params.success, "Radio Bearer Setup failed");  
+  NS_LOG_FUNCTION (this);
   LteFlowId_t rbid (params.rnti, params.lcid);
   // side effect: create entries if not exist
   m_rbidTeidMap[rbid] = params.teid;
   m_teidRbidMap[params.teid] = rbid;
 }
 
+
+void 
+EpcEnbApplication::DoInitialUeMessage (uint64_t imsi, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this);
+  // side effect: create entry if not exist
+  m_imsiRntiMap[imsi] = rnti;
+}
+
 void 
 EpcEnbApplication::RecvFromLteSocket (Ptr<Socket> socket)
 {
--- a/src/lte/model/epc-enb-application.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/epc-enb-application.h	Sun Jul 29 14:29:41 2012 +0200
@@ -48,6 +48,8 @@
 class EpcEnbApplication : public Application
 {
 
+  friend class MemberEpcEnbS1SapProvider<EpcEnbApplication>;
+
 public:
 
   // inherited from Object
@@ -85,14 +87,6 @@
    */
   EpcEnbS1SapProvider* GetS1SapProvider ();
 
-
-  /** 
-   * \see EpcEnbS1SapUser::DataRadioBearerSetupResponse
-   * 
-   * \param params 
-   */
-  void DoDataRadioBearerSetupResponse (EpcEnbS1SapProvider::DataRadioBearerSetupResponseParameters params);
-
   /** 
    * This method is triggered after the eNB received
    * a S1-AP message of type E-RAB Setup Request by the MME and will
@@ -119,6 +113,13 @@
    */
   void RecvFromS1uSocket (Ptr<Socket> socket);
 
+
+private:
+
+  // S1 SAP provider methods
+  void DoS1BearerSetupRequest (EpcEnbS1SapProvider::S1BearerSetupRequestParameters params);
+  void DoInitialUeMessage (uint64_t imsi, uint16_t rnti);
+
   /** 
    * Send a packet to the UE via the LTE radio interface of the eNB
    * 
@@ -137,8 +138,15 @@
   void SendToS1uSocket (Ptr<Packet> packet, uint32_t teid);
 
 
-private:
-
+  
+  /** 
+   * internal method used for the actual setup of the S1 Bearer
+   * 
+   * \param teid 
+   * \param rnti 
+   * \param lcid 
+   */
+  void SetupS1Bearer (uint32_t teid, uint16_t rnti, uint8_t lcid);
 
   /**
    * raw packet socket to send and receive the packets to and from the LTE radio interface
@@ -183,6 +191,12 @@
   EpcEnbS1SapUser* m_s1SapUser;
 
 
+  /**
+   * UE context info
+   * 
+   */
+  std::map<uint64_t, uint16_t> m_imsiRntiMap;
+
 };
 
 } //namespace ns3
--- a/src/lte/model/epc-enb-s1-sap.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/epc-enb-s1-sap.h	Sun Jul 29 14:29:41 2012 +0200
@@ -40,13 +40,11 @@
   virtual ~EpcEnbS1SapProvider ();
   
   /**
-   * Parameters passed to DataRadioBearerSetupResponse ()
+   * Parameters passed to S1BearerSetupRequest ()
    * 
    */
-  struct DataRadioBearerSetupResponseParameters
+  struct S1BearerSetupRequestParameters
   {
-    bool success; /**< true if DataRadioBearer was setup
-		     successfully, false otherwise*/
     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 */
@@ -57,12 +55,18 @@
   };
 
   /**
-   * response after a call to
-   * EpcEnbS1SapUser::DataRadioBearerSetupRequest ()
+   * Request the setup of a S1 bearer
    * 
    */
-  virtual void DataRadioBearerSetupResponse (DataRadioBearerSetupResponseParameters params) = 0;
+  virtual void S1BearerSetupRequest (S1BearerSetupRequestParameters params) = 0;
   
+  /** 
+   * 
+   * 
+   * \param imsi 
+   * \param rnti 
+   */
+  virtual void InitialUeMessage (uint64_t imsi, uint16_t rnti) = 0;
 };
   
 
@@ -85,13 +89,13 @@
    */
   struct DataRadioBearerSetupRequestParameters
   {
-    uint64_t imsi;   /**< the IMSI identifying the UE for which the
+    uint16_t rnti;   /**< the RNTI identifying the UE for which the
 			DataRadioBearer is to be created */ 
     EpsBearer bearer; /**< the characteristics of the bearer to be set
                          up */
     uint32_t teid;   /**< context information that needs to be passed
                       to the corresponding call to
-                      EpcEnbS1SapProvider::DataRadioBearerSetupResponse */ 
+                      EpcEnbS1SapProvider::S1BearerSetupRequest */ 
   };
 
   /**
@@ -117,8 +121,8 @@
   MemberEpcEnbS1SapProvider (C* owner);
 
   // inherited from EpcEnbS1SapProvider
-  virtual void DataRadioBearerSetupResponse (DataRadioBearerSetupResponseParameters params);
-
+  virtual void S1BearerSetupRequest (S1BearerSetupRequestParameters params);
+  virtual void InitialUeMessage (uint64_t imsi, uint16_t rnti);
 
 private:
   MemberEpcEnbS1SapProvider ();
@@ -137,12 +141,18 @@
 }
 
 template <class C>
-void MemberEpcEnbS1SapProvider<C>::DataRadioBearerSetupResponse (DataRadioBearerSetupResponseParameters params)
+void MemberEpcEnbS1SapProvider<C>::S1BearerSetupRequest (S1BearerSetupRequestParameters params)
 {
-  m_owner->DoDataRadioBearerSetupResponse (params);
+  m_owner->DoS1BearerSetupRequest (params);
 }
 
 
+template <class C>
+void MemberEpcEnbS1SapProvider<C>::InitialUeMessage (uint64_t imsi, uint16_t rnti)
+{
+  m_owner->DoInitialUeMessage (imsi, rnti);
+}
+
 /**
  * Template for the implementation of the EpcEnbS1SapUser as a member
  * of an owner class of type C to which all methods are forwarded
--- a/src/lte/model/epc-x2.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/epc-x2.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -194,8 +194,7 @@
                          "Missing infos of local and remote CellId");
           Ptr<X2CellInfo> cellsInfo = m_x2InterfaceCellIds [socket];
 
-          EpcX2SapUser::HandoverRequestAckParams params;
-          params.cause          = x2HoReqAckHeader.GetCause ();
+          EpcX2SapUser::HandoverRequestAckParams params;          
           params.sourceCellId   = cellsInfo->m_localCellId;
           params.targetCellId   = cellsInfo->m_remoteCellId;
 
--- a/src/lte/model/lte-enb-cmac-sap.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-cmac-sap.h	Sun Jul 29 14:29:41 2012 +0200
@@ -55,6 +55,12 @@
 
   virtual void AddUe (uint16_t rnti) = 0;
 
+  /** 
+   * remove the UE, e.g., after handover or termination of the RRC connection
+   * 
+   * \param rnti 
+   */
+  virtual void RemoveUe (uint16_t rnti) = 0;
 
   /**
    * Logical Channel information to be passed to CmacSapProvider::ConfigureLc
--- a/src/lte/model/lte-enb-cphy-sap.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-cphy-sap.h	Sun Jul 29 14:29:41 2012 +0200
@@ -67,10 +67,9 @@
   /** 
    * Add a new UE to the cell
    * 
-   * \param imsi the unique UE id
    * \param rnti the UE id relative to this cell
    */
-  virtual void AddUe (uint64_t imsi, uint16_t rnti) = 0;
+  virtual void AddUe (uint16_t rnti) = 0;
 
   
   /**
@@ -115,7 +114,7 @@
   virtual void SetCellId (uint16_t cellId);
   virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
   virtual void SetEarfcn (uint16_t ulEarfcn, uint16_t dlEarfcn);
-  virtual void AddUe (uint64_t imsi, uint16_t rnti);
+  virtual void AddUe (uint16_t rnti);
   virtual void SetTransmissionMode (uint16_t  rnti, uint8_t txMode);
 
 private:
@@ -158,9 +157,9 @@
 
 template <class C>
 void 
-MemberLteEnbCphySapProvider<C>::AddUe (uint64_t imsi, uint16_t rnti)
+MemberLteEnbCphySapProvider<C>::AddUe (uint16_t rnti)
 {
-  m_owner->DoAddUe (imsi, rnti);
+  m_owner->DoAddUe (rnti);
 }
 
 
--- a/src/lte/model/lte-enb-mac.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-mac.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -59,6 +59,7 @@
   // inherited from LteEnbCmacSapProvider
   virtual void ConfigureMac (uint8_t ulBandwidth, uint8_t dlBandwidth);
   virtual void AddUe (uint16_t rnti);
+  virtual void RemoveUe (uint16_t rnti);
   virtual void AddLc (LcInfo lcinfo, LteMacSapUser* msu);
   virtual void ReconfigureLc (LcInfo lcinfo);
   virtual void ReleaseLc (uint16_t rnti, uint8_t lcid);
@@ -87,6 +88,12 @@
 }
 
 void
+EnbMacMemberLteEnbCmacSapProvider::RemoveUe (uint16_t rnti)
+{
+  m_mac->DoRemoveUe (rnti);
+}
+
+void
 EnbMacMemberLteEnbCmacSapProvider::AddLc (LcInfo lcinfo, LteMacSapUser* msu)
 {
   m_mac->DoAddLc (lcinfo, msu);
@@ -640,6 +647,14 @@
   m_cschedSapProvider->CschedUeConfigReq (params);
 }
 
+void
+LteEnbMac::DoRemoveUe (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << " rnti=" << rnti);
+  FfMacCschedSapProvider::CschedUeReleaseReqParameters params;
+  params.m_rnti = rnti;
+  m_cschedSapProvider->CschedUeReleaseReq (params);
+}
 
 void
 LteEnbMac::DoAddLc (LteEnbCmacSapProvider::LcInfo lcinfo, LteMacSapUser* msu)
--- a/src/lte/model/lte-enb-mac.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-mac.h	Sun Jul 29 14:29:41 2012 +0200
@@ -141,6 +141,7 @@
   // forwarded from LteEnbCmacSapProvider
   void DoConfigureMac (uint8_t ulBandwidth, uint8_t dlBandwidth);
   void DoAddUe (uint16_t rnti);
+  void DoRemoveUe (uint16_t rnti);
   void DoAddLc (LteEnbCmacSapProvider::LcInfo lcinfo, LteMacSapUser* msu);
   void DoReconfigureLc (LteEnbCmacSapProvider::LcInfo lcinfo);
   void DoReleaseLc (uint16_t  rnti, uint8_t lcid);
--- a/src/lte/model/lte-enb-phy.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-phy.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -33,6 +33,7 @@
 #include "lte-spectrum-value-helper.h"
 #include "ideal-control-messages.h"
 #include "lte-enb-net-device.h"
+#include "lte-ue-rrc.h"
 #include "lte-enb-mac.h"
 #include <ns3/lte-common.h>
 
@@ -606,9 +607,9 @@
 
 
 void 
-LteEnbPhy::DoAddUe (uint64_t imsi, uint16_t rnti)
+LteEnbPhy::DoAddUe (uint16_t rnti)
 {
-  NS_LOG_FUNCTION (this << imsi << rnti);
+  NS_LOG_FUNCTION (this << rnti);
   // since for now ctrl messages are still sent directly to the UePhy
   // without passing to the channel, we need to get a pointer to the
   // UePhy. We do so by walking the whole UE list. This code will
@@ -630,7 +631,8 @@
             }
           else
             {
-              if (ueDev->GetImsi () == imsi)
+              Ptr<LteUeRrc> rrc = ueDev->GetRrc ();
+              if ((rrc->GetRnti () == rnti) && (rrc->GetCellId () == m_cellId))
                 {
                   found = true;
                   uePhy = ueDev->GetPhy ();
@@ -638,7 +640,7 @@
             }
         }
     }
-  NS_ASSERT_MSG (found , " Unable to find UE with IMSI =" << imsi);
+  NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId);
   bool success = AddUePhy (rnti, uePhy);
   NS_ASSERT_MSG (success, "AddUePhy() failed");
 }
--- a/src/lte/model/lte-enb-phy.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-phy.h	Sun Jul 29 14:29:41 2012 +0200
@@ -207,7 +207,7 @@
   // LteEnbCphySapProvider forwarded methods
   void DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
   void DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
-  void DoAddUe (uint64_t imsi, uint16_t rnti);  
+  void DoAddUe (uint16_t rnti);  
   void DoSetTransmissionMode (uint16_t  rnti, uint8_t txMode);
   
 
--- a/src/lte/model/lte-enb-rrc.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -26,6 +26,7 @@
 #include "ns3/pointer.h"
 #include "ns3/object-map.h"
 #include "ns3/object-factory.h"
+#include "ns3/simulator.h"
 
 #include "ns3/lte-enb-rrc.h"
 #include "ns3/lte-enb-net-device.h"
@@ -132,6 +133,12 @@
   return m_imsi;
 }
 
+void
+UeInfo::SetImsi (uint64_t imsi)
+{
+  m_imsi = imsi;
+}
+
 uint8_t
 UeInfo::AddRadioBearer (Ptr<LteRadioBearerInfo> rbi)
 {
@@ -171,11 +178,7 @@
   NS_ASSERT_MSG (it != m_rbMap.end (), "request to remove radio bearer with unknown lcid " << lcid);
   m_rbMap.erase (it);
 }
-
-
-
-
-
+  
 // ///////////////////////////
 // eNB RRC methods
 // ///////////////////////////
@@ -356,20 +359,60 @@
   m_cmacSapProvider->ConfigureMac (ulBandwidth, dlBandwidth);
   m_cphySapProvider->SetBandwidth (ulBandwidth, dlBandwidth);
   m_cphySapProvider->SetEarfcn (ulEarfcn, dlEarfcn);
+  m_cellId = cellId;
   m_cphySapProvider->SetCellId (cellId);
   m_configured = true;
 }
 
 uint16_t
-LteEnbRrc::AddUe (uint64_t imsi)
+LteEnbRrc::ConnectionRequest (uint64_t imsi)
+{
+  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);
+
+  if (m_s1SapProvider != 0)
+    {
+      m_s1SapProvider->InitialUeMessage (imsi, rnti);
+    }
+
+  return rnti;
+}
+
+
+uint16_t
+LteEnbRrc::ConnectionReestablishmentRequest (uint64_t imsi, uint16_t rnti)
 {
-  NS_LOG_FUNCTION (this << imsi);
+  NS_LOG_FUNCTION (this);
   // no Call Admission Control for now
-  uint16_t rnti = CreateUeInfo (imsi); // side effect: create UeInfo for this UE
-  m_imsiRntiMap[imsi] = rnti; // side effect: add entry if not present
+  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);
+
+  // this is needed because if the reestablishment comes from handover we don't know the imsi yet
+  it->second->SetImsi (imsi);
+
+  if (m_s1SapProvider != 0)
+    {
+      m_s1SapProvider->InitialUeMessage (imsi, rnti);
+    }
+
+  return rnti;
+}
+
+
+uint16_t
+LteEnbRrc::AddUe ()
+{
+  NS_LOG_FUNCTION (this);
+  // no Call Admission Control for now
+  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 (imsi, rnti);
+  // need to do this after the present method returns, because under the hood a lookup is done for the RNTI, and otherwise the UE will not have it assigned yet
+  Simulator::ScheduleNow (&LteEnbCphySapProvider::AddUe, m_cphySapProvider, rnti);
   return rnti;
 }
 
@@ -378,7 +421,6 @@
 {
   NS_LOG_FUNCTION (this << (uint32_t) rnti);
   RemoveUeInfo (rnti);
-  m_imsiRntiMap.erase (rnti);
   NS_FATAL_ERROR ("missing RemoveUe method in CMAC SAP");
 }
 
@@ -420,32 +462,21 @@
 void 
 LteEnbRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
 {
-  EpcEnbS1SapProvider::DataRadioBearerSetupResponseParameters response;
-  std::map<uint64_t, uint16_t>::iterator it = m_imsiRntiMap.find (request.imsi);
-  if (it == m_imsiRntiMap.end ())
-    {
-      NS_LOG_ERROR ("unknown IMSI");
-      response.success = false;
-      if (m_s1SapProvider)
-        {
-          m_s1SapProvider->DataRadioBearerSetupResponse (response);      
-        }
-    }
-  else
-    {
-      response.rnti = it->second;
-      response.lcid = SetupRadioBearer (response.rnti, request.bearer);      
-      response.success = (response.lcid > 0);
-      response.teid = request.teid;
-      if (m_s1SapProvider)
-        {          
-          m_s1SapProvider->DataRadioBearerSetupResponse (response);
-        }
+  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)
+LteEnbRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint32_t teid)
 {
   NS_LOG_FUNCTION (this << (uint32_t) rnti);
 
@@ -461,6 +492,8 @@
   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)
@@ -546,19 +579,19 @@
 // User API
 //
 void
-LteEnbRrc::SendHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode)
+LteEnbRrc::SendHandoverRequest (uint16_t rnti, uint16_t cellId)
 {
-  NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode);
+  NS_LOG_FUNCTION (this << rnti << cellId);
   NS_LOG_LOGIC ("Request to send HANDOVER REQUEST");
-  
-  Ptr<LteUeRrc> ueRrc = ueNode->GetDevice (0)->GetObject<LteUeNetDevice> ()->GetRrc ();
-  uint16_t rnti = ueRrc->GetRnti ();
+
+  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   = sourceEnbNode->GetDevice (0)->GetObject<LteEnbNetDevice> ()->GetCellId ();
-  params.targetCellId   = targetEnbNode->GetDevice (0)->GetObject<LteEnbNetDevice> ()->GetCellId ();
+  params.sourceCellId   = m_cellId;
+  params.targetCellId   = cellId;
   params.ueAggregateMaxBitRateDownlink = 200 * 1000;
   params.ueAggregateMaxBitRateUplink = 100 * 1000;
   
@@ -588,9 +621,19 @@
   NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
   NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
   
-  uint8_t rrcData [100];
-  params.rrcContext->CopyData (rrcData, params.rrcContext->GetSize ());
-  NS_LOG_LOGIC ("rrcContext   = " << rrcData);
+  // 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");
 
@@ -651,9 +694,9 @@
 
 
 uint16_t
-LteEnbRrc::CreateUeInfo (uint64_t imsi)
+LteEnbRrc::CreateUeInfo ()
 {
-  NS_LOG_FUNCTION (this << imsi);
+  NS_LOG_FUNCTION (this);
   for (uint16_t rnti = m_lastAllocatedRnti; rnti != m_lastAllocatedRnti - 1; ++rnti)
     {
       if (rnti != 0)
@@ -661,7 +704,7 @@
           if (m_ueMap.find (rnti) == m_ueMap.end ())
             {
               m_lastAllocatedRnti = rnti;
-              m_ueMap.insert (std::pair<uint16_t, Ptr<UeInfo> > (rnti, CreateObject<UeInfo> (imsi)));
+              m_ueMap.insert (std::pair<uint16_t, Ptr<UeInfo> > (rnti, CreateObject<UeInfo> ()));
               return rnti;
             }
         }
--- a/src/lte/model/lte-enb-rrc.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.h	Sun Jul 29 14:29:41 2012 +0200
@@ -41,7 +41,6 @@
 class EpcEnbS1SapProvider;
 class LteUeRrc;
 
-
 /**
  * Manages all the radio bearer information possessed by the ENB RRC for a single UE
  *
@@ -75,6 +74,19 @@
    */
   void RemoveRadioBearer (uint8_t lcid);
 
+  /** 
+   * 
+   * \return a const iterator pointing to the beginning of the embedded map of radio bearers 
+   */
+  std::map <uint8_t, Ptr<LteRadioBearerInfo> >::const_iterator RadioBearerMapBegin ();
+
+
+  /** 
+   * 
+   * \return a const iterator pointing to the end of the embedded map of radio bearers 
+   */
+  std::map <uint8_t, Ptr<LteRadioBearerInfo> >::const_iterator RadioBearerMapEnd ();
+
   UeInfo (void);
   UeInfo (uint64_t imsi);
   virtual ~UeInfo (void);
@@ -83,6 +95,8 @@
 
   uint64_t GetImsi (void);
 
+  void SetImsi (uint64_t imsi);
+
 private:
   std::map <uint8_t, Ptr<LteRadioBearerInfo> > m_rbMap;
   uint8_t m_lastAllocatedId;
@@ -212,13 +226,25 @@
                       uint16_t dlEarfcn,
                       uint16_t cellId);
 
-  /**
-   * Add a new UE to the cell
-   *
-   * \param imsi IMSI of the attaching UE
-   * \return the C-RNTI of the newly added UE
+
+  /** 
+   * RRC connection request by an UE
+   * 
+   * \param imsi the id of the UE
+   * 
+   * \return the RNTI identifying the UE in this cell
    */
-  uint16_t AddUe (uint64_t imsi);
+  uint16_t ConnectionRequest (uint64_t imsi);
+  
+  /** 
+   * RRC connection reestablishment request by UE
+   * 
+   * \param imsi 
+   * \param rnti 
+   * 
+   * \return 
+   */
+  uint16_t ConnectionReestablishmentRequest (uint64_t imsi, uint16_t rnti);
 
   /**
    * remove a UE from the cell
@@ -242,17 +268,6 @@
 
 
   /**
-   * 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
-   *
-   * \return the logical channel identifier of the radio bearer for the considered user
-   */
-  uint8_t SetupRadioBearer (uint16_t rnti, EpsBearer bearer);
-
-
-  /**
    *
    * Release the given radio bearer
    *
@@ -281,8 +296,15 @@
 
   /** 
    * Send a HandoverRequest through the X2 SAP interface
+   * 
+   * This method will trigger a handover which is started by the RRC
+   * by sending a handover request to the target eNB over the X2
+   * interface 
+   *
+   * \param imsi the id of the UE to be handed over 
+   * \param cellId the id of the target eNB
    */
-  void SendHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode);
+  void SendHandoverRequest (uint16_t rnti, uint16_t cellId);
 
   /**
    * Identifies how EPS Bearer parameters are mapped to different RLC types
@@ -293,6 +315,28 @@
                                    RLC_AM_ALWAYS = 3,
                                    PER_BASED = 4};
 private:
+
+  /**
+   * Add a new UE to the cell
+   *
+   * \return the C-RNTI of the newly added UE
+   */
+  uint16_t AddUe ();
+
+
+
+  /**
+   * 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
+   *
+   * \return the logical channel identifier of the radio bearer for the considered user
+   */
+  uint8_t SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint32_t teid);
+
+
   void DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params);
   void DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params);
 
@@ -311,7 +355,7 @@
 
 
   // management of multiple UE info instances
-  uint16_t CreateUeInfo (uint64_t imsi);
+  uint16_t CreateUeInfo ();
   Ptr<UeInfo> GetUeInfo (uint16_t rnti);
   void RemoveUeInfo (uint16_t rnti);
 
@@ -338,10 +382,9 @@
   LteEnbCphySapProvider* m_cphySapProvider;
 
   bool m_configured;
+  uint16_t m_cellId;
   uint16_t m_lastAllocatedRnti;
 
-  std::map<uint64_t, uint16_t> m_imsiRntiMap;
-
   std::map<uint16_t, Ptr<UeInfo> > m_ueMap;
   
   uint8_t m_defaultTransmissionMode;
--- a/src/lte/model/lte-radio-bearer-info.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-info.h	Sun Jul 29 14:29:41 2012 +0200
@@ -21,6 +21,7 @@
 
 #include <ns3/object.h>
 #include <ns3/pointer.h>
+#include <ns3/eps-bearer.h>
 
 namespace ns3 {
 
@@ -41,7 +42,8 @@
 
   Ptr<LteRlc> m_rlc;
   Ptr<LtePdcp> m_pdcp;  
-
+  EpsBearer m_epsBearer;
+  uint32_t m_teid;
 };
 
 
--- a/src/lte/model/lte-ue-rrc.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -22,6 +22,8 @@
 #include <ns3/log.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"
@@ -289,7 +291,7 @@
 {
   NS_LOG_FUNCTION (this);
   
-  m_rnti = m_enbRrc->AddUe (m_imsi);
+  m_rnti = m_enbRrc->ConnectionRequest (m_imsi);
   m_cmacSapProvider->ConfigureUe (m_rnti);
   m_cphySapProvider->SetRnti (m_rnti);
 }
@@ -327,6 +329,43 @@
   m_cphySapProvider->SetTransmissionMode (params.m_transmissionMode);
 }
 
+void 
+LteUeRrc::ConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti)
+{
+  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++)
+    {
+      Ptr<Node> node = *i;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; j < nDevs; j++)
+        {
+          enbDev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
+          if (!enbDev)
+            {
+              continue;
+            }
+          else
+            {
+              if (enbDev->GetCellId () == targetCellId)
+                {
+                  found = true;                  
+                }
+            }
+        }
+    }
+  NS_ASSERT_MSG (found , " Unable to find eNB with CellId =" << targetCellId);
 
+
+  DoForceCampedOnEnb (enbDev, targetCellId);
+  m_rnti = newRnti;
+  m_cmacSapProvider->ConfigureUe (m_rnti);
+  m_cphySapProvider->SetRnti (m_rnti);
+  enbDev->GetObject<LteEnbRrc> ()->ConnectionReestablishmentRequest (m_imsi, m_rnti);
+  
+}
+  
 } // namespace ns3
 
--- a/src/lte/model/lte-ue-rrc.h	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.h	Sun Jul 29 14:29:41 2012 +0200
@@ -185,6 +185,15 @@
   *
   */
   void DoRrcConfigurationUpdateInd (LteUeConfig_t params);
+
+
+  /** 
+   * Execute a handover
+   * 
+   * \param targetCellId 
+   * \param newRnti 
+   */
+  void ConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti);
   
 private:
 
--- a/src/lte/test/epc-test-s1u-downlink.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/test/epc-test-s1u-downlink.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -202,6 +202,7 @@
 
           uint64_t imsi = u+1;
           epcHelper->AttachUe (ueLteDevice, imsi, enbDevice);
+          enbApp->GetS1SapProvider ()->InitialUeMessage (imsi, (uint16_t) imsi);
           epcHelper->ActivateEpsBearer (ueLteDevice, imsi, EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
         } 
             
--- a/src/lte/test/epc-test-s1u-uplink.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/test/epc-test-s1u-uplink.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -425,6 +425,7 @@
 
           uint64_t imsi = u+1;
           epcHelper->AttachUe (ueLteDevice, imsi, enbDevice);
+          enbApp->GetS1SapProvider ()->InitialUeMessage (imsi, (uint16_t) imsi);
           epcHelper->ActivateEpsBearer (ueLteDevice, imsi, EpcTft::Default (), EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT));
           
           // need this since all sinks are installed in the same node
--- a/src/lte/test/lte-test-entities.cc	Fri Jul 20 18:24:23 2012 +0200
+++ b/src/lte/test/lte-test-entities.cc	Sun Jul 29 14:29:41 2012 +0200
@@ -657,13 +657,11 @@
 void 
 EpcTestRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
 {
-  EpcEnbS1SapProvider::DataRadioBearerSetupResponseParameters response;   
-  // works for a single eNB scenario with at most 1 LCID per UE
-  response.rnti = (uint16_t) request.imsi;
+  EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;   
+  response.rnti = request.rnti;
   response.lcid = 1;      
-  response.success = true;
   response.teid = request.teid;
-  m_s1SapProvider->DataRadioBearerSetupResponse (response);
+  m_s1SapProvider->S1BearerSetupRequest (response);
 }