This commit is contained in:
jaumenin
2011-11-10 16:00:53 +01:00
9 changed files with 443 additions and 30 deletions

View File

@@ -64,7 +64,6 @@ BuildingsShadowingTestSuite::BuildingsShadowingTestSuite ()
double distance = 2000;
double hm = 1;
double hb = 30;
double freq = 869e6; // E_UTRA BAND #5 see table 5.5-1 of 36.101
Ptr<BuildingsMobilityModel> mm1 = CreateObject<BuildingsMobilityModel> ();
mm1->SetPosition (Vector (0.0, 0.0, hb));
@@ -76,7 +75,6 @@ BuildingsShadowingTestSuite::BuildingsShadowingTestSuite ()
// Test #2 Indoor model
distance = 30;
freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101
double henbHeight = 10.0;
Ptr<BuildingsMobilityModel> mm5 = CreateObject<BuildingsMobilityModel> ();
mm5->SetPosition (Vector (0.0, 0.0, henbHeight));
@@ -93,7 +91,6 @@ BuildingsShadowingTestSuite::BuildingsShadowingTestSuite ()
// Test #3 Indoor -> Outdoor
distance = 100;
freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101
Ptr<BuildingsMobilityModel> mm9 = CreateObject<BuildingsMobilityModel> ();
mm9->SetPosition (Vector (0.0, 0.0, henbHeight));
mm9->SetIndoor (building1);

View File

@@ -421,3 +421,49 @@ For communications involving at least one indoor node, the corresponding wall pe
Please refer to the documentation of the Buildings module for details on the actual models used in each case.
Trace Fading Model
++++++++++++++++++
The fading model is based on the one developed during the GSoC 2010 [Piro2011]_. The main characteristic of this model is the fact that the fading evaluation during simulation run-time is based on per-calculated traces. This is done for limiting the computational complexity of the simulator. On the other hand, it needs huge structures for storing the traces; therefore, a trade-off between the number of possible parameters and the memory occupancy has to be found. The most important ones are:
* users' speed: relative speed between users (affects the Doppler frequency, which in turns affects the time-variance property of the fading)
* number of taps (and relative power): number of multiple paths considered, which affects the frequency property of the fading.
* time granularity of the trace: sampling time of the trace.
* frequency granularity of the trace: number of values in frequency to be evaluated.
* length of trace: ideally large as the simulation time, might be reduced by windowing mechanism.
* number of users: number of independent traces to be used (ideally one trace per user).
With respect to the mathematical channel propagation model, we suggest the one provided by the ``rayleighchan`` function of Matlab, since it provides a well accepted channel modelization both in time and frequency domain. For more information, the reader is referred to [mathworks]_.
The simulator provides a matlab script (``/lte/model/JakesTraces/fading-trace-generator.m``) for generating traces based on the format used by the simulator.
In detail, the channel object created with the rayleighchan function is used for filtering a discrete-time impulse signal in order to obtain the channel impulse response. The filtering is repeated for different TTI, thus yielding subsequent time-correlated channel responses (one per TTI). The channel response is then processed with the ``pwelch`` function for obtaining its power spectral density values, which are then saved in a file with the proper format compatible with the simulator model.
Since the number of variable it is pretty high, generate traces considering all of them might produce a high number of traces of huge size. On this matter, we considered the following assumptions of the parameters based on the 3GPP fading propagation conditions (see Annex B.2 of [TS36.104]_):
* users' speed: typically only a few discrete values are considered, i.e.:
* 0 and 3 kmph for pedestrian scenarios
* 30 and 60 kmph for vehicular scenarios
* 0, 3, 30 and 60 for urban scenarios
* channel taps: only a limited number of sets of channel taps are normally considered, for example three models are mentioned in Annex B.2 of [TS36.104]_.
* time granularity: we need one fading value per TTI, i.e., every 1 ms (as this is the granularity in time of the ns-3 LTE PHY model).
* frequency granularity: we need one fading value per RB (which is the frequency granularity of the spectrum model used by the ns-3 LTE model).
* length of the trace: the simulator includes the windowing mechanism implemented during the GSoC 2011, which consists of picking up a window of the trace each window length in a random fashion.
* per-user fading process: users share the same fading trace, but for each user a different starting point in the trace is randomly picked up. This choice was made to avoid the need to provide one fading trace per user.
According to the parameters we considered, the following formula express in detail the total size :math:`S_{traces}` of the fading traces:
.. math::
S_{traces} = S_{sample} \times N_{RB} \times \frac{T_{trace}}{T_{sample}} \times N_{scenarios} \mbox{ [bytes]}
where :math:`S_{sample}` is the size in bytes of the sample (e.g., 8 in case of double precision, 4 in case of float precision), :math:`N_{RB}` is the number of RB or set of RBs to be considered, :math:`T_{trace}` is the total length of the trace, :math:`T_{sample}` is the time resolution of the trace (1 ms), and :math:`N_{scenarios}` is the number of fading scenarios that are desired (i.e., combinations of different sets of channel taps and user speed values). We provide traces for 3 different scenarios one for each taps configuration defined in Annex B.2 of [TS36.104]_:
* Pedestrian: with nodes' speed of 3 kmph.
* Vehicular: with nodes' speed of 60 kmph.
* Urban: with nodes' speed of 3 kmph.
hence :math:`N_{scenarios} = 3`. All traces have :math:`T_{trace} = 10` s and :math:`RB_{NUM} = 100`. This results in a total 24 MB bytes of traces.

