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 "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#include "ns3/object-base.h"
24
25#include <vector>
26
27namespace ns3
28{
29
30NS_LOG_COMPONENT_DEFINE("GlobalRouter");
31
32// ---------------------------------------------------------------------------
33//
34// GlobalRoutingLinkRecord Implementation
35//
36// ---------------------------------------------------------------------------
37
38template <typename T>
48
49template <typename T>
51 IpAddress linkId,
52 IpAddress linkData,
53 uint16_t metric)
54 : m_linkId(linkId),
55 m_linkData(linkData),
56 m_linkLocData(IpAddress::GetZero()),
57 m_linkType(linkType),
58 m_metric(metric)
59{
60 NS_LOG_FUNCTION(this << linkType << linkId << linkData << metric);
61}
62
63template <typename T>
65 IpAddress linkId,
66 IpAddress linkData,
67 IpAddress linkLocData,
68 uint16_t metric)
69 : m_linkId(linkId),
70 m_linkData(linkData),
71 m_linkLocData(linkLocData),
72 m_linkType(linkType),
73 m_metric(metric)
74{
76}
77
78template <typename T>
83
84template <typename T>
91
92template <typename T>
93void
99
100template <typename T>
108template <typename T>
109void
115
116template <typename T>
123
124template <typename T>
125void
131
132template <typename T>
133uint16_t
135{
136 NS_LOG_FUNCTION(this);
137 return m_metric;
138}
139
140template <typename T>
141void
143{
144 NS_LOG_FUNCTION(this << metric);
145 m_metric = metric;
146}
147
148template <typename T>
149void
151{
152 NS_LOG_FUNCTION(this << linkLocData);
153 m_linkLocData = linkLocData;
154}
155
156template <typename T>
159{
160 NS_LOG_FUNCTION(this);
162}
163
164// ---------------------------------------------------------------------------
165//
166// GlobalRoutingLSA Implementation
167//
168// ---------------------------------------------------------------------------
169
170template <typename T>
173 m_linkStateId(IpAddress::GetZero()),
174 m_advertisingRtr(IpAddress::GetZero()),
175 m_linkRecords(),
176 m_networkLSANetworkMask(IpMaskOrPrefix::GetZero()),
177 m_attachedRouters(),
178 m_status(GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED),
179 m_node_id(0)
180{
181 NS_LOG_FUNCTION(this);
182}
183
184template <typename T>
186 IpAddress linkStateId,
187 IpAddress advertisingRtr)
188 : m_lsType(GlobalRoutingLSA::Unknown),
189 m_linkStateId(linkStateId),
190 m_advertisingRtr(advertisingRtr),
191 m_linkRecords(),
192 m_networkLSANetworkMask(IpMaskOrPrefix::GetZero()),
193 m_attachedRouters(),
194 m_status(status),
195 m_node_id(0)
196{
197 NS_LOG_FUNCTION(this << status << linkStateId << advertisingRtr);
198}
199
200template <typename T>
202 : m_lsType(lsa.m_lsType),
206 m_status(lsa.m_status),
208{
209 NS_LOG_FUNCTION(this << &lsa);
210 NS_ASSERT_MSG(IsEmpty(), "GlobalRoutingLSA::GlobalRoutingLSA (): Non-empty LSA in constructor");
212}
213
214template <typename T>
217{
218 NS_LOG_FUNCTION(this << &lsa);
219 m_lsType = lsa.m_lsType;
222 m_networkLSANetworkMask = lsa.m_networkLSANetworkMask, m_status = lsa.m_status;
223 m_node_id = lsa.m_node_id;
224
225 ClearLinkRecords();
226 CopyLinkRecords(lsa);
227 return *this;
228}
229
230template <typename T>
231void
233{
234 NS_LOG_FUNCTION(this << &lsa);
235 for (auto i = lsa.m_linkRecords.begin(); i != lsa.m_linkRecords.end(); i++)
236 {
238 auto pDst = new GlobalRoutingLinkRecord<T>;
239
240 pDst->SetLinkType(pSrc->GetLinkType());
241 pDst->SetLinkId(pSrc->GetLinkId());
242 pDst->SetLinkData(pSrc->GetLinkData());
243 pDst->SetLinkLocData(pSrc->GetLinkLocData());
244 pDst->SetMetric(pSrc->GetMetric());
245
246 m_linkRecords.push_back(pDst);
247 pDst = nullptr;
249
250 m_attachedRouters = lsa.m_attachedRouters;
251}
252
253template <typename T>
259
260template <typename T>
261void
263{
264 NS_LOG_FUNCTION(this);
265 for (auto i = m_linkRecords.begin(); i != m_linkRecords.end(); i++)
266 {
267 NS_LOG_LOGIC("Free link record");
268
270 delete p;
271 p = nullptr;
273 *i = nullptr;
274 }
275 NS_LOG_LOGIC("Clear list");
276 m_linkRecords.clear();
277}
278
279template <typename T>
282{
283 NS_LOG_FUNCTION(this << lr);
284 m_linkRecords.push_back(lr);
285 return m_linkRecords.size();
286}
287
288template <typename T>
291{
292 NS_LOG_FUNCTION(this);
293 return m_linkRecords.size();
294}
295
296template <typename T>
299{
300 NS_LOG_FUNCTION(this << n);
301 uint32_t j = 0;
302 for (auto i = m_linkRecords.begin(); i != m_linkRecords.end(); i++, j++)
303 {
304 if (j == n)
305 {
306 return *i;
307 }
308 }
309 NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetLinkRecord (): invalid index");
310 return nullptr;
311}
312
313template <typename T>
314bool
316{
317 NS_LOG_FUNCTION(this);
318 return m_linkRecords.empty();
319}
320
321template <typename T>
324{
325 NS_LOG_FUNCTION(this);
326 return m_lsType;
327}
328
329template <typename T>
330void
336
337template <typename T>
344
345template <typename T>
346void
348{
349 NS_LOG_FUNCTION(this << addr);
350 m_linkStateId = addr;
351}
352
353template <typename T>
360
361template <typename T>
362void
368
369template <typename T>
370void
376
377template <typename T>
384
385template <typename T>
388{
389 NS_LOG_FUNCTION(this);
390 return m_status;
391}
392
393template <typename T>
396{
397 NS_LOG_FUNCTION(this << addr);
398 m_attachedRouters.push_back(addr);
399 return m_attachedRouters.size();
400}
401
402template <typename T>
405{
406 NS_LOG_FUNCTION(this);
407 return m_attachedRouters.size();
408}
409
410template <typename T>
413{
414 NS_LOG_FUNCTION(this << n);
415 uint32_t j = 0;
416 for (auto i = m_attachedRouters.begin(); i != m_attachedRouters.end(); i++, j++)
417 {
418 if (j == n)
419 {
420 return *i;
421 }
422 }
423 NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetAttachedRouter (): invalid index");
424 return IpAddress::GetZero();
425}
426
427template <typename T>
428void
430{
431 NS_LOG_FUNCTION(this << status);
432 m_status = status;
433}
434
435template <typename T>
442
443template <typename T>
444void
446{
447 NS_LOG_FUNCTION(this << node);
448 m_node_id = node->GetId();
449}
450
451template <typename T>
452void
453GlobalRoutingLSA<T>::Print(std::ostream& os) const
454{
455 NS_LOG_FUNCTION(this << &os);
456 os << std::endl;
457 os << "========== Global Routing LSA ==========" << std::endl;
458 os << "m_lsType = " << m_lsType;
460 {
461 os << " (GlobalRoutingLSA::RouterLSA)";
462 }
463 else if (m_lsType == GlobalRoutingLSA::NetworkLSA)
464 {
465 os << " (GlobalRoutingLSA::NetworkLSA)";
466 }
467 else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
469 os << " (GlobalRoutingLSA::ASExternalLSA)";
470 }
471 else
472 {
473 os << "(Unknown LSType)";
474 }
475 os << std::endl;
477 os << "m_linkStateId = " << m_linkStateId << " (Router ID)" << std::endl;
478 os << "m_advertisingRtr = " << m_advertisingRtr << " (Router ID)" << std::endl;
479
481 {
482 for (auto i = m_linkRecords.begin(); i != m_linkRecords.end(); i++)
483 {
485
486 os << "---------- RouterLSA Link Record ----------" << std::endl;
487 os << "m_linkType = " << p->m_linkType;
489 {
490 os << " (GlobalRoutingLinkRecord::PointToPoint)" << std::endl;
491 os << "m_linkId = " << p->m_linkId << std::endl;
492 os << "m_linkData = " << p->m_linkData << std::endl;
493 os << "m_metric = " << p->m_metric << std::endl;
494 }
496 {
497 os << " (GlobalRoutingLinkRecord::TransitNetwork)" << std::endl;
498 os << "m_linkId = " << p->m_linkId << " (Designated router for network)"
499 << std::endl;
500 os << "m_linkData = " << p->m_linkData << " (This router's IP address)"
501 << std::endl;
502 os << "m_metric = " << p->m_metric << std::endl;
505 {
506 os << " (GlobalRoutingLinkRecord::StubNetwork)" << std::endl;
507 os << "m_linkId = " << p->m_linkId << " (Network number of attached network)"
508 << std::endl;
509 os << "m_linkData = " << p->m_linkData << " (Network mask of attached network)"
510 << std::endl;
511 os << "m_metric = " << p->m_metric << std::endl;
512 }
513 else
514 {
515 os << " (Unknown LinkType)" << std::endl;
516 os << "m_linkId = " << p->m_linkId << std::endl;
517 os << "m_linkData = " << p->m_linkData << std::endl;
518 os << "m_metric = " << p->m_metric << std::endl;
519 }
520 os << "---------- End RouterLSA Link Record ----------" << std::endl;
521 }
522 }
523 else if (m_lsType == GlobalRoutingLSA::NetworkLSA)
524 {
525 os << "---------- NetworkLSA Link Record ----------" << std::endl;
526 os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
527 for (auto i = m_attachedRouters.begin(); i != m_attachedRouters.end(); i++)
528 {
529 os << "attachedRouter = " << *i << std::endl;
530 }
531 os << "---------- End NetworkLSA Link Record ----------" << std::endl;
532 }
533 else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
534 {
535 os << "---------- ASExternalLSA Link Record --------" << std::endl;
536 os << "m_linkStateId = " << m_linkStateId << std::endl;
537 os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
538 }
539 else
540 {
541 NS_ASSERT_MSG(0, "Illegal LSA LSType: " << m_lsType);
542 }
543 os << "========== End Global Routing LSA ==========" << std::endl;
544}
545
546template <typename T>
547std::ostream&
548operator<<(std::ostream& os, GlobalRoutingLSA<T>& lsa)
549{
550 lsa.Print(os);
551 return os;
552}
553
554// ---------------------------------------------------------------------------
555//
556// GlobalRouter Implementation
557//
558// ---------------------------------------------------------------------------
559
560template <typename T>
561TypeId
563{
564 std::string name;
565 if constexpr (IsIpv4)
566 {
567 name = "Ipv4";
568 }
569 else
571 name = "Ipv6";
572 }
573 static TypeId tid = TypeId("ns3::" + name + "GlobalRouter")
574 .SetParent<Object>()
575 .SetGroupName("GlobalRouter")
576 .template AddConstructor<GlobalRouter<T>>();
577 return tid;
578}
579
580template <typename T>
582 : m_LSAs()
583{
584 NS_LOG_FUNCTION(this);
585 if constexpr (IsIpv4)
586 {
588 }
589 else
590 {
591 // looks ugly but gets the job done .
592 // Alternatively, convert uint32_t to a uint8_t buf[16] and then use Ipv6Address(buf)
595 }
596}
597
598template <typename T>
601 NS_LOG_FUNCTION(this);
602 ClearLSAs();
603}
604
605template <typename T>
606void
613template <typename T>
620
621template <typename T>
622void
624{
625 NS_LOG_FUNCTION(this);
626 m_routingProtocol = nullptr;
627 for (auto k = m_injectedRoutes.begin(); k != m_injectedRoutes.end();
628 k = m_injectedRoutes.erase(k))
629 {
630 delete (*k);
631 }
633}
634
635template <typename T>
636void
638{
639 NS_LOG_FUNCTION(this);
640 for (auto i = m_LSAs.begin(); i != m_LSAs.end(); i++)
641 {
642 NS_LOG_LOGIC("Free LSA");
643
644 GlobalRoutingLSA<T>* p = *i;
645 delete p;
646 p = nullptr;
647
648 *i = nullptr;
649 }
650 NS_LOG_LOGIC("Clear list of LSAs");
651 m_LSAs.clear();
652}
653
654template <typename T>
657{
658 NS_LOG_FUNCTION(this);
659 return m_routerId;
660}
661
662//
663// DiscoverLSAs is called on all nodes in the system that have a GlobalRouter
664// interface aggregated. We need to go out and discover any adjacent routers
665// and build the Link State Advertisements that reflect them and their associated
666// networks.
667//
668template <typename T>
671{
672 NS_LOG_FUNCTION(this);
673 Ptr<Node> node = GetObject<Node>();
675 "GlobalRouter::DiscoverLSAs (): GetObject for <Node> interface failed");
676 NS_LOG_LOGIC("For node " << node->GetId());
677
678 ClearLSAs();
679
680 //
681 // While building the Router-LSA, keep a list of those NetDevices for
682 // which the current node is the designated router and we will later build
683 // a NetworkLSA for.
684 //
686
687 //
688 // We're aggregated to a node. We need to ask the node for a pointer to its
689 // Ipv4 interface. This is where the information regarding the attached
690 // interfaces lives. If we're a router, we had better have an Ipv4 interface.
691 //
692 Ptr<Ip> ipLocal = node->GetObject<Ip>();
693 NS_ABORT_MSG_UNLESS(ipLocal,
694 "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed");
695
696 //
697 // Every router node originates a Router-LSA
698 //
699 auto pLSA = new GlobalRoutingLSA<T>;
701 pLSA->SetLinkStateId(m_routerId);
702 pLSA->SetAdvertisingRouter(m_routerId);
704 pLSA->SetNode(node);
705
706 //
707 // Ask the node for the number of net devices attached. This isn't necessarily
708 // equal to the number of links to adjacent nodes (other routers) as the number
709 // of devices may include those for stub networks (e.g., ethernets, etc.) and
710 // bridge devices also take up an "extra" net device.
711 //
712 uint32_t numDevices = node->GetNDevices();
713
714 //
715 // Iterate through the devices on the node and walk the channel to see what's
716 // on the other side of the standalone devices..
717 //
718 for (uint32_t i = 0; i < numDevices; ++i)
719 {
720 Ptr<NetDevice> ndLocal = node->GetDevice(i);
721
723 {
724 continue;
725 }
726
727 //
728 // There is an assumption that bridge ports must never have an IP address
729 // associated with them. This turns out to be a very convenient place to
730 // check and make sure that this is the case.
731 //
732 if (NetDeviceIsBridged(ndLocal))
733 {
734 int32_t ifIndex = ipLocal->GetInterfaceForDevice(ndLocal);
736 ifIndex != -1,
737 "GlobalRouter::DiscoverLSAs(): Bridge ports must not have an IPv4 interface index");
738 }
739
740 //
741 // Check to see if the net device we just got has a corresponding IP
742 // interface (could be a pure L2 NetDevice) -- for example a net device
743 // associated with a bridge. We are only going to involve devices with
744 // IP addresses in routing.
745 //
746 int32_t interfaceNumber = ipLocal->GetInterfaceForDevice(ndLocal);
747 if (interfaceNumber == -1 ||
748 !(ipLocal->IsUp(interfaceNumber) && ipLocal->IsForwarding(interfaceNumber)))
749 {
750 NS_LOG_LOGIC("Net device "
751 << ndLocal
752 << "has no IP interface or is not enabled for forwarding, skipping");
753 continue;
754 }
755
756 //
757 // We have a net device that we need to check out. If it supports
758 // broadcast and is not a point-point link, then it will be either a stub
759 // network or a transit network depending on the number of routers on
760 // the segment. We add the appropriate link record to the LSA.
761 //
762 // If the device is a point to point link, we treat it separately. In
763 // that case, there may be zero, one, or two link records added.
764 //
765
766 if (ndLocal->IsBroadcast() && !ndLocal->IsPointToPoint())
767 {
768 NS_LOG_LOGIC("Broadcast link");
769 ProcessBroadcastLink(ndLocal, pLSA, c);
770 }
771 else if (ndLocal->IsPointToPoint())
772 {
773 NS_LOG_LOGIC("Point=to-point link");
774 ProcessPointToPointLink(ndLocal, pLSA);
775 }
776 else
777 {
778 NS_ASSERT_MSG(0, "GlobalRouter::DiscoverLSAs (): unknown link type");
779 }
780 }
781
782 NS_LOG_LOGIC("========== LSA for node " << node->GetId() << " ==========");
783 NS_LOG_LOGIC(*pLSA);
784 m_LSAs.push_back(pLSA);
785 pLSA = nullptr;
786
787 //
788 // Now, determine whether we need to build a NetworkLSA. This is the case if
789 // we found at least one designated router.
790 //
791 uint32_t nDesignatedRouters = c.GetN();
792 if (nDesignatedRouters > 0)
793 {
794 NS_LOG_LOGIC("Build Network LSAs");
796 }
797
798 //
799 // Build injected route LSAs as external routes
800 // RFC 2328, section 12.4.4
801 //
802 for (auto i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
803 {
804 auto pLSA = new GlobalRoutingLSA<T>;
806 pLSA->SetLinkStateId((*i)->GetDestNetwork());
807 pLSA->SetAdvertisingRouter(m_routerId);
808 if constexpr (IsIpv4)
809 {
810 pLSA->SetNetworkLSANetworkMask((*i)->GetDestNetworkMask());
811 }
812 else
813 {
814 pLSA->SetNetworkLSANetworkMask((*i)->GetDestNetworkPrefix());
815 }
817 m_LSAs.push_back(pLSA);
818 }
819 return m_LSAs.size();
820}
821
822template <typename T>
823void
827{
828 NS_LOG_FUNCTION(this << nd << pLSA << &c);
829
830 if (nd->IsBridge())
831 {
832 ProcessBridgedBroadcastLink(nd, pLSA, c);
833 }
834 else
835 {
836 ProcessSingleBroadcastLink(nd, pLSA, c);
837 }
838}
839
840template <typename T>
841void
845{
846 NS_LOG_FUNCTION(this << nd << pLSA << &c);
847
848 auto plr = new GlobalRoutingLinkRecord<T>;
849 NS_ABORT_MSG_IF(plr == nullptr,
850 "GlobalRouter::ProcessSingleBroadcastLink(): Can't alloc link record");
851
852 //
853 // We have some preliminaries to do to get enough information to proceed.
854 // This information we need comes from the internet stack, so notice that
855 // there is an implied assumption that global routing is only going to
856 // work with devices attached to the internet stack (have an ipv4 interface
857 // associated to them.
858 //
859 Ptr<Node> node = nd->GetNode();
860
861 Ptr<Ip> ipLocal = node->GetObject<Ip>();
863 ipLocal,
864 "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for <Ipv4> interface failed");
865
866 int32_t interfaceLocal = ipLocal->GetInterfaceForDevice(nd);
868 interfaceLocal == -1,
869 "GlobalRouter::ProcessSingleBroadcastLink(): No interface index associated with device");
870
871 if (ipLocal->GetNAddresses(interfaceLocal) > 1)
872 {
873 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
874 }
875 IpAddress addrLocal;
876 IpAddress addrLinkLocal; // this is the link local associated with the link for ipv6
877 if constexpr (IsIpv4)
878 {
879 addrLocal = ipLocal->GetAddress(interfaceLocal, 0).GetAddress();
880 }
881 else
882 {
883 addrLinkLocal = ipLocal->GetAddress(interfaceLocal, 0).GetAddress();
884 addrLocal = ipLocal->GetAddress(interfaceLocal, 1).GetAddress();
885 }
886
887 IpMaskOrPrefix maskLocal;
888 if constexpr (IsIpv4)
889 {
890 maskLocal = ipLocal->GetAddress(interfaceLocal, 0).GetMask();
891 }
892 else
893 {
894 maskLocal = ipLocal->GetAddress(interfaceLocal, 1).GetPrefix();
895 }
896 NS_LOG_LOGIC("Working with local address " << addrLocal);
897 uint16_t metricLocal = ipLocal->GetMetric(interfaceLocal);
898
899 //
900 // Check to see if the net device is connected to a channel/network that has
901 // another router on it. If there is no other router on the link (but us) then
902 // this is a stub network. If we find another router, then what we have here
903 // is a transit network.
904 //
906 if (!AnotherRouterOnLink(nd))
907 {
908 //
909 // This is a net device connected to a stub network
910 //
911 NS_LOG_LOGIC("Router-LSA Stub Network");
913
914 //
915 // According to OSPF, the Link ID is the IP network number of
916 // the attached network.
917 //
918 if constexpr (IsIpv4)
919 {
920 plr->SetLinkId(addrLocal.CombineMask(maskLocal));
921 }
922 else
923 {
924 plr->SetLinkId(addrLocal.CombinePrefix(maskLocal));
925 }
926
927 //
928 // and the Link Data is the network mask; converted to Ipv4Address
929 //
930 IpAddress maskLocalAddr;
931 if constexpr (IsIpv4)
932 {
933 maskLocalAddr.Set(maskLocal.Get());
934 }
935 else
936 {
937 uint8_t buf[16];
938 maskLocal.GetBytes(buf);
939 maskLocalAddr.Set(buf);
940 }
941 plr->SetLinkData(maskLocalAddr);
942 plr->SetMetric(metricLocal);
943 pLSA->AddLinkRecord(plr);
944 plr = nullptr;
945 }
946 else
947 {
948 //
949 // We have multiple routers on a broadcast interface, so this is
950 // a transit network.
951 //
952 NS_LOG_LOGIC("Router-LSA Transit Network");
954
955 //
956 // By definition, the router with the lowest IP address is the
957 // designated router for the network. OSPF says that the Link ID
958 // gets the IP interface address of the designated router in this
959 // case.
960 //
962 IpAddress designatedRtr;
963 designatedRtr = FindDesignatedRouterForLink(nd);
964
965 //
966 // Let's double-check that any designated router we find out on our
967 // network is really on our network.
968 //
969 bool isRtrAllOnes = false;
970 if constexpr (IsIpv4)
971 {
972 if (designatedRtr.IsBroadcast())
973 {
974 isRtrAllOnes = true;
975 }
976 }
977 else
978 {
979 if (designatedRtr == Ipv6Address::GetOnes())
980 {
981 isRtrAllOnes = true;
982 }
983 }
984
985 if (!isRtrAllOnes)
986 {
987 IpAddress networkHere;
988 IpAddress networkThere;
989 if constexpr (IsIpv4)
990 {
991 networkHere = addrLocal.CombineMask(maskLocal);
992 networkThere = designatedRtr.CombineMask(maskLocal);
993 }
994 else
995 {
996 networkHere = addrLocal.CombinePrefix(maskLocal);
997 networkThere = designatedRtr.CombinePrefix(maskLocal);
998 }
1000 networkHere == networkThere,
1001 "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion ("
1002 << addrLocal << "/" << maskLocal.GetPrefixLength() << ", " << designatedRtr
1003 << "/" << maskLocal.GetPrefixLength() << ")");
1004 }
1005 if (designatedRtr == addrLocal)
1006 {
1007 c.Add(nd);
1008 NS_LOG_LOGIC("Node " << node->GetId() << " elected a designated router");
1009 }
1010 plr->SetLinkId(designatedRtr);
1011
1012 //
1013 // OSPF says that the Link Data is this router's own IP address.
1014 //
1015 plr->SetLinkData(addrLocal);
1016 plr->SetLinkLocData(addrLinkLocal);
1017 plr->SetMetric(metricLocal);
1018 pLSA->AddLinkRecord(plr);
1019 plr = nullptr;
1020 }
1021}
1022
1023template <typename T>
1024void
1026 GlobalRoutingLSA<T>* pLSA,
1028{
1029 NS_LOG_FUNCTION(this << nd << pLSA << &c);
1030 NS_ASSERT_MSG(nd->IsBridge(),
1031 "GlobalRouter::ProcessBridgedBroadcastLink(): Called with non-bridge net device");
1032
1033#if 0
1034 //
1035 // It is possible to admit the possibility that a bridge device on a node
1036 // can also participate in routing. This would surprise people who don't
1037 // come from Microsoft-land where they do use such a construct. Based on
1038 // the principle of least-surprise, we will leave the relatively simple
1039 // code in place to do this, but not enable it until someone really wants
1040 // the capability. Even then, we will not enable this code as a default
1041 // but rather something you will have to go and turn on.
1042 //
1043
1044 Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> ();
1045 NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
1046
1047 //
1048 // We have some preliminaries to do to get enough information to proceed.
1049 // This information we need comes from the internet stack, so notice that
1050 // there is an implied assumption that global routing is only going to
1051 // work with devices attached to the internet stack (have an ipv4 interface
1052 // associated to them.
1053 //
1054 Ptr<Node> node = nd->GetNode ();
1055 Ptr<Ip> ipLocal = node->GetObject<Ip> ();
1056 NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for <Ipv4> interface failed");
1057
1058 int32_t interfaceLocal = ipLocal->GetInterfaceForDevice (nd);
1059 NS_ABORT_MSG_IF (interfaceLocal == -1, "GlobalRouter::ProcessBridgedBroadcastLink(): No interface index associated with device");
1060
1061 if (ipLocal->GetNAddresses (interfaceLocal) > 1)
1062 {
1063 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
1064 }
1065 IpAddress addrLocal;
1066 IpAddress addrLinkLocal; // this is the link local associated with the link for ipv6
1067 if constexpr (IsIpv4)
1068 {
1069 addrLocal = ipLocal->GetAddress(interfaceLocal, 0).GetAddress();
1070 }
1071 else
1072 {
1073 addrLinkLocal = ipLocal->GetAddress(interfaceLocal, 0).GetAddress();
1074 addrLocal = ipLocal->GetAddress(interfaceLocal, 1).GetAddress();
1075 }
1076
1077 IpMaskOrPrefix maskLocal;
1078 if constexpr (IsIpv4)
1079 {
1080 maskLocal = ipLocal->GetAddress(interfaceLocal, 0).GetMask();
1081 }
1082 else
1083 {
1084 maskLocal = ipLocal->GetAddress(interfaceLocal, 1).GetPrefix();
1085 }
1086 NS_LOG_LOGIC ("Working with local address " << addrLocal);
1087 uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
1088
1089 //
1090 // We need to handle a bridge on the router. This means that we have been
1091 // given a net device that is a BridgeNetDevice. It has an associated Ipv4
1092 // interface index and address. Some number of other net devices live "under"
1093 // the bridge device as so-called bridge ports. In a nutshell, what we have
1094 // to do is to repeat what is done for a single broadcast link on all of
1095 // those net devices living under the bridge (trolls?)
1096 //
1097
1098 bool areTransitNetwork = false;
1099 IpAddress designatedRtr;
1100
1101 for (uint32_t i = 0; i < bnd->GetNBridgePorts (); ++i)
1102 {
1103 Ptr<NetDevice> ndTemp = bnd->GetBridgePort (i);
1104
1105 //
1106 // We have to decide if we are a transit network. This is characterized
1107 // by the presence of another router on the network segment. If we find
1108 // another router on any of our bridged links, we are a transit network.
1109 //
1111 if (AnotherRouterOnLink (ndTemp))
1112 {
1113 areTransitNetwork = true;
1114
1115 //
1116 // If we're going to be a transit network, then we have got to elect
1117 // a designated router for the whole bridge. This means finding the
1118 // router with the lowest IP address on the whole bridge. We ask
1119 // for the lowest address on each segment and pick the lowest of them
1120 // all.
1121 //
1123 IpAddress designatedRtrTemp = FindDesignatedRouterForLink (ndTemp);
1124
1125 //
1126 // Let's double-check that any designated router we find out on our
1127 // network is really on our network.
1128 //
1129 bool isRtrAllOnes = false;
1130 if constexpr (IsIpv4)
1131 {
1132 if (designatedRtrTemp.IsBroadcast())
1133 {
1134 isRtrAllOnes = true;
1135 }
1136 }
1137 else
1138 {
1139 if (designatedRtrTemp == Ipv6Address::GetOnes())
1140 {
1141 isRtrAllOnes = true;
1142 }
1143 }
1144
1145 if (!isRtrAllOnes)
1146 {
1147 IpAddress networkHere;
1148 IpAddress networkThere;
1149 if constexpr (IsIpv4)
1150 {
1151 networkHere = addrLocal.CombineMask(maskLocal);
1152 networkThere = designatedRtrTemp.CombineMask(maskLocal);
1153 }
1154 else
1155 {
1156 networkHere = addrLocal.CombinePrefix(maskLocal);
1157 networkThere = designatedRtrTemp.CombinePrefix(maskLocal);
1158 }
1160 networkHere == networkThere,
1161 "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion ("
1162 << addrLocal << "/" << maskLocal.GetPrefixLength() << ", " << designatedRtr
1163 << "/" << maskLocal.GetPrefixLength() << ")");
1164 }
1165 if (designatedRtrTemp < designatedRtr)
1166 {
1167 designatedRtr = designatedRtrTemp;
1168 }
1169 }
1170 }
1171 //
1172 // That's all the information we need to put it all together, just like we did
1173 // in the case of a single broadcast link.
1174 //
1175
1177 NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessBridgedBroadcastLink(): Can't alloc link record");
1178
1179 if (areTransitNetwork == false)
1180 {
1181 //
1182 // This is a net device connected to a bridge of stub networks
1183 //
1184 NS_LOG_LOGIC ("Router-LSA Stub Network");
1186
1187 //
1188 // According to OSPF, the Link ID is the IP network number of
1189 // the attached network.
1190 //
1191 if constexpr (IsIpv4)
1192 {
1193 plr->SetLinkId(addrLocal.CombineMask(maskLocal));
1194 }
1195 else
1196 {
1197 plr->SetLinkId(addrLocal.CombinePrefix(maskLocal));
1198 }
1199 //
1200 // and the Link Data is the network mask; converted to Ipv4Address
1201 //
1202IpAddress maskLocalAddr;
1203 if constexpr (IsIpv4)
1204 {
1205 maskLocalAddr.Set(maskLocal.Get());
1206 }
1207 else
1208 {
1209 uint8_t buf[16];
1210 maskLocal.GetBytes(buf);
1211 maskLocalAddr.Set(buf);
1212 }
1213 plr->SetLinkData(maskLocalAddr);
1214 plr->SetMetric (metricLocal);
1215 pLSA->AddLinkRecord (plr);
1216 plr = 0;
1217 }
1218 else
1219 {
1220 //
1221 // We have multiple routers on a bridged broadcast interface, so this is
1222 // a transit network.
1223 //
1224 NS_LOG_LOGIC ("Router-LSA Transit Network");
1226
1227 //
1228 // By definition, the router with the lowest IP address is the
1229 // designated router for the network. OSPF says that the Link ID
1230 // gets the IP interface address of the designated router in this
1231 // case.
1232 //
1233 if (designatedRtr == addrLocal)
1234 {
1235 c.Add (nd);
1236 NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
1237 }
1238 plr->SetLinkId (designatedRtr);
1239
1240 //
1241 // OSPF says that the Link Data is this router's own IP address.
1242 //
1243 plr->SetLinkData (addrLocal);
1244 plr->SetLinkLocData (addrLinkLocal);
1245 plr->SetMetric (metricLocal);
1246 pLSA->AddLinkRecord (plr);
1247 plr = 0;
1248 }
1249#endif
1250}
1251
1252template <typename T>
1253void
1255{
1256 NS_LOG_FUNCTION(this << ndLocal << pLSA);
1257
1258 //
1259 // We have some preliminaries to do to get enough information to proceed.
1260 // This information we need comes from the internet stack, so notice that
1261 // there is an implied assumption that global routing is only going to
1262 // work with devices attached to the internet stack (have an ipv4 interface
1263 // associated to them.
1264 //
1265 Ptr<Node> nodeLocal = ndLocal->GetNode();
1266
1267 Ptr<Ip> ipLocal = nodeLocal->GetObject<Ip>();
1269 ipLocal,
1270 "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1271
1272 int32_t interfaceLocal = ipLocal->GetInterfaceForDevice(ndLocal);
1274 interfaceLocal == -1,
1275 "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device");
1276
1277 if ((ipLocal->GetNAddresses(interfaceLocal) == 0))
1278 {
1279 NS_LOG_LOGIC("Local interface " << interfaceLocal << " has no address");
1280 return;
1281 }
1282
1283 IpAddress addrLocal;
1284 IpAddress addrLinkLocal; // this is the link local associated with the link for ipv6
1285 if constexpr (IsIpv4)
1286 {
1287 if (ipLocal->GetNAddresses(interfaceLocal) > 1)
1288 {
1289 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
1290 }
1291 addrLocal = ipLocal->GetAddress(interfaceLocal, 0).GetAddress();
1292 }
1293 else
1294 {
1295 addrLinkLocal = ipLocal->GetAddress(interfaceLocal, 0).GetAddress();
1296 if (ipLocal->GetNAddresses(interfaceLocal) >
1297 1) // if there is a globalUnicast address for the interface
1298 {
1299 addrLocal = ipLocal->GetAddress(interfaceLocal, 1).GetAddress();
1300 }
1301 }
1302 IpMaskOrPrefix maskLocal;
1303 if constexpr (IsIpv4)
1304 {
1305 maskLocal = ipLocal->GetAddress(interfaceLocal, 0).GetMask();
1306 }
1307 else
1308 {
1309 if (ipLocal->GetNAddresses(interfaceLocal) >
1310 1) // if there is a globalUnicast address for the remote interface
1311 {
1312 maskLocal = ipLocal->GetAddress(interfaceLocal, 1).GetPrefix();
1313 }
1314 }
1315 NS_LOG_LOGIC("Working with local address " << addrLocal);
1316 uint16_t metricLocal = ipLocal->GetMetric(interfaceLocal);
1317
1318 //
1319 // Now, we're going to walk over to the remote net device on the other end of
1320 // the point-to-point channel we know we have. This is where our adjacent
1321 // router (to use OSPF lingo) is running.
1322 //
1323 Ptr<Channel> ch = ndLocal->GetChannel();
1324
1325 //
1326 // Get the net device on the other side of the point-to-point channel.
1327 //
1328 Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch);
1329
1330 //
1331 // The adjacent net device is aggregated to a node. We need to ask that net
1332 // device for its node, then ask that node for its Ipv4 interface. Note a
1333 // requirement that nodes on either side of a point-to-point link must have
1334 // internet stacks; and an assumption that point-to-point links are incompatible
1335 // with bridging.
1336 //
1337 Ptr<Node> nodeRemote = ndRemote->GetNode();
1338 Ptr<Ip> ipRemote = nodeRemote->GetObject<Ip>();
1340 ipRemote,
1341 "GlobalRouter::ProcessPointToPointLink(): GetObject for remote <Ipv4> failed");
1342
1343 //
1344 // Further note the requirement that nodes on either side of a point-to-point
1345 // link must participate in global routing and therefore have a GlobalRouter
1346 // interface aggregated.
1347 //
1348 Ptr<GlobalRouter> rtrRemote = nodeRemote->GetObject<GlobalRouter>();
1349 if (!rtrRemote)
1350 {
1351 // This case is possible if the remote does not participate in global routing
1352 return;
1353 }
1354 //
1355 // We're going to need the remote router ID, so we might as well get it now.
1356 //
1357 IpAddress rtrIdRemote = rtrRemote->GetRouterId();
1358 NS_LOG_LOGIC("Working with remote router " << rtrIdRemote);
1359
1360 //
1361 // Now, just like we did above, we need to get the IP interface index for the
1362 // net device on the other end of the point-to-point channel.
1363 //
1364 int32_t interfaceRemote = ipRemote->GetInterfaceForDevice(ndRemote);
1365 NS_ABORT_MSG_IF(interfaceRemote == -1,
1366 "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with "
1367 "remote device");
1368
1369 if ((ipRemote->GetNAddresses(interfaceRemote) == 0))
1370 {
1371 NS_LOG_LOGIC("Remote interface " << interfaceRemote << " has no address");
1372 }
1373 //
1374 // Now that we have the Ipv4 interface, we can get the (remote) address and
1375 // mask we need.
1376 //
1377
1378 IpAddress addrRemote;
1379 if constexpr (IsIpv4)
1380 {
1381 if (ipRemote->GetNAddresses(interfaceRemote) > 1)
1382 {
1383 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
1384 }
1385 addrRemote = ipRemote->GetAddress(interfaceRemote, 0).GetAddress();
1386 }
1387 else
1388 {
1389 if (ipRemote->GetNAddresses(interfaceRemote) >
1390 1) // if there is a globalUnicast address for the interface
1391 {
1392 addrRemote = ipRemote->GetAddress(interfaceRemote, 1).GetAddress();
1393 }
1394 }
1395 IpMaskOrPrefix maskRemote;
1396 if constexpr (IsIpv4)
1397 {
1398 maskRemote = ipRemote->GetAddress(interfaceRemote, 0).GetMask();
1399 }
1400 else
1401 {
1402 if (ipRemote->GetNAddresses(interfaceRemote) >
1403 1) // if there is a globalUnicast address for the remote interface
1404 {
1405 maskRemote = ipRemote->GetAddress(interfaceRemote, 1).GetPrefix();
1406 }
1407 }
1408 NS_LOG_LOGIC("Working with remote address " << addrRemote);
1409
1410 //
1411 // Now we can fill out the link records for this link. There are always two
1412 // link records; the first is a point-to-point record describing the link and
1413 // the second is a stub network record with the network number.
1414 //
1416
1417 if (ipRemote->IsUp(interfaceRemote))
1418 {
1419 NS_LOG_LOGIC("Remote side interface " << interfaceRemote << " is up-- add a type 1 link");
1420
1422 NS_ABORT_MSG_IF(plr == nullptr,
1423 "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1425 plr->SetLinkId(rtrIdRemote);
1426 plr->SetLinkData(addrLocal);
1427 plr->SetLinkLocData(addrLinkLocal);
1428 plr->SetMetric(metricLocal);
1429 pLSA->AddLinkRecord(plr);
1430 plr = nullptr;
1431 }
1432
1433 // Regardless of state of peer, add a type 3 link (RFC 2328: 12.4.1.1)
1434 // the only exception is if the remote interface has a link local address only, then it behaves
1435 // as a router and not a host
1436 if constexpr (!IsIpv4)
1437 {
1438 if (ipRemote->GetNAddresses(interfaceRemote) == 1 &&
1439 ipRemote->GetAddress(interfaceRemote, 0).GetAddress().IsLinkLocal())
1440 {
1441 NS_LOG_LOGIC("The remote interface only has a link local address, not adding a type 3 "
1442 "link record");
1443 return;
1444 }
1445 }
1446
1448 NS_ABORT_MSG_IF(plr == nullptr,
1449 "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1451 plr->SetLinkId(addrRemote);
1452 if constexpr (IsIpv4)
1453 {
1454 plr->SetLinkData(Ipv4Address(maskRemote.Get())); // Frown
1455 }
1456 else
1457 {
1458 uint8_t buf[16];
1459 maskRemote.GetBytes(buf);
1460 plr->SetLinkData(Ipv6Address(buf)); // Frown
1461 }
1462 plr->SetMetric(metricLocal);
1463 pLSA->AddLinkRecord(plr);
1464 plr = nullptr;
1465}
1466
1467template <typename T>
1468void
1470{
1471 NS_LOG_FUNCTION(this << &c);
1472
1473 uint32_t nDesignatedRouters = c.GetN();
1474 NS_LOG_DEBUG("Number of designated routers: " << nDesignatedRouters);
1475
1476 for (uint32_t i = 0; i < nDesignatedRouters; ++i)
1477 {
1478 //
1479 // Build one NetworkLSA for each net device talking to a network that we are the
1480 // designated router for. These devices are in the provided container.
1481 //
1482 Ptr<NetDevice> ndLocal = c.Get(i);
1483 Ptr<Node> node = ndLocal->GetNode();
1484
1485 Ptr<Ip> ipLocal = node->GetObject<Ip>();
1487 ipLocal,
1488 "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1489
1490 int32_t interfaceLocal = ipLocal->GetInterfaceForDevice(ndLocal);
1492 interfaceLocal == -1,
1493 "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device");
1494
1495 if (ipLocal->GetNAddresses(interfaceLocal) > 1)
1496 {
1497 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
1498 }
1499 IpAddress addrLocal;
1500 if constexpr (IsIpv4)
1501 {
1502 addrLocal = ipLocal->GetAddress(interfaceLocal, 0).GetAddress();
1503 }
1504 else
1505 {
1506 addrLocal = ipLocal->GetAddress(interfaceLocal, 1).GetAddress();
1507 }
1508 IpMaskOrPrefix maskLocal;
1509 if constexpr (IsIpv4)
1510 {
1511 maskLocal = ipLocal->GetAddress(interfaceLocal, 0).GetMask();
1512 }
1513 else
1514 {
1515 maskLocal = ipLocal->GetAddress(interfaceLocal, 1).GetPrefix();
1516 }
1517
1518 auto pLSA = new GlobalRoutingLSA<T>;
1519 NS_ABORT_MSG_IF(pLSA == nullptr,
1520 "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record");
1521
1522 pLSA->SetLSType(GlobalRoutingLSA<T>::NetworkLSA);
1523 pLSA->SetLinkStateId(addrLocal);
1524 pLSA->SetAdvertisingRouter(m_routerId);
1525 pLSA->SetNetworkLSANetworkMask(maskLocal);
1527 pLSA->SetNode(node);
1528
1529 //
1530 // Build a list of AttachedRouters by walking the devices in the channel
1531 // and, if we find a node with a GlobalRouter interface and an IPv4
1532 // interface associated with that device, we call it an attached router.
1533 //
1535 Ptr<Channel> ch = ndLocal->GetChannel();
1536 std::size_t nDevices = ch->GetNDevices();
1537 NS_ASSERT(nDevices);
1539 NS_LOG_LOGIC("Found " << deviceList.GetN() << " non-bridged devices on channel");
1540
1541 for (uint32_t i = 0; i < deviceList.GetN(); i++)
1542 {
1543 Ptr<NetDevice> tempNd = deviceList.Get(i);
1544 NS_ASSERT(tempNd);
1545 if (tempNd == ndLocal)
1546 {
1547 NS_LOG_LOGIC("Adding " << addrLocal << " to Network LSA");
1548 pLSA->AddAttachedRouter(addrLocal);
1549 continue;
1550 }
1551 Ptr<Node> tempNode = tempNd->GetNode();
1552
1553 // Does the node in question have a GlobalRouter interface? If not it can
1554 // hardly be considered an attached router.
1555 //
1556 Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter>();
1557 if (!rtr)
1558 {
1559 NS_LOG_LOGIC("Node " << tempNode->GetId()
1560 << " does not have GlobalRouter interface--skipping");
1561 continue;
1562 }
1563
1564 //
1565 // Does the attached node have an ipv4 interface for the device we're probing?
1566 // If not, it can't play router.
1567 //
1568 Ptr<Ip> tempIp = tempNode->GetObject<Ip>();
1569 int32_t tempInterface = tempIp->GetInterfaceForDevice(tempNd);
1570
1571 if (tempInterface != -1)
1572 {
1573 Ptr<Ip> tempIp = tempNode->GetObject<Ip>();
1574 NS_ASSERT(tempIp);
1575 if (!tempIp->IsUp(tempInterface))
1576 {
1577 NS_LOG_LOGIC("Remote side interface " << tempInterface << " not up");
1578 }
1579 else
1580 {
1581 if (tempIp->GetNAddresses(tempInterface) > 1)
1582 {
1583 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the "
1584 "primary one");
1585 }
1586 IpAddress tempAddr;
1587 if constexpr (IsIpv4)
1588 {
1589 tempAddr = tempIp->GetAddress(tempInterface, 0).GetAddress();
1590 }
1591 else
1592 {
1593 tempAddr = tempIp->GetAddress(tempInterface, 1).GetAddress();
1594 }
1595 NS_LOG_LOGIC("Adding " << tempAddr << " to Network LSA");
1596 pLSA->AddAttachedRouter(tempAddr);
1597 }
1598 }
1599 else
1600 {
1601 NS_LOG_LOGIC("Node " << tempNode->GetId() << " device " << tempNd
1602 << " does not have IPv4 interface; skipping");
1603 }
1604 }
1605 m_LSAs.push_back(pLSA);
1606 NS_LOG_LOGIC("========== LSA for node " << node->GetId() << " ==========");
1607 NS_LOG_LOGIC(*pLSA);
1608 pLSA = nullptr;
1609 }
1610}
1611
1612template <typename T>
1615{
1616 NS_LOG_FUNCTION(this << ch);
1618
1619 for (std::size_t i = 0; i < ch->GetNDevices(); i++)
1620 {
1621 Ptr<NetDevice> nd = ch->GetDevice(i);
1622 NS_LOG_LOGIC("checking to see if the device " << nd << " is bridged");
1624 if (bnd && !BridgeHasAlreadyBeenVisited(bnd))
1625 {
1626 NS_LOG_LOGIC("Device is bridged by BridgeNetDevice "
1627 << bnd << " with " << bnd->GetNBridgePorts() << " ports");
1629 // Find all channels bridged together, and recursively call
1630 // on all other channels
1631 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); j++)
1632 {
1633 Ptr<NetDevice> bridgedDevice = bnd->GetBridgePort(j);
1634 if (bridgedDevice->GetChannel() == ch)
1635 {
1636 NS_LOG_LOGIC("Skipping my own device/channel");
1637 continue;
1638 }
1639 NS_LOG_LOGIC("Calling on channel " << bridgedDevice->GetChannel());
1640 c.Add(FindAllNonBridgedDevicesOnLink(bridgedDevice->GetChannel()));
1641 }
1642 }
1643 else
1644 {
1645 NS_LOG_LOGIC("Device is not bridged; adding");
1646 c.Add(nd);
1647 }
1648 }
1649 NS_LOG_LOGIC("Found " << c.GetN() << " devices");
1650 return c;
1651}
1652
1653//
1654// Given a local net device, we need to walk the channel to which the net device is
1655// attached and look for nodes with GlobalRouter interfaces on them (one of them
1656// will be us). Of these, the router with the lowest IP address on the net device
1657// connecting to the channel becomes the designated router for the link.
1658//
1659template <typename T>
1662{
1663 NS_LOG_FUNCTION(this << ndLocal);
1664
1665 Ptr<Channel> ch = ndLocal->GetChannel();
1666 uint32_t nDevices = ch->GetNDevices();
1667 NS_ASSERT(nDevices);
1668
1669 NS_LOG_LOGIC("Looking for designated router off of net device " << ndLocal << " on node "
1670 << ndLocal->GetNode()->GetId());
1671
1672 IpAddress designatedRtr;
1673 if constexpr (IsIpv4)
1674 {
1675 designatedRtr = Ipv4Address::GetBroadcast();
1676 }
1677 else
1678 {
1679 designatedRtr = Ipv6Address::GetOnes();
1680 }
1681
1682 //
1683 // Look through all of the devices on the channel to which the net device
1684 // in question is attached.
1685 //
1686 for (uint32_t i = 0; i < nDevices; i++)
1687 {
1688 Ptr<NetDevice> ndOther = ch->GetDevice(i);
1689 NS_ASSERT(ndOther);
1690
1691 Ptr<Node> nodeOther = ndOther->GetNode();
1692
1693 NS_LOG_LOGIC("Examine channel device " << i << " on node " << nodeOther->GetId());
1694
1695 //
1696 // For all other net devices, we need to check and see if a router
1697 // is present. If the net device on the other side is a bridged
1698 // device, we need to consider all of the other devices on the
1699 // bridge as well (all of the bridge ports.
1700 //
1701 NS_LOG_LOGIC("checking to see if the device is bridged");
1703 if (bnd)
1704 {
1705 NS_LOG_LOGIC("Device is bridged by BridgeNetDevice " << bnd);
1706
1707 //
1708 // When enumerating a bridge, don't count the netdevice we came in on
1709 //
1710 if (ndLocal == ndOther)
1711 {
1712 NS_LOG_LOGIC("Skip -- it is where we came from.");
1713 continue;
1714 }
1715
1716 //
1717 // It is possible that the bridge net device is sitting under a
1718 // router, so we have to check for the presence of that router
1719 // before we run off and follow all the links
1720 //
1721 // We require a designated router to have a GlobalRouter interface and
1722 // an internet stack that includes the Ipv4 interface. If it doesn't
1723 // it can't play router.
1724 //
1725 NS_LOG_LOGIC("Checking for router on bridge net device " << bnd);
1726 Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter>();
1727 Ptr<Ip> ip = nodeOther->GetObject<Ip>();
1728 if (rtr && ip)
1729 {
1730 int32_t interfaceOther = ip->GetInterfaceForDevice(bnd);
1731 if (interfaceOther != -1)
1732 {
1733 NS_LOG_LOGIC("Found router on bridge net device " << bnd);
1734 if (!ip->IsUp(interfaceOther))
1735 {
1736 NS_LOG_LOGIC("Remote side interface " << interfaceOther << " not up");
1737 continue;
1738 }
1739 if (ip->GetNAddresses(interfaceOther) > 1)
1740 {
1741 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the "
1742 "primary one");
1743 }
1744 IpAddress addrOther;
1745 if constexpr (IsIpv4)
1746 {
1747 addrOther = ip->GetAddress(interfaceOther, 0).GetAddress();
1748 }
1749 else
1750 {
1751 addrOther = ip->GetAddress(interfaceOther, 1).GetAddress();
1752 }
1753 designatedRtr = addrOther < designatedRtr ? addrOther : designatedRtr;
1754 NS_LOG_LOGIC("designated router now " << designatedRtr);
1755 }
1756 }
1757
1758 //
1759 // Check if we have seen this bridge net device already while
1760 // recursively enumerating an L2 broadcast domain. If it is new
1761 // to us, go ahead and process it. If we have already processed it,
1762 // move to the next
1763 //
1765 {
1766 NS_ABORT_MSG("ERROR: L2 forwarding loop detected!");
1767 }
1768
1770
1771 NS_LOG_LOGIC("Looking through bridge ports of bridge net device " << bnd);
1772 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); ++j)
1773 {
1774 Ptr<NetDevice> ndBridged = bnd->GetBridgePort(j);
1775 NS_LOG_LOGIC("Examining bridge port " << j << " device " << ndBridged);
1776 if (ndBridged == ndOther)
1777 {
1778 NS_LOG_LOGIC("That bridge port is me, don't walk backward");
1779 continue;
1780 }
1781
1782 NS_LOG_LOGIC("Recursively looking for routers down bridge port " << ndBridged);
1783 IpAddress addrOther = FindDesignatedRouterForLink(ndBridged);
1784 designatedRtr = addrOther < designatedRtr ? addrOther : designatedRtr;
1785 NS_LOG_LOGIC("designated router now " << designatedRtr);
1786 }
1787 }
1788 else
1789 {
1790 NS_LOG_LOGIC("This device is not bridged");
1791 Ptr<Node> nodeOther = ndOther->GetNode();
1792 NS_ASSERT(nodeOther);
1793
1794 //
1795 // We require a designated router to have a GlobalRouter interface and
1796 // an internet stack that includes the Ipv4 interface. If it doesn't
1797 //
1798 Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter>();
1799 Ptr<Ip> ip = nodeOther->GetObject<Ip>();
1800 if (rtr && ip)
1801 {
1802 int32_t interfaceOther = ip->GetInterfaceForDevice(ndOther);
1803 if (interfaceOther != -1)
1804 {
1805 if (!ip->IsUp(interfaceOther))
1806 {
1807 NS_LOG_LOGIC("Remote side interface " << interfaceOther << " not up");
1808 continue;
1809 }
1810 NS_LOG_LOGIC("Found router on net device " << ndOther);
1811 if (ip->GetNAddresses(interfaceOther) > 1)
1812 {
1813 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the "
1814 "primary one");
1815 }
1816 IpAddress addrOther;
1817 if constexpr (IsIpv4)
1818 {
1819 addrOther = ip->GetAddress(interfaceOther, 0).GetAddress();
1820 }
1821 else
1822 {
1823 addrOther = ip->GetAddress(interfaceOther, 1).GetAddress();
1824 }
1825 designatedRtr = addrOther < designatedRtr ? addrOther : designatedRtr;
1826 NS_LOG_LOGIC("designated router now " << designatedRtr);
1827 }
1828 }
1829 }
1830 }
1831 return designatedRtr;
1832}
1833
1834//
1835// Given a node and an attached net device, take a look off in the channel to
1836// which the net device is attached and look for a node on the other side
1837// that has a GlobalRouter interface aggregated. Life gets more complicated
1838// when there is a bridged net device on the other side.
1839//
1840template <typename T>
1841bool
1843{
1844 NS_LOG_FUNCTION(this << nd);
1845
1846 Ptr<Channel> ch = nd->GetChannel();
1847 if (!ch)
1848 {
1849 // It may be that this net device is a stub device, without a channel
1850 return false;
1851 }
1852 uint32_t nDevices = ch->GetNDevices();
1853 NS_ASSERT(nDevices);
1854
1855 NS_LOG_LOGIC("Looking for routers off of net device " << nd << " on node "
1856 << nd->GetNode()->GetId());
1857
1858 //
1859 // Look through all of the devices on the channel to which the net device
1860 // in question is attached.
1861 //
1862 for (uint32_t i = 0; i < nDevices; i++)
1863 {
1864 Ptr<NetDevice> ndOther = ch->GetDevice(i);
1865 NS_ASSERT(ndOther);
1866
1867 NS_LOG_LOGIC("Examine channel device " << i << " on node " << ndOther->GetNode()->GetId());
1868
1869 //
1870 // Ignore the net device itself.
1871 //
1872 if (ndOther == nd)
1873 {
1874 NS_LOG_LOGIC("Myself, skip");
1875 continue;
1876 }
1877
1878 //
1879 // For all other net devices, we need to check and see if a router
1880 // is present. If the net device on the other side is a bridged
1881 // device, we need to consider all of the other devices on the
1882 // bridge.
1883 //
1884 NS_LOG_LOGIC("checking to see if device is bridged");
1886 if (bnd)
1887 {
1888 NS_LOG_LOGIC("Device is bridged by net device " << bnd);
1889
1890 //
1891 // Check if we have seen this bridge net device already while
1892 // recursively enumerating an L2 broadcast domain. If it is new
1893 // to us, go ahead and process it. If we have already processed it,
1894 // move to the next
1895 //
1897 {
1898 NS_ABORT_MSG("ERROR: L2 forwarding loop detected!");
1899 }
1900
1902
1903 NS_LOG_LOGIC("Looking through bridge ports of bridge net device " << bnd);
1904 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); ++j)
1905 {
1906 Ptr<NetDevice> ndBridged = bnd->GetBridgePort(j);
1907 NS_LOG_LOGIC("Examining bridge port " << j << " device " << ndBridged);
1908 if (ndBridged == ndOther)
1909 {
1910 NS_LOG_LOGIC("That bridge port is me, skip");
1911 continue;
1912 }
1913
1914 NS_LOG_LOGIC("Recursively looking for routers on bridge port " << ndBridged);
1915 if (AnotherRouterOnLink(ndBridged))
1916 {
1917 NS_LOG_LOGIC("Found routers on bridge port, return true");
1918 return true;
1919 }
1920 }
1921 NS_LOG_LOGIC("No routers on bridged net device, return false");
1922 return false;
1923 }
1924
1925 NS_LOG_LOGIC("This device is not bridged");
1926 Ptr<Node> nodeTemp = ndOther->GetNode();
1927 NS_ASSERT(nodeTemp);
1928
1929 Ptr<GlobalRouter> rtr = nodeTemp->GetObject<GlobalRouter>();
1930 if (rtr)
1931 {
1932 NS_LOG_LOGIC("Found GlobalRouter interface, return true");
1933 return true;
1934 }
1935 else
1936 {
1937 NS_LOG_LOGIC("No GlobalRouter interface on device, continue search");
1938 }
1939 }
1940 NS_LOG_LOGIC("No routers found, return false");
1941 return false;
1942}
1943
1944template <typename T>
1947{
1948 NS_LOG_FUNCTION(this);
1949 return m_LSAs.size();
1950}
1951
1952//
1953// Get the nth link state advertisement from this router.
1954//
1955template <typename T>
1956bool
1958{
1959 NS_LOG_FUNCTION(this << n << &lsa);
1960 NS_ASSERT_MSG(lsa.IsEmpty(), "GlobalRouter::GetLSA (): Must pass empty LSA");
1961 //
1962 // All of the work was done in GetNumLSAs. All we have to do here is to
1963 // walk the list of link state advertisements created there and return the
1964 // one the client is interested in.
1965 //
1966 auto i = m_LSAs.begin();
1967 uint32_t j = 0;
1968
1969 for (; i != m_LSAs.end(); i++, j++)
1970 {
1971 if (j == n)
1972 {
1973 GlobalRoutingLSA<T>* p = *i;
1974 lsa = *p;
1975 return true;
1976 }
1977 }
1978
1979 return false;
1980}
1981
1982template <typename T>
1983void
1985{
1986 NS_LOG_FUNCTION(this << network << networkMask);
1987 auto route = new IpRoutingTableEntry();
1988 //
1989 // Interface number does not matter here, using 1.
1990 //
1991 *route = IpRoutingTableEntry::CreateNetworkRouteTo(network, networkMask, 1);
1992 m_injectedRoutes.push_back(route);
1993}
1994
1995template <typename T>
1998{
1999 NS_LOG_FUNCTION(this << index);
2000 if (index < m_injectedRoutes.size())
2001 {
2002 uint32_t tmp = 0;
2003 for (auto i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
2004 {
2005 if (tmp == index)
2006 {
2007 return *i;
2008 }
2009 tmp++;
2010 }
2011 }
2012 NS_ASSERT(false);
2013 // quiet compiler.
2014 return nullptr;
2015}
2016
2017template <typename T>
2020{
2021 NS_LOG_FUNCTION(this);
2022 return m_injectedRoutes.size();
2023}
2024
2025template <typename T>
2026void
2028{
2029 NS_LOG_FUNCTION(this << index);
2030 NS_ASSERT(index < m_injectedRoutes.size());
2031 uint32_t tmp = 0;
2032 for (auto i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
2033 {
2034 if (tmp == index)
2035 {
2036 NS_LOG_LOGIC("Removing route " << index << "; size = " << m_injectedRoutes.size());
2037 delete *i;
2038 m_injectedRoutes.erase(i);
2039 return;
2040 }
2041 tmp++;
2042 }
2043}
2044
2045template <typename T>
2046bool
2048{
2049 NS_LOG_FUNCTION(this << network << networkMask);
2050 for (auto i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
2051 {
2052 if constexpr (IsIpv4)
2053 {
2054 if ((*i)->GetDestNetwork() == network && (*i)->GetDestNetworkMask() == networkMask)
2055 {
2056 NS_LOG_LOGIC("Withdrawing route to network/mask " << network << "/" << networkMask);
2057 delete *i;
2058 m_injectedRoutes.erase(i);
2059 return true;
2060 }
2061 }
2062 else
2063 {
2064 if ((*i)->GetDestNetwork() == network && (*i)->GetDestNetworkPrefix() == networkMask)
2065 {
2066 NS_LOG_LOGIC("Withdrawing route to network/mask " << network << "/" << networkMask);
2067 delete *i;
2068 m_injectedRoutes.erase(i);
2069 return true;
2070 }
2071 }
2072 }
2073 return false;
2074}
2075
2076//
2077// Link through the given channel and find the net device that's on the
2078// other end. This only makes sense with a point-to-point channel.
2079//
2080template <typename T>
2083{
2084 NS_LOG_FUNCTION(this << nd << ch);
2085 NS_ASSERT_MSG(ch->GetNDevices() == 2,
2086 "GlobalRouter::GetAdjacent (): Channel with other than two devices");
2087 //
2088 // This is a point to point channel with two endpoints. Get both of them.
2089 //
2090 Ptr<NetDevice> nd1 = ch->GetDevice(0);
2091 Ptr<NetDevice> nd2 = ch->GetDevice(1);
2092 //
2093 // One of the endpoints is going to be "us" -- that is the net device attached
2094 // to the node on which we're running -- i.e., "nd". The other endpoint (the
2095 // one to which we are connected via the channel) is the adjacent router.
2096 //
2097 if (nd1 == nd)
2098 {
2099 return nd2;
2100 }
2101 else if (nd2 == nd)
2102 {
2103 return nd1;
2104 }
2105 else
2106 {
2107 NS_ASSERT_MSG(false, "GlobalRouter::GetAdjacent (): Wrong or confused channel?");
2108 return nullptr;
2109 }
2110}
2111
2112//
2113// Decide whether or not a given net device is being bridged by a BridgeNetDevice.
2114//
2115template <typename T>
2118{
2119 NS_LOG_FUNCTION(this << nd);
2120
2121 Ptr<Node> node = nd->GetNode();
2122 uint32_t nDevices = node->GetNDevices();
2123
2124 //
2125 // There is no bit on a net device that says it is being bridged, so we have
2126 // to look for bridges on the node to which the device is attached. If we
2127 // find a bridge, we need to look through its bridge ports (the devices it
2128 // bridges) to see if we find the device in question.
2129 //
2130 for (uint32_t i = 0; i < nDevices; ++i)
2131 {
2132 Ptr<NetDevice> ndTest = node->GetDevice(i);
2133 NS_LOG_LOGIC("Examine device " << i << " " << ndTest);
2134
2135 if (ndTest->IsBridge())
2136 {
2137 NS_LOG_LOGIC("device " << i << " is a bridge net device");
2138 Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice>();
2140 bnd,
2141 "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
2142
2143 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); ++j)
2144 {
2145 NS_LOG_LOGIC("Examine bridge port " << j << " " << bnd->GetBridgePort(j));
2146 if (bnd->GetBridgePort(j) == nd)
2147 {
2148 NS_LOG_LOGIC("Net device " << nd << " is bridged by " << bnd);
2149 return bnd;
2150 }
2151 }
2152 }
2153 }
2154 NS_LOG_LOGIC("Net device " << nd << " is not bridged");
2155 return nullptr;
2156}
2157
2158//
2159// Start a new enumeration of an L2 broadcast domain by clearing m_bridgesVisited
2160//
2161template <typename T>
2162void
2167
2168//
2169// Check if we have already visited a given bridge net device by searching m_bridgesVisited
2170//
2171template <typename T>
2172bool
2174{
2175 for (auto iter = m_bridgesVisited.begin(); iter != m_bridgesVisited.end(); ++iter)
2176 {
2177 if (bridgeNetDevice == *iter)
2178 {
2179 NS_LOG_LOGIC("Bridge " << bridgeNetDevice << " has been visited.");
2180 return true;
2181 }
2182 }
2183 return false;
2184}
2185
2186//
2187// Remember that we visited a bridge net device by adding it to m_bridgesVisited
2188//
2189template <typename T>
2190void
2192{
2193 NS_LOG_FUNCTION(this << bridgeNetDevice);
2194 m_bridgesVisited.push_back(bridgeNetDevice);
2195}
2196
2197/**Explicit initialize the template classes */
2198/** @brief Stream insertion operator
2199 * @returns the reference to the output stream
2200 */
2201template std::ostream& operator<< <Ipv4Manager>(std::ostream&, GlobalRoutingLSA<Ipv4Manager>&);
2203template class GlobalRoutingLSA<Ipv4Manager>;
2204/** @brief Stream insertion operator
2205 * @returns the reference to the output stream
2206 */
2207template std::ostream& operator<< <Ipv6Manager>(std::ostream&, GlobalRoutingLSA<Ipv6Manager>&);
2209template class GlobalRoutingLSA<Ipv6Manager>;
2212
2213} // namespace ns3
a virtual net device that bridges multiple LAN segments
An interface aggregated to a node to provide global routing info.
uint32_t DiscoverLSAs()
Walk the connected channels, discover the adjacent routers and build the associated number of Global ...
Ptr< GlobalRouting< IpRoutingProtocol > > m_routingProtocol
the Ipv4GlobalRouting in use
ListOfLSAs_t m_LSAs
database of GlobalRoutingLSAs
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.
typename std::conditional_t< IsIpv4, Ipv4, Ipv6 > Ip
Alias for Ipv4 and Ipv6 classes.
IpRoutingTableEntry * GetInjectedRoute(uint32_t i)
Return the injected route indexed by i.
std::vector< Ptr< BridgeNetDevice > > m_bridgesVisited
Container of bridges visited.
static constexpr bool IsIpv4
Alias for determining whether the parent is Ipv4RoutingProtocol or Ipv6RoutingProtocol.
void ProcessSingleBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA< T > *pLSA, NetDeviceContainer &c)
Process a single broadcast link.
bool BridgeHasAlreadyBeenVisited(Ptr< BridgeNetDevice > device) const
When recursively checking for devices on the link, check whether a given device has already been visi...
bool WithdrawRoute(IpAddress network, IpMaskOrPrefix networkMask)
Withdraw a route from the global unicast routing table.
uint32_t GetNumLSAs() const
Get the Number of Global Routing Link State Advertisements that this router can export.
GlobalRouter()
Create a Global Router class.
void ProcessBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA< T > *pLSA, NetDeviceContainer &c)
Process a generic broadcast link.
bool AnotherRouterOnLink(Ptr< NetDevice > nd) const
Checks for the presence of another router on the NetDevice.
void ProcessBridgedBroadcastLink(Ptr< NetDevice > nd, GlobalRoutingLSA< T > *pLSA, NetDeviceContainer &c)
Process a bridged broadcast link.
uint32_t GetNInjectedRoutes()
Get the number of injected routes that have been added to the routing table.
InjectedRoutes m_injectedRoutes
Routes we are exporting.
Ptr< BridgeNetDevice > NetDeviceIsBridged(Ptr< NetDevice > nd) const
Decide whether or not a given net device is being bridged by a BridgeNetDevice.
void ClearBridgesVisited() const
Clear the list of bridges visited on the link.
NetDeviceContainer FindAllNonBridgedDevicesOnLink(Ptr< Channel > ch) const
Return a container of all non-bridged NetDevices on a link.
IpAddress FindDesignatedRouterForLink(Ptr< NetDevice > ndLocal) const
Finds a designated router.
bool GetLSA(uint32_t n, GlobalRoutingLSA< T > &lsa) const
Get a Global Routing Link State Advertisements that this router has said that it can export.
void BuildNetworkLSAs(NetDeviceContainer c)
Build one NetworkLSA for each net device talking to a network that we are the designated router for.
typename std::conditional_t< IsIpv4, Ipv4Mask, Ipv6Prefix > IpMaskOrPrefix
Alias for Ipv4Mask And Ipv6Prefix.
void ClearLSAs()
Clear list of LSAs.
void InjectRoute(IpAddress network, IpMaskOrPrefix networkMask)
Inject a route to be circulated to other routers as an external route.
static TypeId GetTypeId()
Get the type ID.
Ptr< GlobalRouting< IpRoutingProtocol > > GetRoutingProtocol()
Get the specific Global Routing Protocol used.
void SetRoutingProtocol(Ptr< GlobalRouting< IpRoutingProtocol > > routing)
Set the specific Global Routing Protocol to be used.
IpAddress GetRouterId() const
Get the Router ID associated with this Global Router.
void DoDispose() override
Destructor implementation.
typename std::conditional_t< IsIpv4, Ipv4RoutingTableEntry, Ipv6RoutingTableEntry > IpRoutingTableEntry
Alias for Ipv4RoutingTableEntry and Ipv6RoutingTableEntry classes.
typename std::conditional_t< IsIpv4, Ipv4Address, Ipv6Address > IpAddress
Alias for Ipv4Address and Ipv6Address classes.
void RemoveInjectedRoute(uint32_t i)
Withdraw a route from the global unicast routing table.
void MarkBridgeAsVisited(Ptr< BridgeNetDevice > device) const
When recursively checking for devices on the link, mark a given device as having been visited.
IpAddress m_routerId
router ID (its IPv4 address)
void ProcessPointToPointLink(Ptr< NetDevice > ndLocal, GlobalRoutingLSA< T > *pLSA)
Process a point to point link.
Global routing protocol for IPv4 stacks.
a Link State Advertisement (LSA) for a router, used in global routing.
GlobalRoutingLinkRecord< T > * GetLinkRecord(uint32_t n) const
Return a pointer to the specified Global Routing Link Record.
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.
IpAddress 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...
SPFStatus GetStatus() const
Get the SPF status of the advertisement.
typename std::conditional_t< IsIpv4, Ipv4Address, Ipv6Address > IpAddress
Alias for Ipv4Address and Ipv6Address classes.
LSType
corresponds to LS type field of RFC 2328 OSPF LSA header
void SetNetworkLSANetworkMask(IpMaskOrPrefix mask)
For a Network LSA, set the Network Mask field that precedes the list of attached routers.
void SetAdvertisingRouter(IpAddress rtr)
Set the Advertising Router as defined by the OSPF spec.
uint32_t GetNLinkRecords() const
Return the number of Global Routing Link Records in the LSA.
ListOfLinkRecords_t m_linkRecords
Each Link State Advertisement contains a number of Link Records that describe the kinds of links that...
uint32_t AddLinkRecord(GlobalRoutingLinkRecord< T > *lr)
Add a given Global Routing Link Record to the LSA.
IpAddress GetLinkStateId() const
Get the Link State ID as defined by the OSPF spec.
void SetLinkStateId(IpAddress addr)
Set the Link State ID is defined by the OSPF spec.
typename std::conditional_t< IsIpv4, Ipv4Mask, Ipv6Prefix > IpMaskOrPrefix
Alias for Ipv4Mask And Ipv6Prefix.
Ptr< Node > GetNode() const
Get the Node pointer of the node that originated this LSA.
void Print(std::ostream &os) const
Print the contents of the Global Routing Link State Advertisement and any Global Routing Link Records...
GlobalRoutingLSA & operator=(const GlobalRoutingLSA &lsa)
Assignment operator for a Global Routing Link State Advertisement.
IpMaskOrPrefix m_networkLSANetworkMask
Each Network LSA contains the network mask of the attached network.
LSType GetLSType() const
Return the LSType field of the LSA.
GlobalRoutingLSA()
Create a blank Global Routing Link State Advertisement.
IpAddress GetAdvertisingRouter() const
Get the Advertising Router as defined by the OSPF spec.
uint32_t GetNAttachedRouters() const
Return the number of attached routers listed in the NetworkLSA.
SPFStatus m_status
This is a tristate flag used internally in the SPF computation to mark if an SPFVertex (a data struct...
IpAddress m_linkStateId
The Link State ID is defined by the OSPF spec.
void SetStatus(SPFStatus status)
Set the SPF status of the advertisement.
ListOfAttachedRouters_t m_attachedRouters
Each Network LSA contains a list of attached routers.
bool IsEmpty() const
Check to see if the list of Global Routing Link Records present in the Global Routing Link State Adve...
~GlobalRoutingLSA()
Destroy an existing Global Routing Link State Advertisement.
void CopyLinkRecords(const GlobalRoutingLSA &lsa)
Copy any Global Routing Link Records in a given Global Routing Link State Advertisement to the curren...
void SetNode(Ptr< Node > node)
Set the Node pointer of the node that originated this LSA.
IpMaskOrPrefix GetNetworkLSANetworkMask() const
For a Network LSA, get the Network Mask field that precedes the list of attached routers.
IpAddress GetAttachedRouter(uint32_t n) const
Return an Ipv4Address corresponding to the specified attached router.
uint32_t AddAttachedRouter(IpAddress addr)
Add an attached router to the list in the NetworkLSA.
LSType m_lsType
The type of the LSA.
Ipv4 addresses are stored in host order in this class.
static Ipv4Address GetBroadcast()
Describes an IPv6 address.
static Ipv6Address GetOnes()
Get the "all-1" IPv6 address (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff).
static Ipv6Address MakeIpv4MappedAddress(Ipv4Address addr)
Make the Ipv4-mapped IPv6 address.
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:81
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:518
virtual void DoDispose()
Destructor implementation.
Definition object.cc:430
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
#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:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#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:253
#define NS_OBJECT_TEMPLATE_CLASS_DEFINE(type, param)
Explicitly instantiate a template class with one template parameter and register the resulting instan...
Definition object-base.h:67
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:605
template std::ostream & operator<<< Ipv4Manager >(std::ostream &, GlobalRoutingLSA< Ipv4Manager > &)
Explicit initialize the template classes.
template std::ostream & operator<<< Ipv6Manager >(std::ostream &, GlobalRoutingLSA< Ipv6Manager > &)
Stream insertion operator.
Empty struct used as a template parameter.
Empty struct used as a template parameter.