/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Nicola Baldo <nbaldo@cttc.es>
* Marco Miozzo <mmiozzo@cttc.es>
* Manuel Requena <manuel.requena@cttc.es>
*/
#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 "lte-enb-rrc.h"
#include "lte-enb-net-device.h"
#include "lte-radio-bearer-info.h"
#include "eps-bearer-tag.h"
#include "ff-mac-csched-sap.h"
#include "epc-enb-s1-sap.h"
#include "lte-rlc.h"
#include "lte-rlc-tm.h"
#include "lte-rlc-um.h"
#include "lte-rlc-am.h"
#include "lte-pdcp.h"
#include "lte-pdcp-sap.h"
#include <ns3/simulator.h>
NS_LOG_COMPONENT_DEFINE ("LteEnbRrc");
namespace ns3 {
// ///////////////////////////
// CMAC SAP forwarder
// ///////////////////////////
class EnbRrcMemberLteEnbCmacSapUser : public LteEnbCmacSapUser
{
public:
EnbRrcMemberLteEnbCmacSapUser (LteEnbRrc* rrc);
virtual uint16_t AllocateTemporaryCellRnti ();
virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
virtual void RrcConfigurationUpdateInd (UeConfig params);
private:
LteEnbRrc* m_rrc;
};
EnbRrcMemberLteEnbCmacSapUser::EnbRrcMemberLteEnbCmacSapUser (LteEnbRrc* rrc)
: m_rrc (rrc)
{
}
uint16_t
EnbRrcMemberLteEnbCmacSapUser::AllocateTemporaryCellRnti ()
{
return m_rrc->DoAllocateTemporaryCellRnti ();
}
void
EnbRrcMemberLteEnbCmacSapUser::NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
{
m_rrc->DoNotifyLcConfigResult (rnti, lcid, success);
}
void
EnbRrcMemberLteEnbCmacSapUser::RrcConfigurationUpdateInd (UeConfig params)
{
m_rrc->DoRrcConfigurationUpdateInd (params);
}
const char* g_ueManagerStateName[UeManager::NUM_STATES] =
{
"INITIAL_RANDOM_ACCESS",
"CONNECTION_SETUP",
"CONNECTED_NORMALLY",
"CONNECTION_RECONFIGURATION",
"CONNECTION_REESTABLISHMENT",
"HANDOVER_JOINING",
"HANDOVER_LEAVING",
};
std::string ToString (UeManager::State s)
{
return std::string (g_ueManagerStateName[s]);
}
///////////////////////////////////////////
// UeManager
///////////////////////////////////////////
NS_OBJECT_ENSURE_REGISTERED (UeManager);
UeManager::UeManager ()
{
NS_FATAL_ERROR ("this constructor is not espected to be used");
}
UeManager::UeManager (Ptr<LteEnbRrc> 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_pendingRrcConnectionReconfiguration (false),
m_sourceX2apId (0),
m_sourceCellId (0)
{
NS_LOG_FUNCTION (this);
m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<UeManager> (this);
m_physicalConfigDedicated.haveAntennaInfoDedicated = true;
m_physicalConfigDedicated.antennaInfo.transmissionMode = m_rrc->m_defaultTransmissionMode;
m_physicalConfigDedicated.haveSoundingRsUlConfigDedicated = true;
m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = m_rrc->GetNewSrsConfigurationIndex ();
m_rrc->m_cmacSapProvider->AddUe (rnti);
m_rrc->m_cphySapProvider->AddUe (rnti);
// setup the eNB side of SRB0
{
uint8_t lcid = 0;
Ptr<LteRlc> rlc = CreateObject<LteRlcTm> ()->GetObject<LteRlc> ();
rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
rlc->SetRnti (m_rnti);
rlc->SetLcId (lcid);
m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();
m_srb0->m_rlc = rlc;
m_srb0->m_srbIdentity = 1;
// no need to store logicalChannelConfig as SRB0 is pre-configured
LteEnbCmacSapProvider::LcInfo 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->GetLteMacSapUser ());
}
// setup the eNB side of SRB1; the UE side will be set up upon RRC connection establishment
{
uint8_t lcid = 1;
Ptr<LteRlc> rlc = CreateObject<LteRlcAm> ()->GetObject<LteRlc> ();
rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
rlc->SetRnti (m_rnti);
rlc->SetLcId (lcid);
Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
pdcp->SetRnti (m_rnti);
pdcp->SetLcId (lcid);
pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();
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;
LteEnbCmacSapProvider::LcInfo lcinfo;
lcinfo.rnti = m_rnti;
lcinfo.lcId = lcid;
lcinfo.lcGroup = 0; // all SRBs always mapped to LCG 0
lcinfo.qci = EpsBearer::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->GetLteMacSapUser ());
}
LteEnbRrcSapUser::SetupUeParameters ueParams;
ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider ();
ueParams.srb1SapProvider = m_srb1->m_pdcp->GetLtePdcpSapProvider ();
m_rrc->m_rrcSapUser->SetupUe (m_rnti, ueParams);
// configure MAC (and scheduler)
LteEnbCmacSapProvider::UeConfig req;
req.m_rnti = rnti;
req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
// configure PHY
m_rrc->m_cphySapProvider->SetTransmissionMode (rnti, m_physicalConfigDedicated.antennaInfo.transmissionMode);
m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (rnti, m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex);
}
UeManager::~UeManager (void)
{
}
void
UeManager::DoDispose ()
{
delete m_pdcpSapUser;
m_rrc->m_cmacSapProvider->RemoveUe (m_rnti);
m_rrc->m_cphySapProvider->RemoveUe (m_rnti);
}
TypeId UeManager::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::UeManager")
.SetParent<Object> ()
.AddConstructor<UeManager> ()
.AddAttribute ("DataRadioBearerMap", "List of UE RadioBearerInfo by DRBID.",
ObjectMapValue (),
MakeObjectMapAccessor (&UeManager::m_drbMap),
MakeObjectMapChecker<LteDataRadioBearerInfo> ())
.AddTraceSource ("StateTransition",
"fired upon every UE state transition seen by the UeManager at the eNB RRC",
MakeTraceSourceAccessor (&UeManager::m_stateTransitionCallback))
;
return tid;
}
void
UeManager::SetSource (uint16_t sourceCellId, uint16_t sourceX2apId)
{
m_sourceX2apId = sourceX2apId;
m_sourceCellId = sourceCellId;
}
uint8_t
UeManager::SetupDataRadioBearer (EpsBearer bearer, uint32_t gtpTeid, Ipv4Address transportLayerAddress)
{
NS_LOG_FUNCTION (this << (uint32_t) m_rnti);
Ptr<LteDataRadioBearerInfo> drbInfo = CreateObject<LteDataRadioBearerInfo> ();
uint8_t drbid = AddDataRadioBearerInfo (drbInfo);
uint8_t lcid = Drbid2Lcid (drbid);
uint8_t bid = Drbid2Bid (drbid);
drbInfo->m_epsBearerIdentity = bid;
drbInfo->m_drbIdentity = drbid;
drbInfo->m_logicalChannelIdentity = lcid;
drbInfo->m_gtpTeid = gtpTeid;
drbInfo->m_transportLayerAddress = transportLayerAddress;
TypeId rlcTypeId = m_rrc->GetRlcType (bearer);
ObjectFactory rlcObjectFactory;
rlcObjectFactory.SetTypeId (rlcTypeId);
Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
rlc->SetLteMacSapProvider (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 != LteRlcSm::GetTypeId ())
{
Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
pdcp->SetRnti (m_rnti);
pdcp->SetLcId (lcid);
pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
drbInfo->m_pdcp = pdcp;
}
LteEnbCmacSapProvider::LcInfo 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->GetLteMacSapUser ());
if (drbInfo->m_rlc->GetTypeId () == LteRlcAm::GetTypeId ())
{
drbInfo->m_rlcConfig.choice = LteRrcSap::RlcConfig::AM;
}
else
{
drbInfo->m_rlcConfig.choice = LteRrcSap::RlcConfig::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;
return drbid;
}
void
UeManager::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<LteDataRadioBearerInfo> >::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);
m_rrc->m_cmacSapProvider->ReleaseLc (m_rnti, lcid);
LteRrcSap::RadioResourceConfigDedicated rrcd;
rrcd.havePhysicalConfigDedicated = false;
rrcd.drbToReleaseList.push_back (drbid);
LteRrcSap::RrcConnectionReconfiguration msg;
msg.haveMeasConfig = false;
msg.haveMobilityControlInfo = false;
m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, msg);
}
void
UeManager::ScheduleRrcConnectionReconfiguration ()
{
NS_LOG_FUNCTION (this);
switch (m_state)
{
case INITIAL_RANDOM_ACCESS:
case CONNECTION_SETUP:
case CONNECTION_RECONFIGURATION:
case CONNECTION_REESTABLISHMENT:
case HANDOVER_JOINING:
case HANDOVER_LEAVING:
// a previous reconfiguration still ongoing, we need to wait for it to be finished
m_pendingRrcConnectionReconfiguration = true;
break;
case CONNECTED_NORMALLY:
{
m_pendingRrcConnectionReconfiguration = false;
LteRrcSap::RrcConnectionReconfiguration msg = BuildRrcConnectionReconfiguration ();
m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, msg);
SwitchToState (CONNECTION_RECONFIGURATION);
}
break;
default:
NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
break;
}
}
void
UeManager::SendHandoverCommand (LteRrcSap::RrcConnectionReconfiguration rcr)
{
NS_LOG_FUNCTION (this);
m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, rcr);
SwitchToState (HANDOVER_LEAVING);
}
LteRrcSap::RadioResourceConfigDedicated
UeManager::GetRadioResourceConfigForHandoverPreparationInfo ()
{
NS_LOG_FUNCTION (this);
return BuildRadioResourceConfigDedicated ();
}
LteRrcSap::RrcConnectionReconfiguration
UeManager::GetHandoverCommand ()
{
NS_LOG_FUNCTION (this);
return BuildRrcConnectionReconfiguration ();
}
void
UeManager::SendData (uint8_t bid, Ptr<Packet> p)
{
NS_LOG_FUNCTION (this << p << (uint16_t) bid);
LtePdcpSapProvider::TransmitPdcpSduParameters params;
params.pdcpSdu = p;
params.rnti = m_rnti;
params.lcid = Bid2Lcid (bid);
uint8_t drbid = Bid2Drbid (bid);
LtePdcpSapProvider* pdcpSapProvider = GetDataRadioBearerInfo (drbid)->m_pdcp->GetLtePdcpSapProvider ();
pdcpSapProvider->TransmitPdcpSdu (params);
}
std::vector<EpcX2Sap::ErabToBeSetupItem>
UeManager::GetErabList ()
{
NS_LOG_FUNCTION (this);
std::vector<EpcX2Sap::ErabToBeSetupItem> ret;
for (std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.begin ();
it != m_drbMap.end ();
++it)
{
EpcX2Sap::ErabToBeSetupItem 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
UeManager::CompleteSetupUe (LteEnbRrcSapProvider::CompleteSetupUeParameters params)
{
NS_LOG_FUNCTION (this);
m_srb0->m_rlc->SetLteRlcSapUser (params.srb0SapUser);
m_srb1->m_pdcp->SetLtePdcpSapUser (params.srb1SapUser);
}
void
UeManager::RecvRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg)
{
NS_LOG_FUNCTION (this);
switch (m_state)
{
case INITIAL_RANDOM_ACCESS:
{
m_imsi = msg.ueIdentity;
if (m_rrc->m_s1SapProvider != 0)
{
m_rrc->m_s1SapProvider->InitialUeMessage (m_imsi, m_rnti);
}
LteRrcSap::RrcConnectionSetup msg2;
msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
msg2.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
m_rrc->m_rrcSapUser->SendRrcConnectionSetup (m_rnti, msg2);
SwitchToState (CONNECTION_SETUP);
}
break;
default:
NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
break;
}
}
void
UeManager::RecvRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg)
{
NS_LOG_FUNCTION (this);
switch (m_state)
{
case CONNECTION_SETUP:
SwitchToState (CONNECTED_NORMALLY);
break;
default:
NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
break;
}
}
void
UeManager::RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg)
{
NS_LOG_FUNCTION (this);
switch (m_state)
{
case CONNECTION_RECONFIGURATION:
SwitchToState (CONNECTED_NORMALLY);
break;
case HANDOVER_JOINING:
NS_LOG_INFO ("Send UE CONTEXT RELEASE from target eNB to source eNB");
EpcX2SapProvider::UeContextReleaseParams ueCtxReleaseParams;
ueCtxReleaseParams.oldEnbUeX2apId = m_sourceX2apId;
ueCtxReleaseParams.newEnbUeX2apId = m_rnti;
m_rrc->m_x2SapProvider->SendUeContextRelease (ueCtxReleaseParams);
SwitchToState (CONNECTED_NORMALLY);
default:
NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
break;
}
}
void
UeManager::RecvRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg)
{
NS_LOG_FUNCTION (this);
LteRrcSap::RrcConnectionReestablishment msg2;
msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
msg2.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
m_rrc->m_rrcSapUser->SendRrcConnectionReestablishment (m_rnti, msg2);
SwitchToState (CONNECTION_REESTABLISHMENT);
}
void
UeManager::RecvRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg)
{
NS_LOG_FUNCTION (this);
SwitchToState (CONNECTED_NORMALLY);
}
void
UeManager::CmacUeConfigUpdateInd (LteEnbCmacSapUser::UeConfig 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;
// configure MAC (and scheduler)
LteEnbCmacSapProvider::UeConfig 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 (req.m_rnti, req.m_transmissionMode);
// reconfigure the UE RRC
ScheduleRrcConnectionReconfiguration ();
}
void
UeManager::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
{
NS_LOG_FUNCTION (this);
if (params.lcid > 2)
{
// data radio bearer
EpsBearerTag tag;
tag.SetRnti (params.rnti);
tag.SetBid (Lcid2Bid (params.lcid));
params.pdcpSdu->AddPacketTag (tag);
m_rrc->m_forwardUpCallback (params.pdcpSdu);
}
}
uint16_t
UeManager::GetRnti (void)
{
return m_rnti;
}
uint64_t
UeManager::GetImsi (void)
{
return m_imsi;
}
uint16_t
UeManager::GetSrsConfigurationIndex (void)
{
return m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex;
}
void
UeManager::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:
ScheduleRrcConnectionReconfiguration ();
break;
}
}
UeManager::State
UeManager::GetState (void)
{
return m_state;
}
uint8_t
UeManager::AddDataRadioBearerInfo (Ptr<LteDataRadioBearerInfo> drbInfo)
{
NS_LOG_FUNCTION (this);
const uint8_t MAX_DRB_ID = 32;
for (uint8_t 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<LteDataRadioBearerInfo> > (drbid, drbInfo));
drbInfo->m_drbIdentity = drbid;
m_lastAllocatedDrbid = drbid;
return drbid;
}
}
}
NS_FATAL_ERROR ("no more data radio bearer ids available");
return 0;
}
Ptr<LteDataRadioBearerInfo>
UeManager::GetDataRadioBearerInfo (uint8_t drbid)
{
NS_LOG_FUNCTION (this << (uint32_t) drbid);
NS_ASSERT (0 != drbid);
std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
NS_ABORT_IF (it == m_drbMap.end ());
return it->second;
}
void
UeManager::RemoveDataRadioBearerInfo (uint8_t drbid)
{
NS_LOG_FUNCTION (this << (uint32_t) drbid);
std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::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);
}
LteRrcSap::RrcConnectionReconfiguration
UeManager::BuildRrcConnectionReconfiguration ()
{
LteRrcSap::RrcConnectionReconfiguration msg;
msg.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
msg.haveRadioResourceConfigDedicated = true;
msg.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
msg.haveMobilityControlInfo = false;
msg.haveMeasConfig = false;
return msg;
}
LteRrcSap::RadioResourceConfigDedicated
UeManager::BuildRadioResourceConfigDedicated ()
{
LteRrcSap::RadioResourceConfigDedicated rrcd;
if (m_srb1 != 0)
{
LteRrcSap::SrbToAddMod stam;
stam.srbIdentity = m_srb1->m_srbIdentity;
stam.logicalChannelConfig = m_srb1->m_logicalChannelConfig;
rrcd.srbToAddModList.push_back (stam);
}
for (std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.begin ();
it != m_drbMap.end ();
++it)
{
LteRrcSap::DrbToAddMod 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.havePhysicalConfigDedicated = true;
rrcd.physicalConfigDedicated = m_physicalConfigDedicated;
return rrcd;
}
uint8_t
UeManager::GetNewRrcTransactionIdentifier ()
{
return ++m_lastRrcTransactionIdentifier;
}
uint8_t
UeManager::Lcid2Drbid (uint8_t lcid)
{
NS_ASSERT (lcid > 2);
return lcid - 2;
}
uint8_t
UeManager::Drbid2Lcid (uint8_t drbid)
{
return drbid + 2;
}
uint8_t
UeManager::Lcid2Bid (uint8_t lcid)
{
NS_ASSERT (lcid > 2);
return lcid - 2;
}
uint8_t
UeManager::Bid2Lcid (uint8_t bid)
{
return bid + 2;
}
uint8_t
UeManager::Drbid2Bid (uint8_t drbid)
{
return drbid;
}
uint8_t
UeManager::Bid2Drbid (uint8_t bid)
{
return bid;
}
void
UeManager::SwitchToState (State newState)
{
NS_LOG_FUNCTION (this << newState);
State oldState = m_state;
m_state = newState;
NS_LOG_INFO ("IMSI " << m_imsi << " RNTI " << m_rnti << " UeManager " << ToString (oldState) << " --> " << ToString (newState));
m_stateTransitionCallback (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_pendingRrcConnectionReconfiguration == true)
{
ScheduleRrcConnectionReconfiguration ();
}
}
break;
case CONNECTION_RECONFIGURATION:
break;
case CONNECTION_REESTABLISHMENT:
break;
case HANDOVER_LEAVING:
break;
default:
break;
}
}
// ///////////////////////////
// eNB RRC methods
// ///////////////////////////
NS_OBJECT_ENSURE_REGISTERED (LteEnbRrc);
LteEnbRrc::LteEnbRrc ()
: m_x2SapProvider (0),
m_cmacSapProvider (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)
{
NS_LOG_FUNCTION (this);
m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this);
m_rrcSapProvider = new MemberLteEnbRrcSapProvider<LteEnbRrc> (this);
m_x2SapUser = new EpcX2SpecificEpcX2SapUser<LteEnbRrc> (this);
m_s1SapUser = new MemberEpcEnbS1SapUser<LteEnbRrc> (this);
m_cphySapUser = new MemberLteEnbCphySapUser<LteEnbRrc> (this);
}
LteEnbRrc::~LteEnbRrc ()
{
NS_LOG_FUNCTION (this);
}
void
LteEnbRrc::DoDispose ()
{
NS_LOG_FUNCTION (this);
delete m_cmacSapUser;
delete m_rrcSapProvider;
delete m_x2SapUser;
delete m_s1SapUser;
delete m_cphySapUser;
}
TypeId
LteEnbRrc::GetTypeId (void)
{
NS_LOG_FUNCTION ("LteEnbRrc::GetTypeId");
static TypeId tid = TypeId ("ns3::LteEnbRrc")
.SetParent<Object> ()
.AddConstructor<LteEnbRrc> ()
.AddAttribute ("UeMap", "List of UeManager by C-RNTI.",
ObjectMapValue (),
MakeObjectMapAccessor (&LteEnbRrc::m_ueMap),
MakeObjectMapChecker<UeManager> ())
.AddAttribute ("DefaultTransmissionMode",
"The default UEs' transmission mode (0: SISO)",
UintegerValue (0), // default tx-mode
MakeUintegerAccessor (&LteEnbRrc::m_defaultTransmissionMode),
MakeUintegerChecker<uint8_t> ())
.AddAttribute ("EpsBearerToRlcMapping",
"Specify which type of RLC will be used for each type of EPS bearer. ",
EnumValue (RLC_SM_ALWAYS),
MakeEnumAccessor (&LteEnbRrc::m_epsBearerToRlcMapping),
MakeEnumChecker (RLC_SM_ALWAYS, "RlcSmAlways",
RLC_UM_ALWAYS, "RlcUmAlways",
RLC_AM_ALWAYS, "RlcAmAlways",
PER_BASED, "PacketErrorRateBased"))
.AddAttribute ("SystemInformationPeriodicity",
"The interval for sending system information",
TimeValue (MilliSeconds (80)),
MakeTimeAccessor (&LteEnbRrc::m_systemInformationPeriodicity),
MakeTimeChecker ())
;
return tid;
}
void
LteEnbRrc::SetEpcX2SapProvider (EpcX2SapProvider * s)
{
NS_LOG_FUNCTION (this << s);
m_x2SapProvider = s;
}
EpcX2SapUser*
LteEnbRrc::GetEpcX2SapUser ()
{
NS_LOG_FUNCTION (this);
return m_x2SapUser;
}
void
LteEnbRrc::SetLteEnbCmacSapProvider (LteEnbCmacSapProvider * s)
{
NS_LOG_FUNCTION (this << s);
m_cmacSapProvider = s;
}
LteEnbCmacSapUser*
LteEnbRrc::GetLteEnbCmacSapUser ()
{
NS_LOG_FUNCTION (this);
return m_cmacSapUser;
}
void
LteEnbRrc::SetLteEnbRrcSapUser (LteEnbRrcSapUser * s)
{
NS_LOG_FUNCTION (this << s);
m_rrcSapUser = s;
}
LteEnbRrcSapProvider*
LteEnbRrc::GetLteEnbRrcSapProvider ()
{
NS_LOG_FUNCTION (this);
return m_rrcSapProvider;
}
void
LteEnbRrc::SetLteMacSapProvider (LteMacSapProvider * s)
{
NS_LOG_FUNCTION (this);
m_macSapProvider = s;
}
void
LteEnbRrc::SetS1SapProvider (EpcEnbS1SapProvider * s)
{
m_s1SapProvider = s;
}
EpcEnbS1SapUser*
LteEnbRrc::GetS1SapUser ()
{
return m_s1SapUser;
}
void
LteEnbRrc::SetLteEnbCphySapProvider (LteEnbCphySapProvider * s)
{
NS_LOG_FUNCTION (this << s);
m_cphySapProvider = s;
}
LteEnbCphySapUser*
LteEnbRrc::GetLteEnbCphySapUser ()
{
NS_LOG_FUNCTION (this);
return m_cphySapUser;
}
Ptr<UeManager>
LteEnbRrc::GetUeManager (uint16_t rnti)
{
NS_LOG_FUNCTION (this << (uint32_t) rnti);
NS_ASSERT (0 != rnti);
std::map<uint16_t, Ptr<UeManager> >::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;
}
void
LteEnbRrc::ConfigureCell (uint8_t ulBandwidth, uint8_t dlBandwidth, uint16_t ulEarfcn, uint16_t dlEarfcn, uint16_t cellId)
{
NS_LOG_FUNCTION (this);
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);
LteRrcSap::MasterInformationBlock mib;
mib.dlBandwidth = m_dlBandwidth;
m_cphySapProvider->SetMasterInformationBlock (mib);
m_configured = true;
// the first time System Information is sent
Simulator::Schedule (MilliSeconds (16), &LteEnbRrc::SendSystemInformation, this);
}
void
LteEnbRrc::SetCellId (uint16_t cellId)
{
m_cellId = cellId;
}
bool
LteEnbRrc::SendData (Ptr<Packet> packet)
{
NS_LOG_FUNCTION (this << packet);
EpsBearerTag tag;
bool found = packet->RemovePacketTag (tag);
NS_ASSERT_MSG (found, "no EpsBearerTag found in packet to be sent");
Ptr<UeManager> ueManager = GetUeManager (tag.GetRnti ());
ueManager->SendData (tag.GetBid (), packet);
return true;
}
void
LteEnbRrc::SetForwardUpCallback (Callback <void, Ptr<Packet> > cb)
{
m_forwardUpCallback = cb;
}
void
LteEnbRrc::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<UeManager> ueManager = GetUeManager (rnti);
EpcX2SapProvider::HandoverRequestParams params;
params.oldEnbUeX2apId = rnti;
params.cause = EpcX2SapProvider::HandoverDesirableForRadioReason;
params.sourceCellId = m_cellId;
params.targetCellId = cellId;
params.ueAggregateMaxBitRateDownlink = 200 * 1000;
params.ueAggregateMaxBitRateUplink = 100 * 1000;
params.bearers = ueManager->GetErabList ();
LteRrcSap::HandoverPreparationInfo hpi;
hpi.asConfig.sourceUeIdentity = rnti;
hpi.asConfig.sourceDlCarrierFreq = m_dlEarfcn;
hpi.asConfig.sourceRadioResourceConfig = ueManager->GetRadioResourceConfigForHandoverPreparationInfo ();
params.rrcContext = m_rrcSapUser->EncodeHandoverPreparationInformation (hpi);
NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
NS_LOG_LOGIC ("rrcContext = " << params.rrcContext);
m_x2SapProvider->SendHandoverRequest (params);
}
void
LteEnbRrc::DoCompleteSetupUe (uint16_t rnti, LteEnbRrcSapProvider::CompleteSetupUeParameters params)
{
NS_LOG_FUNCTION (this << rnti);
GetUeManager (rnti)->CompleteSetupUe (params);
}
void
LteEnbRrc::DoRecvRrcConnectionRequest (uint16_t rnti, LteRrcSap::RrcConnectionRequest msg)
{
NS_LOG_FUNCTION (this << rnti);
GetUeManager (rnti)->RecvRrcConnectionRequest (msg);
}
void
LteEnbRrc::DoRecvRrcConnectionSetupCompleted (uint16_t rnti, LteRrcSap::RrcConnectionSetupCompleted msg)
{
NS_LOG_FUNCTION (this << rnti);
GetUeManager (rnti)->RecvRrcConnectionSetupCompleted (msg);
}
void
LteEnbRrc::DoRecvRrcConnectionReconfigurationCompleted (uint16_t rnti, LteRrcSap::RrcConnectionReconfigurationCompleted msg)
{
NS_LOG_FUNCTION (this << rnti);
GetUeManager (rnti)->RecvRrcConnectionReconfigurationCompleted (msg);
}
void
LteEnbRrc::DoRecvRrcConnectionReestablishmentRequest (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentRequest msg)
{
NS_LOG_FUNCTION (this << rnti);
GetUeManager (rnti)->RecvRrcConnectionReestablishmentRequest (msg);
}
void
LteEnbRrc::DoRecvRrcConnectionReestablishmentComplete (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentComplete msg)
{
NS_LOG_FUNCTION (this << rnti);
GetUeManager (rnti)->RecvRrcConnectionReestablishmentComplete (msg);
}
void
LteEnbRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
{
EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;
Ptr<UeManager> ueManager = GetUeManager (request.rnti);
response.rnti = request.rnti;
response.bid = ueManager->SetupDataRadioBearer (request.bearer, request.gtpTeid, request.transportLayerAddress);
response.gtpTeid = request.gtpTeid;
if (m_s1SapProvider)
{
m_s1SapProvider->S1BearerSetupRequest (response);
}
ueManager->ScheduleRrcConnectionReconfiguration ();
}
void
LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params)
{
NS_LOG_FUNCTION (this);
NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST");
NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
uint16_t rnti = AddUe (UeManager::HANDOVER_JOINING);
Ptr<UeManager> ueManager = GetUeManager (rnti);
ueManager->SetSource (params.sourceCellId, params.oldEnbUeX2apId);
for (std::vector <EpcX2Sap::ErabToBeSetupItem>::iterator it = params.bearers.begin ();
it != params.bearers.end ();
++it)
{
ueManager->SetupDataRadioBearer (it->erabLevelQosParameters, it->gtpTeid, it->transportLayerAddress);
}
LteRrcSap::RrcConnectionReconfiguration handoverCommand = ueManager->GetHandoverCommand ();
Ptr<Packet> encodedHandoverCommand = m_rrcSapUser->EncodeHandoverCommand (handoverCommand);
NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
EpcX2SapProvider::HandoverRequestAckParams ackParams;
ackParams.oldEnbUeX2apId = params.oldEnbUeX2apId;
ackParams.newEnbUeX2apId = rnti;
ackParams.sourceCellId = params.sourceCellId;
ackParams.targetCellId = params.targetCellId;
ackParams.rrcContext = encodedHandoverCommand;
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
LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams 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<UeManager> ueManager = GetUeManager (rnti);
// 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;
LteRrcSap::RrcConnectionReconfiguration handoverCommand = m_rrcSapUser->DecodeHandoverCommand (encodedHandoverCommand);
ueManager->SendHandoverCommand (handoverCommand);
}
void
LteEnbRrc::DoRecvUeContextRelease (EpcX2SapUser::UeContextReleaseParams 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;
RemoveUe (rnti);
}
void
LteEnbRrc::DoRecvLoadInformation (EpcX2SapUser::LoadInformationParams params)
{
NS_LOG_FUNCTION (this);
NS_LOG_LOGIC ("Recv X2 message: LOAD INFORMATION");
NS_LOG_LOGIC ("Number of cellInformationItems = " << params.cellInformationList.size ());
NS_ASSERT ("Processing of LOAD INFORMATION X2 message IS NOT IMPLEMENTED");
}
void
LteEnbRrc::DoRecvResourceStatusUpdate (EpcX2SapUser::ResourceStatusUpdateParams 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");
}
uint16_t
LteEnbRrc::DoAllocateTemporaryCellRnti ()
{
NS_LOG_FUNCTION (this);
return AddUe (UeManager::INITIAL_RANDOM_ACCESS);
}
void
LteEnbRrc::DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
{
Ptr<UeManager> ueManager = GetUeManager (cmacParams.m_rnti);
ueManager->CmacUeConfigUpdateInd (cmacParams);
}
void
LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
{
NS_LOG_FUNCTION (this << (uint32_t) rnti);
NS_FATAL_ERROR ("not implemented");
}
uint16_t
LteEnbRrc::AddUe (UeManager::State state)
{
NS_LOG_FUNCTION (this);
bool found = false;
uint16_t rnti;
for (rnti = m_lastAllocatedRnti;
(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<UeManager> ueManager = CreateObject<UeManager> (this, rnti, state);
m_ueMap.insert (std::pair<uint16_t, Ptr<UeManager> > (rnti, ueManager));
NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueManager->GetSrsConfigurationIndex ());
return rnti;
}
void
LteEnbRrc::RemoveUe (uint16_t rnti)
{
NS_LOG_FUNCTION (this << (uint32_t) rnti);
std::map <uint16_t, Ptr<UeManager> >::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);
// need to do this after UeManager has been deleted
RemoveSrsConfigurationIndex (srsCi);
}
TypeId
LteEnbRrc::GetRlcType (EpsBearer bearer)
{
switch (m_epsBearerToRlcMapping)
{
case RLC_SM_ALWAYS:
return LteRlcSm::GetTypeId ();
break;
case RLC_UM_ALWAYS:
return LteRlcUm::GetTypeId ();
break;
case RLC_AM_ALWAYS:
return LteRlcAm::GetTypeId ();
break;
case PER_BASED:
if (bearer.GetPacketErrorLossRate () > 1.0e-5)
{
return LteRlcUm::GetTypeId ();
}
else
{
return LteRlcAm::GetTypeId ();
}
break;
default:
return LteRlcSm::GetTypeId ();
break;
}
}
// from 3GPP TS 36.213 table 8.2-1 UE Specific SRS Periodicity
const uint8_t SRS_ENTRIES = 9;
uint16_t g_srsPeriodicity[SRS_ENTRIES] = {0, 2, 5, 10, 20, 40, 80, 160, 320};
uint16_t g_srsCiLow[SRS_ENTRIES] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
uint16_t g_srsCiHigh[SRS_ENTRIES] = {0, 1, 6, 16, 36, 76, 156, 316, 636};
uint16_t
LteEnbRrc::GetNewSrsConfigurationIndex ()
{
NS_LOG_FUNCTION (this << m_ueSrsConfigurationIndexSet.size ());
// SRS
if (m_srsCurrentPeriodicityId==0)
{
// no UEs -> init
m_ueSrsConfigurationIndexSet.insert (0);
m_lastAllocatedConfigurationIndex = 0;
m_srsCurrentPeriodicityId++;
return 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_LOG_DEBUG (this << " SRS reconfigure CIs " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " to " << g_srsPeriodicity[m_srsCurrentPeriodicityId+1] << " at " << Simulator::Now ());
// increase the current periocity for having enough CIs
m_ueSrsConfigurationIndexSet.clear ();
m_srsCurrentPeriodicityId++;
NS_ASSERT (m_srsCurrentPeriodicityId < SRS_ENTRIES);
// update all the UE's CI
uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
std::map<uint16_t, Ptr<UeManager> >::iterator it;
for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
{
(*it).second->SetSrsConfigurationIndex (srcCi);
m_ueSrsConfigurationIndexSet.insert (srcCi);
m_lastAllocatedConfigurationIndex = srcCi;
// update UeManager and trigger/update RRC connection reconfiguration
(*it).second->SetSrsConfigurationIndex (srcCi);
// configure PHY
m_cphySapProvider->SetSrsConfigurationIndex ((*it).first, srcCi);
srcCi++;
}
m_ueSrsConfigurationIndexSet.insert (m_lastAllocatedConfigurationIndex + 1);
m_lastAllocatedConfigurationIndex++;
}
else
{
// find a CI from the available ones
std::set<uint16_t>::reverse_iterator rit = m_ueSrsConfigurationIndexSet.rbegin ();
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
LteEnbRrc::RemoveSrsConfigurationIndex (uint16_t srcCi)
{
NS_LOG_FUNCTION (this << srcCi);
NS_FATAL_ERROR ("I though this method was unused so far...");
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);
NS_ASSERT (m_srsCurrentPeriodicityId > 1);
if (m_ueSrsConfigurationIndexSet.size () < g_srsPeriodicity[m_srsCurrentPeriodicityId - 1])
{
// reduce the periodicity
m_ueSrsConfigurationIndexSet.clear ();
m_srsCurrentPeriodicityId--;
if (m_srsCurrentPeriodicityId==0)
{
// no active users : renitialize structures
m_lastAllocatedConfigurationIndex = 0;
}
else
{
// update all the UE's CI
uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
std::map<uint16_t, Ptr<UeManager> >::iterator it;
for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
{
(*it).second->SetSrsConfigurationIndex (srcCi);
m_ueSrsConfigurationIndexSet.insert (srcCi);
m_lastAllocatedConfigurationIndex = srcCi;
// update UeManager and trigger/update RRC connection reconfiguration
(*it).second->SetSrsConfigurationIndex (srcCi);
// configure PHY
m_cphySapProvider->SetSrsConfigurationIndex ((*it).first, (*it).second->GetSrsConfigurationIndex ());
srcCi++;
}
}
}
}
uint8_t
LteEnbRrc::GetLogicalChannelGroup (EpsBearer bearer)
{
if (bearer.IsGbr ())
{
return 1;
}
else
{
return 2;
}
}
uint8_t
LteEnbRrc::GetLogicalChannelPriority (EpsBearer bearer)
{
return bearer.qci;
}
void
LteEnbRrc::SendSystemInformation ()
{
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
LteRrcSap::SystemInformation si;
si.haveSib2 = true;
si.sib2.freqInfo.ulCarrierFreq = m_ulEarfcn;
si.sib2.freqInfo.ulBandwidth = m_ulBandwidth;
m_rrcSapUser->SendSystemInformation (si);
Simulator::Schedule (m_systemInformationPeriodicity, &LteEnbRrc::SendSystemInformation, this);
}
} // namespace ns3