View File

@@ -0,0 +1,138 @@
/* -*- 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: Manuel Requena <manuel.requena@cttc.es>
*/
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/config-store.h"
//#include "ns3/gtk-config-store.h"
using namespace ns3;
// position functions insipred by /examples/wireless/wifi-ap.cc
static void
SetPosition (Ptr<Node> node, Vector position)
{
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
mobility->SetPosition (position);
}
static Vector
GetPosition (Ptr<Node> node)
{
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
return mobility->GetPosition ();
}
static void
ChangePosition (Ptr<Node> node)
{
Vector pos = GetPosition (node);
if (pos.x <= 10.0)
{
pos.x = 100000.0; // force CQI to 0
}
else
{
pos.x = 5.0;
}
SetPosition (node, pos);
}
int main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
// to save a template default attribute file run it like this:
// ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt --ns3::ConfigStore::Mode=Save --ns3::ConfigStore::FileFormat=RawText" --run src/lte/examples/lena-first-sim
//
// to load a previously created default attribute file
// ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt --ns3::ConfigStore::Mode=Load --ns3::ConfigStore::FileFormat=RawText" --run src/lte/examples/lena-first-sim
ConfigStore inputConfig;
inputConfig.ConfigureDefaults ();
// parse again so you can override default values from the command line
cmd.Parse (argc, argv);
Ptr<LenaHelper> lena = CreateObject<LenaHelper> ();
lena->SetAttribute ("PropagationModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
//lena->EnableLogComponents ();
// LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
// LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
LogComponentEnable ("LenaHelper", LOG_LEVEL_ALL);
LogComponentEnable ("BuildingsPropagationLossModel", LOG_LEVEL_ALL);
// Create Nodes: eNodeB and UE
NodeContainer enbNodes;
NodeContainer ueNodes;
enbNodes.Create (1);
ueNodes.Create (1);
// Install Mobility Model
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::BuildingsMobilityModel");
mobility.Install (enbNodes);
mobility.SetMobilityModel ("ns3::BuildingsMobilityModel");
mobility.Install (ueNodes);
// Create Devices and install them in the Nodes (eNB and UE)
NetDeviceContainer enbDevs;
NetDeviceContainer ueDevs;
// lena->SetSchedulerType ("ns3::RrFfMacScheduler");
lena->SetSchedulerType ("ns3::PfFfMacScheduler");
lena->SetSchedulerAttribute ("CqiTimerThreshold", UintegerValue (3));
enbDevs = lena->InstallEnbDevice (enbNodes);
ueDevs = lena->InstallUeDevice (ueNodes);
lena->EnableRlcTraces();
lena->EnableMacTraces();
// Attach a UE to a eNB
lena->Attach (ueDevs, enbDevs.Get (0));
Simulator::Schedule (Seconds (0.010), &ChangePosition, ueNodes.Get (0));
Simulator::Schedule (Seconds (0.020), &ChangePosition, ueNodes.Get (0));
// Activate an EPS bearer
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
EpsBearer bearer (q);
lena->ActivateEpsBearer (ueDevs, bearer);
Simulator::Stop (Seconds (0.030));
Simulator::Run ();
//GtkConfigStore config;
//config.ConfigureAttributes ();
Simulator::Destroy ();
return 0;
}

