added release bearer functionality draft
authorGaurav Sathe <gaurav.sathe@tcs.com>
Thu, 27 Nov 2014 16:01:05 +0100
changeset 11078 d09129217e78
parent 10813 da0eb48df23f
child 11079 5101180376fd
added release bearer functionality
AUTHORS
RELEASE_NOTES
src/lte/bindings/modulegen__gcc_ILP32.py
src/lte/examples/lena-deactivate-bearer.cc
src/lte/examples/wscript
src/lte/helper/lte-helper.cc
src/lte/helper/lte-helper.h
src/lte/helper/radio-bearer-stats-calculator.cc
src/lte/model/epc-enb-application.cc
src/lte/model/epc-enb-application.h
src/lte/model/epc-enb-s1-sap.h
src/lte/model/epc-mme.cc
src/lte/model/epc-mme.h
src/lte/model/epc-s11-sap.h
src/lte/model/epc-s1ap-sap.h
src/lte/model/epc-sgw-pgw-application.cc
src/lte/model/epc-sgw-pgw-application.h
src/lte/model/lte-enb-mac.cc
src/lte/model/lte-enb-rrc.cc
src/lte/model/lte-enb-rrc.h
src/lte/model/lte-ue-mac.cc
src/lte/model/lte-ue-rrc.cc
src/lte/test/lte-test-deactivate-bearer.cc
src/lte/test/lte-test-deactivate-bearer.h
src/lte/wscript
--- a/AUTHORS	Sun Jun 15 08:54:48 2014 -0700
+++ b/AUTHORS	Thu Nov 27 16:01:05 2014 +0100
@@ -156,3 +156,4 @@
 He Wu (mdzz@u.washington.edu)
 Yoshihiko Yazawa (yoshiyaz@gmail.com)
 Dizhi Zhou (dizhi.zhou@gmail.com)
+Gaurav Sathe (gaurav.sathe@tcs.com)
--- a/RELEASE_NOTES	Sun Jun 15 08:54:48 2014 -0700
+++ b/RELEASE_NOTES	Thu Nov 27 16:01:05 2014 +0100
@@ -48,6 +48,11 @@
 - 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
 ----------
--- a/src/lte/bindings/modulegen__gcc_ILP32.py	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/bindings/modulegen__gcc_ILP32.py	Thu Nov 27 16:01:05 2014 +0100
@@ -2878,6 +2878,11 @@
                    '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 @@
                    '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 @@
                    '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 @@
                    '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<ErabToBeReleasedIndication> erabToBeReleaseIndication) [member function]
+    cls.add_method('ErabReleaseIndication', 
+                   'void', 
+                   [param('uint64_t', 'mmeUeS1Id'), param('uint16_t', 'enbUeS1Id'), param('std::list<ns3::EpcS1apSapMme::ErabToBeReleasedIndication>', 'erabToBeReleaseIndication')], 
+                   is_pure_virtual=True, is_virtual=True)     
     return
 
 def register_Ns3EpcS1apSapMmeErabSetupItem_methods(root_module, cls):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/examples/lena-deactivate-bearer.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -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 <gaurav.sathe@tcs.com>
+ */
+
+#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> lteHelper = CreateObject<LteHelper> ();
+  Ptr<PointToPointEpcHelper>  epcHelper = CreateObject<PointToPointEpcHelper> ();
+  lteHelper->SetEpcHelper (epcHelper);
+
+  ConfigStore inputConfig;
+  inputConfig.ConfigureDefaults ();
+
+  // parse again so you can override default values from the command line
+  cmd.Parse (argc, argv);
+
+  Ptr<Node> 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<Node> remoteHost = remoteHostContainer.Get (0);
+  InternetStackHelper internet;
+  internet.Install (remoteHostContainer);
+
+  // Create the Internet
+  PointToPointHelper p2ph;
+  p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
+  p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
+  p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
+  NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
+  Ipv4AddressHelper ipv4h;
+  ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
+  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
+  // interface 0 is localhost, 1 is the p2p device
+  Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1);
+
+  Ipv4StaticRoutingHelper ipv4RoutingHelper;
+  Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
+  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<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  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<Node> ueNode = ueNodes.Get (u);
+      // Set the default gateway for the UE
+      Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
+      ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
+    }
+
+  // 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<NetDevice> 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<RadioBearerStatsCalculator> 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<NetDevice> ueDevice, Ptr<NetDevice> 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;
+
+}
+
--- a/src/lte/examples/wscript	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/examples/wscript	Thu Nov 27 16:01:05 2014 +0100
@@ -34,6 +34,9 @@
     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'
