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