A Discrete-Event Network Simulator
API
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 "loopback-net-device.h"
33#include <vector>
34
35namespace ns3 {
36
37NS_LOG_COMPONENT_DEFINE ("GlobalRouter");
38
39// ---------------------------------------------------------------------------
40//
41// GlobalRoutingLinkRecord Implementation
42//
43// ---------------------------------------------------------------------------
44
46 :
47 m_linkId ("0.0.0.0"),
48 m_linkData ("0.0.0.0"),
49 m_linkType (Unknown),
50 m_metric (0)
51{
52 NS_LOG_FUNCTION (this);
53}
54
56 LinkType linkType,
57 Ipv4Address linkId,
58 Ipv4Address linkData,
59 uint16_t metric)
60 :
61 m_linkId (linkId),
62 m_linkData (linkData),
63 m_linkType (linkType),
64 m_metric (metric)
65{
66 NS_LOG_FUNCTION (this << linkType << linkId << linkData << metric);
67}
68
70{
71 NS_LOG_FUNCTION (this);
72}
73
76{
77 NS_LOG_FUNCTION (this);
78 return m_linkId;
79}
80
81void
83{
84 NS_LOG_FUNCTION (this << addr);
85 m_linkId = addr;
86}
87
90{
91 NS_LOG_FUNCTION (this);
92 return m_linkData;
93}
94
95void
97{
98 NS_LOG_FUNCTION (this << addr);
99 m_linkData = addr;
100}
101
104{
105 NS_LOG_FUNCTION (this);
106 return m_linkType;
107}
108
109void
112{
113 NS_LOG_FUNCTION (this << linkType);
114 m_linkType = linkType;
115}
116
117uint16_t
119{
120 NS_LOG_FUNCTION (this);
121 return m_metric;
122}
123
124void
126{
127 NS_LOG_FUNCTION (this << metric);
128 m_metric = metric;
129}
130
131// ---------------------------------------------------------------------------
132//
133// GlobalRoutingLSA Implementation
134//
135// ---------------------------------------------------------------------------
136
138 :
139 m_lsType (GlobalRoutingLSA::Unknown),
140 m_linkStateId ("0.0.0.0"),
141 m_advertisingRtr ("0.0.0.0"),
142 m_linkRecords (),
143 m_networkLSANetworkMask ("0.0.0.0"),
144 m_attachedRouters (),
145 m_status (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED),
146 m_node_id (0)
147{
148 NS_LOG_FUNCTION (this);
149}
150
153 Ipv4Address linkStateId,
154 Ipv4Address advertisingRtr)
155 :
156 m_lsType (GlobalRoutingLSA::Unknown),
157 m_linkStateId (linkStateId),
158 m_advertisingRtr (advertisingRtr),
159 m_linkRecords (),
160 m_networkLSANetworkMask ("0.0.0.0"),
161 m_attachedRouters (),
162 m_status (status),
163 m_node_id (0)
164{
165 NS_LOG_FUNCTION (this << status << linkStateId << advertisingRtr);
166}
167
169 : m_lsType (lsa.m_lsType), m_linkStateId (lsa.m_linkStateId),
170 m_advertisingRtr (lsa.m_advertisingRtr),
171 m_networkLSANetworkMask (lsa.m_networkLSANetworkMask),
172 m_status (lsa.m_status),
173 m_node_id (lsa.m_node_id)
174{
175 NS_LOG_FUNCTION (this << &lsa);
177 "GlobalRoutingLSA::GlobalRoutingLSA (): Non-empty LSA in constructor");
178 CopyLinkRecords (lsa);
179}
180
183{
184 NS_LOG_FUNCTION (this << &lsa);
185 m_lsType = lsa.m_lsType;
189 m_status = lsa.m_status;
190 m_node_id = lsa.m_node_id;
191
193 CopyLinkRecords (lsa);
194 return *this;
195}
196
197void
199{
200 NS_LOG_FUNCTION (this << &lsa);
201 for (ListOfLinkRecords_t::const_iterator i = lsa.m_linkRecords.begin ();
202 i != lsa.m_linkRecords.end ();
203 i++)
204 {
205 GlobalRoutingLinkRecord *pSrc = *i;
207
208 pDst->SetLinkType (pSrc->GetLinkType ());
209 pDst->SetLinkId (pSrc->GetLinkId ());
210 pDst->SetLinkData (pSrc->GetLinkData ());
211 pDst->SetMetric (pSrc->GetMetric ());
212
213 m_linkRecords.push_back (pDst);
214 pDst = 0;
215 }
216
218}
219
221{
222 NS_LOG_FUNCTION (this);
224}
225
226void
228{
229 NS_LOG_FUNCTION (this);
230 for ( ListOfLinkRecords_t::iterator i = m_linkRecords.begin ();
231 i != m_linkRecords.end ();
232 i++)
233 {
234 NS_LOG_LOGIC ("Free link record");
235
237 delete p;
238 p = 0;
239
240 *i = 0;
241 }
242 NS_LOG_LOGIC ("Clear list");
243 m_linkRecords.clear ();
244}
245
248{
249 NS_LOG_FUNCTION (this << lr);
250 m_linkRecords.push_back (lr);
251 return m_linkRecords.size ();
252}
253
256{
257 NS_LOG_FUNCTION (this);
258 return m_linkRecords.size ();
259}
260
263{
264 NS_LOG_FUNCTION (this << n);
265 uint32_t j = 0;
266 for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
267 i != m_linkRecords.end ();
268 i++, j++)
269 {
270 if (j == n)
271 {
272 return *i;
273 }
274 }
275 NS_ASSERT_MSG (false, "GlobalRoutingLSA::GetLinkRecord (): invalid index");
276 return 0;
277}
278
279bool
281{
282 NS_LOG_FUNCTION (this);
283 return m_linkRecords.size () == 0;
284}
285
288{
289 NS_LOG_FUNCTION (this);
290 return m_lsType;
291}
292
293void
295{
296 NS_LOG_FUNCTION (this << typ);
297 m_lsType = typ;
298}
299
302{
303 NS_LOG_FUNCTION (this);
304 return m_linkStateId;
305}
306
307void
309{
310 NS_LOG_FUNCTION (this << addr);
311 m_linkStateId = addr;
312}
313
316{
317 NS_LOG_FUNCTION (this);
318 return m_advertisingRtr;
319}
320
321void
323{
324 NS_LOG_FUNCTION (this << addr);
325 m_advertisingRtr = addr;
326}
327
328void
330{
331 NS_LOG_FUNCTION (this << mask);
333}
334
337{
338 NS_LOG_FUNCTION (this);
340}
341
344{
345 NS_LOG_FUNCTION (this);
346 return m_status;
347}
348
351{
352 NS_LOG_FUNCTION (this << addr);
353 m_attachedRouters.push_back (addr);
354 return m_attachedRouters.size ();
355}
356
359{
360 NS_LOG_FUNCTION (this);
361 return m_attachedRouters.size ();
362}
363
366{
367 NS_LOG_FUNCTION (this << n);
368 uint32_t j = 0;
369 for ( ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin ();
370 i != m_attachedRouters.end ();
371 i++, j++)
372 {
373 if (j == n)
374 {
375 return *i;
376 }
377 }
378 NS_ASSERT_MSG (false, "GlobalRoutingLSA::GetAttachedRouter (): invalid index");
379 return Ipv4Address ("0.0.0.0");
380}
381
382void
384{
385 NS_LOG_FUNCTION (this << status);
386 m_status = status;
387}
388
391{
392 NS_LOG_FUNCTION (this);
394}
395
396void
398{
399 NS_LOG_FUNCTION (this << node);
400 m_node_id = node->GetId ();
401}
402
403void
404GlobalRoutingLSA::Print (std::ostream &os) const
405{
406 NS_LOG_FUNCTION (this << &os);
407 os << std::endl;
408 os << "========== Global Routing LSA ==========" << std::endl;
409 os << "m_lsType = " << m_lsType;
411 {
412 os << " (GlobalRoutingLSA::RouterLSA)";
413 }
415 {
416 os << " (GlobalRoutingLSA::NetworkLSA)";
417 }
419 {
420 os << " (GlobalRoutingLSA::ASExternalLSA)";
421 }
422 else
423 {
424 os << "(Unknown LSType)";
425 }
426 os << std::endl;
427
428 os << "m_linkStateId = " << m_linkStateId << " (Router ID)" << std::endl;
429 os << "m_advertisingRtr = " << m_advertisingRtr << " (Router ID)" << std::endl;
430
432 {
433 for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
434 i != m_linkRecords.end ();
435 i++)
436 {
438
439 os << "---------- RouterLSA Link Record ----------" << std::endl;
440 os << "m_linkType = " << p->m_linkType;
442 {
443 os << " (GlobalRoutingLinkRecord::PointToPoint)" << std::endl;
444 os << "m_linkId = " << p->m_linkId << std::endl;
445 os << "m_linkData = " << p->m_linkData << std::endl;
446 os << "m_metric = " << p->m_metric << std::endl;
447 }
449 {
450 os << " (GlobalRoutingLinkRecord::TransitNetwork)" << std::endl;
451 os << "m_linkId = " << p->m_linkId << " (Designated router for network)" << std::endl;
452 os << "m_linkData = " << p->m_linkData << " (This router's IP address)" << std::endl;
453 os << "m_metric = " << p->m_metric << std::endl;
454 }
456 {
457 os << " (GlobalRoutingLinkRecord::StubNetwork)" << std::endl;
458 os << "m_linkId = " << p->m_linkId << " (Network number of attached network)" << std::endl;
459 os << "m_linkData = " << p->m_linkData << " (Network mask of attached network)" << std::endl;
460 os << "m_metric = " << p->m_metric << std::endl;
461 }
462 else
463 {
464 os << " (Unknown LinkType)" << std::endl;
465 os << "m_linkId = " << p->m_linkId << std::endl;
466 os << "m_linkData = " << p->m_linkData << std::endl;
467 os << "m_metric = " << p->m_metric << std::endl;
468 }
469 os << "---------- End RouterLSA Link Record ----------" << std::endl;
470 }
471 }
473 {
474 os << "---------- NetworkLSA Link Record ----------" << std::endl;
475 os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
476 for ( ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin (); i != m_attachedRouters.end (); i++)
477 {
478 Ipv4Address p = *i;
479 os << "attachedRouter = " << p << std::endl;
480 }
481 os << "---------- End NetworkLSA Link Record ----------" << std::endl;
482 }
484 {
485 os << "---------- ASExternalLSA Link Record --------" << std::endl;
486 os << "m_linkStateId = " << m_linkStateId << std::endl;
487 os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
488 }
489 else
490 {
491 NS_ASSERT_MSG (0, "Illegal LSA LSType: " << m_lsType);
492 }
493 os << "========== End Global Routing LSA ==========" << std::endl;
494}
495
496std::ostream& operator<< (std::ostream& os, GlobalRoutingLSA& lsa)
497{
498 lsa.Print (os);
499 return os;
500}
501
502// ---------------------------------------------------------------------------
503//
504// GlobalRouter Implementation
505//
506// ---------------------------------------------------------------------------
507
508NS_OBJECT_ENSURE_REGISTERED (GlobalRouter);
509
510TypeId
512{
513 static TypeId tid = TypeId ("ns3::GlobalRouter")
514 .SetParent<Object> ()
515 .SetGroupName ("Internet");
516 return tid;
517}
518
520 : m_LSAs ()
521{
522 NS_LOG_FUNCTION (this);
524}
525
527{
528 NS_LOG_FUNCTION (this);
529 ClearLSAs ();
530}
531
532void
534{
535 NS_LOG_FUNCTION (this << routing);
536 m_routingProtocol = routing;
537}
540{
541 NS_LOG_FUNCTION (this);
542 return m_routingProtocol;
543}
544
545void
547{
548 NS_LOG_FUNCTION (this);
550 for (InjectedRoutesI k = m_injectedRoutes.begin ();
551 k != m_injectedRoutes.end ();
552 k = m_injectedRoutes.erase (k))
553 {
554 delete (*k);
555 }
557}
558
559void
561{
562 NS_LOG_FUNCTION (this);
563 for ( ListOfLSAs_t::iterator i = m_LSAs.begin ();
564 i != m_LSAs.end ();
565 i++)
566 {
567 NS_LOG_LOGIC ("Free LSA");
568
569 GlobalRoutingLSA *p = *i;
570 delete p;
571 p = 0;
572
573 *i = 0;
574 }
575 NS_LOG_LOGIC ("Clear list of LSAs");
576 m_LSAs.clear ();
577}
578
581{
582 NS_LOG_FUNCTION (this);
583 return m_routerId;
584}
585
586//
587// DiscoverLSAs is called on all nodes in the system that have a GlobalRouter
588// interface aggregated. We need to go out and discover any adjacent routers
589// and build the Link State Advertisements that reflect them and their associated
590// networks.
591//
594{
595 NS_LOG_FUNCTION (this);
596 Ptr<Node> node = GetObject<Node> ();
597 NS_ABORT_MSG_UNLESS (node, "GlobalRouter::DiscoverLSAs (): GetObject for <Node> interface failed");
598 NS_LOG_LOGIC ("For node " << node->GetId () );
599
600 ClearLSAs ();
601
602 //
603 // While building the Router-LSA, keep a list of those NetDevices for
604 // which the current node is the designated router and we will later build
605 // a NetworkLSA for.
606 //
608
609 //
610 // We're aggregated to a node. We need to ask the node for a pointer to its
611 // Ipv4 interface. This is where the information regarding the attached
612 // interfaces lives. If we're a router, we had better have an Ipv4 interface.
613 //
614 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
615 NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed");
616
617 //
618 // Every router node originates a Router-LSA
619 //
625 pLSA->SetNode (node);
626
627 //
628 // Ask the node for the number of net devices attached. This isn't necessarily
629 // equal to the number of links to adjacent nodes (other routers) as the number
630 // of devices may include those for stub networks (e.g., ethernets, etc.) and
631 // bridge devices also take up an "extra" net device.
632 //
633 uint32_t numDevices = node->GetNDevices ();
634
635 //
636 // Iterate through the devices on the node and walk the channel to see what's
637 // on the other side of the standalone devices..
638 //
639 for (uint32_t i = 0; i < numDevices; ++i)
640 {
641 Ptr<NetDevice> ndLocal = node->GetDevice (i);
642
643 if (DynamicCast <LoopbackNetDevice> (ndLocal))
644 {
645 continue;
646 }
647
648 //
649 // There is an assumption that bridge ports must never have an IP address
650 // associated with them. This turns out to be a very convenient place to
651 // check and make sure that this is the case.
652 //
653 if (NetDeviceIsBridged (ndLocal))
654 {
655 // Initialize to value out of bounds to silence compiler
656 uint32_t interfaceBridge = ipv4Local->GetNInterfaces () + 1;
657 bool rc = FindInterfaceForDevice (node, ndLocal, interfaceBridge);
658 NS_ABORT_MSG_IF (rc, "GlobalRouter::DiscoverLSAs(): Bridge ports must not have an IPv4 interface index");
659 }
660
661 //
662 // Check to see if the net device we just got has a corresponding IP
663 // interface (could be a pure L2 NetDevice) -- for example a net device
664 // associated with a bridge. We are only going to involve devices with
665 // IP addresses in routing.
666 //
667 bool isForwarding = false;
668 for (uint32_t j = 0; j < ipv4Local->GetNInterfaces (); ++j )
669 {
670 if (ipv4Local->GetNetDevice (j) == ndLocal && ipv4Local->IsUp (j) &&
671 ipv4Local->IsForwarding (j))
672 {
673 isForwarding = true;
674 break;
675 }
676 }
677
678 if (!isForwarding)
679 {
680 NS_LOG_LOGIC ("Net device " << ndLocal << "has no IP interface or is not enabled for forwarding, skipping");
681 continue;
682 }
683
684 //
685 // We have a net device that we need to check out. If it supports
686 // broadcast and is not a point-point link, then it will be either a stub
687 // network or a transit network depending on the number of routers on
688 // the segment. We add the appropriate link record to the LSA.
689 //
690 // If the device is a point to point link, we treat it separately. In
691 // that case, there may be zero, one, or two link records added.
692 //
693
694 if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () )
695 {
696 NS_LOG_LOGIC ("Broadcast link");
697 ProcessBroadcastLink (ndLocal, pLSA, c);
698 }
699 else if (ndLocal->IsPointToPoint () )
700 {
701 NS_LOG_LOGIC ("Point=to-point link");
702 ProcessPointToPointLink (ndLocal, pLSA);
703 }
704 else
705 {
706 NS_ASSERT_MSG (0, "GlobalRouter::DiscoverLSAs (): unknown link type");
707 }
708 }
709
710 NS_LOG_LOGIC ("========== LSA for node " << node->GetId () << " ==========");
711 NS_LOG_LOGIC (*pLSA);
712 m_LSAs.push_back (pLSA);
713 pLSA = 0;
714
715 //
716 // Now, determine whether we need to build a NetworkLSA. This is the case if
717 // we found at least one designated router.
718 //
719 uint32_t nDesignatedRouters = c.GetN ();
720 if (nDesignatedRouters > 0)
721 {
722 NS_LOG_LOGIC ("Build Network LSAs");
724 }
725
726 //
727 // Build injected route LSAs as external routes
728 // RFC 2328, section 12.4.4
729 //
730 for (InjectedRoutesCI i = m_injectedRoutes.begin ();
731 i != m_injectedRoutes.end ();
732 i++)
733 {
736 pLSA->SetLinkStateId ((*i)->GetDestNetwork ());
738 pLSA->SetNetworkLSANetworkMask ((*i)->GetDestNetworkMask ());
740 m_LSAs.push_back (pLSA);
741 }
742 return m_LSAs.size ();
743}
744
745void
747{
748 NS_LOG_FUNCTION (this << nd << pLSA << &c);
749
750 if (nd->IsBridge ())
751 {
752 ProcessBridgedBroadcastLink (nd, pLSA, c);
753 }
754 else
755 {
756 ProcessSingleBroadcastLink (nd, pLSA, c);
757 }
758}
759
760void
762{
763 NS_LOG_FUNCTION (this << nd << pLSA << &c);
764
766 NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessSingleBroadcastLink(): Can't alloc link record");
767
768 //
769 // We have some preliminaries to do to get enough information to proceed.
770 // This information we need comes from the internet stack, so notice that
771 // there is an implied assumption that global routing is only going to
772 // work with devices attached to the internet stack (have an ipv4 interface
773 // associated to them.
774 //
775 Ptr<Node> node = nd->GetNode ();
776
777 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
778 NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for <Ipv4> interface failed");
779
780 // Initialize to value out of bounds to silence compiler
781 uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
782 bool rc = FindInterfaceForDevice (node, nd, interfaceLocal);
783 NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessSingleBroadcastLink(): No interface index associated with device");
784
785 if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
786 {
787 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
788 }
789 Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
790 Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
791 NS_LOG_LOGIC ("Working with local address " << addrLocal);
792 uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
793
794 //
795 // Check to see if the net device is connected to a channel/network that has
796 // another router on it. If there is no other router on the link (but us) then
797 // this is a stub network. If we find another router, then what we have here
798 // is a transit network.
799 //
801 if (AnotherRouterOnLink (nd) == false)
802 {
803 //
804 // This is a net device connected to a stub network
805 //
806 NS_LOG_LOGIC ("Router-LSA Stub Network");
808
809 //
810 // According to OSPF, the Link ID is the IP network number of
811 // the attached network.
812 //
813 plr->SetLinkId (addrLocal.CombineMask (maskLocal));
814
815 //
816 // and the Link Data is the network mask; converted to Ipv4Address
817 //
818 Ipv4Address maskLocalAddr;
819 maskLocalAddr.Set (maskLocal.Get ());
820 plr->SetLinkData (maskLocalAddr);
821 plr->SetMetric (metricLocal);
822 pLSA->AddLinkRecord (plr);
823 plr = 0;
824 }
825 else
826 {
827 //
828 // We have multiple routers on a broadcast interface, so this is
829 // a transit network.
830 //
831 NS_LOG_LOGIC ("Router-LSA Transit Network");
833
834 //
835 // By definition, the router with the lowest IP address is the
836 // designated router for the network. OSPF says that the Link ID
837 // gets the IP interface address of the designated router in this
838 // case.
839 //
841 Ipv4Address desigRtr;
842 desigRtr = FindDesignatedRouterForLink (nd);
843
844 //
845 // Let's double-check that any designated router we find out on our
846 // network is really on our network.
847 //
848 if (desigRtr != "255.255.255.255")
849 {
850 Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
851 Ipv4Address networkThere = desigRtr.CombineMask (maskLocal);
852 NS_ABORT_MSG_UNLESS (networkHere == networkThere,
853 "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion (" <<
854 addrLocal << "/" << maskLocal.GetPrefixLength () << ", " <<
855 desigRtr << "/" << maskLocal.GetPrefixLength () << ")");
856 }
857 if (desigRtr == addrLocal)
858 {
859 c.Add (nd);
860 NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
861 }
862 plr->SetLinkId (desigRtr);
863
864 //
865 // OSPF says that the Link Data is this router's own IP address.
866 //
867 plr->SetLinkData (addrLocal);
868 plr->SetMetric (metricLocal);
869 pLSA->AddLinkRecord (plr);
870 plr = 0;
871 }
872}
873
874void
876{
877 NS_LOG_FUNCTION (this << nd << pLSA << &c);
878 NS_ASSERT_MSG (nd->IsBridge (), "GlobalRouter::ProcessBridgedBroadcastLink(): Called with non-bridge net device");
879
880#if 0
881 //
882 // It is possible to admit the possibility that a bridge device on a node
883 // can also participate in routing. This would surprise people who don't
884 // come from Microsoft-land where they do use such a construct. Based on
885 // the principle of least-surprise, we will leave the relatively simple
886 // code in place to do this, but not enable it until someone really wants
887 // the capability. Even then, we will not enable this code as a default
888 // but rather something you will have to go and turn on.
889 //
890
892 NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
893
894 //
895 // We have some preliminaries to do to get enough information to proceed.
896 // This information we need comes from the internet stack, so notice that
897 // there is an implied assumption that global routing is only going to
898 // work with devices attached to the internet stack (have an ipv4 interface
899 // associated to them.
900 //
901 Ptr<Node> node = nd->GetNode ();
902 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
903 NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for <Ipv4> interface failed");
904
905 // Initialize to value out of bounds to silence compiler
906 uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
907 bool rc = FindInterfaceForDevice (node, nd, interfaceLocal);
908 NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessBridgedBroadcastLink(): No interface index associated with device");
909
910 if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
911 {
912 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
913 }
914 Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
915 Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
916 NS_LOG_LOGIC ("Working with local address " << addrLocal);
917 uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
918
919 //
920 // We need to handle a bridge on the router. This means that we have been
921 // given a net device that is a BridgeNetDevice. It has an associated Ipv4
922 // interface index and address. Some number of other net devices live "under"
923 // the bridge device as so-called bridge ports. In a nutshell, what we have
924 // to do is to repeat what is done for a single broadcast link on all of
925 // those net devices living under the bridge (trolls?)
926 //
927
928 bool areTransitNetwork = false;
929 Ipv4Address desigRtr ("255.255.255.255");
930
931 for (uint32_t i = 0; i < bnd->GetNBridgePorts (); ++i)
932 {
933 Ptr<NetDevice> ndTemp = bnd->GetBridgePort (i);
934
935 //
936 // We have to decide if we are a transit network. This is characterized
937 // by the presence of another router on the network segment. If we find
938 // another router on any of our bridged links, we are a transit network.
939 //
941 if (AnotherRouterOnLink (ndTemp))
942 {
943 areTransitNetwork = true;
944
945 //
946 // If we're going to be a transit network, then we have got to elect
947 // a designated router for the whole bridge. This means finding the
948 // router with the lowest IP address on the whole bridge. We ask
949 // for the lowest address on each segment and pick the lowest of them
950 // all.
951 //
953 Ipv4Address desigRtrTemp = FindDesignatedRouterForLink (ndTemp);
954
955 //
956 // Let's double-check that any designated router we find out on our
957 // network is really on our network.
958 //
959 if (desigRtrTemp != "255.255.255.255")
960 {
961 Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
962 Ipv4Address networkThere = desigRtrTemp.CombineMask (maskLocal);
963 NS_ABORT_MSG_UNLESS (networkHere == networkThere,
964 "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion (" <<
965 addrLocal << "/" << maskLocal.GetPrefixLength () << ", " <<
966 desigRtrTemp << "/" << maskLocal.GetPrefixLength () << ")");
967 }
968 if (desigRtrTemp < desigRtr)
969 {
970 desigRtr = desigRtrTemp;
971 }
972 }
973 }
974 //
975 // That's all the information we need to put it all together, just like we did
976 // in the case of a single broadcast link.
977 //
978
980 NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessBridgedBroadcastLink(): Can't alloc link record");
981
982 if (areTransitNetwork == false)
983 {
984 //
985 // This is a net device connected to a bridge of stub networks
986 //
987 NS_LOG_LOGIC ("Router-LSA Stub Network");
989
990 //
991 // According to OSPF, the Link ID is the IP network number of
992 // the attached network.
993 //
994 plr->SetLinkId (addrLocal.CombineMask (maskLocal));
995
996 //
997 // and the Link Data is the network mask; converted to Ipv4Address
998 //
999 Ipv4Address maskLocalAddr;
1000 maskLocalAddr.Set (maskLocal.Get ());
1001 plr->SetLinkData (maskLocalAddr);
1002 plr->SetMetric (metricLocal);
1003 pLSA->AddLinkRecord (plr);
1004 plr = 0;
1005 }
1006 else
1007 {
1008 //
1009 // We have multiple routers on a bridged broadcast interface, so this is
1010 // a transit network.
1011 //
1012 NS_LOG_LOGIC ("Router-LSA Transit Network");
1014
1015 //
1016 // By definition, the router with the lowest IP address is the
1017 // designated router for the network. OSPF says that the Link ID
1018 // gets the IP interface address of the designated router in this
1019 // case.
1020 //
1021 if (desigRtr == addrLocal)
1022 {
1023 c.Add (nd);
1024 NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
1025 }
1026 plr->SetLinkId (desigRtr);
1027
1028 //
1029 // OSPF says that the Link Data is this router's own IP address.
1030 //
1031 plr->SetLinkData (addrLocal);
1032 plr->SetMetric (metricLocal);
1033 pLSA->AddLinkRecord (plr);
1034 plr = 0;
1035 }
1036#endif
1037}
1038
1039void
1041{
1042 NS_LOG_FUNCTION (this << ndLocal << pLSA);
1043
1044 //
1045 // We have some preliminaries to do to get enough information to proceed.
1046 // This information we need comes from the internet stack, so notice that
1047 // there is an implied assumption that global routing is only going to
1048 // work with devices attached to the internet stack (have an ipv4 interface
1049 // associated to them.
1050 //
1051 Ptr<Node> nodeLocal = ndLocal->GetNode ();
1052
1053 Ptr<Ipv4> ipv4Local = nodeLocal->GetObject<Ipv4> ();
1054 NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1055
1056 uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
1057 bool rc = FindInterfaceForDevice (nodeLocal, ndLocal, interfaceLocal);
1058 NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device");
1059
1060 if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
1061 {
1062 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1063 }
1064 Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
1065 NS_LOG_LOGIC ("Working with local address " << addrLocal);
1066 uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
1067
1068 //
1069 // Now, we're going to walk over to the remote net device on the other end of
1070 // the point-to-point channel we know we have. This is where our adjacent
1071 // router (to use OSPF lingo) is running.
1072 //
1073 Ptr<Channel> ch = ndLocal->GetChannel ();
1074
1075 //
1076 // Get the net device on the other side of the point-to-point channel.
1077 //
1078 Ptr<NetDevice> ndRemote = GetAdjacent (ndLocal, ch);
1079
1080 //
1081 // The adjacent net device is aggregated to a node. We need to ask that net
1082 // device for its node, then ask that node for its Ipv4 interface. Note a
1083 // requirement that nodes on either side of a point-to-point link must have
1084 // internet stacks; and an assumption that point-to-point links are incompatible
1085 // with bridging.
1086 //
1087 Ptr<Node> nodeRemote = ndRemote->GetNode ();
1088 Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4> ();
1089 NS_ABORT_MSG_UNLESS (ipv4Remote,
1090 "GlobalRouter::ProcessPointToPointLink(): GetObject for remote <Ipv4> failed");
1091
1092 //
1093 // Further note the requirement that nodes on either side of a point-to-point
1094 // link must participate in global routing and therefore have a GlobalRouter
1095 // interface aggregated.
1096 //
1097 Ptr<GlobalRouter> rtrRemote = nodeRemote->GetObject<GlobalRouter> ();
1098 if (rtrRemote == 0)
1099 {
1100 // This case is possible if the remote does not participate in global routing
1101 return;
1102 }
1103 //
1104 // We're going to need the remote router ID, so we might as well get it now.
1105 //
1106 Ipv4Address rtrIdRemote = rtrRemote->GetRouterId ();
1107 NS_LOG_LOGIC ("Working with remote router " << rtrIdRemote);
1108
1109 //
1110 // Now, just like we did above, we need to get the IP interface index for the
1111 // net device on the other end of the point-to-point channel.
1112 //
1113 uint32_t interfaceRemote = ipv4Remote->GetNInterfaces () + 1;
1114 rc = FindInterfaceForDevice (nodeRemote, ndRemote, interfaceRemote);
1115 NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with remote device");
1116
1117 //
1118 // Now that we have the Ipv4 interface, we can get the (remote) address and
1119 // mask we need.
1120 //
1121 if (ipv4Remote->GetNAddresses (interfaceRemote) > 1)
1122 {
1123 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1124 }
1125 Ipv4Address addrRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetLocal ();
1126 Ipv4Mask maskRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetMask ();
1127 NS_LOG_LOGIC ("Working with remote address " << addrRemote);
1128
1129 //
1130 // Now we can fill out the link records for this link. There are always two
1131 // link records; the first is a point-to-point record describing the link and
1132 // the second is a stub network record with the network number.
1133 //
1135 if (ipv4Remote->IsUp (interfaceRemote))
1136 {
1137 NS_LOG_LOGIC ("Remote side interface " << interfaceRemote << " is up-- add a type 1 link");
1138
1139 plr = new GlobalRoutingLinkRecord;
1140 NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1142 plr->SetLinkId (rtrIdRemote);
1143 plr->SetLinkData (addrLocal);
1144 plr->SetMetric (metricLocal);
1145 pLSA->AddLinkRecord (plr);
1146 plr = 0;
1147 }
1148
1149 // Regardless of state of peer, add a type 3 link (RFC 2328: 12.4.1.1)
1150 plr = new GlobalRoutingLinkRecord;
1151 NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1153 plr->SetLinkId (addrRemote);
1154 plr->SetLinkData (Ipv4Address (maskRemote.Get ())); // Frown
1155 plr->SetMetric (metricLocal);
1156 pLSA->AddLinkRecord (plr);
1157 plr = 0;
1158}
1159
1160void
1162{
1163 NS_LOG_FUNCTION (this << &c);
1164
1165 uint32_t nDesignatedRouters = c.GetN ();
1166 NS_LOG_DEBUG ("Number of designated routers: " << nDesignatedRouters);
1167
1168 for (uint32_t i = 0; i < nDesignatedRouters; ++i)
1169 {
1170 //
1171 // Build one NetworkLSA for each net device talking to a network that we are the
1172 // designated router for. These devices are in the provided container.
1173 //
1174 Ptr<NetDevice> ndLocal = c.Get (i);
1175 Ptr<Node> node = ndLocal->GetNode ();
1176
1177 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
1178 NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1179
1180 uint32_t interfaceLocal = ipv4Local->GetNInterfaces () + 1;
1181 bool rc = FindInterfaceForDevice (node, ndLocal, interfaceLocal);
1182 NS_ABORT_MSG_IF (rc == false, "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device");
1183
1184 if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
1185 {
1186 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1187 }
1188 Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
1189 Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
1190
1192 NS_ABORT_MSG_IF (pLSA == 0, "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record");
1193
1195 pLSA->SetLinkStateId (addrLocal);
1197 pLSA->SetNetworkLSANetworkMask (maskLocal);
1199 pLSA->SetNode (node);
1200
1201 //
1202 // Build a list of AttachedRouters by walking the devices in the channel
1203 // and, if we find a node with a GlobalRouter interface and an IPv4
1204 // interface associated with that device, we call it an attached router.
1205 //
1207 Ptr<Channel> ch = ndLocal->GetChannel ();
1208 std::size_t nDevices = ch->GetNDevices ();
1209 NS_ASSERT (nDevices);
1211 NS_LOG_LOGIC ("Found " << deviceList.GetN () << " non-bridged devices on channel");
1212
1213 for (uint32_t i = 0; i < deviceList.GetN (); i++)
1214 {
1215 Ptr<NetDevice> tempNd = deviceList.Get (i);
1216 NS_ASSERT (tempNd);
1217 if (tempNd == ndLocal)
1218 {
1219 NS_LOG_LOGIC ("Adding " << addrLocal << " to Network LSA");
1220 pLSA->AddAttachedRouter (addrLocal);
1221 continue;
1222 }
1223 Ptr<Node> tempNode = tempNd->GetNode ();
1224
1225 // Does the node in question have a GlobalRouter interface? If not it can
1226 // hardly be considered an attached router.
1227 //
1228 Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter> ();
1229 if (rtr == 0)
1230 {
1231 NS_LOG_LOGIC ("Node " << tempNode->GetId () << " does not have GlobalRouter interface--skipping");
1232 continue;
1233 }
1234
1235 //
1236 // Does the attached node have an ipv4 interface for the device we're probing?
1237 // If not, it can't play router.
1238 //
1239 uint32_t tempInterface = 0;
1240 if (FindInterfaceForDevice (tempNode, tempNd, tempInterface))
1241 {
1242 Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> ();
1243 NS_ASSERT (tempIpv4);
1244 if (!tempIpv4->IsUp (tempInterface))
1245 {
1246 NS_LOG_LOGIC ("Remote side interface " << tempInterface << " not up");
1247 }
1248 else
1249 {
1250 if (tempIpv4->GetNAddresses (tempInterface) > 1)
1251 {
1252 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1253 }
1254 Ipv4Address tempAddr = tempIpv4->GetAddress (tempInterface, 0).GetLocal ();
1255 NS_LOG_LOGIC ("Adding " << tempAddr << " to Network LSA");
1256 pLSA->AddAttachedRouter (tempAddr);
1257 }
1258 }
1259 else
1260 {
1261 NS_LOG_LOGIC ("Node " << tempNode->GetId () << " device " << tempNd << " does not have IPv4 interface; skipping");
1262 }
1263 }
1264 m_LSAs.push_back (pLSA);
1265 NS_LOG_LOGIC ("========== LSA for node " << node->GetId () << " ==========");
1266 NS_LOG_LOGIC (*pLSA);
1267 pLSA = 0;
1268 }
1269}
1270
1273{
1274 NS_LOG_FUNCTION (this << ch);
1276
1277 for (std::size_t i = 0; i < ch->GetNDevices (); i++)
1278 {
1279 Ptr<NetDevice> nd = ch->GetDevice (i);
1280 NS_LOG_LOGIC ("checking to see if the device " << nd << " is bridged");
1282 if (bnd && BridgeHasAlreadyBeenVisited (bnd) == false)
1283 {
1284 NS_LOG_LOGIC ("Device is bridged by BridgeNetDevice " << bnd << " with " << bnd->GetNBridgePorts () << " ports");
1285 MarkBridgeAsVisited (bnd);
1286 // Find all channels bridged together, and recursively call
1287 // on all other channels
1288 for (uint32_t j = 0; j < bnd->GetNBridgePorts (); j++)
1289 {
1290 Ptr<NetDevice> bridgedDevice = bnd->GetBridgePort (j);
1291 if (bridgedDevice->GetChannel () == ch)
1292 {
1293 NS_LOG_LOGIC ("Skipping my own device/channel");
1294 continue;
1295 }
1296 NS_LOG_LOGIC ("Calling on channel " << bridgedDevice->GetChannel ());
1297 c.Add (FindAllNonBridgedDevicesOnLink (bridgedDevice->GetChannel ()));
1298 }
1299 }
1300 else
1301 {
1302 NS_LOG_LOGIC ("Device is not bridged; adding");
1303 c.Add (nd);
1304 }
1305 }
1306 NS_LOG_LOGIC ("Found " << c.GetN () << " devices");
1307 return c;
1308}
1309
1310//
1311// Given a local net device, we need to walk the channel to which the net device is
1312// attached and look for nodes with GlobalRouter interfaces on them (one of them
1313// will be us). Of these, the router with the lowest IP address on the net device
1314// connecting to the channel becomes the designated router for the link.
1315//
1318{
1319 NS_LOG_FUNCTION (this << ndLocal);
1320
1321 Ptr<Channel> ch = ndLocal->GetChannel ();
1322 uint32_t nDevices = ch->GetNDevices ();
1323 NS_ASSERT (nDevices);
1324
1325 NS_LOG_LOGIC ("Looking for designated router off of net device " << ndLocal << " on node " <<
1326 ndLocal->GetNode ()->GetId ());
1327
1328 Ipv4Address desigRtr ("255.255.255.255");
1329
1330 //
1331 // Look through all of the devices on the channel to which the net device
1332 // in question is attached.
1333 //
1334 for (uint32_t i = 0; i < nDevices; i++)
1335 {
1336 Ptr<NetDevice> ndOther = ch->GetDevice (i);
1337 NS_ASSERT (ndOther);
1338
1339 Ptr<Node> nodeOther = ndOther->GetNode ();
1340
1341 NS_LOG_LOGIC ("Examine channel device " << i << " on node " << nodeOther->GetId ());
1342
1343 //
1344 // For all other net devices, we need to check and see if a router
1345 // is present. If the net device on the other side is a bridged
1346 // device, we need to consider all of the other devices on the
1347 // bridge as well (all of the bridge ports.
1348 //
1349 NS_LOG_LOGIC ("checking to see if the device is bridged");
1351 if (bnd)
1352 {
1353 NS_LOG_LOGIC ("Device is bridged by BridgeNetDevice " << bnd);
1354
1355 //
1356 // When enumerating a bridge, don't count the netdevice we came in on
1357 //
1358 if (ndLocal == ndOther)
1359 {
1360 NS_LOG_LOGIC ("Skip -- it is where we came from.");
1361 continue;
1362 }
1363
1364 //
1365 // It is possible that the bridge net device is sitting under a
1366 // router, so we have to check for the presence of that router
1367 // before we run off and follow all the links
1368 //
1369 // We require a designated router to have a GlobalRouter interface and
1370 // an internet stack that includes the Ipv4 interface. If it doesn't
1371 // it can't play router.
1372 //
1373 NS_LOG_LOGIC ("Checking for router on bridge net device " << bnd);
1374 Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
1375 Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
1376 if (rtr && ipv4)
1377 {
1378 // Initialize to value out of bounds to silence compiler
1379 uint32_t interfaceOther = ipv4->GetNInterfaces () + 1;
1380 if (FindInterfaceForDevice (nodeOther, bnd, interfaceOther))
1381 {
1382 NS_LOG_LOGIC ("Found router on bridge net device " << bnd);
1383 if (!ipv4->IsUp (interfaceOther))
1384 {
1385 NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up");
1386 continue;
1387 }
1388 if (ipv4->GetNAddresses (interfaceOther) > 1)
1389 {
1390 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1391 }
1392 Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal ();
1393 desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1394 NS_LOG_LOGIC ("designated router now " << desigRtr);
1395 }
1396 }
1397
1398 //
1399 // Check if we have seen this bridge net device already while
1400 // recursively enumerating an L2 broadcast domain. If it is new
1401 // to us, go ahead and process it. If we have already processed it,
1402 // move to the next
1403 //
1405 {
1406 NS_ABORT_MSG ("ERROR: L2 forwarding loop detected!");
1407 }
1408
1410
1411 NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
1412 for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1413 {
1414 Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
1415 NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
1416 if (ndBridged == ndOther)
1417 {
1418 NS_LOG_LOGIC ("That bridge port is me, don't walk backward");
1419 continue;
1420 }
1421
1422 NS_LOG_LOGIC ("Recursively looking for routers down bridge port " << ndBridged);
1423 Ipv4Address addrOther = FindDesignatedRouterForLink (ndBridged);
1424 desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1425 NS_LOG_LOGIC ("designated router now " << desigRtr);
1426 }
1427 }
1428 else
1429 {
1430 NS_LOG_LOGIC ("This device is not bridged");
1431 Ptr<Node> nodeOther = ndOther->GetNode ();
1432 NS_ASSERT (nodeOther);
1433
1434 //
1435 // We require a designated router to have a GlobalRouter interface and
1436 // an internet stack that includes the Ipv4 interface. If it doesn't
1437 //
1438 Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter> ();
1439 Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4> ();
1440 if (rtr && ipv4)
1441 {
1442 // Initialize to value out of bounds to silence compiler
1443 uint32_t interfaceOther = ipv4->GetNInterfaces () + 1;
1444 if (FindInterfaceForDevice (nodeOther, ndOther, interfaceOther))
1445 {
1446 if (!ipv4->IsUp (interfaceOther))
1447 {
1448 NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up");
1449 continue;
1450 }
1451 NS_LOG_LOGIC ("Found router on net device " << ndOther);
1452 if (ipv4->GetNAddresses (interfaceOther) > 1)
1453 {
1454 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1455 }
1456 Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal ();
1457 desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1458 NS_LOG_LOGIC ("designated router now " << desigRtr);
1459 }
1460 }
1461 }
1462 }
1463 return desigRtr;
1464}
1465
1466//
1467// Given a node and an attached net device, take a look off in the channel to
1468// which the net device is attached and look for a node on the other side
1469// that has a GlobalRouter interface aggregated. Life gets more complicated
1470// when there is a bridged net device on the other side.
1471//
1472bool
1474{
1475 NS_LOG_FUNCTION (this << nd);
1476
1477 Ptr<Channel> ch = nd->GetChannel ();
1478 if (!ch)
1479 {
1480 // It may be that this net device is a stub device, without a channel
1481 return false;
1482 }
1483 uint32_t nDevices = ch->GetNDevices ();
1484 NS_ASSERT (nDevices);
1485
1486 NS_LOG_LOGIC ("Looking for routers off of net device " << nd << " on node " << nd->GetNode ()->GetId ());
1487
1488 //
1489 // Look through all of the devices on the channel to which the net device
1490 // in question is attached.
1491 //
1492 for (uint32_t i = 0; i < nDevices; i++)
1493 {
1494 Ptr<NetDevice> ndOther = ch->GetDevice (i);
1495 NS_ASSERT (ndOther);
1496
1497 NS_LOG_LOGIC ("Examine channel device " << i << " on node " << ndOther->GetNode ()->GetId ());
1498
1499 //
1500 // Ignore the net device itself.
1501 //
1502 if (ndOther == nd)
1503 {
1504 NS_LOG_LOGIC ("Myself, skip");
1505 continue;
1506 }
1507
1508 //
1509 // For all other net devices, we need to check and see if a router
1510 // is present. If the net device on the other side is a bridged
1511 // device, we need to consider all of the other devices on the
1512 // bridge.
1513 //
1514 NS_LOG_LOGIC ("checking to see if device is bridged");
1516 if (bnd)
1517 {
1518 NS_LOG_LOGIC ("Device is bridged by net device " << bnd);
1519
1520 //
1521 // Check if we have seen this bridge net device already while
1522 // recursively enumerating an L2 broadcast domain. If it is new
1523 // to us, go ahead and process it. If we have already processed it,
1524 // move to the next
1525 //
1527 {
1528 NS_ABORT_MSG ("ERROR: L2 forwarding loop detected!");
1529 }
1530
1532
1533 NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bnd);
1534 for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1535 {
1536 Ptr<NetDevice> ndBridged = bnd->GetBridgePort (j);
1537 NS_LOG_LOGIC ("Examining bridge port " << j << " device " << ndBridged);
1538 if (ndBridged == ndOther)
1539 {
1540 NS_LOG_LOGIC ("That bridge port is me, skip");
1541 continue;
1542 }
1543
1544 NS_LOG_LOGIC ("Recursively looking for routers on bridge port " << ndBridged);
1545 if (AnotherRouterOnLink (ndBridged))
1546 {
1547 NS_LOG_LOGIC ("Found routers on bridge port, return true");
1548 return true;
1549 }
1550 }
1551 NS_LOG_LOGIC ("No routers on bridged net device, return false");
1552 return false;
1553 }
1554
1555 NS_LOG_LOGIC ("This device is not bridged");
1556 Ptr<Node> nodeTemp = ndOther->GetNode ();
1557 NS_ASSERT (nodeTemp);
1558
1559 Ptr<GlobalRouter> rtr = nodeTemp->GetObject<GlobalRouter> ();
1560 if (rtr)
1561 {
1562 NS_LOG_LOGIC ("Found GlobalRouter interface, return true");
1563 return true;
1564 }
1565 else
1566 {
1567 NS_LOG_LOGIC ("No GlobalRouter interface on device, continue search");
1568 }
1569 }
1570 NS_LOG_LOGIC ("No routers found, return false");
1571 return false;
1572}
1573
1576{
1577 NS_LOG_FUNCTION (this);
1578 return m_LSAs.size ();
1579}
1580
1581//
1582// Get the nth link state advertisement from this router.
1583//
1584bool
1586{
1587 NS_LOG_FUNCTION (this << n << &lsa);
1588 NS_ASSERT_MSG (lsa.IsEmpty (), "GlobalRouter::GetLSA (): Must pass empty LSA");
1589//
1590// All of the work was done in GetNumLSAs. All we have to do here is to
1591// walk the list of link state advertisements created there and return the
1592// one the client is interested in.
1593//
1594 ListOfLSAs_t::const_iterator i = m_LSAs.begin ();
1595 uint32_t j = 0;
1596
1597 for (; i != m_LSAs.end (); i++, j++)
1598 {
1599 if (j == n)
1600 {
1601 GlobalRoutingLSA *p = *i;
1602 lsa = *p;
1603 return true;
1604 }
1605 }
1606
1607 return false;
1608}
1609
1610void
1612{
1613 NS_LOG_FUNCTION (this << network << networkMask);
1615//
1616// Interface number does not matter here, using 1.
1617//
1619 networkMask,
1620 1);
1621 m_injectedRoutes.push_back (route);
1622}
1623
1626{
1627 NS_LOG_FUNCTION (this << index);
1628 if (index < m_injectedRoutes.size ())
1629 {
1630 uint32_t tmp = 0;
1631 for (InjectedRoutesCI i = m_injectedRoutes.begin ();
1632 i != m_injectedRoutes.end ();
1633 i++)
1634 {
1635 if (tmp == index)
1636 {
1637 return *i;
1638 }
1639 tmp++;
1640 }
1641 }
1642 NS_ASSERT (false);
1643 // quiet compiler.
1644 return 0;
1645}
1646
1649{
1650 NS_LOG_FUNCTION (this);
1651 return m_injectedRoutes.size ();
1652}
1653
1654void
1656{
1657 NS_LOG_FUNCTION (this << index);
1658 NS_ASSERT (index < m_injectedRoutes.size ());
1659 uint32_t tmp = 0;
1660 for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
1661 {
1662 if (tmp == index)
1663 {
1664 NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_injectedRoutes.size ());
1665 delete *i;
1666 m_injectedRoutes.erase (i);
1667 return;
1668 }
1669 tmp++;
1670 }
1671}
1672
1673bool
1675{
1676 NS_LOG_FUNCTION (this << network << networkMask);
1677 for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
1678 {
1679 if ((*i)->GetDestNetwork () == network && (*i)->GetDestNetworkMask () == networkMask)
1680 {
1681 NS_LOG_LOGIC ("Withdrawing route to network/mask " << network << "/" << networkMask);
1682 delete *i;
1683 m_injectedRoutes.erase (i);
1684 return true;
1685 }
1686 }
1687 return false;
1688}
1689
1690
1691//
1692// Link through the given channel and find the net device that's on the
1693// other end. This only makes sense with a point-to-point channel.
1694//
1697{
1698 NS_LOG_FUNCTION (this << nd << ch);
1699 NS_ASSERT_MSG (ch->GetNDevices () == 2, "GlobalRouter::GetAdjacent (): Channel with other than two devices");
1700//
1701// This is a point to point channel with two endpoints. Get both of them.
1702//
1703 Ptr<NetDevice> nd1 = ch->GetDevice (0);
1704 Ptr<NetDevice> nd2 = ch->GetDevice (1);
1705//
1706// One of the endpoints is going to be "us" -- that is the net device attached
1707// to the node on which we're running -- i.e., "nd". The other endpoint (the
1708// one to which we are connected via the channel) is the adjacent router.
1709//
1710 if (nd1 == nd)
1711 {
1712 return nd2;
1713 }
1714 else if (nd2 == nd)
1715 {
1716 return nd1;
1717 }
1718 else
1719 {
1720 NS_ASSERT_MSG (false,
1721 "GlobalRouter::GetAdjacent (): Wrong or confused channel?");
1722 return 0;
1723 }
1724}
1725
1726//
1727// Given a node and a net device, find an IPV4 interface index that corresponds
1728// to that net device. This function may fail for various reasons. If a node
1729// does not have an internet stack (for example if it is a bridge) we won't have
1730// an IPv4 at all. If the node does have a stack, but the net device in question
1731// is bridged, there will not be an interface associated directly with the device.
1732//
1733bool
1735{
1736 NS_LOG_FUNCTION (this << node << nd << &index);
1737 NS_LOG_LOGIC ("For node " << node->GetId () << " for net device " << nd );
1738
1739 Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
1740 if (ipv4 == 0)
1741 {
1742 NS_LOG_LOGIC ("No Ipv4 interface on node " << node->GetId ());
1743 return false;
1744 }
1745
1746 for (uint32_t i = 0; i < ipv4->GetNInterfaces (); ++i )
1747 {
1748 if (ipv4->GetNetDevice (i) == nd)
1749 {
1750 NS_LOG_LOGIC ("Device " << nd << " has associated ipv4 index " << i);
1751 index = i;
1752 return true;
1753 }
1754 }
1755
1756 NS_LOG_LOGIC ("Device " << nd << " has no associated ipv4 index");
1757 return false;
1758}
1759
1760//
1761// Decide whether or not a given net device is being bridged by a BridgeNetDevice.
1762//
1765{
1766 NS_LOG_FUNCTION (this << nd);
1767
1768 Ptr<Node> node = nd->GetNode ();
1769 uint32_t nDevices = node->GetNDevices ();
1770
1771 //
1772 // There is no bit on a net device that says it is being bridged, so we have
1773 // to look for bridges on the node to which the device is attached. If we
1774 // find a bridge, we need to look through its bridge ports (the devices it
1775 // bridges) to see if we find the device in question.
1776 //
1777 for (uint32_t i = 0; i < nDevices; ++i)
1778 {
1779 Ptr<NetDevice> ndTest = node->GetDevice (i);
1780 NS_LOG_LOGIC ("Examine device " << i << " " << ndTest);
1781
1782 if (ndTest->IsBridge ())
1783 {
1784 NS_LOG_LOGIC ("device " << i << " is a bridge net device");
1786 NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
1787
1788 for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
1789 {
1790 NS_LOG_LOGIC ("Examine bridge port " << j << " " << bnd->GetBridgePort (j));
1791 if (bnd->GetBridgePort (j) == nd)
1792 {
1793 NS_LOG_LOGIC ("Net device " << nd << " is bridged by " << bnd);
1794 return bnd;
1795 }
1796 }
1797 }
1798 }
1799 NS_LOG_LOGIC ("Net device " << nd << " is not bridged");
1800 return 0;
1801}
1802
1803//
1804// Start a new enumeration of an L2 broadcast domain by clearing m_bridgesVisited
1805//
1806void
1808{
1809 m_bridgesVisited.clear();
1810}
1811
1812//
1813// Check if we have already visited a given bridge net device by searching m_bridgesVisited
1814//
1815bool
1817{
1818 std::vector<Ptr<BridgeNetDevice> >::iterator iter;
1819 for (iter = m_bridgesVisited.begin (); iter != m_bridgesVisited.end (); ++iter)
1820 {
1821 if (bridgeNetDevice == *iter)
1822 {
1823 NS_LOG_LOGIC ("Bridge " << bridgeNetDevice << " has been visited.");
1824 return true;
1825 }
1826 }
1827 return false;
1828}
1829
1830//
1831// Remember that we visited a bridge net device by adding it to m_bridgesVisited
1832//
1833void
1835{
1836 NS_LOG_FUNCTION (this << bridgeNetDevice);
1837 m_bridgesVisited.push_back (bridgeNetDevice);
1838}
1839
1840
1841} // namespace ns3
a virtual net device that bridges multiple LAN segments
virtual Ptr< NetDevice > GetDevice(std::size_t i) const =0
virtual std::size_t GetNDevices(void) const =0
static uint32_t AllocateRouterId()
Allocate a 32-bit router ID from monotonically increasing counter.
An interface aggregated to a node to provide global routing info.
static TypeId GetTypeId(void)
Get the type ID.
Ipv4Address FindDesignatedRouterForLink(Ptr< NetDevice > ndLocal) const
Finds a designated router.
void MarkBridgeAsVisited(Ptr< BridgeNetDevice > device) const
When recursively checking for devices on the link, mark a given device as having been visited.
Ptr< Ipv4GlobalRouting > m_routingProtocol
the Ipv4GlobalRouting in use
bool GetLSA(uint32_t n, GlobalRoutingLSA &lsa) const
Get a Global Routing Link State Advertisements that this router has said that it can export.
void ProcessSingleBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
Process a single broadcast link.
bool WithdrawRoute(Ipv4Address network, Ipv4Mask networkMask)
Withdraw a route from the global unicast routing table.
virtual void DoDispose(void)
Destructor implementation.
NetDeviceContainer FindAllNonBridgedDevicesOnLink(Ptr< Channel > ch) const
Return a container of all non-bridged NetDevices on a link.
bool BridgeHasAlreadyBeenVisited(Ptr< BridgeNetDevice > device) const
When recursively checking for devices on the link, check whether a given device has already been visi...
InjectedRoutes m_injectedRoutes
Routes we are exporting.
void InjectRoute(Ipv4Address network, Ipv4Mask networkMask)
Inject a route to be circulated to other routers as an external route.
uint32_t DiscoverLSAs(void)
Walk the connected channels, discover the adjacent routers and build the associated number of Global ...
Ptr< BridgeNetDevice > NetDeviceIsBridged(Ptr< NetDevice > nd) const
Decide whether or not a given net device is being bridged by a BridgeNetDevice.
void ClearBridgesVisited(void) const
Clear the list of bridges visited on the link.
uint32_t GetNInjectedRoutes(void)
Get the number of injected routes that have been added to the routing table.
ListOfLSAs_t m_LSAs
database of GlobalRoutingLSAs
Ptr< Ipv4GlobalRouting > GetRoutingProtocol(void)
Get the specific Global Routing Protocol used.
void ProcessBridgedBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
Process a bridged broadcast link.
GlobalRouter()
Create a Global Router class.
void ClearLSAs(void)
Clear list of LSAs.
Ipv4RoutingTableEntry * GetInjectedRoute(uint32_t i)
Return the injected route indexed by i.
std::list< Ipv4RoutingTableEntry * >::iterator InjectedRoutesI
Iterator to container of Ipv4RoutingTableEntry.
uint32_t GetNumLSAs(void) const
Get the Number of Global Routing Link State Advertisements that this router can export.
Ipv4Address m_routerId
router ID (its IPv4 address)
void RemoveInjectedRoute(uint32_t i)
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.
bool AnotherRouterOnLink(Ptr< NetDevice > nd) const
Checks for the presence of another router on the NetDevice.
std::list< Ipv4RoutingTableEntry * >::const_iterator InjectedRoutesCI
Const Iterator to container of Ipv4RoutingTableEntry.
void SetRoutingProtocol(Ptr< Ipv4GlobalRouting > routing)
Set the specific Global Routing Protocol to be used.
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.
std::vector< Ptr< BridgeNetDevice > > m_bridgesVisited
Container of bridges visited.
void ProcessPointToPointLink(Ptr< NetDevice > ndLocal, GlobalRoutingLSA *pLSA)
Process a point to point link.
Ipv4Address GetRouterId(void) const
Get the Router ID associated with this Global Router.
void ProcessBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c)
Process a generic broadcast link.
void BuildNetworkLSAs(NetDeviceContainer c)
Build one NetworkLSA for each net device talking to a network that we are the designated router for.
a Link State Advertisement (LSA) for a router, used in global routing.
void SetStatus(SPFStatus status)
Set the SPF status of the advertisement.
void Print(std::ostream &os) const
Print the contents of the Global Routing Link State Advertisement and any Global Routing Link Records...
SPFStatus
Enumeration of the possible values of the status flag in the Routing Link State Advertisements.
@ LSA_SPF_NOT_EXPLORED
New vertex not yet considered.
SPFStatus GetStatus(void) const
Get the SPF status of the advertisement.
uint32_t GetNLinkRecords(void) const
Return the number of Global Routing Link Records in the LSA.
uint32_t AddLinkRecord(GlobalRoutingLinkRecord *lr)
Add a given Global Routing Link Record to the LSA.
uint32_t GetNAttachedRouters(void) const
Return the number of attached routers listed in the NetworkLSA.
LSType
corresponds to LS type field of RFC 2328 OSPF LSA header
Ipv4Address m_linkStateId
The Link State ID is defined by the OSPF spec.
LSType GetLSType(void) const
Return the LSType field of the LSA.
Ipv4Address GetAdvertisingRouter(void) const
Get the Advertising Router as defined by the OSPF spec.
Ptr< Node > GetNode(void) const
Get the Node pointer of the node that originated this LSA.
GlobalRoutingLSA()
Create a blank Global Routing Link State Advertisement.
ListOfLinkRecords_t m_linkRecords
Each Link State Advertisement contains a number of Link Records that describe the kinds of links that...
Ipv4Address GetAttachedRouter(uint32_t n) const
Return an Ipv4Address corresponding to the specified attached router.
void SetNode(Ptr< Node > node)
Set the Node pointer of the node that originated this LSA.
uint32_t AddAttachedRouter(Ipv4Address addr)
Add an attached router to the list in the NetworkLSA.
~GlobalRoutingLSA()
Destroy an existing Global Routing Link State Advertisement.
Ipv4Address m_advertisingRtr
The Advertising Router is defined by the OSPF spec.
void SetLSType(LSType typ)
Set the LS type field of the LSA.
void SetAdvertisingRouter(Ipv4Address rtr)
Set the Advertising Router as defined by the OSPF spec.
SPFStatus m_status
This is a tristate flag used internally in the SPF computation to mark if an SPFVertex (a data struct...
LSType m_lsType
The type of the LSA.
ListOfAttachedRouters_t m_attachedRouters
Each Network LSA contains a list of attached routers.
void ClearLinkRecords(void)
Release all of the Global Routing Link Records present in the Global Routing Link State Advertisement...
Ipv4Mask GetNetworkLSANetworkMask(void) const
For a Network LSA, get the Network Mask field that precedes the list of attached routers.
GlobalRoutingLinkRecord * GetLinkRecord(uint32_t n) const
Return a pointer to the specified Global Routing Link Record.
void SetNetworkLSANetworkMask(Ipv4Mask mask)
For a Network LSA, set the Network Mask field that precedes the list of attached routers.
Ipv4Mask m_networkLSANetworkMask
Each Network LSA contains the network mask of the attached network.
bool IsEmpty(void) const
Check to see if the list of Global Routing Link Records present in the Global Routing Link State Adve...
void CopyLinkRecords(const GlobalRoutingLSA &lsa)
Copy any Global Routing Link Records in a given Global Routing Link State Advertisement to the curren...
Ipv4Address GetLinkStateId(void) const
Get the Link State ID as defined by the OSPF spec.
void SetLinkStateId(Ipv4Address addr)
Set the Link State ID is defined by the OSPF spec.
GlobalRoutingLSA & operator=(const GlobalRoutingLSA &lsa)
Assignment operator for a Global Routing Link State Advertisement.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
void Set(uint32_t address)
input address is in host order.
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:77
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:256
uint16_t GetPrefixLength(void) const
uint32_t Get(void) const
Get the host-order 32-bit IP mask.
A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting.
static Ipv4RoutingTableEntry CreateNetworkRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
holds a vector of ns3::NetDevice pointers
uint32_t GetN(void) const
Get the number of Ptr<NetDevice> stored in this container.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
virtual bool IsBroadcast(void) const =0
virtual bool IsPointToPoint(void) const =0
Return true if the net device is on a point-to-point link.
virtual bool IsBridge(void) const =0
Return true if the net device is acting as a bridge.
virtual Ptr< Node > GetNode(void) const =0
virtual Ptr< Channel > GetChannel(void) const =0
uint32_t GetId(void) const
Definition: node.cc:109
uint32_t GetNDevices(void) const
Definition: node.cc:152
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
static Ptr< Node > GetNode(uint32_t n)
Definition: node-list.cc:241
A base class which provides memory management and object aggregation.
Definition: object.h:88
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139