--- a/src/lte/helper/lte-helper.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/helper/lte-helper.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -813,8 +813,8 @@
       Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
       NS_ASSERT (ueRrc->GetCellId () == enbLteDevice->GetCellId ());
       Ptr<UeManager> 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 @@
   sourceRrc->SendHandoverRequest (rnti, targetCellId);
 }
 
+void
+LteHelper::DeActivateDedicatedEpsBearer (Time deActivateTime, Ptr<NetDevice> ueDevice,Ptr<NetDevice> 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<NetDevice> ueDevice, Ptr<NetDevice> enbDevice, uint8_t bearerId)
+{
+  NS_LOG_FUNCTION (this << ueDevice << bearerId);
+
+  //Extract IMSI and rnti
+  uint64_t imsi = ueDevice->GetObject<LteUeNetDevice> ()->GetImsi ();
+  uint16_t rnti = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti ();
 
 
+  Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
+
+  enbRrc->DoSendReleaseDataRadioBearer (imsi,rnti,bearerId);
+}
 
 
 void 
--- a/src/lte/helper/lte-helper.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/helper/lte-helper.h	Thu Nov 27 16:01:05 2014 +0100
@@ -325,6 +325,17 @@
    */
   void ActivateDedicatedEpsBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer, Ptr<EpcTft> 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<NetDevice> ueDevice, Ptr<NetDevice> enbDevice, uint8_t bearerId);
 
   /**
    * Create an X2 interface between all the eNBs in a given set
@@ -479,10 +490,13 @@
    */
   Ptr<RadioBearerStatsCalculator> 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 @@
                           Ptr<NetDevice> sourceEnbDev,
                           Ptr<NetDevice> 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<NetDevice> ueDevice, Ptr<NetDevice> enbDevice, uint8_t bearerId);
+
+
   Ptr<SpectrumChannel> m_downlinkChannel;
   Ptr<SpectrumChannel> m_uplinkChannel;
 
--- a/src/lte/helper/radio-bearer-stats-calculator.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/helper/radio-bearer-stats-calculator.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -26,8 +26,7 @@
 #include <vector>
 #include <algorithm>
 
-namespace ns3
-{
+namespace ns3 {
 
 NS_LOG_COMPONENT_DEFINE ("RadioBearerStatsCalculator");
 
--- a/src/lte/model/epc-enb-application.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-enb-application.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -310,8 +310,18 @@
   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<EpcS1apSapMme::ErabToBeReleasedIndication> 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
--- a/src/lte/model/epc-enb-application.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-enb-application.h	Thu Nov 27 16:01:05 2014 +0100
@@ -150,6 +150,15 @@
   void DoPathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> 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
--- a/src/lte/model/epc-enb-s1-sap.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-enb-s1-sap.h	Thu Nov 27 16:01:05 2014 +0100
@@ -49,6 +49,13 @@
    */
   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 @@
 
   // 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 @@
   m_owner->DoInitialUeMessage (imsi, rnti);
 }
 
+template <class C>
+void MemberEpcEnbS1SapProvider<C>::DoSendReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId)
+{
+  m_owner->DoReleaseIndication (imsi, rnti, bearerId);
+}
 
 template <class C>
 void MemberEpcEnbS1SapProvider<C>::PathSwitchRequest (PathSwitchRequestParameters params)
