A Discrete-Event Network Simulator
API
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 "loopback-net-device.h"
24
25#include "ns3/abort.h"
26#include "ns3/assert.h"
27#include "ns3/bridge-net-device.h"
28#include "ns3/channel.h"
29#include "ns3/ipv4.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 (ListOfLinkRecords_t::const_iterator i = lsa.m_linkRecords.begin();
197 i != lsa.m_linkRecords.end();
198 i++)
199 {
200 GlobalRoutingLinkRecord* pSrc = *i;
202
203 pDst->SetLinkType(pSrc->GetLinkType());
204 pDst->SetLinkId(pSrc->GetLinkId());
205 pDst->SetLinkData(pSrc->GetLinkData());
206 pDst->SetMetric(pSrc->GetMetric());
207
208 m_linkRecords.push_back(pDst);
209 pDst = nullptr;
210 }
211
213}
214
216{
217 NS_LOG_FUNCTION(this);
219}
220
221void
223{
224 NS_LOG_FUNCTION(this);
225 for (ListOfLinkRecords_t::iterator i = m_linkRecords.begin(); i != m_linkRecords.end(); i++)
226 {
227 NS_LOG_LOGIC("Free link record");
228
230 delete p;
231 p = nullptr;
232
233 *i = nullptr;
234 }
235 NS_LOG_LOGIC("Clear list");
236 m_linkRecords.clear();
237}
238
241{
242 NS_LOG_FUNCTION(this << lr);
243 m_linkRecords.push_back(lr);
244 return m_linkRecords.size();
245}
246
249{
250 NS_LOG_FUNCTION(this);
251 return m_linkRecords.size();
252}
253
256{
257 NS_LOG_FUNCTION(this << n);
258 uint32_t j = 0;
259 for (ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin(); i != m_linkRecords.end();
260 i++, j++)
261 {
262 if (j == n)
263 {
264 return *i;
265 }
266 }
267 NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetLinkRecord (): invalid index");
268 return nullptr;
269}
270
271bool
273{
274 NS_LOG_FUNCTION(this);
275 return m_linkRecords.size() == 0;
276}
277
280{
281 NS_LOG_FUNCTION(this);
282 return m_lsType;
283}
284
285void
287{
288 NS_LOG_FUNCTION(this << typ);
289 m_lsType = typ;
290}
291
294{
295 NS_LOG_FUNCTION(this);
296 return m_linkStateId;
297}
298
299void
301{
302 NS_LOG_FUNCTION(this << addr);
303 m_linkStateId = addr;
304}
305
308{
309 NS_LOG_FUNCTION(this);
310 return m_advertisingRtr;
311}
312
313void
315{
316 NS_LOG_FUNCTION(this << addr);
317 m_advertisingRtr = addr;
318}
319
320void
322{
323 NS_LOG_FUNCTION(this << mask);
325}
326
329{
330 NS_LOG_FUNCTION(this);
332}
333
336{
337 NS_LOG_FUNCTION(this);
338 return m_status;
339}
340
343{
344 NS_LOG_FUNCTION(this << addr);
345 m_attachedRouters.push_back(addr);
346 return m_attachedRouters.size();
347}
348
351{
352 NS_LOG_FUNCTION(this);
353 return m_attachedRouters.size();
354}
355
358{
359 NS_LOG_FUNCTION(this << n);
360 uint32_t j = 0;
361 for (ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin();
362 i != m_attachedRouters.end();
363 i++, j++)
364 {
365 if (j == n)
366 {
367 return *i;
368 }
369 }
370 NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetAttachedRouter (): invalid index");
371 return Ipv4Address("0.0.0.0");
372}
373
374void
376{
377 NS_LOG_FUNCTION(this << status);
378 m_status = status;
379}
380
383{
384 NS_LOG_FUNCTION(this);
386}
387
388void
390{
391 NS_LOG_FUNCTION(this << node);
392 m_node_id = node->GetId();
393}
394
395void
396GlobalRoutingLSA::Print(std::ostream& os) const
397{
398 NS_LOG_FUNCTION(this << &os);
399 os << std::endl;
400 os << "========== Global Routing LSA ==========" << std::endl;
401 os << "m_lsType = " << m_lsType;
403 {
404 os << " (GlobalRoutingLSA::RouterLSA)";
405 }
407 {
408 os << " (GlobalRoutingLSA::NetworkLSA)";
409 }
411 {
412 os << " (GlobalRoutingLSA::ASExternalLSA)";
413 }
414 else
415 {
416 os << "(Unknown LSType)";
417 }
418 os << std::endl;
419
420 os << "m_linkStateId = " << m_linkStateId << " (Router ID)" << std::endl;
421 os << "m_advertisingRtr = " << m_advertisingRtr << " (Router ID)" << std::endl;
422
424 {
425 for (ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin();
426 i != m_linkRecords.end();
427 i++)
428 {
430
431 os << "---------- RouterLSA Link Record ----------" << std::endl;
432 os << "m_linkType = " << p->m_linkType;
434 {
435 os << " (GlobalRoutingLinkRecord::PointToPoint)" << std::endl;
436 os << "m_linkId = " << p->m_linkId << std::endl;
437 os << "m_linkData = " << p->m_linkData << std::endl;
438 os << "m_metric = " << p->m_metric << std::endl;
439 }
441 {
442 os << " (GlobalRoutingLinkRecord::TransitNetwork)" << std::endl;
443 os << "m_linkId = " << p->m_linkId << " (Designated router for network)"
444 << std::endl;
445 os << "m_linkData = " << p->m_linkData << " (This router's IP address)"
446 << std::endl;
447 os << "m_metric = " << p->m_metric << std::endl;
448 }
450 {
451 os << " (GlobalRoutingLinkRecord::StubNetwork)" << std::endl;
452 os << "m_linkId = " << p->m_linkId << " (Network number of attached network)"
453 << std::endl;
454 os << "m_linkData = " << p->m_linkData << " (Network mask of attached network)"
455 << std::endl;
456 os << "m_metric = " << p->m_metric << std::endl;
457 }
458 else
459 {
460 os << " (Unknown LinkType)" << std::endl;
461 os << "m_linkId = " << p->m_linkId << std::endl;
462 os << "m_linkData = " << p->m_linkData << std::endl;
463 os << "m_metric = " << p->m_metric << std::endl;
464 }
465 os << "---------- End RouterLSA Link Record ----------" << std::endl;
466 }
467 }
469 {
470 os << "---------- NetworkLSA Link Record ----------" << std::endl;
471 os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
472 for (ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin();
473 i != m_attachedRouters.end();
474 i++)
475 {
476 Ipv4Address p = *i;
477 os << "attachedRouter = " << p << std::endl;
478 }
479 os << "---------- End NetworkLSA Link Record ----------" << std::endl;
480 }
482 {
483 os << "---------- ASExternalLSA Link Record --------" << std::endl;
484 os << "m_linkStateId = " << m_linkStateId << std::endl;
485 os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
486 }
487 else
488 {
489 NS_ASSERT_MSG(0, "Illegal LSA LSType: " << m_lsType);
490 }
491 os << "========== End Global Routing LSA ==========" << std::endl;
492}
493
494std::ostream&
495operator<<(std::ostream& os, GlobalRoutingLSA& lsa)
496{
497 lsa.Print(os);
498 return os;
499}
500
501// ---------------------------------------------------------------------------
502//
503// GlobalRouter Implementation
504//
505// ---------------------------------------------------------------------------
506
507NS_OBJECT_ENSURE_REGISTERED(GlobalRouter);
508
509TypeId
511{
512 static TypeId tid = TypeId("ns3::GlobalRouter").SetParent<Object>().SetGroupName("Internet");
513 return tid;
514}
515
517 : m_LSAs()
518{
519 NS_LOG_FUNCTION(this);
521}
522
524{
525 NS_LOG_FUNCTION(this);
526 ClearLSAs();
527}
528
529void
531{
532 NS_LOG_FUNCTION(this << routing);
533 m_routingProtocol = routing;
534}
535
538{
539 NS_LOG_FUNCTION(this);
540 return m_routingProtocol;
541}
542
543void
545{
546 NS_LOG_FUNCTION(this);
547 m_routingProtocol = nullptr;
548 for (InjectedRoutesI k = m_injectedRoutes.begin(); k != m_injectedRoutes.end();
549 k = m_injectedRoutes.erase(k))
550 {
551 delete (*k);
552 }
554}
555
556void
558{
559 NS_LOG_FUNCTION(this);
560 for (ListOfLSAs_t::iterator i = m_LSAs.begin(); i != m_LSAs.end(); i++)
561 {
562 NS_LOG_LOGIC("Free LSA");
563
564 GlobalRoutingLSA* p = *i;
565 delete p;
566 p = nullptr;
567
568 *i = nullptr;
569 }
570 NS_LOG_LOGIC("Clear list of LSAs");
571 m_LSAs.clear();
572}
573
576{
577 NS_LOG_FUNCTION(this);
578 return m_routerId;
579}
580
581//
582// DiscoverLSAs is called on all nodes in the system that have a GlobalRouter
583// interface aggregated. We need to go out and discover any adjacent routers
584// and build the Link State Advertisements that reflect them and their associated
585// networks.
586//
589{
590 NS_LOG_FUNCTION(this);
591 Ptr<Node> node = GetObject<Node>();
593 "GlobalRouter::DiscoverLSAs (): GetObject for <Node> interface failed");
594 NS_LOG_LOGIC("For node " << node->GetId());
595
596 ClearLSAs();
597
598 //
599 // While building the Router-LSA, keep a list of those NetDevices for
600 // which the current node is the designated router and we will later build
601 // a NetworkLSA for.
602 //
604
605 //
606 // We're aggregated to a node. We need to ask the node for a pointer to its
607 // Ipv4 interface. This is where the information regarding the attached
608 // interfaces lives. If we're a router, we had better have an Ipv4 interface.
609 //
610 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4>();
611 NS_ABORT_MSG_UNLESS(ipv4Local,
612 "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed");
613
614 //
615 // Every router node originates a Router-LSA
616 //
622 pLSA->SetNode(node);
623
624 //
625 // Ask the node for the number of net devices attached. This isn't necessarily
626 // equal to the number of links to adjacent nodes (other routers) as the number
627 // of devices may include those for stub networks (e.g., ethernets, etc.) and
628 // bridge devices also take up an "extra" net device.
629 //
630 uint32_t numDevices = node->GetNDevices();
631
632 //
633 // Iterate through the devices on the node and walk the channel to see what's
634 // on the other side of the standalone devices..
635 //
636 for (uint32_t i = 0; i < numDevices; ++i)
637 {
638 Ptr<NetDevice> ndLocal = node->GetDevice(i);
639
640 if (DynamicCast<LoopbackNetDevice>(ndLocal))
641 {
642 continue;
643 }
644
645 //
646 // There is an assumption that bridge ports must never have an IP address
647 // associated with them. This turns out to be a very convenient place to
648 // check and make sure that this is the case.
649 //
650 if (NetDeviceIsBridged(ndLocal))
651 {
652 int32_t ifIndex = ipv4Local->GetInterfaceForDevice(ndLocal);
654 ifIndex != -1,
655 "GlobalRouter::DiscoverLSAs(): Bridge ports must not have an IPv4 interface index");
656 }
657
658 //
659 // Check to see if the net device we just got has a corresponding IP
660 // interface (could be a pure L2 NetDevice) -- for example a net device
661 // associated with a bridge. We are only going to involve devices with
662 // IP addresses in routing.
663 //
664 int32_t interfaceNumber = ipv4Local->GetInterfaceForDevice(ndLocal);
665 if (interfaceNumber == -1 ||
666 !(ipv4Local->IsUp(interfaceNumber) && ipv4Local->IsForwarding(interfaceNumber)))
667 {
668 NS_LOG_LOGIC("Net device "
669 << ndLocal
670 << "has no IP interface or is not enabled for forwarding, skipping");
671 continue;
672 }
673
674 //
675 // We have a net device that we need to check out. If it supports
676 // broadcast and is not a point-point link, then it will be either a stub
677 // network or a transit network depending on the number of routers on
678 // the segment. We add the appropriate link record to the LSA.
679 //
680 // If the device is a point to point link, we treat it separately. In
681 // that case, there may be zero, one, or two link records added.
682 //
683
684 if (ndLocal->IsBroadcast() && !ndLocal->IsPointToPoint())
685 {
686 NS_LOG_LOGIC("Broadcast link");
687 ProcessBroadcastLink(ndLocal, pLSA, c);
688 }
689 else if (ndLocal->IsPointToPoint())
690 {
691 NS_LOG_LOGIC("Point=to-point link");
692 ProcessPointToPointLink(ndLocal, pLSA);
693 }
694 else
695 {
696 NS_ASSERT_MSG(0, "GlobalRouter::DiscoverLSAs (): unknown link type");
697 }
698 }
699
700 NS_LOG_LOGIC("========== LSA for node " << node->GetId() << " ==========");
701 NS_LOG_LOGIC(*pLSA);
702 m_LSAs.push_back(pLSA);
703 pLSA = nullptr;
704
705 //
706 // Now, determine whether we need to build a NetworkLSA. This is the case if
707 // we found at least one designated router.
708 //
709 uint32_t nDesignatedRouters = c.GetN();
710 if (nDesignatedRouters > 0)
711 {
712 NS_LOG_LOGIC("Build Network LSAs");
714 }
715
716 //
717 // Build injected route LSAs as external routes
718 // RFC 2328, section 12.4.4
719 //
720 for (InjectedRoutesCI i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
721 {
724 pLSA->SetLinkStateId((*i)->GetDestNetwork());
726 pLSA->SetNetworkLSANetworkMask((*i)->GetDestNetworkMask());
728 m_LSAs.push_back(pLSA);
729 }
730 return m_LSAs.size();
731}
732
733void
735{
736 NS_LOG_FUNCTION(this << nd << pLSA << &c);
737
738 if (nd->IsBridge())
739 {
740 ProcessBridgedBroadcastLink(nd, pLSA, c);
741 }
742 else
743 {
744 ProcessSingleBroadcastLink(nd, pLSA, c);
745 }
746}
747
748void
750 GlobalRoutingLSA* pLSA,
752{
753 NS_LOG_FUNCTION(this << nd << pLSA << &c);
754
756 NS_ABORT_MSG_IF(plr == nullptr,
757 "GlobalRouter::ProcessSingleBroadcastLink(): Can't alloc link record");
758
759 //
760 // We have some preliminaries to do to get enough information to proceed.
761 // This information we need comes from the internet stack, so notice that
762 // there is an implied assumption that global routing is only going to
763 // work with devices attached to the internet stack (have an ipv4 interface
764 // associated to them.
765 //
766 Ptr<Node> node = nd->GetNode();
767
768 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4>();
770 ipv4Local,
771 "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for <Ipv4> interface failed");
772
773 int32_t interfaceLocal = ipv4Local->GetInterfaceForDevice(nd);
775 interfaceLocal == -1,
776 "GlobalRouter::ProcessSingleBroadcastLink(): No interface index associated with device");
777
778 if (ipv4Local->GetNAddresses(interfaceLocal) > 1)
779 {
780 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
781 }
782 Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal, 0).GetLocal();
783 Ipv4Mask maskLocal = ipv4Local->GetAddress(interfaceLocal, 0).GetMask();
784 NS_LOG_LOGIC("Working with local address " << addrLocal);
785 uint16_t metricLocal = ipv4Local->GetMetric(interfaceLocal);
786
787 //
788 // Check to see if the net device is connected to a channel/network that has
789 // another router on it. If there is no other router on the link (but us) then
790 // this is a stub network. If we find another router, then what we have here
791 // is a transit network.
792 //
794 if (AnotherRouterOnLink(nd) == false)
795 {
796 //
797 // This is a net device connected to a stub network
798 //
799 NS_LOG_LOGIC("Router-LSA Stub Network");
801
802 //
803 // According to OSPF, the Link ID is the IP network number of
804 // the attached network.
805 //
806 plr->SetLinkId(addrLocal.CombineMask(maskLocal));
807
808 //
809 // and the Link Data is the network mask; converted to Ipv4Address
810 //
811 Ipv4Address maskLocalAddr;
812 maskLocalAddr.Set(maskLocal.Get());
813 plr->SetLinkData(maskLocalAddr);
814 plr->SetMetric(metricLocal);
815 pLSA->AddLinkRecord(plr);
816 plr = nullptr;
817 }
818 else
819 {
820 //
821 // We have multiple routers on a broadcast interface, so this is
822 // a transit network.
823 //
824 NS_LOG_LOGIC("Router-LSA Transit Network");
826
827 //
828 // By definition, the router with the lowest IP address is the
829 // designated router for the network. OSPF says that the Link ID
830 // gets the IP interface address of the designated router in this
831 // case.
832 //
834 Ipv4Address desigRtr;
835 desigRtr = FindDesignatedRouterForLink(nd);
836
837 //
838 // Let's double-check that any designated router we find out on our
839 // network is really on our network.
840 //
841 if (desigRtr != "255.255.255.255")
842 {
843 Ipv4Address networkHere = addrLocal.CombineMask(maskLocal);
844 Ipv4Address networkThere = desigRtr.CombineMask(maskLocal);
846 networkHere == networkThere,
847 "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion ("
848 << addrLocal << "/" << maskLocal.GetPrefixLength() << ", " << desigRtr << "/"
849 << maskLocal.GetPrefixLength() << ")");
850 }
851 if (desigRtr == addrLocal)
852 {
853 c.Add(nd);
854 NS_LOG_LOGIC("Node " << node->GetId() << " elected a designated router");
855 }
856 plr->SetLinkId(desigRtr);
857
858 //
859 // OSPF says that the Link Data is this router's own IP address.
860 //
861 plr->SetLinkData(addrLocal);
862 plr->SetMetric(metricLocal);
863 pLSA->AddLinkRecord(plr);
864 plr = nullptr;
865 }
866}
867
868void
870 GlobalRoutingLSA* pLSA,
872{
873 NS_LOG_FUNCTION(this << nd << pLSA << &c);
874 NS_ASSERT_MSG(nd->IsBridge(),
875 "GlobalRouter::ProcessBridgedBroadcastLink(): Called with non-bridge net device");
876
877#if 0
878 //
879 // It is possible to admit the possibility that a bridge device on a node
880 // can also participate in routing. This would surprise people who don't
881 // come from Microsoft-land where they do use such a construct. Based on
882 // the principle of least-surprise, we will leave the relatively simple
883 // code in place to do this, but not enable it until someone really wants
884 // the capability. Even then, we will not enable this code as a default
885 // but rather something you will have to go and turn on.
886 //
887
888 Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> ();
889 NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
890
891 //
892 // We have some preliminaries to do to get enough information to proceed.
893 // This information we need comes from the internet stack, so notice that
894 // there is an implied assumption that global routing is only going to
895 // work with devices attached to the internet stack (have an ipv4 interface
896 // associated to them.
897 //
898 Ptr<Node> node = nd->GetNode ();
899 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> ();
900 NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for <Ipv4> interface failed");
901
902 int32_t interfaceLocal = ipv4Local->GetInterfaceForDevice (nd);
903 NS_ABORT_MSG_IF (interfaceLocal == -1, "GlobalRouter::ProcessBridgedBroadcastLink(): No interface index associated with device");
904
905 if (ipv4Local->GetNAddresses (interfaceLocal) > 1)
906 {
907 NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one");
908 }
909 Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal ();
910 Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();
911 NS_LOG_LOGIC ("Working with local address " << addrLocal);
912 uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal);
913
914 //
915 // We need to handle a bridge on the router. This means that we have been
916 // given a net device that is a BridgeNetDevice. It has an associated Ipv4
917 // interface index and address. Some number of other net devices live "under"
918 // the bridge device as so-called bridge ports. In a nutshell, what we have
919 // to do is to repeat what is done for a single broadcast link on all of
920 // those net devices living under the bridge (trolls?)
921 //
922
923 bool areTransitNetwork = false;
924 Ipv4Address desigRtr ("255.255.255.255");
925
926 for (uint32_t i = 0; i < bnd->GetNBridgePorts (); ++i)
927 {
928 Ptr<NetDevice> ndTemp = bnd->GetBridgePort (i);
929
930 //
931 // We have to decide if we are a transit network. This is characterized
932 // by the presence of another router on the network segment. If we find
933 // another router on any of our bridged links, we are a transit network.
934 //
936 if (AnotherRouterOnLink (ndTemp))
937 {
938 areTransitNetwork = true;
939
940 //
941 // If we're going to be a transit network, then we have got to elect
942 // a designated router for the whole bridge. This means finding the
943 // router with the lowest IP address on the whole bridge. We ask
944 // for the lowest address on each segment and pick the lowest of them
945 // all.
946 //
948 Ipv4Address desigRtrTemp = FindDesignatedRouterForLink (ndTemp);
949
950 //
951 // Let's double-check that any designated router we find out on our
952 // network is really on our network.
953 //
954 if (desigRtrTemp != "255.255.255.255")
955 {
956 Ipv4Address networkHere = addrLocal.CombineMask (maskLocal);
957 Ipv4Address networkThere = desigRtrTemp.CombineMask (maskLocal);
958 NS_ABORT_MSG_UNLESS (networkHere == networkThere,
959 "GlobalRouter::ProcessSingleBroadcastLink(): Network number confusion (" <<
960 addrLocal << "/" << maskLocal.GetPrefixLength () << ", " <<
961 desigRtrTemp << "/" << maskLocal.GetPrefixLength () << ")");
962 }
963 if (desigRtrTemp < desigRtr)
964 {
965 desigRtr = desigRtrTemp;
966 }
967 }
968 }
969 //
970 // That's all the information we need to put it all together, just like we did
971 // in the case of a single broadcast link.
972 //
973
975 NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessBridgedBroadcastLink(): Can't alloc link record");
976
977 if (areTransitNetwork == false)
978 {
979 //
980 // This is a net device connected to a bridge of stub networks
981 //
982 NS_LOG_LOGIC ("Router-LSA Stub Network");
984
985 //
986 // According to OSPF, the Link ID is the IP network number of
987 // the attached network.
988 //
989 plr->SetLinkId (addrLocal.CombineMask (maskLocal));
990
991 //
992 // and the Link Data is the network mask; converted to Ipv4Address
993 //
994 Ipv4Address maskLocalAddr;
995 maskLocalAddr.Set (maskLocal.Get ());
996 plr->SetLinkData (maskLocalAddr);
997 plr->SetMetric (metricLocal);
998 pLSA->AddLinkRecord (plr);
999 plr = 0;
1000 }
1001 else
1002 {
1003 //
1004 // We have multiple routers on a bridged broadcast interface, so this is
1005 // a transit network.
1006 //
1007 NS_LOG_LOGIC ("Router-LSA Transit Network");
1009
1010 //
1011 // By definition, the router with the lowest IP address is the
1012 // designated router for the network. OSPF says that the Link ID
1013 // gets the IP interface address of the designated router in this
1014 // case.
1015 //
1016 if (desigRtr == addrLocal)
1017 {
1018 c.Add (nd);
1019 NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router");
1020 }
1021 plr->SetLinkId (desigRtr);
1022
1023 //
1024 // OSPF says that the Link Data is this router's own IP address.
1025 //
1026 plr->SetLinkData (addrLocal);
1027 plr->SetMetric (metricLocal);
1028 pLSA->AddLinkRecord (plr);
1029 plr = 0;
1030 }
1031#endif
1032}
1033
1034void
1036{
1037 NS_LOG_FUNCTION(this << ndLocal << pLSA);
1038
1039 //
1040 // We have some preliminaries to do to get enough information to proceed.
1041 // This information we need comes from the internet stack, so notice that
1042 // there is an implied assumption that global routing is only going to
1043 // work with devices attached to the internet stack (have an ipv4 interface
1044 // associated to them.
1045 //
1046 Ptr<Node> nodeLocal = ndLocal->GetNode();
1047
1048 Ptr<Ipv4> ipv4Local = nodeLocal->GetObject<Ipv4>();
1050 ipv4Local,
1051 "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1052
1053 int32_t interfaceLocal = ipv4Local->GetInterfaceForDevice(ndLocal);
1055 interfaceLocal == -1,
1056 "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device");
1057
1058 if (ipv4Local->GetNAddresses(interfaceLocal) > 1)
1059 {
1060 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
1061 }
1062 Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal, 0).GetLocal();
1063 NS_LOG_LOGIC("Working with local address " << addrLocal);
1064 uint16_t metricLocal = ipv4Local->GetMetric(interfaceLocal);
1065
1066 //
1067 // Now, we're going to walk over to the remote net device on the other end of
1068 // the point-to-point channel we know we have. This is where our adjacent
1069 // router (to use OSPF lingo) is running.
1070 //
1071 Ptr<Channel> ch = ndLocal->GetChannel();
1072
1073 //
1074 // Get the net device on the other side of the point-to-point channel.
1075 //
1076 Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch);
1077
1078 //
1079 // The adjacent net device is aggregated to a node. We need to ask that net
1080 // device for its node, then ask that node for its Ipv4 interface. Note a
1081 // requirement that nodes on either side of a point-to-point link must have
1082 // internet stacks; and an assumption that point-to-point links are incompatible
1083 // with bridging.
1084 //
1085 Ptr<Node> nodeRemote = ndRemote->GetNode();
1086 Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4>();
1088 ipv4Remote,
1089 "GlobalRouter::ProcessPointToPointLink(): GetObject for remote <Ipv4> failed");
1090
1091 //
1092 // Further note the requirement that nodes on either side of a point-to-point
1093 // link must participate in global routing and therefore have a GlobalRouter
1094 // interface aggregated.
1095 //
1096 Ptr<GlobalRouter> rtrRemote = nodeRemote->GetObject<GlobalRouter>();
1097 if (!rtrRemote)
1098 {
1099 // This case is possible if the remote does not participate in global routing
1100 return;
1101 }
1102 //
1103 // We're going to need the remote router ID, so we might as well get it now.
1104 //
1105 Ipv4Address rtrIdRemote = rtrRemote->GetRouterId();
1106 NS_LOG_LOGIC("Working with remote router " << rtrIdRemote);
1107
1108 //
1109 // Now, just like we did above, we need to get the IP interface index for the
1110 // net device on the other end of the point-to-point channel.
1111 //
1112 int32_t interfaceRemote = ipv4Remote->GetInterfaceForDevice(ndRemote);
1113 NS_ABORT_MSG_IF(interfaceRemote == -1,
1114 "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with "
1115 "remote device");
1116
1117 //
1118 // Now that we have the Ipv4 interface, we can get the (remote) address and
1119 // mask we need.
1120 //
1121 if (ipv4Remote->GetNAddresses(interfaceRemote) > 1)
1122 {
1123 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
1124 }
1125 Ipv4Address addrRemote = ipv4Remote->GetAddress(interfaceRemote, 0).GetLocal();
1126 Ipv4Mask maskRemote = ipv4Remote->GetAddress(interfaceRemote, 0).GetMask();
1127 NS_LOG_LOGIC("Working with remote address " << addrRemote);
1128
1129 //
1130 // Now we can fill out the link records for this link. There are always two
1131 // link records; the first is a point-to-point record describing the link and
1132 // the second is a stub network record with the network number.
1133 //
1135 if (ipv4Remote->IsUp(interfaceRemote))
1136 {
1137 NS_LOG_LOGIC("Remote side interface " << interfaceRemote << " is up-- add a type 1 link");
1138
1139 plr = new GlobalRoutingLinkRecord;
1140 NS_ABORT_MSG_IF(plr == nullptr,
1141 "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1143 plr->SetLinkId(rtrIdRemote);
1144 plr->SetLinkData(addrLocal);
1145 plr->SetMetric(metricLocal);
1146 pLSA->AddLinkRecord(plr);
1147 plr = nullptr;
1148 }
1149
1150 // Regardless of state of peer, add a type 3 link (RFC 2328: 12.4.1.1)
1151 plr = new GlobalRoutingLinkRecord;
1152 NS_ABORT_MSG_IF(plr == nullptr,
1153 "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
1155 plr->SetLinkId(addrRemote);
1156 plr->SetLinkData(Ipv4Address(maskRemote.Get())); // Frown
1157 plr->SetMetric(metricLocal);
1158 pLSA->AddLinkRecord(plr);
1159 plr = nullptr;
1160}
1161
1162void
1164{
1165 NS_LOG_FUNCTION(this << &c);
1166
1167 uint32_t nDesignatedRouters = c.GetN();
1168 NS_LOG_DEBUG("Number of designated routers: " << nDesignatedRouters);
1169
1170 for (uint32_t i = 0; i < nDesignatedRouters; ++i)
1171 {
1172 //
1173 // Build one NetworkLSA for each net device talking to a network that we are the
1174 // designated router for. These devices are in the provided container.
1175 //
1176 Ptr<NetDevice> ndLocal = c.Get(i);
1177 Ptr<Node> node = ndLocal->GetNode();
1178
1179 Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4>();
1181 ipv4Local,
1182 "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed");
1183
1184 int32_t interfaceLocal = ipv4Local->GetInterfaceForDevice(ndLocal);
1186 interfaceLocal == -1,
1187 "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device");
1188
1189 if (ipv4Local->GetNAddresses(interfaceLocal) > 1)
1190 {
1191 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the primary one");
1192 }
1193 Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal, 0).GetLocal();
1194 Ipv4Mask maskLocal = ipv4Local->GetAddress(interfaceLocal, 0).GetMask();
1195
1197 NS_ABORT_MSG_IF(pLSA == nullptr,
1198 "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record");
1199
1201 pLSA->SetLinkStateId(addrLocal);
1203 pLSA->SetNetworkLSANetworkMask(maskLocal);
1205 pLSA->SetNode(node);
1206
1207 //
1208 // Build a list of AttachedRouters by walking the devices in the channel
1209 // and, if we find a node with a GlobalRouter interface and an IPv4
1210 // interface associated with that device, we call it an attached router.
1211 //
1213 Ptr<Channel> ch = ndLocal->GetChannel();
1214 std::size_t nDevices = ch->GetNDevices();
1215 NS_ASSERT(nDevices);
1217 NS_LOG_LOGIC("Found " << deviceList.GetN() << " non-bridged devices on channel");
1218
1219 for (uint32_t i = 0; i < deviceList.GetN(); i++)
1220 {
1221 Ptr<NetDevice> tempNd = deviceList.Get(i);
1222 NS_ASSERT(tempNd);
1223 if (tempNd == ndLocal)
1224 {
1225 NS_LOG_LOGIC("Adding " << addrLocal << " to Network LSA");
1226 pLSA->AddAttachedRouter(addrLocal);
1227 continue;
1228 }
1229 Ptr<Node> tempNode = tempNd->GetNode();
1230
1231 // Does the node in question have a GlobalRouter interface? If not it can
1232 // hardly be considered an attached router.
1233 //
1234 Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter>();
1235 if (!rtr)
1236 {
1237 NS_LOG_LOGIC("Node " << tempNode->GetId()
1238 << " does not have GlobalRouter interface--skipping");
1239 continue;
1240 }
1241
1242 //
1243 // Does the attached node have an ipv4 interface for the device we're probing?
1244 // If not, it can't play router.
1245 //
1246 Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4>();
1247 int32_t tempInterface = tempIpv4->GetInterfaceForDevice(tempNd);
1248
1249 if (tempInterface != -1)
1250 {
1251 Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4>();
1252 NS_ASSERT(tempIpv4);
1253 if (!tempIpv4->IsUp(tempInterface))
1254 {
1255 NS_LOG_LOGIC("Remote side interface " << tempInterface << " not up");
1256 }
1257 else
1258 {
1259 if (tempIpv4->GetNAddresses(tempInterface) > 1)
1260 {
1261 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the "
1262 "primary one");
1263 }
1264 Ipv4Address tempAddr = tempIpv4->GetAddress(tempInterface, 0).GetLocal();
1265 NS_LOG_LOGIC("Adding " << tempAddr << " to Network LSA");
1266 pLSA->AddAttachedRouter(tempAddr);
1267 }
1268 }
1269 else
1270 {
1271 NS_LOG_LOGIC("Node " << tempNode->GetId() << " device " << tempNd
1272 << " does not have IPv4 interface; skipping");
1273 }
1274 }
1275 m_LSAs.push_back(pLSA);
1276 NS_LOG_LOGIC("========== LSA for node " << node->GetId() << " ==========");
1277 NS_LOG_LOGIC(*pLSA);
1278 pLSA = nullptr;
1279 }
1280}
1281
1284{
1285 NS_LOG_FUNCTION(this << ch);
1287
1288 for (std::size_t i = 0; i < ch->GetNDevices(); i++)
1289 {
1290 Ptr<NetDevice> nd = ch->GetDevice(i);
1291 NS_LOG_LOGIC("checking to see if the device " << nd << " is bridged");
1293 if (bnd && BridgeHasAlreadyBeenVisited(bnd) == false)
1294 {
1295 NS_LOG_LOGIC("Device is bridged by BridgeNetDevice "
1296 << bnd << " with " << bnd->GetNBridgePorts() << " ports");
1298 // Find all channels bridged together, and recursively call
1299 // on all other channels
1300 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); j++)
1301 {
1302 Ptr<NetDevice> bridgedDevice = bnd->GetBridgePort(j);
1303 if (bridgedDevice->GetChannel() == ch)
1304 {
1305 NS_LOG_LOGIC("Skipping my own device/channel");
1306 continue;
1307 }
1308 NS_LOG_LOGIC("Calling on channel " << bridgedDevice->GetChannel());
1309 c.Add(FindAllNonBridgedDevicesOnLink(bridgedDevice->GetChannel()));
1310 }
1311 }
1312 else
1313 {
1314 NS_LOG_LOGIC("Device is not bridged; adding");
1315 c.Add(nd);
1316 }
1317 }
1318 NS_LOG_LOGIC("Found " << c.GetN() << " devices");
1319 return c;
1320}
1321
1322//
1323// Given a local net device, we need to walk the channel to which the net device is
1324// attached and look for nodes with GlobalRouter interfaces on them (one of them
1325// will be us). Of these, the router with the lowest IP address on the net device
1326// connecting to the channel becomes the designated router for the link.
1327//
1330{
1331 NS_LOG_FUNCTION(this << ndLocal);
1332
1333 Ptr<Channel> ch = ndLocal->GetChannel();
1334 uint32_t nDevices = ch->GetNDevices();
1335 NS_ASSERT(nDevices);
1336
1337 NS_LOG_LOGIC("Looking for designated router off of net device " << ndLocal << " on node "
1338 << ndLocal->GetNode()->GetId());
1339
1340 Ipv4Address desigRtr("255.255.255.255");
1341
1342 //
1343 // Look through all of the devices on the channel to which the net device
1344 // in question is attached.
1345 //
1346 for (uint32_t i = 0; i < nDevices; i++)
1347 {
1348 Ptr<NetDevice> ndOther = ch->GetDevice(i);
1349 NS_ASSERT(ndOther);
1350
1351 Ptr<Node> nodeOther = ndOther->GetNode();
1352
1353 NS_LOG_LOGIC("Examine channel device " << i << " on node " << nodeOther->GetId());
1354
1355 //
1356 // For all other net devices, we need to check and see if a router
1357 // is present. If the net device on the other side is a bridged
1358 // device, we need to consider all of the other devices on the
1359 // bridge as well (all of the bridge ports.
1360 //
1361 NS_LOG_LOGIC("checking to see if the device is bridged");
1363 if (bnd)
1364 {
1365 NS_LOG_LOGIC("Device is bridged by BridgeNetDevice " << bnd);
1366
1367 //
1368 // When enumerating a bridge, don't count the netdevice we came in on
1369 //
1370 if (ndLocal == ndOther)
1371 {
1372 NS_LOG_LOGIC("Skip -- it is where we came from.");
1373 continue;
1374 }
1375
1376 //
1377 // It is possible that the bridge net device is sitting under a
1378 // router, so we have to check for the presence of that router
1379 // before we run off and follow all the links
1380 //
1381 // We require a designated router to have a GlobalRouter interface and
1382 // an internet stack that includes the Ipv4 interface. If it doesn't
1383 // it can't play router.
1384 //
1385 NS_LOG_LOGIC("Checking for router on bridge net device " << bnd);
1386 Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter>();
1387 Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4>();
1388 if (rtr && ipv4)
1389 {
1390 int32_t interfaceOther = ipv4->GetInterfaceForDevice(bnd);
1391 if (interfaceOther != -1)
1392 {
1393 NS_LOG_LOGIC("Found router on bridge net device " << bnd);
1394 if (!ipv4->IsUp(interfaceOther))
1395 {
1396 NS_LOG_LOGIC("Remote side interface " << interfaceOther << " not up");
1397 continue;
1398 }
1399 if (ipv4->GetNAddresses(interfaceOther) > 1)
1400 {
1401 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the "
1402 "primary one");
1403 }
1404 Ipv4Address addrOther = ipv4->GetAddress(interfaceOther, 0).GetLocal();
1405 desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1406 NS_LOG_LOGIC("designated router now " << desigRtr);
1407 }
1408 }
1409
1410 //
1411 // Check if we have seen this bridge net device already while
1412 // recursively enumerating an L2 broadcast domain. If it is new
1413 // to us, go ahead and process it. If we have already processed it,
1414 // move to the next
1415 //
1417 {
1418 NS_ABORT_MSG("ERROR: L2 forwarding loop detected!");
1419 }
1420
1422
1423 NS_LOG_LOGIC("Looking through bridge ports of bridge net device " << bnd);
1424 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); ++j)
1425 {
1426 Ptr<NetDevice> ndBridged = bnd->GetBridgePort(j);
1427 NS_LOG_LOGIC("Examining bridge port " << j << " device " << ndBridged);
1428 if (ndBridged == ndOther)
1429 {
1430 NS_LOG_LOGIC("That bridge port is me, don't walk backward");
1431 continue;
1432 }
1433
1434 NS_LOG_LOGIC("Recursively looking for routers down bridge port " << ndBridged);
1435 Ipv4Address addrOther = FindDesignatedRouterForLink(ndBridged);
1436 desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1437 NS_LOG_LOGIC("designated router now " << desigRtr);
1438 }
1439 }
1440 else
1441 {
1442 NS_LOG_LOGIC("This device is not bridged");
1443 Ptr<Node> nodeOther = ndOther->GetNode();
1444 NS_ASSERT(nodeOther);
1445
1446 //
1447 // We require a designated router to have a GlobalRouter interface and
1448 // an internet stack that includes the Ipv4 interface. If it doesn't
1449 //
1450 Ptr<GlobalRouter> rtr = nodeOther->GetObject<GlobalRouter>();
1451 Ptr<Ipv4> ipv4 = nodeOther->GetObject<Ipv4>();
1452 if (rtr && ipv4)
1453 {
1454 int32_t interfaceOther = ipv4->GetInterfaceForDevice(ndOther);
1455 if (interfaceOther != -1)
1456 {
1457 if (!ipv4->IsUp(interfaceOther))
1458 {
1459 NS_LOG_LOGIC("Remote side interface " << interfaceOther << " not up");
1460 continue;
1461 }
1462 NS_LOG_LOGIC("Found router on net device " << ndOther);
1463 if (ipv4->GetNAddresses(interfaceOther) > 1)
1464 {
1465 NS_LOG_WARN("Warning, interface has multiple IP addresses; using only the "
1466 "primary one");
1467 }
1468 Ipv4Address addrOther = ipv4->GetAddress(interfaceOther, 0).GetLocal();
1469 desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
1470 NS_LOG_LOGIC("designated router now " << desigRtr);
1471 }
1472 }
1473 }
1474 }
1475 return desigRtr;
1476}
1477
1478//
1479// Given a node and an attached net device, take a look off in the channel to
1480// which the net device is attached and look for a node on the other side
1481// that has a GlobalRouter interface aggregated. Life gets more complicated
1482// when there is a bridged net device on the other side.
1483//
1484bool
1486{
1487 NS_LOG_FUNCTION(this << nd);
1488
1489 Ptr<Channel> ch = nd->GetChannel();
1490 if (!ch)
1491 {
1492 // It may be that this net device is a stub device, without a channel
1493 return false;
1494 }
1495 uint32_t nDevices = ch->GetNDevices();
1496 NS_ASSERT(nDevices);
1497
1498 NS_LOG_LOGIC("Looking for routers off of net device " << nd << " on node "
1499 << nd->GetNode()->GetId());
1500
1501 //
1502 // Look through all of the devices on the channel to which the net device
1503 // in question is attached.
1504 //
1505 for (uint32_t i = 0; i < nDevices; i++)
1506 {
1507 Ptr<NetDevice> ndOther = ch->GetDevice(i);
1508 NS_ASSERT(ndOther);
1509
1510 NS_LOG_LOGIC("Examine channel device " << i << " on node " << ndOther->GetNode()->GetId());
1511
1512 //
1513 // Ignore the net device itself.
1514 //
1515 if (ndOther == nd)
1516 {
1517 NS_LOG_LOGIC("Myself, skip");
1518 continue;
1519 }
1520
1521 //
1522 // For all other net devices, we need to check and see if a router
1523 // is present. If the net device on the other side is a bridged
1524 // device, we need to consider all of the other devices on the
1525 // bridge.
1526 //
1527 NS_LOG_LOGIC("checking to see if device is bridged");
1529 if (bnd)
1530 {
1531 NS_LOG_LOGIC("Device is bridged by net device " << bnd);
1532
1533 //
1534 // Check if we have seen this bridge net device already while
1535 // recursively enumerating an L2 broadcast domain. If it is new
1536 // to us, go ahead and process it. If we have already processed it,
1537 // move to the next
1538 //
1540 {
1541 NS_ABORT_MSG("ERROR: L2 forwarding loop detected!");
1542 }
1543
1545
1546 NS_LOG_LOGIC("Looking through bridge ports of bridge net device " << bnd);
1547 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); ++j)
1548 {
1549 Ptr<NetDevice> ndBridged = bnd->GetBridgePort(j);
1550 NS_LOG_LOGIC("Examining bridge port " << j << " device " << ndBridged);
1551 if (ndBridged == ndOther)
1552 {
1553 NS_LOG_LOGIC("That bridge port is me, skip");
1554 continue;
1555 }
1556
1557 NS_LOG_LOGIC("Recursively looking for routers on bridge port " << ndBridged);
1558 if (AnotherRouterOnLink(ndBridged))
1559 {
1560 NS_LOG_LOGIC("Found routers on bridge port, return true");
1561 return true;
1562 }
1563 }
1564 NS_LOG_LOGIC("No routers on bridged net device, return false");
1565 return false;
1566 }
1567
1568 NS_LOG_LOGIC("This device is not bridged");
1569 Ptr<Node> nodeTemp = ndOther->GetNode();
1570 NS_ASSERT(nodeTemp);
1571
1572 Ptr<GlobalRouter> rtr = nodeTemp->GetObject<GlobalRouter>();
1573 if (rtr)
1574 {
1575 NS_LOG_LOGIC("Found GlobalRouter interface, return true");
1576 return true;
1577 }
1578 else
1579 {
1580 NS_LOG_LOGIC("No GlobalRouter interface on device, continue search");
1581 }
1582 }
1583 NS_LOG_LOGIC("No routers found, return false");
1584 return false;
1585}
1586
1589{
1590 NS_LOG_FUNCTION(this);
1591 return m_LSAs.size();
1592}
1593
1594//
1595// Get the nth link state advertisement from this router.
1596//
1597bool
1599{
1600 NS_LOG_FUNCTION(this << n << &lsa);
1601 NS_ASSERT_MSG(lsa.IsEmpty(), "GlobalRouter::GetLSA (): Must pass empty LSA");
1602 //
1603 // All of the work was done in GetNumLSAs. All we have to do here is to
1604 // walk the list of link state advertisements created there and return the
1605 // one the client is interested in.
1606 //
1607 ListOfLSAs_t::const_iterator i = m_LSAs.begin();
1608 uint32_t j = 0;
1609
1610 for (; i != m_LSAs.end(); i++, j++)
1611 {
1612 if (j == n)
1613 {
1614 GlobalRoutingLSA* p = *i;
1615 lsa = *p;
1616 return true;
1617 }
1618 }
1619
1620 return false;
1621}
1622
1623void
1625{
1626 NS_LOG_FUNCTION(this << network << networkMask);
1628 //
1629 // Interface number does not matter here, using 1.
1630 //
1631 *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, 1);
1632 m_injectedRoutes.push_back(route);
1633}
1634
1637{
1638 NS_LOG_FUNCTION(this << index);
1639 if (index < m_injectedRoutes.size())
1640 {
1641 uint32_t tmp = 0;
1642 for (InjectedRoutesCI i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
1643 {
1644 if (tmp == index)
1645 {
1646 return *i;
1647 }
1648 tmp++;
1649 }
1650 }
1651 NS_ASSERT(false);
1652 // quiet compiler.
1653 return nullptr;
1654}
1655
1658{
1659 NS_LOG_FUNCTION(this);
1660 return m_injectedRoutes.size();
1661}
1662
1663void
1665{
1666 NS_LOG_FUNCTION(this << index);
1667 NS_ASSERT(index < m_injectedRoutes.size());
1668 uint32_t tmp = 0;
1669 for (InjectedRoutesI i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
1670 {
1671 if (tmp == index)
1672 {
1673 NS_LOG_LOGIC("Removing route " << index << "; size = " << m_injectedRoutes.size());
1674 delete *i;
1675 m_injectedRoutes.erase(i);
1676 return;
1677 }
1678 tmp++;
1679 }
1680}
1681
1682bool
1684{
1685 NS_LOG_FUNCTION(this << network << networkMask);
1686 for (InjectedRoutesI i = m_injectedRoutes.begin(); i != m_injectedRoutes.end(); i++)
1687 {
1688 if ((*i)->GetDestNetwork() == network && (*i)->GetDestNetworkMask() == networkMask)
1689 {
1690 NS_LOG_LOGIC("Withdrawing route to network/mask " << network << "/" << networkMask);
1691 delete *i;
1692 m_injectedRoutes.erase(i);
1693 return true;
1694 }
1695 }
1696 return false;
1697}
1698
1699//
1700// Link through the given channel and find the net device that's on the
1701// other end. This only makes sense with a point-to-point channel.
1702//
1705{
1706 NS_LOG_FUNCTION(this << nd << ch);
1707 NS_ASSERT_MSG(ch->GetNDevices() == 2,
1708 "GlobalRouter::GetAdjacent (): Channel with other than two devices");
1709 //
1710 // This is a point to point channel with two endpoints. Get both of them.
1711 //
1712 Ptr<NetDevice> nd1 = ch->GetDevice(0);
1713 Ptr<NetDevice> nd2 = ch->GetDevice(1);
1714 //
1715 // One of the endpoints is going to be "us" -- that is the net device attached
1716 // to the node on which we're running -- i.e., "nd". The other endpoint (the
1717 // one to which we are connected via the channel) is the adjacent router.
1718 //
1719 if (nd1 == nd)
1720 {
1721 return nd2;
1722 }
1723 else if (nd2 == nd)
1724 {
1725 return nd1;
1726 }
1727 else
1728 {
1729 NS_ASSERT_MSG(false, "GlobalRouter::GetAdjacent (): Wrong or confused channel?");
1730 return nullptr;
1731 }
1732}
1733
1734//
1735// Decide whether or not a given net device is being bridged by a BridgeNetDevice.
1736//
1739{
1740 NS_LOG_FUNCTION(this << nd);
1741
1742 Ptr<Node> node = nd->GetNode();
1743 uint32_t nDevices = node->GetNDevices();
1744
1745 //
1746 // There is no bit on a net device that says it is being bridged, so we have
1747 // to look for bridges on the node to which the device is attached. If we
1748 // find a bridge, we need to look through its bridge ports (the devices it
1749 // bridges) to see if we find the device in question.
1750 //
1751 for (uint32_t i = 0; i < nDevices; ++i)
1752 {
1753 Ptr<NetDevice> ndTest = node->GetDevice(i);
1754 NS_LOG_LOGIC("Examine device " << i << " " << ndTest);
1755
1756 if (ndTest->IsBridge())
1757 {
1758 NS_LOG_LOGIC("device " << i << " is a bridge net device");
1759 Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice>();
1761 bnd,
1762 "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed");
1763
1764 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); ++j)
1765 {
1766 NS_LOG_LOGIC("Examine bridge port " << j << " " << bnd->GetBridgePort(j));
1767 if (bnd->GetBridgePort(j) == nd)
1768 {
1769 NS_LOG_LOGIC("Net device " << nd << " is bridged by " << bnd);
1770 return bnd;
1771 }
1772 }
1773 }
1774 }
1775 NS_LOG_LOGIC("Net device " << nd << " is not bridged");
1776 return nullptr;
1777}
1778
1779//
1780// Start a new enumeration of an L2 broadcast domain by clearing m_bridgesVisited
1781//
1782void
1784{
1785 m_bridgesVisited.clear();
1786}
1787
1788//
1789// Check if we have already visited a given bridge net device by searching m_bridgesVisited
1790//
1791bool
1793{
1794 std::vector<Ptr<BridgeNetDevice>>::iterator iter;
1795 for (iter = m_bridgesVisited.begin(); iter != m_bridgesVisited.end(); ++iter)
1796 {
1797 if (bridgeNetDevice == *iter)
1798 {
1799 NS_LOG_LOGIC("Bridge " << bridgeNetDevice << " has been visited.");
1800 return true;
1801 }
1802 }
1803 return false;
1804}
1805
1806//
1807// Remember that we visited a bridge net device by adding it to m_bridgesVisited
1808//
1809void
1811{
1812 NS_LOG_FUNCTION(this << bridgeNetDevice);
1813 m_bridgesVisited.push_back(bridgeNetDevice);
1814}
1815
1816} // namespace ns3
a virtual net device that bridges multiple LAN segments
virtual Ptr< NetDevice > GetDevice(std::size_t i) const =0
virtual std::size_t GetNDevices() const =0
static uint32_t AllocateRouterId()
Allocate a 32-bit router ID from monotonically increasing counter.
An interface aggregated to a node to provide global routing info.
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.
std::list< Ipv4RoutingTableEntry * >::iterator InjectedRoutesI
Iterator to container of Ipv4RoutingTableEntry.
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.
std::list< Ipv4RoutingTableEntry * >::const_iterator InjectedRoutesCI
Const Iterator to container of Ipv4RoutingTableEntry.
void SetRoutingProtocol(Ptr< Ipv4GlobalRouting > routing)
Set the specific Global Routing Protocol to be used.
Ptr< NetDevice > GetAdjacent(Ptr< NetDevice > nd, Ptr< Channel > ch) const
Link through the given channel and find the net device that's on the other end.
std::vector< Ptr< BridgeNetDevice > > m_bridgesVisited
Container of bridges visited.
void ProcessPointToPointLink(Ptr< NetDevice > ndLocal, GlobalRoutingLSA *pLSA)
Process a point to point link.
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:43
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:79
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:258
uint16_t GetPrefixLength() const
uint32_t Get() const
Get the host-order 32-bit IP mask.
A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting.
static Ipv4RoutingTableEntry CreateNetworkRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
uint32_t GetNDevices() const
Definition: node.cc:162
uint32_t GetId() const
Definition: node.cc:117
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:152
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
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#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:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129