404 lines
17 KiB
C++
404 lines
17 KiB
C++
/*
|
|
* Copyright (c) 2014 Piotr Gawlowicz
|
|
*
|
|
* 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: Piotr Gawlowicz <gawlowicz.p@gmail.com>
|
|
*
|
|
*/
|
|
|
|
#include "ns3/applications-module.h"
|
|
#include "ns3/core-module.h"
|
|
#include "ns3/internet-module.h"
|
|
#include "ns3/log.h"
|
|
#include "ns3/lte-module.h"
|
|
#include "ns3/mobility-module.h"
|
|
#include "ns3/network-module.h"
|
|
#include "ns3/point-to-point-epc-helper.h"
|
|
#include "ns3/point-to-point-module.h"
|
|
#include "ns3/spectrum-module.h"
|
|
#include <ns3/buildings-helper.h>
|
|
|
|
using namespace ns3;
|
|
|
|
NS_LOG_COMPONENT_DEFINE("LenaDistributedFrequencyReuse");
|
|
|
|
void
|
|
PrintGnuplottableUeListToFile(std::string filename)
|
|
{
|
|
std::ofstream outFile;
|
|
outFile.open(filename, std::ios_base::out | std::ios_base::trunc);
|
|
if (!outFile.is_open())
|
|
{
|
|
NS_LOG_ERROR("Can't open file " << filename);
|
|
return;
|
|
}
|
|
for (auto it = NodeList::Begin(); it != NodeList::End(); ++it)
|
|
{
|
|
Ptr<Node> node = *it;
|
|
int nDevs = node->GetNDevices();
|
|
for (int j = 0; j < nDevs; j++)
|
|
{
|
|
Ptr<LteUeNetDevice> uedev = node->GetDevice(j)->GetObject<LteUeNetDevice>();
|
|
if (uedev)
|
|
{
|
|
Vector pos = node->GetObject<MobilityModel>()->GetPosition();
|
|
outFile << "set label \"" << uedev->GetImsi() << "\" at " << pos.x << "," << pos.y
|
|
<< " left font \"Helvetica,4\" textcolor rgb \"grey\" front point pt 1 ps "
|
|
"0.3 lc rgb \"grey\" offset 0,0"
|
|
<< std::endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
PrintGnuplottableEnbListToFile(std::string filename)
|
|
{
|
|
std::ofstream outFile;
|
|
outFile.open(filename, std::ios_base::out | std::ios_base::trunc);
|
|
if (!outFile.is_open())
|
|
{
|
|
NS_LOG_ERROR("Can't open file " << filename);
|
|
return;
|
|
}
|
|
for (auto it = NodeList::Begin(); it != NodeList::End(); ++it)
|
|
{
|
|
Ptr<Node> node = *it;
|
|
int nDevs = node->GetNDevices();
|
|
for (int j = 0; j < nDevs; j++)
|
|
{
|
|
Ptr<LteEnbNetDevice> enbdev = node->GetDevice(j)->GetObject<LteEnbNetDevice>();
|
|
if (enbdev)
|
|
{
|
|
Vector pos = node->GetObject<MobilityModel>()->GetPosition();
|
|
outFile << "set label \"" << enbdev->GetCellId() << "\" at " << pos.x << ","
|
|
<< pos.y
|
|
<< " left font \"Helvetica,4\" textcolor rgb \"white\" front point pt 2 "
|
|
"ps 0.3 lc rgb \"white\" offset 0,0"
|
|
<< std::endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
main(int argc, char* argv[])
|
|
{
|
|
Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(true));
|
|
Config::SetDefault("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue(true));
|
|
Config::SetDefault("ns3::LteHelper::UseIdealRrc", BooleanValue(true));
|
|
Config::SetDefault("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue(true));
|
|
|
|
// Uplink Power Control
|
|
Config::SetDefault("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue(true));
|
|
Config::SetDefault("ns3::LteUePowerControl::ClosedLoop", BooleanValue(true));
|
|
Config::SetDefault("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue(false));
|
|
|
|
uint32_t runId = 3;
|
|
uint16_t numberOfRandomUes = 0;
|
|
double simTime = 5.000;
|
|
bool generateSpectrumTrace = false;
|
|
bool generateRem = false;
|
|
int32_t remRbId = -1;
|
|
uint16_t bandwidth = 25;
|
|
double distance = 1000;
|
|
Box macroUeBox =
|
|
Box(-distance * 0.5, distance * 1.5, -distance * 0.5, distance * 1.5, 1.5, 1.5);
|
|
|
|
// Command line arguments
|
|
CommandLine cmd(__FILE__);
|
|
cmd.AddValue("numberOfUes", "Number of UEs", numberOfRandomUes);
|
|
cmd.AddValue("simTime", "Total duration of the simulation (in seconds)", simTime);
|
|
cmd.AddValue("generateSpectrumTrace",
|
|
"if true, will generate a Spectrum Analyzer trace",
|
|
generateSpectrumTrace);
|
|
cmd.AddValue("generateRem",
|
|
"if true, will generate a REM and then abort the simulation",
|
|
generateRem);
|
|
cmd.AddValue("remRbId",
|
|
"Resource block Id, for which REM will be generated,"
|
|
"default value is -1, what means REM will be averaged from all RBs",
|
|
remRbId);
|
|
cmd.AddValue("runId", "runId", runId);
|
|
cmd.Parse(argc, argv);
|
|
|
|
RngSeedManager::SetSeed(1);
|
|
RngSeedManager::SetRun(runId);
|
|
|
|
Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
|
|
Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper>();
|
|
lteHelper->SetEpcHelper(epcHelper);
|
|
lteHelper->SetHandoverAlgorithmType("ns3::NoOpHandoverAlgorithm"); // disable automatic handover
|
|
|
|
Ptr<Node> pgw = epcHelper->GetPgwNode();
|
|
|
|
// Create a single RemoteHost
|
|
NodeContainer remoteHostContainer;
|
|
remoteHostContainer.Create(1);
|
|
Ptr<Node> remoteHost = remoteHostContainer.Get(0);
|
|
InternetStackHelper internet;
|
|
internet.Install(remoteHostContainer);
|
|
|
|
// Create the Internet
|
|
PointToPointHelper p2ph;
|
|
p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
|
|
p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
|
|
p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.010)));
|
|
NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
|
|
Ipv4AddressHelper ipv4h;
|
|
ipv4h.SetBase("1.0.0.0", "255.0.0.0");
|
|
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
|
|
Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress(1);
|
|
|
|
// Routing of the Internet Host (towards the LTE network)
|
|
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
|
Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
|
|
ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
|
|
// interface 0 is localhost, 1 is the p2p device
|
|
remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
|
|
|
|
// Create Nodes: eNodeB and UE
|
|
NodeContainer enbNodes;
|
|
NodeContainer randomUeNodes;
|
|
enbNodes.Create(3);
|
|
randomUeNodes.Create(numberOfRandomUes);
|
|
|
|
/* the topology is the following:
|
|
* eNB3
|
|
* / \
|
|
* / \
|
|
* / \
|
|
* / \
|
|
* distance / \ distance
|
|
* / UEs \
|
|
* / \
|
|
* / \
|
|
* / \
|
|
* / \
|
|
* eNB1-------------------------eNB2
|
|
* distance
|
|
*/
|
|
|
|
// Install Mobility Model
|
|
Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator>();
|
|
enbPositionAlloc->Add(Vector(0.0, 0.0, 0.0)); // eNB1
|
|
enbPositionAlloc->Add(Vector(distance, 0.0, 0.0)); // eNB2
|
|
enbPositionAlloc->Add(Vector(distance * 0.5, distance * 0.866, 0.0)); // eNB3
|
|
MobilityHelper mobility;
|
|
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
|
|
mobility.SetPositionAllocator(enbPositionAlloc);
|
|
mobility.Install(enbNodes);
|
|
|
|
Ptr<RandomBoxPositionAllocator> randomUePositionAlloc =
|
|
CreateObject<RandomBoxPositionAllocator>();
|
|
Ptr<UniformRandomVariable> xVal = CreateObject<UniformRandomVariable>();
|
|
xVal->SetAttribute("Min", DoubleValue(macroUeBox.xMin));
|
|
xVal->SetAttribute("Max", DoubleValue(macroUeBox.xMax));
|
|
randomUePositionAlloc->SetAttribute("X", PointerValue(xVal));
|
|
Ptr<UniformRandomVariable> yVal = CreateObject<UniformRandomVariable>();
|
|
yVal->SetAttribute("Min", DoubleValue(macroUeBox.yMin));
|
|
yVal->SetAttribute("Max", DoubleValue(macroUeBox.yMax));
|
|
randomUePositionAlloc->SetAttribute("Y", PointerValue(yVal));
|
|
Ptr<UniformRandomVariable> zVal = CreateObject<UniformRandomVariable>();
|
|
zVal->SetAttribute("Min", DoubleValue(macroUeBox.zMin));
|
|
zVal->SetAttribute("Max", DoubleValue(macroUeBox.zMax));
|
|
randomUePositionAlloc->SetAttribute("Z", PointerValue(zVal));
|
|
mobility.SetPositionAllocator(randomUePositionAlloc);
|
|
mobility.Install(randomUeNodes);
|
|
|
|
// Create Devices and install them in the Nodes (eNB and UE)
|
|
NetDeviceContainer enbDevs;
|
|
NetDeviceContainer randomUeDevs;
|
|
lteHelper->SetSchedulerType("ns3::PfFfMacScheduler");
|
|
lteHelper->SetSchedulerAttribute("HarqEnabled", BooleanValue(true));
|
|
|
|
lteHelper->SetEnbDeviceAttribute("DlBandwidth", UintegerValue(bandwidth));
|
|
lteHelper->SetEnbDeviceAttribute("UlBandwidth", UintegerValue(bandwidth));
|
|
|
|
lteHelper->SetFfrAlgorithmType("ns3::LteFfrDistributedAlgorithm");
|
|
lteHelper->SetFfrAlgorithmAttribute("CalculationInterval", TimeValue(MilliSeconds(200)));
|
|
lteHelper->SetFfrAlgorithmAttribute("RsrpDifferenceThreshold", UintegerValue(5));
|
|
lteHelper->SetFfrAlgorithmAttribute("RsrqThreshold", UintegerValue(25));
|
|
lteHelper->SetFfrAlgorithmAttribute("EdgeRbNum", UintegerValue(6));
|
|
lteHelper->SetFfrAlgorithmAttribute("CenterPowerOffset",
|
|
UintegerValue(LteRrcSap::PdschConfigDedicated::dB_3));
|
|
lteHelper->SetFfrAlgorithmAttribute("EdgePowerOffset",
|
|
UintegerValue(LteRrcSap::PdschConfigDedicated::dB3));
|
|
|
|
lteHelper->SetFfrAlgorithmAttribute("CenterAreaTpc", UintegerValue(0));
|
|
lteHelper->SetFfrAlgorithmAttribute("EdgeAreaTpc", UintegerValue(3));
|
|
|
|
// ns3::LteFfrDistributedAlgorithm works with Absolute Mode Uplink Power Control
|
|
Config::SetDefault("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue(false));
|
|
|
|
enbDevs = lteHelper->InstallEnbDevice(enbNodes);
|
|
randomUeDevs = lteHelper->InstallUeDevice(randomUeNodes);
|
|
|
|
// Add X2 interface
|
|
lteHelper->AddX2Interface(enbNodes);
|
|
|
|
NodeContainer ueNodes;
|
|
ueNodes.Add(randomUeNodes);
|
|
NetDeviceContainer ueDevs;
|
|
ueDevs.Add(randomUeDevs);
|
|
|
|
// Install the IP stack on the UEs
|
|
internet.Install(ueNodes);
|
|
Ipv4InterfaceContainer ueIpIfaces;
|
|
ueIpIfaces = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueDevs));
|
|
|
|
// Attach a UE to a eNB
|
|
lteHelper->AttachToClosestEnb(ueDevs, enbDevs);
|
|
|
|
// Install and start applications on UEs and remote host
|
|
uint16_t dlPort = 10000;
|
|
uint16_t ulPort = 20000;
|
|
|
|
// randomize a bit start times to avoid simulation artifacts
|
|
// (e.g., buffer overflows due to packet transmissions happening
|
|
// exactly at the same time)
|
|
Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable>();
|
|
startTimeSeconds->SetAttribute("Min", DoubleValue(0));
|
|
startTimeSeconds->SetAttribute("Max", DoubleValue(0.010));
|
|
|
|
for (uint32_t u = 0; u < ueNodes.GetN(); ++u)
|
|
{
|
|
Ptr<Node> ue = ueNodes.Get(u);
|
|
// Set the default gateway for the UE
|
|
Ptr<Ipv4StaticRouting> ueStaticRouting =
|
|
ipv4RoutingHelper.GetStaticRouting(ue->GetObject<Ipv4>());
|
|
ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
|
|
|
|
for (uint32_t b = 0; b < 1; ++b)
|
|
{
|
|
++dlPort;
|
|
++ulPort;
|
|
|
|
ApplicationContainer clientApps;
|
|
ApplicationContainer serverApps;
|
|
|
|
UdpClientHelper dlClientHelper(ueIpIfaces.GetAddress(u), dlPort);
|
|
dlClientHelper.SetAttribute("MaxPackets", UintegerValue(1000000));
|
|
dlClientHelper.SetAttribute("Interval", TimeValue(MilliSeconds(1.0)));
|
|
clientApps.Add(dlClientHelper.Install(remoteHost));
|
|
PacketSinkHelper dlPacketSinkHelper("ns3::UdpSocketFactory",
|
|
InetSocketAddress(Ipv4Address::GetAny(), dlPort));
|
|
serverApps.Add(dlPacketSinkHelper.Install(ue));
|
|
|
|
UdpClientHelper ulClientHelper(remoteHostAddr, ulPort);
|
|
ulClientHelper.SetAttribute("MaxPackets", UintegerValue(1000000));
|
|
ulClientHelper.SetAttribute("Interval", TimeValue(MilliSeconds(1.0)));
|
|
clientApps.Add(ulClientHelper.Install(ue));
|
|
PacketSinkHelper ulPacketSinkHelper("ns3::UdpSocketFactory",
|
|
InetSocketAddress(Ipv4Address::GetAny(), ulPort));
|
|
serverApps.Add(ulPacketSinkHelper.Install(remoteHost));
|
|
|
|
Ptr<EpcTft> tft = Create<EpcTft>();
|
|
EpcTft::PacketFilter dlpf;
|
|
dlpf.localPortStart = dlPort;
|
|
dlpf.localPortEnd = dlPort;
|
|
tft->Add(dlpf);
|
|
EpcTft::PacketFilter ulpf;
|
|
ulpf.remotePortStart = ulPort;
|
|
ulpf.remotePortEnd = ulPort;
|
|
tft->Add(ulpf);
|
|
EpsBearer bearer(EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
|
|
lteHelper->ActivateDedicatedEpsBearer(ueDevs.Get(u), bearer, tft);
|
|
|
|
Time startTime = Seconds(startTimeSeconds->GetValue());
|
|
serverApps.Start(startTime);
|
|
clientApps.Start(startTime);
|
|
}
|
|
}
|
|
|
|
// Spectrum analyzer
|
|
NodeContainer spectrumAnalyzerNodes;
|
|
spectrumAnalyzerNodes.Create(1);
|
|
SpectrumAnalyzerHelper spectrumAnalyzerHelper;
|
|
|
|
if (generateSpectrumTrace)
|
|
{
|
|
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
|
|
// position of Spectrum Analyzer
|
|
positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // eNB1
|
|
// positionAlloc->Add (Vector (distance, 0.0, 0.0)); // eNB2
|
|
// positionAlloc->Add (Vector (distance*0.5, distance*0.866, 0.0)); // eNB3
|
|
|
|
MobilityHelper mobility;
|
|
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
|
|
mobility.SetPositionAllocator(positionAlloc);
|
|
mobility.Install(spectrumAnalyzerNodes);
|
|
|
|
Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get(0)
|
|
->GetObject<LteEnbNetDevice>()
|
|
->GetPhy()
|
|
->GetDownlinkSpectrumPhy()
|
|
->GetObject<LteSpectrumPhy>();
|
|
Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel();
|
|
|
|
spectrumAnalyzerHelper.SetChannel(dlChannel);
|
|
Ptr<SpectrumModel> sm = LteSpectrumValueHelper::GetSpectrumModel(100, bandwidth);
|
|
spectrumAnalyzerHelper.SetRxSpectrumModel(sm);
|
|
spectrumAnalyzerHelper.SetPhyAttribute("Resolution", TimeValue(MicroSeconds(10)));
|
|
spectrumAnalyzerHelper.SetPhyAttribute("NoisePowerSpectralDensity",
|
|
DoubleValue(1e-15)); // -120 dBm/Hz
|
|
spectrumAnalyzerHelper.EnableAsciiAll("spectrum-analyzer-output");
|
|
spectrumAnalyzerHelper.Install(spectrumAnalyzerNodes);
|
|
}
|
|
|
|
Ptr<RadioEnvironmentMapHelper> remHelper;
|
|
if (generateRem)
|
|
{
|
|
PrintGnuplottableEnbListToFile("enbs.txt");
|
|
PrintGnuplottableUeListToFile("ues.txt");
|
|
|
|
remHelper = CreateObject<RadioEnvironmentMapHelper>();
|
|
Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get(0)
|
|
->GetObject<LteEnbNetDevice>()
|
|
->GetPhy()
|
|
->GetDownlinkSpectrumPhy()
|
|
->GetObject<LteSpectrumPhy>();
|
|
Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel();
|
|
uint32_t dlChannelId = dlChannel->GetId();
|
|
NS_LOG_INFO("DL ChannelId: " << dlChannelId);
|
|
remHelper->SetAttribute("Channel", PointerValue(dlChannel));
|
|
remHelper->SetAttribute("OutputFile", StringValue("lena-distributed-ffr.rem"));
|
|
remHelper->SetAttribute("XMin", DoubleValue(macroUeBox.xMin));
|
|
remHelper->SetAttribute("XMax", DoubleValue(macroUeBox.xMax));
|
|
remHelper->SetAttribute("YMin", DoubleValue(macroUeBox.yMin));
|
|
remHelper->SetAttribute("YMax", DoubleValue(macroUeBox.yMax));
|
|
remHelper->SetAttribute("Z", DoubleValue(1.5));
|
|
remHelper->SetAttribute("XRes", UintegerValue(500));
|
|
remHelper->SetAttribute("YRes", UintegerValue(500));
|
|
|
|
if (remRbId >= 0)
|
|
{
|
|
remHelper->SetAttribute("UseDataChannel", BooleanValue(true));
|
|
remHelper->SetAttribute("RbId", IntegerValue(remRbId));
|
|
}
|
|
|
|
remHelper->Install();
|
|
// simulation will stop right after the REM has been generated
|
|
}
|
|
else
|
|
{
|
|
Simulator::Stop(Seconds(simTime));
|
|
}
|
|
|
|
Simulator::Run();
|
|
Simulator::Destroy();
|
|
return 0;
|
|
}
|