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 
510 TypeId
512 {
513  static TypeId tid = TypeId ("ns3::GlobalRouter")
514  .SetParent<Object> ();
515  return tid;
516 }
517 
519  : m_LSAs ()
520 {
521  NS_LOG_FUNCTION (this);
523 }
524 
526 {
527  NS_LOG_FUNCTION (this);
528  ClearLSAs ();
529 }
530 
531 void
533 {
534  NS_LOG_FUNCTION (this << routing);
535  m_routingProtocol = routing;
536 }
539 {
540  NS_LOG_FUNCTION (this);
541  return m_routingProtocol;
542 }
543 
544 void
546 {
547  NS_LOG_FUNCTION (this);
548  m_routingProtocol = 0;
549  for (InjectedRoutesI k = m_injectedRoutes.begin ();
550  k != m_injectedRoutes.end ();
551  k = m_injectedRoutes.erase (k))
552  {
553  delete (*k);
554  }
556 }
557 
558 void
560 {
561  NS_LOG_FUNCTION (this);
562  for ( ListOfLSAs_t::iterator i = m_LSAs.begin ();
563  i != m_LSAs.end ();
564  i++)
565  {
566  NS_LOG_LOGIC ("Free LSA");
567 
568  GlobalRoutingLSA *p = *i;
569  delete p;
570  p = 0;
571 
572  *i = 0;
573  }
574  NS_LOG_LOGIC ("Clear list of LSAs");
575  m_LSAs.clear ();
576 }
577 
580 {
581  NS_LOG_FUNCTION (this);
582  return m_routerId;
583 }
584 
585 //
586 // DiscoverLSAs is called on all nodes in the system that have a GlobalRouter
587 // interface aggregated. We need to go out and discover any adjacent routers
588 // and build the Link State Advertisements that reflect them and their associated
589 // networks.
590 //
591 uint32_t
593 {
594  NS_LOG_FUNCTION (this);
595  Ptr<Node> node = GetObject<Node> ();
596  NS_ABORT_MSG_UNLESS (node, "GlobalRouter::DiscoverLSAs (): GetObject for <Node> interface failed");
597  NS_LOG_LOGIC ("For node " << node->GetId () );
598 
599  ClearLSAs ();
600 
601  //
602  // While building the Router-LSA, keep a list of those NetDevices for
603  // which the current node is the designated router and we will later build
604  // a NetworkLSA for.
605  //
607 
608  //
609  // We're aggregated to a node. We need to ask the node for a pointer to its
610  // Ipv4 interface. This is where the information regarding the attached
611  // interfaces lives. If we're a router, we had better have an Ipv4 interface.
612  //
613  Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
614  NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed");
615 
616  //
617  // Every router node originates a Router-LSA
618  //
621  pLSA->SetLinkStateId (m_routerId);
624  pLSA->SetNode (node);
625 
626  //
627  // Ask the node for the number of net devices attached. This isn't necessarily
628  // equal to the number of links to adjacent nodes (other routers) as the number
629  // of devices may include those for stub networks (e.g., ethernets, etc.) and
630  // bridge devices also take up an "extra" net device.
631  //
632  uint32_t numDevices = node->GetNDevices ();
633 
634  //
635  // Iterate through the devices on the node and walk the channel to see what's
636  // on the other side of the standalone devices..
637  //
638  for (uint32_t i = 0; i < numDevices; ++i)
639  {
640  Ptr<NetDevice> ndLocal = node->GetDevice (i);
641 
642  //
643  // There is an assumption that bridge ports must never have an IP address
644  // associated with them. This turns out to be a very convenient place to
645  // check and make sure that this is the case.
646  //
647  if (NetDeviceIsBridged (ndLocal))
648  {
649  // Initialize to value out of bounds to silence compiler
650  uint32_t interfaceBridge = ipv4Local->GetNInterfaces () + 1;
651  bool rc = FindInterfaceForDevice (node, ndLocal, interfaceBridge);
652  NS_ABORT_MSG_IF (rc, "GlobalRouter::DiscoverLSAs(): Bridge ports must not have an IPv4 interface index");
653  }
654 
655  //
656  // Check to see if the net device we just got has a corresponding IP
657  // interface (could be a pure L2 NetDevice) -- for example a net device
658  // associated with a bridge. We are only going to involve devices with
659  // IP addresses in routing.
660  //
661  bool isForwarding = false;
662  for (uint32_t j = 0; j < ipv4Local->GetNInterfaces (); ++j )
663  {
664  if (ipv4Local->GetNetDevice (j) == ndLocal && ipv4Local->IsUp (j) &&
665  ipv4Local->IsForwarding (j))
666  {
667  isForwarding = true;
668  break;
669  }
670  }
671 
672  if (!isForwarding)
673  {
674  NS_LOG_LOGIC ("Net device " << ndLocal << "has no IP interface or is not enabled for forwarding, skipping");
675  continue;
676  }
677 
678  //
679  // We have a net device that we need to check out. If it suports
680  // broadcast and is not a point-point link, then it will be either a stub
681  // network or a transit network depending on the number of routers on
682  // the segment. We add the appropriate link record to the LSA.
683  //
684  // If the device is a point to point link, we treat it separately. In
685  // that case, there may be zero, one, or two link records added.
686  //
687 
688  if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () )
689  {
690  NS_LOG_LOGIC ("Broadcast link");
691  ProcessBroadcastLink (ndLocal, pLSA, c);
692  }
693  else if (ndLocal->IsPointToPoint () )
694  {
695  NS_LOG_LOGIC ("Point=to-point link");
696  ProcessPointToPointLink (ndLocal, pLSA);
697  }
698  else
699  {
700  NS_ASSERT_MSG (0, "GlobalRouter::DiscoverLSAs (): unknown link type");
701  }
702  }
703 
704  NS_LOG_LOGIC ("========== LSA for node " << node->GetId () << " ==========");
705  NS_LOG_LOGIC (*pLSA);
706  m_LSAs.push_back (pLSA);
707  pLSA = 0;
708 
709  //
710  // Now, determine whether we need to build a NetworkLSA. This is the case if
711  // we found at least one designated router.
712  //
713  uint32_t nDesignatedRouters = c.GetN ();
714  if (nDesignatedRouters > 0)
715  {
716  NS_LOG_LOGIC ("Build Network LSAs");
717  BuildNetworkLSAs (c);
718  }
719 
720  //
721  // Build injected route LSAs as external routes
722  // RFC 2328, section 12.4.4
723  //
724  for (InjectedRoutesCI i = m_injectedRoutes.begin ();
725  i != m_injectedRoutes.end ();
726  i++)
727  {
730  pLSA->SetLinkStateId ((*i)->GetDestNetwork ());
732  pLSA->SetNetworkLSANetworkMask ((*i)->GetDestNetworkMask ());
734  m_LSAs.push_back (pLSA);
735  }
736  return m_LSAs.size ();
737 }
738 
739 void
741 {
742  NS_LOG_FUNCTION (this << nd << pLSA << &c);
743 
744  if (nd->IsBridge ())
745  {
746  ProcessBridgedBroadcastLink (nd, pLSA, c);
747  }
748  else
749  {
750  ProcessSingleBroadcastLink (nd, pLSA, c);
751  }
752 }
753 
754 void
756 {
757  NS_LOG_FUNCTION (this << nd << pLSA << &c);
758 
760  NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessSingleBroadcastLink(): Can't alloc link record");
761 
762  //
763  // We have some preliminaries to do to get enough information to proceed.
764  // This information we need comes from the internet stack, so notice that
765  // there is an implied assumption that global routing is only going to
766  // work with devices attached to the internet stack (have an ipv4 interface
767  // associated to them.
768  //
769  Ptr<Node> node = nd->GetNode ();
770 
771  Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
772  NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for <Ipv4> interface failed");
773 
774  // Initialize to value out of bounds to silence compiler
775  uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
776  bool rc = FindInterfaceForDevice (node, nd, interfaceLocal);
777  NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessSingleBroadcastLink(): No interface index associated with device");
778 
779  if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
780  {
781  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
782  }
783  Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
784  Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
785  NS_LOG_LOGIC ("Working with local address " << addrLocal);
786  uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
787 
788  //
789  // Check to see if the net device is connected to a channel/network that has
790  // another router on it. If there is no other router on the link (but us) then
791  // this is a stub network. If we find another router, then what we have here
792  // is a transit network.
793  //
794  if (AnotherRouterOnLink (nd, true) == false)
795  {
796  //
797  // This is a net device connected to a stub network
798  //
799  NS_LOG_LOGIC ("Router-LSA Stub Network");
801 
802  //
803  // According to OSPF, the Link ID is the IP network number of
804  // the attached network.
805  //
806  plr->SetLinkId (addrLocal.CombineMask (maskLocal));
807 
808  //
809  // and the Link Data is the network mask; converted to Ipv4Address
810  //
811  Ipv4Address maskLocalAddr;
812  maskLocalAddr.Set (maskLocal.Get ());
813  plr->SetLinkData (maskLocalAddr);
814  plr->SetMetric (metricLocal);
815  pLSA->AddLinkRecord (plr);
816  plr = 0;
817  }
818  else
819  {
820  //
821  // We have multiple routers on a broadcast interface, so this is
822  // a transit network.
823  //
824  NS_LOG_LOGIC ("Router-LSA Transit Network");
826 
827  //
828  // By definition, the router with the lowest IP address is the
829  // designated router for the network. OSPF says that the Link ID
830  // gets the IP interface address of the designated router in this
831  // case.
832  //
833  Ipv4Address desigRtr = FindDesignatedRouterForLink (nd, true);
834 
835  //
836  // Let's double-check that any designated router we find out on our
837  // network is really on our network.
838  //
839  if (desigRtr != "255.255.255.255")
840  {
841  Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
842  Ipv4Address networkThere = desigRtr.CombineMask (maskLocal);
843  NS_ABORT_MSG_UNLESS (networkHere == networkThere,
844  "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion");
845  }
846  if (desigRtr == addrLocal)
847  {
848  c.Add (nd);
849  NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
850  }
851  plr->SetLinkId (desigRtr);
852 
853  //
854  // OSPF says that the Link Data is this router's own IP address.
855  //
856  plr->SetLinkData (addrLocal);
857  plr->SetMetric (metricLocal);
858  pLSA->AddLinkRecord (plr);
859  plr = 0;
860  }
861 }
862 
863 void
865 {
866  NS_LOG_FUNCTION (this << nd << pLSA << &c);
867  NS_ASSERT_MSG (nd->IsBridge (), "GlobalRouter::ProcessBridgedBroadcastLink(): Called with non-bridge net device");
868 
869 #if 0
870  //
871  // It is possible to admit the possibility that a bridge device on a node
872  // can also participate in routing. This would surprise people who don't
873  // come from Microsoft-land where they do use such a construct. Based on
874  // the principle of least-surprise, we will leave the relatively simple
875  // code in place to do this, but not enable it until someone really wants
876  // the capability. Even then, we will not enable this code as a default
877  // but rather something you will have to go and turn on.
878  //
879 
880  Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> ();
881  NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
882 
883  //
884  // We have some preliminaries to do to get enough information to proceed.
885  // This information we need comes from the internet stack, so notice that
886  // there is an implied assumption that global routing is only going to
887  // work with devices attached to the internet stack (have an ipv4 interface
888  // associated to them.
889  //
890  Ptr<Node> node = nd->GetNode ();
891  Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
892  NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for <Ipv4> interface failed");
893 
894  // Initialize to value out of bounds to silence compiler
895  uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
896  bool rc = FindInterfaceForDevice (node, nd, interfaceLocal);
897  NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessBridgedBroadcastLink(): No interface index associated with device");
898 
899  if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
900  {
901  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
902  }
903  Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
904  Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();;
905  NS_LOG_LOGIC ("Working with local address " << addrLocal);
906  uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
907 
908  //
909  // We need to handle a bridge on the router. This means that we have been
910  // given a net device that is a BridgeNetDevice. It has an associated Ipv4
911  // interface index and address. Some number of other net devices live "under"
912  // the bridge device as so-called bridge ports. In a nutshell, what we have
913  // to do is to repeat what is done for a single broadcast link on all of
914  // those net devices living under the bridge (trolls?)
915  //
916 
917  bool areTransitNetwork = false;
918  Ipv4Address desigRtr ("255.255.255.255");
919 
920  for (uint32_t i = 0; i < bnd->GetNBridgePorts (); ++i)
921  {
922  Ptr<NetDevice> ndTemp = bnd->GetBridgePort (i);
923 
924  //
925  // We have to decide if we are a transit network. This is characterized
926  // by the presence of another router on the network segment. If we find
927  // another router on any of our bridged links, we are a transit network.
928  //
929  if (AnotherRouterOnLink (ndTemp, true))
930  {
931  areTransitNetwork = true;
932 
933  //
934  // If we're going to be a transit network, then we have got to elect
935  // a designated router for the whole bridge. This means finding the
936  // router with the lowest IP address on the whole bridge. We ask
937  // for the lowest address on each segment and pick the lowest of them
938  // all.
939  //
940  Ipv4Address desigRtrTemp = FindDesignatedRouterForLink (ndTemp, true);
941 
942  //
943  // Let's double-check that any designated router we find out on our
944  // network is really on our network.
945  //
946  if (desigRtrTemp != "255.255.255.255")
947  {
948  Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
949  Ipv4Address networkThere = desigRtrTemp.CombineMask (maskLocal);
950  NS_ABORT_MSG_UNLESS (networkHere == networkThere,
951  "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion");
952  }
953  if (desigRtrTemp < desigRtr)
954  {
955  desigRtr = desigRtrTemp;
956  }
957  }
958  }
959  //
960  // That's all the information we need to put it all together, just like we did
961  // in the case of a single broadcast link.
962  //
963 
965  NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessBridgedBroadcastLink(): Can't alloc link record");
966 
967  if (areTransitNetwork == false)
968  {
969  //
970  // This is a net device connected to a bridge of stub networks
971  //
972  NS_LOG_LOGIC ("Router-LSA Stub Network");
974 
975  //
976  // According to OSPF, the Link ID is the IP network number of
977  // the attached network.
978  //
979  plr->SetLinkId (addrLocal.CombineMask (maskLocal));
980 
981  //
982  // and the Link Data is the network mask; converted to Ipv4Address
983  //
984  Ipv4Address maskLocalAddr;
985  maskLocalAddr.Set (maskLocal.Get ());
986  plr->SetLinkData (maskLocalAddr);
987  plr->SetMetric (metricLocal);
988  pLSA->AddLinkRecord (plr);
989  plr = 0;
990  }
991  else
992  {
993  //
994  // We have multiple routers on a bridged broadcast interface, so this is
995  // a transit network.
996  //
997  NS_LOG_LOGIC ("Router-LSA Transit Network");
999 
1000  //
1001  // By definition, the router with the lowest IP address is the
1002  // designated router for the network. OSPF says that the Link ID
1003  // gets the IP interface address of the designated router in this
1004  // case.
1005  //
1006  if (desigRtr == addrLocal)
1007  {
1008  c.Add (nd);
1009  NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
1010  }
1011  plr->SetLinkId (desigRtr);
1012 
1013  //
1014  // OSPF says that the Link Data is this router's own IP address.
1015  //
1016  plr->SetLinkData (addrLocal);
1017  plr->SetMetric (metricLocal);
1018  pLSA->AddLinkRecord (plr);
1019  plr = 0;
1020  }
1021 #endif
1022 }
1023 
1024 void
1026 {
1027  NS_LOG_FUNCTION (this << ndLocal << pLSA);
1028 
1029  //
1030  // We have some preliminaries to do to get enough information to proceed.
1031  // This information we need comes from the internet stack, so notice that
1032  // there is an implied assumption that global routing is only going to
1033  // work with devices attached to the internet stack (have an ipv4 interface
1034  // associated to them.
1035  //
1036  Ptr<Node> nodeLocal = ndLocal->GetNode ();
1037 
1038  Ptr<Ipv4> ipv4Local = nodeLocal->GetObject<Ipv4> ();
1039  NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1040 
1041  uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
1042  bool rc = FindInterfaceForDevice (nodeLocal, ndLocal, interfaceLocal);
1043  NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device");
1044 
1045  if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
1046  {
1047  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1048  }
1049  Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
1050  NS_LOG_LOGIC ("Working with local address " << addrLocal);
1051  uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
1052 
1053  //
1054  // Now, we're going to walk over to the remote net device on the other end of
1055  // the point-to-point channel we know we have. This is where our adjacent
1056  // router (to use OSPF lingo) is running.
1057  //
1058  Ptr<Channel> ch = ndLocal->GetChannel ();
1059 
1060  //
1061  // Get the net device on the other side of the point-to-point channel.
1062  //
1063  Ptr<NetDevice> ndRemote = GetAdjacent (ndLocal, ch);
1064 
1065  //
1066  // The adjacent net device is aggregated to a node. We need to ask that net
1067  // device for its node, then ask that node for its Ipv4 interface. Note a
1068  // requirement that nodes on either side of a point-to-point link must have
1069  // internet stacks; and an assumption that point-to-point links are incompatible
1070  // with bridging.
1071  //
1072  Ptr<Node> nodeRemote = ndRemote->GetNode ();
1073  Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4> ();
1074  NS_ABORT_MSG_UNLESS (ipv4Remote,
1075  "GlobalRouter::ProcessPointToPointLink(): GetObject for remote <Ipv4> failed");
1076 
1077  //
1078  // Further note the requirement that nodes on either side of a point-to-point
1079  // link must participate in global routing and therefore have a GlobalRouter
1080  // interface aggregated.
1081  //
1082  Ptr<GlobalRouter> rtrRemote = nodeRemote->GetObject<GlobalRouter> ();
1083  if (rtrRemote == 0)
1084  {
1085  // This case is possible if the remote does not participate in global routing
1086  return;
1087  }
1088  //
1089  // We're going to need the remote router ID, so we might as well get it now.
1090  //
1091  Ipv4Address rtrIdRemote = rtrRemote->GetRouterId ();
1092  NS_LOG_LOGIC ("Working with remote router " << rtrIdRemote);
1093 
1094  //
1095  // Now, just like we did above, we need to get the IP interface index for the
1096  // net device on the other end of the point-to-point channel.
1097  //
1098  uint32_t interfaceRemote = ipv4Remote->GetNInterfaces () + 1;
1099  rc = FindInterfaceForDevice (nodeRemote, ndRemote, interfaceRemote);
1100  NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with remote device");
1101 
1102  //
1103  // Now that we have the Ipv4 interface, we can get the (remote) address and
1104  // mask we need.
1105  //
1106  if (ipv4Remote->GetNAddresses (interfaceRemote) > 1)
1107  {
1108  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1109  }
1110  Ipv4Address addrRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetLocal ();
1111  Ipv4Mask maskRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetMask ();
1112  NS_LOG_LOGIC ("Working with remote address " << addrRemote);
1113 
1114  //
1115  // Now we can fill out the link records for this link. There are always two
1116  // link records; the first is a point-to-point record describing the link and
1117  // the second is a stub network record with the network number.
1118  //
1120  if (ipv4Remote->IsUp (interfaceRemote))
1121  {
1122  NS_LOG_LOGIC ("Remote side interface " << interfaceRemote << " is up-- add a type 1 link");
1123 
1124  plr = new GlobalRoutingLinkRecord;
1125  NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1127  plr->SetLinkId (rtrIdRemote);
1128  plr->SetLinkData (addrLocal);
1129  plr->SetMetric (metricLocal);
1130  pLSA->AddLinkRecord (plr);
1131  plr = 0;
1132  }
1133 
1134  // Regardless of state of peer, add a type 3 link (RFC 2328: 12.4.1.1)
1135  plr = new GlobalRoutingLinkRecord;
1136  NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1138  plr->SetLinkId (addrRemote);
1139  plr->SetLinkData (Ipv4Address (maskRemote.Get ())); // Frown
1140  plr->SetMetric (metricLocal);
1141  pLSA->AddLinkRecord (plr);
1142  plr = 0;
1143 }
1144 
1145 void
1147 {
1148  NS_LOG_FUNCTION (this << &c);
1149 
1150  uint32_t nDesignatedRouters = c.GetN ();
1151 
1152  for (uint32_t i = 0; i < nDesignatedRouters; ++i)
1153  {
1154  //
1155  // Build one NetworkLSA for each net device talking to a network that we are the
1156  // designated router for. These devices are in the provided container.
1157  //
1158  Ptr<NetDevice> ndLocal = c.Get (i);
1159  Ptr<Node> node = ndLocal->GetNode ();
1160 
1161  Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
1162  NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1163 
1164  uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
1165  bool rc = FindInterfaceForDevice (node, ndLocal, interfaceLocal);
1166  NS_ABORT_MSG_IF (rc == false, "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device");
1167 
1168  if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
1169  {
1170  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1171  }
1172  Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
1173  Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
1174 
1175  GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
1176  NS_ABORT_MSG_IF (pLSA == 0, "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record");
1177 
1179  pLSA->SetLinkStateId (addrLocal);
1181  pLSA->SetNetworkLSANetworkMask (maskLocal);
1183  pLSA->SetNode (node);
1184 
1185  //
1186  // Build a list of AttachedRouters by walking the devices in the channel
1187  // and, if we find a node with a GlobalRouter interface and an IPv4
1188  // interface associated with that device, we call it an attached router.
1189  //
1190  Ptr<Channel> ch = ndLocal->GetChannel ();
1191  uint32_t nDevices = ch->GetNDevices ();
1192  NS_ASSERT (nDevices);
1193 
1194  for (uint32_t i = 0; i < nDevices; i++)
1195  {
1196  Ptr<NetDevice> tempNd = ch->GetDevice (i);
1197  NS_ASSERT (tempNd);
1198  Ptr<Node> tempNode = tempNd->GetNode ();
1199 
1200  //
1201  // Does the node in question have a GlobalRouter interface? If not it can
1202  // hardly be considered an attached router.
1203  //
1204  Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter> ();
1205  if (rtr == 0)
1206  {
1207  continue;
1208  }
1209 
1210  //
1211  // Does the attached node have an ipv4 interface for the device we're probing?
1212  // If not, it can't play router.
1213  //
1214  uint32_t tempInterface = 0;
1215  if (FindInterfaceForDevice (tempNode, tempNd, tempInterface))
1216  {
1217  Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> ();
1218  NS_ASSERT (tempIpv4);
1219  if (!tempIpv4->IsUp (tempInterface))
1220  {
1221  NS_LOG_LOGIC ("Remote side interface " << tempInterface << " not up");
1222  }
1223  else
1224  {
1225  if (tempIpv4->GetNAddresses (tempInterface) > 1)
1226  {
1227  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1228  }
1229  Ipv4Address tempAddr = tempIpv4->GetAddress (tempInterface, 0).GetLocal ();
1230  pLSA->AddAttachedRouter (tempAddr);
1231  }
1232  }
1233  }
1234  m_LSAs.push_back (pLSA);
1235  pLSA = 0;
1236  }
1237 }
1238 
1239 //
1240 // Given a local net device, we need to walk the channel to which the net device is
1241 // attached and look for nodes with GlobalRouter interfaces on them (one of them
1242 // will be us). Of these, the router with the lowest IP address on the net device
1243 // connecting to the channel becomes the designated router for the link.
1244 //
1246 GlobalRouter::FindDesignatedRouterForLink (Ptr<NetDevice> ndLocal, bool allowRecursion) const
1247 {
1248  NS_LOG_FUNCTION (this << ndLocal << allowRecursion);
1249 
1250  Ptr<Channel> ch = ndLocal->GetChannel ();
1251  uint32_t nDevices = ch->GetNDevices ();
1252  NS_ASSERT (nDevices);
1253 
1254  NS_LOG_LOGIC ("Looking for designated router off of net device " << ndLocal << " on node " <<
1255  ndLocal->GetNode ()->GetId ());
1256 
1257  Ipv4Address desigRtr ("255.255.255.255");
1258 
1259  //
1260  // Look through all of the devices on the channel to which the net device
1261  // in question is attached.
1262  //
1263  for (uint32_t i = 0; i < nDevices; i++)
1264  {
1265  Ptr<NetDevice> ndOther = ch->GetDevice (i);
1266  NS_ASSERT (ndOther);
1267 
1268  Ptr<Node> nodeOther = ndOther->GetNode ();
1269 
1270  NS_LOG_LOGIC ("Examine channel device " << i << " on node " << nodeOther->GetId ());
1271 
1272  //
1273  // For all other net devices, we need to check and see if a router
1274  // is present. If the net device on the other side is a bridged
1275  // device, we need to consider all of the other devices on the
1276  // bridge as well (all of the bridge ports.
1277  //
1278  NS_LOG_LOGIC ("checking to see if the device is bridged");
1279  Ptr<BridgeNetDevice> bnd = NetDeviceIsBridged (ndOther);
1280  if (bnd)
1281  {
1282  NS_LOG_LOGIC ("Device is bridged by BridgeNetDevice " << bnd);
1283 
1284  //
1285  // It is possible that the bridge net device is sitting under a
1286  // router, so we have to check for the presence of that router
1287  // before we run off and follow all the links
1288  //
1289  // We require a designated router to have a GlobalRouter interface and
1290  // an internet stack that includes the Ipv4 interface. If it doesn't
1291  // it can't play router.
1292  //
1293  NS_LOG_LOGIC ("Checking for router on bridge net device " << bnd);
1294  Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
1295  Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
1296  if (rtr && ipv4)
1297  {
1298  // Initialize to value out of bounds to silence compiler
1299  uint32_t interfaceOther = ipv4->GetNInterfaces () + 1;
1300  if (FindInterfaceForDevice (nodeOther, bnd, interfaceOther))
1301  {
1302  NS_LOG_LOGIC ("Found router on bridge net device " << bnd);
1303  if (!ipv4->IsUp (interfaceOther))
1304  {
1305  NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up");
1306  continue;
1307  }
1308  if (ipv4->GetNAddresses (interfaceOther) > 1)
1309  {
1310  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1311  }
1312  Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal ();
1313  desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1314  NS_LOG_LOGIC ("designated router now " << desigRtr);
1315  }
1316  }
1317 
1318  NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
1319  for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1320  {
1321  Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
1322  NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
1323  if (ndBridged == ndOther)
1324  {
1325  NS_LOG_LOGIC ("That bridge port is me, don't walk backward");
1326  continue;
1327  }
1328 
1329  if (allowRecursion)
1330  {
1331  NS_LOG_LOGIC ("Recursively looking for routers down bridge port " << ndBridged);
1332  Ipv4Address addrOther = FindDesignatedRouterForLink (ndBridged, false);
1333  desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1334  NS_LOG_LOGIC ("designated router now " << desigRtr);
1335  }
1336  }
1337  }
1338  else
1339  {
1340  NS_LOG_LOGIC ("This device is not bridged");
1341  Ptr<Node> nodeOther = ndOther->GetNode ();
1342  NS_ASSERT (nodeOther);
1343 
1344  //
1345  // We require a designated router to have a GlobalRouter interface and
1346  // an internet stack that includes the Ipv4 interface. If it doesn't
1347  //
1348  Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
1349  Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
1350  if (rtr && ipv4)
1351  {
1352  // Initialize to value out of bounds to silence compiler
1353  uint32_t interfaceOther = ipv4->GetNInterfaces () + 1;
1354  if (FindInterfaceForDevice (nodeOther, ndOther, interfaceOther))
1355  {
1356  if (!ipv4->IsUp (interfaceOther))
1357  {
1358  NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up");
1359  continue;
1360  }
1361  NS_LOG_LOGIC ("Found router on net device " << ndOther);
1362  if (ipv4->GetNAddresses (interfaceOther) > 1)
1363  {
1364  NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1365  }
1366  Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal ();
1367  desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1368  NS_LOG_LOGIC ("designated router now " << desigRtr);
1369  }
1370  }
1371  }
1372  }
1373  return desigRtr;
1374 }
1375 
1376 //
1377 // Given a node and an attached net device, take a look off in the channel to
1378 // which the net device is attached and look for a node on the other side
1379 // that has a GlobalRouter interface aggregated. Life gets more complicated
1380 // when there is a bridged net device on the other side.
1381 //
1382 bool
1383 GlobalRouter::AnotherRouterOnLink (Ptr<NetDevice> nd, bool allowRecursion) const
1384 {
1385  NS_LOG_FUNCTION (this << nd << allowRecursion);
1386 
1387  Ptr<Channel> ch = nd->GetChannel ();
1388  if (!ch)
1389  {
1390  // It may be that this net device is a stub device, without a channel
1391  return false;
1392  }
1393  uint32_t nDevices = ch->GetNDevices ();
1394  NS_ASSERT (nDevices);
1395 
1396  NS_LOG_LOGIC ("Looking for routers off of net device " << nd << " on node " << nd->GetNode ()->GetId ());
1397 
1398  //
1399  // Look through all of the devices on the channel to which the net device
1400  // in question is attached.
1401  //
1402  for (uint32_t i = 0; i < nDevices; i++)
1403  {
1404  Ptr<NetDevice> ndOther = ch->GetDevice (i);
1405  NS_ASSERT (ndOther);
1406 
1407  NS_LOG_LOGIC ("Examine channel device " << i << " on node " << ndOther->GetNode ()->GetId ());
1408 
1409  //
1410  // Ignore the net device itself.
1411  //
1412  if (ndOther == nd)
1413  {
1414  NS_LOG_LOGIC ("Myself, skip");
1415  continue;
1416  }
1417 
1418  //
1419  // For all other net devices, we need to check and see if a router
1420  // is present. If the net device on the other side is a bridged
1421  // device, we need to consider all of the other devices on the
1422  // bridge.
1423  //
1424  NS_LOG_LOGIC ("checking to see if device is bridged");
1425  Ptr<BridgeNetDevice> bnd = NetDeviceIsBridged (ndOther);
1426  if (bnd)
1427  {
1428  NS_LOG_LOGIC ("Device is bridged by net device " << bnd);
1429  NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
1430  for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1431  {
1432  Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
1433  NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
1434  if (ndBridged == ndOther)
1435  {
1436  NS_LOG_LOGIC ("That bridge port is me, skip");
1437  continue;
1438  }
1439 
1440  if (allowRecursion)
1441  {
1442  NS_LOG_LOGIC ("Recursively looking for routers on bridge port " << ndBridged);
1443  if (AnotherRouterOnLink (ndBridged, false))
1444  {
1445  NS_LOG_LOGIC ("Found routers on bridge port, return true");
1446  return true;
1447  }
1448  }
1449  }
1450  NS_LOG_LOGIC ("No routers on bridged net device, return false");
1451  return false;
1452  }
1453 
1454  NS_LOG_LOGIC ("This device is not bridged");
1455  Ptr<Node> nodeTemp = ndOther->GetNode ();
1456  NS_ASSERT (nodeTemp);
1457 
1458  Ptr<GlobalRouter> rtr = nodeTemp->GetObject<GlobalRouter> ();
1459  if (rtr)
1460  {
1461  NS_LOG_LOGIC ("Found GlobalRouter interface, return true");
1462  return true;
1463  }
1464  else
1465  {
1466  NS_LOG_LOGIC ("No GlobalRouter interface on device, continue search");
1467  }
1468  }
1469  NS_LOG_LOGIC ("No routers found, return false");
1470  return false;
1471 }
1472 
1473 uint32_t
1475 {
1476  NS_LOG_FUNCTION (this);
1477  return m_LSAs.size ();
1478 }
1479 
1480 //
1481 // Get the nth link state advertisement from this router.
1482 //
1483 bool
1484 GlobalRouter::GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const
1485 {
1486  NS_LOG_FUNCTION (this << n << &lsa);
1487  NS_ASSERT_MSG (lsa.IsEmpty (), "GlobalRouter::GetLSA (): Must pass empty LSA");
1488 //
1489 // All of the work was done in GetNumLSAs. All we have to do here is to
1490 // walk the list of link state advertisements created there and return the
1491 // one the client is interested in.
1492 //
1493  ListOfLSAs_t::const_iterator i = m_LSAs.begin ();
1494  uint32_t j = 0;
1495 
1496  for (; i != m_LSAs.end (); i++, j++)
1497  {
1498  if (j == n)
1499  {
1500  GlobalRoutingLSA *p = *i;
1501  lsa = *p;
1502  return true;
1503  }
1504  }
1505 
1506  return false;
1507 }
1508 
1509 void
1511 {
1512  NS_LOG_FUNCTION (this << network << networkMask);
1514 //
1515 // Interface number does not matter here, using 1.
1516 //
1518  networkMask,
1519  1);
1520  m_injectedRoutes.push_back (route);
1521 }
1522 
1525 {
1526  NS_LOG_FUNCTION (this << index);
1527  if (index < m_injectedRoutes.size ())
1528  {
1529  uint32_t tmp = 0;
1530  for (InjectedRoutesCI i = m_injectedRoutes.begin ();
1531  i != m_injectedRoutes.end ();
1532  i++)
1533  {
1534  if (tmp == index)
1535  {
1536  return *i;
1537  }
1538  tmp++;
1539  }
1540  }
1541  NS_ASSERT (false);
1542  // quiet compiler.
1543  return 0;
1544 }
1545 
1546 uint32_t
1548 {
1549  NS_LOG_FUNCTION (this);
1550  return m_injectedRoutes.size ();
1551 }
1552 
1553 void
1555 {
1556  NS_LOG_FUNCTION (this << index);
1557  NS_ASSERT (index < m_injectedRoutes.size ());
1558  uint32_t tmp = 0;
1559  for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
1560  {
1561  if (tmp == index)
1562  {
1563  NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_injectedRoutes.size ());
1564  delete *i;
1565  m_injectedRoutes.erase (i);
1566  return;
1567  }
1568  tmp++;
1569  }
1570 }
1571 
1572 bool
1574 {
1575  NS_LOG_FUNCTION (this << network << networkMask);
1576  for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
1577  {
1578  if ((*i)->GetDestNetwork () == network && (*i)->GetDestNetworkMask () == networkMask)
1579  {
1580  NS_LOG_LOGIC ("Withdrawing route to network/mask " << network << "/" << networkMask);
1581  delete *i;
1582  m_injectedRoutes.erase (i);
1583  return true;
1584  }
1585  }
1586  return false;
1587 }
1588 
1589 
1590 //
1591 // Link through the given channel and find the net device that's on the
1592 // other end. This only makes sense with a point-to-point channel.
1593 //
1596 {
1597  NS_LOG_FUNCTION (this << nd << ch);
1598  NS_ASSERT_MSG (ch->GetNDevices () == 2, "GlobalRouter::GetAdjacent (): Channel with other than two devices");
1599 //
1600 // This is a point to point channel with two endpoints. Get both of them.
1601 //
1602  Ptr<NetDevice> nd1 = ch->GetDevice (0);
1603  Ptr<NetDevice> nd2 = ch->GetDevice (1);
1604 //
1605 // One of the endpoints is going to be "us" -- that is the net device attached
1606 // to the node on which we're running -- i.e., "nd". The other endpoint (the
1607 // one to which we are connected via the channel) is the adjacent router.
1608 //
1609  if (nd1 == nd)
1610  {
1611  return nd2;
1612  }
1613  else if (nd2 == nd)
1614  {
1615  return nd1;
1616  }
1617  else
1618  {
1619  NS_ASSERT_MSG (false,
1620  "GlobalRouter::GetAdjacent (): Wrong or confused channel?");
1621  return 0;
1622  }
1623 }
1624 
1625 //
1626 // Given a node and a net device, find an IPV4 interface index that corresponds
1627 // to that net device. This function may fail for various reasons. If a node
1628 // does not have an internet stack (for example if it is a bridge) we won't have
1629 // an IPv4 at all. If the node does have a stack, but the net device in question
1630 // is bridged, there will not be an interface associated directly with the device.
1631 //
1632 bool
1634 {
1635  NS_LOG_FUNCTION (this << node << nd << &index);
1636  NS_LOG_LOGIC ("For node " << node->GetId () << " for net device " << nd );
1637 
1638  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
1639  if (ipv4 == 0)
1640  {
1641  NS_LOG_LOGIC ("No Ipv4 interface on node " << node->GetId ());
1642  return false;
1643  }
1644 
1645  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); ++i )
1646  {
1647  if (ipv4->GetNetDevice (i) == nd)
1648  {
1649  NS_LOG_LOGIC ("Device " << nd << " has associated ipv4 index " << i);
1650  index = i;
1651  return true;
1652  }
1653  }
1654 
1655  NS_LOG_LOGIC ("Device " << nd << " has no associated ipv4 index");
1656  return false;
1657 }
1658 
1659 //
1660 // Decide whether or not a given net device is being bridged by a BridgeNetDevice.
1661 //
1664 {
1665  NS_LOG_FUNCTION (this << nd);
1666 
1667  Ptr<Node> node = nd->GetNode ();
1668  uint32_t nDevices = node->GetNDevices ();
1669 
1670  //
1671  // There is no bit on a net device that says it is being bridged, so we have
1672  // to look for bridges on the node to which the device is attached. If we
1673  // find a bridge, we need to look through its bridge ports (the devices it
1674  // bridges) to see if we find the device in question.
1675  //
1676  for (uint32_t i = 0; i < nDevices; ++i)
1677  {
1678  Ptr<NetDevice> ndTest = node->GetDevice (i);
1679  NS_LOG_LOGIC ("Examine device " << i << " " << ndTest);
1680 
1681  if (ndTest->IsBridge ())
1682  {
1683  NS_LOG_LOGIC ("device " << i << " is a bridge net device");
1684  Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice> ();
1685  NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
1686 
1687  for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1688  {
1689  NS_LOG_LOGIC ("Examine bridge port " << j << " " << bnd->GetBridgePort (j));
1690  if (bnd->GetBridgePort (j) == nd)
1691  {
1692  NS_LOG_LOGIC ("Net device " << nd << " is bridged by " << bnd);
1693  return bnd;
1694  }
1695  }
1696  }
1697  }
1698  NS_LOG_LOGIC ("Net device " << nd << " is not bridged");
1699  return 0;
1700 }
1701 
1702 } // namespace ns3
void SetRoutingProtocol(Ptr< Ipv4GlobalRouting > routing)
Set the specific Global Routing Protocol to be used.
LSType GetLSType(void) const
Return the LSType field of the LSA.
Ptr< Ipv4GlobalRouting > GetRoutingProtocol(void)
Get the specific Global Routing Protocol used.
GlobalRoutingLinkRecord * GetLinkRecord(uint32_t n) const
Return a pointer to the specified Global Routing Link Record.
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
~GlobalRoutingLSA()
Destroy an existing Global Routing Link State Advertisement.
Ipv4Address m_advertisingRtr
The Advertising Router is defined by the OSPF spec.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr stored in this container at a given index.
static Ptr< Node > GetNode(uint32_t n)
Definition: node-list.cc:194
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
std::list< Ipv4RoutingTableEntry * >::const_iterator InjectedRoutesCI
Const Iterator to container of Ipv4RoutingTableEntry.
static TypeId GetTypeId(void)
Get the type ID.
bool WithdrawRoute(Ipv4Address network, Ipv4Mask networkMask)
Withdraw a route from the global unicast routing table.
bool FindInterfaceForDevice(Ptr< Node > node, Ptr< NetDevice > nd, uint32_t &index) const
Given a node and a net device, find an IPV4 interface index that corresponds to that net device...
uint32_t DiscoverLSAs(void)
Walk the connected channels, discover the adjacent routers and build the associated number of Global ...
Ipv4Address FindDesignatedRouterForLink(Ptr< NetDevice > ndLocal, bool allowRecursion) const
Finds a designated router.
void SetAdvertisingRouter(Ipv4Address rtr)
Set the Advertising Router as defined by the OSPF spec.
LSType m_lsType
The type of the LSA.
#define NS_ASSERT(condition)
Definition: assert.h:64
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
uint32_t AddLinkRecord(GlobalRoutingLinkRecord *lr)
Add a given Global Routing Link Record to the LSA.
Ipv4Mask m_networkLSANetworkMask
Each Network LSA contains the network mask of the attached network.
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:336
bool GetLSA(uint32_t n, GlobalRoutingLSA &lsa) const
Get a Global Routing Link State Advertisements that this router has said that it can export...
a virtual net device that bridges multiple LAN segments
uint32_t GetNInjectedRoutes(void)
Get the number of injected routes that have been added to the routing table.
void ProcessSingleBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
Process a single broadcast link.
uint32_t AddAttachedRouter(Ipv4Address addr)
Add an attached router to the list in the NetworkLSA.
InjectedRoutes m_injectedRoutes
Routes we are exporting.
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
void ProcessBridgedBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
Process a bridged broadcast link.
Ipv4Address GetAdvertisingRouter(void) const
Get the Advertising Router as defined by the OSPF spec.
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 stored in this container.
LSType
corresponds to LS type field of RFC 2328 OSPF LSA header
Ptr< Ipv4GlobalRouting > m_routingProtocol
the Ipv4GlobalRouting in use
A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting.
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.
void ClearLSAs(void)
Clear list of LSAs.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
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:132
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:368
SPFStatus m_status
This is a tristate flag used internally in the SPF computation to mark if an SPFVertex (a data struct...
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:75
uint32_t GetNDevices(void) const
Definition: node.cc:140
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
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.
ListOfLSAs_t m_LSAs
database of GlobalRoutingLSAs
An interface aggregated to a node to provide global routing info.
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
Ipv4Address m_routerId
router ID (its IPv4 address)
Ptr< BridgeNetDevice > NetDeviceIsBridged(Ptr< NetDevice > nd) const
Decide whether or not a given net device is being bridged by a BridgeNetDevice.
Ipv4Address m_linkStateId
The Link State ID is defined by the OSPF spec.
void Set(uint32_t address)
input address is in host order.
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:104
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:280
static uint32_t AllocateRouterId()
Allocate a 32-bit router ID from monotonically increasing counter.
bool AnotherRouterOnLink(Ptr< NetDevice > nd, bool allowRecursion) const
Checks for the presence of another router on the NetDevice.
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.
void BuildNetworkLSAs(NetDeviceContainer c)
Build one NetworkLSA for each net device talking to a network that we are the designated router for...
ListOfAttachedRouters_t m_attachedRouters
Each Network LSA contains a list of attached routers.
uint32_t Get(void) const
Get the host-order 32-bit IP mask.
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
Ptr< NetDevice > GetAdjacent(Ptr< NetDevice > nd, Ptr< Channel > ch) const
Link through the given channel and find the net device that's on the other end.
#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.
void ProcessPointToPointLink(Ptr< NetDevice > ndLocal, GlobalRoutingLSA *pLSA)
Process a point to point link.
Ptr< T > GetObject(void) const
Definition: object.h:361
ListOfLinkRecords_t m_linkRecords
Each Link State Advertisement contains a number of Link Records that describe the kinds of links that...
a unique identifier for an interface.
Definition: type-id.h:49
TypeId SetParent(TypeId tid)
Definition: type-id.cc:611
void SetLinkStateId(Ipv4Address addr)
Set the Link State ID is defined by the OSPF spec.
virtual uint32_t GetNInterfaces(void) const =0
NS_LOG_COMPONENT_DEFINE("GlobalRouter")
Ipv4Address GetLinkStateId(void) const
Get the Link State ID as defined by the OSPF spec.
std::list< Ipv4RoutingTableEntry * >::iterator InjectedRoutesI
Iterator to container of Ipv4RoutingTableEntry.
void ProcessBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
Process a generic broadcast link.