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