1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  *
16  * Author: George F. Riley<riley@ece.gatech.edu>
17  */
18 
19 // Implement an object to create a dumbbell topology.
20 
21 #include <cmath>
22 #include <iostream>
23 #include <sstream>
24 
25 // ns3 includes
26 #include "ns3/log.h"
27 #include "ns3/point-to-point-dumbbell.h"
28 #include "ns3/constant-position-mobility-model.h"
29 
30 #include "ns3/node-list.h"
31 #include "ns3/point-to-point-net-device.h"
32 #include "ns3/vector.h"
33 #include "ns3/ipv6-address-generator.h"
34 
35 namespace ns3 {
36 
37 NS_LOG_COMPONENT_DEFINE ("PointToPointDumbbellHelper");
38 
PointToPointDumbbellHelper(uint32_t nLeftLeaf,PointToPointHelper leftHelper,uint32_t nRightLeaf,PointToPointHelper rightHelper,PointToPointHelper bottleneckHelper)39 PointToPointDumbbellHelper::PointToPointDumbbellHelper (uint32_t nLeftLeaf,
40                                                         PointToPointHelper leftHelper,
41                                                         uint32_t nRightLeaf,
42                                                         PointToPointHelper rightHelper,
43                                                         PointToPointHelper bottleneckHelper)
44 {
45   // Create the bottleneck routers
46   m_routers.Create (2);
47   // Create the leaf nodes
48   m_leftLeaf.Create (nLeftLeaf);
49   m_rightLeaf.Create (nRightLeaf);
50 
51   // Add the link connecting routers
52   m_routerDevices = bottleneckHelper.Install (m_routers);
53   // Add the left side links
54   for (uint32_t i = 0; i < nLeftLeaf; ++i)
55     {
56       NetDeviceContainer c = leftHelper.Install (m_routers.Get (0),
57                                                  m_leftLeaf.Get (i));
58       m_leftRouterDevices.Add (c.Get (0));
59       m_leftLeafDevices.Add (c.Get (1));
60     }
61   // Add the right side links
62   for (uint32_t i = 0; i < nRightLeaf; ++i)
63     {
64       NetDeviceContainer c = rightHelper.Install (m_routers.Get (1),
65                                                   m_rightLeaf.Get (i));
66       m_rightRouterDevices.Add (c.Get (0));
67       m_rightLeafDevices.Add (c.Get (1));
68     }
69 }
70 
~PointToPointDumbbellHelper()71 PointToPointDumbbellHelper::~PointToPointDumbbellHelper ()
72 {
73 }
74 
GetLeft() const75 Ptr<Node> PointToPointDumbbellHelper::GetLeft () const
76 { // Get the left side bottleneck router
77   return m_routers.Get (0);
78 }
79 
GetLeft(uint32_t i) const80 Ptr<Node> PointToPointDumbbellHelper::GetLeft (uint32_t i) const
81 { // Get the i'th left side leaf
82   return m_leftLeaf.Get (i);
83 }
84 
GetRight() const85 Ptr<Node> PointToPointDumbbellHelper::GetRight () const
86 { // Get the right side bottleneck router
87   return m_routers.Get (1);
88 }
89 
GetRight(uint32_t i) const90 Ptr<Node> PointToPointDumbbellHelper::GetRight (uint32_t i) const
91 { // Get the i'th right side leaf
92   return m_rightLeaf.Get (i);
93 }
94 
GetLeftIpv4Address(uint32_t i) const95 Ipv4Address PointToPointDumbbellHelper::GetLeftIpv4Address (uint32_t i) const
96 {
97   return m_leftLeafInterfaces.GetAddress (i);
98 }
99 
GetRightIpv4Address(uint32_t i) const100 Ipv4Address PointToPointDumbbellHelper::GetRightIpv4Address (uint32_t i) const
101 {
102   return m_rightLeafInterfaces.GetAddress (i);
103 }
104 
GetLeftIpv6Address(uint32_t i) const105 Ipv6Address PointToPointDumbbellHelper::GetLeftIpv6Address (uint32_t i) const
106 {
107   return m_leftLeafInterfaces6.GetAddress (i, 1);
108 }
109 
GetRightIpv6Address(uint32_t i) const110 Ipv6Address PointToPointDumbbellHelper::GetRightIpv6Address (uint32_t i) const
111 {
112   return m_rightLeafInterfaces6.GetAddress (i, 1);
113 }
114 
LeftCount() const115 uint32_t  PointToPointDumbbellHelper::LeftCount () const
116 { // Number of left side nodes
117   return m_leftLeaf.GetN ();
118 }
119 
RightCount() const120 uint32_t  PointToPointDumbbellHelper::RightCount () const
121 { // Number of right side nodes
122   return m_rightLeaf.GetN ();
123 }
124 
InstallStack(InternetStackHelper stack)125 void PointToPointDumbbellHelper::InstallStack (InternetStackHelper stack)
126 {
127   stack.Install (m_routers);
128   stack.Install (m_leftLeaf);
129   stack.Install (m_rightLeaf);
130 }
131 
AssignIpv4Addresses(Ipv4AddressHelper leftIp,Ipv4AddressHelper rightIp,Ipv4AddressHelper routerIp)132 void PointToPointDumbbellHelper::AssignIpv4Addresses (Ipv4AddressHelper leftIp,
133                                                       Ipv4AddressHelper rightIp,
134                                                       Ipv4AddressHelper routerIp)
135 {
136   // Assign the router network
137   m_routerInterfaces = routerIp.Assign (m_routerDevices);
138   // Assign to left side
139   for (uint32_t i = 0; i < LeftCount (); ++i)
140     {
141       NetDeviceContainer ndc;
142       ndc.Add (m_leftLeafDevices.Get (i));
143       ndc.Add (m_leftRouterDevices.Get (i));
144       Ipv4InterfaceContainer ifc = leftIp.Assign (ndc);
145       m_leftLeafInterfaces.Add (ifc.Get (0));
146       m_leftRouterInterfaces.Add (ifc.Get (1));
147       leftIp.NewNetwork ();
148     }
149   // Assign to right side
150   for (uint32_t i = 0; i < RightCount (); ++i)
151     {
152       NetDeviceContainer ndc;
153       ndc.Add (m_rightLeafDevices.Get (i));
154       ndc.Add (m_rightRouterDevices.Get (i));
155       Ipv4InterfaceContainer ifc = rightIp.Assign (ndc);
156       m_rightLeafInterfaces.Add (ifc.Get (0));
157       m_rightRouterInterfaces.Add (ifc.Get (1));
158       rightIp.NewNetwork ();
159     }
160 }
161 
AssignIpv6Addresses(Ipv6Address addrBase,Ipv6Prefix prefix)162 void PointToPointDumbbellHelper::AssignIpv6Addresses (Ipv6Address addrBase, Ipv6Prefix prefix)
163 {
164   // Assign the router network
165   Ipv6AddressGenerator::Init (addrBase, prefix);
166   Ipv6Address v6network;
167   Ipv6AddressHelper addressHelper;
168 
169   v6network = Ipv6AddressGenerator::GetNetwork (prefix);
170   addressHelper.SetBase (v6network, prefix);
171   m_routerInterfaces6 = addressHelper.Assign (m_routerDevices);
172   Ipv6AddressGenerator::NextNetwork (prefix);
173 
174   // Assign to left side
175   for (uint32_t i = 0; i < LeftCount (); ++i)
176     {
177       v6network = Ipv6AddressGenerator::GetNetwork (prefix);
178       addressHelper.SetBase (v6network, prefix);
179 
180       NetDeviceContainer ndc;
181       ndc.Add (m_leftLeafDevices.Get (i));
182       ndc.Add (m_leftRouterDevices.Get (i));
183       Ipv6InterfaceContainer ifc = addressHelper.Assign (ndc);
184       Ipv6InterfaceContainer::Iterator it = ifc.Begin ();
185       m_leftLeafInterfaces6.Add ((*it).first, (*it).second);
186       it++;
187       m_leftRouterInterfaces6.Add ((*it).first, (*it).second);
188       Ipv6AddressGenerator::NextNetwork (prefix);
189     }
190   // Assign to right side
191   for (uint32_t i = 0; i < RightCount (); ++i)
192     {
193       v6network = Ipv6AddressGenerator::GetNetwork (prefix);
194       addressHelper.SetBase (v6network, prefix);
195 
196       NetDeviceContainer ndc;
197       ndc.Add (m_rightLeafDevices.Get (i));
198       ndc.Add (m_rightRouterDevices.Get (i));
199       Ipv6InterfaceContainer ifc = addressHelper.Assign (ndc);
200       Ipv6InterfaceContainer::Iterator it = ifc.Begin ();
201       m_rightLeafInterfaces6.Add ((*it).first, (*it).second);
202       it++;
203       m_rightRouterInterfaces6.Add ((*it).first, (*it).second);
204       Ipv6AddressGenerator::NextNetwork (prefix);
205     }
206 }
207 
208 
BoundingBox(double ulx,double uly,double lrx,double lry)209 void PointToPointDumbbellHelper::BoundingBox (double ulx, double uly, // Upper left x/y
210                                               double lrx, double lry) // Lower right x/y
211 {
212   double xDist;
213   double yDist;
214   if (lrx > ulx)
215     {
216       xDist = lrx - ulx;
217     }
218   else
219     {
220       xDist = ulx - lrx;
221     }
222   if (lry > uly)
223     {
224       yDist = lry - uly;
225     }
226   else
227     {
228       yDist = uly - lry;
229     }
230 
231   double xAdder = xDist / 3.0;
232   double  thetaL = M_PI / (LeftCount () + 1.0);
233   double  thetaR = M_PI / (RightCount () + 1.0);
234 
235   // Place the left router
236   Ptr<Node> lr = GetLeft ();
237   Ptr<ConstantPositionMobilityModel> loc = lr->GetObject<ConstantPositionMobilityModel> ();
238   if (loc == 0)
239     {
240       loc = CreateObject<ConstantPositionMobilityModel> ();
241       lr->AggregateObject (loc);
242     }
243   Vector lrl (ulx + xAdder, uly + yDist/2.0, 0);
244   loc->SetPosition (lrl);
245 
246   // Place the right router
247   Ptr<Node> rr = GetRight ();
248   loc = rr->GetObject<ConstantPositionMobilityModel> ();
249   if (loc == 0)
250     {
251       loc = CreateObject<ConstantPositionMobilityModel> ();
252       rr->AggregateObject (loc);
253     }
254   Vector rrl (ulx + xAdder * 2, uly + yDist/2.0, 0); // Right router location
255   loc->SetPosition (rrl);
256 
257   // Place the left leaf nodes
258   double theta = -M_PI_2 + thetaL;
259   for (uint32_t l = 0; l < LeftCount (); ++l)
260     {
261       // Make them in a circular pattern to make all line lengths the same
262       // Special case when theta = 0, to be sure we get a straight line
263       if ((LeftCount () % 2) == 1)
264         { // Count is odd, see if we are in middle
265           if (l == (LeftCount () / 2))
266             {
267               theta = 0.0;
268             }
269         }
270       Ptr<Node> ln = GetLeft (l);
271       loc = ln->GetObject<ConstantPositionMobilityModel> ();
272       if (loc == 0)
273         {
274           loc = CreateObject<ConstantPositionMobilityModel> ();
275           ln->AggregateObject (loc);
276         }
277       Vector lnl (lrl.x - std::cos (theta) * xAdder,
278                   lrl.y + std::sin (theta) * xAdder, 0);   // Left Node Location
279       // Insure did not exceed bounding box
280       if (lnl.y < uly)
281         {
282           lnl.y = uly; // Set to upper left y
283         }
284       if (lnl.y > lry)
285         {
286           lnl.y = lry; // Set to lower right y
287         }
288       loc->SetPosition (lnl);
289       theta += thetaL;
290     }
291   // Place the right nodes
292   theta = -M_PI_2 + thetaR;
293   for (uint32_t r = 0; r < RightCount (); ++r)
294     {
295       // Special case when theta = 0, to be sure we get a straight line
296       if ((RightCount () % 2) == 1)
297         { // Count is odd, see if we are in middle
298           if (r == (RightCount () / 2))
299             {
300               theta = 0.0;
301             }
302         }
303       Ptr<Node> rn = GetRight (r);
304       loc = rn->GetObject<ConstantPositionMobilityModel> ();
305       if (loc == 0)
306         {
307           loc = CreateObject<ConstantPositionMobilityModel> ();
308           rn->AggregateObject (loc);
309         }
310       Vector rnl (rrl.x + std::cos (theta) * xAdder, // Right node location
311                   rrl.y + std::sin (theta) * xAdder, 0);
312       // Insure did not exceed bounding box
313       if (rnl.y < uly)
314         {
315           rnl.y = uly; // Set to upper left y
316         }
317       if (rnl.y > lry)
318         {
319           rnl.y = lry; // Set to lower right y
320         }
321       loc->SetPosition (rnl);
322       theta += thetaR;
323     }
324 }
325 
326 } // namespace ns3
327