--- a/src/lte/model/epc-mme.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-mme.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -221,4 +221,66 @@
   jt->second->s1apSapEnb->PathSwitchRequestAcknowledge (enbUeS1Id, mmeUeS1Id, cgi, erabToBeSwitchedInUplinkList);
 }
 
+void
+EpcMme::DoErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication)
+{
+  NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id);
+  uint64_t imsi = mmeUeS1Id;
+  std::map<uint64_t, Ptr<UeInfo> >::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<EpcS1apSapMme::ErabToBeReleasedIndication>::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<uint64_t, Ptr<UeInfo> >::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<EpcS11SapMme::BearerContextRemoved>::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> ueInfo, uint8_t epsBearerId)
+{
+  NS_LOG_FUNCTION (this << epsBearerId);
+  for (std::list<BearerInfo>::iterator bit = ueInfo->bearersToBeActivated.begin ();
+       bit != ueInfo->bearersToBeActivated.end ();
+       ++bit)
+    {
+      if (bit->bearerId == epsBearerId)
+        {
+          ueInfo->bearersToBeActivated.erase (bit);
+          break;
+        }
+    }
+}
+
 } // namespace ns3
--- a/src/lte/model/epc-mme.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-mme.h	Thu Nov 27 16:01:05 2014 +0100
@@ -115,11 +115,13 @@
   void DoInitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi);
   void DoInitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapMme::ErabSetupItem> erabSetupList);
   void DoPathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList);
-
+  void DoErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapMme::ErabToBeReleasedIndication> 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
@@ -153,6 +155,13 @@
   std::map<uint64_t, Ptr<UeInfo> > 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> ueInfo, uint8_t epsBearerId);
+
+  /**
    * Hold info on a ENB
    * 
    */
--- a/src/lte/model/epc-s11-sap.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-s11-sap.h	Thu Nov 27 16:01:05 2014 +0100
@@ -103,6 +103,27 @@
    */
   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<BearerContextRemoved> 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 @@
    */
   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<BearerContextToBeRemoved> 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<BearerContextRemovedSgwPgw> 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 @@
   // inherited from EpcS11SapMme
   virtual void CreateSessionResponse (CreateSessionResponseMessage msg);
   virtual void ModifyBearerResponse (ModifyBearerResponseMessage msg);
+  virtual void DeleteBearerRequest (DeleteBearerRequestMessage msg);
 
 private:
   MemberEpcS11SapMme ();
@@ -224,6 +283,12 @@
 }
 
 template <class C>
+void MemberEpcS11SapMme<C>::DeleteBearerRequest (DeleteBearerRequestMessage msg)
+{
+  m_owner->DoDeleteBearerRequest (msg);
+}
+
+template <class C>
 void MemberEpcS11SapMme<C>::ModifyBearerResponse (ModifyBearerResponseMessage msg)
 {
   m_owner->DoModifyBearerResponse (msg);
@@ -247,6 +312,8 @@
   // 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 @@
   m_owner->DoModifyBearerRequest (msg);
 }
 
-
+template <class C>
+void MemberEpcS11SapSgw<C>::DeleteBearerCommand (DeleteBearerCommandMessage msg)
+{
+  m_owner->DoDeleteBearerCommand (msg);
+}
 
-
-
+template <class C>
+void MemberEpcS11SapSgw<C>::DeleteBearerResponse (DeleteBearerResponseMessage msg)
+{
+  m_owner->DoDeleteBearerResponse (msg);
+}
 
 
 
--- a/src/lte/model/epc-s1ap-sap.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-s1ap-sap.h	Thu Nov 27 16:01:05 2014 +0100
@@ -61,6 +61,24 @@
 
 
   /**
+   *  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<ErabToBeReleasedIndication> erabToBeReleaseIndication ) = 0;
+
+  /**
    *  E-RAB Setup Item IEs, see 3GPP TS 36.413 9.1.4.2 
    * 
    */
@@ -174,6 +192,8 @@
 
   // 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<ErabToBeReleasedIndication> erabToBeReleaseIndication );
