diff --git a/src/lte/helper/epc-helper.cc b/src/lte/helper/epc-helper.cc new file mode 100644 index 000000000..45aa9828b --- /dev/null +++ b/src/lte/helper/epc-helper.cc @@ -0,0 +1,199 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 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: Jaume Nin + * Nicola Baldo + */ + +#include +#include +#include "ns3/inet-socket-address.h" +#include "ns3/mac48-address.h" +#include "ns3/epc-gtpu-tunnel-endpoint.h" + + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("EpcHelper"); + +NS_OBJECT_ENSURE_REGISTERED (EpcHelper); + +EpcHelper::EpcHelper () +{ + NS_LOG_FUNCTION (this); + + // since we use point-to-point links for all S1-U links, + // we use a /30 subnet which can hold exactly two addresses + // (remember that net broadcast and null address are not valid) + m_s1uIpv4AddressHelper.SetBase ("10.7.0.0", "255.255.255.252"); + + // create SgwPgwNode + m_sgwPgw = CreateObject (); + + Ptr sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + sgwPgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort)); + + // create SgwPgwApplication + + // create WAN NetDevice? + + // create virtual net device + + // interface SgwPgwApplication and virtual net device for tunneling + + // set up static routes appropriately + + +} + +EpcHelper::~EpcHelper () +{ + NS_LOG_FUNCTION (this); +} + +TypeId +EpcHelper::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EpcHelper") + .SetParent () + .AddConstructor () + .AddAttribute ("", "The IP address to assign to the tap device, when in ConfigureLocal mode. " + Ipv4AddressValue ("255.255.255.255"), + MakeIpv4AddressAccessor (&TapBridge::m_tapIp), + MakeIpv4AddressChecker ()) + .AddAttribute ("S1uLinkDataRate", + "The data rate to be used for the next S1-U link to be created", + DataRateValue (DataRate ("10Gb/s")), + MakeDataRateAccessor (&EpcHelper::m_s1uLinkDataRate), + MakeDataRateChecker ()) + .AddAttribute ("S1uLinkDelay", + "The delay to be used for the next S1-U link to be created", + TimeValue (Seconds (0)), + MakeTimeAccessor (&EpcHelper::m_m_s1uLinkDelay), + MakeTimeChecker ()) + .AddAttribute("GtpuPort", + "UDP Port to be used for GTP-U", + UintegerValue (2152), + MakeUintegerAccessor (&EpcHelper::m_gtpuUdpPort), + MakeUintegerChecker ()) + ; + return tid; +} + +void +EpcHelper::CreateSgwPgw () +{ + +} + + +void +EpcHelper::AddEnb (Ptr enb, Ptr lteEnbNetDevice) +{ + + // add an IPv4 stack to the previously created eNB + InternetStackHelper internet; + internet.Install (enb); + + // create a point to point link between the new eNB and the SGW with + // the corresponding new NetDevices on each side + NodeContainer enbSgwNodes; + enbSgwNodes.Add (m_sgwPgw); + enbSgwNodes.Add (enb); + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (m_s1uLinkDataRate)); + p2ph.SetChannelAttribute ("Delay", TimeValue (m_s1uLinkDelay)); + NetDeviceContainer enbSgwDevices = p2ph.Install (enb, m_sgwPgw); + Ptr enbDev = enbSgwDevices.Get (0); + Ptr sgwDev = enbSgwDevices.Get (1); + m_s1uIpv4AddressHelper.NewNetwork (); + Ipv4InterfaceContainer enbSgwIpIfaces m_s1uIpv4AddressHelper.Assign (enbSgwDevices); + Ipv4Address enbAddress = enbSgwIpIfaces.GetAddress (0); + Ipv4Address sgwAddress = enbSgwIpIfaces.GetAddress (1); + + // create S1-U socket for the ENB + Ptr enbS1uSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::UdpSocketFactory")); + enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort)); + + // create LTE socket for the ENB + PacketSocketAddress enbLteSocketAddr; + enbLteSocketAddr.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + // do we need the following? + //enbLteSocketAddr.SetPhysicalAddress (devices.Get (1)->GetAddress ()); + //enbLteSocketAddr.SetProtocol (1); + + Ptr enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); + enbLteSocket->Bind (enbLteSocketAddr); + + // create EpcEnbApplication + Ptr = CreateObject (enbLteSocket, enbS1uSocket, sgwAddress); + + +} + + +void +EpcHelper::ActivateEpsBearer () +{ + // add tunnel at EpcSgwPgwApplication + // add tunnel at EpcEnbApplication +} + + +Ptr +EpcHelper::GetSgwPgwNode () +{ + return m_sgwPgw; +} + + +void +EpcHelper::InstallGtpu (Ptr n) +{ + InstallGtpu (n, m_ipv4.NewAddress ()); +} + +void +EpcHelper::InstallGtpu (Ptr n, Ipv4Address addr) +{ + NS_LOG_FUNCTION (this); + // UDP socket creation and configuration + Ptr m_socket = Socket::CreateSocket (n, TypeId::LookupByName ("ns3::UdpSocketFactory")); + m_socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_udpPort)); + + // tap device creation and configuration + Ptr m_tap = CreateObject (); + m_tap->SetAddress (Mac48Address::Allocate ()); + + n->AddDevice (m_tap); + Ptr ipv4 = n->GetObject (); + uint32_t i = ipv4->AddInterface (m_tap); + ipv4->AddAddress (i, Ipv4InterfaceAddress (addr, m_mask)); + ipv4->SetUp (i); + Ptr tunnel = CreateObject (m_tap, m_socket); + m_gtpuEndpoint[n] = tunnel; +} + +void +EpcHelper::CreateGtpuTunnel (Ptr n, Ipv4Address nAddr, Ptr m, Ipv4Address mAddr) +{ + uint32_t teid = m_gtpuEndpoint[n]->CreateGtpuTunnel (mAddr); + m_gtpuEndpoint[m]->CreateGtpuTunnel (nAddr, teid); +} + + +} // namespace ns3 diff --git a/src/lte/helper/epc-helper.h b/src/lte/helper/epc-helper.h new file mode 100644 index 000000000..bb352c259 --- /dev/null +++ b/src/lte/helper/epc-helper.h @@ -0,0 +1,112 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 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: Jaume Nin + */ + +#ifndef EPC_HELPER_H +#define EPC_HELPER_H + +#include + + + + +namespace ns3 { + +class Node; +class NetDevice; + +/** + * \brief Helper class to handle the creation of the EPC entities and protocols. + * + * This Helper will create an EPC network topology comprising of a + * single node that implements both the SGW and PGW functionality, and + * is connected to all the eNBs in the simulation by means of the S1-U + * interface. + */ +class EpcHelper : public Object +{ +public: + + /** + * Constructor + */ + EpcHelper (); + + /** + * Destructor + */ + virtual ~EpcHelper (); + + // inherited from Object + TypeId GetTypeId (void); + + + /** + * Add an eNB to the EPC + * + * \param enbNode the previosuly created eNB node which is to be + * added to the EPC + * \param lteEnbNetDevice the LteEnbNetDevice of the eNB node + */ + void AddEnb (Ptr enbNode, Ptr lteEnbNetDevice); + + + /** + * Activate an EPS bearer, setting up the corresponding S1-U tunnel. + * + */ + void ActivateEpsBearer (); + + + /** + * + * \return a pointer to the node implementing PGW + * functionality. Note that in this particular implementation this + * node will also hold the SGW functionality. The primary use + * intended for this method is to allow the user to configure the Gi + * interface of the PGW, i.e., to connect the PGW to the internet. + */ + Ptr GetPgwNode (); + +private: + + + Ipv4AddressHelper m_s1uIpv4AddressHelper; /**< helper to assign + addresses to S1-U + NetDevices */ + + Ptr m_sgwPgw; /**< the SGW/PGW node */ + + DataRate m_s1uLinkDataRate; + Time m_s1uLinkDelay; + + + /** + * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152 + */ + uint16_t m_gtpuUdpPort; + +}; + + + + +} // namespace ns3 + +#endif // EPC_HELPER_H diff --git a/src/lte/model/epc-enb-application.cc b/src/lte/model/epc-enb-application.cc index ea381592d..600798647 100644 --- a/src/lte/model/epc-enb-application.cc +++ b/src/lte/model/epc-enb-application.cc @@ -38,24 +38,73 @@ TypeId EpcEnbApplication::GetTypeId (void) { static TypeId tid = TypeId ("ns3::EpcEnbApplication") - .SetParent (); + .SetParent () + .AddAttribute("GtpuPort", + "UDP Port to be used for GTP-U", + UintegerValue (2152), + MakeUintegerAccessor (&EpcEnbApplication::m_updPort), + MakeUintegerChecker ()); return tid; } -EpcEnbApplication::EpcEnbApplication (const Ptr tap, const Ptr s) - : m_udpPort (2152) +EpcEnbApplication::EpcEnbApplication (Address sgwAddress) { NS_LOG_FUNCTION (this); - m_tap = tap; - m_tap->SetSendCallback (MakeCallback (&EpcEnbApplication::GtpuSend, this)); - m_socket = s; - m_socket->SetRecvCallback (MakeCallback (&EpcEnbApplication::GtpuRecv, this)); } + +EpcEnbApplication::~EpcEnbApplication (void) +{ +} + + +void +EpcEnbApplication::RecvFromLteSocket (Ptr socket) +{ + NS_LOG_FUNCTION (this); + NS_ASSERT (socket == m_lteSocket); + Ptr packet = socket->Recv (); + GtpuHeader gtpu; + // TODO: should determine the TEID based on the Radio Bearer ID + // which should be conveyed by means of a Packet Tag + uint32_t teid = 0; + SendToS1uSocket (packet, teid); +} + +void +EpcEnbApplication::RecvFromS1uSocket (Ptr socket) +{ + NS_LOG_FUNCTION (this); + NS_ASSERT (socket == m_s1uSocket); + Ptr packet = socket->Recv (); + GtpuHeader gtpu; + packet->RemoveHeader (gtpu); + uint32_t teid = gtpu.GetTeid (); + uint32_t rbid = GetRbid (teid); + SendToLteSocket (packet, rbid); +} + +void +EpcEnbApplication::SendToS1uSocket (Ptr packet, uint32_t teid) +{ + gtpu.SetTeid (teid); + // From 3GPP TS 29.281 v10.0.0 Section 5.1 + // Length of the payload + the non obligatory GTP-U header + gtpu.SetLength (p->GetSize () + h.GetSerializedSize () - 8); + packet->AddHeader (gtpu); + uint32_t flags = 0; + m_s1uSocket->SendTo (packet, flags, m_sgwAddress); +} + + uint32_t EpcEnbApplication::CreateGtpuTunnel (Ipv4Address destination) { NS_LOG_FUNCTION (this); + if (m_teidCounter == 0xffffffff) + { + NS_FATAL_ERROR ("TEID space exhausted, please implement some TEID reuse mechanism"); + } CreateGtpuTunnel (destination, ++m_teidCounter); return m_teidCounter; } @@ -68,12 +117,25 @@ EpcEnbApplication::CreateGtpuTunnel (Ipv4Address destination, uint32_t teid) m_dstAddrMap[m_indexCounter] = destination; } +uint32_t +EpcEnbApplication::GetRbid (uint32_t teid) +{ + // since we don't have SRBs for now, we can just use the same identifiers + return teid; +} + +uint32_t +EpcEnbApplication::GetTeid (uint32_t rbid) +{ + // since we don't have SRBs for now, we can just use the same identifiers + return rbid; +} void EpcEnbApplication::GtpuRecv (Ptr socket) { - NS_LOG_FUNCTION (this); - Ptr packet = socket->Recv (65535, 0); + NS_LOG_FUNCTION (this); + Ptr packet = socket->Recv (); uint32_t index = 0; m_gtpuMap[index]->RemoveHeader (packet); m_tap->Receive (packet, 0x0800, m_tap->GetAddress (), m_tap->GetAddress (), NetDevice::PACKET_HOST); diff --git a/src/lte/model/epc-enb-application.h b/src/lte/model/epc-enb-application.h index 0aedfba71..ad3243847 100644 --- a/src/lte/model/epc-enb-application.h +++ b/src/lte/model/epc-enb-application.h @@ -44,26 +44,65 @@ class EpcEnbApplication : public Object public: static TypeId GetTypeId (void); + + + /** + * + * + * \param radioSocket the socket to be used to send/receive packets to/from the LTE radio interface + * \param s1uSocket the socket to be used to send/receive packets + * to/from the S1-U interface connected with the SGW + * \param sgwAddress the IPv4 address at which this eNB will be able to reach its SGW + * + */ + EpcEnbApplication (Ptr radioSocket, Ptr s1uSocket, Address sgwAddress); /** - * Method assigned to the send callback of the upper end of the tunnel. It adds - * the GTP header and sends it through the tunnel + * destructor + * */ - bool GtpuSend (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); - /** - * Method assigned to the receive callback of the upper end of the tunnel. It strips - * the GTP header and sends it up to the application - */ - void GtpuRecv (Ptr socket); - - /** - * Constructor that binds the tap device to the callback methods. - * \param tap VirtualNetDevice used to tunnel the packets - * \param s Socket used to send the tunneled packets - */ - EpcEnbApplication (const Ptr tap, const Ptr s); virtual ~EpcEnbApplication (void); + + + void SetupS1Bearer () + + /** + * Method to be assigned to the recv callback of the LTE socket. It is called when the eNB receives a data packet from the radio interface that is to be forwarded to the SGW. + * + * \param socket pointer to the LTE socket + */ + void RecvFromLteSocket (Ptr socket); + + + /** + * Method to be assigned to the recv callback of the S1-U socket. It is called when the eNB receives a data packet from the SGW that is to be forwarded to the UE. + * + * \param socket pointer to the S1-U socket + */ + void RecvFromS1uSocket (Ptr socket); + + /** + * Send a packet to the UE via the LTE radio interface of the eNB + * + * \param packet t + * \param rbid the Radio Bearer IDentifier + */ + void SendToLteSocket (Ptr packet, uint32_t rbid); + + + /** + * Send a packet to the SGW via the S1-U interface + * + * \param packet packet to be sent + * \param teid the Tunnel Enpoint IDentifier + */ + void SendToS1uSocket (Ptr packet, uint32_t teid); + + +private: + + /** * Creates a GTPv1-U tunnel between the given destination and the enpoint * using the specified TEID. @@ -76,31 +115,54 @@ public: * Creates a GTPv1-U tunnel between the given destination and the enpoint. The * TEID is automatically sellected. * \param destination IP address of the other end of the tunnel - * \return teid Tunnel Endpoint IDentifier assigned to the tunnel + * \return the Tunnel Endpoint IDentifier (TEID) assigned to the tunnel */ uint32_t CreateGtpuTunnel (Ipv4Address destination); -private: - /** - * UDP socket to send and receive the packets to and from the tunnel + + /** + * this function implements the 1-to-1 mapping between S1 Bearers and Radio Bearers + * + * \param teid the Tunnel Endpoint IDentifier (TEID) that identifies an S1-bearer on this eNB + * + * \return the corresponding Radio Bearer Identifier */ - Ptr m_socket; + uint32_t GetRbid (uint32_t teid); + + + /** + * this function implements the 1-to-1 mapping between Radio Bearers and S1 Bearers + * + * \param rbid the Radio Bearer Identifier + * + * \return the corresponding the Tunnel Endpoint IDentifier (TEID) that identifies an S1-bearer on this eNB + */ + uint32_t GetTeid (uint32_t rbid); + /** - * UDP port where the socket is bind, fixed by the standard as 2152 + * raw packet socket to send and receive the packets to and from the LTE radio interface + */ + Ptr m_lteSocket; + + /** + * UDP socket to send and receive GTP-U the packets to and from the S1-U interface + */ + Ptr m_epcSocket; + + /** + * UDP port where the GTP-U Socket is bound, fixed by the standard as 2152 */ uint16_t m_udpPort; - /** - * VirtualNetDevice to create the tunnel - */ - Ptr m_tap; + /** * Map holding the GTP instances of the active tunnels on this endpoint */ std::map > m_gtpuMap; + /** - * Map holding the destination address of the active tunnels on this endpoint + * address of the SGW which terminates all tunnels */ - std::map m_dstAddrMap; + Ipv4Address m_sgwAddress; static uint16_t m_teidCounter; static uint32_t m_indexCounter; diff --git a/src/lte/wscript b/src/lte/wscript index 981486814..028d2eb9c 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -33,6 +33,7 @@ def build(bld): 'model/ideal-control-messages.cc', 'helper/lena-helper.cc', 'helper/gtpu-tunnel-helper.cc', + 'helper/epc-helper.cc', 'helper/rlc-stats-calculator.cc', 'helper/mac-stats-calculator.cc', 'model/ff-mac-csched-sap.cc', @@ -109,6 +110,7 @@ def build(bld): 'model/ideal-control-messages.h', 'helper/lena-helper.h', 'helper/gtpu-tunnel-helper.h', + 'helper/epc-helper.h', 'helper/mac-stats-calculator.h', 'helper/rlc-stats-calculator.h', 'model/ff-mac-common.h',