Merge
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
|
||||
138
src/lte/examples/lena-cqi-threshold.cc
Normal file
138
src/lte/examples/lena-cqi-threshold.cc
Normal 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;
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user