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#include <map>
53
54using namespace ns3;
55
56NS_LOG_COMPONENT_DEFINE("TestCarrierAggregation");
57
58bool CarrierAggregationTestCase::s_writeResults = false; // set to true to write response vectors
59const std::string dlResultsFileName = "carrier_aggregation_results_dl.txt";
60const std::string ulResultsFileName = "carrier_aggregation_results_ul.txt";
61
62void
64 std::string path,
66{
67 testcase->DlScheduling(dlInfo);
68}
69
70void
72 std::string path,
73 uint32_t frameNo,
74 uint32_t subframeNo,
75 uint16_t rnti,
76 uint8_t mcs,
77 uint16_t sizeTb,
78 uint8_t ccId)
79{
80 testcase->UlScheduling(frameNo, subframeNo, rnti, mcs, sizeTb, ccId);
81}
82
84 : TestSuite("lte-carrier-aggregation", SYSTEM)
85{
86 NS_LOG_INFO("creating CarrierAggregationTestCase");
87
88 if (CarrierAggregationTestCase::s_writeResults) // write result vectors to file
89 {
90 std::cout << "\n Running TestCarrierAggregationSuite with activated option to write "
91 "results to files."
92 "Dl results will be written to "
93 << dlResultsFileName << " and uplink results to " << ulResultsFileName
94 << std::endl;
95
96 bool abort = false;
97
98 if (fopen(dlResultsFileName.c_str(), "r"))
99 {
100 std::cout << "\nResults file " << dlResultsFileName
101 << " already exists. Move it out of the way or specify another downlink "
102 "results file name."
103 << std::endl;
104 abort = true;
105 }
106 if (fopen(ulResultsFileName.c_str(), "r"))
107 {
108 std::cout << "\nResults file " << ulResultsFileName
109 << " already exists. Move it out of the way or specify another uplink "
110 "results file name."
111 << std::endl;
112 abort = true;
113 }
114
115 if (abort)
116 {
117 return;
118 }
119
126
133
140 }
141 else
142 {
143 // bandwidth is 25 and there are 2 carriers
150
157
164
170 AddTestCase(new CarrierAggregationTestCase(15, 20000, 25, 25, 2), TestCase::QUICK);
171
172 // bandwidth is 25 and there are 3 carriers
179
186
193
200
201 // bandwidth = 6 RB and there are 3 carriers
208
227
228 // bandwidth = 6 RB and there are 2 carriers
235
242
249
256 }
257}
258
264
265std::string
267 uint16_t dist,
268 uint32_t dlBandwidth,
269 uint32_t ulBandwidth,
270 uint32_t numberOfComponentCarriers)
271{
272 std::ostringstream oss;
273 oss << nUser << " UEs, distance " << dist << " m"
274 << " dlBandwidth " << dlBandwidth << " ulBandwidth " << ulBandwidth
275 << " number of carriers " << numberOfComponentCarriers;
276 return oss.str();
277}
278
280 uint16_t dist,
281 uint32_t dlbandwidth,
282 uint32_t ulBandwidth,
283 uint32_t numberOfComponentCarriers)
284 : TestCase(BuildNameString(nUser, dist, dlbandwidth, ulBandwidth, numberOfComponentCarriers)),
285 m_nUser(nUser),
286 m_dist(dist),
287 m_dlBandwidth(dlbandwidth),
288 m_ulBandwidth(ulBandwidth),
289 m_numberOfComponentCarriers(numberOfComponentCarriers)
290{
291 m_dlThroughput = 0;
292 m_statsDuration = 0.6;
293}
294
296{
297}
298
299void
301{
304
305 Config::SetDefault("ns3::LteEnbNetDevice::DlEarfcn", UintegerValue(100));
306 Config::SetDefault("ns3::LteEnbNetDevice::UlEarfcn", UintegerValue(100 + 18000));
307 Config::SetDefault("ns3::LteEnbNetDevice::DlBandwidth", UintegerValue(m_dlBandwidth));
308 Config::SetDefault("ns3::LteEnbNetDevice::UlBandwidth", UintegerValue(m_ulBandwidth));
309 Config::SetDefault("ns3::LteUeNetDevice::DlEarfcn", UintegerValue(100));
310
311 Config::SetDefault("ns3::LteHelper::UseCa", BooleanValue(true));
312 Config::SetDefault("ns3::LteHelper::NumberOfComponentCarriers",
314 Config::SetDefault("ns3::LteHelper::EnbComponentCarrierManager",
315 StringValue("ns3::RrComponentCarrierManager"));
316 Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
317 Config::SetDefault("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue(false));
318 Config::SetDefault("ns3::LteHelper::UseIdealRrc", BooleanValue(true));
319
320 Config::SetDefault("ns3::MacStatsCalculator::DlOutputFilename",
321 StringValue(CreateTempDirFilename("DlMacStats.txt")));
322 Config::SetDefault("ns3::MacStatsCalculator::UlOutputFilename",
323 StringValue(CreateTempDirFilename("UlMacStats.txt")));
324 Config::SetDefault("ns3::RadioBearerStatsCalculator::DlRlcOutputFilename",
325 StringValue(CreateTempDirFilename("DlRlcStats.txt")));
326 Config::SetDefault("ns3::RadioBearerStatsCalculator::UlRlcOutputFilename",
327 StringValue(CreateTempDirFilename("UlRlcStats.txt")));
328 Config::SetDefault("ns3::RadioBearerStatsCalculator::DlPdcpOutputFilename",
329 StringValue(CreateTempDirFilename("DlPdcpStats.txt")));
330 Config::SetDefault("ns3::RadioBearerStatsCalculator::UlPdcpOutputFilename",
331 StringValue(CreateTempDirFilename("UlPdcpStats.txt")));
332 Config::SetDefault("ns3::PhyStatsCalculator::DlRsrpSinrFilename",
333 StringValue(CreateTempDirFilename("DlRsrpSinrStats.txt")));
334 Config::SetDefault("ns3::PhyStatsCalculator::UlSinrFilename",
335 StringValue(CreateTempDirFilename("UlSinrStats.txt")));
336 Config::SetDefault("ns3::PhyStatsCalculator::UlInterferenceFilename",
337 StringValue(CreateTempDirFilename("UlInterferenceStats.txt")));
338 Config::SetDefault("ns3::PhyRxStatsCalculator::DlRxOutputFilename",
339 StringValue(CreateTempDirFilename("DlRxPhyStats.txt")));
340 Config::SetDefault("ns3::PhyRxStatsCalculator::UlRxOutputFilename",
341 StringValue(CreateTempDirFilename("UlRxPhyStats.txt")));
342 Config::SetDefault("ns3::PhyTxStatsCalculator::DlTxOutputFilename",
343 StringValue(CreateTempDirFilename("DlTxPhyStats.txt")));
344 Config::SetDefault("ns3::PhyTxStatsCalculator::UlTxOutputFilename",
345 StringValue(CreateTempDirFilename("UlTxPhyStats.txt")));
346
351 Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
352
353 lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
354
355 // Create Nodes: eNodeB and UE
356 NodeContainer enbNodes;
357 NodeContainer ueNodes;
358 enbNodes.Create(1);
359 ueNodes.Create(m_nUser);
360
361 // Install Mobility Model
362 MobilityHelper mobility;
363 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
364 mobility.Install(enbNodes);
365 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
366 mobility.Install(ueNodes);
367
368 // Create Devices and install them in the Nodes (eNB and UE)
369 NetDeviceContainer enbDevs;
370 NetDeviceContainer ueDevs;
371 lteHelper->SetSchedulerType("ns3::PfFfMacScheduler");
372 lteHelper->SetSchedulerAttribute("UlCqiFilter", EnumValue(FfMacScheduler::SRS_UL_CQI));
373 enbDevs = lteHelper->InstallEnbDevice(enbNodes);
374 ueDevs = lteHelper->InstallUeDevice(ueNodes);
375
376 // Attach a UE to a eNB
377 lteHelper->Attach(ueDevs, enbDevs.Get(0));
378
379 // Activate an EPS bearer
381 EpsBearer bearer(q);
382 lteHelper->ActivateDataRadioBearer(ueDevs, bearer);
383
384 Ptr<LteEnbNetDevice> lteEnbDev = enbDevs.Get(0)->GetObject<LteEnbNetDevice>();
385 Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy();
386 enbPhy->SetAttribute("TxPower", DoubleValue(30.0));
387 enbPhy->SetAttribute("NoiseFigure", DoubleValue(5.0));
388
389 // Set UEs' position and power
390 for (int i = 0; i < m_nUser; i++)
391 {
394 mm->SetPosition(Vector(m_dist, 0.0, 0.0));
395 Ptr<LteUeNetDevice> lteUeDev = ueDevs.Get(i)->GetObject<LteUeNetDevice>();
396 Ptr<LteUePhy> uePhy = lteUeDev->GetPhy();
397 uePhy->SetAttribute("TxPower", DoubleValue(23.0));
398 uePhy->SetAttribute("NoiseFigure", DoubleValue(9.0));
399 }
400
401 double statsStartTime = 0.300; // need to allow for RRC connection establishment + SRS
402
403 Simulator::Stop(Seconds(statsStartTime + m_statsDuration - 0.0001));
404
405 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMap/*/LteEnbMac/DlScheduling",
407
408 Config::Connect("/NodeList/*/DeviceList/*/ComponentCarrierMap/*/LteEnbMac/UlScheduling",
410
411 lteHelper->EnableTraces();
412
414
418 NS_LOG_INFO("DL - Test with " << m_nUser << " user(s) at distance " << m_dist);
419 std::vector<uint64_t> dlDataRxed;
420
421 // tolerance increases with the number of users because the lc 0 and lc 1 will go always over
422 // primary carrier, so as the number of users increases the difference between primary and
423 // secondary
424 // carrier will increase
425
426 bool testDownlinkShare = true;
427
428 for (std::map<uint8_t, uint32_t>::iterator itDownlink = m_ccDownlinkTraffic.begin();
429 itDownlink != m_ccDownlinkTraffic.end();
430 itDownlink++)
431 {
432 if (itDownlink == m_ccDownlinkTraffic.begin())
433 {
434 NS_LOG_INFO("Downlink traffic per carrier:" << itDownlink->second);
435 }
436 else
437 {
438 if (itDownlink->second != m_ccDownlinkTraffic.begin()->second)
439 {
440 testDownlinkShare = false;
441 break;
442 }
443 }
444 }
445
446 bool testUplinkShare = true;
447
448 for (std::map<uint8_t, uint32_t>::iterator itUplink = m_ccUplinkTraffic.begin();
449 itUplink != m_ccUplinkTraffic.end();
450 itUplink++)
451 {
452 if (itUplink == m_ccUplinkTraffic.begin())
453 {
454 NS_LOG_INFO("Uplink traffic per carrier:" << itUplink->second);
455 }
456 else
457 {
458 if (itUplink->second != m_ccUplinkTraffic.begin()->second)
459 {
460 testUplinkShare = false;
461 break;
462 }
463 }
464 }
465
468 "Number of carriers in uplink does not correspond to number of carriers "
469 "being configured in test.");
472 "Number of carriers in downlink does not correspond to number of "
473 "carriers being configured in test.");
474
475 NS_TEST_ASSERT_MSG_EQ(testDownlinkShare,
476 true,
477 " Downlink traffic not split equally between carriers!");
478 NS_TEST_ASSERT_MSG_EQ(testUplinkShare,
479 true,
480 " Uplink traffic not split equally between carriers");
481
482 if (s_writeResults)
483 {
485 }
486
488}
489
490void
492{
493 // NS_LOG_FUNCTION (dlInfo.frameNo << dlInfo.subframeNo << dlInfo.rnti << (uint32_t)
494 // dlInfo.mcsTb1 << dlInfo.sizeTb1 << (uint32_t) dlInfo.mcsTb2 <<
495 // dlInfo.sizeTb2<<(uint16_t)dlInfo.componentCarrierId);
496 // need to allow for RRC connection establishment + CQI feedback reception + persistent data
497 // transmission
498 if (Simulator::Now() > MilliSeconds(300))
499 {
501 {
502 m_ccDownlinkTraffic.insert(
503 std::pair<uint8_t, uint32_t>(dlInfo.componentCarrierId,
504 dlInfo.sizeTb1 + dlInfo.sizeTb2));
505 }
506 else
507 {
508 m_ccDownlinkTraffic[dlInfo.componentCarrierId] += (dlInfo.sizeTb1 + dlInfo.sizeTb2);
509 }
510
511 m_dlThroughput += dlInfo.sizeTb1 + dlInfo.sizeTb2;
512 }
513}
514
515void
517 uint32_t subframeNo,
518 uint16_t rnti,
519 uint8_t mcs,
520 uint16_t sizeTb,
521 uint8_t componentCarrierId)
522{
523 // NS_LOG_FUNCTION (frameNo << subframeNo << rnti << (uint32_t) mcs << sizeTb);
524 // need to allow for RRC connection establishment + SRS transmission
525 if (Simulator::Now() > MilliSeconds(300))
526 {
527 if (m_ccUplinkTraffic.find(componentCarrierId) == m_ccUplinkTraffic.end())
528 {
529 m_ccUplinkTraffic.insert(std::pair<uint8_t, uint32_t>(componentCarrierId, sizeTb));
530 }
531 else
532 {
533 m_ccUplinkTraffic[componentCarrierId] += sizeTb;
534 }
535
536 m_ulThroughput += sizeTb;
537 }
538}
539
540void
542{
543 std::ofstream dlOutFile;
544 dlOutFile.open(dlResultsFileName, std::ofstream::out | std::ofstream::app);
545 dlOutFile.setf(std::ios_base::fixed);
546
547 if (!dlOutFile.is_open())
548 {
549 NS_LOG_ERROR("Can't open file " << dlResultsFileName);
550 return;
551 }
552 dlOutFile << m_nUser << " " << m_numberOfComponentCarriers << " "
553 << ((m_dlThroughput * 8) / m_statsDuration) / m_nUser << std::endl;
554 dlOutFile.close();
555
556 std::ofstream ulOutFile;
557 ulOutFile.open(ulResultsFileName, std::ofstream::out | std::ofstream::app);
558 ulOutFile.setf(std::ios_base::fixed);
559
560 if (!ulOutFile.is_open())
561 {
562 NS_LOG_ERROR("Can't open file " << ulResultsFileName);
563 return;
564 }
565 ulOutFile << m_nUser << " " << m_numberOfComponentCarriers << " "
566 << ((m_ulThroughput * 8) / m_statsDuration) / m_nUser << std::endl;
567 ulOutFile.close();
568}
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:301
std::string CreateTempDirFilename(std::string filename)
Construct the full path to a file in a temporary directory.
Definition: test.cc:438
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:763
#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:237
uint16_t sizeTb2
size TB2
Definition: lte-common.h:244
uint16_t sizeTb1
size TB1
Definition: lte-common.h:242
uint8_t componentCarrierId
component carrier ID
Definition: lte-common.h:245