Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(402)

Unified Diff: src/nist/model/nist-lte-enb-rrc.cc

Issue 326890043: Public Safety Communication modeling tools based on ns-3
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/nist/model/nist-lte-enb-rrc.h ('k') | src/nist/model/nist-lte-ffr-algorithm.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/nist/model/nist-lte-enb-rrc.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/nist/model/nist-lte-enb-rrc.cc
@@ -0,0 +1,2812 @@
+/* -*- 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
+ *
+ * Authors: Nicola Baldo <nbaldo@cttc.es>
+ * Marco Miozzo <mmiozzo@cttc.es>
+ * Manuel Requena <manuel.requena@cttc.es>
+ * Modified by: NIST
+ */
+
+#include "nist-lte-enb-rrc.h"
+
+#include <ns3/fatal-error.h>
+#include <ns3/log.h>
+#include <ns3/abort.h>
+
+#include <ns3/pointer.h>
+#include <ns3/object-map.h>
+#include <ns3/object-factory.h>
+#include <ns3/simulator.h>
+
+#include <ns3/nist-lte-radio-bearer-info.h>
+#include <ns3/nist-eps-bearer-tag.h>
+#include <ns3/packet.h>
+
+#include <ns3/nist-lte-rlc.h>
+#include <ns3/nist-lte-rlc-tm.h>
+#include <ns3/nist-lte-rlc-um.h>
+#include <ns3/nist-lte-rlc-am.h>
+#include <ns3/nist-lte-pdcp.h>
+
+
+
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("NistLteEnbRrc");
+
+///////////////////////////////////////////
+// CMAC SAP forwarder
+///////////////////////////////////////////
+
+/**
+ * \brief Class for forwarding CMAC SAP User functions.
+ */
+class NistEnbRrcMemberLteEnbCmacSapUser : public NistLteEnbCmacSapUser
+{
+public:
+ NistEnbRrcMemberLteEnbCmacSapUser (NistLteEnbRrc* rrc);
+
+ virtual uint16_t AllocateTemporaryCellRnti ();
+ virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
+ virtual void RrcConfigurationUpdateInd (NistUeConfig params);
+
+private:
+ NistLteEnbRrc* m_rrc;
+};
+
+NistEnbRrcMemberLteEnbCmacSapUser::NistEnbRrcMemberLteEnbCmacSapUser (NistLteEnbRrc* rrc)
+ : m_rrc (rrc)
+{
+}
+
+uint16_t
+NistEnbRrcMemberLteEnbCmacSapUser::AllocateTemporaryCellRnti ()
+{
+ return m_rrc->DoAllocateTemporaryCellRnti ();
+}
+
+void
+NistEnbRrcMemberLteEnbCmacSapUser::NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
+{
+ m_rrc->DoNotifyLcConfigResult (rnti, lcid, success);
+}
+
+void
+NistEnbRrcMemberLteEnbCmacSapUser::RrcConfigurationUpdateInd (NistUeConfig params)
+{
+ m_rrc->DoRrcConfigurationUpdateInd (params);
+}
+
+///////////////////////////////////////////
+// LteEnbRrcSl
+///////////////////////////////////////////
+
+NS_OBJECT_ENSURE_REGISTERED (LteEnbRrcSl);
+
+LteEnbRrcSl::LteEnbRrcSl ()
+ : m_slEnabled (false)
+{
+ m_preconfigCommTxPoolExceptional.nbPools = 0;
+}
+
+void
+LteEnbRrcSl::DoInitialize ()
+{
+
+
+}
+
+LteEnbRrcSl::~LteEnbRrcSl (void)
+{
+}
+
+void
+LteEnbRrcSl::DoDispose ()
+{
+
+
+}
+
+TypeId LteEnbRrcSl::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::LteEnbRrcSl")
+ .SetParent<Object> ()
+ .AddConstructor<LteEnbRrcSl> ()
+
+ ;
+ return tid;
+}
+
+/**
+ * \brief makes a copy of the sidelink configuration
+ * \return a copy of the sidelink configuration
+ */
+Ptr<LteEnbRrcSl>
+LteEnbRrcSl::Copy ()
+{
+ NS_LOG_FUNCTION (this);
+ Ptr<LteEnbRrcSl> copy = CreateObject<LteEnbRrcSl> ();
+ //copy internal values
+ copy->m_slEnabled = m_slEnabled;
+ copy->m_sib18 = m_sib18;
+ //copy->m_dedicatedPoolMap = m_dedicatedPoolMap;
+ copy->m_preconfigDedicatedPoolMap = m_preconfigDedicatedPoolMap;
+ copy->m_preconfigCommTxPoolExceptional = m_preconfigCommTxPoolExceptional;
+
+ return copy;
+}
+
+
+// void
+// LteEnbRrcSl::SetSystemInformationBlockType18 (NistLteRrcSap::SystemInformationBlockType18 sib18)
+// {
+// NS_LOG_FUNCTION (this);
+// m_sib18 = sib18;
+// }
+
+/**
+ * Gets the SIB 18 information
+ * \return The SIB 18
+ */
+NistLteRrcSap::SystemInformationBlockType18
+LteEnbRrcSl::GetSystemInformationType18 ()
+{
+ NS_LOG_FUNCTION (this);
+
+ //build the content of SIB 18 by looking at pools allocated
+ NistLteRrcSap::SystemInformationBlockType18 sib18;
+ sib18.commConfig.commRxPool.nbPools = 0;
+ sib18.commConfig.commTxPoolNormalCommon.nbPools = 0;
+ sib18.commConfig.commTxPoolExceptional.nbPools = 0;
+
+ std::map <uint32_t, LteEnbRrcSl::ActivePoolInfo>::iterator it;
+ for (it = m_activePoolMap.begin() ; it != m_activePoolMap.end() ; it++) {
+ //check if pool already listed
+ if (it->second.m_poolSetup.setup == NistLteRrcSap::SlCommTxResourcesSetup::SCHEDULED) {
+ //check single pool
+ if (!IsPoolInList(it->second.m_poolSetup.scheduled.commTxConfig, sib18.commConfig.commRxPool.pools, sib18.commConfig.commRxPool.nbPools)) {
+ //add pool
+ sib18.commConfig.commRxPool.pools[sib18.commConfig.commRxPool.nbPools]=it->second.m_poolSetup.scheduled.commTxConfig;
+ sib18.commConfig.commRxPool.nbPools++;
+ }
+ } else if (it->second.m_poolSetup.ueSelected.havePoolToAdd) {
+ //check all pools
+ for (int i = 0 ; i < it->second.m_poolSetup.ueSelected.poolToAddModList.nbPools ; i++) {
+ if (!IsPoolInList(it->second.m_poolSetup.ueSelected.poolToAddModList.pools[i].pool, sib18.commConfig.commRxPool.pools, sib18.commConfig.commRxPool.nbPools)) {
+ //add pool
+ sib18.commConfig.commRxPool.pools[sib18.commConfig.commRxPool.nbPools]=it->second.m_poolSetup.ueSelected.poolToAddModList.pools[i].pool;
+ sib18.commConfig.commRxPool.nbPools++;
+ }
+ }
+ }
+ }
+
+ sib18.commConfig.commTxPoolExceptional = m_preconfigCommTxPoolExceptional;
+
+ return sib18;
+}
+
+bool
+LteEnbRrcSl::IsPoolInList (NistLteRrcSap::SlCommResourcePool pool, NistLteRrcSap::SlCommResourcePool *pools, int nbPool)
+{
+ bool found = false;
+ for (int i = 0 ; i < nbPool && !found; i++) {
+ found = pool == pools[i];
+ }
+ return found;
+}
+
+
+void
+LteEnbRrcSl::SetSlEnabled (bool status)
+{
+ NS_LOG_FUNCTION (this);
+ m_slEnabled = status;
+}
+
+bool
+LteEnbRrcSl::IsSlEnabled ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_slEnabled;
+}
+
+void
+LteEnbRrcSl::AddPreconfiguredDedicatedPool (uint32_t group, NistLteRrcSap::SlCommTxResourcesSetup pool)
+{
+ NS_LOG_FUNCTION (this);
+ m_preconfigDedicatedPoolMap.insert (std::pair<uint32_t, NistLteRrcSap::SlCommTxResourcesSetup> (group, pool));
+}
+
+void
+LteEnbRrcSl::SetCommTxPoolExceptional (NistLteRrcSap::SlCommTxPoolList pool)
+{
+ NS_LOG_FUNCTION (this);
+ m_preconfigCommTxPoolExceptional = pool;
+}
+
+
+
+///////////////////////////////////////////
+// NistUeManager
+///////////////////////////////////////////
+
+
+/// Map each of UE Manager states to its string representation.
+static const std::string g_ueManagerStateName[NistUeManager::NUM_STATES] =
+{
+ "INITIAL_RANDOM_ACCESS",
+ "CONNECTION_SETUP",
+ "CONNECTION_REJECTED",
+ "CONNECTED_NORMALLY",
+ "CONNECTION_RECONFIGURATION",
+ "CONNECTION_REESTABLISHMENT",
+ "HANDOVER_PREPARATION",
+ "HANDOVER_JOINING",
+ "HANDOVER_PATH_SWITCH",
+ "HANDOVER_LEAVING",
+};
+
+/**
+ * \param s The UE manager state.
+ * \return The string representation of the given state.
+ */
+static const std::string & ToString (NistUeManager::State s)
+{
+ return g_ueManagerStateName[s];
+}
+
+
+NS_OBJECT_ENSURE_REGISTERED (NistUeManager);
+
+
+NistUeManager::NistUeManager ()
+{
+ NS_FATAL_ERROR ("this constructor is not espected to be used");
+}
+
+
+NistUeManager::NistUeManager (Ptr<NistLteEnbRrc> rrc, uint16_t rnti, State s)
+ : m_lastAllocatedDrbid (0),
+ m_rnti (rnti),
+ m_imsi (0),
+ m_lastRrcTransactionIdentifier (0),
+ m_rrc (rrc),
+ m_state (s),
+ m_pendingNistRrcConnectionReconfiguration (false),
+ m_sourceX2apId (0),
+ m_sourceCellId (0),
+ m_needPhyMacConfiguration (false),
+ m_slPoolChanged (false)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+NistUeManager::DoInitialize ()
+{
+ NS_LOG_FUNCTION (this);
+ m_drbPdcpSapUser = new NistLtePdcpSpecificLtePdcpSapUser<NistUeManager> (this);
+
+ m_physicalConfigDedicated.haveNistAntennaInfoDedicated = true;
+ m_physicalConfigDedicated.antennaInfo.transmissionMode = m_rrc->m_defaultTransmissionMode;
+ m_physicalConfigDedicated.haveNistSoundingRsUlConfigDedicated = true;
+ m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = m_rrc->GetNewSrsConfigurationIndex ();
+ m_physicalConfigDedicated.soundingRsUlConfigDedicated.type = NistLteRrcSap::NistSoundingRsUlConfigDedicated::SETUP;
+ m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsBandwidth = 0;
+ m_physicalConfigDedicated.haveNistPdschConfigDedicated = true;
+ m_physicalConfigDedicated.pdschConfigDedicated.pa = NistLteRrcSap::NistPdschConfigDedicated::dB0;
+
+ m_rrc->m_cmacSapProvider->AddUe (m_rnti);
+ m_rrc->m_cphySapProvider->AddUe (m_rnti);
+
+ // setup the eNB side of SRB0
+ {
+ uint8_t lcid = 0;
+
+ Ptr<NistLteRlc> rlc = CreateObject<NistLteRlcTm> ()->GetObject<NistLteRlc> ();
+ rlc->SetNistLteMacSapProvider (m_rrc->m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+ rlc->SetLcId (lcid);
+
+ m_srb0 = CreateObject<LteSignalingRadioNistBearerInfo> ();
+ m_srb0->m_rlc = rlc;
+ m_srb0->m_srbIdentity = 0;
+ // no need to store logicalChannelConfig as SRB0 is pre-configured
+
+ NistLteEnbCmacSapProvider::NistLcInfo lcinfo;
+ lcinfo.rnti = m_rnti;
+ lcinfo.lcId = lcid;
+ // leave the rest of lcinfo empty as CCCH (LCID 0) is pre-configured
+ m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetNistLteMacSapUser ());
+
+ }
+
+ // setup the eNB side of SRB1; the UE side will be set up upon RRC connection establishment
+ {
+ uint8_t lcid = 1;
+
+ Ptr<NistLteRlc> rlc = CreateObject<NistLteRlcAm> ()->GetObject<NistLteRlc> ();
+ rlc->SetNistLteMacSapProvider (m_rrc->m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+ rlc->SetLcId (lcid);
+
+ Ptr<NistLtePdcp> pdcp = CreateObject<NistLtePdcp> ();
+ pdcp->SetRnti (m_rnti);
+ pdcp->SetLcId (lcid);
+ pdcp->SetNistLtePdcpSapUser (m_drbPdcpSapUser);
+ pdcp->SetNistLteRlcSapProvider (rlc->GetNistLteRlcSapProvider ());
+ rlc->SetNistLteRlcSapUser (pdcp->GetNistLteRlcSapUser ());
+
+ m_srb1 = CreateObject<LteSignalingRadioNistBearerInfo> ();
+ m_srb1->m_rlc = rlc;
+ m_srb1->m_pdcp = pdcp;
+ m_srb1->m_srbIdentity = 1;
+ m_srb1->m_logicalChannelConfig.priority = 0;
+ m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = 100;
+ m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = 100;
+ m_srb1->m_logicalChannelConfig.logicalChannelGroup = 0;
+
+ NistLteEnbCmacSapProvider::NistLcInfo lcinfo;
+ lcinfo.rnti = m_rnti;
+ lcinfo.lcId = lcid;
+ lcinfo.lcGroup = 0; // all SRBs always mapped to LCG 0
+ lcinfo.qci = NistEpsBearer::GBR_CONV_VOICE; // not sure why the FF API requires a CQI even for SRBs...
+ lcinfo.isGbr = true;
+ lcinfo.mbrUl = 1e6;
+ lcinfo.mbrDl = 1e6;
+ lcinfo.gbrUl = 1e4;
+ lcinfo.gbrDl = 1e4;
+ m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetNistLteMacSapUser ());
+ }
+
+ NistLteEnbRrcSapUser::NistSetupUeParameters ueParams;
+ ueParams.srb0SapProvider = m_srb0->m_rlc->GetNistLteRlcSapProvider ();
+ ueParams.srb1SapProvider = m_srb1->m_pdcp->GetNistLtePdcpSapProvider ();
+ m_rrc->m_rrcSapUser->SetupUe (m_rnti, ueParams);
+
+ // configure MAC (and scheduler)
+ NistLteEnbCmacSapProvider::NistUeConfig req;
+ req.m_rnti = m_rnti;
+ req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
+ m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
+
+ // configure PHY
+ m_rrc->m_cphySapProvider->SetTransmissionMode (m_rnti, m_physicalConfigDedicated.antennaInfo.transmissionMode);
+ m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (m_rnti, m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex);
+
+ // schedule this NistUeManager instance to be deleted if the UE does not give any sign of life within a reasonable time
+ Time maxConnectionDelay;
+ switch (m_state)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ m_connectionRequestTimeout = Simulator::Schedule (m_rrc->m_connectionRequestTimeoutDuration,
+ &NistLteEnbRrc::ConnectionRequestTimeout,
+ m_rrc, m_rnti);
+ break;
+
+ case HANDOVER_JOINING:
+ m_handoverJoiningTimeout = Simulator::Schedule (m_rrc->m_handoverJoiningTimeoutDuration,
+ &NistLteEnbRrc::HandoverJoiningTimeout,
+ m_rrc, m_rnti);
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unexpected state " << ToString (m_state));
+ break;
+ }
+
+}
+
+
+NistUeManager::~NistUeManager (void)
+{
+}
+
+void
+NistUeManager::DoDispose ()
+{
+ delete m_drbPdcpSapUser;
+ // delete eventual X2-U TEIDs
+ for (std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.begin ();
+ it != m_drbMap.end ();
+ ++it)
+ {
+ m_rrc->m_x2uTeidInfoMap.erase (it->second->m_gtpTeid);
+ }
+
+}
+
+TypeId NistUeManager::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::NistUeManager")
+ .SetParent<Object> ()
+ .AddConstructor<NistUeManager> ()
+ .AddAttribute ("DataRadioBearerMap", "List of UE DataRadioNistBearerInfo by DRBID.",
+ ObjectMapValue (),
+ MakeObjectMapAccessor (&NistUeManager::m_drbMap),
+ MakeObjectMapChecker<LteDataRadioNistBearerInfo> ())
+ .AddAttribute ("Srb0", "SignalingRadioNistBearerInfo for SRB0",
+ PointerValue (),
+ MakePointerAccessor (&NistUeManager::m_srb0),
+ MakePointerChecker<LteSignalingRadioNistBearerInfo> ())
+ .AddAttribute ("Srb1", "SignalingRadioNistBearerInfo for SRB1",
+ PointerValue (),
+ MakePointerAccessor (&NistUeManager::m_srb1),
+ MakePointerChecker<LteSignalingRadioNistBearerInfo> ())
+ .AddAttribute ("C-RNTI",
+ "Cell Radio Network Temporary Identifier",
+ TypeId::ATTR_GET, // read-only attribute
+ UintegerValue (0), // unused, read-only attribute
+ MakeUintegerAccessor (&NistUeManager::m_rnti),
+ MakeUintegerChecker<uint16_t> ())
+ .AddTraceSource ("StateTransition",
+ "fired upon every UE state transition seen by the "
+ "NistUeManager at the eNB RRC",
+ MakeTraceSourceAccessor (&NistUeManager::m_stateTransitionTrace),
+ "ns3::NistUeManager::StateTracedCallback")
+ ;
+ return tid;
+}
+
+void
+NistUeManager::SetSource (uint16_t sourceCellId, uint16_t sourceX2apId)
+{
+ m_sourceX2apId = sourceX2apId;
+ m_sourceCellId = sourceCellId;
+}
+
+void
+NistUeManager::SetImsi (uint64_t imsi)
+{
+ m_imsi = imsi;
+}
+
+void
+NistUeManager::SetupDataRadioBearer (NistEpsBearer bearer, uint8_t bearerId, uint32_t gtpTeid, Ipv4Address transportLayerAddress)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) m_rnti);
+
+ Ptr<LteDataRadioNistBearerInfo> drbInfo = CreateObject<LteDataRadioNistBearerInfo> ();
+ uint8_t drbid = AddDataRadioNistBearerInfo (drbInfo);
+ uint8_t lcid = Drbid2Lcid (drbid);
+ uint8_t bid = Drbid2Bid (drbid);
+ NS_ASSERT_MSG ( bearerId == 0 || bid == bearerId, "bearer ID mismatch (" << (uint32_t) bid << " != " << (uint32_t) bearerId << ", the assumption that ID are allocated in the same way by MME and RRC is not valid any more");
+ drbInfo->m_epsBearerIdentity = bid;
+ drbInfo->m_drbIdentity = drbid;
+ drbInfo->m_logicalChannelIdentity = lcid;
+ drbInfo->m_gtpTeid = gtpTeid;
+ drbInfo->m_transportLayerAddress = transportLayerAddress;
+
+ if (m_state == HANDOVER_JOINING)
+ {
+ // setup TEIDs for receiving data eventually forwarded over X2-U
+ NistLteEnbRrc::NistX2uTeidInfo x2uTeidInfo;
+ x2uTeidInfo.rnti = m_rnti;
+ x2uTeidInfo.drbid = drbid;
+ std::pair<std::map<uint32_t, NistLteEnbRrc::NistX2uTeidInfo>::iterator, bool>
+ ret = m_rrc->m_x2uTeidInfoMap.insert (std::pair<uint32_t, NistLteEnbRrc::NistX2uTeidInfo> (gtpTeid, x2uTeidInfo));
+ NS_ASSERT_MSG (ret.second == true, "overwriting a pre-existing entry in m_x2uTeidInfoMap");
+ }
+
+ TypeId rlcTypeId = m_rrc->GetRlcType (bearer);
+
+ ObjectFactory rlcObjectFactory;
+ rlcObjectFactory.SetTypeId (rlcTypeId);
+ Ptr<NistLteRlc> rlc = rlcObjectFactory.Create ()->GetObject<NistLteRlc> ();
+ rlc->SetNistLteMacSapProvider (m_rrc->m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+
+ drbInfo->m_rlc = rlc;
+
+ rlc->SetLcId (lcid);
+
+ // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
+ // if we are using RLC/SM we don't care of anything above RLC
+ if (rlcTypeId != NistLteRlcSm::GetTypeId ())
+ {
+ Ptr<NistLtePdcp> pdcp = CreateObject<NistLtePdcp> ();
+ pdcp->SetRnti (m_rnti);
+ pdcp->SetLcId (lcid);
+ pdcp->SetNistLtePdcpSapUser (m_drbPdcpSapUser);
+ pdcp->SetNistLteRlcSapProvider (rlc->GetNistLteRlcSapProvider ());
+ rlc->SetNistLteRlcSapUser (pdcp->GetNistLteRlcSapUser ());
+ drbInfo->m_pdcp = pdcp;
+ }
+
+ NistLteEnbCmacSapProvider::NistLcInfo lcinfo;
+ lcinfo.rnti = m_rnti;
+ lcinfo.lcId = lcid;
+ lcinfo.lcGroup = m_rrc->GetLogicalChannelGroup (bearer);
+ lcinfo.qci = bearer.qci;
+ lcinfo.isGbr = bearer.IsGbr ();
+ lcinfo.mbrUl = bearer.gbrQosInfo.mbrUl;
+ lcinfo.mbrDl = bearer.gbrQosInfo.mbrDl;
+ lcinfo.gbrUl = bearer.gbrQosInfo.gbrUl;
+ lcinfo.gbrDl = bearer.gbrQosInfo.gbrDl;
+ m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetNistLteMacSapUser ());
+
+ if (rlcTypeId == NistLteRlcAm::GetTypeId ())
+ {
+ drbInfo->m_rlcConfig.choice = NistLteRrcSap::NistRlcConfig::AM;
+ }
+ else
+ {
+ drbInfo->m_rlcConfig.choice = NistLteRrcSap::NistRlcConfig::UM_BI_DIRECTIONAL;
+ }
+
+ drbInfo->m_logicalChannelIdentity = lcid;
+ drbInfo->m_logicalChannelConfig.priority = m_rrc->GetLogicalChannelPriority (bearer);
+ drbInfo->m_logicalChannelConfig.logicalChannelGroup = m_rrc->GetLogicalChannelGroup (bearer);
+ if (bearer.IsGbr ())
+ {
+ drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = bearer.gbrQosInfo.gbrUl;
+ }
+ else
+ {
+ drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = 0;
+ }
+ drbInfo->m_logicalChannelConfig.bucketSizeDurationMs = 1000;
+
+ ScheduleNistRrcConnectionReconfiguration ();
+}
+
+void
+NistUeManager::RecordDataRadioBearersToBeStarted ()
+{
+ NS_LOG_FUNCTION (this << (uint32_t) m_rnti);
+ for (std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.begin ();
+ it != m_drbMap.end ();
+ ++it)
+ {
+ m_drbsToBeStarted.push_back (it->first);
+ }
+}
+
+void
+NistUeManager::StartDataRadioBearers ()
+{
+ NS_LOG_FUNCTION (this << (uint32_t) m_rnti);
+ for (std::list <uint8_t>::iterator drbIdIt = m_drbsToBeStarted.begin ();
+ drbIdIt != m_drbsToBeStarted.end ();
+ ++drbIdIt)
+ {
+ std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator drbIt = m_drbMap.find (*drbIdIt);
+ NS_ASSERT (drbIt != m_drbMap.end ());
+ drbIt->second->m_rlc->Initialize ();
+ if (drbIt->second->m_pdcp)
+ {
+ drbIt->second->m_pdcp->Initialize ();
+ }
+ }
+ m_drbsToBeStarted.clear ();
+}
+
+
+void
+NistUeManager::ReleaseDataRadioBearer (uint8_t drbid)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) m_rnti << (uint32_t) drbid);
+ uint8_t lcid = Drbid2Lcid (drbid);
+ std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ASSERT_MSG (it != m_drbMap.end (), "request to remove radio bearer with unknown drbid " << drbid);
+
+ // first delete eventual X2-U TEIDs
+ m_rrc->m_x2uTeidInfoMap.erase (it->second->m_gtpTeid);
+
+ m_drbMap.erase (it);
+ m_rrc->m_cmacSapProvider->ReleaseLc (m_rnti, lcid);
+
+ NistLteRrcSap::NistRadioResourceConfigDedicated rrcd;
+ rrcd.haveNistPhysicalConfigDedicated = false;
+ rrcd.drbToReleaseList.push_back (drbid);
+ //populating NistRadioResourceConfigDedicated information element as per 3GPP TS 36.331 version 9.2.0
+ rrcd.haveNistPhysicalConfigDedicated = true;
+ rrcd.physicalConfigDedicated = m_physicalConfigDedicated;
+
+ //populating RRCConnectionReconfiguration message as per 3GPP TS 36.331 version 9.2.0 Release 9
+ NistLteRrcSap::NistRrcConnectionReconfiguration msg;
+ msg.haveNistMeasConfig = false;
+ msg.haveNistMobilityControlInfo = false;
+ msg.radioResourceConfigDedicated = rrcd;
+ msg.haveNistRadioResourceConfigDedicated = true;
+ //RRC Connection Reconfiguration towards UE
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionReconfiguration (m_rnti, msg);
+}
+
+void
+NistLteEnbRrc::DoSendReleaseDataRadioBearer (uint64_t imsi, uint16_t rnti, uint8_t bearerId)
+{
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ // Bearer de-activation towards UE
+ ueManager->ReleaseDataRadioBearer (bearerId);
+ // Bearer de-activation indication towards epc-enb application
+ m_s1SapProvider->DoSendReleaseIndication (imsi,rnti,bearerId);
+}
+
+void
+NistUeManager::ScheduleNistRrcConnectionReconfiguration ()
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ case CONNECTION_SETUP:
+ case CONNECTION_RECONFIGURATION:
+ case CONNECTION_REESTABLISHMENT:
+ case HANDOVER_PREPARATION:
+ case HANDOVER_JOINING:
+ case HANDOVER_LEAVING:
+ // a previous reconfiguration still ongoing, we need to wait for it to be finished
+ m_pendingNistRrcConnectionReconfiguration = true;
+ break;
+
+ case CONNECTED_NORMALLY:
+ {
+ m_pendingNistRrcConnectionReconfiguration = false;
+ NistLteRrcSap::NistRrcConnectionReconfiguration msg = BuildNistRrcConnectionReconfiguration ();
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionReconfiguration (m_rnti, msg);
+ RecordDataRadioBearersToBeStarted ();
+ SwitchToState (CONNECTION_RECONFIGURATION);
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+NistUeManager::PrepareHandover (uint16_t cellId)
+{
+ NS_LOG_FUNCTION (this << cellId);
+ switch (m_state)
+ {
+ case CONNECTED_NORMALLY:
+ {
+ m_targetCellId = cellId;
+ NistEpcX2SapProvider::NistHandoverRequestParams params;
+ params.oldEnbUeX2apId = m_rnti;
+ params.cause = NistEpcX2SapProvider::HandoverDesirableForRadioReason;
+ params.sourceCellId = m_rrc->m_cellId;
+ params.targetCellId = cellId;
+ params.mmeUeS1apId = m_imsi;
+ params.ueAggregateMaxBitRateDownlink = 200 * 1000;
+ params.ueAggregateMaxBitRateUplink = 100 * 1000;
+ params.bearers = GetErabList ();
+
+ NistLteRrcSap::NistHandoverPreparationInfo hpi;
+ hpi.asConfig.sourceUeIdentity = m_rnti;
+ hpi.asConfig.sourceDlCarrierFreq = m_rrc->m_dlEarfcn;
+ hpi.asConfig.sourceNistMeasConfig = m_rrc->m_ueNistMeasConfig;
+ hpi.asConfig.sourceRadioResourceConfig = GetRadioResourceConfigForNistHandoverPreparationInfo ();
+ hpi.asConfig.sourceNistMasterInformationBlock.dlBandwidth = m_rrc->m_dlBandwidth;
+ hpi.asConfig.sourceNistMasterInformationBlock.systemFrameNumber = 0;
+ hpi.asConfig.sourceNistSystemInformationBlockType1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity = m_rrc->m_sib1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity;
+ hpi.asConfig.sourceNistSystemInformationBlockType1.cellAccessRelatedInfo.cellIdentity = m_rrc->m_cellId;
+ hpi.asConfig.sourceNistSystemInformationBlockType1.cellAccessRelatedInfo.csgIndication = m_rrc->m_sib1.cellAccessRelatedInfo.csgIndication;
+ hpi.asConfig.sourceNistSystemInformationBlockType1.cellAccessRelatedInfo.csgIdentity = m_rrc->m_sib1.cellAccessRelatedInfo.csgIdentity;
+ NistLteEnbCmacSapProvider::NistRachConfig rc = m_rrc->m_cmacSapProvider->GetNistRachConfig ();
+ hpi.asConfig.sourceNistSystemInformationBlockType2.radioResourceConfigCommon.rachConfigCommon.preambleInfo.numberOfRaPreambles = rc.numberOfRaPreambles;
+ hpi.asConfig.sourceNistSystemInformationBlockType2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.preambleTransMax = rc.preambleTransMax;
+ hpi.asConfig.sourceNistSystemInformationBlockType2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.raResponseWindowSize = rc.raResponseWindowSize;
+ hpi.asConfig.sourceNistSystemInformationBlockType2.freqInfo.ulCarrierFreq = m_rrc->m_ulEarfcn;
+ hpi.asConfig.sourceNistSystemInformationBlockType2.freqInfo.ulBandwidth = m_rrc->m_ulBandwidth;
+ params.rrcContext = m_rrc->m_rrcSapUser->EncodeNistHandoverPreparationInformation (hpi);
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+ NS_LOG_LOGIC ("mmeUeS1apId = " << params.mmeUeS1apId);
+ NS_LOG_LOGIC ("rrcContext = " << params.rrcContext);
+
+ m_rrc->m_x2SapProvider->SendHandoverRequest (params);
+ SwitchToState (HANDOVER_PREPARATION);
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+
+}
+
+void
+NistUeManager::RecvHandoverRequestAck (NistEpcX2SapUser::NistHandoverRequestAckParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_ASSERT_MSG (params.notAdmittedBearers.empty (), "not admission of some bearers upon handover is not supported");
+ NS_ASSERT_MSG (params.admittedBearers.size () == m_drbMap.size (), "not enough bearers in admittedBearers");
+
+ // note: the Handover command from the target eNB to the source eNB
+ // is expected to be sent transparently to the UE; however, here we
+ // decode the message and eventually reencode it. This way we can
+ // support both a real RRC protocol implementation and an ideal one
+ // without actual RRC protocol encoding.
+
+ Ptr<Packet> encodedHandoverCommand = params.rrcContext;
+ NistLteRrcSap::NistRrcConnectionReconfiguration handoverCommand = m_rrc->m_rrcSapUser->DecodeHandoverCommand (encodedHandoverCommand);
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionReconfiguration (m_rnti, handoverCommand);
+ SwitchToState (HANDOVER_LEAVING);
+ m_handoverLeavingTimeout = Simulator::Schedule (m_rrc->m_handoverLeavingTimeoutDuration,
+ &NistLteEnbRrc::HandoverLeavingTimeout,
+ m_rrc, m_rnti);
+ NS_ASSERT (handoverCommand.haveNistMobilityControlInfo);
+ m_rrc->m_handoverStartTrace (m_imsi, m_rrc->m_cellId, m_rnti, handoverCommand.mobilityControlInfo.targetPhysCellId);
+
+ NistEpcX2SapProvider::NistSnNistStatusTransferParams sst;
+ sst.oldEnbUeX2apId = params.oldEnbUeX2apId;
+ sst.newEnbUeX2apId = params.newEnbUeX2apId;
+ sst.sourceCellId = params.sourceCellId;
+ sst.targetCellId = params.targetCellId;
+ for ( std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator drbIt = m_drbMap.begin ();
+ drbIt != m_drbMap.end ();
+ ++drbIt)
+ {
+ // SN status transfer is only for AM RLC
+ if (0 != drbIt->second->m_rlc->GetObject<NistLteRlcAm> ())
+ {
+ NistLtePdcp::NistStatus status = drbIt->second->m_pdcp->GetNistStatus ();
+ NistEpcX2Sap::NistErabsSubjectToNistStatusTransferItem i;
+ i.dlPdcpSn = status.txSn;
+ i.ulPdcpSn = status.rxSn;
+ sst.erabsSubjectToNistStatusTransferList.push_back (i);
+ }
+ }
+ m_rrc->m_x2SapProvider->SendSnNistStatusTransfer (sst);
+}
+
+
+NistLteRrcSap::NistRadioResourceConfigDedicated
+NistUeManager::GetRadioResourceConfigForNistHandoverPreparationInfo ()
+{
+ NS_LOG_FUNCTION (this);
+ return BuildNistRadioResourceConfigDedicated ();
+}
+
+NistLteRrcSap::NistRrcConnectionReconfiguration
+NistUeManager::GetNistRrcConnectionReconfigurationForHandover ()
+{
+ NS_LOG_FUNCTION (this);
+ return BuildNistRrcConnectionReconfiguration ();
+}
+
+void
+NistUeManager::SendData (uint8_t bid, Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION (this << p << (uint16_t) bid);
+ switch (m_state)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ case CONNECTION_SETUP:
+ NS_LOG_WARN ("not connected, discarding packet");
+ return;
+ break;
+
+ case CONNECTED_NORMALLY:
+ case CONNECTION_RECONFIGURATION:
+ case CONNECTION_REESTABLISHMENT:
+ case HANDOVER_PREPARATION:
+ case HANDOVER_JOINING:
+ case HANDOVER_PATH_SWITCH:
+ {
+ NS_LOG_LOGIC ("queueing data on PDCP for transmission over the air");
+ NistLtePdcpSapProvider::NistTransmitPdcpSduParameters params;
+ params.pdcpSdu = p;
+ params.rnti = m_rnti;
+ params.lcid = Bid2Lcid (bid);
+ uint8_t drbid = Bid2Drbid (bid);
+ //Transmit PDCP sdu only if DRB ID found in drbMap
+ std::map<uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ if (it != m_drbMap.end ())
+ {
+ Ptr<LteDataRadioNistBearerInfo> bearerInfo = GetDataRadioNistBearerInfo (drbid);
+ if (bearerInfo != NULL)
+ {
+ NistLtePdcpSapProvider* pdcpSapProvider = bearerInfo->m_pdcp->GetNistLtePdcpSapProvider ();
+ pdcpSapProvider->TransmitPdcpSdu (params);
+ }
+ }
+ }
+ break;
+
+ case HANDOVER_LEAVING:
+ {
+ NS_LOG_LOGIC ("forwarding data to target eNB over X2-U");
+ uint8_t drbid = Bid2Drbid (bid);
+ NistEpcX2Sap::NistUeDataParams params;
+ params.sourceCellId = m_rrc->m_cellId;
+ params.targetCellId = m_targetCellId;
+ params.gtpTeid = GetDataRadioNistBearerInfo (drbid)->m_gtpTeid;
+ params.ueData = p;
+ m_rrc->m_x2SapProvider->SendUeData (params);
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+std::vector<NistEpcX2Sap::NistErabToBeSetupItem>
+NistUeManager::GetErabList ()
+{
+ NS_LOG_FUNCTION (this);
+ std::vector<NistEpcX2Sap::NistErabToBeSetupItem> ret;
+ for (std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.begin ();
+ it != m_drbMap.end ();
+ ++it)
+ {
+ NistEpcX2Sap::NistErabToBeSetupItem etbsi;
+ etbsi.erabId = it->second->m_epsBearerIdentity;
+ etbsi.erabLevelQosParameters = it->second->m_epsBearer;
+ etbsi.dlForwarding = false;
+ etbsi.transportLayerAddress = it->second->m_transportLayerAddress;
+ etbsi.gtpTeid = it->second->m_gtpTeid;
+ ret.push_back (etbsi);
+ }
+ return ret;
+}
+
+void
+NistUeManager::SendUeContextRelease ()
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case HANDOVER_PATH_SWITCH:
+ NS_LOG_INFO ("Send UE CONTEXT RELEASE from target eNB to source eNB");
+ NistEpcX2SapProvider::NistUeContextReleaseParams ueCtxReleaseParams;
+ ueCtxReleaseParams.oldEnbUeX2apId = m_sourceX2apId;
+ ueCtxReleaseParams.newEnbUeX2apId = m_rnti;
+ ueCtxReleaseParams.sourceCellId = m_sourceCellId;
+ m_rrc->m_x2SapProvider->SendUeContextRelease (ueCtxReleaseParams);
+ SwitchToState (CONNECTED_NORMALLY);
+ m_rrc->m_handoverEndOkTrace (m_imsi, m_rrc->m_cellId, m_rnti);
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+NistUeManager::RecvHandoverPreparationFailure (uint16_t cellId)
+{
+ NS_LOG_FUNCTION (this << cellId);
+ switch (m_state)
+ {
+ case HANDOVER_PREPARATION:
+ NS_ASSERT (cellId == m_targetCellId);
+ NS_LOG_INFO ("target eNB sent HO preparation failure, aborting HO");
+ SwitchToState (CONNECTED_NORMALLY);
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+NistUeManager::RecvSnNistStatusTransfer (NistEpcX2SapUser::NistSnNistStatusTransferParams params)
+{
+ NS_LOG_FUNCTION (this);
+ for (std::vector<NistEpcX2Sap::NistErabsSubjectToNistStatusTransferItem>::iterator erabIt
+ = params.erabsSubjectToNistStatusTransferList.begin ();
+ erabIt != params.erabsSubjectToNistStatusTransferList.end ();
+ ++erabIt)
+ {
+ // NistLtePdcp::NistStatus status;
+ // status.txSn = erabIt->dlPdcpSn;
+ // status.rxSn = erabIt->ulPdcpSn;
+ // uint8_t drbId = Bid2Drbid (erabIt->erabId);
+ // std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator drbIt = m_drbMap.find (drbId);
+ // NS_ASSERT_MSG (drbIt != m_drbMap.end (), "could not find DRBID " << (uint32_t) drbId);
+ // drbIt->second->m_pdcp->SetNistStatus (status);
+ }
+}
+
+void
+NistUeManager::RecvUeContextRelease (NistEpcX2SapUser::NistUeContextReleaseParams params)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG (m_state == HANDOVER_LEAVING, "method unexpected in state " << ToString (m_state));
+ m_handoverLeavingTimeout.Cancel ();
+}
+
+
+// methods forwarded from RRC SAP
+
+void
+NistUeManager::CompleteSetupUe (NistLteEnbRrcSapProvider::CompleteNistSetupUeParameters params)
+{
+ NS_LOG_FUNCTION (this);
+ m_srb0->m_rlc->SetNistLteRlcSapUser (params.srb0SapUser);
+ m_srb1->m_pdcp->SetNistLtePdcpSapUser (params.srb1SapUser);
+}
+
+void
+NistUeManager::RecvNistRrcConnectionRequest (NistLteRrcSap::NistRrcConnectionRequest msg)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ {
+ m_connectionRequestTimeout.Cancel ();
+
+ if (m_rrc->m_admitNistRrcConnectionRequest == true)
+ {
+ m_imsi = msg.ueIdentity;
+ if (m_rrc->m_s1SapProvider != 0)
+ {
+ m_rrc->m_s1SapProvider->InitialUeMessage (m_imsi, m_rnti);
+ }
+
+ // send RRC CONNECTION SETUP to UE
+ NistLteRrcSap::NistRrcConnectionSetup msg2;
+ msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+ msg2.radioResourceConfigDedicated = BuildNistRadioResourceConfigDedicated ();
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionSetup (m_rnti, msg2);
+
+ RecordDataRadioBearersToBeStarted ();
+ m_connectionSetupTimeout = Simulator::Schedule (
+ m_rrc->m_connectionSetupTimeoutDuration,
+ &NistLteEnbRrc::ConnectionSetupTimeout, m_rrc, m_rnti);
+ SwitchToState (CONNECTION_SETUP);
+ }
+ else
+ {
+ NS_LOG_INFO ("rejecting connection request for RNTI " << m_rnti);
+
+ // send RRC CONNECTION REJECT to UE
+ NistLteRrcSap::NistRrcConnectionReject rejectMsg;
+ rejectMsg.waitTime = 3;
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionReject (m_rnti, rejectMsg);
+
+ m_connectionRejectedTimeout = Simulator::Schedule (
+ m_rrc->m_connectionRejectedTimeoutDuration,
+ &NistLteEnbRrc::ConnectionRejectedTimeout, m_rrc, m_rnti);
+ SwitchToState (CONNECTION_REJECTED);
+ }
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+NistUeManager::RecvNistRrcConnectionSetupCompleted (NistLteRrcSap::NistRrcConnectionSetupCompleted msg)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case CONNECTION_SETUP:
+ m_connectionSetupTimeout.Cancel ();
+ StartDataRadioBearers ();
+ SwitchToState (CONNECTED_NORMALLY);
+ m_rrc->m_connectionEstablishedTrace (m_imsi, m_rrc->m_cellId, m_rnti);
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+NistUeManager::RecvNistRrcConnectionReconfigurationCompleted (NistLteRrcSap::NistRrcConnectionReconfigurationCompleted msg)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case CONNECTION_RECONFIGURATION:
+ StartDataRadioBearers ();
+ if (m_needPhyMacConfiguration)
+ {
+ // configure MAC (and scheduler)
+ NistLteEnbCmacSapProvider::NistUeConfig req;
+ req.m_rnti = m_rnti;
+ req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
+ req.m_slDestinations = m_slDestinations;
+ m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
+
+ // configure PHY
+ m_rrc->m_cphySapProvider->SetTransmissionMode (req.m_rnti, req.m_transmissionMode);
+
+ double paDouble = NistLteRrcSap::ConvertNistPdschConfigDedicated2Double (m_physicalConfigDedicated.pdschConfigDedicated);
+ m_rrc->m_cphySapProvider->SetPa (m_rnti, paDouble);
+
+ m_needPhyMacConfiguration = false;
+ }
+ SwitchToState (CONNECTED_NORMALLY);
+ 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:
+ if (!m_slPoolChanged) {
+ NS_LOG_INFO ("ignoring RecvNistRrcConnectionReconfigurationCompleted in state " << ToString (m_state));
+ } else {
+ //inform about new sidelink pool if needed
+ // configure MAC (and scheduler)
+ NistLteEnbCmacSapProvider::NistUeConfig req;
+ req.m_rnti = m_rnti;
+ req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
+ req.m_slDestinations = m_slDestinations;
+ m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
+
+ m_slPoolChanged = false;
+ }
+ break;
+
+ case HANDOVER_LEAVING:
+ NS_LOG_INFO ("ignoring RecvNistRrcConnectionReconfigurationCompleted in state " << ToString (m_state));
+ break;
+
+ case HANDOVER_JOINING:
+ {
+ m_handoverJoiningTimeout.Cancel ();
+ NS_LOG_INFO ("Send PATH SWITCH REQUEST to the MME");
+ NistEpcEnbS1SapProvider::NistPathSwitchRequestParameters params;
+ params.rnti = m_rnti;
+ params.cellId = m_rrc->m_cellId;
+ params.mmeUeS1Id = m_imsi;
+ SwitchToState (HANDOVER_PATH_SWITCH);
+ for (std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.begin ();
+ it != m_drbMap.end ();
+ ++it)
+ {
+ NistEpcEnbS1SapProvider::NistBearerToBeSwitched b;
+ b.epsBearerId = it->second->m_epsBearerIdentity;
+ b.teid = it->second->m_gtpTeid;
+ params.bearersToBeSwitched.push_back (b);
+ }
+ m_rrc->m_s1SapProvider->PathSwitchRequest (params);
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+NistUeManager::RecvNistRrcConnectionReestablishmentRequest (NistLteRrcSap::NistRrcConnectionReestablishmentRequest msg)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case CONNECTED_NORMALLY:
+ break;
+
+ case HANDOVER_LEAVING:
+ m_handoverLeavingTimeout.Cancel ();
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+
+ NistLteRrcSap::NistRrcConnectionReestablishment msg2;
+ msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+ msg2.radioResourceConfigDedicated = BuildNistRadioResourceConfigDedicated ();
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionReestablishment (m_rnti, msg2);
+ SwitchToState (CONNECTION_REESTABLISHMENT);
+}
+
+void
+NistUeManager::RecvNistRrcConnectionReestablishmentComplete (NistLteRrcSap::NistRrcConnectionReestablishmentComplete msg)
+{
+ NS_LOG_FUNCTION (this);
+ SwitchToState (CONNECTED_NORMALLY);
+}
+
+void
+NistUeManager::RecvNistMeasurementReport (NistLteRrcSap::NistMeasurementReport msg)
+{
+ uint8_t measId = msg.measResults.measId;
+ NS_LOG_FUNCTION (this << (uint16_t) measId);
+ NS_LOG_LOGIC ("measId " << (uint16_t) measId
+ << " haveMeasResultNeighCells " << msg.measResults.haveMeasResultNeighCells
+ << " measResultListEutra " << msg.measResults.measResultListEutra.size ());
+ NS_LOG_LOGIC ("serving cellId " << m_rrc->m_cellId
+ << " RSRP " << (uint16_t) msg.measResults.rsrpResult
+ << " RSRQ " << (uint16_t) msg.measResults.rsrqResult);
+
+ for (std::list <NistLteRrcSap::NistMeasResultEutra>::iterator it = msg.measResults.measResultListEutra.begin ();
+ it != msg.measResults.measResultListEutra.end ();
+ ++it)
+ {
+ NS_LOG_LOGIC ("neighbour cellId " << it->physCellId
+ << " RSRP " << (it->haveRsrpResult ? (uint16_t) it->rsrpResult : 255)
+ << " RSRQ " << (it->haveRsrqResult ? (uint16_t) it->rsrqResult : 255));
+ }
+
+ if ((m_rrc->m_handoverManagementSapProvider != 0)
+ && (m_rrc->m_handoverMeasIds.find (measId) != m_rrc->m_handoverMeasIds.end ()))
+ {
+ // this measurement was requested by the handover algorithm
+ m_rrc->m_handoverManagementSapProvider->ReportUeMeas (m_rnti,
+ msg.measResults);
+ }
+
+ if ((m_rrc->m_anrSapProvider != 0)
+ && (m_rrc->m_anrMeasIds.find (measId) != m_rrc->m_anrMeasIds.end ()))
+ {
+ // this measurement was requested by the ANR function
+ m_rrc->m_anrSapProvider->ReportUeMeas (msg.measResults);
+ }
+
+ if ((m_rrc->m_ffrRrcSapProvider != 0)
+ && (m_rrc->m_ffrMeasIds.find (measId) != m_rrc->m_ffrMeasIds.end ()))
+ {
+ // this measurement was requested by the FFR function
+ m_rrc->m_ffrRrcSapProvider->ReportUeMeas (m_rnti, msg.measResults);
+ }
+
+ // fire a trace source
+ m_rrc->m_recvNistMeasurementReportTrace (m_imsi, m_rrc->m_cellId, m_rnti, msg);
+
+} // end of NistUeManager::RecvNistMeasurementReport
+
+
+void
+NistUeManager::RecvSidelinkUeInformation (NistLteRrcSap::SidelinkUeInformation msg)
+{
+ NS_LOG_FUNCTION (this);
+ //Parse message and decide on allocation
+ //for now we only handle one group per UE
+ if (msg.haveCommTxResourceReq) {
+ NS_ASSERT_MSG (msg.slCommTxResourceReq.slDestinationInfoList.nbDestinations=1, "Current implementation does not support more than 1 group per UE");
+
+ //store destination list in the UE
+ m_slDestinations.clear ();
+ for (int i = 0 ; i < msg.slCommTxResourceReq.slDestinationInfoList.nbDestinations; i++) {
+ m_slDestinations.push_back (msg.slCommTxResourceReq.slDestinationInfoList.SlDestinationIdentity[i]);
+ }
+
+
+ //populate dedicated resources
+ NistLteRrcSap::SlCommConfig dedicatedResource;
+ dedicatedResource.commTxResources = NistLteRrcSap::SlCommConfig::SETUP;
+
+ //check if pool already in use
+ std::map <uint32_t, LteEnbRrcSl::ActivePoolInfo>::iterator it2 = m_rrc->m_sidelinkConfiguration->m_activePoolMap.find (msg.slCommTxResourceReq.slDestinationInfoList.SlDestinationIdentity[0]);
+
+ if (it2 == m_rrc->m_sidelinkConfiguration->m_activePoolMap.end())
+ {
+ //no active pool for this group, let's check if we have a preconfigured one
+ //or later, how to create one dynamically
+ std::map <uint32_t, NistLteRrcSap::SlCommTxResourcesSetup>::iterator it = m_rrc->m_sidelinkConfiguration->m_preconfigDedicatedPoolMap.find (msg.slCommTxResourceReq.slDestinationInfoList.SlDestinationIdentity[0]);
+
+ if (it != m_rrc->m_sidelinkConfiguration->m_preconfigDedicatedPoolMap.end())
+ {
+ dedicatedResource.setup = it->second;
+ } else
+ {
+ NS_LOG_INFO ("No pre-provisioned pool found for group " << msg.slCommTxResourceReq.slDestinationInfoList.SlDestinationIdentity[0]);
+ }
+
+ Ptr<SidelinkTxCommResourcePool> m_slPool = CreateObject<SidelinkTxCommResourcePool> ();
+ if (dedicatedResource.setup.setup == NistLteRrcSap::SlCommTxResourcesSetup::SCHEDULED)
+ {
+ m_slPool->SetPool (dedicatedResource.setup.scheduled.commTxConfig);
+ if (dedicatedResource.setup.scheduled.haveMcs) {
+ m_slPool->SetScheduledTxParameters (m_rnti, dedicatedResource.setup.scheduled.macMainConfig, dedicatedResource.setup.scheduled.commTxConfig, 0, dedicatedResource.setup.scheduled.mcs);
+ } else
+ {
+ m_slPool->SetScheduledTxParameters (m_rnti, dedicatedResource.setup.scheduled.macMainConfig, dedicatedResource.setup.scheduled.commTxConfig, 0);
+ }
+ } else
+ {
+ //right now, only use the first pool
+ NS_ASSERT (dedicatedResource.setup.ueSelected.havePoolToAdd && dedicatedResource.setup.ueSelected.poolToAddModList.nbPools > 0);
+ m_slPool->SetPool (dedicatedResource.setup.ueSelected.poolToAddModList.pools[0].pool);
+ }
+
+ LteEnbRrcSl::ActivePoolInfo newPoolInfo;
+ newPoolInfo.m_pool = m_slPool;
+ newPoolInfo.m_poolSetup = it->second;
+ newPoolInfo.m_rntiSet.insert (m_rnti);
+ //tell the MAC that there is a new pool
+ m_rrc->m_cmacSapProvider->AddPool (msg.slCommTxResourceReq.slDestinationInfoList.SlDestinationIdentity[0], m_slPool);
+
+ m_rrc->m_sidelinkConfiguration->m_activePoolMap.insert (std::pair<uint32_t, LteEnbRrcSl::ActivePoolInfo> (msg.slCommTxResourceReq.slDestinationInfoList.SlDestinationIdentity[0], newPoolInfo));
+ m_slPoolChanged = true;
+
+ } else
+ {
+ dedicatedResource.setup = it2->second.m_poolSetup;
+ if (it2->second.m_rntiSet.find (m_rnti) == it2->second.m_rntiSet.end()) {
+ //the pool is active but the UE was not on the list
+ it2->second.m_rntiSet.insert (m_rnti);
+ m_slPoolChanged = true;
+ }
+ } //else we already know this UE is using this pool
+
+ //populating RRCConnectionReconfiguration message
+ NistLteRrcSap::NistRrcConnectionReconfiguration msg2;
+ msg2.haveNistMeasConfig = false;
+ msg2.haveNistMobilityControlInfo = false;
+ msg2.haveNistRadioResourceConfigDedicated = false;
+ msg2.haveSlCommConfig = true;
+ msg2.slCommConfig = dedicatedResource;
+ //RRC Connection Reconfiguration towards UE
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionReconfiguration (m_rnti, msg2);
+
+
+ } else {
+ //must release resources
+
+ NistLteRrcSap::SlCommConfig dedicatedResource;
+ dedicatedResource.commTxResources = NistLteRrcSap::SlCommConfig::RELEASE;
+ //populating RRCConnectionReconfiguration message
+ NistLteRrcSap::NistRrcConnectionReconfiguration msg2;
+ msg2.haveNistMeasConfig = false;
+ msg2.haveNistMobilityControlInfo = false;
+ msg2.haveNistRadioResourceConfigDedicated = false;
+ msg2.haveSlCommConfig = true;
+ msg2.slCommConfig = dedicatedResource;
+ //RRC Connection Reconfiguration towards UE
+ m_rrc->m_rrcSapUser->SendNistRrcConnectionReconfiguration (m_rnti, msg2);
+
+ m_slDestinations.clear();
+ m_slPoolChanged = true;
+ }
+
+ if (msg.haveCommRxInterestedFreq) {
+ //interest from the UE
+ } else if (0) {
+ //no more interest from that UE
+ }
+}
+
+// methods forwarded from CMAC SAP
+
+void
+NistUeManager::CmacNistUeConfigUpdateInd (NistLteEnbCmacSapUser::NistUeConfig cmacParams)
+{
+ NS_LOG_FUNCTION (this << m_rnti);
+ // at this stage used only by the scheduler for updating txMode
+
+ m_physicalConfigDedicated.antennaInfo.transmissionMode = cmacParams.m_transmissionMode;
+
+ m_needPhyMacConfiguration = true;
+
+ // reconfigure the UE RRC
+ ScheduleNistRrcConnectionReconfiguration ();
+}
+
+
+// methods forwarded from PDCP SAP
+
+void
+NistUeManager::DoReceivePdcpSdu (NistLtePdcpSapUser::NistReceivePdcpSduParameters params)
+{
+ NS_LOG_FUNCTION (this);
+ if (params.lcid > 2)
+ {
+ // data radio bearer
+ NistEpsBearerTag tag;
+ tag.SetRnti (params.rnti);
+ tag.SetBid (Lcid2Bid (params.lcid));
+ params.pdcpSdu->AddPacketTag (tag);
+ m_rrc->m_forwardUpCallback (params.pdcpSdu);
+ }
+}
+
+
+uint16_t
+NistUeManager::GetRnti (void) const
+{
+ return m_rnti;
+}
+
+uint64_t
+NistUeManager::GetImsi (void) const
+{
+ return m_imsi;
+}
+
+uint16_t
+NistUeManager::GetSrsConfigurationIndex (void) const
+{
+ return m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex;
+}
+
+void
+NistUeManager::SetSrsConfigurationIndex (uint16_t srsConfIndex)
+{
+ NS_LOG_FUNCTION (this);
+ m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = srsConfIndex;
+ m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (m_rnti, srsConfIndex);
+ switch (m_state)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ // do nothing, srs conf index will be correctly enforced upon
+ // RRC connection establishment
+ break;
+
+ default:
+ ScheduleNistRrcConnectionReconfiguration ();
+ break;
+ }
+}
+
+NistUeManager::State
+NistUeManager::GetState (void) const
+{
+ return m_state;
+}
+
+void
+NistUeManager::SetNistPdschConfigDedicated (NistLteRrcSap::NistPdschConfigDedicated pdschConfigDedicated)
+{
+ NS_LOG_FUNCTION (this);
+ m_physicalConfigDedicated.pdschConfigDedicated = pdschConfigDedicated;
+
+ m_needPhyMacConfiguration = true;
+
+ // reconfigure the UE RRC
+ ScheduleNistRrcConnectionReconfiguration ();
+}
+
+uint8_t
+NistUeManager::AddDataRadioNistBearerInfo (Ptr<LteDataRadioNistBearerInfo> drbInfo)
+{
+ NS_LOG_FUNCTION (this);
+ const uint8_t MAX_DRB_ID = 32;
+ for (int drbid = (m_lastAllocatedDrbid + 1) % MAX_DRB_ID;
+ drbid != m_lastAllocatedDrbid;
+ drbid = (drbid + 1) % MAX_DRB_ID)
+ {
+ if (drbid != 0) // 0 is not allowed
+ {
+ if (m_drbMap.find (drbid) == m_drbMap.end ())
+ {
+ m_drbMap.insert (std::pair<uint8_t, Ptr<LteDataRadioNistBearerInfo> > (drbid, drbInfo));
+ drbInfo->m_drbIdentity = drbid;
+ m_lastAllocatedDrbid = drbid;
+ return drbid;
+ }
+ }
+ }
+ NS_FATAL_ERROR ("no more data radio bearer ids available");
+ return 0;
+}
+
+Ptr<LteDataRadioNistBearerInfo>
+NistUeManager::GetDataRadioNistBearerInfo (uint8_t drbid)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) drbid);
+ NS_ASSERT (0 != drbid);
+ std::map<uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ABORT_IF (it == m_drbMap.end ());
+ return it->second;
+}
+
+
+void
+NistUeManager::RemoveDataRadioNistBearerInfo (uint8_t drbid)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) drbid);
+ std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ASSERT_MSG (it != m_drbMap.end (), "request to remove radio bearer with unknown drbid " << drbid);
+ m_drbMap.erase (it);
+}
+
+
+NistLteRrcSap::NistRrcConnectionReconfiguration
+NistUeManager::BuildNistRrcConnectionReconfiguration ()
+{
+ NistLteRrcSap::NistRrcConnectionReconfiguration msg;
+ msg.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+ msg.haveNistRadioResourceConfigDedicated = true;
+ msg.radioResourceConfigDedicated = BuildNistRadioResourceConfigDedicated ();
+ msg.haveNistMobilityControlInfo = false;
+ msg.haveNistMeasConfig = true;
+ msg.haveSlCommConfig = false;
+ msg.measConfig = m_rrc->m_ueNistMeasConfig;
+
+ return msg;
+}
+
+NistLteRrcSap::NistRadioResourceConfigDedicated
+NistUeManager::BuildNistRadioResourceConfigDedicated ()
+{
+ NistLteRrcSap::NistRadioResourceConfigDedicated rrcd;
+
+ if (m_srb1 != 0)
+ {
+ NistLteRrcSap::NistSrbToAddMod stam;
+ stam.srbIdentity = m_srb1->m_srbIdentity;
+ stam.logicalChannelConfig = m_srb1->m_logicalChannelConfig;
+ rrcd.srbToAddModList.push_back (stam);
+ }
+
+ for (std::map <uint8_t, Ptr<LteDataRadioNistBearerInfo> >::iterator it = m_drbMap.begin ();
+ it != m_drbMap.end ();
+ ++it)
+ {
+ NistLteRrcSap::NistDrbToAddMod dtam;
+ dtam.epsBearerIdentity = it->second->m_epsBearerIdentity;
+ dtam.drbIdentity = it->second->m_drbIdentity;
+ dtam.rlcConfig = it->second->m_rlcConfig;
+ dtam.logicalChannelIdentity = it->second->m_logicalChannelIdentity;
+ dtam.logicalChannelConfig = it->second->m_logicalChannelConfig;
+ rrcd.drbToAddModList.push_back (dtam);
+ }
+
+ rrcd.haveNistPhysicalConfigDedicated = true;
+ rrcd.physicalConfigDedicated = m_physicalConfigDedicated;
+ return rrcd;
+}
+
+uint8_t
+NistUeManager::GetNewRrcTransactionIdentifier ()
+{
+ return ++m_lastRrcTransactionIdentifier;
+}
+
+uint8_t
+NistUeManager::Lcid2Drbid (uint8_t lcid)
+{
+ NS_ASSERT (lcid > 2);
+ return lcid - 2;
+}
+
+uint8_t
+NistUeManager::Drbid2Lcid (uint8_t drbid)
+{
+ return drbid + 2;
+}
+uint8_t
+NistUeManager::Lcid2Bid (uint8_t lcid)
+{
+ NS_ASSERT (lcid > 2);
+ return lcid - 2;
+}
+
+uint8_t
+NistUeManager::Bid2Lcid (uint8_t bid)
+{
+ return bid + 2;
+}
+
+uint8_t
+NistUeManager::Drbid2Bid (uint8_t drbid)
+{
+ return drbid;
+}
+
+uint8_t
+NistUeManager::Bid2Drbid (uint8_t bid)
+{
+ return bid;
+}
+
+
+void
+NistUeManager::SwitchToState (State newState)
+{
+ NS_LOG_FUNCTION (this << ToString (newState));
+ State oldState = m_state;
+ m_state = newState;
+ NS_LOG_INFO (this << " IMSI " << m_imsi << " RNTI " << m_rnti << " NistUeManager "
+ << ToString (oldState) << " --> " << ToString (newState));
+ m_stateTransitionTrace (m_imsi, m_rrc->m_cellId, m_rnti, oldState, newState);
+
+ switch (newState)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ case HANDOVER_JOINING:
+ NS_FATAL_ERROR ("cannot switch to an initial state");
+ break;
+
+ case CONNECTION_SETUP:
+ break;
+
+ case CONNECTED_NORMALLY:
+ {
+ if (m_pendingNistRrcConnectionReconfiguration == true)
+ {
+ ScheduleNistRrcConnectionReconfiguration ();
+ }
+ }
+ break;
+
+ case CONNECTION_RECONFIGURATION:
+ break;
+
+ case CONNECTION_REESTABLISHMENT:
+ break;
+
+ case HANDOVER_LEAVING:
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+///////////////////////////////////////////
+// eNB RRC methods
+///////////////////////////////////////////
+
+NS_OBJECT_ENSURE_REGISTERED (NistLteEnbRrc);
+
+NistLteEnbRrc::NistLteEnbRrc ()
+ : m_x2SapProvider (0),
+ m_cmacSapProvider (0),
+ m_handoverManagementSapProvider (0),
+ m_anrSapProvider (0),
+ m_ffrRrcSapProvider (0),
+ m_rrcSapUser (0),
+ m_macSapProvider (0),
+ m_s1SapProvider (0),
+ m_cphySapProvider (0),
+ m_configured (false),
+ m_lastAllocatedRnti (0),
+ m_srsCurrentPeriodicityId (0),
+ m_lastAllocatedConfigurationIndex (0),
+ m_reconfigureUes (false),
+ m_sidelinkConfiguration (0)
+{
+ NS_LOG_FUNCTION (this);
+ m_cmacSapUser = new NistEnbRrcMemberLteEnbCmacSapUser (this);
+ m_handoverManagementSapUser = new MemberNistLteHandoverManagementSapUser<NistLteEnbRrc> (this);
+ m_anrSapUser = new MemberNistLteAnrSapUser<NistLteEnbRrc> (this);
+ m_ffrRrcSapUser = new MemberNistLteFfrRrcSapUser<NistLteEnbRrc> (this);
+ m_rrcSapProvider = new NistMemberLteEnbRrcSapProvider<NistLteEnbRrc> (this);
+ m_x2SapUser = new NistEpcX2SpecificNistEpcX2SapUser<NistLteEnbRrc> (this);
+ m_s1SapUser = new MemberNistEpcEnbS1SapUser<NistLteEnbRrc> (this);
+ m_cphySapUser = new MemberNistLteEnbCphySapUser<NistLteEnbRrc> (this);
+}
+
+
+NistLteEnbRrc::~NistLteEnbRrc ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+
+void
+NistLteEnbRrc::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ m_ueMap.clear ();
+ delete m_cmacSapUser;
+ delete m_handoverManagementSapUser;
+ delete m_anrSapUser;
+ delete m_ffrRrcSapUser;
+ delete m_rrcSapProvider;
+ delete m_x2SapUser;
+ delete m_s1SapUser;
+ delete m_cphySapUser;
+}
+
+TypeId
+NistLteEnbRrc::GetTypeId (void)
+{
+ NS_LOG_FUNCTION ("NistLteEnbRrc::GetTypeId");
+ static TypeId tid = TypeId ("ns3::NistLteEnbRrc")
+ .SetParent<Object> ()
+ .AddConstructor<NistLteEnbRrc> ()
+ .AddAttribute ("UeMap", "List of NistUeManager by C-RNTI.",
+ ObjectMapValue (),
+ MakeObjectMapAccessor (&NistLteEnbRrc::m_ueMap),
+ MakeObjectMapChecker<NistUeManager> ())
+ .AddAttribute ("DefaultTransmissionMode",
+ "The default UEs' transmission mode (0: SISO)",
+ UintegerValue (0), // default tx-mode
+ MakeUintegerAccessor (&NistLteEnbRrc::m_defaultTransmissionMode),
+ MakeUintegerChecker<uint8_t> ())
+ .AddAttribute ("NistEpsBearerToRlcMapping",
+ "Specify which type of RLC will be used for each type of EPS bearer. ",
+ EnumValue (RLC_SM_ALWAYS),
+ MakeEnumAccessor (&NistLteEnbRrc::m_epsBearerToRlcMapping),
+ MakeEnumChecker (RLC_SM_ALWAYS, "RlcSmAlways",
+ RLC_UM_ALWAYS, "RlcUmAlways",
+ RLC_AM_ALWAYS, "RlcAmAlways",
+ PER_BASED, "PacketErrorRateBased"))
+ .AddAttribute ("NistSystemInformationPeriodicity",
+ "The interval for sending system information (Time value)",
+ TimeValue (MilliSeconds (80)),
+ MakeTimeAccessor (&NistLteEnbRrc::m_systemInformationPeriodicity),
+ MakeTimeChecker ())
+
+ // SRS related attributes
+ .AddAttribute ("SrsPeriodicity",
+ "The SRS periodicity in milliseconds",
+ UintegerValue (40),
+ MakeUintegerAccessor (&NistLteEnbRrc::SetSrsPeriodicity,
+ &NistLteEnbRrc::GetSrsPeriodicity),
+ MakeUintegerChecker<uint32_t> ())
+
+ // Timeout related attributes
+ .AddAttribute ("ConnectionRequestTimeoutDuration",
+ "After a RA attempt, if no RRC CONNECTION REQUEST is "
+ "received before this time, the UE context is destroyed. "
+ "Must account for reception of RAR and transmission of "
+ "RRC CONNECTION REQUEST over UL GRANT.",
+ TimeValue (MilliSeconds (15)),
+ MakeTimeAccessor (&NistLteEnbRrc::m_connectionRequestTimeoutDuration),
+ MakeTimeChecker ())
+ .AddAttribute ("ConnectionSetupTimeoutDuration",
+ "After accepting connection request, if no RRC CONNECTION "
+ "SETUP COMPLETE is received before this time, the UE "
+ "context is destroyed. Must account for the UE's reception "
+ "of RRC CONNECTION SETUP and transmission of RRC CONNECTION "
+ "SETUP COMPLETE.",
+ TimeValue (MilliSeconds (150)),
+ MakeTimeAccessor (&NistLteEnbRrc::m_connectionSetupTimeoutDuration),
+ MakeTimeChecker ())
+ .AddAttribute ("ConnectionRejectedTimeoutDuration",
+ "Time to wait between sending a RRC CONNECTION REJECT and "
+ "destroying the UE context",
+ TimeValue (MilliSeconds (30)),
+ MakeTimeAccessor (&NistLteEnbRrc::m_connectionRejectedTimeoutDuration),
+ MakeTimeChecker ())
+ .AddAttribute ("HandoverJoiningTimeoutDuration",
+ "After accepting a handover request, if no RRC CONNECTION "
+ "RECONFIGURATION COMPLETE is received before this time, the "
+ "UE context is destroyed. Must account for reception of "
+ "X2 HO REQ ACK by source eNB, transmission of the Handover "
+ "Command, non-contention-based random access and reception "
+ "of the RRC CONNECTION RECONFIGURATION COMPLETE message.",
+ TimeValue (MilliSeconds (200)),
+ MakeTimeAccessor (&NistLteEnbRrc::m_handoverJoiningTimeoutDuration),
+ MakeTimeChecker ())
+ .AddAttribute ("HandoverLeavingTimeoutDuration",
+ "After issuing a Handover Command, if neither RRC "
+ "CONNECTION RE-ESTABLISHMENT nor X2 UE Context Release has "
+ "been previously received, the UE context is destroyed.",
+ TimeValue (MilliSeconds (500)),
+ MakeTimeAccessor (&NistLteEnbRrc::m_handoverLeavingTimeoutDuration),
+ MakeTimeChecker ())
+
+ // Cell selection related attribute
+ .AddAttribute ("QRxLevMin",
+ "One of information transmitted within the SIB1 message, "
+ "indicating the required minimum RSRP level that any UE must "
+ "receive from this cell before it is allowed to camp to this "
+ "cell. The default value -70 corresponds to -140 dBm and is "
+ "the lowest possible value as defined by Section 6.3.4 of "
+ "3GPP TS 36.133. This restriction, however, only applies to "
+ "initial cell selection and EPC-enabled simulation.",
+ TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+ IntegerValue (-70),
+ MakeIntegerAccessor (&NistLteEnbRrc::m_qRxLevMin),
+ MakeIntegerChecker<int8_t> (-70, -22))
+
+ // Handover related attributes
+ .AddAttribute ("AdmitHandoverRequest",
+ "Whether to admit an X2 handover request from another eNB",
+ BooleanValue (true),
+ MakeBooleanAccessor (&NistLteEnbRrc::m_admitHandoverRequest),
+ MakeBooleanChecker ())
+ .AddAttribute ("AdmitNistRrcConnectionRequest",
+ "Whether to admit a connection request from a UE",
+ BooleanValue (true),
+ MakeBooleanAccessor (&NistLteEnbRrc::m_admitNistRrcConnectionRequest),
+ MakeBooleanChecker ())
+
+ // UE measurements related attributes
+ .AddAttribute ("RsrpFilterCoefficient",
+ "Determines the strength of smoothing effect induced by "
+ "layer 3 filtering of RSRP in all attached UE; "
+ "if set to 0, no layer 3 filtering is applicable",
+ // i.e. the variable k in 3GPP TS 36.331 section 5.5.3.2
+ UintegerValue (4),
+ MakeUintegerAccessor (&NistLteEnbRrc::m_rsrpFilterCoefficient),
+ MakeUintegerChecker<uint8_t> (0))
+ .AddAttribute ("RsrqFilterCoefficient",
+ "Determines the strength of smoothing effect induced by "
+ "layer 3 filtering of RSRQ in all attached UE; "
+ "if set to 0, no layer 3 filtering is applicable",
+ // i.e. the variable k in 3GPP TS 36.331 section 5.5.3.2
+ UintegerValue (4),
+ MakeUintegerAccessor (&NistLteEnbRrc::m_rsrqFilterCoefficient),
+ MakeUintegerChecker<uint8_t> (0))
+ //Add accessor to sidelink configuration
+ .AddAttribute ("SidelinkConfiguration",
+ "The sidelink configuration associated to this NistLtePhy",
+ PointerValue (),
+ MakePointerAccessor (&NistLteEnbRrc::m_sidelinkConfiguration),
+ MakePointerChecker <LteEnbRrcSl> ())
+ // Trace sources
+ .AddTraceSource ("NewUeContext",
+ "Fired upon creation of a new UE context.",
+ MakeTraceSourceAccessor (&NistLteEnbRrc::m_newUeContextTrace),
+ "ns3::NistLteEnbRrc::NewUeContextTracedCallback")
+ .AddTraceSource ("ConnectionEstablished",
+ "Fired upon successful RRC connection establishment.",
+ MakeTraceSourceAccessor (&NistLteEnbRrc::m_connectionEstablishedTrace),
+ "ns3::NistLteEnbRrc::ConnectionHandoverTracedCallback")
+ .AddTraceSource ("ConnectionReconfiguration",
+ "trace fired upon RRC connection reconfiguration",
+ MakeTraceSourceAccessor (&NistLteEnbRrc::m_connectionReconfigurationTrace),
+ "ns3::NistLteEnbRrc::ConnectionHandoverTracedCallback")
+ .AddTraceSource ("HandoverStart",
+ "trace fired upon start of a handover procedure",
+ MakeTraceSourceAccessor (&NistLteEnbRrc::m_handoverStartTrace),
+ "ns3::NistLteEnbRrc::HandoverStartTracedCallback")
+ .AddTraceSource ("HandoverEndOk",
+ "trace fired upon successful termination of a handover procedure",
+ MakeTraceSourceAccessor (&NistLteEnbRrc::m_handoverEndOkTrace),
+ "ns3::NistLteEnbRrc::ConnectionHandoverTracedCallback")
+ .AddTraceSource ("RecvNistMeasurementReport",
+ "trace fired when measurement report is received",
+ MakeTraceSourceAccessor (&NistLteEnbRrc::m_recvNistMeasurementReportTrace),
+ "ns3::NistLteEnbRrc::ReceiveReportTracedCallback")
+ ;
+ return tid;
+}
+
+void
+NistLteEnbRrc::SetNistEpcX2SapProvider (NistEpcX2SapProvider * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_x2SapProvider = s;
+}
+
+NistEpcX2SapUser*
+NistLteEnbRrc::GetNistEpcX2SapUser ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_x2SapUser;
+}
+
+void
+NistLteEnbRrc::SetNistLteEnbCmacSapProvider (NistLteEnbCmacSapProvider * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_cmacSapProvider = s;
+}
+
+NistLteEnbCmacSapUser*
+NistLteEnbRrc::GetNistLteEnbCmacSapUser ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_cmacSapUser;
+}
+
+void
+NistLteEnbRrc::SetNistLteHandoverManagementSapProvider (NistLteHandoverManagementSapProvider * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_handoverManagementSapProvider = s;
+}
+
+NistLteHandoverManagementSapUser*
+NistLteEnbRrc::GetNistLteHandoverManagementSapUser ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_handoverManagementSapUser;
+}
+
+void
+NistLteEnbRrc::SetNistLteAnrSapProvider (NistLteAnrSapProvider * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_anrSapProvider = s;
+}
+
+NistLteAnrSapUser*
+NistLteEnbRrc::GetNistLteAnrSapUser ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_anrSapUser;
+}
+
+void
+NistLteEnbRrc::SetNistLteFfrRrcSapProvider (NistLteFfrRrcSapProvider * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_ffrRrcSapProvider = s;
+}
+
+NistLteFfrRrcSapUser*
+NistLteEnbRrc::GetNistLteFfrRrcSapUser ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_ffrRrcSapUser;
+}
+
+void
+NistLteEnbRrc::SetNistLteEnbRrcSapUser (NistLteEnbRrcSapUser * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_rrcSapUser = s;
+}
+
+NistLteEnbRrcSapProvider*
+NistLteEnbRrc::GetNistLteEnbRrcSapProvider ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_rrcSapProvider;
+}
+
+void
+NistLteEnbRrc::SetNistLteMacSapProvider (NistLteMacSapProvider * s)
+{
+ NS_LOG_FUNCTION (this);
+ m_macSapProvider = s;
+}
+
+void
+NistLteEnbRrc::SetS1SapProvider (NistEpcEnbS1SapProvider * s)
+{
+ m_s1SapProvider = s;
+}
+
+
+NistEpcEnbS1SapUser*
+NistLteEnbRrc::GetS1SapUser ()
+{
+ return m_s1SapUser;
+}
+
+void
+NistLteEnbRrc::SetNistLteEnbCphySapProvider (NistLteEnbCphySapProvider * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_cphySapProvider = s;
+}
+
+NistLteEnbCphySapUser*
+NistLteEnbRrc::GetNistLteEnbCphySapUser ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_cphySapUser;
+}
+
+bool
+NistLteEnbRrc::HasNistUeManager (uint16_t rnti) const
+{
+ NS_LOG_FUNCTION (this << (uint32_t) rnti);
+ std::map<uint16_t, Ptr<NistUeManager> >::const_iterator it = m_ueMap.find (rnti);
+ return (it != m_ueMap.end ());
+}
+
+Ptr<NistUeManager>
+NistLteEnbRrc::GetNistUeManager (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) rnti);
+ NS_ASSERT (0 != rnti);
+ std::map<uint16_t, Ptr<NistUeManager> >::iterator it = m_ueMap.find (rnti);
+ NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
+ return it->second;
+}
+
+uint8_t
+NistLteEnbRrc::AddUeMeasReportConfig (NistLteRrcSap::NistReportConfigEutra config)
+{
+ NS_LOG_FUNCTION (this);
+
+ // SANITY CHECK
+
+ NS_ASSERT_MSG (m_ueNistMeasConfig.measIdToAddModList.size () == m_ueNistMeasConfig.reportConfigToAddModList.size (),
+ "Measurement identities and reporting configuration should not have different quantity");
+
+ if (Simulator::Now () != Seconds (0))
+ {
+ NS_FATAL_ERROR ("AddUeMeasReportConfig may not be called after the simulation has run");
+ }
+
+ // INPUT VALIDATION
+
+ switch (config.triggerQuantity)
+ {
+ case NistLteRrcSap::NistReportConfigEutra::RSRP:
+ if ((config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A5)
+ && (config.threshold2.choice != NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP))
+ {
+ NS_FATAL_ERROR ("The given triggerQuantity (RSRP) does not match with the given threshold2.choice");
+ }
+
+ if (((config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A1)
+ || (config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A2)
+ || (config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A4)
+ || (config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A5))
+ && (config.threshold1.choice != NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRP))
+ {
+ NS_FATAL_ERROR ("The given triggerQuantity (RSRP) does not match with the given threshold1.choice");
+ }
+ break;
+
+ case NistLteRrcSap::NistReportConfigEutra::RSRQ:
+ if ((config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A5)
+ && (config.threshold2.choice != NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ))
+ {
+ NS_FATAL_ERROR ("The given triggerQuantity (RSRQ) does not match with the given threshold2.choice");
+ }
+
+ if (((config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A1)
+ || (config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A2)
+ || (config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A4)
+ || (config.eventId == NistLteRrcSap::NistReportConfigEutra::EVENT_A5))
+ && (config.threshold1.choice != NistLteRrcSap::NistThresholdEutra::THRESHOLD_RSRQ))
+ {
+ NS_FATAL_ERROR ("The given triggerQuantity (RSRQ) does not match with the given threshold1.choice");
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unsupported triggerQuantity");
+ break;
+ }
+
+ if (config.purpose != NistLteRrcSap::NistReportConfigEutra::REPORT_STRONGEST_CELLS)
+ {
+ NS_FATAL_ERROR ("Only REPORT_STRONGEST_CELLS purpose is supported");
+ }
+
+ if (config.reportQuantity != NistLteRrcSap::NistReportConfigEutra::BOTH)
+ {
+ NS_LOG_WARN ("reportQuantity = BOTH will be used instead of the given reportQuantity");
+ }
+
+ uint8_t nextId = m_ueNistMeasConfig.reportConfigToAddModList.size () + 1;
+
+ // create the reporting configuration
+ NistLteRrcSap::NistReportConfigToAddMod reportConfig;
+ reportConfig.reportConfigId = nextId;
+ reportConfig.reportConfigEutra = config;
+
+ // create the measurement identity
+ NistLteRrcSap::NistMeasIdToAddMod measId;
+ measId.measId = nextId;
+ measId.measObjectId = 1;
+ measId.reportConfigId = nextId;
+
+ // add both to the list of UE measurement configuration
+ m_ueNistMeasConfig.reportConfigToAddModList.push_back (reportConfig);
+ m_ueNistMeasConfig.measIdToAddModList.push_back (measId);
+
+ return nextId;
+}
+
+void
+NistLteEnbRrc::ConfigureCell (uint8_t ulBandwidth, uint8_t dlBandwidth,
+ uint16_t ulEarfcn, uint16_t dlEarfcn, uint16_t cellId)
+{
+ NS_LOG_FUNCTION (this << (uint16_t) ulBandwidth << (uint16_t) dlBandwidth
+ << ulEarfcn << dlEarfcn << cellId);
+ NS_ASSERT (!m_configured);
+ m_cmacSapProvider->ConfigureMac (ulBandwidth, dlBandwidth);
+ m_cphySapProvider->SetBandwidth (ulBandwidth, dlBandwidth);
+ m_cphySapProvider->SetEarfcn (ulEarfcn, dlEarfcn);
+ m_dlEarfcn = dlEarfcn;
+ m_ulEarfcn = ulEarfcn;
+ m_dlBandwidth = dlBandwidth;
+ m_ulBandwidth = ulBandwidth;
+ m_cellId = cellId;
+ m_cphySapProvider->SetCellId (cellId);
+ m_ffrRrcSapProvider->SetCellId (cellId);
+ m_ffrRrcSapProvider->SetBandwidth(ulBandwidth, dlBandwidth);
+
+ /*
+ * Initializing the list of UE measurement configuration (m_ueNistMeasConfig).
+ * Only intra-frequency measurements are supported, so only one measurement
+ * object is created.
+ */
+
+ NistLteRrcSap::NistMeasObjectToAddMod measObject;
+ measObject.measObjectId = 1;
+ measObject.measObjectEutra.carrierFreq = m_dlEarfcn;
+ measObject.measObjectEutra.allowedMeasBandwidth = m_dlBandwidth;
+ measObject.measObjectEutra.presenceAntennaPort1 = false;
+ measObject.measObjectEutra.neighCellConfig = 0;
+ measObject.measObjectEutra.offsetFreq = 0;
+ measObject.measObjectEutra.haveCellForWhichToReportCGI = false;
+
+ m_ueNistMeasConfig.measObjectToAddModList.push_back (measObject);
+ m_ueNistMeasConfig.haveNistQuantityConfig = true;
+ m_ueNistMeasConfig.quantityConfig.filterCoefficientRSRP = m_rsrpFilterCoefficient;
+ m_ueNistMeasConfig.quantityConfig.filterCoefficientRSRQ = m_rsrqFilterCoefficient;
+ m_ueNistMeasConfig.haveNistMeasGapConfig = false;
+ m_ueNistMeasConfig.haveSmeasure = false;
+ m_ueNistMeasConfig.haveNistSpeedStatePars = false;
+
+ // Enabling MIB transmission
+ NistLteRrcSap::NistMasterInformationBlock mib;
+ mib.dlBandwidth = m_dlBandwidth;
+ m_cphySapProvider->SetNistMasterInformationBlock (mib);
+
+ // Enabling SIB1 transmission with default values
+ m_sib1.cellAccessRelatedInfo.cellIdentity = cellId;
+ m_sib1.cellAccessRelatedInfo.csgIndication = false;
+ m_sib1.cellAccessRelatedInfo.csgIdentity = 0;
+ m_sib1.cellAccessRelatedInfo.plmnIdentityInfo.plmnIdentity = 0; // not used
+ m_sib1.cellSelectionInfo.qQualMin = -34; // not used, set as minimum value
+ m_sib1.cellSelectionInfo.qRxLevMin = m_qRxLevMin; // set as minimum value
+ m_cphySapProvider->SetNistSystemInformationBlockType1 (m_sib1);
+
+ /*
+ * Enabling transmission of other SIB. The first time System Information is
+ * transmitted is arbitrarily assumed to be at +0.016s, and then it will be
+ * regularly transmitted every 80 ms by default (set the
+ * NistSystemInformationPeriodicity attribute to configure this).
+ */
+ Simulator::Schedule (MilliSeconds (16), &NistLteEnbRrc::SendNistSystemInformation, this);
+
+ m_configured = true;
+
+}
+
+
+void
+NistLteEnbRrc::SetCellId (uint16_t cellId)
+{
+ m_cellId = cellId;
+
+ // update SIB1 too
+ m_sib1.cellAccessRelatedInfo.cellIdentity = cellId;
+ m_cphySapProvider->SetNistSystemInformationBlockType1 (m_sib1);
+}
+
+bool
+NistLteEnbRrc::SendData (Ptr<Packet> packet)
+{
+ NS_LOG_FUNCTION (this << packet);
+
+ NistEpsBearerTag tag;
+ bool found = packet->RemovePacketTag (tag);
+ NS_ASSERT_MSG (found, "no NistEpsBearerTag found in packet to be sent");
+ Ptr<NistUeManager> ueManager = GetNistUeManager (tag.GetRnti ());
+ ueManager->SendData (tag.GetBid (), packet);
+
+ return true;
+}
+
+void
+NistLteEnbRrc::SetForwardUpCallback (Callback <void, Ptr<Packet> > cb)
+{
+ m_forwardUpCallback = cb;
+}
+
+void
+NistLteEnbRrc::ConnectionRequestTimeout (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ NS_ASSERT_MSG (GetNistUeManager (rnti)->GetState () == NistUeManager::INITIAL_RANDOM_ACCESS,
+ "ConnectionRequestTimeout in unexpected state " << ToString (GetNistUeManager (rnti)->GetState ()));
+ RemoveUe (rnti);
+}
+
+void
+NistLteEnbRrc::ConnectionSetupTimeout (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ NS_ASSERT_MSG (GetNistUeManager (rnti)->GetState () == NistUeManager::CONNECTION_SETUP,
+ "ConnectionSetupTimeout in unexpected state " << ToString (GetNistUeManager (rnti)->GetState ()));
+ RemoveUe (rnti);
+}
+
+void
+NistLteEnbRrc::ConnectionRejectedTimeout (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ NS_ASSERT_MSG (GetNistUeManager (rnti)->GetState () == NistUeManager::CONNECTION_REJECTED,
+ "ConnectionRejectedTimeout in unexpected state " << ToString (GetNistUeManager (rnti)->GetState ()));
+ RemoveUe (rnti);
+}
+
+void
+NistLteEnbRrc::HandoverJoiningTimeout (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ NS_ASSERT_MSG (GetNistUeManager (rnti)->GetState () == NistUeManager::HANDOVER_JOINING,
+ "HandoverJoiningTimeout in unexpected state " << ToString (GetNistUeManager (rnti)->GetState ()));
+ RemoveUe (rnti);
+}
+
+void
+NistLteEnbRrc::HandoverLeavingTimeout (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ NS_ASSERT_MSG (GetNistUeManager (rnti)->GetState () == NistUeManager::HANDOVER_LEAVING,
+ "HandoverLeavingTimeout in unexpected state " << ToString (GetNistUeManager (rnti)->GetState ()));
+ RemoveUe (rnti);
+}
+
+void
+NistLteEnbRrc::SendHandoverRequest (uint16_t rnti, uint16_t cellId)
+{
+ NS_LOG_FUNCTION (this << rnti << cellId);
+ NS_LOG_LOGIC ("Request to send HANDOVER REQUEST");
+ NS_ASSERT (m_configured);
+
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ ueManager->PrepareHandover (cellId);
+
+}
+
+void
+NistLteEnbRrc::DoCompleteSetupUe (uint16_t rnti, NistLteEnbRrcSapProvider::CompleteNistSetupUeParameters params)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetNistUeManager (rnti)->CompleteSetupUe (params);
+}
+
+void
+NistLteEnbRrc::DoRecvNistRrcConnectionRequest (uint16_t rnti, NistLteRrcSap::NistRrcConnectionRequest msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetNistUeManager (rnti)->RecvNistRrcConnectionRequest (msg);
+}
+
+void
+NistLteEnbRrc::DoRecvNistRrcConnectionSetupCompleted (uint16_t rnti, NistLteRrcSap::NistRrcConnectionSetupCompleted msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetNistUeManager (rnti)->RecvNistRrcConnectionSetupCompleted (msg);
+}
+
+void
+NistLteEnbRrc::DoRecvNistRrcConnectionReconfigurationCompleted (uint16_t rnti, NistLteRrcSap::NistRrcConnectionReconfigurationCompleted msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetNistUeManager (rnti)->RecvNistRrcConnectionReconfigurationCompleted (msg);
+}
+
+void
+NistLteEnbRrc::DoRecvNistRrcConnectionReestablishmentRequest (uint16_t rnti, NistLteRrcSap::NistRrcConnectionReestablishmentRequest msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetNistUeManager (rnti)->RecvNistRrcConnectionReestablishmentRequest (msg);
+}
+
+void
+NistLteEnbRrc::DoRecvNistRrcConnectionReestablishmentComplete (uint16_t rnti, NistLteRrcSap::NistRrcConnectionReestablishmentComplete msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetNistUeManager (rnti)->RecvNistRrcConnectionReestablishmentComplete (msg);
+}
+
+void
+NistLteEnbRrc::DoRecvNistMeasurementReport (uint16_t rnti, NistLteRrcSap::NistMeasurementReport msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetNistUeManager (rnti)->RecvNistMeasurementReport (msg);
+}
+
+void
+NistLteEnbRrc::DoRecvSidelinkUeInformation (uint16_t rnti, NistLteRrcSap::SidelinkUeInformation msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ //TODO
+ GetNistUeManager (rnti)->RecvSidelinkUeInformation (msg);
+}
+
+
+void
+NistLteEnbRrc::DoDataRadioBearerSetupRequest (NistEpcEnbS1SapUser::NistDataRadioBearerSetupRequestParameters request)
+{
+ Ptr<NistUeManager> ueManager = GetNistUeManager (request.rnti);
+ ueManager->SetupDataRadioBearer (request.bearer, request.bearerId, request.gtpTeid, request.transportLayerAddress);
+}
+
+void
+NistLteEnbRrc::DoPathSwitchRequestAcknowledge (NistEpcEnbS1SapUser::NistPathSwitchRequestAcknowledgeParameters params)
+{
+ Ptr<NistUeManager> ueManager = GetNistUeManager (params.rnti);
+ ueManager->SendUeContextRelease ();
+}
+
+void
+NistLteEnbRrc::DoRecvHandoverRequest (NistEpcX2SapUser::NistHandoverRequestParams req)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << req.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << req.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << req.targetCellId);
+ NS_LOG_LOGIC ("mmeUeS1apId = " << req.mmeUeS1apId);
+
+ NS_ASSERT (req.targetCellId == m_cellId);
+
+ if (m_admitHandoverRequest == false)
+ {
+ NS_LOG_INFO ("rejecting handover request from cellId " << req.sourceCellId);
+ NistEpcX2Sap::NistHandoverPreparationFailureParams res;
+ res.oldEnbUeX2apId = req.oldEnbUeX2apId;
+ res.sourceCellId = req.sourceCellId;
+ res.targetCellId = req.targetCellId;
+ res.cause = 0;
+ res.criticalityDiagnostics = 0;
+ m_x2SapProvider->SendHandoverPreparationFailure (res);
+ return;
+ }
+
+ uint16_t rnti = AddUe (NistUeManager::HANDOVER_JOINING);
+ NistLteEnbCmacSapProvider::NistAllocateNcRaPreambleReturnValue anrcrv = m_cmacSapProvider->AllocateNcRaPreamble (rnti);
+ if (anrcrv.valid == false)
+ {
+ NS_LOG_INFO (this << " failed to allocate a preamble for non-contention based RA => cannot accept HO");
+ RemoveUe (rnti);
+ NS_FATAL_ERROR ("should trigger HO Preparation Failure, but it is not implemented");
+ return;
+ }
+
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ ueManager->SetSource (req.sourceCellId, req.oldEnbUeX2apId);
+ ueManager->SetImsi (req.mmeUeS1apId);
+
+ NistEpcX2SapProvider::NistHandoverRequestAckParams ackParams;
+ ackParams.oldEnbUeX2apId = req.oldEnbUeX2apId;
+ ackParams.newEnbUeX2apId = rnti;
+ ackParams.sourceCellId = req.sourceCellId;
+ ackParams.targetCellId = req.targetCellId;
+
+ for (std::vector <NistEpcX2Sap::NistErabToBeSetupItem>::iterator it = req.bearers.begin ();
+ it != req.bearers.end ();
+ ++it)
+ {
+ ueManager->SetupDataRadioBearer (it->erabLevelQosParameters, it->erabId, it->gtpTeid, it->transportLayerAddress);
+ NistEpcX2Sap::NistErabAdmittedItem i;
+ i.erabId = it->erabId;
+ ackParams.admittedBearers.push_back (i);
+ }
+
+ NistLteRrcSap::NistRrcConnectionReconfiguration handoverCommand = ueManager->GetNistRrcConnectionReconfigurationForHandover ();
+ handoverCommand.haveNistMobilityControlInfo = true;
+ handoverCommand.mobilityControlInfo.targetPhysCellId = m_cellId;
+ handoverCommand.mobilityControlInfo.haveCarrierFreq = true;
+ handoverCommand.mobilityControlInfo.carrierFreq.dlCarrierFreq = m_dlEarfcn;
+ handoverCommand.mobilityControlInfo.carrierFreq.ulCarrierFreq = m_ulEarfcn;
+ handoverCommand.mobilityControlInfo.haveCarrierBandwidth = true;
+ handoverCommand.mobilityControlInfo.carrierBandwidth.dlBandwidth = m_dlBandwidth;
+ handoverCommand.mobilityControlInfo.carrierBandwidth.ulBandwidth = m_ulBandwidth;
+ handoverCommand.mobilityControlInfo.newUeIdentity = rnti;
+ handoverCommand.mobilityControlInfo.haveNistRachConfigDedicated = true;
+ handoverCommand.mobilityControlInfo.rachConfigDedicated.raPreambleIndex = anrcrv.raPreambleId;
+ handoverCommand.mobilityControlInfo.rachConfigDedicated.raPrachMaskIndex = anrcrv.raPrachMaskIndex;
+
+ NistLteEnbCmacSapProvider::NistRachConfig rc = m_cmacSapProvider->GetNistRachConfig ();
+ handoverCommand.mobilityControlInfo.radioResourceConfigCommon.rachConfigCommon.preambleInfo.numberOfRaPreambles = rc.numberOfRaPreambles;
+ handoverCommand.mobilityControlInfo.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.preambleTransMax = rc.preambleTransMax;
+ handoverCommand.mobilityControlInfo.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.raResponseWindowSize = rc.raResponseWindowSize;
+
+ Ptr<Packet> encodedHandoverCommand = m_rrcSapUser->EncodeHandoverCommand (handoverCommand);
+
+ ackParams.rrcContext = encodedHandoverCommand;
+
+ NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << ackParams.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << ackParams.newEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << ackParams.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << ackParams.targetCellId);
+
+ m_x2SapProvider->SendHandoverRequestAck (ackParams);
+}
+
+void
+NistLteEnbRrc::DoRecvHandoverRequestAck (NistEpcX2SapUser::NistHandoverRequestAckParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+
+ uint16_t rnti = params.oldEnbUeX2apId;
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ ueManager->RecvHandoverRequestAck (params);
+}
+
+void
+NistLteEnbRrc::DoRecvHandoverPreparationFailure (NistEpcX2SapUser::NistHandoverPreparationFailureParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: HANDOVER PREPARATION FAILURE");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+ NS_LOG_LOGIC ("cause = " << params.cause);
+ NS_LOG_LOGIC ("criticalityDiagnostics = " << params.criticalityDiagnostics);
+
+ uint16_t rnti = params.oldEnbUeX2apId;
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ ueManager->RecvHandoverPreparationFailure (params.targetCellId);
+}
+
+void
+NistLteEnbRrc::DoRecvSnNistStatusTransfer (NistEpcX2SapUser::NistSnNistStatusTransferParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: SN STATUS TRANSFER");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
+ NS_LOG_LOGIC ("erabsSubjectToNistStatusTransferList size = " << params.erabsSubjectToNistStatusTransferList.size ());
+
+ uint16_t rnti = params.newEnbUeX2apId;
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ ueManager->RecvSnNistStatusTransfer (params);
+}
+
+void
+NistLteEnbRrc::DoRecvUeContextRelease (NistEpcX2SapUser::NistUeContextReleaseParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: UE CONTEXT RELEASE");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
+
+ uint16_t rnti = params.oldEnbUeX2apId;
+ GetNistUeManager (rnti)->RecvUeContextRelease (params);
+ RemoveUe (rnti);
+}
+
+void
+NistLteEnbRrc::DoRecvLoadInformation (NistEpcX2SapUser::NistLoadInformationParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: LOAD INFORMATION");
+
+ NS_LOG_LOGIC ("Number of cellInformationItems = " << params.cellInformationList.size ());
+
+ m_ffrRrcSapProvider->RecvLoadInformation(params);
+}
+
+void
+NistLteEnbRrc::DoRecvResourceNistStatusUpdate (NistEpcX2SapUser::NistResourceNistStatusUpdateParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: RESOURCE STATUS UPDATE");
+
+ NS_LOG_LOGIC ("Number of cellMeasurementResultItems = " << params.cellMeasurementResultList.size ());
+
+ NS_ASSERT ("Processing of RESOURCE STATUS UPDATE X2 message IS NOT IMPLEMENTED");
+}
+
+void
+NistLteEnbRrc::DoRecvUeData (NistEpcX2SapUser::NistUeDataParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv UE DATA FORWARDING through X2 interface");
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+ NS_LOG_LOGIC ("gtpTeid = " << params.gtpTeid);
+ NS_LOG_LOGIC ("ueData = " << params.ueData);
+ NS_LOG_LOGIC ("ueData size = " << params.ueData->GetSize ());
+
+ std::map<uint32_t, NistX2uTeidInfo>::iterator
+ teidInfoIt = m_x2uTeidInfoMap.find (params.gtpTeid);
+ if (teidInfoIt != m_x2uTeidInfoMap.end ())
+ {
+ GetNistUeManager (teidInfoIt->second.rnti)->SendData (teidInfoIt->second.drbid, params.ueData);
+ }
+ else
+ {
+ NS_FATAL_ERROR ("X2-U data received but no NistX2uTeidInfo found");
+ }
+}
+
+
+uint16_t
+NistLteEnbRrc::DoAllocateTemporaryCellRnti ()
+{
+ NS_LOG_FUNCTION (this);
+ return AddUe (NistUeManager::INITIAL_RANDOM_ACCESS);
+}
+
+void
+NistLteEnbRrc::DoRrcConfigurationUpdateInd (NistLteEnbCmacSapUser::NistUeConfig cmacParams)
+{
+ Ptr<NistUeManager> ueManager = GetNistUeManager (cmacParams.m_rnti);
+ ueManager->CmacNistUeConfigUpdateInd (cmacParams);
+}
+
+void
+NistLteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) rnti);
+ NS_FATAL_ERROR ("not implemented");
+}
+
+
+uint8_t
+NistLteEnbRrc::DoAddUeMeasReportConfigForHandover (NistLteRrcSap::NistReportConfigEutra reportConfig)
+{
+ NS_LOG_FUNCTION (this);
+ uint8_t measId = AddUeMeasReportConfig (reportConfig);
+ m_handoverMeasIds.insert (measId);
+ return measId;
+}
+
+void
+NistLteEnbRrc::DoTriggerHandover (uint16_t rnti, uint16_t targetCellId)
+{
+ NS_LOG_FUNCTION (this << rnti << targetCellId);
+
+ bool isHandoverAllowed = true;
+
+ if (m_anrSapProvider != 0)
+ {
+ // ensure that proper neighbour relationship exists between source and target cells
+ bool noHo = m_anrSapProvider->GetNoHo (targetCellId);
+ bool noX2 = m_anrSapProvider->GetNoX2 (targetCellId);
+ NS_LOG_DEBUG (this << " cellId=" << m_cellId
+ << " targetCellId=" << targetCellId
+ << " NRT.NoHo=" << noHo << " NRT.NoX2=" << noX2);
+
+ if (noHo || noX2)
+ {
+ isHandoverAllowed = false;
+ NS_LOG_LOGIC (this << " handover to cell " << targetCellId
+ << " is not allowed by ANR");
+ }
+ }
+
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ NS_ASSERT_MSG (ueManager != 0, "Cannot find UE context with RNTI " << rnti);
+
+ if (ueManager->GetState () != NistUeManager::CONNECTED_NORMALLY)
+ {
+ isHandoverAllowed = false;
+ NS_LOG_LOGIC (this << " handover is not allowed because the UE"
+ << " rnti=" << rnti << " is in "
+ << ToString (ueManager->GetState ()) << " state");
+ }
+
+ if (isHandoverAllowed)
+ {
+ // initiate handover execution
+ ueManager->PrepareHandover (targetCellId);
+ }
+}
+
+uint8_t
+NistLteEnbRrc::DoAddUeMeasReportConfigForAnr (NistLteRrcSap::NistReportConfigEutra reportConfig)
+{
+ NS_LOG_FUNCTION (this);
+ uint8_t measId = AddUeMeasReportConfig (reportConfig);
+ m_anrMeasIds.insert (measId);
+ return measId;
+}
+
+uint8_t
+NistLteEnbRrc::DoAddUeMeasReportConfigForFfr (NistLteRrcSap::NistReportConfigEutra reportConfig)
+{
+ NS_LOG_FUNCTION (this);
+ uint8_t measId = AddUeMeasReportConfig (reportConfig);
+ m_ffrMeasIds.insert (measId);
+ return measId;
+}
+
+void
+NistLteEnbRrc::DoSetNistPdschConfigDedicated (uint16_t rnti, NistLteRrcSap::NistPdschConfigDedicated pdschConfigDedicated)
+{
+ NS_LOG_FUNCTION (this);
+ Ptr<NistUeManager> ueManager = GetNistUeManager (rnti);
+ ueManager->SetNistPdschConfigDedicated (pdschConfigDedicated);
+}
+
+void
+NistLteEnbRrc::DoSendLoadInformation (NistEpcX2Sap::NistLoadInformationParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ m_x2SapProvider->SendLoadInformation(params);
+}
+
+uint16_t
+NistLteEnbRrc::AddUe (NistUeManager::State state)
+{
+ NS_LOG_FUNCTION (this);
+ bool found = false;
+ uint16_t rnti;
+ for (rnti = m_lastAllocatedRnti + 1;
+ (rnti != m_lastAllocatedRnti - 1) && (!found);
+ ++rnti)
+ {
+ if ((rnti != 0) && (m_ueMap.find (rnti) == m_ueMap.end ()))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ NS_ASSERT_MSG (found, "no more RNTIs available (do you have more than 65535 UEs in a cell?)");
+ m_lastAllocatedRnti = rnti;
+ Ptr<NistUeManager> ueManager = CreateObject<NistUeManager> (this, rnti, state);
+ m_ueMap.insert (std::pair<uint16_t, Ptr<NistUeManager> > (rnti, ueManager));
+ ueManager->Initialize ();
+ NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueManager->GetSrsConfigurationIndex ());
+ m_newUeContextTrace (m_cellId, rnti);
+ return rnti;
+}
+
+void
+NistLteEnbRrc::RemoveUe (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) rnti);
+ std::map <uint16_t, Ptr<NistUeManager> >::iterator it = m_ueMap.find (rnti);
+ NS_ASSERT_MSG (it != m_ueMap.end (), "request to remove UE info with unknown rnti " << rnti);
+ uint16_t srsCi = (*it).second->GetSrsConfigurationIndex ();
+ m_ueMap.erase (it);
+ m_cmacSapProvider->RemoveUe (rnti);
+ m_cphySapProvider->RemoveUe (rnti);
+ if (m_s1SapProvider != 0)
+ {
+ m_s1SapProvider->UeContextRelease (rnti);
+ }
+ // need to do this after NistUeManager has been deleted
+ RemoveSrsConfigurationIndex (srsCi);
+}
+
+TypeId
+NistLteEnbRrc::GetRlcType (NistEpsBearer bearer)
+{
+ switch (m_epsBearerToRlcMapping)
+ {
+ case RLC_SM_ALWAYS:
+ return NistLteRlcSm::GetTypeId ();
+ break;
+
+ case RLC_UM_ALWAYS:
+ return NistLteRlcUm::GetTypeId ();
+ break;
+
+ case RLC_AM_ALWAYS:
+ return NistLteRlcAm::GetTypeId ();
+ break;
+
+ case PER_BASED:
+ if (bearer.GetPacketErrorLossRate () > 1.0e-5)
+ {
+ return NistLteRlcUm::GetTypeId ();
+ }
+ else
+ {
+ return NistLteRlcAm::GetTypeId ();
+ }
+ break;
+
+ default:
+ return NistLteRlcSm::GetTypeId ();
+ break;
+ }
+}
+
+
+void
+NistLteEnbRrc::AddX2Neighbour (uint16_t cellId)
+{
+ NS_LOG_FUNCTION (this << cellId);
+
+ if (m_anrSapProvider != 0)
+ {
+ m_anrSapProvider->AddNeighbourRelation (cellId);
+ }
+}
+
+void
+NistLteEnbRrc::SetCsgId (uint32_t csgId, bool csgIndication)
+{
+ NS_LOG_FUNCTION (this << csgId << csgIndication);
+ m_sib1.cellAccessRelatedInfo.csgIdentity = csgId;
+ m_sib1.cellAccessRelatedInfo.csgIndication = csgIndication;
+ m_cphySapProvider->SetNistSystemInformationBlockType1 (m_sib1);
+}
+
+
+/// Number of distinct SRS periodicity plus one.
+static const uint8_t SRS_ENTRIES = 9;
+/**
+ * Sounding Reference Symbol (SRS) periodicity (TSRS) in milliseconds. Taken
+ * from 3GPP TS 36.213 Table 8.2-1. Index starts from 1.
+ */
+static const uint16_t g_srsPeriodicity[SRS_ENTRIES] = {0, 2, 5, 10, 20, 40, 80, 160, 320};
+/**
+ * The lower bound (inclusive) of the SRS configuration indices (ISRS) which
+ * use the corresponding SRS periodicity (TSRS). Taken from 3GPP TS 36.213
+ * Table 8.2-1. Index starts from 1.
+ */
+static const uint16_t g_srsCiLow[SRS_ENTRIES] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
+/**
+ * The upper bound (inclusive) of the SRS configuration indices (ISRS) which
+ * use the corresponding SRS periodicity (TSRS). Taken from 3GPP TS 36.213
+ * Table 8.2-1. Index starts from 1.
+ */
+static const uint16_t g_srsCiHigh[SRS_ENTRIES] = {0, 1, 6, 16, 36, 76, 156, 316, 636};
+
+void
+NistLteEnbRrc::SetSrsPeriodicity (uint32_t p)
+{
+ NS_LOG_FUNCTION (this << p);
+ for (uint32_t id = 1; id < SRS_ENTRIES; ++id)
+ {
+ if (g_srsPeriodicity[id] == p)
+ {
+ m_srsCurrentPeriodicityId = id;
+ return;
+ }
+ }
+ // no match found
+ std::ostringstream allowedValues;
+ for (uint32_t id = 1; id < SRS_ENTRIES; ++id)
+ {
+ allowedValues << g_srsPeriodicity[id] << " ";
+ }
+ NS_FATAL_ERROR ("illecit SRS periodicity value " << p << ". Allowed values: " << allowedValues.str ());
+}
+
+uint32_t
+NistLteEnbRrc::GetSrsPeriodicity () const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_srsCurrentPeriodicityId > 0);
+ NS_ASSERT (m_srsCurrentPeriodicityId < SRS_ENTRIES);
+ return g_srsPeriodicity[m_srsCurrentPeriodicityId];
+}
+
+
+uint16_t
+NistLteEnbRrc::GetNewSrsConfigurationIndex ()
+{
+ NS_LOG_FUNCTION (this << m_ueSrsConfigurationIndexSet.size ());
+ // SRS
+ NS_ASSERT (m_srsCurrentPeriodicityId > 0);
+ NS_ASSERT (m_srsCurrentPeriodicityId < SRS_ENTRIES);
+ NS_LOG_DEBUG (this << " SRS p " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " set " << m_ueSrsConfigurationIndexSet.size ());
+ if (m_ueSrsConfigurationIndexSet.size () >= g_srsPeriodicity[m_srsCurrentPeriodicityId])
+ {
+ NS_FATAL_ERROR ("too many UEs (" << m_ueSrsConfigurationIndexSet.size () + 1
+ << ") for current SRS periodicity "
+ << g_srsPeriodicity[m_srsCurrentPeriodicityId]
+ << ", consider increasing the value of ns3::NistLteEnbRrc::SrsPeriodicity");
+ }
+
+ if (m_ueSrsConfigurationIndexSet.empty ())
+ {
+ // first entry
+ m_lastAllocatedConfigurationIndex = g_srsCiLow[m_srsCurrentPeriodicityId];
+ m_ueSrsConfigurationIndexSet.insert (m_lastAllocatedConfigurationIndex);
+ }
+ else
+ {
+ // find a CI from the available ones
+ std::set<uint16_t>::reverse_iterator rit = m_ueSrsConfigurationIndexSet.rbegin ();
+ NS_ASSERT (rit != m_ueSrsConfigurationIndexSet.rend ());
+ NS_LOG_DEBUG (this << " lower bound " << (*rit) << " of " << g_srsCiHigh[m_srsCurrentPeriodicityId]);
+ if ((*rit) < g_srsCiHigh[m_srsCurrentPeriodicityId])
+ {
+ // got it from the upper bound
+ m_lastAllocatedConfigurationIndex = (*rit) + 1;
+ m_ueSrsConfigurationIndexSet.insert (m_lastAllocatedConfigurationIndex);
+ }
+ else
+ {
+ // look for released ones
+ 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 ())
+ {
+ m_lastAllocatedConfigurationIndex = srcCi;
+ m_ueSrsConfigurationIndexSet.insert (srcCi);
+ break;
+ }
+ }
+ }
+ }
+ return m_lastAllocatedConfigurationIndex;
+
+}
+
+
+void
+NistLteEnbRrc::RemoveSrsConfigurationIndex (uint16_t srcCi)
+{
+ NS_LOG_FUNCTION (this << srcCi);
+ std::set<uint16_t>::iterator it = m_ueSrsConfigurationIndexSet.find (srcCi);
+ NS_ASSERT_MSG (it != m_ueSrsConfigurationIndexSet.end (), "request to remove unkwown SRS CI " << srcCi);
+ m_ueSrsConfigurationIndexSet.erase (it);
+}
+
+uint8_t
+NistLteEnbRrc::GetLogicalChannelGroup (NistEpsBearer bearer)
+{
+ if (bearer.IsGbr ())
+ {
+ return 1;
+ }
+ else
+ {
+ return 2;
+ }
+}
+
+uint8_t
+NistLteEnbRrc::GetLogicalChannelPriority (NistEpsBearer bearer)
+{
+ return bearer.qci;
+}
+
+void
+NistLteEnbRrc::SendNistSystemInformation ()
+{
+ // NS_LOG_FUNCTION (this);
+
+ /*
+ * For simplicity, we use the same periodicity for all SIBs. Note that in real
+ * systems the periodicy of each SIBs could be different.
+ */
+ NistLteRrcSap::NistSystemInformation si;
+ si.haveSib2 = true;
+ si.sib2.freqInfo.ulCarrierFreq = m_ulEarfcn;
+ si.sib2.freqInfo.ulBandwidth = m_ulBandwidth;
+ si.sib2.radioResourceConfigCommon.pdschConfigCommon.referenceSignalPower = m_cphySapProvider->GetReferenceSignalPower();
+ si.sib2.radioResourceConfigCommon.pdschConfigCommon.pb = 0;
+
+ NistLteEnbCmacSapProvider::NistRachConfig rc = m_cmacSapProvider->GetNistRachConfig ();
+ NistLteRrcSap::NistRachConfigCommon rachConfigCommon;
+ rachConfigCommon.preambleInfo.numberOfRaPreambles = rc.numberOfRaPreambles;
+ rachConfigCommon.raSupervisionInfo.preambleTransMax = rc.preambleTransMax;
+ rachConfigCommon.raSupervisionInfo.raResponseWindowSize = rc.raResponseWindowSize;
+ si.sib2.radioResourceConfigCommon.rachConfigCommon = rachConfigCommon;
+
+ /*
+ * Send information for SIB 18
+ */
+ if (m_sidelinkConfiguration && m_sidelinkConfiguration->IsSlEnabled()) {
+ si.haveSib18 = true;
+ si.sib18 = m_sidelinkConfiguration->GetSystemInformationType18();
+ } else {
+ si.haveSib18 = false;
+ }
+
+ m_rrcSapUser->SendNistSystemInformation (si);
+ Simulator::Schedule (m_systemInformationPeriodicity, &NistLteEnbRrc::SendNistSystemInformation, this);
+}
+
+
+} // namespace ns3
+
« no previous file with comments | « src/nist/model/nist-lte-enb-rrc.h ('k') | src/nist/model/nist-lte-ffr-algorithm.h » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b