diff --git a/src/lte/examples/wscript b/src/lte/examples/wscript index 533094580..66e9e2d17 100644 --- a/src/lte/examples/wscript +++ b/src/lte/examples/wscript @@ -34,4 +34,7 @@ def build(bld): 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' diff --git a/src/lte/helper/epc-helper.cc b/src/lte/helper/epc-helper.cc index a3160c63d..7fc33cc4e 100644 --- a/src/lte/helper/epc-helper.cc +++ b/src/lte/helper/epc-helper.cc @@ -32,6 +32,10 @@ #include #include +#include +#include +#include + namespace ns3 { @@ -39,8 +43,10 @@ NS_LOG_COMPONENT_DEFINE ("EpcHelper"); NS_OBJECT_ENSURE_REGISTERED (EpcHelper); + 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 +55,8 @@ EpcHelper::EpcHelper () // (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 +199,88 @@ EpcHelper::AddEnb (Ptr enb, Ptr lteEnbNetDevice) NS_ASSERT (enb->GetNApplications () == 1); NS_ASSERT_MSG (enb->GetApplication (0)->GetObject () != 0, "cannot retrieve EpcEnbApplication"); NS_LOG_LOGIC ("enb: " << enb << ", enb->GetApplication (0): " << enb->GetApplication (0)); + + NS_LOG_INFO ("Create EpcX2 entity"); + Ptr x2 = CreateObject (); + NS_LOG_INFO ("Connect EpcX2 and LteEnbRrc entities"); + Ptr rrc = lteEnbNetDevice->GetObject ()->GetRrc (); + x2->SetEpcX2SapUser (rrc->GetEpcX2SapUser ()); + rrc->SetEpcX2SapProvider (x2->GetEpcX2SapProvider ()); + + + enb->AggregateObject (x2); + +} + + +void +EpcHelper::AddX2Interface (Ptr enb1, Ptr 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 ()->GetNInterfaces ()); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after installing p2p dev: " << enb2->GetObject ()->GetNInterfaces ()); + Ptr enb1Dev = enbDevices.Get (0); + Ptr 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 ()->GetNInterfaces ()); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB #2 after assigning Ipv4 addr to X2 dev: " << enb2->GetObject ()->GetNInterfaces ()); + + Ipv4Address enb1Address = enbIpIfaces.GetAddress (0); + Ipv4Address enb2Address = enbIpIfaces.GetAddress (1); + + // Create X2-C socket for the eNB1 + Ptr 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 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 enb1X2 = enb1->GetObject (); + Ptr enb1LteDev = enb1->GetDevice (0)->GetObject (); + uint16_t enb1CellId = enb1LteDev->GetCellId (); + NS_LOG_LOGIC ("LteEnbNetDevice #1 = " << enb1LteDev << " - CellId = " << enb1CellId); + + // Add X2 interface to the eNB2's X2 entity + Ptr enb2X2 = enb2->GetObject (); + Ptr enb2LteDev = enb2->GetDevice (0)->GetObject (); + 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); + +} + + +void +EpcHelper::SendHandoverRequest (Ptr ueNode, Ptr sourceEnbNode, Ptr targetEnbNode) +{ + NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode); + + Ptr sourceRrc = sourceEnbNode->GetDevice (0)->GetObject ()->GetRrc (); + + sourceRrc->SendHandoverRequest (ueNode, sourceEnbNode, targetEnbNode); } diff --git a/src/lte/helper/epc-helper.h b/src/lte/helper/epc-helper.h index 7eae00b7d..8656f37ec 100644 --- a/src/lte/helper/epc-helper.h +++ b/src/lte/helper/epc-helper.h @@ -34,6 +34,7 @@ class Node; class NetDevice; class VirtualNetDevice; class EpcSgwPgwApplication; +class EpcX2; /** * \brief Helper class to handle the creation of the EPC entities and protocols. @@ -72,6 +73,17 @@ public: void AddEnb (Ptr enbNode, Ptr lteEnbNetDevice); + /** + * 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 enbNode1, Ptr enbNode2); + + void SendHandoverRequest (Ptr ueNode, Ptr sourceEnbNode, Ptr targetEnbNode); + + /** * Activate an EPS bearer, setting up the corresponding S1-U tunnel. * @@ -115,12 +127,10 @@ public: 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,41 @@ private: Ptr m_sgwPgw; Ptr m_sgwPgwApp; Ptr 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; + + /** + * 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; + }; diff --git a/src/lte/helper/lte-helper.cc b/src/lte/helper/lte-helper.cc index de58a43a7..67496b010 100644 --- a/src/lte/helper/lte-helper.cc +++ b/src/lte/helper/lte-helper.cc @@ -570,6 +570,54 @@ LteHelper::ActivateEpsBearer (Ptr ueDevice, EpsBearer bearer, Ptr enbNode1, Ptr enbNode2) +{ + NS_LOG_FUNCTION (this); + NS_LOG_INFO ("setting up the X2 interface"); + + m_epcHelper->AddX2Interface (enbNode1, enbNode2); +} + +void +LteHelper::HandoverRequest (Time hoTime, Ptr ueNode, Ptr sourceEnbNode, Ptr targetEnbNode) +{ + NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode); + Simulator::Schedule (hoTime, &LteHelper::DoHandoverRequest, this, ueNode, sourceEnbNode, targetEnbNode); +} + +void +LteHelper::DoHandoverRequest (Ptr ueNode, Ptr sourceEnbNode, Ptr 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) { diff --git a/src/lte/helper/lte-helper.h b/src/lte/helper/lte-helper.h index bb9a51612..ce9c2b829 100644 --- a/src/lte/helper/lte-helper.h +++ b/src/lte/helper/lte-helper.h @@ -219,6 +219,33 @@ public: */ void ActivateEpsBearer (Ptr ueDevice, EpsBearer bearer, Ptr 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 enbNode1, Ptr 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 ueNode, Ptr sourceEnbNode, Ptr targetEnbNode); + + /** * * \param bearer the specification of an EPS bearer @@ -320,6 +347,8 @@ private: Ptr InstallSingleEnbDevice (Ptr n); Ptr InstallSingleUeDevice (Ptr n); + void DoHandoverRequest (Ptr ueNode, Ptr sourceEnbNode, Ptr targetEnbNode); + Ptr m_downlinkChannel; Ptr m_uplinkChannel; diff --git a/src/lte/model/epc-x2-sap.h b/src/lte/model/epc-x2-sap.h index bb1786336..ea34cda09 100644 --- a/src/lte/model/epc-x2-sap.h +++ b/src/lte/model/epc-x2-sap.h @@ -41,19 +41,18 @@ public: struct HandoverRequestParams { - Ptr ueNode; - Ptr sourceEnbNode; - Ptr targetEnbNode; - - uint32_t targetCellId; + uint16_t cause; + uint16_t sourceCellId; + uint16_t targetCellId; std::list bearers; Ptr rrcContext; }; struct HandoverRequestAckParams { - Ptr ueNode; - + uint16_t cause; + uint16_t sourceCellId; + uint16_t targetCellId; std::list bearers; Ptr rrcContext; }; @@ -84,13 +83,18 @@ public: struct HandoverRequestParams { - uint32_t targetCellId; + uint16_t cause; + uint16_t sourceCellId; + uint16_t targetCellId; std::list bearers; Ptr rrcContext; }; struct HandoverRequestAckParams { + uint16_t cause; + uint16_t sourceCellId; + uint16_t targetCellId; std::list bearers; Ptr rrcContext; }; diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index fed8a8889..0ac5be740 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -28,6 +28,7 @@ #include "ns3/object-factory.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" @@ -47,9 +48,6 @@ NS_LOG_COMPONENT_DEFINE ("LteEnbRrc"); namespace ns3 { - - - // /////////////////////////// // CMAC SAP forwarder // /////////////////////////// @@ -459,30 +457,37 @@ void LteEnbRrc::SendHandoverRequest (Ptr ueNode, Ptr sourceEnbNode, Ptr targetEnbNode) { NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode); - NS_LOG_INFO ("Request to send HANDOVER REQUEST"); + NS_LOG_LOGIC ("Request to send HANDOVER REQUEST"); EpcX2SapProvider::HandoverRequestParams params; - params.ueNode = ueNode; - params.sourceEnbNode = sourceEnbNode; - params.targetEnbNode = targetEnbNode; + params.sourceCellId = sourceEnbNode->GetDevice (0)->GetObject ()->GetCellId (); + params.targetCellId = targetEnbNode->GetDevice (0)->GetObject ()->GetCellId (); + + NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId); + NS_LOG_LOGIC ("targetCellId = " << params.targetCellId); m_x2SapProvider->SendHandoverRequest (params); } // -// X2-User SAP +// X2 User SAP // void LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params) { NS_LOG_FUNCTION (this); - NS_LOG_INFO ("Recv X2 message: HANDOVER REQUEST"); + NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST"); - NS_LOG_INFO ("Send X2 message: HANDOVER REQUEST ACK"); + NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId); + NS_LOG_LOGIC ("targetCellId = " << params.targetCellId); + + NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK"); EpcX2SapProvider::HandoverRequestAckParams ackParams; + ackParams.sourceCellId = params.sourceCellId; + ackParams.targetCellId = params.targetCellId; m_x2SapProvider->SendHandoverRequestAck (ackParams); } @@ -492,7 +497,10 @@ LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams para { NS_LOG_FUNCTION (this); - NS_LOG_INFO ("Recv X2 message: HANDOVER REQUEST ACK"); + NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK"); + + NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId); + NS_LOG_LOGIC ("targetCellId = " << params.targetCellId); } diff --git a/src/lte/model/lte-ue-net-device.cc b/src/lte/model/lte-ue-net-device.cc index ab8f264f5..5312a6790 100644 --- a/src/lte/model/lte-ue-net-device.cc +++ b/src/lte/model/lte-ue-net-device.cc @@ -31,7 +31,7 @@ #include "ns3/trace-source-accessor.h" #include "ns3/pointer.h" #include "ns3/enum.h" -#include "lte-enb-net-device.h" +#include "ns3/lte-enb-net-device.h" #include "lte-ue-net-device.h" #include "lte-ue-mac.h" #include "lte-ue-rrc.h"