--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/examples/lena-x2-handover.cc Thu Jun 28 13:47:39 2012 +0200
@@ -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 <manuel.requena@cttc.es>
+ */
+
+#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> lteHelper = CreateObject<LteHelper> ();
+ Ptr<EpcHelper> epcHelper = CreateObject<EpcHelper> ();
+ lteHelper->SetEpcHelper (epcHelper);
+ lteHelper->SetSchedulerType("ns3::RrFfMacScheduler");
+
+ Ptr<Node> pgw = epcHelper->GetPgwNode ();
+
+ // Create a single RemoteHost
+ NodeContainer remoteHostContainer;
+ remoteHostContainer.Create (1);
+ Ptr<Node> 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<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
+ // 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<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+ 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<Node> ueNode = ueNodes.Get (u);
+ // Set the default gateway for the UE
+ Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
+ 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;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-x2-header.cc Thu Jun 28 13:47:39 2012 +0200
@@ -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 <manuel.requena@cttc.es>
+ */
+
+#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<Header> ()
+ .AddConstructor<EpcX2Header> ()
+ ;
+ 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<Header> ()
+ .AddConstructor<EpcX2HandoverRequestHeader> ()
+ ;
+ 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<Header> ()
+ .AddConstructor<EpcX2HandoverRequestAckHeader> ()
+ ;
+ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-x2-header.h Thu Jun 28 13:47:39 2012 +0200
@@ -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 <manuel.requena@cttc.es>
+ */
+
+#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<uint16_t> 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<uint16_t> m_erabsList;
+};
+
+
+} // namespace ns3
+
+#endif // EPC_X2_HEADER_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-x2.cc Thu Jun 28 13:47:39 2012 +0200
@@ -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 <manuel.requena@cttc.es>
+ */
+
+#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<Socket> 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<EpcX2> (this);
+}
+
+TypeId
+EpcX2::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::EpcX2")
+ .SetParent<Object> ();
+ 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<Socket> enb1X2cSocket, uint16_t enb2CellId, Ptr<Socket> 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<X2IfaceInfo> (enb1X2cSocket, remoteInetAddr.GetIpv4 ());
+
+ NS_ASSERT_MSG (m_x2InterfaceCellIds.find (enb1X2cSocket) == m_x2InterfaceCellIds.end (),
+ "Mapping for localSocket = " << enb1X2cSocket << " is already known");
+ m_x2InterfaceCellIds [enb1X2cSocket] = Create<X2CellInfo> (enb1CellId, enb2CellId);
+}
+
+
+void
+EpcX2::RecvFromX2cSocket (Ptr<Socket> socket)
+{
+ NS_LOG_FUNCTION (this << socket);
+
+ NS_LOG_LOGIC ("Recv X2 message: from Socket");
+ Ptr<Packet> 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<X2CellInfo> 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<X2CellInfo> 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<X2IfaceInfo> socketInfo = m_x2InterfaceSockets [params.targetCellId];
+ Ptr<Socket> 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> packet = Create<Packet> ();
+ 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<Socket> 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> packet = Create<Packet> ();
+ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/epc-x2.h Thu Jun 28 13:47:39 2012 +0200
@@ -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 <manuel.requena@cttc.es>
+ */
+
+#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<X2IfaceInfo>
+{
+public:
+ X2IfaceInfo (Ptr<Socket> localSocket, Ipv4Address remoteIpAddr);
+ virtual ~X2IfaceInfo (void);
+
+ X2IfaceInfo& operator= (const X2IfaceInfo &);
+
+public:
+ Ptr<Socket> m_localSocket;
+ Ipv4Address m_remoteIpAddr;
+};
+
+
+class X2CellInfo : public SimpleRefCount<X2CellInfo>
+{
+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<EpcX2>;
+
+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<Socket> enb1X2cSocket, uint16_t enb2CellId, Ptr<Socket> 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> 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<X2IfaceInfo> > m_x2InterfaceSockets;
+
+ /**
+ * Map the localSocket (the one receiving the X2 message)
+ * to the corresponding (sourceCellId, targetCellId) associated with the X2 interface
+ */
+ std::map < Ptr<Socket>, Ptr<X2CellInfo> > m_x2InterfaceCellIds;
+
+ /**
+ * UDP port to be used for the X2 interface
+ */
+ uint16_t m_x2cUdpPort;
+
+};
+
+} //namespace ns3
+
+#endif // EPC_X2_H
--- a/src/lte/wscript Wed Jun 27 18:06:50 2012 +0200
+++ b/src/lte/wscript Thu Jun 28 13:47:39 2012 +0200
@@ -61,6 +61,9 @@
'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 @@
'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',
'model/epc-tft.h',
'model/epc-tft-classifier.h',
'model/lte-mi-error-model.h',