A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
global-router-interface.cc
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 <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 
524 GlobalRouter::~GlobalRouter ()
525 {
526  NS_LOG_FUNCTION (this);
527  ClearLSAs ();
528 }
529 
530 void
531 GlobalRouter::SetRoutingProtocol (Ptr<Ipv4GlobalRouting> routing)
532 {
533  NS_LOG_FUNCTION (this << routing);
534  m_routingProtocol = routing;
535 }
536 Ptr<Ipv4GlobalRouting>
537 GlobalRouter::GetRoutingProtocol (void)
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
558 GlobalRouter::ClearLSAs ()
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 
577 Ipv4Address
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  //
619  pLSA->SetLSType (GlobalRoutingLSA::RouterLSA);
620  pLSA->SetLinkStateId (m_routerId);
621  pLSA->SetAdvertisingRouter (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  {
728  pLSA->SetLSType (GlobalRoutingLSA::ASExternalLSAs);
729  pLSA->SetLinkStateId ((*i)->GetDestNetwork ());
730  pLSA->SetAdvertisingRouter (m_routerId);
731  pLSA->SetNetworkLSANetworkMask ((*i)->GetDestNetworkMask ());
733  m_LSAs.push_back (pLSA);
734  }
735  return m_LSAs.size ();
736 }
737 
738 void
739 GlobalRouter::ProcessBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
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
754 GlobalRouter::ProcessSingleBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
755 {
756  NS_LOG_FUNCTION (this << nd << pLSA << &c);
757 
758  GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
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");
799  plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
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");
824  plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
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
863 GlobalRouter::ProcessBridgedBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
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 
879  Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> ();
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 
963  GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
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");
972  plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
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");
997  plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
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
1024 GlobalRouter::ProcessPointToPointLink (Ptr<NetDevice> ndLocal, GlobalRoutingLSA *pLSA)
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  //
1118  GlobalRoutingLinkRecord *plr;
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");
1125  plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
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");
1136  plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
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
1145 GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c)
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 
1177  pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA);
1178  pLSA->SetLinkStateId (addrLocal);
1179  pLSA->SetAdvertisingRouter (m_routerId);
1180  pLSA->SetNetworkLSANetworkMask (maskLocal);
1181  pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
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 //
1244 Ipv4Address
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 //
1594 GlobalRouter::GetAdjacent (Ptr<NetDevice> nd, Ptr<Channel> ch) const
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
1632 GlobalRouter::FindInterfaceForDevice (Ptr<Node> node, Ptr<NetDevice> nd, uint32_t &index) const
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 //
1661 Ptr<BridgeNetDevice>
1662 GlobalRouter::NetDeviceIsBridged (Ptr<NetDevice> nd) const
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");
1683  Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice> ();
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
LSType GetLSType(void) const
Return the LSType field of the LSA.
GlobalRoutingLinkRecord * GetLinkRecord(uint32_t n) const
Return a pointer to the specified Global Routing Link Record.
virtual void DoDispose(void)
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
~GlobalRoutingLSA()
Destroy an existing Global Routing Link State Advertisement.
static Ptr< Node > GetNode(uint32_t n)
Definition: node-list.cc:192
Ipv4RoutingTableEntry * GetInjectedRoute(uint32_t i)
Return the injected route indexed by i.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:210
static TypeId GetTypeId(void)
The Interface ID of the Global Router interface.
bool WithdrawRoute(Ipv4Address network, Ipv4Mask networkMask)
Withdraw a route from the global unicast routing table.
uint32_t DiscoverLSAs(void)
Walk the connected channels, discover the adjacent routers and build the associated number of Global ...
void SetAdvertisingRouter(Ipv4Address rtr)
Set the Advertising Router as defined by the OSPF spec. We always set it to the router ID of the rout...
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t AddLinkRecord(GlobalRoutingLinkRecord *lr)
Add a given Global Routing Link Record to the LSA.
virtual void DoDispose(void)
Definition: object.cc:335
bool GetLSA(uint32_t n, GlobalRoutingLSA &lsa) const
Get a Global Routing Link State Advertisements that this router has said that it can export...
uint32_t GetNInjectedRoutes(void)
Get the number of injected routes that have been added to the routing table.
uint32_t AddAttachedRouter(Ipv4Address addr)
Add an attached router to the list in the NetworkLSA.
Ipv4Mask GetNetworkLSANetworkMask(void) const
For a Network LSA, get the Network Mask field that precedes the list of attached routers.
void SetNode(Ptr< Node > node)
Set the Node pointer of the node that originated this LSA.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:131
Ipv4Address GetAdvertisingRouter(void) const
Get the Advertising Router as defined by the OSPF spec. We always set it to the router ID of the rout...
void ClearLinkRecords(void)
Release all of the Global Routing Link Records present in the Global Routing Link State Advertisement...
uint32_t GetN(void) const
Get the number of Ptr<NetDevice> stored in this container.
LSType
corresponds to LS type field of RFC 2328 OSPF LSA header
a Link State Advertisement (LSA) for a router, used in global routing.
void InjectRoute(Ipv4Address network, Ipv4Mask networkMask)
Inject a route to be circulated to other routers as an external route.
static Ipv4RoutingTableEntry CreateNetworkRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > GetDevice(uint32_t index) const
Definition: node.cc:133
void SetLSType(LSType typ)
Set the LS type field of the LSA.
void Print(std::ostream &os) const
Print the contents of the Global Routing Link State Advertisement and any Global Routing Link Records...
void RemoveInjectedRoute(uint32_t i)
Withdraw a route from the global unicast routing table.
SPFStatus GetStatus(void) const
Get the SPF status of the advertisement.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:75
uint32_t GetNDevices(void) const
Definition: node.cc:141
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:43
void SetStatus(SPFStatus status)
Set the SPF status of the advertisement.
uint32_t GetNAttachedRouters(void) const
Return the number of attached routers listed in the NetworkLSA.
uint32_t GetNLinkRecords(void) const
Return the number of Global Routing Link Records in the LSA.
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
void Set(uint32_t address)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
void CopyLinkRecords(const GlobalRoutingLSA &lsa)
Copy any Global Routing Link Records in a given Global Routing Link State Advertisement to the curren...
GlobalRoutingLSA & operator=(const GlobalRoutingLSA &lsa)
Assignment operator for a Global Routing Link State Advertisement.
uint32_t GetId(void) const
Definition: node.cc:105
void SetNetworkLSANetworkMask(Ipv4Mask mask)
For a Network LSA, set the Network Mask field that precedes the list of attached routers.
#define NS_LOG_WARN(msg)
Definition: log.h:246
static uint32_t AllocateRouterId()
Allocate a 32-bit router ID from monotonically increasing counter.
SPFStatus
Enumeration of the possible values of the status flag in the Routing Link State Advertisements.
uint32_t GetNumLSAs(void) const
Get the Number of Global Routing Link State Advertisements that this router can export.
GlobalRouter()
Create a Global Router class.
Ipv4Address GetRouterId(void) const
Get the Router ID associated with this Global Router.
Ipv4Address GetAttachedRouter(uint32_t n) const
Return an Ipv4Address corresponding to the specified attached router.
Ptr< Node > GetNode(void) const
Get the Node pointer of the node that originated this LSA.
ListOfAttachedRouters_t m_attachedRouters
bool IsEmpty(void) const
Check to see if the list of Global Routing Link Records present in the Global Routing Link State Adve...
a base class which provides memory management and object aggregation
Definition: object.h:63
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if cond is true.
Definition: abort.h:98
GlobalRoutingLSA()
Create a blank Global Routing Link State Advertisement.
Ptr< T > GetObject(void) const
Definition: object.h:332
ListOfLinkRecords_t m_linkRecords
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
void SetLinkStateId(Ipv4Address addr)
Set the Link State ID is defined by the OSPF spec. We always set it to the router ID of the router ma...
Ipv4Address GetLinkStateId(void) const
Get the Link State ID as defined by the OSPF spec. We always set it to the router ID of the router ma...