diff --git a/AUTHORS b/AUTHORS index eaf61ef5e..5822aa221 100644 --- a/AUTHORS +++ b/AUTHORS @@ -156,3 +156,4 @@ Florian Westphal (fw@strlen.de) He Wu (mdzz@u.washington.edu) Yoshihiko Yazawa (yoshiyaz@gmail.com) Dizhi Zhou (dizhi.zhou@gmail.com) +Gaurav Sathe (gaurav.sathe@tcs.com) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 3d1013a92..ff719f9c2 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -48,6 +48,11 @@ New user-visible features - Fixes to support Python >= 3.3 in ns3 Python bindings - Enable selection of high precision int64x64_t implementation at configure time, for debugging purposes. +- In LENA NS3.20, bearer release functionality is partially present. + As an enhancement, complete release bearer functionality is provided on access and core side(3GPP compliant). + A new procedure 'DeActivateDedicatedEpsBearer' is defined in LTEHelper for the same. + Related output can be seen through the stats collected at different layers like PDCP, RLC, MAC, PHY. + To support the implementation, example and test suite is added under examples and tests folder. Bugs fixed ---------- diff --git a/src/lte/bindings/modulegen__gcc_ILP32.py b/src/lte/bindings/modulegen__gcc_ILP32.py index fe3df2b4c..a3a7ae320 100644 --- a/src/lte/bindings/modulegen__gcc_ILP32.py +++ b/src/lte/bindings/modulegen__gcc_ILP32.py @@ -2878,6 +2878,11 @@ def register_Ns3EpcEnbS1SapProvider_methods(root_module, cls): 'void', [param('uint16_t', 'rnti')], is_pure_virtual=True, is_virtual=True) + ## epc-enb-s1-sap.h (module 'lte'): void ns3::EpcEnbS1SapProvider::DoSendReleaseIndication(uint64_t imsi, uint16_t rnti, uint8_t bearerId) [member function] + cls.add_method('DoSendReleaseIndication', + 'void', + [param('uint64_t', 'imsi'), param('uint16_t', 'rnti'), param('uint8_t', 'bearerId')], + is_pure_virtual=True, is_virtual=True) return def register_Ns3EpcEnbS1SapProviderBearerToBeSwitched_methods(root_module, cls): @@ -3000,6 +3005,11 @@ def register_Ns3EpcS11SapMme_methods(root_module, cls): 'void', [param('ns3::EpcS11SapMme::ModifyBearerResponseMessage', 'msg')], is_pure_virtual=True, is_virtual=True) + ## epc-s11-sap.h (module 'lte'): void ns3::EpcS11SapMme::DeleteBearerRequest(ns3::EpcS11SapMme::DeleteBearerRequestMessage msg) [member function] + cls.add_method('DeleteBearerRequest', + 'void', + [param('ns3::EpcS11SapMme::DeleteBearerRequestMessage', 'msg')], + is_pure_virtual=True, is_virtual=True) return def register_Ns3EpcS11SapMmeBearerContextCreated_methods(root_module, cls): @@ -3050,6 +3060,16 @@ def register_Ns3EpcS11SapSgw_methods(root_module, cls): 'void', [param('ns3::EpcS11SapSgw::ModifyBearerRequestMessage', 'msg')], is_pure_virtual=True, is_virtual=True) + ## epc-s11-sap.h (module 'lte'): void ns3::EpcS11SapSgw::DeleteBearerCommand(ns3::EpcS11SapSgw::DeleteBearerCommandMessage msg) [member function] + cls.add_method('DeleteBearerCommand', + 'void', + [param('ns3::EpcS11SapSgw::DeleteBearerCommandMessage', 'msg')], + is_pure_virtual=True, is_virtual=True) + ## epc-s11-sap.h (module 'lte'): void ns3::EpcS11SapSgw::DeleteBearerResponse(ns3::EpcS11SapSgw::DeleteBearerResponseMessage msg) [member function] + cls.add_method('DeleteBearerResponse', + 'void', + [param('ns3::EpcS11SapSgw::DeleteBearerResponseMessage', 'msg')], + is_pure_virtual=True, is_virtual=True) return def register_Ns3EpcS11SapSgwBearerContextToBeCreated_methods(root_module, cls): @@ -3161,6 +3181,11 @@ def register_Ns3EpcS1apSapMme_methods(root_module, cls): 'void', [param('uint64_t', 'enbUeS1Id'), param('uint64_t', 'mmeUeS1Id'), param('uint16_t', 'gci'), param('std::list< ns3::EpcS1apSapMme::ErabSwitchedInDownlinkItem >', 'erabToBeSwitchedInDownlinkList')], is_pure_virtual=True, is_virtual=True) + ## epc-s1ap-sap.h (module 'lte'): void ns3::EpcS1apSapMme::ErabReleaseIndication(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, std::list erabToBeReleaseIndication) [member function] + cls.add_method('ErabReleaseIndication', + 'void', + [param('uint64_t', 'mmeUeS1Id'), param('uint16_t', 'enbUeS1Id'), param('std::list', 'erabToBeReleaseIndication')], + is_pure_virtual=True, is_virtual=True) return def register_Ns3EpcS1apSapMmeErabSetupItem_methods(root_module, cls): diff --git a/src/lte/examples/lena-deactivate-bearer.cc b/src/lte/examples/lena-deactivate-bearer.cc new file mode 100644 index 000000000..ef6d5ed54 --- /dev/null +++ b/src/lte/examples/lena-deactivate-bearer.cc @@ -0,0 +1,234 @@ +/* -*- 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: Gaurav Sathe + */ + +#include "ns3/lte-helper.h" +#include "ns3/epc-helper.h" +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/ipv4-global-routing-helper.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-helper.h" +#include "ns3/config-store.h" +//#include "ns3/gtk-config-store.h" + +using namespace ns3; + +/** + * Sample simulation script for LTE+EPC. It instantiates one eNodeB, + * attaches three UE to eNodeB starts a flow for each UE to and from a remote host. + * It also instantiates one dedicated bearer per UE + */ +NS_LOG_COMPONENT_DEFINE ("BearerDeactivateExample"); +int +main (int argc, char *argv[]) +{ + + uint16_t numberOfNodes = 1; + uint16_t numberOfUeNodes = 3; + double simTime = 1.1; + double distance = 60.0; + double interPacketInterval = 100; + + // Command line arguments + CommandLine cmd; + cmd.AddValue ("numberOfNodes", "Number of eNodeBs + UE pairs", numberOfNodes); + cmd.AddValue ("simTime", "Total duration of the simulation [s])", simTime); + cmd.AddValue ("distance", "Distance between eNBs [m]", distance); + cmd.AddValue ("interPacketInterval", "Inter packet interval [ms])", interPacketInterval); + cmd.Parse (argc, argv); + + Ptr lteHelper = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + ConfigStore inputConfig; + inputConfig.ConfigureDefaults (); + + // parse again so you can override default values from the command line + cmd.Parse (argc, argv); + + Ptr pgw = epcHelper->GetPgwNode (); + + // Enable Logging + LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL); + + LogComponentEnable ("BearerDeactivateExample", LOG_LEVEL_ALL); + LogComponentEnable ("LteHelper", logLevel); + LogComponentEnable ("EpcHelper", logLevel); + LogComponentEnable ("EpcEnbApplication", logLevel); + LogComponentEnable ("EpcSgwPgwApplication", logLevel); + LogComponentEnable ("EpcMme", logLevel); + LogComponentEnable ("LteEnbRrc", logLevel); + + + // 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); + // interface 0 is localhost, 1 is the p2p device + Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1); + + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1); + + NodeContainer ueNodes; + NodeContainer enbNodes; + enbNodes.Create (numberOfNodes); + ueNodes.Create (numberOfUeNodes); + + // Install Mobility Model + Ptr positionAlloc = CreateObject (); + for (uint16_t i = 0; i < numberOfNodes; 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 to the nodes + NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes); + NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes); + + // 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); + } + + // Attach a UE to a eNB + lteHelper->Attach (ueLteDevs, enbLteDevs.Get (0)); + + // Activate an EPS bearer on all UEs + + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ueDevice = ueLteDevs.Get (u); + GbrQosInformation qos; + qos.gbrDl = 132; // bit/s, considering IP, UDP, RLC, PDCP header size + qos.gbrUl = 132; + qos.mbrDl = qos.gbrDl; + qos.mbrUl = qos.gbrUl; + + enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; + EpsBearer bearer (q, qos); + bearer.arp.priorityLevel = 15 - (u + 1); + bearer.arp.preemptionCapability = true; + bearer.arp.preemptionVulnerability = true; + lteHelper->ActivateDedicatedEpsBearer (ueDevice, bearer, EpcTft::Default ()); + } + + + // Install and start applications on UEs and remote host + uint16_t dlPort = 1234; + uint16_t ulPort = 2000; + uint16_t otherPort = 3000; + ApplicationContainer clientApps; + ApplicationContainer serverApps; + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + ++ulPort; + ++otherPort; + PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), dlPort)); + PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), ulPort)); + PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), otherPort)); + serverApps.Add (dlPacketSinkHelper.Install (ueNodes.Get (u))); + serverApps.Add (ulPacketSinkHelper.Install (remoteHost)); + serverApps.Add (packetSinkHelper.Install (ueNodes.Get (u))); + + UdpClientHelper dlClient (ueIpIface.GetAddress (u), dlPort); + dlClient.SetAttribute ("Interval", TimeValue (MilliSeconds (interPacketInterval))); + dlClient.SetAttribute ("MaxPackets", UintegerValue (1000000)); + + UdpClientHelper ulClient (remoteHostAddr, ulPort); + ulClient.SetAttribute ("Interval", TimeValue (MilliSeconds (interPacketInterval))); + ulClient.SetAttribute ("MaxPackets", UintegerValue (1000000)); + + UdpClientHelper client (ueIpIface.GetAddress (u), otherPort); + client.SetAttribute ("Interval", TimeValue (MilliSeconds (interPacketInterval))); + client.SetAttribute ("MaxPackets", UintegerValue (1000000)); + + clientApps.Add (dlClient.Install (remoteHost)); + clientApps.Add (ulClient.Install (ueNodes.Get (u))); + if (u + 1 < ueNodes.GetN ()) + { + clientApps.Add (client.Install (ueNodes.Get (u + 1))); + } + else + { + clientApps.Add (client.Install (ueNodes.Get (0))); + } + } + + serverApps.Start (Seconds (0.030)); + clientApps.Start (Seconds (0.030)); + + double statsStartTime = 0.04; // need to allow for RRC connection establishment + SRS + double statsDuration = 1.0; + + lteHelper->EnableRlcTraces (); + Ptr rlcStats = lteHelper->GetRlcStats (); + rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime))); + rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration))); + + /* + * Schedule dedicated bearer de-activation at 'deActivateTime' + * Instantiate De-activation in sequence (Time deActivateTime, Ptr ueDevice, Ptr enbDevice, uint8_t bearerId) + */ + Time deActivateTime (Seconds (1.5)); + lteHelper->DeActivateDedicatedEpsBearer (deActivateTime,ueLteDevs.Get (0),enbLteDevs.Get (0), 2); + + //stop simulation after 3 seconds + Simulator::Stop (Seconds (3.0)); + + Simulator::Run (); + /*GtkConfigStore config; + config.ConfigureAttributes();*/ + + Simulator::Destroy (); + return 0; + +} + diff --git a/src/lte/examples/wscript b/src/lte/examples/wscript index 43c03f849..d8e0cbb93 100644 --- a/src/lte/examples/wscript +++ b/src/lte/examples/wscript @@ -34,6 +34,9 @@ def build(bld): obj = bld.create_ns3_program('lena-simple-epc', ['lte']) obj.source = 'lena-simple-epc.cc' + obj = bld.create_ns3_program('lena-deactivate-bearer', + ['lte']) + obj.source = 'lena-deactivate-bearer.cc' obj = bld.create_ns3_program('lena-x2-handover', ['lte']) obj.source = 'lena-x2-handover.cc' diff --git a/src/lte/helper/lte-helper.cc b/src/lte/helper/lte-helper.cc index 744f71ca2..8d24d699e 100644 --- a/src/lte/helper/lte-helper.cc +++ b/src/lte/helper/lte-helper.cc @@ -813,8 +813,8 @@ DrbActivator::ActivateDrb (uint64_t imsi, uint16_t cellId, uint16_t rnti) Ptr enbRrc = enbLteDevice->GetObject ()->GetRrc (); NS_ASSERT (ueRrc->GetCellId () == enbLteDevice->GetCellId ()); Ptr ueManager = enbRrc->GetUeManager (rnti); - NS_ASSERT (ueManager->GetState () == UeManager::CONNECTED_NORMALLY || - ueManager->GetState () == UeManager::CONNECTION_RECONFIGURATION); + NS_ASSERT (ueManager->GetState () == UeManager::CONNECTED_NORMALLY + || ueManager->GetState () == UeManager::CONNECTION_RECONFIGURATION); EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params; params.rnti = rnti; params.bearer = m_bearer; @@ -892,8 +892,30 @@ LteHelper::DoHandoverRequest (Ptr ueDev, Ptr sourceEnbDev, sourceRrc->SendHandoverRequest (rnti, targetCellId); } +void +LteHelper::DeActivateDedicatedEpsBearer (Time deActivateTime, Ptr ueDevice,Ptr enbDevice, uint8_t bearerId) +{ + NS_LOG_FUNCTION (this << ueDevice << bearerId); + NS_ASSERT_MSG (m_epcHelper != 0, "Dedicated EPS bearers cannot be de-activated when the EPC is not used"); + NS_ASSERT_MSG (bearerId != 1, "Default bearer cannot be de-activated until and unless and UE is released"); + + Simulator::Schedule (deActivateTime, &LteHelper::DoDeActivateDedicatedEpsBearer, this, ueDevice, enbDevice, bearerId); +} + +void +LteHelper::DoDeActivateDedicatedEpsBearer (Ptr ueDevice, Ptr enbDevice, uint8_t bearerId) +{ + NS_LOG_FUNCTION (this << ueDevice << bearerId); + + //Extract IMSI and rnti + uint64_t imsi = ueDevice->GetObject ()->GetImsi (); + uint16_t rnti = ueDevice->GetObject ()->GetRrc ()->GetRnti (); + Ptr enbRrc = enbDevice->GetObject ()->GetRrc (); + + enbRrc->DoSendReleaseDataRadioBearer (imsi,rnti,bearerId); +} void diff --git a/src/lte/helper/lte-helper.h b/src/lte/helper/lte-helper.h index ad971144b..b837aca4f 100644 --- a/src/lte/helper/lte-helper.h +++ b/src/lte/helper/lte-helper.h @@ -325,6 +325,17 @@ public: */ void ActivateDedicatedEpsBearer (Ptr ueDevice, EpsBearer bearer, Ptr tft); + /** + * \brief Manually trigger dedicated bearer de-activation at specific simulation time + * \param deActivateTime when the dedicated bearer de-activation to be initiated + * \param ueDevice the UE on which dedicated bearer to be de-activated must be of the type LteUeNetDevice + * \param enbDevice eNB, must be of the type LteEnbNetDevice + * \param bearerId Bearer Identity which is to be de-activated + * + * \warning Requires the use of EPC mode. See SetEpcHelper() method. + */ + + void DeActivateDedicatedEpsBearer (Time deActivateTime, Ptr ueDevice, Ptr enbDevice, uint8_t bearerId); /** * Create an X2 interface between all the eNBs in a given set @@ -479,10 +490,13 @@ public: */ Ptr GetPdcpStats (void); - enum LteEpsBearerToRlcMapping_t {RLC_SM_ALWAYS = 1, + enum LteEpsBearerToRlcMapping_t + { + RLC_SM_ALWAYS = 1, RLC_UM_ALWAYS = 2, RLC_AM_ALWAYS = 3, - PER_BASED = 4}; + PER_BASED = 4 + }; /** * Assign a fixed random variable stream number to the random variables @@ -531,6 +545,19 @@ private: Ptr sourceEnbDev, Ptr targetEnbDev); + + /** + * \brief The actual function to trigger a manual bearer de-activation + * \param ueDevice the UE on which bearer to be de-activated must be of the type LteUeNetDevice + * \param enbDevice eNB, must be of the type LteEnbNetDevice + * \param bearerId Bearer Identity which is to be de-activated + * + * This method is normally scheduled by DeActivateDedicatedEpsBearer() to run at a specific + * time when a manual bearer de-activation is desired by the simulation user. + */ + void DoDeActivateDedicatedEpsBearer (Ptr ueDevice, Ptr enbDevice, uint8_t bearerId); + + Ptr m_downlinkChannel; Ptr m_uplinkChannel; diff --git a/src/lte/helper/radio-bearer-stats-calculator.cc b/src/lte/helper/radio-bearer-stats-calculator.cc index bb536bd6b..b7dd7a988 100644 --- a/src/lte/helper/radio-bearer-stats-calculator.cc +++ b/src/lte/helper/radio-bearer-stats-calculator.cc @@ -26,8 +26,7 @@ #include #include -namespace ns3 -{ +namespace ns3 { NS_LOG_COMPONENT_DEFINE ("RadioBearerStatsCalculator"); diff --git a/src/lte/model/epc-enb-application.cc b/src/lte/model/epc-enb-application.cc index cf3efc1ac..b43ebcec0 100644 --- a/src/lte/model/epc-enb-application.cc +++ b/src/lte/model/epc-enb-application.cc @@ -310,8 +310,18 @@ EpcEnbApplication::SendToS1uSocket (Ptr packet, uint32_t teid) gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8); packet->AddHeader (gtpu); uint32_t flags = 0; - m_s1uSocket->SendTo (packet, flags, InetSocketAddress(m_sgwS1uAddress, m_gtpuUdpPort)); + m_s1uSocket->SendTo (packet, flags, InetSocketAddress (m_sgwS1uAddress, m_gtpuUdpPort)); } - -}; // namespace ns3 +void +EpcEnbApplication::DoReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId) +{ + NS_LOG_FUNCTION (this << bearerId ); + std::list erabToBeReleaseIndication; + EpcS1apSapMme::ErabToBeReleasedIndication erab; + erab.erabId = bearerId; + erabToBeReleaseIndication.push_back (erab); + //From 3GPP TS 23401-950 Section 5.4.4.2, enB sends EPS bearer Identity in Bearer Release Indication message to MME + m_s1apSapMme->ErabReleaseIndication (imsi, rnti, erabToBeReleaseIndication); +} +} // namespace ns3 diff --git a/src/lte/model/epc-enb-application.h b/src/lte/model/epc-enb-application.h index df091de1b..590642295 100644 --- a/src/lte/model/epc-enb-application.h +++ b/src/lte/model/epc-enb-application.h @@ -150,6 +150,15 @@ private: void DoPathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list erabToBeSwitchedInUplinkList); /** + * \brief This function accepts bearer id corresponding to a particular UE and schedules indication of bearer release towards MME + * \param imsi maps to mmeUeS1Id + * \param rnti maps to enbUeS1Id + * \param bearerId Bearer Identity which is to be de-activated + */ + void DoReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId); + + + /** * Send a packet to the UE via the LTE radio interface of the eNB * * \param packet t diff --git a/src/lte/model/epc-enb-s1-sap.h b/src/lte/model/epc-enb-s1-sap.h index caddc75cc..2d3224eb9 100644 --- a/src/lte/model/epc-enb-s1-sap.h +++ b/src/lte/model/epc-enb-s1-sap.h @@ -49,6 +49,13 @@ public: */ virtual void InitialUeMessage (uint64_t imsi, uint16_t rnti) = 0; + /** + * \brief Triggers epc-enb-application to send ERAB Release Indication message towards MME + * \param imsi the UE IMSI + * \param rnti the UE RNTI + * \param bearerId Bearer Identity which is to be de-activated + */ + virtual void DoSendReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId) = 0; struct BearerToBeSwitched { @@ -139,6 +146,8 @@ public: // inherited from EpcEnbS1SapProvider virtual void InitialUeMessage (uint64_t imsi, uint16_t rnti); + virtual void DoSendReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId); + virtual void PathSwitchRequest (PathSwitchRequestParameters params); virtual void UeContextRelease (uint16_t rnti); @@ -165,6 +174,11 @@ void MemberEpcEnbS1SapProvider::InitialUeMessage (uint64_t imsi, uint16_t rnt m_owner->DoInitialUeMessage (imsi, rnti); } +template +void MemberEpcEnbS1SapProvider::DoSendReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId) +{ + m_owner->DoReleaseIndication (imsi, rnti, bearerId); +} template void MemberEpcEnbS1SapProvider::PathSwitchRequest (PathSwitchRequestParameters params) diff --git a/src/lte/model/epc-mme.cc b/src/lte/model/epc-mme.cc index e6da9f4b4..62d3fa389 100644 --- a/src/lte/model/epc-mme.cc +++ b/src/lte/model/epc-mme.cc @@ -221,4 +221,66 @@ EpcMme::DoModifyBearerResponse (EpcS11SapMme::ModifyBearerResponseMessage msg) jt->second->s1apSapEnb->PathSwitchRequestAcknowledge (enbUeS1Id, mmeUeS1Id, cgi, erabToBeSwitchedInUplinkList); } +void +EpcMme::DoErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabToBeReleaseIndication) +{ + NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id); + uint64_t imsi = mmeUeS1Id; + std::map >::iterator it = m_ueInfoMap.find (imsi); + NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); + + EpcS11SapSgw::DeleteBearerCommandMessage msg; + // trick to avoid the need for allocating TEIDs on the S11 interface + msg.teid = imsi; + + for (std::list::iterator bit = erabToBeReleaseIndication.begin (); bit != erabToBeReleaseIndication.end (); ++bit) + { + EpcS11SapSgw::BearerContextToBeRemoved bearerContext; + bearerContext.epsBearerId = bit->erabId; + msg.bearerContextsToBeRemoved.push_back (bearerContext); + } + //Delete Bearer command towards epc-sgw-pgw-application + m_s11SapSgw->DeleteBearerCommand (msg); +} + +void +EpcMme::DoDeleteBearerRequest (EpcS11SapMme::DeleteBearerRequestMessage msg) +{ + NS_LOG_FUNCTION (this); + uint64_t imsi = msg.teid; + std::map >::iterator it = m_ueInfoMap.find (imsi); + NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi); + EpcS11SapSgw::DeleteBearerResponseMessage res; + + res.teid = imsi; + + for (std::list::iterator bit = msg.bearerContextsRemoved.begin (); + bit != msg.bearerContextsRemoved.end (); + ++bit) + { + EpcS11SapSgw::BearerContextRemovedSgwPgw bearerContext; + bearerContext.epsBearerId = bit->epsBearerId; + res.bearerContextsRemoved.push_back (bearerContext); + + RemoveBearer (it->second, bearerContext.epsBearerId); //schedules function to erase, context of de-activated bearer + } + //schedules Delete Bearer Response towards epc-sgw-pgw-application + m_s11SapSgw->DeleteBearerResponse (res); +} + +void EpcMme::RemoveBearer (Ptr ueInfo, uint8_t epsBearerId) +{ + NS_LOG_FUNCTION (this << epsBearerId); + for (std::list::iterator bit = ueInfo->bearersToBeActivated.begin (); + bit != ueInfo->bearersToBeActivated.end (); + ++bit) + { + if (bit->bearerId == epsBearerId) + { + ueInfo->bearersToBeActivated.erase (bit); + break; + } + } +} + } // namespace ns3 diff --git a/src/lte/model/epc-mme.h b/src/lte/model/epc-mme.h index f36b2e793..99085bfbd 100644 --- a/src/lte/model/epc-mme.h +++ b/src/lte/model/epc-mme.h @@ -115,11 +115,13 @@ private: void DoInitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi); void DoInitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabSetupList); void DoPathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list erabToBeSwitchedInDownlinkList); - + void DoErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabToBeReleaseIndication); // S11 SAP MME forwarded methods void DoCreateSessionResponse (EpcS11SapMme::CreateSessionResponseMessage msg); void DoModifyBearerResponse (EpcS11SapMme::ModifyBearerResponseMessage msg); + void DoDeleteBearerRequest (EpcS11SapMme::DeleteBearerRequestMessage msg); + /** * Hold info on an EPS bearer to be activated @@ -152,6 +154,13 @@ private: */ std::map > m_ueInfoMap; + /** + * \brief This Function erases all contexts of bearer from MME side + * \param ueInfo UE information pointer + * \param epsBearerId Bearer Id which need to be removed corresponding to UE + */ + void RemoveBearer (Ptr ueInfo, uint8_t epsBearerId); + /** * Hold info on a ENB * diff --git a/src/lte/model/epc-s11-sap.h b/src/lte/model/epc-s11-sap.h index fd2c8056d..9d5c9083c 100644 --- a/src/lte/model/epc-s11-sap.h +++ b/src/lte/model/epc-s11-sap.h @@ -103,6 +103,27 @@ public: */ virtual void CreateSessionResponse (CreateSessionResponseMessage msg) = 0; + struct BearerContextRemoved + { + uint8_t epsBearerId; + }; + + /** + * Delete Bearer Request message, see 3GPP TS 29.274 Release 9 V9.3.0 section 7.2.9.2 + */ + struct DeleteBearerRequestMessage : public GtpcMessage + { + std::list bearerContextsRemoved; + }; + + /** + * \brief As per 3GPP TS 29.274 Release 9 V9.3.0, a Delete Bearer Request message shall be sent on the S11 interface by PGW to SGW and from SGW to MME + * \param msg the message + */ + virtual void DeleteBearerRequest (DeleteBearerRequestMessage msg) = 0; + + + /** * Modify Bearer Response message, see 3GPP TS 29.274 7.2.7 @@ -162,6 +183,43 @@ public: */ virtual void CreateSessionRequest (CreateSessionRequestMessage msg) = 0; + struct BearerContextToBeRemoved + { + uint8_t epsBearerId; + }; + + /** + * Delete Bearer Command message, see 3GPP TS 29.274 Release 9 V9.3.0 section 7.2.17.1 + */ + struct DeleteBearerCommandMessage : public GtpcMessage + { + std::list bearerContextsToBeRemoved; + }; + + /** + * \brief As per 3GPP TS 29.274 Release 9 V9.3.0, a Delete Bearer Command message shall be sent on the S11 interface by the MME to the SGW + */ + virtual void DeleteBearerCommand (DeleteBearerCommandMessage msg) = 0; + + + struct BearerContextRemovedSgwPgw + { + uint8_t epsBearerId; + }; + + /** + * Delete Bearer Response message, see 3GPP TS 29.274 Release 9 V9.3.0 section 7.2.10.2 + */ + struct DeleteBearerResponseMessage : public GtpcMessage + { + std::list bearerContextsRemoved; + }; + + /** + * \brief As per 3GPP TS 29.274 Release 9 V9.3.0, a Delete Bearer Command message shall be sent on the S11 interface by the MME to the SGW + * \param msg the message + */ + virtual void DeleteBearerResponse (DeleteBearerResponseMessage msg) = 0; /** * Modify Bearer Request message, see 3GPP TS 29.274 7.2.7 @@ -200,6 +258,7 @@ public: // inherited from EpcS11SapMme virtual void CreateSessionResponse (CreateSessionResponseMessage msg); virtual void ModifyBearerResponse (ModifyBearerResponseMessage msg); + virtual void DeleteBearerRequest (DeleteBearerRequestMessage msg); private: MemberEpcS11SapMme (); @@ -223,6 +282,12 @@ void MemberEpcS11SapMme::CreateSessionResponse (CreateSessionResponseMessage m_owner->DoCreateSessionResponse (msg); } +template +void MemberEpcS11SapMme::DeleteBearerRequest (DeleteBearerRequestMessage msg) +{ + m_owner->DoDeleteBearerRequest (msg); +} + template void MemberEpcS11SapMme::ModifyBearerResponse (ModifyBearerResponseMessage msg) { @@ -247,6 +312,8 @@ public: // inherited from EpcS11SapSgw virtual void CreateSessionRequest (CreateSessionRequestMessage msg); virtual void ModifyBearerRequest (ModifyBearerRequestMessage msg); + virtual void DeleteBearerCommand (DeleteBearerCommandMessage msg); + virtual void DeleteBearerResponse (DeleteBearerResponseMessage msg); private: MemberEpcS11SapSgw (); @@ -276,10 +343,17 @@ void MemberEpcS11SapSgw::ModifyBearerRequest (ModifyBearerRequestMessage msg) m_owner->DoModifyBearerRequest (msg); } +template +void MemberEpcS11SapSgw::DeleteBearerCommand (DeleteBearerCommandMessage msg) +{ + m_owner->DoDeleteBearerCommand (msg); +} - - - +template +void MemberEpcS11SapSgw::DeleteBearerResponse (DeleteBearerResponseMessage msg) +{ + m_owner->DoDeleteBearerResponse (msg); +} diff --git a/src/lte/model/epc-s1ap-sap.h b/src/lte/model/epc-s1ap-sap.h index f449e35fe..a82d80d03 100644 --- a/src/lte/model/epc-s1ap-sap.h +++ b/src/lte/model/epc-s1ap-sap.h @@ -60,6 +60,24 @@ public: virtual void InitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t stmsi, uint16_t ecgi) = 0; + /** + * E-RAB Release Indication Item IEs, 3GPP TS 36.413 version 9.8.0 section 9.1.3.7 + * + */ + struct ErabToBeReleasedIndication + { + uint8_t erabId; + }; + + /** + * \brief As per 3GPP TS 23.401 Release 9 V9.5.0 Figure 5.4.4.2-1 eNB sends indication of Bearer Release to MME + * \param mmeUeS1Id in practice, we use the IMSI + * \param enbUeS1Id in practice, we use the RNTI + * \param erabToBeReleaseIndication, List of bearers to be deactivated + * + */ + virtual void ErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabToBeReleaseIndication ) = 0; + /** * E-RAB Setup Item IEs, see 3GPP TS 36.413 9.1.4.2 * @@ -174,6 +192,8 @@ public: // inherited from EpcS1apSapMme virtual void InitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi); + virtual void ErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabToBeReleaseIndication ); + virtual void InitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabSetupList); virtual void PathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list erabToBeSwitchedInDownlinkList); @@ -199,6 +219,12 @@ void MemberEpcS1apSapMme::InitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbU m_owner->DoInitialUeMessage (mmeUeS1Id, enbUeS1Id, imsi, ecgi); } +template +void MemberEpcS1apSapMme::ErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabToBeReleaseIndication) +{ + m_owner->DoErabReleaseIndication (mmeUeS1Id, enbUeS1Id, erabToBeReleaseIndication); +} + template void MemberEpcS1apSapMme::InitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list erabSetupList) { diff --git a/src/lte/model/epc-sgw-pgw-application.cc b/src/lte/model/epc-sgw-pgw-application.cc index 75cdfde8f..bb085f0a4 100644 --- a/src/lte/model/epc-sgw-pgw-application.cc +++ b/src/lte/model/epc-sgw-pgw-application.cc @@ -51,6 +51,13 @@ EpcSgwPgwApplication::UeInfo::AddBearer (Ptr tft, uint8_t bearerId, uint return m_tftClassifier.Add (tft, teid); } +void +EpcSgwPgwApplication::UeInfo::RemoveBearer (uint8_t bearerId) +{ + NS_LOG_FUNCTION (this << bearerId); + m_teidByBearerIdMap.erase (bearerId); +} + uint32_t EpcSgwPgwApplication::UeInfo::Classify (Ptr p) { @@ -144,7 +151,7 @@ EpcSgwPgwApplication::RecvFromTunDevice (Ptr packet, const Address& sour std::map >::iterator it = m_ueInfoByAddrMap.find (ueAddr); if (it == m_ueInfoByAddrMap.end ()) { - NS_LOG_WARN ("unknown UE address " << ueAddr) ; + NS_LOG_WARN ("unknown UE address " << ueAddr); } else { @@ -204,7 +211,7 @@ EpcSgwPgwApplication::SendToS1uSocket (Ptr packet, Ipv4Address enbAddr, gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8); packet->AddHeader (gtpu); uint32_t flags = 0; - m_s1uSocket->SendTo (packet, flags, InetSocketAddress(enbAddr, m_gtpuUdpPort)); + m_s1uSocket->SendTo (packet, flags, InetSocketAddress (enbAddr, m_gtpuUdpPort)); } @@ -305,4 +312,44 @@ EpcSgwPgwApplication::DoModifyBearerRequest (EpcS11SapSgw::ModifyBearerRequestMe m_s11SapMme->ModifyBearerResponse (res); } -}; // namespace ns3 +void +EpcSgwPgwApplication::DoDeleteBearerCommand (EpcS11SapSgw::DeleteBearerCommandMessage req) +{ + NS_LOG_FUNCTION (this << req.teid); + uint64_t imsi = req.teid; // trick to avoid the need for allocating TEIDs on the S11 interface + std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); + NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); + + EpcS11SapMme::DeleteBearerRequestMessage res; + res.teid = imsi; + + for (std::list::iterator bit = req.bearerContextsToBeRemoved.begin (); + bit != req.bearerContextsToBeRemoved.end (); + ++bit) + { + EpcS11SapMme::BearerContextRemoved bearerContext; + bearerContext.epsBearerId = bit->epsBearerId; + res.bearerContextsRemoved.push_back (bearerContext); + } + //schedules Delete Bearer Request towards MME + m_s11SapMme->DeleteBearerRequest (res); +} + +void +EpcSgwPgwApplication::DoDeleteBearerResponse (EpcS11SapSgw::DeleteBearerResponseMessage req) +{ + NS_LOG_FUNCTION (this << req.teid); + uint64_t imsi = req.teid; // trick to avoid the need for allocating TEIDs on the S11 interface + std::map >::iterator ueit = m_ueInfoByImsiMap.find (imsi); + NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi); + + for (std::list::iterator bit = req.bearerContextsRemoved.begin (); + bit != req.bearerContextsRemoved.end (); + ++bit) + { + //Function to remove de-activated bearer contexts from S-Gw and P-Gw side + ueit->second->RemoveBearer (bit->epsBearerId); + } +} + +} // namespace ns3 diff --git a/src/lte/model/epc-sgw-pgw-application.h b/src/lte/model/epc-sgw-pgw-application.h index 571dd5353..b315cfced 100644 --- a/src/lte/model/epc-sgw-pgw-application.h +++ b/src/lte/model/epc-sgw-pgw-application.h @@ -156,12 +156,16 @@ private: void DoCreateSessionRequest (EpcS11SapSgw::CreateSessionRequestMessage msg); void DoModifyBearerRequest (EpcS11SapSgw::ModifyBearerRequestMessage msg); + void DoDeleteBearerCommand (EpcS11SapSgw::DeleteBearerCommandMessage req); + void DoDeleteBearerResponse (EpcS11SapSgw::DeleteBearerResponseMessage req); + + /** * store info for each UE connected to this SGW */ class UeInfo : public SimpleRefCount { - public: +public: UeInfo (); /** @@ -173,6 +177,12 @@ private: void AddBearer (Ptr tft, uint8_t epsBearerId, uint32_t teid); /** + * \brief Function, deletes contexts of bearer on SGW and PGW side + * \param bearerId, the Bearer Id whose contexts to be removed + */ + void RemoveBearer (uint8_t bearerId); + + /** * * * \param p the IP packet from the internet to be classified diff --git a/src/lte/model/lte-enb-mac.cc b/src/lte/model/lte-enb-mac.cc index 4529df243..55ea8c62a 100644 --- a/src/lte/model/lte-enb-mac.cc +++ b/src/lte/model/lte-enb-mac.cc @@ -544,13 +544,13 @@ LteEnbMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo) std::vector ::iterator itCqi; for (uint16_t i = 0; i < m_ulCqiReceived.size (); i++) { - if (subframeNo>1) + if (subframeNo > 1) { m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & frameNo) << 4) | (0xF & (subframeNo - 1)); } else { - m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & (frameNo-1)) << 4) | (0xF & 10); + m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & (frameNo - 1)) << 4) | (0xF & 10); } m_schedSapProvider->SchedUlCqiInfoReq (m_ulCqiReceived.at (i)); } @@ -571,14 +571,14 @@ LteEnbMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo) uint32_t ulSchedFrameNo = m_frameNo; uint32_t ulSchedSubframeNo = m_subframeNo; // NS_LOG_DEBUG (this << " sfn " << frameNo << " sbfn " << subframeNo); - if (ulSchedSubframeNo + (m_macChTtiDelay+UL_PUSCH_TTIS_DELAY) > 10) + if (ulSchedSubframeNo + (m_macChTtiDelay + UL_PUSCH_TTIS_DELAY) > 10) { ulSchedFrameNo++; - ulSchedSubframeNo = (ulSchedSubframeNo + (m_macChTtiDelay+UL_PUSCH_TTIS_DELAY)) % 10; + ulSchedSubframeNo = (ulSchedSubframeNo + (m_macChTtiDelay + UL_PUSCH_TTIS_DELAY)) % 10; } else { - ulSchedSubframeNo = ulSchedSubframeNo + (m_macChTtiDelay+UL_PUSCH_TTIS_DELAY); + ulSchedSubframeNo = ulSchedSubframeNo + (m_macChTtiDelay + UL_PUSCH_TTIS_DELAY); } FfMacSchedSapProvider::SchedUlTriggerReqParameters ulparams; ulparams.m_sfnSf = ((0x3FF & ulSchedFrameNo) << 4) | (0xF & ulSchedSubframeNo); @@ -711,9 +711,13 @@ LteEnbMac::DoReceivePhyPdu (Ptr p) std::map >::iterator rntiIt = m_rlcAttached.find (rnti); NS_ASSERT_MSG (rntiIt != m_rlcAttached.end (), "could not find RNTI" << rnti); std::map::iterator lcidIt = rntiIt->second.find (lcid); - NS_ASSERT_MSG (lcidIt != rntiIt->second.end (), "could not find LCID" << lcid); - (*lcidIt).second->ReceivePdu (p); + //NS_ASSERT_MSG (lcidIt != rntiIt->second.end (), "could not find LCID" << lcid); + //Receive PDU only if LCID is found + if (lcidIt != rntiIt->second.end ()) + { + (*lcidIt).second->ReceivePdu (p); + } } @@ -840,7 +844,16 @@ LteEnbMac::DoReconfigureLc (LteEnbCmacSapProvider::LcInfo lcinfo) void LteEnbMac::DoReleaseLc (uint16_t rnti, uint8_t lcid) { - NS_FATAL_ERROR ("not implemented"); + NS_LOG_FUNCTION (this); + + //Find user based on rnti and then erase lcid stored against the same + std::map >::iterator rntiIt = m_rlcAttached.find (rnti); + rntiIt->second.erase (lcid); + + struct FfMacCschedSapProvider::CschedLcReleaseReqParameters params; + params.m_rnti = rnti; + params.m_logicalChannelIdentity.push_back (lcid); + m_cschedSapProvider->CschedLcReleaseReq (params); } void @@ -919,8 +932,8 @@ LteEnbMac::DoTransmitPdu (LteMacSapProvider::TransmitPduParameters params) params.pdu->AddPacketTag (tag); // Store pkt in HARQ buffer std::map ::iterator it = m_miDlHarqProcessesPackets.find (params.rnti); - NS_ASSERT (it!=m_miDlHarqProcessesPackets.end ()); - NS_LOG_DEBUG (this << " LAYER " <<(uint16_t)tag.GetLayer () << " HARQ ID " << (uint16_t)params.harqProcessId); + NS_ASSERT (it != m_miDlHarqProcessesPackets.end ()); + NS_LOG_DEBUG (this << " LAYER " << (uint16_t)tag.GetLayer () << " HARQ ID " << (uint16_t)params.harqProcessId); //(*it).second.at (params.layer).at (params.harqProcessId) = params.pdu;//->Copy (); (*it).second.at (params.layer).at (params.harqProcessId)->AddPacket (params.pdu); @@ -966,8 +979,8 @@ LteEnbMac::DoSchedDlConfigInd (FfMacSchedSapUser::SchedDlConfigIndParameters ind { // new data -> force emptying correspondent harq pkt buffer std::map ::iterator it = m_miDlHarqProcessesPackets.find (ind.m_buildDataList.at (i).m_rnti); - NS_ASSERT(it!=m_miDlHarqProcessesPackets.end()); - for (uint16_t lcId = 0; lcId < (*it).second.size (); lcId ++) + NS_ASSERT (it != m_miDlHarqProcessesPackets.end ()); + for (uint16_t lcId = 0; lcId < (*it).second.size (); lcId++) { Ptr pb = CreateObject (); (*it).second.at (lcId).at (ind.m_buildDataList.at (i).m_dci.m_harqProcess) = pb; @@ -992,11 +1005,11 @@ LteEnbMac::DoSchedDlConfigInd (FfMacSchedSapUser::SchedDlConfigIndParameters ind } else { - if (ind.m_buildDataList.at (i).m_dci.m_tbsSize.at (k)>0) + if (ind.m_buildDataList.at (i).m_dci.m_tbsSize.at (k) > 0) { // HARQ retransmission -> retrieve TB from HARQ buffer std::map ::iterator it = m_miDlHarqProcessesPackets.find (ind.m_buildDataList.at (i).m_rnti); - NS_ASSERT(it!=m_miDlHarqProcessesPackets.end()); + NS_ASSERT (it != m_miDlHarqProcessesPackets.end ()); Ptr pb = (*it).second.at (k).at ( ind.m_buildDataList.at (i).m_dci.m_harqProcess); for (std::list >::const_iterator j = pb->Begin (); j != pb->End (); ++j) { @@ -1171,17 +1184,17 @@ LteEnbMac::DoDlInfoListElementHarqFeeback (DlInfoListElement_s params) NS_LOG_FUNCTION (this); // Update HARQ buffer std::map ::iterator it = m_miDlHarqProcessesPackets.find (params.m_rnti); - NS_ASSERT (it!=m_miDlHarqProcessesPackets.end ()); + NS_ASSERT (it != m_miDlHarqProcessesPackets.end ()); for (uint8_t layer = 0; layer < params.m_harqStatus.size (); layer++) { - if (params.m_harqStatus.at (layer)==DlInfoListElement_s::ACK) + if (params.m_harqStatus.at (layer) == DlInfoListElement_s::ACK) { // discard buffer Ptr emptyBuf = CreateObject (); (*it).second.at (layer).at (params.m_harqProcessId) = emptyBuf; NS_LOG_DEBUG (this << " HARQ-ACK UE " << params.m_rnti << " harqId " << (uint16_t)params.m_harqProcessId << " layer " << (uint16_t)layer); } - else if (params.m_harqStatus.at (layer)==DlInfoListElement_s::NACK) + else if (params.m_harqStatus.at (layer) == DlInfoListElement_s::NACK) { NS_LOG_DEBUG (this << " HARQ-NACK UE " << params.m_rnti << " harqId " << (uint16_t)params.m_harqProcessId << " layer " << (uint16_t)layer); } diff --git a/src/lte/model/lte-enb-rrc.cc b/src/lte/model/lte-enb-rrc.cc index d3a23b376..084f254eb 100644 --- a/src/lte/model/lte-enb-rrc.cc +++ b/src/lte/model/lte-enb-rrc.cc @@ -458,14 +458,29 @@ UeManager::ReleaseDataRadioBearer (uint8_t drbid) LteRrcSap::RadioResourceConfigDedicated rrcd; rrcd.havePhysicalConfigDedicated = false; rrcd.drbToReleaseList.push_back (drbid); + //populating RadioResourceConfigDedicated information element as per 3GPP TS 36.331 version 9.2.0 + rrcd.havePhysicalConfigDedicated = true; + rrcd.physicalConfigDedicated = m_physicalConfigDedicated; + //populating RRCConnectionReconfiguration message as per 3GPP TS 36.331 version 9.2.0 Release 9 LteRrcSap::RrcConnectionReconfiguration msg; msg.haveMeasConfig = false; msg.haveMobilityControlInfo = false; - + msg.radioResourceConfigDedicated = rrcd; + msg.haveRadioResourceConfigDedicated = true; + //RRC Connection Reconfiguration towards UE m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, msg); } +void +LteEnbRrc::DoSendReleaseDataRadioBearer (uint64_t imsi, uint16_t rnti, uint8_t bearerId) +{ + Ptr ueManager = GetUeManager (rnti); + // Bearer de-activation towards UE + ueManager->ReleaseDataRadioBearer (bearerId); + // Bearer de-activation indication towards epc-enb application + m_s1SapProvider->DoSendReleaseIndication (imsi,rnti,bearerId); +} void UeManager::ScheduleRrcConnectionReconfiguration () @@ -642,8 +657,17 @@ UeManager::SendData (uint8_t bid, Ptr p) params.rnti = m_rnti; params.lcid = Bid2Lcid (bid); uint8_t drbid = Bid2Drbid (bid); - LtePdcpSapProvider* pdcpSapProvider = GetDataRadioBearerInfo (drbid)->m_pdcp->GetLtePdcpSapProvider (); + //Transmit PDCP sdu only if DRB ID found in drbMap + std::map >::iterator it = m_drbMap.find (drbid); + if (it != m_drbMap.end ()) + { + Ptr bearerInfo = GetDataRadioBearerInfo (drbid); + if (bearerInfo != NULL) + { + LtePdcpSapProvider* pdcpSapProvider = bearerInfo->m_pdcp->GetLtePdcpSapProvider (); pdcpSapProvider->TransmitPdcpSdu (params); + } + } } break; @@ -852,6 +876,11 @@ UeManager::RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionRe m_rrc->m_connectionReconfigurationTrace (m_imsi, m_rrc->m_cellId, m_rnti); break; + // This case is added to NS-3 in order to handle bearer de-activation scenario for CONNECTED state UE + case CONNECTED_NORMALLY: + NS_LOG_INFO ("ignoring RecvRrcConnectionReconfigurationCompleted in state " << ToString (m_state)); + break; + case HANDOVER_LEAVING: NS_LOG_INFO ("ignoring RecvRrcConnectionReconfigurationCompleted in state " << ToString (m_state)); break; @@ -1823,8 +1852,8 @@ LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams req) NS_LOG_INFO ("rejecting handover request from cellId " << req.sourceCellId); EpcX2Sap::HandoverPreparationFailureParams res; res.oldEnbUeX2apId = req.oldEnbUeX2apId; - res.sourceCellId = req.sourceCellId ; - res.targetCellId = req.targetCellId ; + res.sourceCellId = req.sourceCellId; + res.targetCellId = req.targetCellId; res.cause = 0; res.criticalityDiagnostics = 0; m_x2SapProvider->SendHandoverPreparationFailure (res); @@ -2271,7 +2300,7 @@ LteEnbRrc::GetNewSrsConfigurationIndex () for (uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId]; srcCi < g_srsCiHigh[m_srsCurrentPeriodicityId]; srcCi++) { std::set::iterator it = m_ueSrsConfigurationIndexSet.find (srcCi); - if (it==m_ueSrsConfigurationIndexSet.end ()) + if (it == m_ueSrsConfigurationIndexSet.end ()) { m_lastAllocatedConfigurationIndex = srcCi; m_ueSrsConfigurationIndexSet.insert (srcCi); diff --git a/src/lte/model/lte-enb-rrc.h b/src/lte/model/lte-enb-rrc.h index d42695387..e0f2fcdf9 100644 --- a/src/lte/model/lte-enb-rrc.h +++ b/src/lte/model/lte-enb-rrc.h @@ -686,6 +686,14 @@ public: */ void SendHandoverRequest (uint16_t rnti, uint16_t cellId); + /** + * \brief This function acts as an interface to trigger Release indication messages towards eNB and EPC + * \param imsi the IMSI + * \param rnti the RNTI + * \param bearerId Bearer Identity which is to be de-activated + */ + void DoSendReleaseDataRadioBearer (uint64_t imsi, uint16_t rnti, uint8_t bearerId); + /** * Identifies how EPS Bearer parameters are mapped to different RLC types * diff --git a/src/lte/model/lte-ue-mac.cc b/src/lte/model/lte-ue-mac.cc index f2599565e..3c8ac00d7 100644 --- a/src/lte/model/lte-ue-mac.cc +++ b/src/lte/model/lte-ue-mac.cc @@ -297,7 +297,7 @@ LteUeMac::DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters it = m_ulBsrReceived.find (params.lcid); - if (it!=m_ulBsrReceived.end ()) + if (it != m_ulBsrReceived.end ()) { // update entry (*it).second = params; @@ -555,7 +555,7 @@ LteUeMac::DoReceiveLteControlMessage (Ptr msg) { Ptr msg2 = DynamicCast (msg); UlDciListElement_s dci = msg2->GetDci (); - if (dci.m_ndi==1) + if (dci.m_ndi == 1) { // New transmission -> emtpy pkt buffer queue (for deleting eventual pkts not acked ) Ptr pb = CreateObject (); @@ -569,11 +569,11 @@ LteUeMac::DoReceiveLteControlMessage (Ptr msg) if (((*itBsr).second.statusPduSize > 0) || ((*itBsr).second.retxQueueSize > 0) || ((*itBsr).second.txQueueSize > 0)) { activeLcs++; - if (((*itBsr).second.statusPduSize!=0)&&((*itBsr).second.statusPduSize < statusPduMinSize)) + if (((*itBsr).second.statusPduSize != 0)&&((*itBsr).second.statusPduSize < statusPduMinSize)) { statusPduMinSize = (*itBsr).second.statusPduSize; } - if (((*itBsr).second.statusPduSize!=0)&&(statusPduMinSize == 0)) + if (((*itBsr).second.statusPduSize != 0)&&(statusPduMinSize == 0)) { statusPduMinSize = (*itBsr).second.statusPduSize; } @@ -598,14 +598,14 @@ LteUeMac::DoReceiveLteControlMessage (Ptr msg) } } NS_LOG_LOGIC (this << " UE " << m_rnti << ": UL-CQI notified TxOpportunity of " << dci.m_tbSize << " => " << bytesPerActiveLc << " bytes per active LC" << " statusPduMinSize " << statusPduMinSize); - for (it = m_lcInfoMap.begin (); it!=m_lcInfoMap.end (); it++) + for (it = m_lcInfoMap.begin (); it != m_lcInfoMap.end (); it++) { itBsr = m_ulBsrReceived.find ((*it).first); NS_LOG_DEBUG (this << " Processing LC " << (uint32_t)(*it).first << " bytesPerActiveLc " << bytesPerActiveLc); - if ( (itBsr!=m_ulBsrReceived.end ()) && - ( ((*itBsr).second.statusPduSize > 0) || - ((*itBsr).second.retxQueueSize > 0) || - ((*itBsr).second.txQueueSize > 0)) ) + if ( (itBsr != m_ulBsrReceived.end ()) + && ( ((*itBsr).second.statusPduSize > 0) + || ((*itBsr).second.retxQueueSize > 0) + || ((*itBsr).second.txQueueSize > 0)) ) { if ((statusPduPriority) && ((*itBsr).second.statusPduSize == statusPduMinSize)) { @@ -627,15 +627,15 @@ LteUeMac::DoReceiveLteControlMessage (Ptr msg) } else { - if ((*itBsr).second.statusPduSize>bytesForThisLc) + if ((*itBsr).second.statusPduSize > bytesForThisLc) { NS_FATAL_ERROR ("Insufficient Tx Opportunity for sending a status message"); } } - if ((bytesForThisLc > 7) && // 7 is the min TxOpportunity useful for Rlc - (((*itBsr).second.retxQueueSize > 0) || - ((*itBsr).second.txQueueSize > 0))) + if ((bytesForThisLc > 7) // 7 is the min TxOpportunity useful for Rlc + && (((*itBsr).second.retxQueueSize > 0) + || ((*itBsr).second.txQueueSize > 0))) { if ((*itBsr).second.retxQueueSize > 0) { @@ -769,7 +769,7 @@ LteUeMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo) m_frameNo = frameNo; m_subframeNo = subframeNo; RefreshHarqProcessesPacketBuffer (); - if ((Simulator::Now () >= m_bsrLast + m_bsrPeriodicity) && (m_freshUlBsr==true)) + if ((Simulator::Now () >= m_bsrLast + m_bsrPeriodicity) && (m_freshUlBsr == true)) { SendReportBufferStatus (); m_bsrLast = Simulator::Now (); diff --git a/src/lte/model/lte-ue-rrc.cc b/src/lte/model/lte-ue-rrc.cc index 32f4b699f..d1666df70 100644 --- a/src/lte/model/lte-ue-rrc.cc +++ b/src/lte/model/lte-ue-rrc.cc @@ -404,6 +404,8 @@ LteUeRrc::DoSendData (Ptr packet, uint8_t bid) uint8_t drbid = Bid2Drbid (bid); + if (drbid != 0) + { std::map >::iterator it = m_drbMap.find (drbid); NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with drbid == " << drbid); @@ -417,6 +419,7 @@ LteUeRrc::DoSendData (Ptr packet, uint8_t bid) << " (LCID " << (uint32_t) params.lcid << ")" << " (" << packet->GetSize () << " bytes)"); it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitPdcpSdu (params); + } } @@ -1250,6 +1253,8 @@ LteUeRrc::ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedic NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with given lcid"); m_drbMap.erase (it); m_bid2DrbidMap.erase (drbid); + //Remove LCID + m_cmacSapProvider->RemoveLc (drbid + 2); } } @@ -1398,8 +1403,8 @@ LteUeRrc::ApplyMeasConfig (LteRrcSap::MeasConfig mc) NS_LOG_LOGIC (this << " setting quantityConfig"); m_varMeasConfig.quantityConfig = mc.quantityConfig; // we calculate here the coefficient a used for Layer 3 filtering, see 3GPP TS 36.331 section 5.5.3.2 - m_varMeasConfig.aRsrp = std::pow (0.5, mc.quantityConfig.filterCoefficientRSRP/4.0); - m_varMeasConfig.aRsrq = std::pow (0.5, mc.quantityConfig.filterCoefficientRSRQ/4.0); + m_varMeasConfig.aRsrp = std::pow (0.5, mc.quantityConfig.filterCoefficientRSRP / 4.0); + m_varMeasConfig.aRsrq = std::pow (0.5, mc.quantityConfig.filterCoefficientRSRQ / 4.0); NS_LOG_LOGIC (this << " new filter coefficients: aRsrp=" << m_varMeasConfig.aRsrp << ", aRsrq=" << m_varMeasConfig.aRsrq); for (std::map::iterator measIdIt @@ -1477,7 +1482,7 @@ LteUeRrc::SaveUeMeasurements (uint16_t cellId, double rsrp, double rsrq, { NS_LOG_FUNCTION (this << cellId << rsrp << rsrq << useLayer3Filtering); - std::map::iterator storedMeasIt = m_storedMeasValues.find (cellId);; + std::map::iterator storedMeasIt = m_storedMeasValues.find (cellId); if (storedMeasIt != m_storedMeasValues.end ()) { @@ -2738,11 +2743,17 @@ uint8_t LteUeRrc::Bid2Drbid (uint8_t bid) { std::map::iterator it = m_bid2DrbidMap.find (bid); - NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid); + //NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid); + if (it == m_bid2DrbidMap.end ()) + { + return 0; + } + else + { return it->second; + } } - void LteUeRrc::SwitchToState (State newState) { diff --git a/src/lte/test/lte-test-deactivate-bearer.cc b/src/lte/test/lte-test-deactivate-bearer.cc new file mode 100644 index 000000000..55d71a50a --- /dev/null +++ b/src/lte/test/lte-test-deactivate-bearer.cc @@ -0,0 +1,347 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011, 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:Gaurav Sathe + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ns3/radio-bearer-stats-calculator.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ns3/string.h" +#include "ns3/double.h" +#include +#include +#include +#include + +#include "ns3/point-to-point-epc-helper.h" +#include "ns3/network-module.h" +#include "ns3/ipv4-global-routing-helper.h" +#include "ns3/internet-module.h" +#include "ns3/applications-module.h" +#include "ns3/point-to-point-helper.h" + +#include "lte-test-deactivate-bearer.h" + +NS_LOG_COMPONENT_DEFINE ("LenaTestDeactivateBearer"); + +namespace ns3 { + +LenaTestBearerDeactivateSuite::LenaTestBearerDeactivateSuite () + : TestSuite ("lte-test-deactivate-bearer", SYSTEM) +{ + NS_LOG_INFO ("creating LenaTestPssFfMacSchedulerSuite"); + + bool errorModel = false; + + // Test Case: homogeneous flow test in PSS (different distance) + // Traffic1 info + // UDP traffic: payload size = 100 bytes, interval = 1 ms + // UDP rate in scheduler: (payload + RLC header + PDCP header + IP header + UDP header) * 1000 byte/sec -> 132000 byte/rate + // Maximum throughput = 3 / ( 1/2196000 + 1/1191000 + 1/1383000) = 1486569 byte/s + // 132000 * 3 = 396000 < 1209046 -> estimated throughput in downlink = 132000 byte/sec + std::vector dist_1; + + dist_1.push_back (0); // User 0 distance --> MCS 28 + dist_1.push_back (0); // User 1 distance --> MCS 22 + dist_1.push_back (0); // User 2 distance --> MCS 20 + + std::vector packetSize_1; + + packetSize_1.push_back (100); //1 + packetSize_1.push_back (100); //2 + packetSize_1.push_back (100); //3 + + std::vector estThrPssDl_1; + + estThrPssDl_1.push_back (132000); // User 0 estimated TTI throughput from PSS + estThrPssDl_1.push_back (132000); // User 1 estimated TTI throughput from PSS + estThrPssDl_1.push_back (132000); // User 2 estimated TTI throughput from PSS + + AddTestCase (new LenaDeactivateBearerTestCase (dist_1,estThrPssDl_1,packetSize_1,1,errorModel), TestCase::QUICK); +} + +static LenaTestBearerDeactivateSuite lenaTestBearerDeactivateSuite; + + +std::string +LenaDeactivateBearerTestCase::BuildNameString (uint16_t nUser, std::vector dist) +{ + std::ostringstream oss; + oss << "distances (m) = [ "; + for (std::vector::iterator it = dist.begin (); it != dist.end (); ++it) + { + oss << *it << " "; + } + oss << "]"; + return oss.str (); +} + +LenaDeactivateBearerTestCase::LenaDeactivateBearerTestCase (std::vector dist, std::vector estThrPssDl, std::vector packetSize, uint16_t interval,bool errorModelEnabled) + : TestCase (BuildNameString (dist.size (), dist)), + m_nUser (dist.size ()), + m_dist (dist), + m_packetSize (packetSize), + m_interval (interval), + m_estThrPssDl (estThrPssDl), + m_errorModelEnabled (errorModelEnabled) +{ +} + +LenaDeactivateBearerTestCase::~LenaDeactivateBearerTestCase () +{ +} + +void +LenaDeactivateBearerTestCase::DoRun (void) +{ + if (!m_errorModelEnabled) + { + Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false)); + Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false)); + } + + Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true)); + + + Ptr lteHelper = CreateObject (); + Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + 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.001))); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + Ipv4AddressHelper ipv4h; + ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); + Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); + // interface 0 is localhost, 1 is the p2p device + Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1); + + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1); + + LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL); + + LogComponentEnable ("LenaTestDeactivateBearer", LOG_LEVEL_ALL); + LogComponentEnable ("LteHelper", logLevel); + LogComponentEnable ("EpcHelper", logLevel); + LogComponentEnable ("EpcEnbApplication", logLevel); + LogComponentEnable ("EpcSgwPgwApplication", logLevel); + LogComponentEnable ("EpcMme", logLevel); + LogComponentEnable ("LteEnbRrc", logLevel); + + lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel")); + + // Create Nodes: eNodeB and UE + NodeContainer enbNodes; + NodeContainer ueNodes; + enbNodes.Create (1); + ueNodes.Create (m_nUser); + + // Install Mobility Model + MobilityHelper mobility; + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (enbNodes); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (ueNodes); + + // Create Devices and install them in the Nodes (eNB and UE) + NetDeviceContainer enbDevs; + NetDeviceContainer ueDevs; + lteHelper->SetSchedulerType ("ns3::PssFfMacScheduler"); + enbDevs = lteHelper->InstallEnbDevice (enbNodes); + ueDevs = lteHelper->InstallUeDevice (ueNodes); + + Ptr lteEnbDev = enbDevs.Get (0)->GetObject (); + Ptr enbPhy = lteEnbDev->GetPhy (); + enbPhy->SetAttribute ("TxPower", DoubleValue (30.0)); + enbPhy->SetAttribute ("NoiseFigure", DoubleValue (5.0)); + + // Set UEs' position and power + for (int i = 0; i < m_nUser; i++) + { + Ptr mm = ueNodes.Get (i)->GetObject (); + mm->SetPosition (Vector (m_dist.at (i), 0.0, 0.0)); + Ptr lteUeDev = ueDevs.Get (i)->GetObject (); + Ptr uePhy = lteUeDev->GetPhy (); + uePhy->SetAttribute ("TxPower", DoubleValue (23.0)); + uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0)); + } + + // Install the IP stack on the UEs + internet.Install (ueNodes); + Ipv4InterfaceContainer ueIpIface; + ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevs)); + + // Assign IP address to UEs + 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); + } + + // Attach a UE to a eNB + lteHelper->Attach (ueDevs, enbDevs.Get (0)); + + // Activate an EPS bearer on all UEs + + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ueDevice = ueDevs.Get (u); + GbrQosInformation qos; + qos.gbrDl = (m_packetSize.at (u) + 32) * (1000 / m_interval) * 8; // bit/s, considering IP, UDP, RLC, PDCP header size + qos.gbrUl = (m_packetSize.at (u) + 32) * (1000 / m_interval) * 8; + qos.mbrDl = qos.gbrDl; + qos.mbrUl = qos.gbrUl; + + enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; + EpsBearer bearer (q, qos); + bearer.arp.priorityLevel = 15 - (u + 1); + bearer.arp.preemptionCapability = true; + bearer.arp.preemptionVulnerability = true; + lteHelper->ActivateDedicatedEpsBearer (ueDevice, bearer, EpcTft::Default ()); + } + + + // Install downlink and uplink applications + uint16_t dlPort = 1234; + uint16_t ulPort = 2000; + PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), dlPort)); + PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), ulPort)); + ApplicationContainer clientApps; + ApplicationContainer serverApps; + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + ++ulPort; + serverApps.Add (dlPacketSinkHelper.Install (ueNodes.Get (u))); // receive packets from remotehost + serverApps.Add (ulPacketSinkHelper.Install (remoteHost)); // receive packets from UEs + + UdpClientHelper dlClient (ueIpIface.GetAddress (u), dlPort); // uplink packets generator + dlClient.SetAttribute ("Interval", TimeValue (MilliSeconds (m_interval))); + dlClient.SetAttribute ("MaxPackets", UintegerValue (1000000)); + dlClient.SetAttribute ("PacketSize", UintegerValue (m_packetSize.at (u))); + + UdpClientHelper ulClient (remoteHostAddr, ulPort); // downlink packets generator + ulClient.SetAttribute ("Interval", TimeValue (MilliSeconds (m_interval))); + ulClient.SetAttribute ("MaxPackets", UintegerValue (1000000)); + ulClient.SetAttribute ("PacketSize", UintegerValue (m_packetSize.at (u))); + + clientApps.Add (dlClient.Install (remoteHost)); + clientApps.Add (ulClient.Install (ueNodes.Get (u))); + } + + + serverApps.Start (Seconds (0.030)); + clientApps.Start (Seconds (0.030)); + + double statsStartTime = 0.04; // need to allow for RRC connection establishment + SRS + double statsDuration = 1.0; + double tolerance = 0.1; + + lteHelper->EnableRlcTraces (); + Ptr rlcStats = lteHelper->GetRlcStats (); + rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime))); + rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration))); + + + //get ue device pointer for UE-ID 0 IMSI 1 + Ptr ueDevice = ueDevs.Get (0); + Time deActivateTime (Seconds (1.5)); + + /* + * Schedule dedicated bearer de-activation at 'deActivateTime' + * Instantiate De-activation in sequence (Time deActivateTime, Ptr ueDevice, Ptr enbDevice, uint8_t bearerId) + */ + + lteHelper->DeActivateDedicatedEpsBearer (deActivateTime,ueDevice,enbDevs.Get (0), 2); + + //stop simulation after 3 seconds + Simulator::Stop (Seconds (3.0)); + + Simulator::Run (); + + NS_LOG_INFO ("DL - Test with " << m_nUser << " user(s)"); + std::vector dlDataRxed; + std::vector dlDataTxed; + for (int i = 0; i < m_nUser; i++) + { + // get the imsi + uint64_t imsi = ueDevs.Get (i)->GetObject ()->GetImsi (); + // get the lcId + // lcId is hard-coded, since only one dedicated bearer is added + uint8_t lcId = 4; + dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId)); + dlDataTxed.push_back (rlcStats->GetDlTxData (imsi, lcId)); + NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " thr " << (double)dlDataRxed.at (i) / statsDuration << " ref " << m_estThrPssDl.at (i)); + NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes txed " << (double)dlDataTxed.at (i) << " thr " << (double)dlDataTxed.at (i) / statsDuration); + } + + for (int i = 0; i < m_nUser; i++) + { + uint64_t imsi = ueDevs.Get (i)->GetObject ()->GetImsi (); + + /* + * For UE ID-0 IMSI 1, LCID=4 is deactivated hence If traffic seen on it, test case should fail + * Else For other UE's, test case should validate throughput + */ + if (imsi == 1) + { + NS_TEST_ASSERT_MSG_EQ ((double)dlDataTxed.at (i), 0, "Invalid LCID in Statistics "); + } + else + { + NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataTxed.at (i) / statsDuration, m_estThrPssDl.at (i), m_estThrPssDl.at (i) * tolerance, " Unfair Throughput!"); + } + } + + Simulator::Destroy (); +} +} diff --git a/src/lte/test/lte-test-deactivate-bearer.h b/src/lte/test/lte-test-deactivate-bearer.h new file mode 100644 index 000000000..cf201584e --- /dev/null +++ b/src/lte/test/lte-test-deactivate-bearer.h @@ -0,0 +1,37 @@ +#ifndef LENA_TEST_DEACTIVATE_BEARER_H +#define LENA_TEST_DEACTIVATE_BEARER_H + +#include "ns3/simulator.h" +#include "ns3/test.h" + + +namespace ns3 { + +class LenaDeactivateBearerTestCase : public TestCase +{ +public: + LenaDeactivateBearerTestCase (std::vector dist, std::vector estThrPssDl, std::vector packetSize, uint16_t interval, bool errorModelEnabled); + virtual ~LenaDeactivateBearerTestCase (); + +private: + static std::string BuildNameString (uint16_t nUser, std::vector dist); + virtual void DoRun (void); + uint16_t m_nUser; + std::vector m_dist; + std::vector m_packetSize; // byte + uint16_t m_interval; // ms + std::vector m_estThrPssDl; + bool m_errorModelEnabled; +}; + + + +class LenaTestBearerDeactivateSuite : public TestSuite +{ +public: + LenaTestBearerDeactivateSuite (); +}; + +} // namespace ns3 + +#endif diff --git a/src/lte/wscript b/src/lte/wscript index 491623099..7bb9a5a6b 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -155,6 +155,7 @@ def build(bld): 'test/lte-test-cell-selection.cc', 'test/test-lte-handover-delay.cc', 'test/test-lte-handover-target.cc', + 'test/lte-test-deactivate-bearer.cc', ] headers = bld(features='ns3header')