+
   virtual void InitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabSetupItem> erabSetupList);
   virtual void PathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list<ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList);
 
@@ -200,6 +220,12 @@
 }
 
 template <class C>
+void MemberEpcS1apSapMme<C>::ErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabToBeReleasedIndication> erabToBeReleaseIndication)
+{
+  m_owner->DoErabReleaseIndication (mmeUeS1Id, enbUeS1Id, erabToBeReleaseIndication);
+}
+
+template <class C>
 void MemberEpcS1apSapMme<C>::InitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<ErabSetupItem> erabSetupList)
 {
   m_owner->DoInitialContextSetupResponse (mmeUeS1Id, enbUeS1Id, erabSetupList);
--- a/src/lte/model/epc-sgw-pgw-application.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-sgw-pgw-application.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -51,6 +51,13 @@
   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<Packet> p)
 {
@@ -144,7 +151,7 @@
   std::map<Ipv4Address, Ptr<UeInfo> >::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 @@
   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 @@
   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<uint64_t, Ptr<UeInfo> >::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<EpcS11SapSgw::BearerContextToBeRemoved>::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<uint64_t, Ptr<UeInfo> >::iterator ueit = m_ueInfoByImsiMap.find (imsi);
+  NS_ASSERT_MSG (ueit != m_ueInfoByImsiMap.end (), "unknown IMSI " << imsi);
+
+  for (std::list<EpcS11SapSgw::BearerContextRemovedSgwPgw>::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
--- a/src/lte/model/epc-sgw-pgw-application.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/epc-sgw-pgw-application.h	Thu Nov 27 16:01:05 2014 +0100
@@ -156,12 +156,16 @@
   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<UeInfo>
   {
-  public:
+public:
     UeInfo ();  
 
     /** 
@@ -173,6 +177,12 @@
     void AddBearer (Ptr<EpcTft> 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
--- a/src/lte/model/lte-enb-mac.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/lte-enb-mac.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -544,13 +544,13 @@
   std::vector <FfMacSchedSapProvider::SchedUlCqiInfoReqParameters>::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 @@
   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 @@
   std::map <uint16_t, std::map<uint8_t, LteMacSapUser*> >::iterator rntiIt = m_rlcAttached.find (rnti);
   NS_ASSERT_MSG (rntiIt != m_rlcAttached.end (), "could not find RNTI" << rnti);
   std::map<uint8_t, LteMacSapUser*>::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 @@
 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 <uint16_t, std::map<uint8_t, LteMacSapUser*> >::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 @@
   params.pdu->AddPacketTag (tag);
   // Store pkt in HARQ buffer
   std::map <uint16_t, DlHarqProcessesBuffer_t>::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 @@
             {
               // new data -> force emptying correspondent harq pkt buffer
               std::map <uint16_t, DlHarqProcessesBuffer_t>::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<PacketBurst> pb = CreateObject <PacketBurst> ();
                   (*it).second.at (lcId).at (ind.m_buildDataList.at (i).m_dci.m_harqProcess) = pb;
@@ -992,11 +1005,11 @@
                 }
               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 <uint16_t, DlHarqProcessesBuffer_t>::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<PacketBurst> pb = (*it).second.at (k).at ( ind.m_buildDataList.at (i).m_dci.m_harqProcess);
                       for (std::list<Ptr<Packet> >::const_iterator j = pb->Begin (); j != pb->End (); ++j)
                         {
@@ -1171,17 +1184,17 @@
   NS_LOG_FUNCTION (this);
   // Update HARQ buffer
   std::map <uint16_t, DlHarqProcessesBuffer_t>::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<PacketBurst> emptyBuf = CreateObject <PacketBurst> ();
           (*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);
         }
--- a/src/lte/model/lte-enb-rrc.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/lte-enb-rrc.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -458,14 +458,29 @@
   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> 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,9 +657,18 @@
         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<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+        if (it != m_drbMap.end ())
+          {
+            Ptr<LteDataRadioBearerInfo> bearerInfo = GetDataRadioBearerInfo (drbid);
+            if (bearerInfo != NULL)
+              {
+                LtePdcpSapProvider* pdcpSapProvider = bearerInfo->m_pdcp->GetLtePdcpSapProvider ();
         pdcpSapProvider->TransmitPdcpSdu (params);
       }
+          }
+      }
       break;
       
     case HANDOVER_LEAVING:
@@ -852,6 +876,11 @@
       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 @@
       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 @@
           for (uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId]; srcCi < g_srsCiHigh[m_srsCurrentPeriodicityId]; srcCi++) 
             {
               std::set<uint16_t>::iterator it = m_ueSrsConfigurationIndexSet.find (srcCi);
-              if (it==m_ueSrsConfigurationIndexSet.end ())
+              if (it == m_ueSrsConfigurationIndexSet.end ())
                 {
                   m_lastAllocatedConfigurationIndex = srcCi;
                   m_ueSrsConfigurationIndexSet.insert (srcCi);
--- a/src/lte/model/lte-enb-rrc.h	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/lte-enb-rrc.h	Thu Nov 27 16:01:05 2014 +0100
@@ -687,6 +687,14 @@
   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
    * 
    */
--- a/src/lte/model/lte-ue-mac.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/lte-ue-mac.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -297,7 +297,7 @@
   
   
   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 @@
     {
       Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (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<PacketBurst> pb = CreateObject <PacketBurst> ();
@@ -569,11 +569,11 @@
               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 @@
                 }
             }
           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 @@
                         }
                       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 @@
   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 ();
--- a/src/lte/model/lte-ue-rrc.cc	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/model/lte-ue-rrc.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -404,6 +404,8 @@
 
   uint8_t drbid = Bid2Drbid (bid);
 
+  if (drbid != 0)
+    {
   std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it =   m_drbMap.find (drbid);
   NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with drbid == " << drbid);
 
@@ -417,6 +419,7 @@
                      << " (LCID " << (uint32_t) params.lcid << ")"
                      << " (" << packet->GetSize () << " bytes)");
   it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitPdcpSdu (params);
+    }
 }
 
 