View File

@@ -12,7 +12,10 @@ def build(bld):
obj.source = 'lena-rlc-calculator.cc'
obj = bld.create_ns3_program('lena-fading',
['lte'])
obj.source = 'lena-fading.cc'
obj.source = 'lena-fading.cc'
obj = bld.create_ns3_program('lena-cqi-threshold',
['lte'])
obj.source = 'lena-cqi-threshold.cc'
obj = bld.create_ns3_program('lena-runtime-profiler',
['lte'])
obj.source = 'lena-runtime-profiler.cc'

View File

@@ -467,12 +467,16 @@ LenaHelper::EnableLogComponents (void)
LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
// LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
// LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
std::string propModelStr = m_dlPropagationModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
const char* propModel = m_dlPropagationModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
LogComponentEnable (propModel, LOG_LEVEL_ALL);
if (m_fadingModelType.compare ( "ns3::TraceFadingLossModel") == 0)
{
const char* fadingModel = m_fadingModelType.erase (0,5).c_str ();
LogComponentEnable (fadingModel, LOG_LEVEL_ALL);
}
LogComponentEnable ("SingleModelSpectrumChannel", LOG_LEVEL_ALL);
LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);

View File

@@ -237,7 +237,13 @@ PfFfMacScheduler::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::PfFfMacScheduler")
.SetParent<FfMacScheduler> ()
.AddConstructor<PfFfMacScheduler> ();
.AddConstructor<PfFfMacScheduler> ()
.AddAttribute ("CqiTimerThreshold",
"The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
UintegerValue (1000),
MakeUintegerAccessor (&PfFfMacScheduler::m_cqiTimersThreshold),
MakeUintegerChecker<uint32_t> ())
;
return tid;
}
@@ -426,6 +432,9 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched
// evaluate the relative channel quality indicator for each UE per each RBG
// (since we are using allocation type 0 the small unit of allocation is RBG)
// Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
RefreshDlCqiMaps ();
int rbgSize = GetRbgSize (m_cschedCellConfig.m_dlBandwidth);
int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
//std::vector <LteFlowId_t> rbgAllocationMap;
@@ -443,12 +452,13 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched
uint8_t cqi = 0;
if (itCqi == m_a30CqiRxed.end ())
{
NS_LOG_DEBUG (this << " No DL-CQI for this UE " << (*it).first);
// NS_LOG_DEBUG (this << " No DL-CQI for this UE " << (*it).first);
cqi = 1; // start with lowest value
}
else
{
cqi = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi.at (0);
// NS_LOG_INFO (this << " CQI " << (uint32_t)cqi);
}
if (cqi > 0) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
{
@@ -527,7 +537,7 @@ PfFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched
{
if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
{
// NS_LOG_DEBUG (this << " RBG " << (*itMap).second.at (k) << " CQI " << (uint16_t)((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) );
// NS_LOG_DEBUG (this << " RBG " << (*itMap).second.at (k) << " CQI " << (uint16_t)((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) );
if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) < worstCqi)
{
worstCqi = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0));
@@ -649,11 +659,17 @@ PfFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
{
// create the new entry
m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (rnti, params.m_cqiList.at (i).m_wbCqi.at (0)) ); // only codeword 0 at this stage (SISO)
// generate correspondent timer
m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
}
else
{
// update the CQI value
// update the CQI value and refresh correspondent timer
(*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
// update correspondent timer
std::map <uint16_t,uint32_t>::iterator itTimers;
itTimers = m_p10CqiTimers.find (rnti);
(*itTimers).second = m_cqiTimersThreshold;
}
}
else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
@@ -666,11 +682,15 @@ PfFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
{
// create the new entry
m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
}
else
{
// update the CQI value
// update the CQI value and refresh correspondent timer
(*it).second = params.m_cqiList.at (i).m_sbMeasResult;
std::map <uint16_t,uint32_t>::iterator itTimers;
itTimers = m_a30CqiTimers.find (rnti);
(*itTimers).second = m_cqiTimersThreshold;
}
}
else
@@ -719,6 +739,7 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched
{
// NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
RefreshUlCqiMaps ();
std::map <uint16_t,uint8_t>::iterator it;
int nflows = 0;
@@ -974,7 +995,7 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
for (uint32_t i = 0; i < (*itMap).second.size (); i++)
{
// convert from fixed point notation Sxxxxxxxxxxx.xxx to double
NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
// NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
//NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
itCqi = m_ueCqi.find ((*itMap).second.at (i));
@@ -996,11 +1017,18 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
}
m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
// generate correspondent timer
m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
}
else
{
// update the value
(*itCqi).second.at (i) = sinr;
// update correspondent timer
std::map <uint16_t, uint32_t>::iterator itTimers;
itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
(*itTimers).second = m_cqiTimersThreshold;
}
}
@@ -1010,4 +1038,82 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
return;
}
void
PfFfMacScheduler::RefreshDlCqiMaps(void)
{
// refresh DL CQI P01 Map
std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
while (itP10!=m_p10CqiTimers.end ())
{
// NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
if ((*itP10).second == 0)
{
// delete correspondent entries
std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
m_p10CqiRxed.erase (itMap);
m_p10CqiTimers.erase (itP10);
}
else
{
(*itP10).second--;
}
itP10++;
}
// refresh DL CQI A30 Map
std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
while (itA30!=m_a30CqiTimers.end ())
{
// NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
if ((*itA30).second == 0)
{
// delete correspondent entries
std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first);
m_a30CqiRxed.erase (itMap);
m_a30CqiTimers.erase (itA30);
}
else
{
(*itA30).second--;
}
itA30++;
}
return;
}
void
PfFfMacScheduler::RefreshUlCqiMaps(void)
{
// refresh UL CQI Map
std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
while (itUl!=m_ueCqiTimers.end ())
{
// NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
if ((*itUl).second == 0)
{
// delete correspondent entries
std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
(*itMap).second.clear ();
m_ueCqi.erase (itMap);
m_ueCqiTimers.erase (itUl);
}
else
{
(*itUl).second--;
}
itUl++;
}
return;
}
}

