A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lte-test-carrier-aggregation.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 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: Biljana Bojovic <bbojovic@cttc.es>
18 *
19 */
20
22
23#include "ns3/double.h"
24#include "ns3/ff-mac-scheduler.h"
25#include "ns3/radio-bearer-stats-calculator.h"
26#include "ns3/string.h"
27#include <ns3/boolean.h>
28#include <ns3/config-store-module.h>
29#include <ns3/constant-position-mobility-model.h>
30#include <ns3/enum.h>
31#include <ns3/eps-bearer.h>
32#include <ns3/log.h>
33#include <ns3/lte-enb-net-device.h>
34#include <ns3/lte-enb-phy.h>
35#include <ns3/lte-helper.h>
36#include <ns3/lte-ue-net-device.h>
37#include <ns3/lte-ue-phy.h>
38#include <ns3/lte-ue-rrc.h>
39#include <ns3/mobility-helper.h>
40#include <ns3/net-device-container.h>
41#include <ns3/node-container.h>
42#include <ns3/object.h>
43#include <ns3/packet.h>
44#include <ns3/ptr.h>
45#include <ns3/simulator.h>
46#include <ns3/spectrum-error-model.h>
47#include <ns3/spectrum-interference.h>
48#include <ns3/test.h>
49
50#include <errno.h>
51#include <iostream>
52
53using namespace ns3;
54
55NS_LOG_COMPONENT_DEFINE("TestCarrierAggregation");
56
57bool CarrierAggregationTestCase::s_writeResults = false; // set to true to write response vectors
58const std::string dlResultsFileName = "carrier_aggregation_results_dl.txt";
59const std::string ulResultsFileName = "carrier_aggregation_results_ul.txt";
60
61void
63 std::string path,
65{
66 testcase->DlScheduling(dlInfo);
67}
68
69void
71 std::string path,
72 uint32_t frameNo,
73 uint32_t subframeNo,
74 uint16_t rnti,
75 uint8_t mcs,
76 uint16_t sizeTb,
77 uint8_t ccId)
78{
79 testcase->UlScheduling(frameNo, subframeNo, rnti, mcs, sizeTb, ccId);
80}
81
83 : TestSuite("lte-carrier-aggregation", SYSTEM)
84{
85 NS_LOG_INFO("creating CarrierAggregationTestCase");
86
87 if (CarrierAggregationTestCase::s_writeResults) // write result vectors to file
88 {
89 std::cout << "\n Running TestCarrierAggregationSuite with activated option to write "
90 "results to files."
91 "Dl results will be written to "
92 << dlResultsFileName << " and uplink results to " << ulResultsFileName
93 << std::endl;
94
95 bool abort = false;
96
97 if (fopen(dlResultsFileName.c_str(), "r"))
98 {
99 std::cout << "\nResults file " << dlResultsFileName
100 << " already exists. Move it out of the way or specify another downlink "
101 "results file name."
102 << std::endl;
103 abort = true;
104 }
105 if (fopen(ulResultsFileName.c_str(), "r"))
106 {
107 std::cout << "\nResults file " << ulResultsFileName
108 << " already exists. Move it out of the way or specify another uplink "
109 "results file name."
110 << std::endl;
111 abort = true;
112 }
113
114 if (abort)
115 {
116 return;
117 }
118
125
132
139 }
140 else
141 {
142 // bandwidth is 25 and there are 2 carriers
149
156
163
169 AddTestCase(new CarrierAggregationTestCase(15, 20000, 25, 25, 2), TestCase::QUICK);
170
171 // bandwidth is 25 and there are 3 carriers
178
185
192
199
200 // bandwidth = 6 RB and there are 3 carriers
207
226
227 // bandwidth = 6 RB and there are 2 carriers
234
241
248
255 }
256}
257
263
264std::string
266 uint16_t dist,
267 uint32_t dlBandwidth,
268 uint32_t ulBandwidth,
269 uint32_t numberOfComponentCarriers)
270{
271 std::ostringstream oss;
272 oss << nUser << " UEs, distance " << dist << " m"
273 << " dlBandwidth " << dlBandwidth << " ulBandwidth " << ulBandwidth
274 << " number of carriers " << numberOfComponentCarriers;
275 return oss.str();
276}
277
279 uint16_t dist,
280 uint32_t dlbandwidth,
281 uint32_t ulBandwidth,
282 uint32_t numberOfComponentCarriers)
283 : TestCase(BuildNameString(nUser, dist, dlbandwidth, ulBandwidth, numberOfComponentCarriers)),
284 m_nUser(nUser),
285 m_dist(dist),
286 m_dlBandwidth(dlbandwidth),
287 m_ulBandwidth(ulBandwidth),
288 m_numberOfComponentCarriers(numberOfComponentCarriers)
289{
290 m_dlThroughput = 0;
291 m_statsDuration = 0.6;
292}
293
295{
296}
297
298void
300{
303
304 Config::SetDefault("ns3::LteEnbNetDevice::DlEarfcn", UintegerValue(100));
305 Config::SetDefault("ns3::LteEnbNetDevice::UlEarfcn", UintegerValue(100 + 18000));
306 Config::SetDefault("ns3::LteEnbNetDevice::DlBandwidth", UintegerValue(m_dlBandwidth));
307 Config::SetDefault("ns3::LteEnbNetDevice::UlBandwidth", UintegerValue(m_ulBandwidth));
308 Config::SetDefault("ns3::LteUeNetDevice::DlEarfcn", UintegerValue(100));
309
310 Config::SetDefault("ns3::LteHelper::UseCa", BooleanValue(true));
311 Config::SetDefault("ns3::LteHelper::NumberOfComponentCarriers",
313 Config::SetDefault("ns3::LteHelper::EnbComponentCarrierManager",
314 StringValue("ns3::RrComponentCarrierManager"));
315 Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
316 Config::SetDefault("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue(false));
317 Config::SetDefault("ns3::LteHelper::UseIdealRrc", BooleanValue(true));
318
319 Config::SetDefault("ns3::MacStatsCalculator::DlOutputFilename",
320 StringValue(CreateTempDirFilename("DlMacStats.txt")));
321 Config::SetDefault("ns3::MacStatsCalculator::UlOutputFilename",
322 StringValue(CreateTempDirFilename("UlMacStats.txt")));
323 Config::SetDefault("ns3::RadioBearerStatsCalculator::DlRlcOutputFilename",
324 StringValue(CreateTempDirFilename("DlRlcStats.txt")));
325 Config::SetDefault("ns3::RadioBearerStatsCalculator::UlRlcOutputFilename",
326 StringValue(CreateTempDirFilename("UlRlcStats.txt")));
327 Config::SetDefault("ns3::RadioBearerStatsCalculator::DlPdcpOutputFilename",
328 StringValue(CreateTempDirFilename("DlPdcpStats.txt")));
329 Config::SetDefault("ns3::RadioBearerStatsCalculator::UlPdcpOutputFilename",
330 StringValue(CreateTempDirFilename("UlPdcpStats.txt")));
331 Config::SetDefault("ns3::PhyStatsCalculator::DlRsrpSinrFilename",
332 StringValue(CreateTempDirFilename("DlRsrpSinrStats.txt")));
333 Config::SetDefault("ns3::PhyStatsCalculator::UlSinrFilename",
334 StringValue(CreateTempDirFilename("UlSinrStats.txt")));
335 Config::SetDefault("ns3::PhyStatsCalculator::UlInterferenceFilename",
336 StringValue(CreateTempDirFilename("UlInterferenceStats.txt")));
337 Config::SetDefault("ns3::PhyRxStatsCalculator::DlRxOutputFilename",
338 StringValue(CreateTempDirFilename("DlRxPhyStats.txt")));
339 Config::SetDefault("ns3::PhyRxStatsCalculator::UlRxOutputFilename",
340 StringValue(CreateTempDirFilename("UlRxPhyStats.txt")));
341 Config::SetDefault("ns3::PhyTxStatsCalculator::DlTxOutputFilename",
342 StringValue(CreateTempDirFilename("DlTxPhyStats.txt")));
343 Config::SetDefault("ns3::PhyTxStatsCalculator::UlTxOutputFilename",
344 StringValue(CreateTempDirFilename("UlTxPhyStats.txt")));
345
350 Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
351
352 lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
353
354 // Create Nodes: eNodeB and UE
355 NodeContainer enbNodes;
356 NodeContainer ueNodes;
357 enbNodes.Create(1);
358 ueNodes.Create(m_nUser);
359
360 // Install Mobility Model
361 MobilityHelper mobility;
362 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
363 mobility.Install(enbNodes);
364 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
365 mobility.Install(ueNodes);
366
367 // Create Devices and install them in the Nodes (eNB and UE)
368 NetDeviceContainer enbDevs;
369 NetDeviceContainer ueDevs;
370 lteHelper->SetSchedulerType("ns3::PfFfMacScheduler");
371 lteHelper->SetSchedulerAttribute("UlCqiFilter", EnumValue(FfMacScheduler::SRS_UL_CQI));
372 enbDevs = lteHelper->InstallEnbDevice(enbNodes);
373 ueDevs = lteHelper->InstallUeDevice(ueNodes);
374
375 // Attach a UE to a eNB
376 lteHelper->Attach(ueDevs, enbDevs.Get(0));
377
378 // Activate an EPS bearer
380 EpsBearer bearer(q);
381 lteHelper->ActivateDataRadioBearer(ueDevs, bearer);
382
383 Ptr<LteEnbNetDevice> lteEnbDev = enbDevs.Get(0)->GetObject<LteEnbNetDevice>();
384 Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy();
385 enbPhy->SetAttribute("TxPower", DoubleValue(30.0));
386 enbPhy->SetAttribute("NoiseFigure", DoubleValue(5.0));
387
388 // Set UEs' position and power
389 for (int i = 0; i < m_nUser; i++)
390 {
393 mm->SetPosition(Vector(m_dist, 0.0, 0.0));
394 Ptr<LteUeNetDevice> lteUeDev = ueDevs.Get(i)->GetObject<LteUeNetDevice>();
395 Ptr<LteUePhy> uePhy = lteUeDev->GetPhy();
396 uePhy->SetAttribute("TxPower", DoubleValue(23.0));
397 uePhy->SetAttribute("NoiseFigure", DoubleValue(9.0));
398 }
399
400 double statsStartTime = 0.300; // need to allow for RRC connection establishment + SRS
401
402 Simulator::Stop(Seconds(statsStartTime + m_statsDuration - 0.0001));
403
404 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMap/*/LteEnbMac/DlScheduling",
406
407 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMap/*/LteEnbMac/UlScheduling",
409
410 lteHelper->EnableTraces();
411
413
417 NS_LOG_INFO("DL - Test with " << m_nUser << " user(s) at distance " << m_dist);
418 std::vector<uint64_t> dlDataRxed;
419
420 // tolerance increases with the number of users because the lc 0 and lc 1 will go always over
421 // primary carrier, so as the number of users increases the difference between primary and
422 // secondary
423 // carrier will increase
424
425 bool testDownlinkShare = true;
426
427 for (std::map<uint8_t, uint32_t>::iterator itDownlink = m_ccDownlinkTraffic.begin();
428 itDownlink != m_ccDownlinkTraffic.end();
429 itDownlink++)
430 {
431 if (itDownlink == m_ccDownlinkTraffic.begin())
432 {
433 NS_LOG_INFO("Downlink traffic per carrier:" << itDownlink->second);
434 }
435 else
436 {
437 if (itDownlink->second != m_ccDownlinkTraffic.begin()->second)
438 {
439 testDownlinkShare = false;
440 break;
441 }
442 }
443 }
444
445 bool testUplinkShare = true;
446
447 for (std::map<uint8_t, uint32_t>::iterator itUplink = m_ccUplinkTraffic.begin();
448 itUplink != m_ccUplinkTraffic.end();
449 itUplink++)
450 {
451 if (itUplink == m_ccUplinkTraffic.begin())
452 {
453 NS_LOG_INFO("Uplink traffic per carrier:" << itUplink->second);
454 }
455 else
456 {
457 if (itUplink->second != m_ccUplinkTraffic.begin()->second)
458 {
459 testUplinkShare = false;
460 break;
461 }
462 }
463 }
464
467 "Number of carriers in uplink does not correspond to number of carriers "
468 "being configured in test.");
471 "Number of carriers in downlink does not correspond to number of "
472 "carriers being configured in test.");
473
474 NS_TEST_ASSERT_MSG_EQ(testDownlinkShare,
475 true,
476 " Downlink traffic not split equally between carriers!");
477 NS_TEST_ASSERT_MSG_EQ(testUplinkShare,
478 true,
479 " Uplink traffic not split equally between carriers");
480
481 if (s_writeResults)
482 {
484 }
485
487}
488
489void
491{
492 // NS_LOG_FUNCTION (dlInfo.frameNo << dlInfo.subframeNo << dlInfo.rnti << (uint32_t)
493 // dlInfo.mcsTb1 << dlInfo.sizeTb1 << (uint32_t) dlInfo.mcsTb2 <<
494 // dlInfo.sizeTb2<<(uint16_t)dlInfo.componentCarrierId);
495 // need to allow for RRC connection establishment + CQI feedback reception + persistent data
496 // transmission
497 if (Simulator::Now() > MilliSeconds(300))
498 {
500 {
501 m_ccDownlinkTraffic.insert(
502 std::pair<uint8_t, uint32_t>(dlInfo.componentCarrierId,
503 dlInfo.sizeTb1 + dlInfo.sizeTb2));
504 }
505 else
506 {
507 m_ccDownlinkTraffic[dlInfo.componentCarrierId] += (dlInfo.sizeTb1 + dlInfo.sizeTb2);
508 }
509
510 m_dlThroughput += dlInfo.sizeTb1 + dlInfo.sizeTb2;
511 }
512}
513
514void
516 uint32_t subframeNo,
517 uint16_t rnti,
518 uint8_t mcs,
519 uint16_t sizeTb,
520 uint8_t componentCarrierId)
521{
522 // NS_LOG_FUNCTION (frameNo << subframeNo << rnti << (uint32_t) mcs << sizeTb);
523 // need to allow for RRC connection establishment + SRS transmission
524 if (Simulator::Now() > MilliSeconds(300))
525 {
526 if (m_ccUplinkTraffic.find(componentCarrierId) == m_ccUplinkTraffic.end())
527 {
528 m_ccUplinkTraffic.insert(std::pair<uint8_t, uint32_t>(componentCarrierId, sizeTb));
529 }
530 else
531 {
532 m_ccUplinkTraffic[componentCarrierId] += sizeTb;
533 }
534
535 m_ulThroughput += sizeTb;
536 }
537}
538
539void
541{
542 std::ofstream dlOutFile;
543 dlOutFile.open(dlResultsFileName, std::ofstream::out | std::ofstream::app);
544 dlOutFile.setf(std::ios_base::fixed);
545
546 if (!dlOutFile.is_open())
547 {
548 NS_LOG_ERROR("Can't open file " << dlResultsFileName);
549 return;
550 }
551 dlOutFile << m_nUser << " " << m_numberOfComponentCarriers << " "
552 << ((m_dlThroughput * 8) / m_statsDuration) / m_nUser << std::endl;
553 dlOutFile.close();
554
555 std::ofstream ulOutFile;
556 ulOutFile.open(ulResultsFileName, std::ofstream::out | std::ofstream::app);
557 ulOutFile.setf(std::ios_base::fixed);
558
559 if (!ulOutFile.is_open())
560 {
561 NS_LOG_ERROR("Can't open file " << ulResultsFileName);
562 return;
563 }
564 ulOutFile << m_nUser << " " << m_numberOfComponentCarriers << " "
565 << ((m_ulThroughput * 8) / m_statsDuration) / m_nUser << std::endl;
566 ulOutFile.close();
567}
This system test program creates different test cases with a single eNB and several UEs,...
void DoRun() override
Implementation to actually run this TestCase.
uint32_t m_numberOfComponentCarriers
number of component carriers
void DlScheduling(DlSchedulingCallbackInfo dlInfo)
DL Scheduling function that is used in this test as callback function of DL scheduling trace.
static bool s_writeResults
write results flag, determines whether to write results to outoput files
CarrierAggregationTestCase(uint16_t nUser, uint16_t dist, uint32_t dlbandwidth, uint32_t ulBandwidth, uint32_t numberOfComponentCarriers)
Constructor of test case.
uint16_t m_nUser
the number of users
std::map< uint8_t, uint32_t > m_ccDownlinkTraffic
CC DL traffic.
void UlScheduling(uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, uint8_t mcs, uint16_t sizeTb, uint8_t componentCarrierId)
UL Scheduling function that is used in this test as callback function of UL sceduling trace.
void WriteResultToFile() const
Write result to file function.
static std::string BuildNameString(uint16_t nUser, uint16_t dist, uint32_t dlBandwidth, uint32_t ulBandwidth, uint32_t numberOfComponentCarriers)
Builds the test name string based on provided parameter values.
std::map< uint8_t, uint32_t > m_ccUplinkTraffic
CC UL traffic.
Test Carrier Aggregation Suite.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Mobility model for which the current position does not change once it has been set and until it is se...
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:56
This class contains the specification of EPS Bearers.
Definition: eps-bearer.h:91
Qci
QoS Class Indicator.
Definition: eps-bearer.h:106
@ GBR_CONV_VOICE
GBR Conversational Voice.
Definition: eps-bearer.h:107
The eNodeB device implementation.
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.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static void Run()
Run the simulation.
Definition: simulator.cc:176
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:184
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
@ EXTENSIVE
Medium length test.
Definition: test.h:1066
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
std::string CreateTempDirFilename(std::string filename)
Construct the full path to a file in a temporary directory.
Definition: test.cc:442
A suite of tests to run.
Definition: test.h:1256
Hold an unsigned integer type.
Definition: uinteger.h:45
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:891
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#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 TestCarrierAggregationSuite lenaTestRrFfMacSchedulerSuite
Static variable for test initialization.
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:768
#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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
const std::string ulResultsFileName
const std::string dlResultsFileName
void LteTestUlSchedulingCallback(CarrierAggregationTestCase *testcase, std::string path, uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, uint8_t mcs, uint16_t sizeTb, uint8_t ccId)
void LteTestDlSchedulingCallback(CarrierAggregationTestCase *testcase, std::string path, DlSchedulingCallbackInfo dlInfo)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
DlSchedulingCallbackInfo structure.
Definition: lte-common.h:231
uint16_t sizeTb2
size TB2
Definition: lte-common.h:238
uint16_t sizeTb1
size TB1
Definition: lte-common.h:236
uint8_t componentCarrierId
component carrier ID
Definition: lte-common.h:239