@@ -1250,6 +1253,8 @@
       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 @@
       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<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt
@@ -1477,7 +1482,7 @@
 {
   NS_LOG_FUNCTION (this << cellId << rsrp << rsrq << useLayer3Filtering);
 
-  std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.find (cellId);;
+  std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.find (cellId);
 
   if (storedMeasIt != m_storedMeasValues.end ())
     {
@@ -2738,11 +2743,17 @@
 LteUeRrc::Bid2Drbid (uint8_t bid)
 {
   std::map<uint8_t, uint8_t>::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)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-deactivate-bearer.cc	Thu Nov 27 16:01:05 2014 +0100
@@ -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 <gaurav.sathe@tcs.com>
+ */
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <ns3/object.h>
+#include <ns3/spectrum-interference.h>
+#include <ns3/spectrum-error-model.h>
+#include <ns3/log.h>
+#include <ns3/test.h>
+#include <ns3/simulator.h>
+#include <ns3/packet.h>
+#include <ns3/ptr.h>
+#include "ns3/radio-bearer-stats-calculator.h"
+#include <ns3/constant-position-mobility-model.h>
+#include <ns3/eps-bearer.h>
+#include <ns3/node-container.h>
+#include <ns3/mobility-helper.h>
+#include <ns3/net-device-container.h>
+#include <ns3/lte-ue-net-device.h>
+#include <ns3/lte-enb-net-device.h>
+#include <ns3/lte-ue-rrc.h>
+#include <ns3/lte-helper.h>
+#include "ns3/string.h"
+#include "ns3/double.h"
+#include <ns3/lte-enb-phy.h>
+#include <ns3/lte-ue-phy.h>
+#include <ns3/boolean.h>
+#include <ns3/enum.h>
+
+#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<uint16_t> 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<uint16_t> packetSize_1;
+
+  packetSize_1.push_back (100); //1
+  packetSize_1.push_back (100); //2
+  packetSize_1.push_back (100); //3
+
+  std::vector<uint32_t> 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<uint16_t> dist)
+{
+  std::ostringstream oss;
+  oss << "distances (m) = [ ";
+  for (std::vector<uint16_t>::iterator it = dist.begin (); it != dist.end (); ++it)
+    {
+      oss << *it << " ";
+    }
+  oss << "]";
+  return oss.str ();
+}
+
+LenaDeactivateBearerTestCase::LenaDeactivateBearerTestCase (std::vector<uint16_t> dist, std::vector<uint32_t> estThrPssDl, std::vector<uint16_t> 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> lteHelper = CreateObject<LteHelper> ();
+  Ptr<PointToPointEpcHelper>  epcHelper = CreateObject<PointToPointEpcHelper> ();
+  lteHelper->SetEpcHelper (epcHelper);
+
+  Ptr<Node> pgw = epcHelper->GetPgwNode ();
+
+  // Create a single RemoteHost
+  NodeContainer remoteHostContainer;
+  remoteHostContainer.Create (1);
+  Ptr<Node> remoteHost = remoteHostContainer.Get (0);
+  InternetStackHelper internet;
+  internet.Install (remoteHostContainer);
+
+  // Create the Internet
+  PointToPointHelper p2ph;
+  p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
+  p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
+  p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.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<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
+  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<LteEnbNetDevice> lteEnbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
+  Ptr<LteEnbPhy> 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<ConstantPositionMobilityModel> mm = ueNodes.Get (i)->GetObject<ConstantPositionMobilityModel> ();
+      mm->SetPosition (Vector (m_dist.at (i), 0.0, 0.0));
+      Ptr<LteUeNetDevice> lteUeDev = ueDevs.Get (i)->GetObject<LteUeNetDevice> ();
+      Ptr<LteUePhy> 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<Node> ueNode = ueNodes.Get (u);
+      // Set the default gateway for the UE
+      Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());
+      ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
+    }
+
+  // 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<NetDevice> 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<RadioBearerStatsCalculator> 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<NetDevice> ueDevice = ueDevs.Get (0);
+  Time deActivateTime (Seconds (1.5));
+
+  /*
+   *   Schedule dedicated bearer de-activation at 'deActivateTime'
+   *   Instantiate De-activation in sequence (Time deActivateTime, Ptr<NetDevice> ueDevice, Ptr<NetDevice> 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 <uint64_t> dlDataRxed;
+  std::vector <uint64_t> dlDataTxed;
+  for (int i = 0; i < m_nUser; i++)
+    {
+      // get the imsi
+      uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->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<LteUeNetDevice> ()->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 ();
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/lte-test-deactivate-bearer.h	Thu Nov 27 16:01:05 2014 +0100
@@ -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<uint16_t> dist, std::vector<uint32_t> estThrPssDl, std::vector<uint16_t> packetSize, uint16_t interval, bool  errorModelEnabled);
+  virtual ~LenaDeactivateBearerTestCase ();
+
+private:
+  static std::string BuildNameString (uint16_t nUser, std::vector<uint16_t> dist);
+  virtual void DoRun (void);
+  uint16_t m_nUser;
+  std::vector<uint16_t> m_dist;
+  std::vector<uint16_t> m_packetSize;  // byte
+  uint16_t m_interval;    // ms
+  std::vector<uint32_t> m_estThrPssDl;
+  bool m_errorModelEnabled;
+};
+
+
+
+class LenaTestBearerDeactivateSuite : public TestSuite
+{
+public:
+  LenaTestBearerDeactivateSuite ();
+};
+
+} // namespace ns3
+
+#endif
--- a/src/lte/wscript	Sun Jun 15 08:54:48 2014 -0700
+++ b/src/lte/wscript	Thu Nov 27 16:01:05 2014 +0100
@@ -155,6 +155,7 @@
         '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')