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