Add support for X2 handover in LTE Helper
authorManuel Requena <manuel.requena@cttc.es>
Wed, 27 Jun 2012 16:58:33 +0200
changeset 9326 1cc7eb255f08
parent 9323 c4c734a16f4f
child 9327 6f8d10f0fb94
Add support for X2 handover in LTE Helper
src/lte/examples/wscript
src/lte/helper/epc-helper.cc
src/lte/helper/epc-helper.h
src/lte/helper/lte-helper.cc
src/lte/helper/lte-helper.h
--- a/src/lte/examples/wscript	Tue Jun 19 13:58:18 2012 +0200
+++ b/src/lte/examples/wscript	Wed Jun 27 16:58:33 2012 +0200
@@ -34,4 +34,7 @@
     obj = bld.create_ns3_program('lena-simple-epc',
                                  ['lte'])
     obj.source = 'lena-simple-epc.cc'
+    obj = bld.create_ns3_program('lena-x2-handover',
+                                 ['lte'])
+    obj.source = 'lena-x2-handover.cc'
 
--- a/src/lte/helper/epc-helper.cc	Tue Jun 19 13:58:18 2012 +0200
+++ b/src/lte/helper/epc-helper.cc	Wed Jun 27 16:58:33 2012 +0200
@@ -32,6 +32,10 @@
 #include <ns3/epc-enb-application.h>
 #include <ns3/epc-sgw-pgw-application.h>
 
+#include <ns3/lte-enb-rrc.h>
+#include <ns3/epc-x2.h>
+#include <ns3/lte-enb-net-device.h>
+
 
 namespace ns3 {
 
@@ -39,8 +43,14 @@
 
 NS_OBJECT_ENSURE_REGISTERED (EpcHelper);
 
+
+// TODO For now, the X2 entities are created here statically
+// TODO std::vector< Ptr<EpcX2> > g_epcHelperEnbX2;
+
+
 EpcHelper::EpcHelper () 
-  : m_gtpuUdpPort (2152) // fixed by the standard
+  : m_gtpuUdpPort (2152), // fixed by the standard
+    m_x2cUdpPort (4444)   // fixed by the standard TODO
 {
   NS_LOG_FUNCTION (this);
 
@@ -49,6 +59,8 @@
   // (remember that net broadcast and null address are not valid)
   m_s1uIpv4AddressHelper.SetBase ("10.0.0.0", "255.255.255.252");
 
+  m_x2Ipv4AddressHelper.SetBase ("12.0.0.0", "255.255.255.252");
+
   // we use a /8 net for all UEs
   m_ueAddressHelper.SetBase ("7.0.0.0", "255.0.0.0");
   
@@ -191,7 +203,96 @@
   NS_ASSERT (enb->GetNApplications () == 1);
   NS_ASSERT_MSG (enb->GetApplication (0)->GetObject<EpcEnbApplication> () != 0, "cannot retrieve EpcEnbApplication");
   NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0));
+
   
