1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Piotr Gawlowicz
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Piotr Gawlowicz <gawlowicz.p@gmail.com>
19  *
20  */
21 
22 #include "ns3/core-module.h"
23 #include "ns3/network-module.h"
24 #include "ns3/mobility-module.h"
25 #include "ns3/lte-module.h"
26 #include "ns3/config-store.h"
27 #include <ns3/buildings-helper.h>
28 #include <ns3/spectrum-module.h>
29 #include <ns3/log.h>
30 
31 using namespace ns3;
32 
33 NS_LOG_COMPONENT_DEFINE ("LenaFrequencyReuse");
34 
35 void
PrintGnuplottableUeListToFile(std::string filename)36 PrintGnuplottableUeListToFile (std::string filename)
37 {
38   std::ofstream outFile;
39   outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
40   if (!outFile.is_open ())
41     {
42       NS_LOG_ERROR ("Can't open file " << filename);
43       return;
44     }
45   for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
46     {
47       Ptr<Node> node = *it;
48       int nDevs = node->GetNDevices ();
49       for (int j = 0; j < nDevs; j++)
50         {
51           Ptr<LteUeNetDevice> uedev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
52           if (uedev)
53             {
54               Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
55               outFile << "set label \"" << uedev->GetImsi ()
56                       << "\" 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"
57                       << std::endl;
58             }
59         }
60     }
61 }
62 
63 void
PrintGnuplottableEnbListToFile(std::string filename)64 PrintGnuplottableEnbListToFile (std::string filename)
65 {
66   std::ofstream outFile;
67   outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
68   if (!outFile.is_open ())
69     {
70       NS_LOG_ERROR ("Can't open file " << filename);
71       return;
72     }
73   for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
74     {
75       Ptr<Node> node = *it;
76       int nDevs = node->GetNDevices ();
77       for (int j = 0; j < nDevs; j++)
78         {
79           Ptr<LteEnbNetDevice> enbdev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
80           if (enbdev)
81             {
82               Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
83               outFile << "set label \"" << enbdev->GetCellId ()
84                       << "\" at " << pos.x << "," << pos.y
85                       << " left font \"Helvetica,4\" textcolor rgb \"white\" front  point pt 2 ps 0.3 lc rgb \"white\" offset 0,0"
86                       << std::endl;
87             }
88         }
89     }
90 }
91 
main(int argc,char * argv[])92 int main (int argc, char *argv[])
93 {
94   Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (true));
95   Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (true));
96   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
97   Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (true));
98 
99   //Uplink Power Control
100   Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (true));
101   Config::SetDefault ("ns3::LteUePowerControl::ClosedLoop", BooleanValue (true));
102   Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
103 
104   uint32_t runId = 3;
105   uint16_t numberOfRandomUes = 0;
106   double simTime = 2.500;
107   bool generateSpectrumTrace = false;
108   bool generateRem = false;
109   int32_t remRbId = -1;
110   uint16_t bandwidth = 25;
111   double distance = 1000;
112   Box macroUeBox = Box (-distance * 0.5, distance * 1.5, -distance * 0.5, distance * 1.5, 1.5, 1.5);
113 
114   // Command line arguments
115   CommandLine cmd (__FILE__);
116   cmd.AddValue ("numberOfUes", "Number of random UEs", numberOfRandomUes);
117   cmd.AddValue ("simTime", "Total duration of the simulation (in seconds)", simTime);
118   cmd.AddValue ("generateSpectrumTrace", "if true, will generate a Spectrum Analyzer trace", generateSpectrumTrace);
119   cmd.AddValue ("generateRem", "if true, will generate a REM and then abort the simulation", generateRem);
120   cmd.AddValue ("remRbId", "Resource Block Id, for which REM will be generated,"
121                 "default value is -1, what means REM will be averaged from all RBs", remRbId);
122   cmd.AddValue ("runId", "runId", runId);
123   cmd.Parse (argc, argv);
124 
125   RngSeedManager::SetSeed (1);
126   RngSeedManager::SetRun (runId);
127 
128   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
129 
130   // Create Nodes: eNodeB and UE
131   NodeContainer enbNodes;
132   NodeContainer centerUeNodes;
133   NodeContainer edgeUeNodes;
134   NodeContainer randomUeNodes;
135   enbNodes.Create (3);
136   centerUeNodes.Create (3);
137   edgeUeNodes.Create (3);
138   randomUeNodes.Create (numberOfRandomUes);
139 
140 
141 /*   the topology is the following:
142  *                 eNB3
143  *                /     \
144  *               /       \
145  *              /         \
146  *             /           \
147  *   distance /             \ distance
148  *           /      UEs      \
149  *          /                 \
150  *         /                   \
151  *        /                     \
152  *       /                       \
153  *   eNB1-------------------------eNB2
154  *                  distance
155  */
156 
157   // Install Mobility Model
158   Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator> ();
159   enbPositionAlloc->Add (Vector (0.0, 0.0, 0.0));                       // eNB1
160   enbPositionAlloc->Add (Vector (distance,  0.0, 0.0));                 // eNB2
161   enbPositionAlloc->Add (Vector (distance * 0.5, distance * 0.866, 0.0));   // eNB3
162   MobilityHelper mobility;
163   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
164   mobility.SetPositionAllocator (enbPositionAlloc);
165   mobility.Install (enbNodes);
166 
167 
168   Ptr<ListPositionAllocator> edgeUePositionAlloc = CreateObject<ListPositionAllocator> ();
169   edgeUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.28867, 0.0));  // edgeUE1
170   edgeUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.28867, 0.0));  // edgeUE2
171   edgeUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.28867, 0.0));  // edgeUE3
172   mobility.SetPositionAllocator (edgeUePositionAlloc);
173   mobility.Install (edgeUeNodes);
174 
175 
176   Ptr<ListPositionAllocator> centerUePositionAlloc = CreateObject<ListPositionAllocator> ();
177   centerUePositionAlloc->Add (Vector (0.0, 0.0, 0.0));                                      // centerUE1
178   centerUePositionAlloc->Add (Vector (distance,  0.0, 0.0));                            // centerUE2
179   centerUePositionAlloc->Add (Vector (distance * 0.5, distance * 0.866, 0.0));      // centerUE3
180   mobility.SetPositionAllocator (centerUePositionAlloc);
181   mobility.Install (centerUeNodes);
182 
183 
184   Ptr<RandomBoxPositionAllocator> randomUePositionAlloc = CreateObject<RandomBoxPositionAllocator> ();
185   Ptr<UniformRandomVariable> xVal = CreateObject<UniformRandomVariable> ();
186   xVal->SetAttribute ("Min", DoubleValue (macroUeBox.xMin));
187   xVal->SetAttribute ("Max", DoubleValue (macroUeBox.xMax));
188   randomUePositionAlloc->SetAttribute ("X", PointerValue (xVal));
189   Ptr<UniformRandomVariable> yVal = CreateObject<UniformRandomVariable> ();
190   yVal->SetAttribute ("Min", DoubleValue (macroUeBox.yMin));
191   yVal->SetAttribute ("Max", DoubleValue (macroUeBox.yMax));
192   randomUePositionAlloc->SetAttribute ("Y", PointerValue (yVal));
193   Ptr<UniformRandomVariable> zVal = CreateObject<UniformRandomVariable> ();
194   zVal->SetAttribute ("Min", DoubleValue (macroUeBox.zMin));
195   zVal->SetAttribute ("Max", DoubleValue (macroUeBox.zMax));
196   randomUePositionAlloc->SetAttribute ("Z", PointerValue (zVal));
197   mobility.SetPositionAllocator (randomUePositionAlloc);
198   mobility.Install (randomUeNodes);
199 
200   // Create Devices and install them in the Nodes (eNB and UE)
201   NetDeviceContainer enbDevs;
202   NetDeviceContainer edgeUeDevs;
203   NetDeviceContainer centerUeDevs;
204   NetDeviceContainer randomUeDevs;
205   lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler");
206   lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
207   lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (bandwidth));
208   lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (bandwidth));
209 
210   std::string frAlgorithmType = lteHelper->GetFfrAlgorithmType ();
211   NS_LOG_DEBUG ("FrAlgorithmType: " << frAlgorithmType);
212 
213   if (frAlgorithmType == "ns3::LteFrHardAlgorithm")
214     {
215 
216       //Nothing to configure here in automatic mode
217 
218     }
219   else if (frAlgorithmType == "ns3::LteFrStrictAlgorithm")
220     {
221 
222       lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (32));
223       lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
224                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
225       lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
226                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
227       lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (0));
228       lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
229 
230       //ns3::LteFrStrictAlgorithm works with Absolute Mode Uplink Power Control
231       Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
232 
233     }
234   else if (frAlgorithmType == "ns3::LteFrSoftAlgorithm")
235     {
236 
237       lteHelper->SetFfrAlgorithmAttribute ("AllowCenterUeUseEdgeSubBand", BooleanValue (true));
238       lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
239       lteHelper->SetFfrAlgorithmAttribute ("CenterPowerOffset",
240                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
241       lteHelper->SetFfrAlgorithmAttribute ("EdgePowerOffset",
242                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
243       lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (0));
244       lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
245 
246       //ns3::LteFrSoftAlgorithm works with Absolute Mode Uplink Power Control
247       Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
248 
249     }
250   else if (frAlgorithmType == "ns3::LteFfrSoftAlgorithm")
251     {
252 
253       lteHelper->SetFfrAlgorithmAttribute ("CenterRsrqThreshold", UintegerValue (30));
254       lteHelper->SetFfrAlgorithmAttribute ("EdgeRsrqThreshold", UintegerValue (25));
255       lteHelper->SetFfrAlgorithmAttribute ("CenterAreaPowerOffset",
256                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
257       lteHelper->SetFfrAlgorithmAttribute ("MediumAreaPowerOffset",
258                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB_1dot77));
259       lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaPowerOffset",
260                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
261       lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (1));
262       lteHelper->SetFfrAlgorithmAttribute ("MediumAreaTpc", UintegerValue (2));
263       lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
264 
265       //ns3::LteFfrSoftAlgorithm works with Absolute Mode Uplink Power Control
266       Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
267 
268     }
269   else if (frAlgorithmType == "ns3::LteFfrEnhancedAlgorithm")
270     {
271 
272       lteHelper->SetFfrAlgorithmAttribute ("RsrqThreshold", UintegerValue (25));
273       lteHelper->SetFfrAlgorithmAttribute ("DlCqiThreshold", UintegerValue (10));
274       lteHelper->SetFfrAlgorithmAttribute ("UlCqiThreshold", UintegerValue (10));
275       lteHelper->SetFfrAlgorithmAttribute ("CenterAreaPowerOffset",
276                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB_6));
277       lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaPowerOffset",
278                                            UintegerValue (LteRrcSap::PdschConfigDedicated::dB3));
279       lteHelper->SetFfrAlgorithmAttribute ("CenterAreaTpc", UintegerValue (0));
280       lteHelper->SetFfrAlgorithmAttribute ("EdgeAreaTpc", UintegerValue (3));
281 
282       //ns3::LteFfrEnhancedAlgorithm works with Absolute Mode Uplink Power Control
283       Config::SetDefault ("ns3::LteUePowerControl::AccumulationEnabled", BooleanValue (false));
284 
285     }
286   else if (frAlgorithmType == "ns3::LteFfrDistributedAlgorithm")
287     {
288 
289       NS_FATAL_ERROR ("ns3::LteFfrDistributedAlgorithm not supported in this example. Please run lena-distributed-ffr");
290 
291     }
292   else
293     {
294       lteHelper->SetFfrAlgorithmType ("ns3::LteFrNoOpAlgorithm");
295     }
296 
297   lteHelper->SetFfrAlgorithmAttribute ("FrCellTypeId", UintegerValue (1));
298   enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (0)));
299 
300   lteHelper->SetFfrAlgorithmAttribute ("FrCellTypeId", UintegerValue (2));
301   enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (1)));
302 
303   lteHelper->SetFfrAlgorithmAttribute ("FrCellTypeId", UintegerValue (3));
304   enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (2)));
305 
306   //FR algorithm reconfiguration if needed
307   PointerValue tmp;
308   enbDevs.Get (0)->GetAttribute ("LteFfrAlgorithm", tmp);
309   Ptr<LteFfrAlgorithm> ffrAlgorithm = DynamicCast<LteFfrAlgorithm> (tmp.GetObject ());
310   ffrAlgorithm->SetAttribute ("FrCellTypeId", UintegerValue (1));
311 
312 
313   //Install Ue Device
314   edgeUeDevs = lteHelper->InstallUeDevice (edgeUeNodes);
315   centerUeDevs = lteHelper->InstallUeDevice (centerUeNodes);
316   randomUeDevs = lteHelper->InstallUeDevice (randomUeNodes);
317 
318   // Attach edge UEs to eNbs
319   for (uint32_t i = 0; i < edgeUeDevs.GetN (); i++)
320     {
321       lteHelper->Attach (edgeUeDevs.Get (i), enbDevs.Get (i));
322     }
323   // Attach center UEs to eNbs
324   for (uint32_t i = 0; i < centerUeDevs.GetN (); i++)
325     {
326       lteHelper->Attach (centerUeDevs.Get (i), enbDevs.Get (i));
327     }
328 
329   // Attach UE to a eNB
330   lteHelper->AttachToClosestEnb (randomUeDevs, enbDevs);
331 
332   // Activate a data radio bearer
333   enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
334   EpsBearer bearer (q);
335   lteHelper->ActivateDataRadioBearer (edgeUeDevs, bearer);
336   lteHelper->ActivateDataRadioBearer (centerUeDevs, bearer);
337   lteHelper->ActivateDataRadioBearer (randomUeDevs, bearer);
338 
339   //Spectrum analyzer
340   NodeContainer spectrumAnalyzerNodes;
341   spectrumAnalyzerNodes.Create (1);
342   SpectrumAnalyzerHelper spectrumAnalyzerHelper;
343 
344   if (generateSpectrumTrace)
345     {
346       Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
347       //position of Spectrum Analyzer
348 //	  positionAlloc->Add (Vector (0.0, 0.0, 0.0));                              // eNB1
349 //	  positionAlloc->Add (Vector (distance,  0.0, 0.0));                        // eNB2
350       positionAlloc->Add (Vector (distance * 0.5, distance * 0.866, 0.0));          // eNB3
351 
352       MobilityHelper mobility;
353       mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
354       mobility.SetPositionAllocator (positionAlloc);
355       mobility.Install (spectrumAnalyzerNodes);
356 
357       Ptr<LteSpectrumPhy> enbDlSpectrumPhy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetDownlinkSpectrumPhy ()->GetObject<LteSpectrumPhy> ();
358       Ptr<SpectrumChannel> dlChannel = enbDlSpectrumPhy->GetChannel ();
359 
360       spectrumAnalyzerHelper.SetChannel (dlChannel);
361       Ptr<SpectrumModel> sm = LteSpectrumValueHelper::GetSpectrumModel (100, bandwidth);
362       spectrumAnalyzerHelper.SetRxSpectrumModel (sm);
363       spectrumAnalyzerHelper.SetPhyAttribute ("Resolution", TimeValue (MicroSeconds (10)));
364       spectrumAnalyzerHelper.SetPhyAttribute ("NoisePowerSpectralDensity", DoubleValue (1e-15));     // -120 dBm/Hz
365       spectrumAnalyzerHelper.EnableAsciiAll ("spectrum-analyzer-output");
366       spectrumAnalyzerHelper.Install (spectrumAnalyzerNodes);
367     }
368 
369   Ptr<RadioEnvironmentMapHelper> remHelper;
370   if (generateRem)
371     {
372       PrintGnuplottableEnbListToFile ("enbs.txt");
373       PrintGnuplottableUeListToFile ("ues.txt");
374 
375       remHelper = CreateObject<RadioEnvironmentMapHelper> ();
376       remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/0"));
377       remHelper->SetAttribute ("OutputFile", StringValue ("lena-frequency-reuse.rem"));
378       remHelper->SetAttribute ("XMin", DoubleValue (macroUeBox.xMin));
379       remHelper->SetAttribute ("XMax", DoubleValue (macroUeBox.xMax));
380       remHelper->SetAttribute ("YMin", DoubleValue (macroUeBox.yMin));
381       remHelper->SetAttribute ("YMax", DoubleValue (macroUeBox.yMax));
382       remHelper->SetAttribute ("Z", DoubleValue (1.5));
383       remHelper->SetAttribute ("XRes", UintegerValue (500));
384       remHelper->SetAttribute ("YRes", UintegerValue (500));
385       if (remRbId >= 0)
386         {
387           remHelper->SetAttribute ("UseDataChannel", BooleanValue (true));
388           remHelper->SetAttribute ("RbId", IntegerValue (remRbId));
389         }
390 
391       remHelper->Install ();
392       // simulation will stop right after the REM has been generated
393     }
394   else
395     {
396       Simulator::Stop (Seconds (simTime));
397     }
398 
399   Simulator::Run ();
400   Simulator::Destroy ();
401   return 0;
402 }
403