diff -r 6be2010385a2 -r a420385d5438 src/lte/helper/point-to-point-epc-helper.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lte/helper/point-to-point-epc-helper.cc Tue Nov 12 13:03:13 2013 +0100 @@ -0,0 +1,344 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011-2013 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 + * Manuel Requena + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("PointToPointEpcHelper"); + +NS_OBJECT_ENSURE_REGISTERED (PointToPointEpcHelper); + + +PointToPointEpcHelper::PointToPointEpcHelper () + : m_gtpuUdpPort (2152) // fixed by the standard +{ + 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.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"); + + // create SgwPgwNode + m_sgwPgw = CreateObject (); + InternetStackHelper internet; + internet.Install (m_sgwPgw); + + // create S1-U socket + Ptr sgwPgwS1uSocket = Socket::CreateSocket (m_sgwPgw, TypeId::LookupByName ("ns3::UdpSocketFactory")); + int retval = sgwPgwS1uSocket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_gtpuUdpPort)); + NS_ASSERT (retval == 0); + + // create TUN device implementing tunneling of user data over GTP-U/UDP/IP + m_tunDevice = CreateObject (); + // allow jumbo packets + m_tunDevice->SetAttribute ("Mtu", UintegerValue (30000)); + + // yes we need this + m_tunDevice->SetAddress (Mac48Address::Allocate ()); + + m_sgwPgw->AddDevice (m_tunDevice); + NetDeviceContainer tunDeviceContainer; + tunDeviceContainer.Add (m_tunDevice); + + // the TUN device is on the same subnet as the UEs, so when a packet + // addressed to an UE arrives at the intenet to the WAN interface of + // the PGW it will be forwarded to the TUN device. + Ipv4InterfaceContainer tunDeviceIpv4IfContainer = m_ueAddressHelper.Assign (tunDeviceContainer); + + // create EpcSgwPgwApplication + m_sgwPgwApp = CreateObject (m_tunDevice, sgwPgwS1uSocket); + m_sgwPgw->AddApplication (m_sgwPgwApp); + + // connect SgwPgwApplication and virtual net device for tunneling + m_tunDevice->SetSendCallback (MakeCallback (&EpcSgwPgwApplication::RecvFromTunDevice, m_sgwPgwApp)); + + // Create MME and connect with SGW via S11 interface + m_mme = CreateObject (); + m_mme->SetS11SapSgw (m_sgwPgwApp->GetS11SapSgw ()); + m_sgwPgwApp->SetS11SapMme (m_mme->GetS11SapMme ()); +} + +PointToPointEpcHelper::~PointToPointEpcHelper () +{ + NS_LOG_FUNCTION (this); +} + +TypeId +PointToPointEpcHelper::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::PointToPointEpcHelper") + .SetParent () + .AddConstructor () + .AddAttribute ("S1uLinkDataRate", + "The data rate to be used for the next S1-U link to be created", + DataRateValue (DataRate ("10Gb/s")), + MakeDataRateAccessor (&PointToPointEpcHelper::m_s1uLinkDataRate), + MakeDataRateChecker ()) + .AddAttribute ("S1uLinkDelay", + "The delay to be used for the next S1-U link to be created", + TimeValue (Seconds (0)), + MakeTimeAccessor (&PointToPointEpcHelper::m_s1uLinkDelay), + MakeTimeChecker ()) + .AddAttribute ("S1uLinkMtu", + "The MTU of the next S1-U link to be created. Note that, because of the additional GTP/UDP/IP tunneling overhead, you need a MTU larger than the end-to-end MTU that you want to support.", + UintegerValue (2000), + MakeUintegerAccessor (&PointToPointEpcHelper::m_s1uLinkMtu), + MakeUintegerChecker ()) + .AddAttribute ("X2LinkDataRate", + "The data rate to be used for the next X2 link to be created", + DataRateValue (DataRate ("10Gb/s")), + MakeDataRateAccessor (&PointToPointEpcHelper::m_x2LinkDataRate), + MakeDataRateChecker ()) + .AddAttribute ("X2LinkDelay", + "The delay to be used for the next X2 link to be created", + TimeValue (Seconds (0)), + MakeTimeAccessor (&PointToPointEpcHelper::m_x2LinkDelay), + MakeTimeChecker ()) + .AddAttribute ("X2LinkMtu", + "The MTU of the next X2 link to be created. Note that, because of some big X2 messages, you need a big MTU.", + UintegerValue (3000), + MakeUintegerAccessor (&PointToPointEpcHelper::m_x2LinkMtu), + MakeUintegerChecker ()) + ; + return tid; +} + +void +PointToPointEpcHelper::DoDispose () +{ + NS_LOG_FUNCTION (this); + m_tunDevice->SetSendCallback (MakeNullCallback, const Address&, const Address&, uint16_t> ()); + m_tunDevice = 0; + m_sgwPgwApp = 0; + m_sgwPgw->Dispose (); +} + + +void +PointToPointEpcHelper::AddEnb (Ptr enb, Ptr lteEnbNetDevice, uint16_t cellId) +{ + NS_LOG_FUNCTION (this << enb << lteEnbNetDevice << cellId); + + NS_ASSERT (enb == lteEnbNetDevice->GetNode ()); + + // add an IPv4 stack to the previously created eNB + InternetStackHelper internet; + internet.Install (enb); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after node creation: " << enb->GetObject ()->GetNInterfaces ()); + + // 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.SetDeviceAttribute ("Mtu", UintegerValue (m_s1uLinkMtu)); + p2ph.SetChannelAttribute ("Delay", TimeValue (m_s1uLinkDelay)); + NetDeviceContainer enbSgwDevices = p2ph.Install (enb, m_sgwPgw); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after installing p2p dev: " << enb->GetObject ()->GetNInterfaces ()); + Ptr enbDev = enbSgwDevices.Get (0); + Ptr sgwDev = enbSgwDevices.Get (1); + m_s1uIpv4AddressHelper.NewNetwork (); + Ipv4InterfaceContainer enbSgwIpIfaces = m_s1uIpv4AddressHelper.Assign (enbSgwDevices); + NS_LOG_LOGIC ("number of Ipv4 ifaces of the eNB after assigning Ipv4 addr to S1 dev: " << enb->GetObject ()->GetNInterfaces ()); + + 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")); + int retval = enbS1uSocket->Bind (InetSocketAddress (enbAddress, m_gtpuUdpPort)); + NS_ASSERT (retval == 0); + + + // give PacketSocket powers to the eNB + //PacketSocketHelper packetSocket; + //packetSocket.Install (enb); + + // create LTE socket for the ENB + Ptr enbLteSocket = Socket::CreateSocket (enb, TypeId::LookupByName ("ns3::PacketSocketFactory")); + PacketSocketAddress enbLteSocketBindAddress; + enbLteSocketBindAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketBindAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); + retval = enbLteSocket->Bind (enbLteSocketBindAddress); + NS_ASSERT (retval == 0); + PacketSocketAddress enbLteSocketConnectAddress; + enbLteSocketConnectAddress.SetPhysicalAddress (Mac48Address::GetBroadcast ()); + enbLteSocketConnectAddress.SetSingleDevice (lteEnbNetDevice->GetIfIndex ()); + enbLteSocketConnectAddress.SetProtocol (Ipv4L3Protocol::PROT_NUMBER); + retval = enbLteSocket->Connect (enbLteSocketConnectAddress); + NS_ASSERT (retval == 0); + + + NS_LOG_INFO ("create EpcEnbApplication"); + Ptr enbApp = CreateObject (enbLteSocket, enbS1uSocket, enbAddress, sgwAddress, cellId); + enb->AddApplication (enbApp); + 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 (); + enb->AggregateObject (x2); + + NS_LOG_INFO ("connect S1-AP interface"); + m_mme->AddEnb (cellId, enbAddress, enbApp->GetS1apSapEnb ()); + m_sgwPgwApp->AddEnb (cellId, enbAddress, sgwAddress); + enbApp->SetS1apSapMme (m_mme->GetS1apSapMme ()); +} + + +void +PointToPointEpcHelper::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; + 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 enb1X2Address = enbIpIfaces.GetAddress (0); + Ipv4Address enb2X2Address = enbIpIfaces.GetAddress (1); + + // Add X2 interface to both eNBs' X2 entities + Ptr enb1X2 = enb1->GetObject (); + Ptr enb1LteDev = enb1->GetDevice (0)->GetObject (); + uint16_t enb1CellId = enb1LteDev->GetCellId (); + NS_LOG_LOGIC ("LteEnbNetDevice #1 = " << enb1LteDev << " - CellId = " << enb1CellId); + + Ptr enb2X2 = enb2->GetObject (); + Ptr enb2LteDev = enb2->GetDevice (0)->GetObject (); + uint16_t enb2CellId = enb2LteDev->GetCellId (); + NS_LOG_LOGIC ("LteEnbNetDevice #2 = " << enb2LteDev << " - CellId = " << enb2CellId); + + enb1X2->AddX2Interface (enb1CellId, enb1X2Address, enb2CellId, enb2X2Address); + enb2X2->AddX2Interface (enb2CellId, enb2X2Address, enb1CellId, enb1X2Address); + + enb1LteDev->GetRrc ()->AddX2Neighbour (enb2LteDev->GetCellId ()); + enb2LteDev->GetRrc ()->AddX2Neighbour (enb1LteDev->GetCellId ()); +} + + +void +PointToPointEpcHelper::AddUe (Ptr ueDevice, uint64_t imsi) +{ + NS_LOG_FUNCTION (this << imsi << ueDevice ); + + m_mme->AddUe (imsi); + m_sgwPgwApp->AddUe (imsi); + + +} + +void +PointToPointEpcHelper::ActivateEpsBearer (Ptr ueDevice, uint64_t imsi, Ptr tft, EpsBearer bearer) +{ + NS_LOG_FUNCTION (this << ueDevice << imsi); + + // we now retrieve the IPv4 address of the UE and notify it to the SGW; + // we couldn't do it before since address assignment is triggered by + // the user simulation program, rather than done by the EPC + Ptr ueNode = ueDevice->GetNode (); + Ptr ueIpv4 = ueNode->GetObject (); + NS_ASSERT_MSG (ueIpv4 != 0, "UEs need to have IPv4 installed before EPS bearers can be activated"); + int32_t interface = ueIpv4->GetInterfaceForDevice (ueDevice); + NS_ASSERT (interface >= 0); + NS_ASSERT (ueIpv4->GetNAddresses (interface) == 1); + Ipv4Address ueAddr = ueIpv4->GetAddress (interface, 0).GetLocal (); + NS_LOG_LOGIC (" UE IP address: " << ueAddr); m_sgwPgwApp->SetUeAddress (imsi, ueAddr); + + m_mme->AddBearer (imsi, tft, bearer); + Ptr ueLteDevice = ueDevice->GetObject (); + if (ueLteDevice) + { + ueLteDevice->GetNas ()->ActivateEpsBearer (bearer, tft); + } +} + + +Ptr +PointToPointEpcHelper::GetPgwNode () +{ + return m_sgwPgw; +} + + +Ipv4InterfaceContainer +PointToPointEpcHelper::AssignUeIpv4Address (NetDeviceContainer ueDevices) +{ + return m_ueAddressHelper.Assign (ueDevices); +} + + + +Ipv4Address +PointToPointEpcHelper::GetUeDefaultGatewayAddress () +{ + // return the address of the tun device + return m_sgwPgw->GetObject ()->GetAddress (1, 0).GetLocal (); +} + + +} // namespace ns3