View File

@@ -134,6 +134,9 @@ private:
int LcActivePerFlow (uint16_t rnti);
double EstimateUlSinr (uint16_t rnti, uint16_t rb);
void RefreshDlCqiMaps(void);
void RefreshUlCqiMaps(void);
/*
* Vectors of UE's LC info
@@ -156,11 +159,19 @@ private:
* Map of UE's DL CQI P01 received
*/
std::map <uint16_t,uint8_t> m_p10CqiRxed;
/*
* Map of UE's timers on DL CQI P01 received
*/
std::map <uint16_t,uint32_t> m_p10CqiTimers;
/*
* Map of UE's DL CQI A30 received
*/
std::map <uint16_t,SbMeasResult_s> m_a30CqiRxed;
/*
* Map of UE's timers on DL CQI A30 received
*/
std::map <uint16_t,uint32_t> m_a30CqiTimers;
/*
* Map of previous allocated UE per RBG
@@ -172,6 +183,10 @@ private:
* Map of UEs' UL-CQI per RBG
*/
std::map <uint16_t, std::vector <double> > m_ueCqi;
/*
* Map of UEs' timers on UL-CQI per RBG
*/
std::map <uint16_t, uint32_t> m_ueCqiTimers;
/*
* Map of UE's buffer status reports received
@@ -193,6 +208,8 @@ private:
uint8_t m_schedTtiDelay; // delay between scheduling and reception (based on m_macChTtiDelay)
uint16_t m_nextRntiUl; // RNTI of the next user to be served next scheduling in UL
uint32_t m_cqiTimersThreshold; // # of TTIs for which a CQI canbe considered valid
};

View File

@@ -235,7 +235,13 @@ RrFfMacScheduler::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::RrFfMacScheduler")
.SetParent<FfMacScheduler> ()
.AddConstructor<RrFfMacScheduler> ();
.AddConstructor<RrFfMacScheduler> ()
.AddAttribute ("CqiTimerThreshold",
"The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
UintegerValue (1000),
MakeUintegerAccessor (&RrFfMacScheduler::m_cqiTimersThreshold),
MakeUintegerChecker<uint32_t> ())
;
return tid;
}
@@ -333,6 +339,7 @@ RrFfMacScheduler::DoSchedDlRlcBufferReq (const struct FfMacSchedSapProvider::Sch
{
m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (params.m_rnti, 1)); // only codeword 0 at this stage (SISO)
// initialized to 1 (i.e., the lowest value for transmitting a signal)
m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (params.m_rnti, m_cqiTimersThreshold));
}
return;
@@ -374,6 +381,8 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched
{
NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
// API generated by RLC for triggering the scheduling of a DL subframe
RefreshDlCqiMaps ();
// Get the actual active flows (queue!=0)
std::vector<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
@@ -388,22 +397,29 @@ RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::Sched
|| ((*it).m_rlcStatusPduSize > 0) )
{
std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find ((*it).m_rnti);
uint8_t cqi = 0;
if (itCqi != m_p10CqiRxed.end ())
{
if ((*itCqi).second != 0)
cqi = (*itCqi).second;
}
else
{
cqi = 1; // lowest value fro trying a transmission
}
if (cqi != 0)
{
// CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
nflows++;
itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
if (itLcRnti != lcActivesPerRnti.end ())
{
// CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
nflows++;
itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
if (itLcRnti != lcActivesPerRnti.end ())
{
(*itLcRnti).second++;
}
else
{
lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
}
(*itLcRnti).second++;
}
else
{
lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
}
}
}
}
@@ -563,11 +579,17 @@ RrFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
{
// create the new entry
m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (rnti, params.m_cqiList.at (i).m_wbCqi.at (0)) ); // only codeword 0 at this stage (SISO)
// generate correspondent timer
m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
}
else
{
// update the CQI value
(*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
// update correspondent timer
std::map <uint16_t,uint32_t>::iterator itTimers;
itTimers = m_p10CqiTimers.find (rnti);
(*itTimers).second = m_cqiTimersThreshold;
}
}
else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
@@ -587,9 +609,11 @@ RrFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
void
RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters& params)
{
NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
// NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
RefreshUlCqiMaps ();
std::map <uint16_t,uint8_t>::iterator it;
int nflows = 0;
@@ -828,11 +852,17 @@ RrFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
}
m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
// generate correspondent timer
m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
}
else
{
// update the value
(*itCqi).second.at (i) = sinr;
// update correspondent timer
std::map <uint16_t, uint32_t>::iterator itTimers;
itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
(*itTimers).second = m_cqiTimersThreshold;
}
}
@@ -842,4 +872,62 @@ RrFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched
return;
}
void
RrFfMacScheduler::RefreshDlCqiMaps(void)
{
NS_LOG_FUNCTION (this << m_p10CqiTimers.size ());
// refresh DL CQI P01 Map
std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
while (itP10!=m_p10CqiTimers.end ())
{
NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
if ((*itP10).second == 0)
{
// delete correspondent entries
std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
m_p10CqiRxed.erase (itMap);
m_p10CqiTimers.erase (itP10);
}
else
{
(*itP10).second--;
}
itP10++;
}
return;
}
void
RrFfMacScheduler::RefreshUlCqiMaps(void)
{
// refresh UL CQI Map
std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
while (itUl!=m_ueCqiTimers.end ())
{
NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
if ((*itUl).second == 0)
{
// delete correspondent entries
std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
(*itMap).second.clear ();
m_ueCqi.erase (itMap);
m_ueCqiTimers.erase (itUl);
}
else
{
(*itUl).second--;
}
itUl++;
}
return;
}
}

View File

@@ -118,6 +118,9 @@ private:
int GetRbgSize (int dlbandwidth);
void RefreshDlCqiMaps(void);
void RefreshUlCqiMaps(void);
/*
* Vectors of UE's RLC info
@@ -128,6 +131,10 @@ private:
* Map of UE's DL CQI P01 received
*/
std::map <uint16_t,uint8_t> m_p10CqiRxed;
/*
* Map of UE's timers on DL CQI P01 received
*/
std::map <uint16_t,uint32_t> m_p10CqiTimers;
/*
* Map of previous allocated UE per RBG
@@ -139,6 +146,10 @@ private:
* Map of UEs' UL-CQI per RBG
*/
std::map <uint16_t, std::vector <double> > m_ueCqi;
/*
* Map of UEs' timers on UL-CQI per RBG
*/
std::map <uint16_t, uint32_t> m_ueCqiTimers;
@@ -161,6 +172,9 @@ private:
uint16_t m_nextRntiDl; // RNTI of the next user to be served next scheduling in DL
uint16_t m_nextRntiUl; // RNTI of the next user to be served next scheduling in UL
uint32_t m_cqiTimersThreshold; // # of TTIs for which a CQI canbe considered valid
};