From 019e83b1455b5ef42272557f6aa39f59bb2338ce Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Tue, 19 Jun 2012 12:05:28 +0200 Subject: [PATCH 1/8] first version of the X2 SAP definition --- src/lte/model/epc-x2-sap.cc | 34 ++++++ src/lte/model/epc-x2-sap.h | 207 ++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 src/lte/model/epc-x2-sap.cc create mode 100644 src/lte/model/epc-x2-sap.h diff --git a/src/lte/model/epc-x2-sap.cc b/src/lte/model/epc-x2-sap.cc new file mode 100644 index 000000000..d8ad89615 --- /dev/null +++ b/src/lte/model/epc-x2-sap.cc @@ -0,0 +1,34 @@ +/* -*- 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: Manuel Requena + */ + +#include "ns3/epc-x2-sap.h" + +namespace ns3 { + + +EpcX2SapProvider::~EpcX2SapProvider () +{ +} + +EpcX2SapUser::~EpcX2SapUser () +{ +} + +} // namespace ns3 diff --git a/src/lte/model/epc-x2-sap.h b/src/lte/model/epc-x2-sap.h new file mode 100644 index 000000000..bb1786336 --- /dev/null +++ b/src/lte/model/epc-x2-sap.h @@ -0,0 +1,207 @@ +/* -*- 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: Manuel Requena + */ + +#ifndef EPC_X2_SAP_H +#define EPC_X2_SAP_H + +#include "ns3/packet.h" + +namespace ns3 { + + +class Node; +class Packet; + + +class EpcX2SapProvider +{ +public: + virtual ~EpcX2SapProvider (); + + /** + * Parameters of the API primitives + */ + + struct HandoverRequestParams + { + Ptr ueNode; + Ptr sourceEnbNode; + Ptr targetEnbNode; + + uint32_t targetCellId; + std::list bearers; + Ptr rrcContext; + }; + + struct HandoverRequestAckParams + { + Ptr ueNode; + + std::list bearers; + Ptr rrcContext; + }; + + /** + * SAP primitives + */ + + virtual void SendHandoverRequest (HandoverRequestParams params) = 0; + + virtual void SendHandoverRequestAck (HandoverRequestAckParams params) = 0; + +// TODO +// virtual void SendSnStatusTransfer (const struct SnStatusTransfer& params) = 0; +// +// virtual void SendUeContextRelease (const struct UeContextRelease& params) = 0; +}; + + +class EpcX2SapUser +{ +public: + virtual ~EpcX2SapUser (); + + /** + * Parameters of the API primitives + */ + + struct HandoverRequestParams + { + uint32_t targetCellId; + std::list bearers; + Ptr rrcContext; + }; + + struct HandoverRequestAckParams + { + std::list bearers; + Ptr rrcContext; + }; + + /** + * SAP primitives + */ + + virtual void RecvHandoverRequest (HandoverRequestParams params) = 0; + + virtual void RecvHandoverRequestAck (HandoverRequestAckParams params) = 0; + +// TODO +// virtual void RecvSnStatusTransfer (const struct SnStatusTransfer& params) = 0; +// +// virtual void RecvUeContextRelease (const struct UeContextRelease& params) = 0; +}; + +/////////////////////////////////////// + +template +class EpcX2SpecificEpcX2SapProvider : public EpcX2SapProvider +{ +public: + EpcX2SpecificEpcX2SapProvider (C* x2); + + // + // Interface implemented from EpcX2SapProvider + // + + virtual void SendHandoverRequest (HandoverRequestParams params); + + virtual void SendHandoverRequestAck (HandoverRequestAckParams params); + +private: + EpcX2SpecificEpcX2SapProvider (); + C* m_x2; +}; + +template +EpcX2SpecificEpcX2SapProvider::EpcX2SpecificEpcX2SapProvider (C* x2) + : m_x2 (x2) +{ +} + +template +EpcX2SpecificEpcX2SapProvider::EpcX2SpecificEpcX2SapProvider () +{ +} + +template +void +EpcX2SpecificEpcX2SapProvider::SendHandoverRequest (HandoverRequestParams params) +{ + m_x2->DoSendHandoverRequest (params); +} + +template +void +EpcX2SpecificEpcX2SapProvider::SendHandoverRequestAck (HandoverRequestAckParams params) +{ + m_x2->DoSendHandoverRequestAck (params); +} + +/////////////////////////////////////// + +template +class EpcX2SpecificEpcX2SapUser : public EpcX2SapUser +{ +public: + EpcX2SpecificEpcX2SapUser (C* rrc); + + // + // Interface implemented from EpcX2SapUser + // + + virtual void RecvHandoverRequest (HandoverRequestParams params); + + virtual void RecvHandoverRequestAck (HandoverRequestAckParams params); + +private: + EpcX2SpecificEpcX2SapUser (); + C* m_rrc; +}; + +template +EpcX2SpecificEpcX2SapUser::EpcX2SpecificEpcX2SapUser (C* rrc) + : m_rrc (rrc) +{ +} + +template +EpcX2SpecificEpcX2SapUser::EpcX2SpecificEpcX2SapUser () +{ +} + +template +void +EpcX2SpecificEpcX2SapUser::RecvHandoverRequest (HandoverRequestParams params) +{ + m_rrc->DoRecvHandoverRequest (params); +} + +template +void +EpcX2SpecificEpcX2SapUser::RecvHandoverRequestAck (HandoverRequestAckParams params) +{ + m_rrc->DoRecvHandoverRequestAck (params); +} + + +} // namespace ns3 + +#endif // EPC_X2_SAP_H From 13fd77fafef23926e2960d3353ab08082fb01a68 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Tue, 19 Jun 2012 13:58:18 +0200 Subject: [PATCH 2/8] Add support for X2 SAP --- src/lte/model/lte-enb-rrc.cc | 86 +++++++++++++++++++++++++++++++----- src/lte/model/lte-enb-rrc.h | 44 +++++++++++++----- 2 files changed, 108 insertions(+), 22 deletions(-) diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index 9252cd434..fed8a8889 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -17,23 +17,23 @@ * * Author: Nicola Baldo * Marco Miozzo + * Manuel Requena */ -#include -#include -#include +#include "ns3/fatal-error.h" +#include "ns3/log.h" +#include "ns3/abort.h" #include "ns3/pointer.h" #include "ns3/object-map.h" #include "ns3/object-factory.h" -#include "lte-enb-rrc.h" -#include "lte-rlc.h" -#include "lte-pdcp.h" -#include "lte-pdcp-sap.h" -#include "lte-radio-bearer-info.h" -#include "lte-radio-bearer-tag.h" -#include "ns3/object-map.h" -#include +#include "ns3/lte-enb-rrc.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 "ns3/lte-radio-bearer-tag.h" +#include "ns3/ff-mac-csched-sap.h" // WILD HACK for UE-RRC direct communications #include @@ -209,7 +209,8 @@ UeInfo::RemoveRadioBearer (uint8_t lcid) NS_OBJECT_ENSURE_REGISTERED (LteEnbRrc); LteEnbRrc::LteEnbRrc () - : m_cmacSapProvider (0), + : m_x2SapProvider (0), + m_cmacSapProvider (0), m_ffMacSchedSapProvider (0), m_macSapProvider (0), m_configured (false), @@ -218,6 +219,7 @@ LteEnbRrc::LteEnbRrc () NS_LOG_FUNCTION (this); m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this); m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser (this); + m_x2SapUser = new EpcX2SpecificEpcX2SapUser (this); } @@ -233,6 +235,7 @@ LteEnbRrc::DoDispose () NS_LOG_FUNCTION (this); delete m_cmacSapUser; delete m_pdcpSapUser; + delete m_x2SapUser; } TypeId @@ -282,6 +285,21 @@ LteEnbRrc::SetLastAllocatedRnti (uint16_t lastAllocatedRnti) +void +LteEnbRrc::SetEpcX2SapProvider (EpcX2SapProvider * s) +{ + NS_LOG_FUNCTION (this << s); + m_x2SapProvider = s; +} + +EpcX2SapUser* +LteEnbRrc::GetEpcX2SapUser () +{ + NS_LOG_FUNCTION (this); + return m_x2SapUser; +} + + void LteEnbRrc::SetLteEnbCmacSapProvider (LteEnbCmacSapProvider * s) { @@ -434,6 +452,50 @@ LteEnbRrc::SetForwardUpCallback (Callback > cb) } +// +// User API +// +void +LteEnbRrc::SendHandoverRequest (Ptr ueNode, Ptr sourceEnbNode, Ptr targetEnbNode) +{ + NS_LOG_FUNCTION (this << ueNode << sourceEnbNode << targetEnbNode); + NS_LOG_INFO ("Request to send HANDOVER REQUEST"); + + EpcX2SapProvider::HandoverRequestParams params; + params.ueNode = ueNode; + params.sourceEnbNode = sourceEnbNode; + params.targetEnbNode = targetEnbNode; + + m_x2SapProvider->SendHandoverRequest (params); +} + + +// +// X2-User SAP +// +void +LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params) +{ + NS_LOG_FUNCTION (this); + + NS_LOG_INFO ("Recv X2 message: HANDOVER REQUEST"); + + NS_LOG_INFO ("Send X2 message: HANDOVER REQUEST ACK"); + + EpcX2SapProvider::HandoverRequestAckParams ackParams; + + m_x2SapProvider->SendHandoverRequestAck (ackParams); +} + +void +LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params) +{ + NS_LOG_FUNCTION (this); + + NS_LOG_INFO ("Recv X2 message: HANDOVER REQUEST ACK"); +} + + void LteEnbRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params) { diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index 39bce0380..df11a8f9d 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -16,26 +16,25 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Nicola Baldo + * Manuel Requena */ #ifndef LTE_ENB_RRC_H #define LTE_ENB_RRC_H -#include -#include -#include -#include -#include +#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 namespace ns3 { -class FfMacSchedSapProvider; -class LteMacSapProvider; class LteRadioBearerInfo; -class LtePdcpSapUser; -class LtePdcpSapProvider; /** @@ -97,6 +96,8 @@ class LteEnbRrc : public Object friend class EnbRrcMemberLteEnbCmacSapUser; friend class LtePdcpSpecificLtePdcpSapUser; + friend class EpcX2SpecificEpcX2SapUser; + public: /** * create an RRC instance for use within an eNB @@ -115,6 +116,19 @@ public: static TypeId GetTypeId (void); + /** + * Set the X2 SAP this RRC should interact with + * \param s the X2 SAP Provider to be used by this RRC entity + */ + void SetEpcX2SapProvider (EpcX2SapProvider* s); + + /** + * Get the X2 SAP offered by this RRC + * \return s the X2 SAP User interface offered to the X2 entity by this RRC entity + */ + EpcX2SapUser* GetEpcX2SapUser (); + + /** * set the CMAC SAP this RRC should interact with * @@ -217,9 +231,16 @@ public: * \param cb */ void SetForwardUpCallback (Callback > cb); - + + /** + * Send a HandoverRequest through the X2 SAP interface + */ + void SendHandoverRequest (Ptr ueNode, Ptr sourceEnbNode, Ptr targetEnbNode); + private: + void DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params); + void DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params); void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params); void DoRrcConfigurationUpdateInd (LteUeConfig_t params); @@ -234,6 +255,9 @@ private: Callback > m_forwardUpCallback; + EpcX2SapUser* m_x2SapUser; + EpcX2SapProvider* m_x2SapProvider; + LteEnbCmacSapUser* m_cmacSapUser; LteEnbCmacSapProvider* m_cmacSapProvider; From 333f9a9b8742b398a6b37c3486741484a8e373d8 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Wed, 27 Jun 2012 16:58:33 +0200 Subject: [PATCH 3/8] Add support for X2 handover in LTE Helper --- src/lte/examples/wscript | 3 + src/lte/helper/epc-helper.cc | 155 ++++++++++++++++++++++++++++++++++- src/lte/helper/epc-helper.h | 83 +++++++++++++++++-- src/lte/helper/lte-helper.cc | 48 +++++++++++ src/lte/helper/lte-helper.h | 29 +++++++ 5 files changed, 311 insertions(+), 7 deletions(-) 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..35f76c7e1 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,14 @@ NS_LOG_COMPONENT_DEFINE ("EpcHelper"); NS_OBJECT_ENSURE_REGISTERED (EpcHelper); + +// TODO For now, the X2 entities are created here statically +// TODO std::vector< Ptr > 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 @@ 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 +203,96 @@ 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 ()); + +// TODO g_epcHelperEnbX2.push_back (x2); + + 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 (); +// TODO Ptr enb1X2 = g_epcHelperEnbX2[0]; + 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 (); +// TODO Ptr enb2X2 = g_epcHelperEnbX2[1]; + 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); + + + // TODO To remove +// EpcX2NodePeers x2NodePeers (enb1, enb2); +// EpcX2ApplicationPairs x2ApplicationPairs (enb1X2, enb2X2); +// m_x2Interfaces [x2NodePeers] = x2ApplicationPairs; +} + + +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); } @@ -260,4 +361,56 @@ EpcHelper::GetUeDefaultGatewayAddress () } + +EpcHelper::EpcX2NodePeers::EpcX2NodePeers (Ptr enbPeer1, Ptr 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 x2AppPair1, Ptr 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 diff --git a/src/lte/helper/epc-helper.h b/src/lte/helper/epc-helper.h index 7eae00b7d..667349e18 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,78 @@ 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; + + /** + * 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 + { + public: + EpcX2NodePeers (Ptr enbPeer1, Ptr enbPeer2); + virtual ~EpcX2NodePeers (void); + + bool operator< (const EpcX2NodePeers &) const; + + Ptr m_enbPeer1; + Ptr m_enbPeer2; + }; + + class EpcX2ApplicationPairs : public SimpleRefCount + { + public: + EpcX2ApplicationPairs (); + EpcX2ApplicationPairs (Ptr m_x2AppPair1, Ptr m_x2AppPair2); + virtual ~EpcX2ApplicationPairs (void); + + EpcX2ApplicationPairs& operator= (const EpcX2ApplicationPairs &); + + Ptr m_x2AppPair1; + Ptr m_x2AppPair2; + }; + + std::map < EpcX2NodePeers, EpcX2ApplicationPairs > m_x2Interfaces; + }; 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; From 9984ad30f3c461ba1e6fabbcd19745c9e868bcf9 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Wed, 27 Jun 2012 17:02:45 +0200 Subject: [PATCH 4/8] Add CellId info to X2 SAP --- src/lte/model/epc-x2-sap.h | 20 ++++++++++++-------- src/lte/model/lte-enb-rrc.cc | 30 +++++++++++++++++++----------- src/lte/model/lte-ue-net-device.cc | 2 +- 3 files changed, 32 insertions(+), 20 deletions(-) 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" From c0df618b61192a0142927a055df9ad1b2cc66ea9 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Wed, 27 Jun 2012 17:26:44 +0200 Subject: [PATCH 5/8] Remove old code --- src/lte/helper/epc-helper.cc | 66 +----------------------------------- src/lte/helper/epc-helper.h | 37 -------------------- 2 files changed, 1 insertion(+), 102 deletions(-) diff --git a/src/lte/helper/epc-helper.cc b/src/lte/helper/epc-helper.cc index 35f76c7e1..7fc33cc4e 100644 --- a/src/lte/helper/epc-helper.cc +++ b/src/lte/helper/epc-helper.cc @@ -44,10 +44,6 @@ NS_LOG_COMPONENT_DEFINE ("EpcHelper"); NS_OBJECT_ENSURE_REGISTERED (EpcHelper); -// TODO For now, the X2 entities are created here statically -// TODO std::vector< Ptr > g_epcHelperEnbX2; - - EpcHelper::EpcHelper () : m_gtpuUdpPort (2152), // fixed by the standard m_x2cUdpPort (4444) // fixed by the standard TODO @@ -212,8 +208,7 @@ EpcHelper::AddEnb (Ptr enb, Ptr lteEnbNetDevice) x2->SetEpcX2SapUser (rrc->GetEpcX2SapUser ()); rrc->SetEpcX2SapProvider (x2->GetEpcX2SapProvider ()); -// TODO g_epcHelperEnbX2.push_back (x2); - + enb->AggregateObject (x2); } @@ -262,14 +257,12 @@ EpcHelper::AddX2Interface (Ptr enb1, Ptr enb2) // Add X2 interface to the eNB1's X2 entity Ptr enb1X2 = enb1->GetObject (); -// TODO Ptr enb1X2 = g_epcHelperEnbX2[0]; 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 (); -// TODO Ptr enb2X2 = g_epcHelperEnbX2[1]; Ptr enb2LteDev = enb2->GetDevice (0)->GetObject (); uint16_t enb2CellId = enb2LteDev->GetCellId (); NS_LOG_LOGIC ("LteEnbNetDevice #2 = " << enb2LteDev << " - CellId = " << enb2CellId); @@ -277,11 +270,6 @@ EpcHelper::AddX2Interface (Ptr enb1, Ptr enb2) 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; } @@ -361,56 +349,4 @@ EpcHelper::GetUeDefaultGatewayAddress () } - -EpcHelper::EpcX2NodePeers::EpcX2NodePeers (Ptr enbPeer1, Ptr 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 x2AppPair1, Ptr 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 diff --git a/src/lte/helper/epc-helper.h b/src/lte/helper/epc-helper.h index 667349e18..8656f37ec 100644 --- a/src/lte/helper/epc-helper.h +++ b/src/lte/helper/epc-helper.h @@ -160,11 +160,6 @@ private: */ uint16_t m_gtpuUdpPort; - - /** - * X2 interfaces - * TODO To separate between X2-U interfaces and X2-C interfaces - */ /** * helper to assign addresses to X2 NetDevices @@ -175,43 +170,11 @@ private: 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 - { - public: - EpcX2NodePeers (Ptr enbPeer1, Ptr enbPeer2); - virtual ~EpcX2NodePeers (void); - - bool operator< (const EpcX2NodePeers &) const; - - Ptr m_enbPeer1; - Ptr m_enbPeer2; - }; - - class EpcX2ApplicationPairs : public SimpleRefCount - { - public: - EpcX2ApplicationPairs (); - EpcX2ApplicationPairs (Ptr m_x2AppPair1, Ptr m_x2AppPair2); - virtual ~EpcX2ApplicationPairs (void); - - EpcX2ApplicationPairs& operator= (const EpcX2ApplicationPairs &); - - Ptr m_x2AppPair1; - Ptr m_x2AppPair2; - }; - - std::map < EpcX2NodePeers, EpcX2ApplicationPairs > m_x2Interfaces; - }; From a058791ec8d9f854f26223c0155d5bf2ff921989 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Thu, 28 Jun 2012 11:40:56 +0200 Subject: [PATCH 6/8] Add X2 entity --- src/lte/model/epc-x2.cc | 288 ++++++++++++++++++++++++++++++++++++++++ src/lte/model/epc-x2.h | 143 ++++++++++++++++++++ 2 files changed, 431 insertions(+) create mode 100644 src/lte/model/epc-x2.cc create mode 100644 src/lte/model/epc-x2.h diff --git a/src/lte/model/epc-x2.cc b/src/lte/model/epc-x2.cc new file mode 100644 index 000000000..43d297192 --- /dev/null +++ b/src/lte/model/epc-x2.cc @@ -0,0 +1,288 @@ +/* -*- 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: Manuel Requena + */ + +#include "ns3/log.h" +#include "ns3/inet-socket-address.h" +#include "ns3/packet.h" +#include "ns3/node.h" +#include "ns3/lte-enb-net-device.h" + +#include "ns3/epc-x2-header.h" +#include "ns3/epc-x2.h" + +NS_LOG_COMPONENT_DEFINE ("EpcX2"); + +namespace ns3 { + + +X2IfaceInfo::X2IfaceInfo (Ptr localSocket, Ipv4Address remoteIpAddr) +{ + m_localSocket = localSocket; + m_remoteIpAddr = remoteIpAddr; +} + +X2IfaceInfo::~X2IfaceInfo (void) +{ +} + +X2IfaceInfo& +X2IfaceInfo::operator= (const X2IfaceInfo& value) +{ + NS_LOG_FUNCTION (this); + m_localSocket = value.m_localSocket; + m_remoteIpAddr = value.m_remoteIpAddr; + return *this; +} + +/////////////////////////////////////////// + +X2CellInfo::X2CellInfo (uint16_t localCellId, uint16_t remoteCellId) +{ + m_localCellId = localCellId; + m_remoteCellId = remoteCellId; +} + +X2CellInfo::~X2CellInfo (void) +{ +} + +X2CellInfo& +X2CellInfo::operator= (const X2CellInfo& value) +{ + NS_LOG_FUNCTION (this); + m_localCellId = value.m_localCellId; + m_remoteCellId = value.m_remoteCellId; + return *this; +} + +/////////////////////////////////////////// + +NS_OBJECT_ENSURE_REGISTERED (EpcX2); + +EpcX2::EpcX2 () + : m_x2cUdpPort (4444) +{ + NS_LOG_FUNCTION (this); + + m_x2SapProvider = new EpcX2SpecificEpcX2SapProvider (this); +} + +TypeId +EpcX2::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EpcX2") + .SetParent (); + return tid; +} + +EpcX2::~EpcX2 (void) +{ + NS_LOG_FUNCTION (this); + delete m_x2SapProvider; +} + +void +EpcX2::SetEpcX2SapUser (EpcX2SapUser * s) +{ + NS_LOG_FUNCTION (this << s); + m_x2SapUser = s; +} + +EpcX2SapProvider* +EpcX2::GetEpcX2SapProvider () +{ + NS_LOG_FUNCTION (this); + return m_x2SapProvider; +} + + +void +EpcX2::AddX2Interface (uint16_t enb1CellId, Ptr enb1X2cSocket, uint16_t enb2CellId, Ptr enb2X2cSocket) +{ + NS_LOG_FUNCTION (this << enb1CellId << enb1X2cSocket << enb2CellId << enb2X2cSocket); + + Address addr; + int retval; + + retval = enb1X2cSocket->GetSockName (addr); + NS_ASSERT (retval == 0); + InetSocketAddress localInetAddr = InetSocketAddress::ConvertFrom (addr); + NS_LOG_LOGIC ("local IP address = " << localInetAddr.GetIpv4 ()); + + retval = enb2X2cSocket->GetSockName (addr); + NS_ASSERT (retval == 0); + InetSocketAddress remoteInetAddr = InetSocketAddress::ConvertFrom (addr); + NS_LOG_LOGIC ("remote IP address = " << remoteInetAddr.GetIpv4 ()); + + enb1X2cSocket->SetRecvCallback (MakeCallback (&EpcX2::RecvFromX2cSocket, this)); + + NS_ASSERT_MSG (m_x2InterfaceSockets.find (enb2CellId) == m_x2InterfaceSockets.end (), + "Mapping for remoteCellId = " << enb2CellId << " is already known"); + m_x2InterfaceSockets [enb2CellId] = Create (enb1X2cSocket, remoteInetAddr.GetIpv4 ()); + + NS_ASSERT_MSG (m_x2InterfaceCellIds.find (enb1X2cSocket) == m_x2InterfaceCellIds.end (), + "Mapping for localSocket = " << enb1X2cSocket << " is already known"); + m_x2InterfaceCellIds [enb1X2cSocket] = Create (enb1CellId, enb2CellId); +} + + +void +EpcX2::RecvFromX2cSocket (Ptr socket) +{ + NS_LOG_FUNCTION (this << socket); + + NS_LOG_LOGIC ("Recv X2 message: from Socket"); + Ptr packet = socket->Recv (); + NS_LOG_LOGIC ("packetLen = " << packet->GetSize ()); + + EpcX2Header x2Header; + packet->RemoveHeader (x2Header); + + uint8_t messageType = x2Header.GetMessageType (); + uint8_t procedureCode = x2Header.GetProcedureCode (); + + NS_LOG_LOGIC ("messageType = " << (uint32_t)messageType); + NS_LOG_LOGIC ("procedureCode = " << (uint32_t)procedureCode); + + if (procedureCode == EpcX2Header::HANDOVER_PREPARATION_TYPE) + { + if (messageType == EpcX2Header::INITIATING_MESSAGE) + { + NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST"); + + EpcX2HandoverRequestHeader x2HoReqHeader; + packet->RemoveHeader (x2HoReqHeader); + + NS_ASSERT_MSG (m_x2InterfaceCellIds.find (socket) != m_x2InterfaceCellIds.end (), + "Missing infos of local and remote CellId"); + Ptr cellsInfo = m_x2InterfaceCellIds [socket]; + + EpcX2SapUser::HandoverRequestParams params; + params.cause = x2HoReqHeader.GetCause (); + params.sourceCellId = cellsInfo->m_remoteCellId; + params.targetCellId = x2HoReqHeader.GetTargetCellId (); + NS_ASSERT_MSG (params.targetCellId == cellsInfo->m_localCellId, + "TargetCellId mismatches with localCellId"); + + m_x2SapUser->RecvHandoverRequest (params); + } + else // messageType == SUCCESSFUL_OUTCOME + { + NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK"); + + EpcX2HandoverRequestAckHeader x2HoReqAckHeader; + packet->RemoveHeader (x2HoReqAckHeader); + + NS_ASSERT_MSG (m_x2InterfaceCellIds.find (socket) != m_x2InterfaceCellIds.end (), + "Missing infos of local and remote CellId"); + Ptr cellsInfo = m_x2InterfaceCellIds [socket]; + + EpcX2SapUser::HandoverRequestAckParams params; + params.cause = x2HoReqAckHeader.GetCause (); + params.sourceCellId = cellsInfo->m_localCellId; + params.targetCellId = cellsInfo->m_remoteCellId; + + m_x2SapUser->RecvHandoverRequestAck (params); + } + } + +} + +// +// Implementation of the X2 SAP Provider +// +void +EpcX2::DoSendHandoverRequest (EpcX2SapProvider::HandoverRequestParams params) +{ + NS_LOG_FUNCTION (this); + + NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId); + NS_LOG_LOGIC ("targetCellId = " << params.targetCellId); + + NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.targetCellId) != m_x2InterfaceSockets.end (), + "Missing infos for targetCellId = " << params.targetCellId); + Ptr socketInfo = m_x2InterfaceSockets [params.targetCellId]; + Ptr sourceSocket = socketInfo->m_localSocket; + Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr; + + NS_LOG_LOGIC ("sourceSocket = " << sourceSocket); + NS_LOG_LOGIC ("targetIpAddr = " << targetIpAddr); + + NS_LOG_INFO ("Send X2 message: HANDOVER REQUEST"); + + // Build the X2 message + EpcX2Header x2Header; + x2Header.SetMessageType (EpcX2Header::INITIATING_MESSAGE); + x2Header.SetProcedureCode (EpcX2Header::HANDOVER_PREPARATION_TYPE); + + EpcX2HandoverRequestHeader x2HoReqHeader; + x2HoReqHeader.SetCause (1111); + x2HoReqHeader.SetTargetCellId (params.targetCellId); + + // Build the X2 packet + Ptr packet = Create (); + packet->AddHeader (x2HoReqHeader); + packet->AddHeader (x2Header); + NS_LOG_INFO ("packetLen = " << packet->GetSize ()); + + // Send the X2 message through the socket + sourceSocket->SendTo (packet, 0, InetSocketAddress (targetIpAddr, m_x2cUdpPort)); + +} + + +void +EpcX2::DoSendHandoverRequestAck (EpcX2SapProvider::HandoverRequestAckParams params) +{ + NS_LOG_FUNCTION (this); + + NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId); + NS_LOG_LOGIC ("targetCellId = " << params.targetCellId); + + NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.sourceCellId) != m_x2InterfaceSockets.end (), + "Socket infos not defined for sourceCellId = " << params.sourceCellId); + + Ptr localSocket = m_x2InterfaceSockets [params.sourceCellId]->m_localSocket; + Ipv4Address remoteIpAddr = m_x2InterfaceSockets [params.sourceCellId]->m_remoteIpAddr; + + NS_LOG_LOGIC ("localSocket = " << localSocket); + NS_LOG_LOGIC ("remoteIpAddr = " << remoteIpAddr); + + // Build the X2 message + EpcX2Header x2Header; + x2Header.SetMessageType (EpcX2Header::SUCCESSFUL_OUTCOME); + x2Header.SetProcedureCode (EpcX2Header::HANDOVER_PREPARATION_TYPE); + + EpcX2HandoverRequestAckHeader x2HoReqHeader; + x2HoReqHeader.SetCause (2222); + x2HoReqHeader.SetTargetCellId (params.targetCellId); + + // Build the X2 packet + Ptr packet = Create (); + packet->AddHeader (x2HoReqHeader); + packet->AddHeader (x2Header); + + NS_LOG_INFO ("Send X2 message: HANDOVER REQUEST ACK"); + + localSocket->SendTo (packet, 0, InetSocketAddress (remoteIpAddr, m_x2cUdpPort)); +} + + +} // namespace ns3 diff --git a/src/lte/model/epc-x2.h b/src/lte/model/epc-x2.h new file mode 100644 index 000000000..a0b04c535 --- /dev/null +++ b/src/lte/model/epc-x2.h @@ -0,0 +1,143 @@ +/* -*- 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: Manuel Requena + */ + +#ifndef EPC_X2_H +#define EPC_X2_H + +#include "ns3/socket.h" +#include "ns3/callback.h" +#include "ns3/ptr.h" +#include "ns3/object.h" + +#include "ns3/epc-x2-sap.h" + +namespace ns3 { + + +class X2IfaceInfo : public SimpleRefCount +{ +public: + X2IfaceInfo (Ptr localSocket, Ipv4Address remoteIpAddr); + virtual ~X2IfaceInfo (void); + + X2IfaceInfo& operator= (const X2IfaceInfo &); + +public: + Ptr m_localSocket; + Ipv4Address m_remoteIpAddr; +}; + + +class X2CellInfo : public SimpleRefCount +{ +public: + X2CellInfo (uint16_t localCellId, uint16_t remoteCellId); + virtual ~X2CellInfo (void); + + X2CellInfo& operator= (const X2CellInfo &); + +public: + uint16_t m_localCellId; + uint16_t m_remoteCellId; +}; + + +/** + * \ingroup lte + * + * This entity is installed inside an eNB and provides the functionality for the X2 interface + */ +class EpcX2 : public Object +{ + friend class EpcX2SpecificEpcX2SapProvider; + +public: + /** + * Constructor + */ + EpcX2 (); + + /** + * Destructor + */ + virtual ~EpcX2 (void); + + static TypeId GetTypeId (void); + + + /** + * \param s the X2 SAP User to be used by this EPC X2 entity + */ + void SetEpcX2SapUser (EpcX2SapUser * s); + + /** + * \param s the X2 SAP Provider interface offered by this EPC X2 entity + */ + EpcX2SapProvider* GetEpcX2SapProvider (); + + + /** + * \param s the X2 SAP Provider interface offered by this EPC X2 entity + */ + void AddX2Interface (uint16_t enb1CellId, Ptr enb1X2cSocket, uint16_t enb2CellId, Ptr enb2X2cSocket); + + + /** + * Method to be assigned to the recv callback of the X2 socket. + * It is called when the eNB receives a packet from the peer eNB of the X2 interface + * + * \param socket socket of the X2 interface + */ + void RecvFromX2cSocket (Ptr socket); + + +protected: + // Interface provided by LteRlcSapProvider + virtual void DoSendHandoverRequest (EpcX2SapProvider::HandoverRequestParams params); + virtual void DoSendHandoverRequestAck (EpcX2SapProvider::HandoverRequestAckParams params); + + EpcX2SapUser* m_x2SapUser; + EpcX2SapProvider* m_x2SapProvider; + + +private: + + /** + * Map the targetCellId to the corresponding (sourceSocket, remoteIpAddr) to be used + * to send the X2 message + */ + std::map < uint16_t, Ptr > m_x2InterfaceSockets; + + /** + * Map the localSocket (the one receiving the X2 message) + * to the corresponding (sourceCellId, targetCellId) associated with the X2 interface + */ + std::map < Ptr, Ptr > m_x2InterfaceCellIds; + + /** + * UDP port to be used for the X2 interface + */ + uint16_t m_x2cUdpPort; + +}; + +} //namespace ns3 + +#endif // EPC_X2_H From 4390e6d3f6503e2ea4a8a48a99937f7838bec355 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Thu, 28 Jun 2012 13:40:41 +0200 Subject: [PATCH 7/8] Add draft of X2AP protocol --- src/lte/model/epc-x2-header.cc | 305 +++++++++++++++++++++++++++++++++ src/lte/model/epc-x2-header.h | 123 +++++++++++++ 2 files changed, 428 insertions(+) create mode 100644 src/lte/model/epc-x2-header.cc create mode 100644 src/lte/model/epc-x2-header.h diff --git a/src/lte/model/epc-x2-header.cc b/src/lte/model/epc-x2-header.cc new file mode 100644 index 000000000..3b4e46553 --- /dev/null +++ b/src/lte/model/epc-x2-header.cc @@ -0,0 +1,305 @@ +/* -*- 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: Manuel Requena + */ + +#include "ns3/log.h" +// #include "ns3/packet.h" +#include "ns3/epc-x2-header.h" + +NS_LOG_COMPONENT_DEFINE ("EpcX2Header"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (EpcX2Header); + +EpcX2Header::EpcX2Header () + : m_messageType (0xfa), + m_procedureCode (0xfa) +{ +} + +EpcX2Header::~EpcX2Header () +{ + m_messageType = 0xfb; + m_procedureCode = 0xfb; +} + +TypeId +EpcX2Header::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EpcX2Header") + .SetParent
() + .AddConstructor () + ; + return tid; +} + +TypeId +EpcX2Header::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +EpcX2Header::GetSerializedSize (void) const +{ + return 2; +} + +void +EpcX2Header::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + + i.WriteU8 (m_messageType); + i.WriteU8 (m_procedureCode); +} + +uint32_t +EpcX2Header::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + + m_messageType = i.ReadU8 (); + m_procedureCode = i.ReadU8 (); + + return GetSerializedSize (); +} + +void +EpcX2Header::Print (std::ostream &os) const +{ + os << "MessageType=" << (uint32_t) m_messageType; + os << " ProcedureCode=" << (uint32_t) m_procedureCode; +} + +uint8_t +EpcX2Header::GetMessageType () const +{ + return m_messageType; +} + +void +EpcX2Header::SetMessageType (uint8_t messageType) +{ + this->m_messageType = messageType; +} + +uint8_t +EpcX2Header::GetProcedureCode () const +{ + return m_procedureCode; +} + +void +EpcX2Header::SetProcedureCode (uint8_t procedureCode) +{ + this->m_procedureCode = procedureCode; +} + +///////////////////////////////////////////////////////////////////// + +NS_OBJECT_ENSURE_REGISTERED (EpcX2HandoverRequestHeader); + +EpcX2HandoverRequestHeader::EpcX2HandoverRequestHeader () + : m_oldEnbUeX2apId (0xfffa), + m_cause (0xfffa), + m_targetCellId (0xfffa) +{ +} + +EpcX2HandoverRequestHeader::~EpcX2HandoverRequestHeader () +{ + m_oldEnbUeX2apId = 0xfffb; + m_cause = 0xfffb; + m_targetCellId = 0xfffb; + m_erabsList.clear (); // TODO Clearing of a list +} + +TypeId +EpcX2HandoverRequestHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EpcX2HandoverRequestHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} + +TypeId +EpcX2HandoverRequestHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +EpcX2HandoverRequestHeader::GetSerializedSize (void) const +{ + return 6; +} + +void +EpcX2HandoverRequestHeader::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + + i.WriteHtonU16 (m_oldEnbUeX2apId); + i.WriteHtonU16 (m_cause); + i.WriteHtonU16 (m_targetCellId); +} + +uint32_t +EpcX2HandoverRequestHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + + m_oldEnbUeX2apId = i.ReadNtohU16 (); + m_cause = i.ReadNtohU16 (); + m_targetCellId = i.ReadNtohU16 (); + + return GetSerializedSize (); +} + +void +EpcX2HandoverRequestHeader::Print (std::ostream &os) const +{ + os << "Cause=" << m_cause; + os << " TargetCellId=" << m_targetCellId; +} + +uint16_t +EpcX2HandoverRequestHeader::GetCause () const +{ + return m_cause; +} + +void +EpcX2HandoverRequestHeader::SetCause (uint16_t cause) +{ + this->m_cause = cause; +} + +uint16_t +EpcX2HandoverRequestHeader::GetTargetCellId () const +{ + return m_targetCellId; +} + +void +EpcX2HandoverRequestHeader::SetTargetCellId (uint16_t targetCellId) +{ + this->m_targetCellId = targetCellId; +} + +///////////////////////////////////////////////////////////////////// + +NS_OBJECT_ENSURE_REGISTERED (EpcX2HandoverRequestAckHeader); + +EpcX2HandoverRequestAckHeader::EpcX2HandoverRequestAckHeader () + : m_oldEnbUeX2apId (0xfffa), + m_cause (0xfffa), + m_targetCellId (0xfffa) +{ +} + +EpcX2HandoverRequestAckHeader::~EpcX2HandoverRequestAckHeader () +{ + m_oldEnbUeX2apId = 0xfffb; + m_cause = 0xfffb; + m_targetCellId = 0xfffb; + m_erabsList.clear (); // TODO Clearing of a list +} + +TypeId +EpcX2HandoverRequestAckHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EpcX2HandoverRequestAckHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} + +TypeId +EpcX2HandoverRequestAckHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +EpcX2HandoverRequestAckHeader::GetSerializedSize (void) const +{ + return 6; +} + +void +EpcX2HandoverRequestAckHeader::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + + i.WriteHtonU16 (m_oldEnbUeX2apId); + i.WriteHtonU16 (m_cause); + i.WriteHtonU16 (m_targetCellId); +} + +uint32_t +EpcX2HandoverRequestAckHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + + m_oldEnbUeX2apId = i.ReadNtohU16 (); + m_cause = i.ReadNtohU16 (); + m_targetCellId = i.ReadNtohU16 (); + + return GetSerializedSize (); +} + +void +EpcX2HandoverRequestAckHeader::Print (std::ostream &os) const +{ + os << "Cause=" << m_cause; + os << " TargetCellId=" << m_targetCellId; +} + +uint16_t +EpcX2HandoverRequestAckHeader::GetCause () const +{ + return m_cause; +} + +void +EpcX2HandoverRequestAckHeader::SetCause (uint16_t cause) +{ + this->m_cause = cause; +} + +uint16_t +EpcX2HandoverRequestAckHeader::GetTargetCellId () const +{ + return m_targetCellId; +} + +void +EpcX2HandoverRequestAckHeader::SetTargetCellId (uint16_t targetCellId) +{ + this->m_targetCellId = targetCellId; +} + + +} // namespace ns3 diff --git a/src/lte/model/epc-x2-header.h b/src/lte/model/epc-x2-header.h new file mode 100644 index 000000000..84e934ceb --- /dev/null +++ b/src/lte/model/epc-x2-header.h @@ -0,0 +1,123 @@ +/* -*- 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: Manuel Requena + */ + +#ifndef EPC_X2_HEADER_H +#define EPC_X2_HEADER_H + +#include "ns3/header.h" + +namespace ns3 { + +class EpcX2Header : public Header +{ +public: + EpcX2Header (); + virtual ~EpcX2Header (); + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + virtual void Print (std::ostream &os) const; + + + uint8_t GetMessageType () const; + void SetMessageType (uint8_t messageType); + + uint8_t GetProcedureCode () const; + void SetProcedureCode (uint8_t procedureCode); + + + enum ProcedureCode_t { + HANDOVER_PREPARATION_TYPE = 0 + }; + + enum TypeOfMessage_t { + INITIATING_MESSAGE = 0, + SUCCESSFUL_OUTCOME = 1, + UNSUCCESSFUL_OUTCOME = 2 + }; + +private: + uint8_t m_messageType; + uint8_t m_procedureCode; +}; + + +class EpcX2HandoverRequestHeader : public Header +{ +public: + EpcX2HandoverRequestHeader (); + virtual ~EpcX2HandoverRequestHeader (); + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + virtual void Print (std::ostream &os) const; + + + uint16_t GetCause () const; + void SetCause (uint16_t cause); + + uint16_t GetTargetCellId () const; + void SetTargetCellId (uint16_t targetCellId); + +private: + uint16_t m_oldEnbUeX2apId; // TODO MRE When and why this is used? + uint16_t m_cause; + uint16_t m_targetCellId; + std::list m_erabsList; +}; + + +class EpcX2HandoverRequestAckHeader : public Header +{ +public: + EpcX2HandoverRequestAckHeader (); + virtual ~EpcX2HandoverRequestAckHeader (); + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + virtual void Print (std::ostream &os) const; + + + uint16_t GetCause () const; + void SetCause (uint16_t cause); + + uint16_t GetTargetCellId () const; + void SetTargetCellId (uint16_t targetCellId); + +private: + uint16_t m_oldEnbUeX2apId; // TODO MRE When and why this is used? + uint16_t m_cause; + uint16_t m_targetCellId; + std::list m_erabsList; +}; + + +} // namespace ns3 + +#endif // EPC_X2_HEADER_H From 40464355bf70c77f139f6c445134ccd3a43961d3 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Thu, 28 Jun 2012 13:40:58 +0200 Subject: [PATCH 8/8] Add draft of X2 handover example --- src/lte/examples/lena-x2-handover.cc | 158 +++++++++++++++++++++++++++ src/lte/wscript | 6 + 2 files changed, 164 insertions(+) create mode 100644 src/lte/examples/lena-x2-handover.cc diff --git a/src/lte/examples/lena-x2-handover.cc b/src/lte/examples/lena-x2-handover.cc new file mode 100644 index 000000000..cf999912a --- /dev/null +++ b/src/lte/examples/lena-x2-handover.cc @@ -0,0 +1,158 @@ +/* -*- 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: Manuel Requena + */ + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/internet-module.h" +#include "ns3/mobility-module.h" +#include "ns3/lte-module.h" +#include "ns3/applications-module.h" +#include "ns3/point-to-point-module.h" +#include "ns3/config-store.h" +//#include "ns3/gtk-config-store.h" + +using namespace ns3; + +/** + * Sample simulation script for a X2-based handover. + * It instantiates two eNodeB, attaches one UE to the 'source' eNB and + * triggers a handover of the UE towards the 'target' eNB. + */ +NS_LOG_COMPONENT_DEFINE ("EpcX2HandoverExample"); +int +main (int argc, char *argv[]) +{ + LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL); + + LogComponentEnable ("LteHelper", logLevel); + LogComponentEnable ("EpcHelper", logLevel); + LogComponentEnable ("EpcEnbApplication", logLevel); + LogComponentEnable ("EpcX2", logLevel); + LogComponentEnable ("EpcSgwPgwApplication", logLevel); + + LogComponentEnable ("LteEnbRrc", logLevel); + LogComponentEnable ("LteEnbNetDevice", logLevel); + LogComponentEnable ("LteUeRrc", logLevel); + LogComponentEnable ("LteUeNetDevice", logLevel); + + uint16_t numberOfUes = 1; + uint16_t numberOfEnbs = 2; + double simTime = 4.0; + double distance = 60.0; + + // Command line arguments + CommandLine cmd; + cmd.AddValue("numberOfUes", "Number of UEs", numberOfUes); + cmd.AddValue("numberOfEnbs", "Number of eNodeBs", numberOfEnbs); + cmd.AddValue("simTime", "Total duration of the simulation (in seconds)",simTime); + cmd.Parse(argc, argv); + + + Ptr lteHelper = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + lteHelper->SetSchedulerType("ns3::RrFfMacScheduler"); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + Ipv4AddressHelper ipv4h; + ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); + Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); + + // Routing of the Internet Host (towards the LTE network) + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + // interface 0 is localhost, 1 is the p2p device + remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1); + + NodeContainer ueNodes; + NodeContainer enbNodes; + enbNodes.Create(numberOfEnbs); + ueNodes.Create(numberOfUes); + + // Install Mobility Model + Ptr positionAlloc = CreateObject (); + for (uint16_t i = 0; i < numberOfEnbs; i++) + { + positionAlloc->Add (Vector(distance * i, 0, 0)); + } + MobilityHelper mobility; + mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); + mobility.SetPositionAllocator(positionAlloc); + mobility.Install(enbNodes); + mobility.Install(ueNodes); + + // Install LTE Devices in eNB and UEs + NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes); + NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes); + + // Attach all UEs to the first eNodeB + for (uint16_t i = 0; i < numberOfUes; i++) + { + lteHelper->Attach (ueLteDevs.Get(i), enbLteDevs.Get(0)); + } + + // Install the IP stack on the UEs + internet.Install (ueNodes); + Ipv4InterfaceContainer ueIpIface; + ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevs)); + // Assign IP address to UEs, and install applications + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ueNode = ueNodes.Get (u); + // Set the default gateway for the UE + Ptr ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject ()); + ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); + } + + // Activate an EPS Bearer (including Radio Bearer) between UEs and its eNB + lteHelper->ActivateEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ()); + + + // Add X2 inteface + lteHelper->AddX2Interface (enbNodes); + + // X2-based Handover + lteHelper->HandoverRequest (Seconds (2.0), ueNodes.Get (0), enbNodes.Get (0), enbNodes.Get (1)); + + + Simulator::Stop(Seconds(simTime)); + Simulator::Run(); + + // GtkConfigStore config; + // config.ConfigureAttributes(); + + Simulator::Destroy(); + return 0; + +} diff --git a/src/lte/wscript b/src/lte/wscript index dec2ec974..00c9dd216 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -61,6 +61,9 @@ def build(bld): 'model/trace-fading-loss-model.cc', 'model/epc-enb-application.cc', 'model/epc-sgw-pgw-application.cc', + 'model/epc-x2-sap.cc', + 'model/epc-x2-header.cc', + 'model/epc-x2.cc', 'model/epc-tft.cc', 'model/epc-tft-classifier.cc', 'model/lte-mi-error-model.cc' @@ -157,6 +160,9 @@ def build(bld): 'model/epc-gtpu-header.h', 'model/epc-enb-application.h', 'model/epc-sgw-pgw-application.h', + 'model/epc-x2-sap.h', + 'model/epc-x2-header.h', + 'model/epc-x2.h', 'test/lte-test-downlink-sinr.h', 'test/lte-test-uplink-sinr.h', 'test/lte-test-link-adaptation.h',