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