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