+  NS_LOG_INFO ("Create EpcX2 entity");
+  Ptr<EpcX2> x2 = CreateObject<EpcX2> ();
+  NS_LOG_INFO ("Connect EpcX2 and LteEnbRrc entities");
+  Ptr<LteEnbRrc> rrc = lteEnbNetDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
+  x2->SetEpcX2SapUser (rrc->GetEpcX2SapUser ());
+  rrc->SetEpcX2SapProvider (x2->GetEpcX2SapProvider ());
+
+// TODO   g_epcHelperEnbX2.push_back (x2);
+ 
+  enb->AggregateObject (x2);
+
+}
+
+
+void
+EpcHelper::AddX2Interface (Ptr<Node> enb1, Ptr<Node> enb2)
+{
+  NS_LOG_FUNCTION (this << enb1 << enb2);
+
+  // Create a point to point link between the two eNBs with
+  // the corresponding new NetDevices on each side
+  NodeContainer enbNodes;
+  enbNodes.Add (enb1);
+  enbNodes.Add (enb2);
+  PointToPointHelper p2ph;
+// TODO Add m_x2Link*** parameters in epc.helper.h
+// TODO Create Make***Accessor functions 
+//   p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_x2LinkDataRate));
+//   p2ph.SetDeviceAttribute ("Mtu", UintegerValue (m_x2LinkMtu));
+//   p2ph.SetChannelAttribute ("Delay", TimeValue (m_x2LinkDelay));  
+  NetDeviceContainer enbDevices = p2ph.Install (enb1, enb2);
+  NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after installing p2p dev: " << enb1->GetObject<Ipv4> ()->GetNInterfaces ());
+  NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after installing p2p dev: " << enb2->GetObject<Ipv4> ()->GetNInterfaces ());
+  Ptr<NetDevice> enb1Dev = enbDevices.Get (0);
+  Ptr<NetDevice> enb2Dev = enbDevices.Get (1);
+
+  m_x2Ipv4AddressHelper.NewNetwork ();
+  Ipv4InterfaceContainer enbIpIfaces = m_x2Ipv4AddressHelper.Assign (enbDevices);
+  NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #1 after assigning Ipv4 addr to X2 dev: " << enb1->GetObject<Ipv4> ()->GetNInterfaces ());
+  NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after assigning Ipv4 addr to X2 dev: " << enb2->GetObject<Ipv4> ()->GetNInterfaces ());
+
+  Ipv4Address enb1Address = enbIpIfaces.GetAddress (0);
+  Ipv4Address enb2Address = enbIpIfaces.GetAddress (1);
+
+  // Create X2-C socket for the eNB1
+  Ptr<Socket> enb1X2cSocket = Socket::CreateSocket (enb1, TypeId::LookupByName ("ns3::UdpSocketFactory"));
+  int retval = enb1X2cSocket->Bind (InetSocketAddress (enb1Address, m_x2cUdpPort));
+  NS_ASSERT (retval == 0);
+
+  // Create X2-C socket for the eNB2
+  Ptr<Socket> enb2X2cSocket = Socket::CreateSocket (enb2, TypeId::LookupByName ("ns3::UdpSocketFactory"));
+  retval = enb2X2cSocket->Bind (InetSocketAddress (enb2Address, m_x2cUdpPort));
+  NS_ASSERT (retval == 0);
+
+  
+  // Add X2 interface to the eNB1's X2 entity 
+  Ptr<EpcX2> enb1X2 = enb1->GetObject<EpcX2> ();
+// TODO  Ptr<EpcX2> enb1X2 = g_epcHelperEnbX2[0];
+  Ptr<LteEnbNetDevice> enb1LteDev = enb1->GetDevice (0)->GetObject<LteEnbNetDevice> ();
+  uint16_t enb1CellId = enb1LteDev->GetCellId ();
+  NS_LOG_LOGIC ("LteEnbNetDevice #1 = " << enb1LteDev << " - CellId = " << enb1CellId);
+
+  // Add X2 interface to the eNB2's X2 entity 
+  Ptr<EpcX2> enb2X2 = enb2->GetObject<EpcX2> ();
+// TODO  Ptr<EpcX2> enb2X2 = g_epcHelperEnbX2[1];
+  Ptr<LteEnbNetDevice> enb2LteDev = enb2->GetDevice (0)->GetObject<LteEnbNetDevice> ();
+  uint16_t enb2CellId = enb2LteDev->GetCellId ();
+  NS_LOG_LOGIC ("LteEnbNetDevice #2 = " << enb2LteDev << " - CellId = " << enb2CellId);
+
+  enb1X2->AddX2Interface (enb1CellId, enb1X2cSocket, enb2CellId, enb2X2cSocket);
+  enb2X2->AddX2Interface (enb2CellId, enb2X2cSocket, enb1CellId, enb1X2cSocket);
+
+  
+  // TODO To remove
+//   EpcX2NodePeers x2NodePeers (enb1, enb2);
+//   EpcX2ApplicationPairs x2ApplicationPairs (enb1X2, enb2X2);
+//   m_x2Interfaces [x2NodePeers] = x2ApplicationPairs;
+}
+
+
+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);
 }
 
 
@@ -260,4 +361,56 @@
 }
 
 
