A Discrete-Event Network Simulator
API
lte-test-interference.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Manuel Requena <manuel.requena@cttc.es>
18  * Nicola Baldo <nbaldo@cttc.es>
19  */
20 
21 #include "lte-test-interference.h"
22 
23 #include "ns3/boolean.h"
24 #include "ns3/double.h"
25 #include "ns3/ff-mac-scheduler.h"
26 #include "ns3/log.h"
27 #include "ns3/lte-enb-net-device.h"
28 #include "ns3/lte-enb-phy.h"
29 #include "ns3/lte-helper.h"
30 #include "ns3/lte-ue-net-device.h"
31 #include "ns3/lte-ue-phy.h"
32 #include "ns3/mobility-helper.h"
33 #include "ns3/simulator.h"
34 #include "ns3/string.h"
35 #include <ns3/enum.h>
36 #include <ns3/lte-chunk-processor.h>
37 
38 using namespace ns3;
39 
40 NS_LOG_COMPONENT_DEFINE("LteInterferenceTest");
41 
42 void
44  std::string path,
46 {
47  testcase->DlScheduling(dlInfo);
48 }
49 
50 void
52  std::string path,
53  uint32_t frameNo,
54  uint32_t subframeNo,
55  uint16_t rnti,
56  uint8_t mcs,
57  uint16_t sizeTb,
58  uint8_t ccId)
59 {
60  testcase->UlScheduling(frameNo, subframeNo, rnti, mcs, sizeTb);
61 }
62 
68  : TestSuite("lte-interference", SYSTEM)
69 {
70  // these two first test cases have a spectral efficiency that corresponds to CQI=0 (out of
71  // range)
72  // TODO: update the test conditions to handle out-of-range correctly
73  // AddTestCase (new LteInterferenceTestCase ("d1=50, d2=10", 50.000000, 10.000000, 0.040000,
74  // 0.040000, 0.010399, 0.010399, 0, 0), TestCase::QUICK); AddTestCase (new
75  // LteInterferenceTestCase ("d1=50, d2=20", 50.000000, 20.000000, 0.160000, 0.159998,
76  // 0.041154, 0.041153, 0, 0), TestCase::QUICK);
77 
78  AddTestCase(new LteInterferenceTestCase("d1=3000, d2=6000",
79  3000.000000,
80  6000.000000,
81  3.844681,
82  1.714583,
83  0.761558,
84  0.389662,
85  6,
86  4),
87  TestCase::QUICK);
88  AddTestCase(new LteInterferenceTestCase("d1=50, d2=50",
89  50.000000,
90  50.000000,
91  0.999997,
92  0.999907,
93  0.239828,
94  0.239808,
95  2,
96  2),
97  TestCase::QUICK);
98  AddTestCase(new LteInterferenceTestCase("d1=50, d2=100",
99  50.000000,
100  100.000000,
101  3.999955,
102  3.998520,
103  0.785259,
104  0.785042,
105  6,
106  6),
107  TestCase::QUICK);
108  AddTestCase(new LteInterferenceTestCase("d1=50, d2=200",
109  50.000000,
110  200.000000,
111  15.999282,
112  15.976339,
113  1.961072,
114  1.959533,
115  14,
116  14),
117  TestCase::QUICK);
118  AddTestCase(new LteInterferenceTestCase("d1=50, d2=500",
119  50.000000,
120  500.000000,
121  99.971953,
122  99.082845,
123  4.254003,
124  4.241793,
125  22,
126  22),
127  TestCase::QUICK);
128  AddTestCase(new LteInterferenceTestCase("d1=50, d2=1000",
129  50.000000,
130  1000.000000,
131  399.551632,
132  385.718468,
133  6.194952,
134  6.144825,
135  28,
136  28),
137  TestCase::QUICK);
138  AddTestCase(new LteInterferenceTestCase("d1=50, d2=10000",
139  50.000000,
140  10000.000000,
141  35964.181431,
142  8505.970614,
143  12.667381,
144  10.588084,
145  28,
146  28),
147  TestCase::QUICK);
148  AddTestCase(new LteInterferenceTestCase("d1=50, d2=100000",
149  50.000000,
150  100000.000000,
151  327284.773828,
152  10774.181090,
153  15.853097,
154  10.928917,
155  28,
156  28),
157  TestCase::QUICK);
158  AddTestCase(new LteInterferenceTestCase("d1=50, d2=1000000",
159  50.000000,
160  1000000.000000,
161  356132.574152,
162  10802.988445,
163  15.974963,
164  10.932767,
165  28,
166  28),
167  TestCase::QUICK);
168  AddTestCase(new LteInterferenceTestCase("d1=4500, d2=12600",
169  4500.000000,
170  12600.000000,
171  6.654462,
172  1.139831,
173  1.139781,
174  0.270399,
175  8,
176  2),
177  TestCase::QUICK);
178  AddTestCase(new LteInterferenceTestCase("d1=5400, d2=12600",
179  5400.000000,
180  12600.000000,
181  4.621154,
182  0.791549,
183  0.876368,
184  0.193019,
185  6,
186  0),
187  TestCase::QUICK);
188 }
189 
195 
201  double d1,
202  double d2,
203  double dlSinr,
204  double ulSinr,
205  double dlSe,
206  double ulSe,
207  uint16_t dlMcs,
208  uint16_t ulMcs)
209  : TestCase(name),
210  m_d1(d1),
211  m_d2(d2),
212  m_expectedDlSinrDb(10 * std::log10(dlSinr)),
213  m_expectedUlSinrDb(10 * std::log10(ulSinr)),
214  m_dlMcs(dlMcs),
215  m_ulMcs(ulMcs)
216 {
217 }
218 
220 {
221 }
222 
223 void
225 {
226  NS_LOG_INFO(this << GetName());
227 
228  Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
229  Config::SetDefault("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue(false));
230  Config::SetDefault("ns3::LteAmc::AmcModel", EnumValue(LteAmc::PiroEW2010));
231  Config::SetDefault("ns3::LteAmc::Ber", DoubleValue(0.00005));
232  Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
233  lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
234  lteHelper->SetAttribute("UseIdealRrc", BooleanValue(false));
235  lteHelper->SetAttribute("UsePdschForCqiGeneration", BooleanValue(true));
236 
237  // Disable Uplink Power Control
238  Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(false));
239 
240  // Create Nodes: eNodeB and UE
241  NodeContainer enbNodes;
242  NodeContainer ueNodes1;
243  NodeContainer ueNodes2;
244  enbNodes.Create(2);
245  ueNodes1.Create(1);
246  ueNodes2.Create(1);
247  NodeContainer allNodes = NodeContainer(enbNodes, ueNodes1, ueNodes2);
248 
249  // the topology is the following:
250  // d2
251  // UE1-----------eNB2
252  // | |
253  // d1| |d1
254  // | d2 |
255  // eNB1----------UE2
256  //
257  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
258  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // eNB1
259  positionAlloc->Add(Vector(m_d2, m_d1, 0.0)); // eNB2
260  positionAlloc->Add(Vector(0.0, m_d1, 0.0)); // UE1
261  positionAlloc->Add(Vector(m_d2, 0.0, 0.0)); // UE2
263  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
264  mobility.SetPositionAllocator(positionAlloc);
265  mobility.Install(allNodes);
266 
267  // Create Devices and install them in the Nodes (eNB and UE)
268  NetDeviceContainer enbDevs;
269  NetDeviceContainer ueDevs1;
270  NetDeviceContainer ueDevs2;
271  lteHelper->SetSchedulerType("ns3::RrFfMacScheduler");
272  lteHelper->SetSchedulerAttribute("UlCqiFilter", EnumValue(FfMacScheduler::PUSCH_UL_CQI));
273  enbDevs = lteHelper->InstallEnbDevice(enbNodes);
274  ueDevs1 = lteHelper->InstallUeDevice(ueNodes1);
275  ueDevs2 = lteHelper->InstallUeDevice(ueNodes2);
276 
277  lteHelper->Attach(ueDevs1, enbDevs.Get(0));
278  lteHelper->Attach(ueDevs2, enbDevs.Get(1));
279 
280  // Activate an EPS bearer
281  EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
282  EpsBearer bearer(q);
283  lteHelper->ActivateDataRadioBearer(ueDevs1, bearer);
284  lteHelper->ActivateDataRadioBearer(ueDevs2, bearer);
285 
286  // Use testing chunk processor in the PHY layer
287  // It will be used to test that the SNR is as intended
288  // we plug in two instances, one for DL and one for UL
289 
290  Ptr<LtePhy> ue1Phy = ueDevs1.Get(0)->GetObject<LteUeNetDevice>()->GetPhy()->GetObject<LtePhy>();
291  Ptr<LteChunkProcessor> testDlSinr1 = Create<LteChunkProcessor>();
292  LteSpectrumValueCatcher dlSinr1Catcher;
293  testDlSinr1->AddCallback(MakeCallback(&LteSpectrumValueCatcher::ReportValue, &dlSinr1Catcher));
294  ue1Phy->GetDownlinkSpectrumPhy()->AddDataSinrChunkProcessor(testDlSinr1);
295 
296  Ptr<LtePhy> enb1phy =
297  enbDevs.Get(0)->GetObject<LteEnbNetDevice>()->GetPhy()->GetObject<LtePhy>();
298  Ptr<LteChunkProcessor> testUlSinr1 = Create<LteChunkProcessor>();
299  LteSpectrumValueCatcher ulSinr1Catcher;
300  testUlSinr1->AddCallback(MakeCallback(&LteSpectrumValueCatcher::ReportValue, &ulSinr1Catcher));
301  enb1phy->GetUplinkSpectrumPhy()->AddDataSinrChunkProcessor(testUlSinr1);
302 
303  Config::Connect("/NodeList/0/DeviceList/0/ComponentCarrierMap/*/LteEnbMac/DlScheduling",
305 
306  Config::Connect("/NodeList/0/DeviceList/0/ComponentCarrierMap/*/LteEnbMac/UlScheduling",
308 
309  // same as above for eNB2 and UE2
310 
311  Ptr<LtePhy> ue2Phy = ueDevs2.Get(0)->GetObject<LteUeNetDevice>()->GetPhy()->GetObject<LtePhy>();
312  Ptr<LteChunkProcessor> testDlSinr2 = Create<LteChunkProcessor>();
313  LteSpectrumValueCatcher dlSinr2Catcher;
314  testDlSinr2->AddCallback(MakeCallback(&LteSpectrumValueCatcher::ReportValue, &dlSinr2Catcher));
315  ue2Phy->GetDownlinkSpectrumPhy()->AddDataSinrChunkProcessor(testDlSinr2);
316 
317  Ptr<LtePhy> enb2phy =
318  enbDevs.Get(1)->GetObject<LteEnbNetDevice>()->GetPhy()->GetObject<LtePhy>();
319  Ptr<LteChunkProcessor> testUlSinr2 = Create<LteChunkProcessor>();
320  LteSpectrumValueCatcher ulSinr2Catcher;
321  testUlSinr2->AddCallback(MakeCallback(&LteSpectrumValueCatcher::ReportValue, &ulSinr2Catcher));
322  enb1phy->GetUplinkSpectrumPhy()->AddDataSinrChunkProcessor(testUlSinr2);
323 
324  Config::Connect("/NodeList/1/DeviceList/0/ComponentCarrierMap/*/LteEnbMac/DlScheduling",
326 
327  Config::Connect("/NodeList/1/DeviceList/0/ComponentCarrierMap/*/LteEnbMac/UlScheduling",
329 
330  // need to allow for RRC connection establishment + SRS
331  Simulator::Stop(Seconds(0.100));
332  Simulator::Run();
333 
334  if (m_dlMcs > 0)
335  {
336  double dlSinr1Db = 10.0 * std::log10(dlSinr1Catcher.GetValue()->operator[](0));
337  NS_TEST_ASSERT_MSG_EQ_TOL(dlSinr1Db,
339  0.01,
340  "Wrong SINR in DL! (eNB1 --> UE1)");
341 
342  double dlSinr2Db = 10.0 * std::log10(dlSinr2Catcher.GetValue()->operator[](0));
343  NS_TEST_ASSERT_MSG_EQ_TOL(dlSinr2Db,
345  0.01,
346  "Wrong SINR in DL! (eNB2 --> UE2)");
347  }
348  if (m_ulMcs > 0)
349  {
350  double ulSinr1Db = 10.0 * std::log10(ulSinr1Catcher.GetValue()->operator[](0));
351  NS_TEST_ASSERT_MSG_EQ_TOL(ulSinr1Db,
353  0.01,
354  "Wrong SINR in UL! (UE1 --> eNB1)");
355 
356  double ulSinr2Db = 10.0 * std::log10(ulSinr2Catcher.GetValue()->operator[](0));
357  NS_TEST_ASSERT_MSG_EQ_TOL(ulSinr2Db,
359  0.01,
360  "Wrong SINR in UL! (UE2 --> eNB2)");
361  }
362 
363  Simulator::Destroy();
364 }
365 
366 void
368 {
369  NS_LOG_FUNCTION(dlInfo.frameNo << dlInfo.subframeNo << dlInfo.rnti << (uint32_t)dlInfo.mcsTb1
370  << dlInfo.sizeTb1 << (uint32_t)dlInfo.mcsTb2 << dlInfo.sizeTb2);
371  // need to allow for RRC connection establishment + CQI feedback reception + persistent data
372  // transmission
373  if (Simulator::Now() > MilliSeconds(65))
374  {
375  NS_TEST_ASSERT_MSG_EQ((uint32_t)dlInfo.mcsTb1, (uint32_t)m_dlMcs, "Wrong DL MCS ");
376  }
377 }
378 
379 void
381  uint32_t subframeNo,
382  uint16_t rnti,
383  uint8_t mcs,
384  uint16_t sizeTb)
385 {
386  NS_LOG_FUNCTION(frameNo << subframeNo << rnti << (uint32_t)mcs << sizeTb);
387  // need to allow for RRC connection establishment + SRS transmission
388  if (Simulator::Now() > MilliSeconds(50))
389  {
390  NS_TEST_ASSERT_MSG_EQ((uint32_t)mcs, (uint32_t)m_ulMcs, "Wrong UL MCS");
391  }
392 }
Test that SINR calculation and MCS selection works fine in a multi-cell interference scenario.
LteInterferenceTestCase(std::string name, double d1, double d2, double dlSinr, double ulSinr, double dlSe, double ulSe, uint16_t dlMcs, uint16_t ulMcs)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
double m_expectedDlSinrDb
expected DL SINR in dB
void UlScheduling(uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, uint8_t mcs, uint16_t sizeTb)
UL scheduling function.
double m_expectedUlSinrDb
expected UL SINR in dB
void DlScheduling(DlSchedulingCallbackInfo dlInfo)
DL scheduling function.
double m_d2
distance between UE and other ENB
double m_d1
distance between UE and ENB
Test suite for interference test.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Hold variables of type enum.
Definition: enum.h:62
This class contains the specification of EPS Bearers.
Definition: eps-bearer.h:91
Qci
QoS Class Indicator.
Definition: eps-bearer.h:106
The eNodeB device implementation.
void SetSchedulerAttribute(std::string n, const AttributeValue &v)
Set an attribute for the scheduler to be created.
Definition: lte-helper.cc:306
NetDeviceContainer InstallEnbDevice(NodeContainer c)
Create a set of eNodeB devices.
Definition: lte-helper.cc:485
void SetSchedulerType(std::string type)
Set the type of scheduler to be used by eNodeB devices.
Definition: lte-helper.cc:292
void Attach(NetDeviceContainer ueDevices)
Enables automatic attachment of a set of UE devices to a suitable cell using Idle mode initial cell s...
Definition: lte-helper.cc:1039
void ActivateDataRadioBearer(NetDeviceContainer ueDevices, EpsBearer bearer)
Activate a Data Radio Bearer on a given UE devices (for LTE-only simulation).
Definition: lte-helper.cc:1436
NetDeviceContainer InstallUeDevice(NodeContainer c)
Create a set of UE devices.
Definition: lte-helper.cc:500
The LtePhy models the physical layer of LTE.
Definition: lte-phy.h:51
A sink to be plugged to the callback of LteChunkProcessor allowing to save and later retrieve the lat...
Ptr< SpectrumValue > GetValue()
The LteUeNetDevice class implements the UE net device.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:204
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
std::string GetName() const
Definition: test.cc:373
A suite of tests to run.
Definition: test.h:1256
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:974
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
static LteInterferenceTestSuite lteLinkAdaptationWithInterferenceTestSuite
Static variable for test initialization.
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:765
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition: test.h:337
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
void LteTestDlSchedulingCallback(LteInterferenceTestCase *testcase, std::string path, DlSchedulingCallbackInfo dlInfo)
void LteTestUlSchedulingCallback(LteInterferenceTestCase *testcase, std::string path, uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, uint8_t mcs, uint16_t sizeTb, uint8_t ccId)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
mobility
Definition: third.py:105
DlSchedulingCallbackInfo structure.
Definition: lte-common.h:237
uint32_t subframeNo
subframe number
Definition: lte-common.h:239
uint16_t sizeTb2
size TB2
Definition: lte-common.h:244
uint16_t sizeTb1
size TB1
Definition: lte-common.h:242
uint32_t frameNo
frame number
Definition: lte-common.h:238