1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright 2007 University of Washington
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  * Authors:  Tom Henderson (tomhend@u.washington.edu)
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/assert.h"
23 #include "ns3/abort.h"
24 #include "ns3/channel.h"
25 #include "ns3/net-device.h"
26 #include "ns3/node.h"
27 #include "ns3/node-list.h"
28 #include "ns3/ipv4.h"
29 #include "ns3/bridge-net-device.h"
30 #include "ipv4-global-routing.h"
31 #include "global-router-interface.h"
32 #include "loopback-net-device.h"
33 #include <vector>
34 
35 namespace ns3 {
36 
37 NS_LOG_COMPONENT_DEFINE ("GlobalRouter");
38 
39 // ---------------------------------------------------------------------------
40 //
41 // GlobalRoutingLinkRecord Implementation
42 //
43 // ---------------------------------------------------------------------------
44 
GlobalRoutingLinkRecord()45 GlobalRoutingLinkRecord::GlobalRoutingLinkRecord ()
46   :
47     m_linkId ("0.0.0.0"),
48     m_linkData ("0.0.0.0"),
49     m_linkType (Unknown),
50     m_metric (0)
51 {
52   NS_LOG_FUNCTION (this);
53 }
54 
GlobalRoutingLinkRecord(LinkType linkType,Ipv4Address linkId,Ipv4Address linkData,uint16_t metric)55 GlobalRoutingLinkRecord::GlobalRoutingLinkRecord (
56   LinkType    linkType,
57   Ipv4Address linkId,
58   Ipv4Address linkData,
59   uint16_t    metric)
60   :
61     m_linkId (linkId),
62     m_linkData (linkData),
63     m_linkType (linkType),
64     m_metric (metric)
65 {
66   NS_LOG_FUNCTION (this << linkType << linkId << linkData << metric);
67 }
68 
~GlobalRoutingLinkRecord()69 GlobalRoutingLinkRecord::~GlobalRoutingLinkRecord ()
70 {
71   NS_LOG_FUNCTION (this);
72 }
73 
74 Ipv4Address
GetLinkId(void) const75 GlobalRoutingLinkRecord::GetLinkId (void) const
76 {
77   NS_LOG_FUNCTION (this);
78   return m_linkId;
79 }
80 
81 void
SetLinkId(Ipv4Address addr)82 GlobalRoutingLinkRecord::SetLinkId (Ipv4Address addr)
83 {
84   NS_LOG_FUNCTION (this << addr);
85   m_linkId = addr;
86 }
87 
88 Ipv4Address
GetLinkData(void) const89 GlobalRoutingLinkRecord::GetLinkData (void) const
90 {
91   NS_LOG_FUNCTION (this);
92   return m_linkData;
93 }
94 
95 void
SetLinkData(Ipv4Address addr)96 GlobalRoutingLinkRecord::SetLinkData (Ipv4Address addr)
97 {
98   NS_LOG_FUNCTION (this << addr);
99   m_linkData = addr;
100 }
101 
102 GlobalRoutingLinkRecord::LinkType
GetLinkType(void) const103 GlobalRoutingLinkRecord::GetLinkType (void) const
104 {
105   NS_LOG_FUNCTION (this);
106   return m_linkType;
107 }
108 
109 void
SetLinkType(GlobalRoutingLinkRecord::LinkType linkType)110 GlobalRoutingLinkRecord::SetLinkType (
111   GlobalRoutingLinkRecord::LinkType linkType)
112 {
113   NS_LOG_FUNCTION (this << linkType);
114   m_linkType = linkType;
115 }
116 
117 uint16_t
GetMetric(void) const118 GlobalRoutingLinkRecord::GetMetric (void) const
119 {
120   NS_LOG_FUNCTION (this);
121   return m_metric;
122 }
123 
124 void
SetMetric(uint16_t metric)125 GlobalRoutingLinkRecord::SetMetric (uint16_t metric)
126 {
127   NS_LOG_FUNCTION (this << metric);
128   m_metric = metric;
129 }
130 
131 // ---------------------------------------------------------------------------
132 //
133 // GlobalRoutingLSA Implementation
134 //
135 // ---------------------------------------------------------------------------
136 
GlobalRoutingLSA()137 GlobalRoutingLSA::GlobalRoutingLSA()
138   :
139     m_lsType (GlobalRoutingLSA::Unknown),
140     m_linkStateId ("0.0.0.0"),
141     m_advertisingRtr ("0.0.0.0"),
142     m_linkRecords (),
143     m_networkLSANetworkMask ("0.0.0.0"),
144     m_attachedRouters (),
145     m_status (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED),
146     m_node_id (0)
147 {
148   NS_LOG_FUNCTION (this);
149 }
150 
GlobalRoutingLSA(GlobalRoutingLSA::SPFStatus status,Ipv4Address linkStateId,Ipv4Address advertisingRtr)151 GlobalRoutingLSA::GlobalRoutingLSA (
152   GlobalRoutingLSA::SPFStatus status,
153   Ipv4Address linkStateId,
154   Ipv4Address advertisingRtr)
155   :
156     m_lsType (GlobalRoutingLSA::Unknown),
157     m_linkStateId (linkStateId),
158     m_advertisingRtr (advertisingRtr),
159     m_linkRecords (),
160     m_networkLSANetworkMask ("0.0.0.0"),
161     m_attachedRouters (),
162     m_status (status),
163     m_node_id (0)
164 {
165   NS_LOG_FUNCTION (this << status << linkStateId << advertisingRtr);
166 }
167 
GlobalRoutingLSA(GlobalRoutingLSA & lsa)168 GlobalRoutingLSA::GlobalRoutingLSA (GlobalRoutingLSA& lsa)
169   : m_lsType (lsa.m_lsType), m_linkStateId (lsa.m_linkStateId),
170     m_advertisingRtr (lsa.m_advertisingRtr),
171     m_networkLSANetworkMask (lsa.m_networkLSANetworkMask),
172     m_status (lsa.m_status),
173     m_node_id (lsa.m_node_id)
174 {
175   NS_LOG_FUNCTION (this << &lsa);
176   NS_ASSERT_MSG (IsEmpty (),
177                  "GlobalRoutingLSA::GlobalRoutingLSA (): Non-empty LSA in constructor");
178   CopyLinkRecords (lsa);
179 }
180 
181 GlobalRoutingLSA&
operator =(const GlobalRoutingLSA & lsa)182 GlobalRoutingLSA::operator= (const GlobalRoutingLSA& lsa)
183 {
184   NS_LOG_FUNCTION (this << &lsa);
185   m_lsType = lsa.m_lsType;
186   m_linkStateId = lsa.m_linkStateId;
187   m_advertisingRtr = lsa.m_advertisingRtr;
188   m_networkLSANetworkMask = lsa.m_networkLSANetworkMask,
189   m_status = lsa.m_status;
190   m_node_id = lsa.m_node_id;
191 
192   ClearLinkRecords ();
193   CopyLinkRecords (lsa);
194   return *this;
195 }
196 
197 void
CopyLinkRecords(const GlobalRoutingLSA & lsa)198 GlobalRoutingLSA::CopyLinkRecords (const GlobalRoutingLSA& lsa)
199 {
200   NS_LOG_FUNCTION (this << &lsa);
201   for (ListOfLinkRecords_t::const_iterator i = lsa.m_linkRecords.begin ();
202        i != lsa.m_linkRecords.end ();
203        i++)
204     {
205       GlobalRoutingLinkRecord *pSrc = *i;
206       GlobalRoutingLinkRecord *pDst = new GlobalRoutingLinkRecord;
207 
208       pDst->SetLinkType (pSrc->GetLinkType ());
209       pDst->SetLinkId (pSrc->GetLinkId ());
210       pDst->SetLinkData (pSrc->GetLinkData ());
211       pDst->SetMetric (pSrc->GetMetric ());
212 
213       m_linkRecords.push_back (pDst);
214       pDst = 0;
215     }
216 
217   m_attachedRouters = lsa.m_attachedRouters;
218 }
219 
~GlobalRoutingLSA()220 GlobalRoutingLSA::~GlobalRoutingLSA()
221 {
222   NS_LOG_FUNCTION (this);
223   ClearLinkRecords ();
224 }
225 
226 void
ClearLinkRecords(void)227 GlobalRoutingLSA::ClearLinkRecords (void)
228 {
229   NS_LOG_FUNCTION (this);
230   for ( ListOfLinkRecords_t::iterator i = m_linkRecords.begin ();
231         i != m_linkRecords.end ();
232         i++)
233     {
234       NS_LOG_LOGIC ("Free link record");
235 
236       GlobalRoutingLinkRecord *p = *i;
237       delete p;
238       p = 0;
239 
240       *i = 0;
241     }
242   NS_LOG_LOGIC ("Clear list");
243   m_linkRecords.clear ();
244 }
245 
246 uint32_t
AddLinkRecord(GlobalRoutingLinkRecord * lr)247 GlobalRoutingLSA::AddLinkRecord (GlobalRoutingLinkRecord* lr)
248 {
249   NS_LOG_FUNCTION (this << lr);
250   m_linkRecords.push_back (lr);
251   return m_linkRecords.size ();
252 }
253 
254 uint32_t
GetNLinkRecords(void) const255 GlobalRoutingLSA::GetNLinkRecords (void) const
256 {
257   NS_LOG_FUNCTION (this);
258   return m_linkRecords.size ();
259 }
260 
261 GlobalRoutingLinkRecord *
GetLinkRecord(uint32_t n) const262 GlobalRoutingLSA::GetLinkRecord (uint32_t n) const
263 {
264   NS_LOG_FUNCTION (this << n);
265   uint32_t j = 0;
266   for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
267         i != m_linkRecords.end ();
268         i++, j++)
269     {
270       if (j == n)
271         {
272           return *i;
273         }
274     }
275   NS_ASSERT_MSG (false, "GlobalRoutingLSA::GetLinkRecord (): invalid index");
276   return 0;
277 }
278 
279 bool
IsEmpty(void) const280 GlobalRoutingLSA::IsEmpty (void) const
281 {
282   NS_LOG_FUNCTION (this);
283   return m_linkRecords.size () == 0;
284 }
285 
286 GlobalRoutingLSA::LSType
GetLSType(void) const287 GlobalRoutingLSA::GetLSType (void) const
288 {
289   NS_LOG_FUNCTION (this);
290   return m_lsType;
291 }
292 
293 void
SetLSType(GlobalRoutingLSA::LSType typ)294 GlobalRoutingLSA::SetLSType (GlobalRoutingLSA::LSType typ)
295 {
296   NS_LOG_FUNCTION (this << typ);
297   m_lsType = typ;
298 }
299 
300 Ipv4Address
GetLinkStateId(void) const301 GlobalRoutingLSA::GetLinkStateId (void) const
302 {
303   NS_LOG_FUNCTION (this);
304   return m_linkStateId;
305 }
306 
307 void
SetLinkStateId(Ipv4Address addr)308 GlobalRoutingLSA::SetLinkStateId (Ipv4Address addr)
309 {
310   NS_LOG_FUNCTION (this << addr);
311   m_linkStateId = addr;
312 }
313 
314 Ipv4Address
GetAdvertisingRouter(void) const315 GlobalRoutingLSA::GetAdvertisingRouter (void) const
316 {
317   NS_LOG_FUNCTION (this);
318   return m_advertisingRtr;
319 }
320 
321 void
SetAdvertisingRouter(Ipv4Address addr)322 GlobalRoutingLSA::SetAdvertisingRouter (Ipv4Address addr)
323 {
324   NS_LOG_FUNCTION (this << addr);
325   m_advertisingRtr = addr;
326 }
327 
328 void
SetNetworkLSANetworkMask(Ipv4Mask mask)329 GlobalRoutingLSA::SetNetworkLSANetworkMask (Ipv4Mask mask)
330 {
331   NS_LOG_FUNCTION (this << mask);
332   m_networkLSANetworkMask = mask;
333 }
334 
335 Ipv4Mask
GetNetworkLSANetworkMask(void) const336 GlobalRoutingLSA::GetNetworkLSANetworkMask (void) const
337 {
338   NS_LOG_FUNCTION (this);
339   return m_networkLSANetworkMask;
340 }
341 
342 GlobalRoutingLSA::SPFStatus
GetStatus(void) const343 GlobalRoutingLSA::GetStatus (void) const
344 {
345   NS_LOG_FUNCTION (this);
346   return m_status;
347 }
348 
349 uint32_t
AddAttachedRouter(Ipv4Address addr)350 GlobalRoutingLSA::AddAttachedRouter (Ipv4Address addr)
351 {
352   NS_LOG_FUNCTION (this << addr);
353   m_attachedRouters.push_back (addr);
354   return m_attachedRouters.size ();
355 }
356 
357 uint32_t
GetNAttachedRouters(void) const358 GlobalRoutingLSA::GetNAttachedRouters (void) const
359 {
360   NS_LOG_FUNCTION (this);
361   return m_attachedRouters.size ();
362 }
363 
364 Ipv4Address
GetAttachedRouter(uint32_t n) const365 GlobalRoutingLSA::GetAttachedRouter (uint32_t n) const
366 {
367   NS_LOG_FUNCTION (this << n);
368   uint32_t j = 0;
369   for ( ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin ();
370         i != m_attachedRouters.end ();
371         i++, j++)
372     {
373       if (j == n)
374         {
375           return *i;
376         }
377     }
378   NS_ASSERT_MSG (false, "GlobalRoutingLSA::GetAttachedRouter (): invalid index");
379   return Ipv4Address ("0.0.0.0");
380 }
381 
382 void
SetStatus(GlobalRoutingLSA::SPFStatus status)383 GlobalRoutingLSA::SetStatus (GlobalRoutingLSA::SPFStatus status)
384 {
385   NS_LOG_FUNCTION (this << status);
386   m_status = status;
387 }
388 
389 Ptr<Node>
GetNode(void) const390 GlobalRoutingLSA::GetNode (void) const
391 {
392   NS_LOG_FUNCTION (this);
393   return NodeList::GetNode (m_node_id);
394 }
395 
396 void
SetNode(Ptr<Node> node)397 GlobalRoutingLSA::SetNode (Ptr<Node> node)
398 {
399   NS_LOG_FUNCTION (this << node);
400   m_node_id = node->GetId ();
401 }
402 
403 void
Print(std::ostream & os) const404 GlobalRoutingLSA::Print (std::ostream &os) const
405 {
406   NS_LOG_FUNCTION (this << &os);
407   os << std::endl;
408   os << "========== Global Routing LSA ==========" << std::endl;
409   os << "m_lsType = " << m_lsType;
410   if (m_lsType == GlobalRoutingLSA::RouterLSA)
411     {
412       os << " (GlobalRoutingLSA::RouterLSA)";
413     }
414   else if (m_lsType == GlobalRoutingLSA::NetworkLSA)
415     {
416       os << " (GlobalRoutingLSA::NetworkLSA)";
417     }
418   else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
419     {
420       os << " (GlobalRoutingLSA::ASExternalLSA)";
421     }
422   else
423     {
424       os << "(Unknown LSType)";
425     }
426   os << std::endl;
427 
428   os << "m_linkStateId = " << m_linkStateId << " (Router ID)" << std::endl;
429   os << "m_advertisingRtr = " << m_advertisingRtr << " (Router ID)" << std::endl;
430 
431   if (m_lsType == GlobalRoutingLSA::RouterLSA)
432     {
433       for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
434             i != m_linkRecords.end ();
435             i++)
436         {
437           GlobalRoutingLinkRecord *p = *i;
438 
439           os << "---------- RouterLSA Link Record ----------" << std::endl;
440           os << "m_linkType = " << p->m_linkType;
441           if (p->m_linkType == GlobalRoutingLinkRecord::PointToPoint)
442             {
443               os << " (GlobalRoutingLinkRecord::PointToPoint)" << std::endl;
444               os << "m_linkId = " << p->m_linkId << std::endl;
445               os << "m_linkData = " << p->m_linkData << std::endl;
446               os << "m_metric = " << p->m_metric << std::endl;
447             }
448           else if (p->m_linkType == GlobalRoutingLinkRecord::TransitNetwork)
449             {
450               os << " (GlobalRoutingLinkRecord::TransitNetwork)" << std::endl;
451               os << "m_linkId = " << p->m_linkId << " (Designated router for network)" << std::endl;
452               os << "m_linkData = " << p->m_linkData << " (This router's IP address)" << std::endl;
453               os << "m_metric = " << p->m_metric << std::endl;
454             }
455           else if (p->m_linkType == GlobalRoutingLinkRecord::StubNetwork)
456             {
457               os << " (GlobalRoutingLinkRecord::StubNetwork)" << std::endl;
458               os << "m_linkId = " << p->m_linkId << " (Network number of attached network)" << std::endl;
459               os << "m_linkData = " << p->m_linkData << " (Network mask of attached network)" << std::endl;
460               os << "m_metric = " << p->m_metric << std::endl;
461             }
462           else
463             {
464               os << " (Unknown LinkType)" << std::endl;
465               os << "m_linkId = " << p->m_linkId << std::endl;
466               os << "m_linkData = " << p->m_linkData << std::endl;
467               os << "m_metric = " << p->m_metric << std::endl;
468             }
469           os << "---------- End RouterLSA Link Record ----------" << std::endl;
470         }
471     }
472   else if (m_lsType == GlobalRoutingLSA::NetworkLSA)
473     {
474       os << "---------- NetworkLSA Link Record ----------" << std::endl;
475       os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
476       for ( ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin (); i != m_attachedRouters.end (); i++)
477         {
478           Ipv4Address p = *i;
479           os << "attachedRouter = " << p << std::endl;
480         }
481       os << "---------- End NetworkLSA Link Record ----------" << std::endl;
482     }
483   else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
484     {
485       os << "---------- ASExternalLSA Link Record --------" << std::endl;
486       os << "m_linkStateId = " << m_linkStateId << std::endl;
487       os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
488     }
489   else
490     {
491       NS_ASSERT_MSG (0, "Illegal LSA LSType: " << m_lsType);
492     }
493   os << "========== End Global Routing LSA ==========" << std::endl;
494 }
495 
operator <<(std::ostream & os,GlobalRoutingLSA & lsa)496 std::ostream& operator<< (std::ostream& os, GlobalRoutingLSA& lsa)
497 {
498   lsa.Print (os);
499   return os;
500 }
501 
502 // ---------------------------------------------------------------------------
503 //
504 // GlobalRouter Implementation
505 //
506 // ---------------------------------------------------------------------------
507 
508 NS_OBJECT_ENSURE_REGISTERED (GlobalRouter);
509 
510 TypeId
GetTypeId(void)511 GlobalRouter::GetTypeId (void)
512 {
513   static TypeId tid = TypeId ("ns3::GlobalRouter")
514     .SetParent<Object> ()
515     .SetGroupName ("Internet");
516   return tid;
517 }
518 
GlobalRouter()519 GlobalRouter::GlobalRouter ()
520   : m_LSAs ()
521 {
522   NS_LOG_FUNCTION (this);
523   m_routerId.Set (GlobalRouteManager::AllocateRouterId ());
524 }
525 
~GlobalRouter()526 GlobalRouter::~GlobalRouter ()
527 {
528   NS_LOG_FUNCTION (this);
529   ClearLSAs ();
530 }
531 
532 void
SetRoutingProtocol(Ptr<Ipv4GlobalRouting> routing)533 GlobalRouter::SetRoutingProtocol (Ptr<Ipv4GlobalRouting> routing)
534 {
535   NS_LOG_FUNCTION (this << routing);
536   m_routingProtocol = routing;
537 }
538 Ptr<Ipv4GlobalRouting>
GetRoutingProtocol(void)539 GlobalRouter::GetRoutingProtocol (void)
540 {
541   NS_LOG_FUNCTION (this);
542   return m_routingProtocol;
543 }
544 
545 void
DoDispose()546 GlobalRouter::DoDispose ()
547 {
548   NS_LOG_FUNCTION (this);
549   m_routingProtocol = 0;
550   for (InjectedRoutesI k = m_injectedRoutes.begin ();
551        k != m_injectedRoutes.end ();
552        k = m_injectedRoutes.erase (k))
553     {
554       delete (*k);
555     }
556   Object::DoDispose ();
557 }
558 
559 void
ClearLSAs()560 GlobalRouter::ClearLSAs ()
561 {
562   NS_LOG_FUNCTION (this);
563   for ( ListOfLSAs_t::iterator i = m_LSAs.begin ();
564         i != m_LSAs.end ();
565         i++)
566     {
567       NS_LOG_LOGIC ("Free LSA");
568 
569       GlobalRoutingLSA *p = *i;
570       delete p;
571       p = 0;
572 
573       *i = 0;
574     }
575   NS_LOG_LOGIC ("Clear list of LSAs");
576   m_LSAs.clear ();
577 }
578 
579 Ipv4Address
GetRouterId(void) const580 GlobalRouter::GetRouterId (void) const
581 {
582   NS_LOG_FUNCTION (this);
583   return m_routerId;
584 }
585 
586 //
587 // DiscoverLSAs is called on all nodes in the system that have a GlobalRouter
588 // interface aggregated.  We need to go out and discover any adjacent routers
589 // and build the Link State Advertisements that reflect them and their associated
590 // networks.
591 //
592 uint32_t
DiscoverLSAs()593 GlobalRouter::DiscoverLSAs ()
594 {
595   NS_LOG_FUNCTION (this);
596   Ptr<Node> node = GetObject<Node> ();
597   NS_ABORT_MSG_UNLESS (node, "GlobalRouter::DiscoverLSAs (): GetObject for <Node> interface failed");
598   NS_LOG_LOGIC ("For node " << node->GetId () );
599 
600   ClearLSAs ();
601 
602   //
603   // While building the Router-LSA, keep a list of those NetDevices for
604   // which the current node is the designated router and we will later build
605   // a NetworkLSA for.
606   //
607   NetDeviceContainer c;
608 
609   //
610   // We're aggregated to a node.  We need to ask the node for a pointer to its
611   // Ipv4 interface.  This is where the information regarding the attached
612   // interfaces lives.  If we're a router, we had better have an Ipv4 interface.
613   //
614   Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
615   NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed");
616 
617   //
618   // Every router node originates a Router-LSA
619   //
620   GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
621   pLSA->SetLSType (GlobalRoutingLSA::RouterLSA);
622   pLSA->SetLinkStateId (m_routerId);
623   pLSA->SetAdvertisingRouter (m_routerId);
624   pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
625   pLSA->SetNode (node);
626 
627   //
628   // Ask the node for the number of net devices attached. This isn't necessarily
629   // equal to the number of links to adjacent nodes (other routers) as the number
630   // of devices may include those for stub networks (e.g., ethernets, etc.) and
631   // bridge devices also take up an "extra" net device.
632   //
633   uint32_t numDevices = node->GetNDevices ();
634 
635   //
636   // Iterate through the devices on the node and walk the channel to see what's
637   // on the other side of the standalone devices..
638   //
639   for (uint32_t i = 0; i < numDevices; ++i)
640     {
641       Ptr<NetDevice> ndLocal = node->GetDevice (i);
642 
643       if (DynamicCast <LoopbackNetDevice> (ndLocal))
644         {
645           continue;
646         }
647 
648       //
649       // There is an assumption that bridge ports must never have an IP address
650       // associated with them.  This turns out to be a very convenient place to
651       // check and make sure that this is the case.
652       //
653       if (NetDeviceIsBridged (ndLocal))
654         {
655           // Initialize to value out of bounds to silence compiler
656           uint32_t interfaceBridge = ipv4Local->GetNInterfaces () + 1;
657           bool rc = FindInterfaceForDevice (node, ndLocal, interfaceBridge);
658           NS_ABORT_MSG_IF (rc, "GlobalRouter::DiscoverLSAs(): Bridge ports must not have an IPv4 interface index");
659         }
660 
661       //
662       // Check to see if the net device we just got has a corresponding IP
663       // interface (could be a pure L2 NetDevice) -- for example a net device
664       // associated with a bridge.  We are only going to involve devices with
665       // IP addresses in routing.
666       //
667       bool isForwarding = false;
668       for (uint32_t j = 0; j < ipv4Local->GetNInterfaces (); ++j )
669         {
670           if (ipv4Local->GetNetDevice (j) == ndLocal && ipv4Local->IsUp (j) &&
671               ipv4Local->IsForwarding (j))
672             {
673               isForwarding = true;
674               break;
675             }
676         }
677 
678       if (!isForwarding)
679         {
680           NS_LOG_LOGIC ("Net device " << ndLocal << "has no IP interface or is not enabled for forwarding, skipping");
681           continue;
682         }
683 
684       //
685       // We have a net device that we need to check out.  If it supports
686       // broadcast and is not a point-point link, then it will be either a stub
687       // network or a transit network depending on the number of routers on
688       // the segment.  We add the appropriate link record to the LSA.
689       //
690       // If the device is a point to point link, we treat it separately.  In
691       // that case, there may be zero, one, or two link records added.
692       //
693 
694       if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () )
695         {
696           NS_LOG_LOGIC ("Broadcast link");
697           ProcessBroadcastLink (ndLocal, pLSA, c);
698         }
699       else if (ndLocal->IsPointToPoint () )
700         {
701           NS_LOG_LOGIC ("Point=to-point link");
702           ProcessPointToPointLink (ndLocal, pLSA);
703         }
704       else
705         {
706           NS_ASSERT_MSG (0, "GlobalRouter::DiscoverLSAs (): unknown link type");
707         }
708     }
709 
710   NS_LOG_LOGIC ("========== LSA for node " << node->GetId () << " ==========");
711   NS_LOG_LOGIC (*pLSA);
712   m_LSAs.push_back (pLSA);
713   pLSA = 0;
714 
715   //
716   // Now, determine whether we need to build a NetworkLSA.  This is the case if
717   // we found at least one designated router.
718   //
719   uint32_t nDesignatedRouters = c.GetN ();
720   if (nDesignatedRouters > 0)
721     {
722       NS_LOG_LOGIC ("Build Network LSAs");
723       BuildNetworkLSAs (c);
724     }
725 
726   //
727   // Build injected route LSAs as external routes
728   // RFC 2328, section 12.4.4
729   //
730   for (InjectedRoutesCI i = m_injectedRoutes.begin ();
731        i != m_injectedRoutes.end ();
732        i++)
733     {
734       GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
735       pLSA->SetLSType (GlobalRoutingLSA::ASExternalLSAs);
736       pLSA->SetLinkStateId ((*i)->GetDestNetwork ());
737       pLSA->SetAdvertisingRouter (m_routerId);
738       pLSA->SetNetworkLSANetworkMask ((*i)->GetDestNetworkMask ());
739       pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
740       m_LSAs.push_back (pLSA);
741     }
742   return m_LSAs.size ();
743 }
744 
745 void
ProcessBroadcastLink(Ptr<NetDevice> nd,GlobalRoutingLSA * pLSA,NetDeviceContainer & c)746 GlobalRouter::ProcessBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
747 {
748   NS_LOG_FUNCTION (this << nd << pLSA << &c);
749 
750   if (nd->IsBridge ())
751     {
752       ProcessBridgedBroadcastLink (nd, pLSA, c);
753     }
754   else
755     {
756       ProcessSingleBroadcastLink (nd, pLSA, c);
757     }
758 }
759 
760 void
ProcessSingleBroadcastLink(Ptr<NetDevice> nd,GlobalRoutingLSA * pLSA,NetDeviceContainer & c)761 GlobalRouter::ProcessSingleBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
762 {
763   NS_LOG_FUNCTION (this << nd << pLSA << &c);
764 
765   GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
766   NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessSingleBroadcastLink(): Can't alloc link record");
767 
768   //
769   // We have some preliminaries to do to get enough information to proceed.
770   // This information we need comes from the internet stack, so notice that
771   // there is an implied assumption that global routing is only going to
772   // work with devices attached to the internet stack (have an ipv4 interface
773   // associated to them.
774   //
775   Ptr<Node> node = nd->GetNode ();
776 
777   Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
778   NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for <Ipv4> interface failed");
779 
780   // Initialize to value out of bounds to silence compiler
781   uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
782   bool rc = FindInterfaceForDevice (node, nd, interfaceLocal);
783   NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessSingleBroadcastLink(): No interface index associated with device");
784 
785   if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
786     {
787       NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
788     }
789   Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
790   Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
791   NS_LOG_LOGIC ("Working with local address " << addrLocal);
792   uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
793 
794   //
795   // Check to see if the net device is connected to a channel/network that has
796   // another router on it.  If there is no other router on the link (but us) then
797   // this is a stub network.  If we find another router, then what we have here
798   // is a transit network.
799   //
800   ClearBridgesVisited ();
801   if (AnotherRouterOnLink (nd) == false)
802     {
803       //
804       // This is a net device connected to a stub network
805       //
806       NS_LOG_LOGIC ("Router-LSA Stub Network");
807       plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
808 
809       //
810       // According to OSPF, the Link ID is the IP network number of
811       // the attached network.
812       //
813       plr->SetLinkId (addrLocal.CombineMask (maskLocal));
814 
815       //
816       // and the Link Data is the network mask; converted to Ipv4Address
817       //
818       Ipv4Address maskLocalAddr;
819       maskLocalAddr.Set (maskLocal.Get ());
820       plr->SetLinkData (maskLocalAddr);
821       plr->SetMetric (metricLocal);
822       pLSA->AddLinkRecord (plr);
823       plr = 0;
824     }
825   else
826     {
827       //
828       // We have multiple routers on a broadcast interface, so this is
829       // a transit network.
830       //
831       NS_LOG_LOGIC ("Router-LSA Transit Network");
832       plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
833 
834       //
835       // By definition, the router with the lowest IP address is the
836       // designated router for the network.  OSPF says that the Link ID
837       // gets the IP interface address of the designated router in this
838       // case.
839       //
840       ClearBridgesVisited ();
841       Ipv4Address desigRtr;
842       desigRtr = FindDesignatedRouterForLink (nd);
843 
844       //
845       // Let's double-check that any designated router we find out on our
846       // network is really on our network.
847       //
848       if (desigRtr != "255.255.255.255")
849         {
850           Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
851           Ipv4Address networkThere = desigRtr.CombineMask (maskLocal);
852           NS_ABORT_MSG_UNLESS (networkHere == networkThere,
853                                "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion (" <<
854                                addrLocal << "/" << maskLocal.GetPrefixLength () << ", " <<
855                                desigRtr << "/" << maskLocal.GetPrefixLength () << ")");
856         }
857       if (desigRtr == addrLocal)
858         {
859           c.Add (nd);
860           NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
861         }
862       plr->SetLinkId (desigRtr);
863 
864       //
865       // OSPF says that the Link Data is this router's own IP address.
866       //
867       plr->SetLinkData (addrLocal);
868       plr->SetMetric (metricLocal);
869       pLSA->AddLinkRecord (plr);
870       plr = 0;
871     }
872 }
873 
874 void
ProcessBridgedBroadcastLink(Ptr<NetDevice> nd,GlobalRoutingLSA * pLSA,NetDeviceContainer & c)875 GlobalRouter::ProcessBridgedBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
876 {
877   NS_LOG_FUNCTION (this << nd << pLSA << &c);
878   NS_ASSERT_MSG (nd->IsBridge (), "GlobalRouter::ProcessBridgedBroadcastLink(): Called with non-bridge net device");
879 
880 #if 0
881   //
882   // It is possible to admit the possibility that a bridge device on a node
883   // can also participate in routing.  This would surprise people who don't
884   // come from Microsoft-land where they do use such a construct.  Based on
885   // the principle of least-surprise, we will leave the relatively simple
886   // code in place to do this, but not enable it until someone really wants
887   // the capability.  Even then, we will not enable this code as a default
888   // but rather something you will have to go and turn on.
889   //
890 
891   Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> ();
892   NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
893 
894   //
895   // We have some preliminaries to do to get enough information to proceed.
896   // This information we need comes from the internet stack, so notice that
897   // there is an implied assumption that global routing is only going to
898   // work with devices attached to the internet stack (have an ipv4 interface
899   // associated to them.
900   //
901   Ptr<Node> node = nd->GetNode ();
902   Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
903   NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for <Ipv4> interface failed");
904 
905   // Initialize to value out of bounds to silence compiler
906   uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
907   bool rc = FindInterfaceForDevice (node, nd, interfaceLocal);
908   NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessBridgedBroadcastLink(): No interface index associated with device");
909 
910   if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
911     {
912       NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
913     }
914   Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
915   Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
916   NS_LOG_LOGIC ("Working with local address " << addrLocal);
917   uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
918 
919   //
920   // We need to handle a bridge on the router.  This means that we have been
921   // given a net device that is a BridgeNetDevice.  It has an associated Ipv4
922   // interface index and address.  Some number of other net devices live "under"
923   // the bridge device as so-called bridge ports.  In a nutshell, what we have
924   // to do is to repeat what is done for a single broadcast link on all of
925   // those net devices living under the bridge (trolls?)
926   //
927 
928   bool areTransitNetwork = false;
929   Ipv4Address desigRtr ("255.255.255.255");
930 
931   for (uint32_t i = 0; i < bnd->GetNBridgePorts (); ++i)
932     {
933       Ptr<NetDevice> ndTemp = bnd->GetBridgePort (i);
934 
935       //
936       // We have to decide if we are a transit network.  This is characterized
937       // by the presence of another router on the network segment.  If we find
938       // another router on any of our bridged links, we are a transit network.
939       //
940       ClearBridgesVisited ();
941       if (AnotherRouterOnLink (ndTemp))
942         {
943           areTransitNetwork = true;
944 
945           //
946           // If we're going to be a transit network, then we have got to elect
947           // a designated router for the whole bridge.  This means finding the
948           // router with the lowest IP address on the whole bridge.  We ask
949           // for the lowest address on each segment and pick the lowest of them
950           // all.
951           //
952           ClearBridgesVisited ();
953           Ipv4Address desigRtrTemp = FindDesignatedRouterForLink (ndTemp);
954 
955           //
956           // Let's double-check that any designated router we find out on our
957           // network is really on our network.
958           //
959           if (desigRtrTemp != "255.255.255.255")
960             {
961               Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
962               Ipv4Address networkThere = desigRtrTemp.CombineMask (maskLocal);
963               NS_ABORT_MSG_UNLESS (networkHere == networkThere,
964                                    "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion (" <<
965                                    addrLocal << "/" << maskLocal.GetPrefixLength () << ", " <<
966                                    desigRtrTemp << "/" << maskLocal.GetPrefixLength () << ")");
967             }
968           if (desigRtrTemp < desigRtr)
969             {
970               desigRtr = desigRtrTemp;
971             }
972         }
973     }
974   //
975   // That's all the information we need to put it all together, just like we did
976   // in the case of a single broadcast link.
977   //
978 
979   GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
980   NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessBridgedBroadcastLink(): Can't alloc link record");
981 
982   if (areTransitNetwork == false)
983     {
984       //
985       // This is a net device connected to a bridge of stub networks
986       //
987       NS_LOG_LOGIC ("Router-LSA Stub Network");
988       plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
989 
990       //
991       // According to OSPF, the Link ID is the IP network number of
992       // the attached network.
993       //
994       plr->SetLinkId (addrLocal.CombineMask (maskLocal));
995 
996       //
997       // and the Link Data is the network mask; converted to Ipv4Address
998       //
999       Ipv4Address maskLocalAddr;
1000       maskLocalAddr.Set (maskLocal.Get ());
1001       plr->SetLinkData (maskLocalAddr);
1002       plr->SetMetric (metricLocal);
1003       pLSA->AddLinkRecord (plr);
1004       plr = 0;
1005     }
1006   else
1007     {
1008       //
1009       // We have multiple routers on a bridged broadcast interface, so this is
1010       // a transit network.
1011       //
1012       NS_LOG_LOGIC ("Router-LSA Transit Network");
1013       plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
1014 
1015       //
1016       // By definition, the router with the lowest IP address is the
1017       // designated router for the network.  OSPF says that the Link ID
1018       // gets the IP interface address of the designated router in this
1019       // case.
1020       //
1021       if (desigRtr == addrLocal)
1022         {
1023           c.Add (nd);
1024           NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
1025         }
1026       plr->SetLinkId (desigRtr);
1027 
1028       //
1029       // OSPF says that the Link Data is this router's own IP address.
1030       //
1031       plr->SetLinkData (addrLocal);
1032       plr->SetMetric (metricLocal);
1033       pLSA->AddLinkRecord (plr);
1034       plr = 0;
1035     }
1036 #endif
1037 }
1038 
1039 void
ProcessPointToPointLink(Ptr<NetDevice> ndLocal,GlobalRoutingLSA * pLSA)1040 GlobalRouter::ProcessPointToPointLink (Ptr<NetDevice> ndLocal, GlobalRoutingLSA *pLSA)
1041 {
1042   NS_LOG_FUNCTION (this << ndLocal << pLSA);
1043 
1044   //
1045   // We have some preliminaries to do to get enough information to proceed.
1046   // This information we need comes from the internet stack, so notice that
1047   // there is an implied assumption that global routing is only going to
1048   // work with devices attached to the internet stack (have an ipv4 interface
1049   // associated to them.
1050   //
1051   Ptr<Node> nodeLocal = ndLocal->GetNode ();
1052 
1053   Ptr<Ipv4> ipv4Local = nodeLocal->GetObject<Ipv4> ();
1054   NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1055 
1056   uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
1057   bool rc = FindInterfaceForDevice (nodeLocal, ndLocal, interfaceLocal);
1058   NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device");
1059 
1060   if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
1061     {
1062       NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1063     }
1064   Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
1065   NS_LOG_LOGIC ("Working with local address " << addrLocal);
1066   uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
1067 
1068   //
1069   // Now, we're going to walk over to the remote net device on the other end of
1070   // the point-to-point channel we know we have.  This is where our adjacent
1071   // router (to use OSPF lingo) is running.
1072   //
1073   Ptr<Channel> ch = ndLocal->GetChannel ();
1074 
1075   //
1076   // Get the net device on the other side of the point-to-point channel.
1077   //
1078   Ptr<NetDevice> ndRemote = GetAdjacent (ndLocal, ch);
1079 
1080   //
1081   // The adjacent net device is aggregated to a node.  We need to ask that net
1082   // device for its node, then ask that node for its Ipv4 interface.  Note a
1083   // requirement that nodes on either side of a point-to-point link must have
1084   // internet stacks; and an assumption that point-to-point links are incompatible
1085   // with bridging.
1086   //
1087   Ptr<Node> nodeRemote = ndRemote->GetNode ();
1088   Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4> ();
1089   NS_ABORT_MSG_UNLESS (ipv4Remote,
1090                        "GlobalRouter::ProcessPointToPointLink(): GetObject for remote <Ipv4> failed");
1091 
1092   //
1093   // Further note the requirement that nodes on either side of a point-to-point
1094   // link must participate in global routing and therefore have a GlobalRouter
1095   // interface aggregated.
1096   //
1097   Ptr<GlobalRouter> rtrRemote = nodeRemote->GetObject<GlobalRouter> ();
1098   if (rtrRemote == 0)
1099     {
1100       // This case is possible if the remote does not participate in global routing
1101       return;
1102     }
1103   //
1104   // We're going to need the remote router ID, so we might as well get it now.
1105   //
1106   Ipv4Address rtrIdRemote = rtrRemote->GetRouterId ();
1107   NS_LOG_LOGIC ("Working with remote router " << rtrIdRemote);
1108 
1109   //
1110   // Now, just like we did above, we need to get the IP interface index for the
1111   // net device on the other end of the point-to-point channel.
1112   //
1113   uint32_t interfaceRemote = ipv4Remote->GetNInterfaces () + 1;
1114   rc = FindInterfaceForDevice (nodeRemote, ndRemote, interfaceRemote);
1115   NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with remote device");
1116 
1117   //
1118   // Now that we have the Ipv4 interface, we can get the (remote) address and
1119   // mask we need.
1120   //
1121   if (ipv4Remote->GetNAddresses (interfaceRemote) > 1)
1122     {
1123       NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1124     }
1125   Ipv4Address addrRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetLocal ();
1126   Ipv4Mask maskRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetMask ();
1127   NS_LOG_LOGIC ("Working with remote address " << addrRemote);
1128 
1129   //
1130   // Now we can fill out the link records for this link.  There are always two
1131   // link records; the first is a point-to-point record describing the link and
1132   // the second is a stub network record with the network number.
1133   //
1134   GlobalRoutingLinkRecord *plr;
1135   if (ipv4Remote->IsUp (interfaceRemote))
1136     {
1137       NS_LOG_LOGIC ("Remote side interface " << interfaceRemote << " is up-- add a type 1 link");
1138 
1139       plr  = new GlobalRoutingLinkRecord;
1140       NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1141       plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
1142       plr->SetLinkId (rtrIdRemote);
1143       plr->SetLinkData (addrLocal);
1144       plr->SetMetric (metricLocal);
1145       pLSA->AddLinkRecord (plr);
1146       plr = 0;
1147     }
1148 
1149   // Regardless of state of peer, add a type 3 link (RFC 2328: 12.4.1.1)
1150   plr = new GlobalRoutingLinkRecord;
1151   NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1152   plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
1153   plr->SetLinkId (addrRemote);
1154   plr->SetLinkData (Ipv4Address (maskRemote.Get ()));  // Frown
1155   plr->SetMetric (metricLocal);
1156   pLSA->AddLinkRecord (plr);
1157   plr = 0;
1158 }
1159 
1160 void
BuildNetworkLSAs(NetDeviceContainer c)1161 GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c)
1162 {
1163   NS_LOG_FUNCTION (this << &c);
1164 
1165   uint32_t nDesignatedRouters = c.GetN ();
1166   NS_LOG_DEBUG ("Number of designated routers: " << nDesignatedRouters);
1167 
1168   for (uint32_t i = 0; i < nDesignatedRouters; ++i)
1169     {
1170       //
1171       // Build one NetworkLSA for each net device talking to a network that we are the
1172       // designated router for.  These devices are in the provided container.
1173       //
1174       Ptr<NetDevice> ndLocal = c.Get (i);
1175       Ptr<Node> node = ndLocal->GetNode ();
1176 
1177       Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
1178       NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1179 
1180       uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
1181       bool rc = FindInterfaceForDevice (node, ndLocal, interfaceLocal);
1182       NS_ABORT_MSG_IF (rc == false, "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device");
1183 
1184       if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
1185         {
1186           NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1187         }
1188       Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
1189       Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
1190 
1191       GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
1192       NS_ABORT_MSG_IF (pLSA == 0, "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record");
1193 
1194       pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA);
1195       pLSA->SetLinkStateId (addrLocal);
1196       pLSA->SetAdvertisingRouter (m_routerId);
1197       pLSA->SetNetworkLSANetworkMask (maskLocal);
1198       pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
1199       pLSA->SetNode (node);
1200 
1201       //
1202       // Build a list of AttachedRouters by walking the devices in the channel
1203       // and, if we find a node with a GlobalRouter interface and an IPv4
1204       // interface associated with that device, we call it an attached router.
1205       //
1206       ClearBridgesVisited ();
1207       Ptr<Channel> ch = ndLocal->GetChannel ();
1208       std::size_t nDevices = ch->GetNDevices ();
1209       NS_ASSERT (nDevices);
1210       NetDeviceContainer deviceList = FindAllNonBridgedDevicesOnLink (ch);
1211       NS_LOG_LOGIC ("Found " << deviceList.GetN () << " non-bridged devices on channel");
1212 
1213       for (uint32_t i = 0; i < deviceList.GetN (); i++)
1214         {
1215           Ptr<NetDevice> tempNd = deviceList.Get (i);
1216           NS_ASSERT (tempNd);
1217           if (tempNd == ndLocal)
1218             {
1219               NS_LOG_LOGIC ("Adding " << addrLocal << " to Network LSA");
1220               pLSA->AddAttachedRouter (addrLocal);
1221               continue;
1222             }
1223           Ptr<Node> tempNode = tempNd->GetNode ();
1224 
1225           // Does the node in question have a GlobalRouter interface?  If not it can
1226           // hardly be considered an attached router.
1227           //
1228           Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter> ();
1229           if (rtr == 0)
1230             {
1231               NS_LOG_LOGIC ("Node " << tempNode->GetId () << " does not have GlobalRouter interface--skipping");
1232               continue;
1233             }
1234 
1235           //
1236           // Does the attached node have an ipv4 interface for the device we're probing?
1237           // If not, it can't play router.
1238           //
1239           uint32_t tempInterface = 0;
1240           if (FindInterfaceForDevice (tempNode, tempNd, tempInterface))
1241             {
1242               Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> ();
1243               NS_ASSERT (tempIpv4);
1244               if (!tempIpv4->IsUp (tempInterface))
1245                 {
1246                   NS_LOG_LOGIC ("Remote side interface " << tempInterface << " not up");
1247                 }
1248               else
1249                 {
1250                   if (tempIpv4->GetNAddresses (tempInterface) > 1)
1251                     {
1252                       NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1253                     }
1254                   Ipv4Address tempAddr = tempIpv4->GetAddress (tempInterface, 0).GetLocal ();
1255                   NS_LOG_LOGIC ("Adding " << tempAddr << " to Network LSA");
1256                   pLSA->AddAttachedRouter (tempAddr);
1257                 }
1258             }
1259           else
1260             {
1261               NS_LOG_LOGIC ("Node " << tempNode->GetId () << " device " << tempNd << " does not have IPv4 interface; skipping");
1262             }
1263         }
1264       m_LSAs.push_back (pLSA);
1265       NS_LOG_LOGIC ("========== LSA for node " << node->GetId () << " ==========");
1266       NS_LOG_LOGIC (*pLSA);
1267       pLSA = 0;
1268     }
1269 }
1270 
1271 NetDeviceContainer
FindAllNonBridgedDevicesOnLink(Ptr<Channel> ch) const1272 GlobalRouter::FindAllNonBridgedDevicesOnLink (Ptr<Channel> ch) const
1273 {
1274   NS_LOG_FUNCTION (this << ch);
1275   NetDeviceContainer c;
1276 
1277   for (std::size_t i = 0; i < ch->GetNDevices (); i++)
1278     {
1279       Ptr<NetDevice> nd = ch->GetDevice (i);
1280       NS_LOG_LOGIC ("checking to see if the device " << nd << " is bridged");
1281       Ptr<BridgeNetDevice> bnd = NetDeviceIsBridged (nd);
1282       if (bnd && BridgeHasAlreadyBeenVisited (bnd) == false)
1283         {
1284           NS_LOG_LOGIC ("Device is bridged by BridgeNetDevice " << bnd << " with " << bnd->GetNBridgePorts () << " ports");
1285           MarkBridgeAsVisited (bnd);
1286           // Find all channels bridged together, and recursively call
1287           // on all other channels
1288           for (uint32_t j = 0; j < bnd->GetNBridgePorts (); j++)
1289             {
1290               Ptr<NetDevice> bridgedDevice = bnd->GetBridgePort (j);
1291               if (bridgedDevice->GetChannel () == ch)
1292                 {
1293                   NS_LOG_LOGIC ("Skipping my own device/channel");
1294                   continue;
1295                 }
1296               NS_LOG_LOGIC ("Calling on channel " << bridgedDevice->GetChannel ());
1297               c.Add (FindAllNonBridgedDevicesOnLink (bridgedDevice->GetChannel ()));
1298             }
1299         }
1300       else
1301         {
1302           NS_LOG_LOGIC ("Device is not bridged; adding");
1303           c.Add (nd);
1304         }
1305     }
1306   NS_LOG_LOGIC ("Found " << c.GetN () << " devices");
1307   return c;
1308 }
1309 
1310 //
1311 // Given a local net device, we need to walk the channel to which the net device is
1312 // attached and look for nodes with GlobalRouter interfaces on them (one of them
1313 // will be us).  Of these, the router with the lowest IP address on the net device
1314 // connecting to the channel becomes the designated router for the link.
1315 //
1316 Ipv4Address
FindDesignatedRouterForLink(Ptr<NetDevice> ndLocal) const1317 GlobalRouter::FindDesignatedRouterForLink (Ptr<NetDevice> ndLocal) const
1318 {
1319   NS_LOG_FUNCTION (this << ndLocal);
1320 
1321   Ptr<Channel> ch = ndLocal->GetChannel ();
1322   uint32_t nDevices = ch->GetNDevices ();
1323   NS_ASSERT (nDevices);
1324 
1325   NS_LOG_LOGIC ("Looking for designated router off of net device " << ndLocal << " on node " <<
1326                 ndLocal->GetNode ()->GetId ());
1327 
1328   Ipv4Address desigRtr ("255.255.255.255");
1329 
1330   //
1331   // Look through all of the devices on the channel to which the net device
1332   // in question is attached.
1333   //
1334   for (uint32_t i = 0; i < nDevices; i++)
1335     {
1336       Ptr<NetDevice> ndOther = ch->GetDevice (i);
1337       NS_ASSERT (ndOther);
1338 
1339       Ptr<Node> nodeOther = ndOther->GetNode ();
1340 
1341       NS_LOG_LOGIC ("Examine channel device " << i << " on node " << nodeOther->GetId ());
1342 
1343       //
1344       // For all other net devices, we need to check and see if a router
1345       // is present.  If the net device on the other side is a bridged
1346       // device, we need to consider all of the other devices on the
1347       // bridge as well (all of the bridge ports.
1348       //
1349       NS_LOG_LOGIC ("checking to see if the device is bridged");
1350       Ptr<BridgeNetDevice> bnd = NetDeviceIsBridged (ndOther);
1351       if (bnd)
1352         {
1353           NS_LOG_LOGIC ("Device is bridged by BridgeNetDevice " << bnd);
1354 
1355           //
1356           // When enumerating a bridge, don't count the netdevice we came in on
1357           //
1358           if (ndLocal == ndOther)
1359             {
1360               NS_LOG_LOGIC ("Skip -- it is where we came from.");
1361               continue;
1362             }
1363 
1364           //
1365           // It is possible that the bridge net device is sitting under a
1366           // router, so we have to check for the presence of that router
1367           // before we run off and follow all the links
1368           //
1369           // We require a designated router to have a GlobalRouter interface and
1370           // an internet stack that includes the Ipv4 interface.  If it doesn't
1371           // it can't play router.
1372           //
1373           NS_LOG_LOGIC ("Checking for router on bridge net device " << bnd);
1374           Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
1375           Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
1376           if (rtr && ipv4)
1377             {
1378               // Initialize to value out of bounds to silence compiler
1379               uint32_t interfaceOther = ipv4->GetNInterfaces () + 1;
1380               if (FindInterfaceForDevice (nodeOther, bnd, interfaceOther))
1381                 {
1382                   NS_LOG_LOGIC ("Found router on bridge net device " << bnd);
1383                   if (!ipv4->IsUp (interfaceOther))
1384                     {
1385                       NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up");
1386                       continue;
1387                     }
1388                   if (ipv4->GetNAddresses (interfaceOther) > 1)
1389                     {
1390                       NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1391                     }
1392                   Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal ();
1393                   desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1394                   NS_LOG_LOGIC ("designated router now " << desigRtr);
1395                 }
1396             }
1397 
1398           //
1399           // Check if we have seen this bridge net device already while
1400           // recursively enumerating an L2 broadcast domain. If it is new
1401           // to us, go ahead and process it. If we have already processed it,
1402           // move to the next
1403           //
1404           if(BridgeHasAlreadyBeenVisited(bnd))
1405             {
1406               NS_ABORT_MSG ("ERROR: L2 forwarding loop detected!");
1407             }
1408 
1409           MarkBridgeAsVisited(bnd);
1410 
1411           NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
1412           for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1413             {
1414               Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
1415               NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
1416               if (ndBridged == ndOther)
1417                 {
1418                   NS_LOG_LOGIC ("That bridge port is me, don't walk backward");
1419                   continue;
1420                 }
1421 
1422               NS_LOG_LOGIC ("Recursively looking for routers down bridge port " << ndBridged);
1423               Ipv4Address addrOther = FindDesignatedRouterForLink (ndBridged);
1424               desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1425               NS_LOG_LOGIC ("designated router now " << desigRtr);
1426             }
1427         }
1428       else
1429         {
1430           NS_LOG_LOGIC ("This device is not bridged");
1431           Ptr<Node> nodeOther = ndOther->GetNode ();
1432           NS_ASSERT (nodeOther);
1433 
1434           //
1435           // We require a designated router to have a GlobalRouter interface and
1436           // an internet stack that includes the Ipv4 interface.  If it doesn't
1437           //
1438           Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
1439           Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
1440           if (rtr && ipv4)
1441             {
1442               // Initialize to value out of bounds to silence compiler
1443               uint32_t interfaceOther = ipv4->GetNInterfaces () + 1;
1444               if (FindInterfaceForDevice (nodeOther, ndOther, interfaceOther))
1445                 {
1446                   if (!ipv4->IsUp (interfaceOther))
1447                     {
1448                       NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up");
1449                       continue;
1450                     }
1451                   NS_LOG_LOGIC ("Found router on net device " << ndOther);
1452                   if (ipv4->GetNAddresses (interfaceOther) > 1)
1453                     {
1454                       NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1455                     }
1456                   Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal ();
1457                   desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1458                   NS_LOG_LOGIC ("designated router now " << desigRtr);
1459                 }
1460             }
1461         }
1462     }
1463   return desigRtr;
1464 }
1465 
1466 //
1467 // Given a node and an attached net device, take a look off in the channel to
1468 // which the net device is attached and look for a node on the other side
1469 // that has a GlobalRouter interface aggregated.  Life gets more complicated
1470 // when there is a bridged net device on the other side.
1471 //
1472 bool
AnotherRouterOnLink(Ptr<NetDevice> nd) const1473 GlobalRouter::AnotherRouterOnLink (Ptr<NetDevice> nd) const
1474 {
1475   NS_LOG_FUNCTION (this << nd);
1476 
1477   Ptr<Channel> ch = nd->GetChannel ();
1478   if (!ch)
1479     {
1480       // It may be that this net device is a stub device, without a channel
1481       return false;
1482     }
1483   uint32_t nDevices = ch->GetNDevices ();
1484   NS_ASSERT (nDevices);
1485 
1486   NS_LOG_LOGIC ("Looking for routers off of net device " << nd << " on node " << nd->GetNode ()->GetId ());
1487 
1488   //
1489   // Look through all of the devices on the channel to which the net device
1490   // in question is attached.
1491   //
1492   for (uint32_t i = 0; i < nDevices; i++)
1493     {
1494       Ptr<NetDevice> ndOther = ch->GetDevice (i);
1495       NS_ASSERT (ndOther);
1496 
1497       NS_LOG_LOGIC ("Examine channel device " << i << " on node " << ndOther->GetNode ()->GetId ());
1498 
1499       //
1500       // Ignore the net device itself.
1501       //
1502       if (ndOther == nd)
1503         {
1504           NS_LOG_LOGIC ("Myself, skip");
1505           continue;
1506         }
1507 
1508       //
1509       // For all other net devices, we need to check and see if a router
1510       // is present.  If the net device on the other side is a bridged
1511       // device, we need to consider all of the other devices on the
1512       // bridge.
1513       //
1514       NS_LOG_LOGIC ("checking to see if device is bridged");
1515       Ptr<BridgeNetDevice> bnd = NetDeviceIsBridged (ndOther);
1516       if (bnd)
1517         {
1518           NS_LOG_LOGIC ("Device is bridged by net device " << bnd);
1519 
1520           //
1521           // Check if we have seen this bridge net device already while
1522           // recursively enumerating an L2 broadcast domain. If it is new
1523           // to us, go ahead and process it. If we have already processed it,
1524           // move to the next
1525           //
1526           if(BridgeHasAlreadyBeenVisited(bnd))
1527             {
1528               NS_ABORT_MSG ("ERROR: L2 forwarding loop detected!");
1529             }
1530 
1531           MarkBridgeAsVisited(bnd);
1532 
1533           NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
1534           for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1535             {
1536               Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
1537               NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
1538               if (ndBridged == ndOther)
1539                 {
1540                   NS_LOG_LOGIC ("That bridge port is me, skip");
1541                   continue;
1542                 }
1543 
1544               NS_LOG_LOGIC ("Recursively looking for routers on bridge port " << ndBridged);
1545               if (AnotherRouterOnLink (ndBridged))
1546                 {
1547                   NS_LOG_LOGIC ("Found routers on bridge port, return true");
1548                   return true;
1549                 }
1550             }
1551           NS_LOG_LOGIC ("No routers on bridged net device, return false");
1552           return false;
1553         }
1554 
1555       NS_LOG_LOGIC ("This device is not bridged");
1556       Ptr<Node> nodeTemp = ndOther->GetNode ();
1557       NS_ASSERT (nodeTemp);
1558 
1559       Ptr<GlobalRouter> rtr = nodeTemp->GetObject<GlobalRouter> ();
1560       if (rtr)
1561         {
1562           NS_LOG_LOGIC ("Found GlobalRouter interface, return true");
1563           return true;
1564         }
1565       else
1566         {
1567           NS_LOG_LOGIC ("No GlobalRouter interface on device, continue search");
1568         }
1569     }
1570   NS_LOG_LOGIC ("No routers found, return false");
1571   return false;
1572 }
1573 
1574 uint32_t
GetNumLSAs(void) const1575 GlobalRouter::GetNumLSAs (void) const
1576 {
1577   NS_LOG_FUNCTION (this);
1578   return m_LSAs.size ();
1579 }
1580 
1581 //
1582 // Get the nth link state advertisement from this router.
1583 //
1584 bool
GetLSA(uint32_t n,GlobalRoutingLSA & lsa) const1585 GlobalRouter::GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const
1586 {
1587   NS_LOG_FUNCTION (this << n << &lsa);
1588   NS_ASSERT_MSG (lsa.IsEmpty (), "GlobalRouter::GetLSA (): Must pass empty LSA");
1589 //
1590 // All of the work was done in GetNumLSAs.  All we have to do here is to
1591 // walk the list of link state advertisements created there and return the
1592 // one the client is interested in.
1593 //
1594   ListOfLSAs_t::const_iterator i = m_LSAs.begin ();
1595   uint32_t j = 0;
1596 
1597   for (; i != m_LSAs.end (); i++, j++)
1598     {
1599       if (j == n)
1600         {
1601           GlobalRoutingLSA *p = *i;
1602           lsa = *p;
1603           return true;
1604         }
1605     }
1606 
1607   return false;
1608 }
1609 
1610 void
InjectRoute(Ipv4Address network,Ipv4Mask networkMask)1611 GlobalRouter::InjectRoute (Ipv4Address network, Ipv4Mask networkMask)
1612 {
1613   NS_LOG_FUNCTION (this << network << networkMask);
1614   Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
1615 //
1616 // Interface number does not matter here, using 1.
1617 //
1618   *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
1619                                                         networkMask,
1620                                                         1);
1621   m_injectedRoutes.push_back (route);
1622 }
1623 
1624 Ipv4RoutingTableEntry *
GetInjectedRoute(uint32_t index)1625 GlobalRouter::GetInjectedRoute (uint32_t index)
1626 {
1627   NS_LOG_FUNCTION (this << index);
1628   if (index < m_injectedRoutes.size ())
1629     {
1630       uint32_t tmp = 0;
1631       for (InjectedRoutesCI i = m_injectedRoutes.begin ();
1632            i != m_injectedRoutes.end ();
1633            i++)
1634         {
1635           if (tmp  == index)
1636             {
1637               return *i;
1638             }
1639           tmp++;
1640         }
1641     }
1642   NS_ASSERT (false);
1643   // quiet compiler.
1644   return 0;
1645 }
1646 
1647 uint32_t
GetNInjectedRoutes()1648 GlobalRouter::GetNInjectedRoutes ()
1649 {
1650   NS_LOG_FUNCTION (this);
1651   return m_injectedRoutes.size ();
1652 }
1653 
1654 void
RemoveInjectedRoute(uint32_t index)1655 GlobalRouter::RemoveInjectedRoute (uint32_t index)
1656 {
1657   NS_LOG_FUNCTION (this << index);
1658   NS_ASSERT (index < m_injectedRoutes.size ());
1659   uint32_t tmp = 0;
1660   for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
1661     {
1662       if (tmp  == index)
1663         {
1664           NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_injectedRoutes.size ());
1665           delete *i;
1666           m_injectedRoutes.erase (i);
1667           return;
1668         }
1669       tmp++;
1670     }
1671 }
1672 
1673 bool
WithdrawRoute(Ipv4Address network,Ipv4Mask networkMask)1674 GlobalRouter::WithdrawRoute (Ipv4Address network, Ipv4Mask networkMask)
1675 {
1676   NS_LOG_FUNCTION (this << network << networkMask);
1677   for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
1678     {
1679       if ((*i)->GetDestNetwork () == network && (*i)->GetDestNetworkMask () == networkMask)
1680         {
1681           NS_LOG_LOGIC ("Withdrawing route to network/mask " << network << "/" << networkMask);
1682           delete *i;
1683           m_injectedRoutes.erase (i);
1684           return true;
1685         }
1686     }
1687   return false;
1688 }
1689 
1690 
1691 //
1692 // Link through the given channel and find the net device that's on the
1693 // other end.  This only makes sense with a point-to-point channel.
1694 //
1695 Ptr<NetDevice>
GetAdjacent(Ptr<NetDevice> nd,Ptr<Channel> ch) const1696 GlobalRouter::GetAdjacent (Ptr<NetDevice> nd, Ptr<Channel> ch) const
1697 {
1698   NS_LOG_FUNCTION (this << nd << ch);
1699   NS_ASSERT_MSG (ch->GetNDevices () == 2, "GlobalRouter::GetAdjacent (): Channel with other than two devices");
1700 //
1701 // This is a point to point channel with two endpoints.  Get both of them.
1702 //
1703   Ptr<NetDevice> nd1 = ch->GetDevice (0);
1704   Ptr<NetDevice> nd2 = ch->GetDevice (1);
1705 //
1706 // One of the endpoints is going to be "us" -- that is the net device attached
1707 // to the node on which we're running -- i.e., "nd".  The other endpoint (the
1708 // one to which we are connected via the channel) is the adjacent router.
1709 //
1710   if (nd1 == nd)
1711     {
1712       return nd2;
1713     }
1714   else if (nd2 == nd)
1715     {
1716       return nd1;
1717     }
1718   else
1719     {
1720       NS_ASSERT_MSG (false,
1721                      "GlobalRouter::GetAdjacent (): Wrong or confused channel?");
1722       return 0;
1723     }
1724 }
1725 
1726 //
1727 // Given a node and a net device, find an IPV4 interface index that corresponds
1728 // to that net device.  This function may fail for various reasons.  If a node
1729 // does not have an internet stack (for example if it is a bridge) we won't have
1730 // an IPv4 at all.  If the node does have a stack, but the net device in question
1731 // is bridged, there will not be an interface associated directly with the device.
1732 //
1733 bool
FindInterfaceForDevice(Ptr<Node> node,Ptr<NetDevice> nd,uint32_t & index) const1734 GlobalRouter::FindInterfaceForDevice (Ptr<Node> node, Ptr<NetDevice> nd, uint32_t &index) const
1735 {
1736   NS_LOG_FUNCTION (this << node << nd << &index);
1737   NS_LOG_LOGIC ("For node " << node->GetId () << " for net device " << nd );
1738 
1739   Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
1740   if (ipv4 == 0)
1741     {
1742       NS_LOG_LOGIC ("No Ipv4 interface on node " << node->GetId ());
1743       return false;
1744     }
1745 
1746   for (uint32_t i = 0; i < ipv4->GetNInterfaces (); ++i )
1747     {
1748       if (ipv4->GetNetDevice (i) == nd)
1749         {
1750           NS_LOG_LOGIC ("Device " << nd << " has associated ipv4 index " << i);
1751           index = i;
1752           return true;
1753         }
1754     }
1755 
1756   NS_LOG_LOGIC ("Device " << nd << " has no associated ipv4 index");
1757   return false;
1758 }
1759 
1760 //
1761 // Decide whether or not a given net device is being bridged by a BridgeNetDevice.
1762 //
1763 Ptr<BridgeNetDevice>
NetDeviceIsBridged(Ptr<NetDevice> nd) const1764 GlobalRouter::NetDeviceIsBridged (Ptr<NetDevice> nd) const
1765 {
1766   NS_LOG_FUNCTION (this << nd);
1767 
1768   Ptr<Node> node = nd->GetNode ();
1769   uint32_t nDevices = node->GetNDevices ();
1770 
1771   //
1772   // There is no bit on a net device that says it is being bridged, so we have
1773   // to look for bridges on the node to which the device is attached.  If we
1774   // find a bridge, we need to look through its bridge ports (the devices it
1775   // bridges) to see if we find the device in question.
1776   //
1777   for (uint32_t i = 0; i < nDevices; ++i)
1778     {
1779       Ptr<NetDevice> ndTest = node->GetDevice (i);
1780       NS_LOG_LOGIC ("Examine device " << i << " " << ndTest);
1781 
1782       if (ndTest->IsBridge ())
1783         {
1784           NS_LOG_LOGIC ("device " << i << " is a bridge net device");
1785           Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice> ();
1786           NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
1787 
1788           for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1789             {
1790               NS_LOG_LOGIC ("Examine bridge port " << j << " " << bnd->GetBridgePort (j));
1791               if (bnd->GetBridgePort (j) == nd)
1792                 {
1793                   NS_LOG_LOGIC ("Net device " << nd << " is bridged by " << bnd);
1794                   return bnd;
1795                 }
1796             }
1797         }
1798     }
1799   NS_LOG_LOGIC ("Net device " << nd << " is not bridged");
1800   return 0;
1801 }
1802 
1803 //
1804 // Start a new enumeration of an L2 broadcast domain by clearing m_bridgesVisited
1805 //
1806 void
ClearBridgesVisited(void) const1807 GlobalRouter::ClearBridgesVisited (void) const
1808 {
1809   m_bridgesVisited.clear();
1810 }
1811 
1812 //
1813 // Check if we have already visited a given bridge net device by searching m_bridgesVisited
1814 //
1815 bool
BridgeHasAlreadyBeenVisited(Ptr<BridgeNetDevice> bridgeNetDevice) const1816 GlobalRouter::BridgeHasAlreadyBeenVisited (Ptr<BridgeNetDevice> bridgeNetDevice) const
1817 {
1818   std::vector<Ptr<BridgeNetDevice> >::iterator iter;
1819   for (iter = m_bridgesVisited.begin (); iter != m_bridgesVisited.end (); ++iter)
1820     {
1821       if (bridgeNetDevice == *iter)
1822         {
1823           NS_LOG_LOGIC ("Bridge " << bridgeNetDevice << " has been visited.");
1824           return true;
1825         }
1826     }
1827   return false;
1828 }
1829 
1830 //
1831 // Remember that we visited a bridge net device by adding it to m_bridgesVisited
1832 //
1833 void
MarkBridgeAsVisited(Ptr<BridgeNetDevice> bridgeNetDevice) const1834 GlobalRouter::MarkBridgeAsVisited (Ptr<BridgeNetDevice> bridgeNetDevice) const
1835 {
1836   NS_LOG_FUNCTION (this << bridgeNetDevice);
1837   m_bridgesVisited.push_back (bridgeNetDevice);
1838 }
1839 
1840 
1841 } // namespace ns3
1842