+
+EpcHelper::EpcX2NodePeers::EpcX2NodePeers (Ptr<Node> enbPeer1, Ptr<Node> enbPeer2)
+{
+  NS_LOG_FUNCTION (this);
+  m_enbPeer1 = enbPeer1;
+  m_enbPeer2 = enbPeer2;
+}
+
+EpcHelper::EpcX2NodePeers::~EpcX2NodePeers ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+bool
+EpcHelper::EpcX2NodePeers::operator< (const EpcX2NodePeers& value) const
+{
+  NS_LOG_FUNCTION (this);
+  return ((m_enbPeer1 < value.m_enbPeer1) &&
+          (m_enbPeer2 < value.m_enbPeer2));
+}
+
+
+EpcHelper::EpcX2ApplicationPairs::EpcX2ApplicationPairs ()
+{
+  NS_LOG_FUNCTION (this);
+  m_x2AppPair1 = 0;
+  m_x2AppPair2 = 0;
+}
+
+EpcHelper::EpcX2ApplicationPairs::EpcX2ApplicationPairs (Ptr<EpcX2> x2AppPair1, Ptr<EpcX2> x2AppPair2)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_x2AppPair1 = x2AppPair1;
+  m_x2AppPair2 = x2AppPair2;
+}
+
+EpcHelper::EpcX2ApplicationPairs::~EpcX2ApplicationPairs ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+EpcHelper::EpcX2ApplicationPairs& 
+EpcHelper::EpcX2ApplicationPairs::operator= (const EpcX2ApplicationPairs& value)
+{
+  NS_LOG_FUNCTION (this);
+  m_x2AppPair1 = value.m_x2AppPair1;
+  m_x2AppPair2 = value.m_x2AppPair2;
+  return *this;
+}
+
+
 } // namespace ns3
--- a/src/lte/helper/epc-helper.h	Tue Jun 19 13:58:18 2012 +0200
+++ b/src/lte/helper/epc-helper.h	Wed Jun 27 16:58:33 2012 +0200
@@ -34,6 +34,7 @@
 class NetDevice;
 class VirtualNetDevice;
 class EpcSgwPgwApplication;
+class EpcX2;
 
 /**
  * \brief Helper class to handle the creation of the EPC entities and protocols.
@@ -73,6 +74,17 @@
 
 
   /** 
+   * Add an X2 interface between two eNB
+   * 
+   * \param enbNode1 one eNB peer of the X2 interface
+   * \param enbNode2 the other eNB peer of the X2 interface
+   */
+  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.
    * 
    * 
@@ -115,12 +127,10 @@
 
 
 private:
-  
-  /** 
-   * helper to assign addresses to S1-U
-   * NetDevices 
+
+  /**
+   * SGW-PGW network element
    */
-  Ipv4AddressHelper m_s1uIpv4AddressHelper; 
 
   /** 
    * helper to assign addresses to UE devices as well as to the TUN device of the SGW/PGW
@@ -130,17 +140,78 @@
   Ptr<Node> m_sgwPgw; 
   Ptr<EpcSgwPgwApplication> m_sgwPgwApp;
   Ptr<VirtualNetDevice> m_tunDevice;
+  
+
+  /**
+   * S1-U interfaces
+   */
+
+  /** 
+   * helper to assign addresses to S1-U NetDevices 
+   */
+  Ipv4AddressHelper m_s1uIpv4AddressHelper; 
 
   DataRate m_s1uLinkDataRate;
   Time     m_s1uLinkDelay;
   uint16_t m_s1uLinkMtu;
 
-
   /**
    * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152
    */
   uint16_t m_gtpuUdpPort;
 
