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/constant-position-mobility-model.h>
29#include <ns3/enum.h>
30#include <ns3/eps-bearer.h>
31#include <ns3/log.h>
32#include <ns3/lte-enb-net-device.h>
33#include <ns3/lte-enb-phy.h>
34#include <ns3/lte-helper.h>
35#include <ns3/lte-ue-net-device.h>
36#include <ns3/lte-ue-phy.h>
37#include <ns3/lte-ue-rrc.h>
38#include <ns3/mobility-helper.h>
39#include <ns3/net-device-container.h>
40#include <ns3/node-container.h>
41#include <ns3/object.h>
42#include <ns3/packet.h>
43#include <ns3/ptr.h>
44#include <ns3/simulator.h>
45#include <ns3/spectrum-error-model.h>
46#include <ns3/spectrum-interference.h>
47#include <ns3/test.h>
48
49#include <errno.h>
50#include <iostream>
51#include <map>
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 (auto itDownlink = m_ccDownlinkTraffic.begin(); itDownlink != m_ccDownlinkTraffic.end();
428 itDownlink++)
429 {
430 if (itDownlink == m_ccDownlinkTraffic.begin())
431 {
432 NS_LOG_INFO("Downlink traffic per carrier:" << itDownlink->second);
433 }
434 else
435 {
436 if (itDownlink->second != m_ccDownlinkTraffic.begin()->second)
437 {
438 testDownlinkShare = false;
439 break;
440 }
441 }
442 }
443
444 bool testUplinkShare = true;
445
446 for (auto itUplink = m_ccUplinkTraffic.begin(); itUplink != m_ccUplinkTraffic.end(); itUplink++)
447 {
448 if (itUplink == m_ccUplinkTraffic.begin())
449 {
450 NS_LOG_INFO("Uplink traffic per carrier:" << itUplink->second);
451 }
452 else
453 {
454 if (itUplink->second != m_ccUplinkTraffic.begin()->second)
455 {
456 testUplinkShare = false;
457 break;
458 }
459 }
460 }
461
464 "Number of carriers in uplink does not correspond to number of carriers "
465 "being configured in test.");
468 "Number of carriers in downlink does not correspond to number of "
469 "carriers being configured in test.");
470
471 NS_TEST_ASSERT_MSG_EQ(testDownlinkShare,
472 true,
473 " Downlink traffic not split equally between carriers!");
474 NS_TEST_ASSERT_MSG_EQ(testUplinkShare,
475 true,
476 " Uplink traffic not split equally between carriers");
477
478 if (s_writeResults)
479 {
481 }
482
484}
485
486void
488{
489 // NS_LOG_FUNCTION (dlInfo.frameNo << dlInfo.subframeNo << dlInfo.rnti << (uint32_t)
490 // dlInfo.mcsTb1 << dlInfo.sizeTb1 << (uint32_t) dlInfo.mcsTb2 <<
491 // dlInfo.sizeTb2<<(uint16_t)dlInfo.componentCarrierId);
492 // need to allow for RRC connection establishment + CQI feedback reception + persistent data
493 // transmission
494 if (Simulator::Now() > MilliSeconds(300))
495 {
497 {
498 m_ccDownlinkTraffic.insert(
499 std::pair<uint8_t, uint32_t>(dlInfo.componentCarrierId,
500 dlInfo.sizeTb1 + dlInfo.sizeTb2));
501 }
502 else
503 {
504 m_ccDownlinkTraffic[dlInfo.componentCarrierId] += (dlInfo.sizeTb1 + dlInfo.sizeTb2);
505 }
506
507 m_dlThroughput += dlInfo.sizeTb1 + dlInfo.sizeTb2;
508 }
509}
510
511void
513 uint32_t subframeNo,
514 uint16_t rnti,
515 uint8_t mcs,
516 uint16_t sizeTb,
517 uint8_t componentCarrierId)
518{
519 // NS_LOG_FUNCTION (frameNo << subframeNo << rnti << (uint32_t) mcs << sizeTb);
520 // need to allow for RRC connection establishment + SRS transmission
521 if (Simulator::Now() > MilliSeconds(300))
522 {
523 if (m_ccUplinkTraffic.find(componentCarrierId) == m_ccUplinkTraffic.end())
524 {
525 m_ccUplinkTraffic.insert(std::pair<uint8_t, uint32_t>(componentCarrierId, sizeTb));
526 }
527 else
528 {
529 m_ccUplinkTraffic[componentCarrierId] += sizeTb;
530 }
531
532 m_ulThroughput += sizeTb;
533 }
534}
535
536void
538{
539 std::ofstream dlOutFile;
540 dlOutFile.open(dlResultsFileName, std::ofstream::out | std::ofstream::app);
541 dlOutFile.setf(std::ios_base::fixed);
542
543 if (!dlOutFile.is_open())
544 {
545 NS_LOG_ERROR("Can't open file " << dlResultsFileName);
546 return;
547 }
548 dlOutFile << m_nUser << " " << m_numberOfComponentCarriers << " "
549 << ((m_dlThroughput * 8) / m_statsDuration) / m_nUser << std::endl;
550 dlOutFile.close();
551
552 std::ofstream ulOutFile;
553 ulOutFile.open(ulResultsFileName, std::ofstream::out | std::ofstream::app);
554 ulOutFile.setf(std::ios_base::fixed);
555
556 if (!ulOutFile.is_open())
557 {
558 NS_LOG_ERROR("Can't open file " << ulResultsFileName);
559 return;
560 }
561 ulOutFile << m_nUser << " " << m_numberOfComponentCarriers << " "
562 << ((m_ulThroughput * 8) / m_statsDuration) / m_nUser << std::endl;
563 ulOutFile.close();
564}
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:62
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:77
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
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:890
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:974
#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:765
#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:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
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