1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
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: Nicola Baldo <nbaldo@cttc.es>
19  */
20 
21 #include <ns3/core-module.h>
22 #include <ns3/network-module.h>
23 #include <ns3/mobility-module.h>
24 #include <ns3/internet-module.h>
25 #include <ns3/lte-module.h>
26 #include <ns3/config-store-module.h>
27 #include <ns3/buildings-module.h>
28 #include <ns3/point-to-point-helper.h>
29 #include <ns3/applications-module.h>
30 #include <ns3/log.h>
31 #include <iomanip>
32 #include <ios>
33 #include <string>
34 #include <vector>
35 
36 // The topology of this simulation program is inspired from
37 // 3GPP R4-092042, Section 4.2.1 Dual Stripe Model
38 // note that the term "apartments" used in that document matches with
39 // the term "room" used in the BuildingsMobilityModel
40 
41 using namespace ns3;
42 
43 NS_LOG_COMPONENT_DEFINE ("LenaDualStripe");
44 
AreOverlapping(Box a,Box b)45 bool AreOverlapping (Box a, Box b)
46 {
47   return !((a.xMin > b.xMax) || (b.xMin > a.xMax) || (a.yMin > b.yMax) || (b.yMin > a.yMax));
48 }
49 
50 /**
51  * Class that takes care of installing blocks of the
52  * buildings in a given area. Buildings are installed in pairs
53  * as in dual stripe scenario.
54  */
55 class FemtocellBlockAllocator
56 {
57 public:
58   /**
59    * Constructor
60    * \param area the total area
61    * \param nApartmentsX the number of apartments in the X direction
62    * \param nFloors the number of floors
63    */
64   FemtocellBlockAllocator (Box area, uint32_t nApartmentsX, uint32_t nFloors);
65   /**
66    * Function that creates building blocks.
67    * \param n the number of blocks to create
68    */
69   void Create (uint32_t n);
70   /// Create function
71   void Create ();
72 
73 private:
74   /**
75    * Function that checks if the box area is overlapping with some of previously created building blocks.
76    * \param box the area to check
77    * \returns true if there is an overlap
78    */
79   bool OverlapsWithAnyPrevious (Box box);
80   Box m_area; ///< Area
81   uint32_t m_nApartmentsX; ///< X apartments
82   uint32_t m_nFloors; ///< number of floors
83   std::list<Box> m_previousBlocks; ///< previous bocks
84   double m_xSize; ///< X size
85   double m_ySize; ///< Y size
86   Ptr<UniformRandomVariable> m_xMinVar; ///< X minimum variance
87   Ptr<UniformRandomVariable> m_yMinVar; ///< Y minimum variance
88 
89 };
90 
FemtocellBlockAllocator(Box area,uint32_t nApartmentsX,uint32_t nFloors)91 FemtocellBlockAllocator::FemtocellBlockAllocator (Box area, uint32_t nApartmentsX, uint32_t nFloors)
92   : m_area (area),
93     m_nApartmentsX (nApartmentsX),
94     m_nFloors (nFloors),
95     m_xSize (nApartmentsX*10 + 20),
96     m_ySize (70)
97 {
98   m_xMinVar = CreateObject<UniformRandomVariable> ();
99   m_xMinVar->SetAttribute ("Min", DoubleValue (area.xMin));
100   m_xMinVar->SetAttribute ("Max", DoubleValue (area.xMax - m_xSize));
101   m_yMinVar = CreateObject<UniformRandomVariable> ();
102   m_yMinVar->SetAttribute ("Min", DoubleValue (area.yMin));
103   m_yMinVar->SetAttribute ("Max", DoubleValue (area.yMax - m_ySize));
104 }
105 
106 void
Create(uint32_t n)107 FemtocellBlockAllocator::Create (uint32_t n)
108 {
109   for (uint32_t i = 0; i < n; ++i)
110     {
111       Create ();
112     }
113 }
114 
115 void
Create()116 FemtocellBlockAllocator::Create ()
117 {
118   Box box;
119   uint32_t attempt = 0;
120   do
121     {
122       NS_ASSERT_MSG (attempt < 100, "Too many failed attempts to position apartment block. Too many blocks? Too small area?");
123       box.xMin = m_xMinVar->GetValue ();
124       box.xMax = box.xMin + m_xSize;
125       box.yMin = m_yMinVar->GetValue ();
126       box.yMax = box.yMin + m_ySize;
127       ++attempt;
128     }
129   while (OverlapsWithAnyPrevious (box));
130 
131   NS_LOG_LOGIC ("allocated non overlapping block " << box);
132   m_previousBlocks.push_back (box);
133   Ptr<GridBuildingAllocator>  gridBuildingAllocator;
134   gridBuildingAllocator = CreateObject<GridBuildingAllocator> ();
135   gridBuildingAllocator->SetAttribute ("GridWidth", UintegerValue (1));
136   gridBuildingAllocator->SetAttribute ("LengthX", DoubleValue (10*m_nApartmentsX));
137   gridBuildingAllocator->SetAttribute ("LengthY", DoubleValue (10*2));
138   gridBuildingAllocator->SetAttribute ("DeltaX", DoubleValue (10));
139   gridBuildingAllocator->SetAttribute ("DeltaY", DoubleValue (10));
140   gridBuildingAllocator->SetAttribute ("Height", DoubleValue (3*m_nFloors));
141   gridBuildingAllocator->SetBuildingAttribute ("NRoomsX", UintegerValue (m_nApartmentsX));
142   gridBuildingAllocator->SetBuildingAttribute ("NRoomsY", UintegerValue (2));
143   gridBuildingAllocator->SetBuildingAttribute ("NFloors", UintegerValue (m_nFloors));
144   gridBuildingAllocator->SetAttribute ("MinX", DoubleValue (box.xMin + 10));
145   gridBuildingAllocator->SetAttribute ("MinY", DoubleValue (box.yMin + 10));
146   gridBuildingAllocator->Create (2);
147 }
148 
149 bool
OverlapsWithAnyPrevious(Box box)150 FemtocellBlockAllocator::OverlapsWithAnyPrevious (Box box)
151 {
152   for (std::list<Box>::iterator it = m_previousBlocks.begin (); it != m_previousBlocks.end (); ++it)
153     {
154       if (AreOverlapping (*it, box))
155         {
156           return true;
157         }
158     }
159   return false;
160 }
161 
162 void
PrintGnuplottableBuildingListToFile(std::string filename)163 PrintGnuplottableBuildingListToFile (std::string filename)
164 {
165   std::ofstream outFile;
166   outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
167   if (!outFile.is_open ())
168     {
169       NS_LOG_ERROR ("Can't open file " << filename);
170       return;
171     }
172   uint32_t index = 0;
173   for (BuildingList::Iterator it = BuildingList::Begin (); it != BuildingList::End (); ++it)
174     {
175       ++index;
176       Box box = (*it)->GetBoundaries ();
177       outFile << "set object " << index
178               << " rect from " << box.xMin  << "," << box.yMin
179               << " to "   << box.xMax  << "," << box.yMax
180               << " front fs empty "
181               << std::endl;
182     }
183 }
184 
185 void
PrintGnuplottableUeListToFile(std::string filename)186 PrintGnuplottableUeListToFile (std::string filename)
187 {
188   std::ofstream outFile;
189   outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
190   if (!outFile.is_open ())
191     {
192       NS_LOG_ERROR ("Can't open file " << filename);
193       return;
194     }
195   for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
196     {
197       Ptr<Node> node = *it;
198       int nDevs = node->GetNDevices ();
199       for (int j = 0; j < nDevs; j++)
200         {
201           Ptr<LteUeNetDevice> uedev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
202           if (uedev)
203             {
204               Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
205               outFile << "set label \"" << uedev->GetImsi ()
206                       << "\" 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"
207                       << std::endl;
208             }
209         }
210     }
211 }
212 
213 void
PrintGnuplottableEnbListToFile(std::string filename)214 PrintGnuplottableEnbListToFile (std::string filename)
215 {
216   std::ofstream outFile;
217   outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
218   if (!outFile.is_open ())
219     {
220       NS_LOG_ERROR ("Can't open file " << filename);
221       return;
222     }
223   for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
224     {
225       Ptr<Node> node = *it;
226       int nDevs = node->GetNDevices ();
227       for (int j = 0; j < nDevs; j++)
228         {
229           Ptr<LteEnbNetDevice> enbdev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
230           if (enbdev)
231             {
232               Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
233               outFile << "set label \"" << enbdev->GetCellId ()
234                       << "\" at "<< pos.x << "," << pos.y
235                       << " left font \"Helvetica,4\" textcolor rgb \"white\" front  point pt 2 ps 0.3 lc rgb \"white\" offset 0,0"
236                       << std::endl;
237             }
238         }
239     }
240 }
241 
242 
243 static ns3::GlobalValue g_nBlocks ("nBlocks",
244                                    "Number of femtocell blocks",
245                                    ns3::UintegerValue (1),
246                                    ns3::MakeUintegerChecker<uint32_t> ());
247 static ns3::GlobalValue g_nApartmentsX ("nApartmentsX",
248                                         "Number of apartments along the X axis in a femtocell block",
249                                         ns3::UintegerValue (10),
250                                         ns3::MakeUintegerChecker<uint32_t> ());
251 static ns3::GlobalValue g_nFloors ("nFloors",
252                                    "Number of floors",
253                                    ns3::UintegerValue (1),
254                                    ns3::MakeUintegerChecker<uint32_t> ());
255 static ns3::GlobalValue g_nMacroEnbSites ("nMacroEnbSites",
256                                           "How many macro sites there are",
257                                           ns3::UintegerValue (3),
258                                           ns3::MakeUintegerChecker<uint32_t> ());
259 static ns3::GlobalValue g_nMacroEnbSitesX ("nMacroEnbSitesX",
260                                            "(minimum) number of sites along the X-axis of the hex grid",
261                                            ns3::UintegerValue (1),
262                                            ns3::MakeUintegerChecker<uint32_t> ());
263 static ns3::GlobalValue g_interSiteDistance ("interSiteDistance",
264                                              "min distance between two nearby macro cell sites",
265                                              ns3::DoubleValue (500),
266                                              ns3::MakeDoubleChecker<double> ());
267 static ns3::GlobalValue g_areaMarginFactor ("areaMarginFactor",
268                                             "how much the UE area extends outside the macrocell grid, "
269                                             "expressed as fraction of the interSiteDistance",
270                                             ns3::DoubleValue (0.5),
271                                             ns3::MakeDoubleChecker<double> ());
272 static ns3::GlobalValue g_macroUeDensity ("macroUeDensity",
273                                           "How many macrocell UEs there are per square meter",
274                                           ns3::DoubleValue (0.00002),
275                                           ns3::MakeDoubleChecker<double> ());
276 static ns3::GlobalValue g_homeEnbDeploymentRatio ("homeEnbDeploymentRatio",
277                                                   "The HeNB deployment ratio as per 3GPP R4-092042",
278                                                   ns3::DoubleValue (0.2),
279                                                   ns3::MakeDoubleChecker<double> ());
280 static ns3::GlobalValue g_homeEnbActivationRatio ("homeEnbActivationRatio",
281                                                   "The HeNB activation ratio as per 3GPP R4-092042",
282                                                   ns3::DoubleValue (0.5),
283                                                   ns3::MakeDoubleChecker<double> ());
284 static ns3::GlobalValue g_homeUesHomeEnbRatio ("homeUesHomeEnbRatio",
285                                                "How many (on average) home UEs per HeNB there are in the simulation",
286                                                ns3::DoubleValue (1.0),
287                                                ns3::MakeDoubleChecker<double> ());
288 static ns3::GlobalValue g_macroEnbTxPowerDbm ("macroEnbTxPowerDbm",
289                                               "TX power [dBm] used by macro eNBs",
290                                               ns3::DoubleValue (46.0),
291                                               ns3::MakeDoubleChecker<double> ());
292 static ns3::GlobalValue g_homeEnbTxPowerDbm ("homeEnbTxPowerDbm",
293                                              "TX power [dBm] used by HeNBs",
294                                              ns3::DoubleValue (20.0),
295                                              ns3::MakeDoubleChecker<double> ());
296 static ns3::GlobalValue g_macroEnbDlEarfcn ("macroEnbDlEarfcn",
297                                             "DL EARFCN used by macro eNBs",
298                                             ns3::UintegerValue (100),
299                                             ns3::MakeUintegerChecker<uint16_t> ());
300 static ns3::GlobalValue g_homeEnbDlEarfcn ("homeEnbDlEarfcn",
301                                            "DL EARFCN used by HeNBs",
302                                            ns3::UintegerValue (100),
303                                            ns3::MakeUintegerChecker<uint16_t> ());
304 static ns3::GlobalValue g_macroEnbBandwidth ("macroEnbBandwidth",
305                                              "bandwidth [num RBs] used by macro eNBs",
306                                              ns3::UintegerValue (25),
307                                              ns3::MakeUintegerChecker<uint16_t> ());
308 static ns3::GlobalValue g_homeEnbBandwidth ("homeEnbBandwidth",
309                                             "bandwidth [num RBs] used by HeNBs",
310                                             ns3::UintegerValue (25),
311                                             ns3::MakeUintegerChecker<uint16_t> ());
312 static ns3::GlobalValue g_simTime ("simTime",
313                                    "Total duration of the simulation [s]",
314                                    ns3::DoubleValue (0.25),
315                                    ns3::MakeDoubleChecker<double> ());
316 static ns3::GlobalValue g_generateRem ("generateRem",
317                                        "if true, will generate a REM and then abort the simulation;"
318                                        "if false, will run the simulation normally (without generating any REM)",
319                                        ns3::BooleanValue (false),
320                                        ns3::MakeBooleanChecker ());
321 static ns3::GlobalValue g_remRbId ("remRbId",
322                                    "Resource Block Id of Data Channel, for which REM will be generated;"
323                                    "default value is -1, what means REM will be averaged from all RBs of "
324                                    "Control Channel",
325                                    ns3::IntegerValue (-1),
326                                    MakeIntegerChecker<int32_t> ());
327 static ns3::GlobalValue g_epc ("epc",
328                                "If true, will setup the EPC to simulate an end-to-end topology, "
329                                "with real IP applications over PDCP and RLC UM (or RLC AM by changing "
330                                "the default value of EpsBearerToRlcMapping e.g. to RLC_AM_ALWAYS). "
331                                "If false, only the LTE radio access will be simulated with RLC SM. ",
332                                ns3::BooleanValue (false),
333                                ns3::MakeBooleanChecker ());
334 static ns3::GlobalValue g_epcDl ("epcDl",
335                                  "if true, will activate data flows in the downlink when EPC is being used. "
336                                  "If false, downlink flows won't be activated. "
337                                  "If EPC is not used, this parameter will be ignored.",
338                                  ns3::BooleanValue (true),
339                                  ns3::MakeBooleanChecker ());
340 static ns3::GlobalValue g_epcUl ("epcUl",
341                                  "if true, will activate data flows in the uplink when EPC is being used. "
342                                  "If false, uplink flows won't be activated. "
343                                  "If EPC is not used, this parameter will be ignored.",
344                                  ns3::BooleanValue (true),
345                                  ns3::MakeBooleanChecker ());
346 static ns3::GlobalValue g_useUdp ("useUdp",
347                                   "if true, the UdpClient application will be used. "
348                                   "Otherwise, the BulkSend application will be used over a TCP connection. "
349                                   "If EPC is not used, this parameter will be ignored.",
350                                   ns3::BooleanValue (true),
351                                   ns3::MakeBooleanChecker ());
352 static ns3::GlobalValue g_fadingTrace ("fadingTrace",
353                                        "The path of the fading trace (by default no fading trace "
354                                        "is loaded, i.e., fading is not considered)",
355                                        ns3::StringValue (""),
356                                        ns3::MakeStringChecker ());
357 static ns3::GlobalValue g_numBearersPerUe ("numBearersPerUe",
358                                            "How many bearers per UE there are in the simulation",
359                                            ns3::UintegerValue (1),
360                                            ns3::MakeUintegerChecker<uint16_t> ());
361 static ns3::GlobalValue g_srsPeriodicity ("srsPeriodicity",
362                                           "SRS Periodicity (has to be at least "
363                                           "greater than the number of UEs per eNB)",
364                                           ns3::UintegerValue (80),
365                                           ns3::MakeUintegerChecker<uint16_t> ());
366 static ns3::GlobalValue g_outdoorUeMinSpeed ("outdoorUeMinSpeed",
367                                              "Minimum speed value of macro UE with random waypoint model [m/s].",
368                                              ns3::DoubleValue (0.0),
369                                              ns3::MakeDoubleChecker<double> ());
370 static ns3::GlobalValue g_outdoorUeMaxSpeed ("outdoorUeMaxSpeed",
371                                              "Maximum speed value of macro UE with random waypoint model [m/s].",
372                                              ns3::DoubleValue (0.0),
373                                              ns3::MakeDoubleChecker<double> ());
374 
375 int
main(int argc,char * argv[])376 main (int argc, char *argv[])
377 {
378   // change some default attributes so that they are reasonable for
379   // this scenario, but do this before processing command line
380   // arguments, so that the user is allowed to override these settings
381   Config::SetDefault ("ns3::UdpClient::Interval", TimeValue (MilliSeconds (1)));
382   Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue (1000000));
383   Config::SetDefault ("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue (10 * 1024));
384 
385   CommandLine cmd (__FILE__);
386   cmd.Parse (argc, argv);
387   ConfigStore inputConfig;
388   inputConfig.ConfigureDefaults ();
389   // parse again so you can override input file default values via command line
390   cmd.Parse (argc, argv);
391 
392   // the scenario parameters get their values from the global attributes defined above
393   UintegerValue uintegerValue;
394   IntegerValue integerValue;
395   DoubleValue doubleValue;
396   BooleanValue booleanValue;
397   StringValue stringValue;
398   GlobalValue::GetValueByName ("nBlocks", uintegerValue);
399   uint32_t nBlocks = uintegerValue.Get ();
400   GlobalValue::GetValueByName ("nApartmentsX", uintegerValue);
401   uint32_t nApartmentsX = uintegerValue.Get ();
402   GlobalValue::GetValueByName ("nFloors", uintegerValue);
403   uint32_t nFloors = uintegerValue.Get ();
404   GlobalValue::GetValueByName ("nMacroEnbSites", uintegerValue);
405   uint32_t nMacroEnbSites = uintegerValue.Get ();
406   GlobalValue::GetValueByName ("nMacroEnbSitesX", uintegerValue);
407   uint32_t nMacroEnbSitesX = uintegerValue.Get ();
408   GlobalValue::GetValueByName ("interSiteDistance", doubleValue);
409   double interSiteDistance = doubleValue.Get ();
410   GlobalValue::GetValueByName ("areaMarginFactor", doubleValue);
411   double areaMarginFactor = doubleValue.Get ();
412   GlobalValue::GetValueByName ("macroUeDensity", doubleValue);
413   double macroUeDensity = doubleValue.Get ();
414   GlobalValue::GetValueByName ("homeEnbDeploymentRatio", doubleValue);
415   double homeEnbDeploymentRatio = doubleValue.Get ();
416   GlobalValue::GetValueByName ("homeEnbActivationRatio", doubleValue);
417   double homeEnbActivationRatio = doubleValue.Get ();
418   GlobalValue::GetValueByName ("homeUesHomeEnbRatio", doubleValue);
419   double homeUesHomeEnbRatio = doubleValue.Get ();
420   GlobalValue::GetValueByName ("macroEnbTxPowerDbm", doubleValue);
421   double macroEnbTxPowerDbm = doubleValue.Get ();
422   GlobalValue::GetValueByName ("homeEnbTxPowerDbm", doubleValue);
423   double homeEnbTxPowerDbm = doubleValue.Get ();
424   GlobalValue::GetValueByName ("macroEnbDlEarfcn", uintegerValue);
425   uint32_t macroEnbDlEarfcn = uintegerValue.Get ();
426   GlobalValue::GetValueByName ("homeEnbDlEarfcn", uintegerValue);
427   uint32_t homeEnbDlEarfcn = uintegerValue.Get ();
428   GlobalValue::GetValueByName ("macroEnbBandwidth", uintegerValue);
429   uint16_t macroEnbBandwidth = uintegerValue.Get ();
430   GlobalValue::GetValueByName ("homeEnbBandwidth", uintegerValue);
431   uint16_t homeEnbBandwidth = uintegerValue.Get ();
432   GlobalValue::GetValueByName ("simTime", doubleValue);
433   double simTime = doubleValue.Get ();
434   GlobalValue::GetValueByName ("epc", booleanValue);
435   bool epc = booleanValue.Get ();
436   GlobalValue::GetValueByName ("epcDl", booleanValue);
437   bool epcDl = booleanValue.Get ();
438   GlobalValue::GetValueByName ("epcUl", booleanValue);
439   bool epcUl = booleanValue.Get ();
440   GlobalValue::GetValueByName ("useUdp", booleanValue);
441   bool useUdp = booleanValue.Get ();
442   GlobalValue::GetValueByName ("generateRem", booleanValue);
443   bool generateRem = booleanValue.Get ();
444   GlobalValue::GetValueByName ("remRbId", integerValue);
445   int32_t remRbId = integerValue.Get ();
446   GlobalValue::GetValueByName ("fadingTrace", stringValue);
447   std::string fadingTrace = stringValue.Get ();
448   GlobalValue::GetValueByName ("numBearersPerUe", uintegerValue);
449   uint16_t numBearersPerUe = uintegerValue.Get ();
450   GlobalValue::GetValueByName ("srsPeriodicity", uintegerValue);
451   uint16_t srsPeriodicity = uintegerValue.Get ();
452   GlobalValue::GetValueByName ("outdoorUeMinSpeed", doubleValue);
453   uint16_t outdoorUeMinSpeed = doubleValue.Get ();
454   GlobalValue::GetValueByName ("outdoorUeMaxSpeed", doubleValue);
455   uint16_t outdoorUeMaxSpeed = doubleValue.Get ();
456 
457   Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (srsPeriodicity));
458 
459   Box macroUeBox;
460   double ueZ = 1.5;
461   if (nMacroEnbSites > 0)
462     {
463       uint32_t currentSite = nMacroEnbSites -1;
464       uint32_t biRowIndex = (currentSite / (nMacroEnbSitesX + nMacroEnbSitesX + 1));
465       uint32_t biRowRemainder = currentSite % (nMacroEnbSitesX + nMacroEnbSitesX + 1);
466       uint32_t rowIndex = biRowIndex*2 + 1;
467       if (biRowRemainder >= nMacroEnbSitesX)
468         {
469           ++rowIndex;
470         }
471       uint32_t nMacroEnbSitesY = rowIndex;
472       NS_LOG_LOGIC ("nMacroEnbSitesY = " << nMacroEnbSitesY);
473 
474       macroUeBox = Box (-areaMarginFactor*interSiteDistance,
475                         (nMacroEnbSitesX + areaMarginFactor)*interSiteDistance,
476                         -areaMarginFactor*interSiteDistance,
477                         (nMacroEnbSitesY -1)*interSiteDistance*sqrt (0.75) + areaMarginFactor*interSiteDistance,
478                         ueZ, ueZ);
479     }
480   else
481     {
482       // still need the box to place femtocell blocks
483       macroUeBox = Box (0, 150, 0, 150, ueZ, ueZ);
484     }
485 
486   FemtocellBlockAllocator blockAllocator (macroUeBox, nApartmentsX, nFloors);
487   blockAllocator.Create (nBlocks);
488 
489 
490   uint32_t nHomeEnbs = round (4 * nApartmentsX * nBlocks * nFloors * homeEnbDeploymentRatio * homeEnbActivationRatio);
491   NS_LOG_LOGIC ("nHomeEnbs = " << nHomeEnbs);
492   uint32_t nHomeUes = round (nHomeEnbs * homeUesHomeEnbRatio);
493   NS_LOG_LOGIC ("nHomeUes = " << nHomeUes);
494   double macroUeAreaSize = (macroUeBox.xMax - macroUeBox.xMin) * (macroUeBox.yMax - macroUeBox.yMin);
495   uint32_t nMacroUes = round (macroUeAreaSize * macroUeDensity);
496   NS_LOG_LOGIC ("nMacroUes = " << nMacroUes << " (density=" << macroUeDensity << ")");
497 
498   NodeContainer homeEnbs;
499   homeEnbs.Create (nHomeEnbs);
500   NodeContainer macroEnbs;
501   macroEnbs.Create (3 * nMacroEnbSites);
502   NodeContainer homeUes;
503   homeUes.Create (nHomeUes);
504   NodeContainer macroUes;
505   macroUes.Create (nMacroUes);
506 
507   MobilityHelper mobility;
508   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
509 
510 
511   Ptr <LteHelper> lteHelper = CreateObject<LteHelper> ();
512   lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::HybridBuildingsPropagationLossModel"));
513   lteHelper->SetPathlossModelAttribute ("ShadowSigmaExtWalls", DoubleValue (0));
514   lteHelper->SetPathlossModelAttribute ("ShadowSigmaOutdoor", DoubleValue (1));
515   lteHelper->SetPathlossModelAttribute ("ShadowSigmaIndoor", DoubleValue (1.5));
516   // use always LOS model
517   lteHelper->SetPathlossModelAttribute ("Los2NlosThr", DoubleValue (1e6));
518   lteHelper->SetSpectrumChannelType ("ns3::MultiModelSpectrumChannel");
519 
520 //   lteHelper->EnableLogComponents ();
521 //   LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
522 
523   if (!fadingTrace.empty ())
524     {
525       lteHelper->SetAttribute ("FadingModel", StringValue ("ns3::TraceFadingLossModel"));
526       lteHelper->SetFadingModelAttribute ("TraceFilename", StringValue (fadingTrace));
527     }
528 
529   Ptr<PointToPointEpcHelper> epcHelper;
530   if (epc)
531     {
532       NS_LOG_LOGIC ("enabling EPC");
533       epcHelper = CreateObject<PointToPointEpcHelper> ();
534       lteHelper->SetEpcHelper (epcHelper);
535     }
536 
537   // Macro eNBs in 3-sector hex grid
538 
539   mobility.Install (macroEnbs);
540   BuildingsHelper::Install (macroEnbs);
541   Ptr<LteHexGridEnbTopologyHelper> lteHexGridEnbTopologyHelper = CreateObject<LteHexGridEnbTopologyHelper> ();
542   lteHexGridEnbTopologyHelper->SetLteHelper (lteHelper);
543   lteHexGridEnbTopologyHelper->SetAttribute ("InterSiteDistance", DoubleValue (interSiteDistance));
544   lteHexGridEnbTopologyHelper->SetAttribute ("MinX", DoubleValue (interSiteDistance/2));
545   lteHexGridEnbTopologyHelper->SetAttribute ("GridWidth", UintegerValue (nMacroEnbSitesX));
546   Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (macroEnbTxPowerDbm));
547   lteHelper->SetEnbAntennaModelType ("ns3::ParabolicAntennaModel");
548   lteHelper->SetEnbAntennaModelAttribute ("Beamwidth",   DoubleValue (70));
549   lteHelper->SetEnbAntennaModelAttribute ("MaxAttenuation",     DoubleValue (20.0));
550   lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (macroEnbDlEarfcn));
551   lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (macroEnbDlEarfcn + 18000));
552   lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (macroEnbBandwidth));
553   lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (macroEnbBandwidth));
554   NetDeviceContainer macroEnbDevs = lteHexGridEnbTopologyHelper->SetPositionAndInstallEnbDevice (macroEnbs);
555 
556   if (epc)
557     {
558       // this enables handover for macro eNBs
559       lteHelper->AddX2Interface (macroEnbs);
560     }
561 
562   // HomeEnbs randomly indoor
563 
564   Ptr<PositionAllocator> positionAlloc = CreateObject<RandomRoomPositionAllocator> ();
565   mobility.SetPositionAllocator (positionAlloc);
566   mobility.Install (homeEnbs);
567   BuildingsHelper::Install (homeEnbs);
568   Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (homeEnbTxPowerDbm));
569   lteHelper->SetEnbAntennaModelType ("ns3::IsotropicAntennaModel");
570   lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (homeEnbDlEarfcn));
571   lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (homeEnbDlEarfcn + 18000));
572   lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (homeEnbBandwidth));
573   lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (homeEnbBandwidth));
574   lteHelper->SetEnbDeviceAttribute ("CsgId", UintegerValue (1));
575   lteHelper->SetEnbDeviceAttribute ("CsgIndication", BooleanValue (true));
576   NetDeviceContainer homeEnbDevs  = lteHelper->InstallEnbDevice (homeEnbs);
577 
578   // home UEs located in the same apartment in which there are the Home eNBs
579   positionAlloc = CreateObject<SameRoomPositionAllocator> (homeEnbs);
580   mobility.SetPositionAllocator (positionAlloc);
581   mobility.Install (homeUes);
582   BuildingsHelper::Install (homeUes);
583   // set the home UE as a CSG member of the home eNodeBs
584   lteHelper->SetUeDeviceAttribute ("CsgId", UintegerValue (1));
585   NetDeviceContainer homeUeDevs = lteHelper->InstallUeDevice (homeUes);
586 
587   // macro Ues
588   NS_LOG_LOGIC ("randomly allocating macro UEs in " << macroUeBox << " speedMin " << outdoorUeMinSpeed << " speedMax " << outdoorUeMaxSpeed);
589   if (outdoorUeMaxSpeed!=0.0)
590     {
591       mobility.SetMobilityModel ("ns3::SteadyStateRandomWaypointMobilityModel");
592 
593       Config::SetDefault ("ns3::SteadyStateRandomWaypointMobilityModel::MinX", DoubleValue (macroUeBox.xMin));
594       Config::SetDefault ("ns3::SteadyStateRandomWaypointMobilityModel::MinY", DoubleValue (macroUeBox.yMin));
595       Config::SetDefault ("ns3::SteadyStateRandomWaypointMobilityModel::MaxX", DoubleValue (macroUeBox.xMax));
596       Config::SetDefault ("ns3::SteadyStateRandomWaypointMobilityModel::MaxY", DoubleValue (macroUeBox.yMax));
597       Config::SetDefault ("ns3::SteadyStateRandomWaypointMobilityModel::Z", DoubleValue (ueZ));
598       Config::SetDefault ("ns3::SteadyStateRandomWaypointMobilityModel::MaxSpeed", DoubleValue (outdoorUeMaxSpeed));
599       Config::SetDefault ("ns3::SteadyStateRandomWaypointMobilityModel::MinSpeed", DoubleValue (outdoorUeMinSpeed));
600 
601       // this is not used since SteadyStateRandomWaypointMobilityModel
602       // takes care of initializing the positions;  however we need to
603       // reset it since the previously used PositionAllocator
604       // (SameRoom) will cause an error when used with homeDeploymentRatio=0
605       positionAlloc = CreateObject<RandomBoxPositionAllocator> ();
606       mobility.SetPositionAllocator (positionAlloc);
607       mobility.Install (macroUes);
608 
609       // forcing initialization so we don't have to wait for Nodes to
610       // start before positions are assigned (which is needed to
611       // output node positions to file and to make AttachToClosestEnb work)
612       for (NodeContainer::Iterator it = macroUes.Begin ();
613            it != macroUes.End ();
614            ++it)
615         {
616           (*it)->Initialize ();
617         }
618     }
619     else
620     {
621       positionAlloc = CreateObject<RandomBoxPositionAllocator> ();
622       Ptr<UniformRandomVariable> xVal = CreateObject<UniformRandomVariable> ();
623       xVal->SetAttribute ("Min", DoubleValue (macroUeBox.xMin));
624       xVal->SetAttribute ("Max", DoubleValue (macroUeBox.xMax));
625       positionAlloc->SetAttribute ("X", PointerValue (xVal));
626       Ptr<UniformRandomVariable> yVal = CreateObject<UniformRandomVariable> ();
627       yVal->SetAttribute ("Min", DoubleValue (macroUeBox.yMin));
628       yVal->SetAttribute ("Max", DoubleValue (macroUeBox.yMax));
629       positionAlloc->SetAttribute ("Y", PointerValue (yVal));
630       Ptr<UniformRandomVariable> zVal = CreateObject<UniformRandomVariable> ();
631       zVal->SetAttribute ("Min", DoubleValue (macroUeBox.zMin));
632       zVal->SetAttribute ("Max", DoubleValue (macroUeBox.zMax));
633       positionAlloc->SetAttribute ("Z", PointerValue (zVal));
634       mobility.SetPositionAllocator (positionAlloc);
635       mobility.Install (macroUes);
636     }
637   BuildingsHelper::Install (macroUes);
638 
639   NetDeviceContainer macroUeDevs = lteHelper->InstallUeDevice (macroUes);
640 
641   Ipv4Address remoteHostAddr;
642   NodeContainer ues;
643   Ipv4StaticRoutingHelper ipv4RoutingHelper;
644   Ipv4InterfaceContainer ueIpIfaces;
645   Ptr<Node> remoteHost;
646   NetDeviceContainer ueDevs;
647 
648   if (epc)
649     {
650       NS_LOG_LOGIC ("setting up internet and remote host");
651 
652       // Create a single RemoteHost
653       NodeContainer remoteHostContainer;
654       remoteHostContainer.Create (1);
655       remoteHost = remoteHostContainer.Get (0);
656       InternetStackHelper internet;
657       internet.Install (remoteHostContainer);
658 
659       // Create the Internet
660       PointToPointHelper p2ph;
661       p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));
662       p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));
663       p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010)));
664       Ptr<Node> pgw = epcHelper->GetPgwNode ();
665       NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);
666       Ipv4AddressHelper ipv4h;
667       ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
668       Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
669       // in this container, interface 0 is the pgw, 1 is the remoteHost
670       remoteHostAddr = internetIpIfaces.GetAddress (1);
671 
672       Ipv4StaticRoutingHelper ipv4RoutingHelper;
673       Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());
674       remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);
675 
676       // for internetworking purposes, consider together home UEs and macro UEs
677       ues.Add (homeUes);
678       ues.Add (macroUes);
679       ueDevs.Add (homeUeDevs);
680       ueDevs.Add (macroUeDevs);
681 
682       // Install the IP stack on the UEs
683       internet.Install (ues);
684       ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevs));
685 
686       // attachment (needs to be done after IP stack configuration)
687       // using initial cell selection
688       lteHelper->Attach (macroUeDevs);
689       lteHelper->Attach (homeUeDevs);
690     }
691   else
692     {
693       // macro UEs attached to the closest macro eNB
694       lteHelper->AttachToClosestEnb (macroUeDevs, macroEnbDevs);
695 
696       // each home UE is attached explicitly to its home eNB
697       NetDeviceContainer::Iterator ueDevIt;
698       NetDeviceContainer::Iterator enbDevIt;
699       for (ueDevIt = homeUeDevs.Begin (), enbDevIt = homeEnbDevs.Begin ();
700            ueDevIt != homeUeDevs.End (); ++ueDevIt, ++enbDevIt)
701         {
702           // this because of the order in which SameRoomPositionAllocator
703           // will place the UEs
704           if (enbDevIt == homeEnbDevs.End ())
705             {
706               enbDevIt = homeEnbDevs.Begin ();
707             }
708           lteHelper->Attach (*ueDevIt, *enbDevIt);
709         }
710     }
711 
712   if (epc)
713     {
714       NS_LOG_LOGIC ("setting up applications");
715 
716       // Install and start applications on UEs and remote host
717       uint16_t dlPort = 10000;
718       uint16_t ulPort = 20000;
719 
720       // randomize a bit start times to avoid simulation artifacts
721       // (e.g., buffer overflows due to packet transmissions happening
722       // exactly at the same time)
723       Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable> ();
724       if (useUdp)
725         {
726           startTimeSeconds->SetAttribute ("Min", DoubleValue (0));
727           startTimeSeconds->SetAttribute ("Max", DoubleValue (0.010));
728         }
729       else
730         {
731           // TCP needs to be started late enough so that all UEs are connected
732           // otherwise TCP SYN packets will get lost
733           startTimeSeconds->SetAttribute ("Min", DoubleValue (0.100));
734           startTimeSeconds->SetAttribute ("Max", DoubleValue (0.110));
735         }
736 
737       for (uint32_t u = 0; u < ues.GetN (); ++u)
738         {
739           Ptr<Node> ue = ues.Get (u);
740           // Set the default gateway for the UE
741           Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ());
742           ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
743 
744           for (uint32_t b = 0; b < numBearersPerUe; ++b)
745             {
746               ++dlPort;
747               ++ulPort;
748 
749               ApplicationContainer clientApps;
750               ApplicationContainer serverApps;
751 
752               if (useUdp)
753                 {
754                   if (epcDl)
755                     {
756                       NS_LOG_LOGIC ("installing UDP DL app for UE " << u);
757                       UdpClientHelper dlClientHelper (ueIpIfaces.GetAddress (u), dlPort);
758                       clientApps.Add (dlClientHelper.Install (remoteHost));
759                       PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory",
760                                                            InetSocketAddress (Ipv4Address::GetAny (), dlPort));
761                       serverApps.Add (dlPacketSinkHelper.Install (ue));
762                     }
763                   if (epcUl)
764                     {
765                       NS_LOG_LOGIC ("installing UDP UL app for UE " << u);
766                       UdpClientHelper ulClientHelper (remoteHostAddr, ulPort);
767                       clientApps.Add (ulClientHelper.Install (ue));
768                       PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory",
769                                                            InetSocketAddress (Ipv4Address::GetAny (), ulPort));
770                       serverApps.Add (ulPacketSinkHelper.Install (remoteHost));
771                     }
772                 }
773               else // use TCP
774                 {
775                   if (epcDl)
776                     {
777                       NS_LOG_LOGIC ("installing TCP DL app for UE " << u);
778                       BulkSendHelper dlClientHelper ("ns3::TcpSocketFactory",
779                                                      InetSocketAddress (ueIpIfaces.GetAddress (u), dlPort));
780                       dlClientHelper.SetAttribute ("MaxBytes", UintegerValue (0));
781                       clientApps.Add (dlClientHelper.Install (remoteHost));
782                       PacketSinkHelper dlPacketSinkHelper ("ns3::TcpSocketFactory",
783                                                            InetSocketAddress (Ipv4Address::GetAny (), dlPort));
784                       serverApps.Add (dlPacketSinkHelper.Install (ue));
785                     }
786                   if (epcUl)
787                     {
788                       NS_LOG_LOGIC ("installing TCP UL app for UE " << u);
789                       BulkSendHelper ulClientHelper ("ns3::TcpSocketFactory",
790                                                      InetSocketAddress (remoteHostAddr, ulPort));
791                       ulClientHelper.SetAttribute ("MaxBytes", UintegerValue (0));
792                       clientApps.Add (ulClientHelper.Install (ue));
793                       PacketSinkHelper ulPacketSinkHelper ("ns3::TcpSocketFactory",
794                                                            InetSocketAddress (Ipv4Address::GetAny (), ulPort));
795                       serverApps.Add (ulPacketSinkHelper.Install (remoteHost));
796                     }
797                 } // end if (useUdp)
798 
799               Ptr<EpcTft> tft = Create<EpcTft> ();
800               if (epcDl)
801                 {
802                   EpcTft::PacketFilter dlpf;
803                   dlpf.localPortStart = dlPort;
804                   dlpf.localPortEnd = dlPort;
805                   tft->Add (dlpf);
806                 }
807               if (epcUl)
808                 {
809                   EpcTft::PacketFilter ulpf;
810                   ulpf.remotePortStart = ulPort;
811                   ulpf.remotePortEnd = ulPort;
812                   tft->Add (ulpf);
813                 }
814 
815               if (epcDl || epcUl)
816                 {
817                   EpsBearer bearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
818                   lteHelper->ActivateDedicatedEpsBearer (ueDevs.Get (u), bearer, tft);
819                 }
820               Time startTime = Seconds (startTimeSeconds->GetValue ());
821               serverApps.Start (startTime);
822               clientApps.Start (startTime);
823 
824             } // end for b
825         }
826 
827     }
828   else // (epc == false)
829     {
830       // for radio bearer activation purposes, consider together home UEs and macro UEs
831       NetDeviceContainer ueDevs;
832       ueDevs.Add (homeUeDevs);
833       ueDevs.Add (macroUeDevs);
834       for (uint32_t u = 0; u < ueDevs.GetN (); ++u)
835         {
836           Ptr<NetDevice> ueDev = ueDevs.Get (u);
837           for (uint32_t b = 0; b < numBearersPerUe; ++b)
838             {
839               enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
840               EpsBearer bearer (q);
841               lteHelper->ActivateDataRadioBearer (ueDev, bearer);
842             }
843         }
844     }
845 
846   Ptr<RadioEnvironmentMapHelper> remHelper;
847   if (generateRem)
848     {
849       PrintGnuplottableBuildingListToFile ("buildings.txt");
850       PrintGnuplottableEnbListToFile ("enbs.txt");
851       PrintGnuplottableUeListToFile ("ues.txt");
852 
853       remHelper = CreateObject<RadioEnvironmentMapHelper> ();
854       remHelper->SetAttribute ("Channel", PointerValue (lteHelper->GetDownlinkSpectrumChannel ()));
855       remHelper->SetAttribute ("OutputFile", StringValue ("lena-dual-stripe.rem"));
856       remHelper->SetAttribute ("XMin", DoubleValue (macroUeBox.xMin));
857       remHelper->SetAttribute ("XMax", DoubleValue (macroUeBox.xMax));
858       remHelper->SetAttribute ("YMin", DoubleValue (macroUeBox.yMin));
859       remHelper->SetAttribute ("YMax", DoubleValue (macroUeBox.yMax));
860       remHelper->SetAttribute ("Z", DoubleValue (1.5));
861 
862       if (remRbId >= 0)
863         {
864           remHelper->SetAttribute ("UseDataChannel", BooleanValue (true));
865           remHelper->SetAttribute ("RbId", IntegerValue (remRbId));
866         }
867 
868       remHelper->Install ();
869       // simulation will stop right after the REM has been generated
870     }
871   else
872     {
873       Simulator::Stop (Seconds (simTime));
874     }
875 
876   lteHelper->EnableMacTraces ();
877   lteHelper->EnableRlcTraces ();
878   if (epc)
879     {
880       lteHelper->EnablePdcpTraces ();
881     }
882 
883   Simulator::Run ();
884 
885   //GtkConfigStore config;
886   //config.ConfigureAttributes ();
887 
888   lteHelper = 0;
889   Simulator::Destroy ();
890   return 0;
891 }
892