+  
+  /**
+   * X2 interfaces
+   * TODO To separate between X2-U interfaces and X2-C interfaces
+   */
+
+  /** 
+   * helper to assign addresses to X2 NetDevices 
+   */
+  Ipv4AddressHelper m_x2Ipv4AddressHelper; 
+
+  DataRate m_x2LinkDataRate;
+  Time     m_x2LinkDelay;
+  uint16_t m_x2LinkMtu;
+
+
+  /**
+   * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152 TODO Check value in the spec
+   */
+  uint16_t m_x2cUdpPort;
+
+
+  /**
+   * X2 Applications
+   */
+  class EpcX2NodePeers : public SimpleRefCount<EpcX2NodePeers>
+  {
+  public:
+    EpcX2NodePeers (Ptr<Node> enbPeer1, Ptr<Node> enbPeer2);
+    virtual ~EpcX2NodePeers (void);
+
+    bool operator< (const EpcX2NodePeers &) const;
+
+    Ptr<Node> m_enbPeer1;
+    Ptr<Node> m_enbPeer2;
+  };
+
+  class EpcX2ApplicationPairs : public SimpleRefCount<EpcX2ApplicationPairs>
+  {
+  public:
+    EpcX2ApplicationPairs ();
+    EpcX2ApplicationPairs (Ptr<EpcX2> m_x2AppPair1, Ptr<EpcX2> m_x2AppPair2);
+    virtual ~EpcX2ApplicationPairs (void);
+
+    EpcX2ApplicationPairs& operator= (const EpcX2ApplicationPairs &);
+
+    Ptr<EpcX2> m_x2AppPair1;
+    Ptr<EpcX2> m_x2AppPair2;
+  };
+
+  std::map < EpcX2NodePeers, EpcX2ApplicationPairs > m_x2Interfaces;
+
 };
 
 
--- a/src/lte/helper/lte-helper.cc	Tue Jun 19 13:58:18 2012 +0200
+++ b/src/lte/helper/lte-helper.cc	Wed Jun 27 16:58:33 2012 +0200
@@ -570,6 +570,54 @@
     }
 }
 
+
+void
+LteHelper::AddX2Interface (NodeContainer enbNodes)
+{
+  NS_LOG_FUNCTION (this);
+
+  for (NodeContainer::Iterator i = enbNodes.Begin (); i != enbNodes.End (); ++i)
+    {
+      for (NodeContainer::Iterator j = i + 1; j != enbNodes.End (); ++j)
+        {
+          AddX2Interface (*i, *j);
+        }
+    }
+}
+
+void
+LteHelper::AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_INFO ("setting up the X2 interface");
+
+  m_epcHelper->AddX2Interface (enbNode1, enbNode2);
+}
+
+void
+LteHelper::HandoverRequest (Time hoTime, Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode)
+{
+  NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode);
+  Simulator::Schedule (hoTime, &LteHelper::DoHandoverRequest, this, ueNode, sourceEnbNode, targetEnbNode);
+}
+
+void
+LteHelper::DoHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode)
+{
+  NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode);
+  
+  m_epcHelper->SendHandoverRequest (ueNode, sourceEnbNode, targetEnbNode);
+  
+  // lteHelper->Attach (ueNode, targetEnbNode);
+  // lteHelper->ActivateEpsBearer (ueNode, *);
+
+  // lteHelper->DeactivateEpsBearer (ueNode, *);
+  // lteHelper->Deattach (ueNode, sourceEnbNode);
+  
+}
+
+
+
 TypeId
 LteHelper::GetRlcType (EpsBearer bearer)
 {
--- a/src/lte/helper/lte-helper.h	Tue Jun 19 13:58:18 2012 +0200
+++ b/src/lte/helper/lte-helper.h	Wed Jun 27 16:58:33 2012 +0200
@@ -219,6 +219,33 @@
    */
   void ActivateEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer, Ptr<EpcTft> tft);
 
+
+  /**
+   * Create an X2 interface between all the eNBs in a given set
+   *
+   * \param enbNodes the set of eNB nodes
+   */
+  void AddX2Interface (NodeContainer enbNodes);
+
+  /**
+   * Create an X2 interface between two eNBs
+   *
+   * \param enbNode1 one eNB of the X2 interface
+   * \param enbNode2 the other eNB of the X2 interface
+   */
+  void AddX2Interface (Ptr<Node> enbNode1, Ptr<Node> enbNode2);
+
+  /**
+   * 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
+   */
+  void HandoverRequest (Time hoTime, Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode);
+
+
   /** 
    * 
    * \param bearer the specification of an EPS bearer
@@ -320,6 +347,8 @@
   Ptr<NetDevice> InstallSingleEnbDevice (Ptr<Node> n);
   Ptr<NetDevice> InstallSingleUeDevice (Ptr<Node> n);
 
+  void DoHandoverRequest (Ptr<Node> ueNode, Ptr<Node> sourceEnbNode, Ptr<Node> targetEnbNode);
+
   Ptr<SpectrumChannel> m_downlinkChannel;
   Ptr<SpectrumChannel> m_uplinkChannel;