A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
nix-vector-routing.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 The Georgia Institute of Technology
3 * Copyright (c) 2021 NITK Surathkal
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * This file is adapted from the old ipv4-nix-vector-routing.cc.
19 *
20 * Authors: Josh Pelkey <jpelkey@gatech.edu>
21 *
22 * Modified by: Ameya Deshpande <ameyanrd@outlook.com>
23 */
24
25#include "nix-vector-routing.h"
26
27#include "ns3/abort.h"
28#include "ns3/ipv4-list-routing.h"
29#include "ns3/log.h"
30#include "ns3/loopback-net-device.h"
31#include "ns3/names.h"
32
33#include <iomanip>
34#include <queue>
35
36namespace ns3
37{
38
39NS_LOG_COMPONENT_DEFINE("NixVectorRouting");
40
41NS_OBJECT_TEMPLATE_CLASS_DEFINE(NixVectorRouting, Ipv4RoutingProtocol);
42NS_OBJECT_TEMPLATE_CLASS_DEFINE(NixVectorRouting, Ipv6RoutingProtocol);
43
44template <typename T>
46
47// Epoch starts from one to make it easier to spot an uninitialized NixVector during debug.
48template <typename T>
50
51template <typename T>
53
54template <typename T>
57
58template <typename T>
59TypeId
61{
62 std::string name;
63 if constexpr (std::is_same_v<T, Ipv4RoutingProtocol>)
64 {
65 name = "Ipv4";
66 }
67 else
68 {
69 name = "Ipv6";
70 }
71 static TypeId tid = TypeId(("ns3::" + name + "NixVectorRouting"))
72 .SetParent<T>()
73 .SetGroupName("NixVectorRouting")
74 .template AddConstructor<NixVectorRouting<T>>();
75 return tid;
76}
77
78template <typename T>
80 : m_totalNeighbors(0)
81{
83}
84
85template <typename T>
87{
89}
90
91template <typename T>
92void
94{
95 NS_ASSERT(ipv4);
96 NS_ASSERT(!m_ip);
97 NS_LOG_DEBUG("Created Ipv4NixVectorProtocol");
98
99 m_ip = ipv4;
100}
101
102template <typename T>
103void
105{
106 NS_ASSERT(ipv6);
107 NS_ASSERT(!m_ip);
108 NS_LOG_DEBUG("Created Ipv6NixVectorProtocol");
109
110 m_ip = ipv6;
111}
112
113template <typename T>
114void
116{
117 NS_LOG_FUNCTION(this);
118
119 for (uint32_t i = 0; i < m_ip->GetNInterfaces(); i++)
120 {
121 m_ip->SetForwarding(i, true);
122 }
123
124 T::DoInitialize();
125}
126
127template <typename T>
128void
130{
132
133 m_node = nullptr;
134 m_ip = nullptr;
135
136 T::DoDispose();
137}
138
139template <typename T>
140void
142{
144
145 m_node = node;
146}
147
148template <typename T>
149void
151{
153
155 for (NodeList::Iterator i = NodeList::Begin(); i != listEnd; i++)
156 {
157 Ptr<Node> node = *i;
158 Ptr<NixVectorRouting<T>> rp = node->GetObject<NixVectorRouting>();
159 if (!rp)
160 {
161 continue;
162 }
163 NS_LOG_LOGIC("Flushing Nix caches.");
164 rp->FlushNixCache();
165 rp->FlushIpRouteCache();
166 rp->m_totalNeighbors = 0;
167 }
168
169 // IP address to node mapping is potentially invalid so clear it.
170 // Will be repopulated in lazy evaluation when mapping is needed.
171 g_ipAddressToNodeMap.clear();
172}
173
174template <typename T>
175void
177{
179 m_nixCache.clear();
180}
181
182template <typename T>
183void
185{
187 m_ipRouteCache.clear();
188}
189
190template <typename T>
193{
194 NS_LOG_FUNCTION(this << source << dest << oif);
195
196 Ptr<NixVector> nixVector = Create<NixVector>();
197 nixVector->SetEpoch(g_epoch);
198
199 // not in cache, must build the nix vector
200 // First, we have to figure out the nodes
201 // associated with these IPs
202 Ptr<Node> destNode = GetNodeByIp(dest);
203 if (!destNode)
204 {
205 NS_LOG_ERROR("No routing path exists");
206 return nullptr;
207 }
208
209 // if source == dest, then we have a special case
212 if (source == destNode)
213 {
214 NS_LOG_DEBUG("Do not process packets to self");
215 return nullptr;
216 }
217 else
218 {
219 // otherwise proceed as normal
220 // and build the nix vector
221 std::vector<Ptr<Node>> parentVector;
222
223 if (BFS(NodeList::GetNNodes(), source, destNode, parentVector, oif))
224 {
225 if (BuildNixVector(parentVector, source->GetId(), destNode->GetId(), nixVector))
226 {
227 return nixVector;
228 }
229 else
230 {
231 NS_LOG_ERROR("No routing path exists");
232 return nullptr;
233 }
234 }
235 else
236 {
237 NS_LOG_ERROR("No routing path exists");
238 return nullptr;
239 }
240 }
241}
242
243template <typename T>
245NixVectorRouting<T>::GetNixVectorInCache(const IpAddress& address, bool& foundInCache) const
246{
247 NS_LOG_FUNCTION(this << address);
248
249 CheckCacheStateAndFlush();
250
251 typename NixMap_t::iterator iter = m_nixCache.find(address);
252 if (iter != m_nixCache.end())
253 {
254 NS_LOG_LOGIC("Found Nix-vector in cache.");
255 foundInCache = true;
256 return iter->second;
257 }
258
259 // not in cache
260 foundInCache = false;
261 return nullptr;
262}
263
264template <typename T>
267{
268 NS_LOG_FUNCTION(this << address);
269
270 CheckCacheStateAndFlush();
271
272 typename IpRouteMap_t::iterator iter = m_ipRouteCache.find(address);
273 if (iter != m_ipRouteCache.end())
274 {
275 NS_LOG_LOGIC("Found IpRoute in cache.");
276 return iter->second;
277 }
278
279 // not in cache
280 return nullptr;
281}
282
283template <typename T>
284bool
285NixVectorRouting<T>::BuildNixVector(const std::vector<Ptr<Node>>& parentVector,
286 uint32_t source,
287 uint32_t dest,
288 Ptr<NixVector> nixVector) const
289{
290 NS_LOG_FUNCTION(this << parentVector << source << dest << nixVector);
291
292 if (source == dest)
293 {
294 return true;
295 }
296
297 if (!parentVector.at(dest))
298 {
299 return false;
300 }
301
302 Ptr<Node> parentNode = parentVector.at(dest);
303
304 uint32_t numberOfDevices = parentNode->GetNDevices();
305 uint32_t destId = 0;
306 uint32_t totalNeighbors = 0;
307
308 // scan through the net devices on the T node
309 // and then look at the nodes adjacent to them
310 for (uint32_t i = 0; i < numberOfDevices; i++)
311 {
312 // Get a net device from the node
313 // as well as the channel, and figure
314 // out the adjacent net devices
315 Ptr<NetDevice> localNetDevice = parentNode->GetDevice(i);
316 if (localNetDevice->IsBridge())
317 {
318 continue;
319 }
320 Ptr<Channel> channel = localNetDevice->GetChannel();
321 if (!channel)
322 {
323 continue;
324 }
325
326 // this function takes in the local net dev, and channel, and
327 // writes to the netDeviceContainer the adjacent net devs
328 NetDeviceContainer netDeviceContainer;
329 GetAdjacentNetDevices(localNetDevice, channel, netDeviceContainer);
330
331 // Finally we can get the adjacent nodes
332 // and scan through them. If we find the
333 // node that matches "dest" then we can add
334 // the index to the nix vector.
335 // the index corresponds to the neighbor index
336 uint32_t offset = 0;
337 for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin();
338 iter != netDeviceContainer.End();
339 iter++)
340 {
341 Ptr<Node> remoteNode = (*iter)->GetNode();
342
343 if (remoteNode->GetId() == dest)
344 {
345 destId = totalNeighbors + offset;
346 }
347 offset += 1;
348 }
349
350 totalNeighbors += netDeviceContainer.GetN();
351 }
352 NS_LOG_LOGIC("Adding Nix: " << destId << " with " << nixVector->BitCount(totalNeighbors)
353 << " bits, for node " << parentNode->GetId());
354 nixVector->AddNeighborIndex(destId, nixVector->BitCount(totalNeighbors));
355
356 // recurse through T vector, grabbing the path
357 // and building the nix vector
358 BuildNixVector(parentVector, source, (parentVector.at(dest))->GetId(), nixVector);
359 return true;
360}
361
362template <typename T>
363void
365 Ptr<Channel> channel,
366 NetDeviceContainer& netDeviceContainer) const
367{
368 NS_LOG_FUNCTION(this << netDevice << channel);
369
370 Ptr<IpInterface> netDeviceInterface = GetInterfaceByNetDevice(netDevice);
371 if (!netDeviceInterface || !netDeviceInterface->IsUp())
372 {
373 NS_LOG_LOGIC("IpInterface either doesn't exist or is down");
374 return;
375 }
376
377 uint32_t netDeviceAddresses = netDeviceInterface->GetNAddresses();
378
379 for (std::size_t i = 0; i < channel->GetNDevices(); i++)
380 {
381 Ptr<NetDevice> remoteDevice = channel->GetDevice(i);
382 if (remoteDevice != netDevice)
383 {
384 // Compare if the remoteDevice shares a common subnet with remoteDevice
385 Ptr<IpInterface> remoteDeviceInterface = GetInterfaceByNetDevice(remoteDevice);
386 if (!remoteDeviceInterface || !remoteDeviceInterface->IsUp())
387 {
388 NS_LOG_LOGIC("IpInterface either doesn't exist or is down");
389 continue;
390 }
391
392 uint32_t remoteDeviceAddresses = remoteDeviceInterface->GetNAddresses();
393 bool commonSubnetFound = false;
394
395 for (uint32_t j = 0; j < netDeviceAddresses; ++j)
396 {
397 IpInterfaceAddress netDeviceIfAddr = netDeviceInterface->GetAddress(j);
398 if constexpr (!IsIpv4)
399 {
400 if (netDeviceIfAddr.GetScope() == Ipv6InterfaceAddress::LINKLOCAL)
401 {
402 continue;
403 }
404 }
405 for (uint32_t k = 0; k < remoteDeviceAddresses; ++k)
406 {
407 IpInterfaceAddress remoteDeviceIfAddr = remoteDeviceInterface->GetAddress(k);
408 if constexpr (!IsIpv4)
409 {
410 if (remoteDeviceIfAddr.GetScope() == Ipv6InterfaceAddress::LINKLOCAL)
411 {
412 continue;
413 }
414 }
415 if (netDeviceIfAddr.IsInSameSubnet(remoteDeviceIfAddr.GetAddress()))
416 {
417 commonSubnetFound = true;
418 break;
419 }
420 }
421
422 if (commonSubnetFound)
423 {
424 break;
425 }
426 }
427
428 if (!commonSubnetFound)
429 {
430 continue;
431 }
432
433 Ptr<BridgeNetDevice> bd = NetDeviceIsBridged(remoteDevice);
434 // we have a bridged device, we need to add all
435 // bridged devices
436 if (bd)
437 {
438 NS_LOG_LOGIC("Looking through bridge ports of bridge net device " << bd);
439 for (uint32_t j = 0; j < bd->GetNBridgePorts(); ++j)
440 {
441 Ptr<NetDevice> ndBridged = bd->GetBridgePort(j);
442 if (ndBridged == remoteDevice)
443 {
444 NS_LOG_LOGIC("That bridge port is me, don't walk backward");
445 continue;
446 }
447 Ptr<Channel> chBridged = ndBridged->GetChannel();
448 if (!chBridged)
449 {
450 continue;
451 }
452 GetAdjacentNetDevices(ndBridged, chBridged, netDeviceContainer);
453 }
454 }
455 else
456 {
457 netDeviceContainer.Add(channel->GetDevice(i));
458 }
459 }
460 }
461}
462
463template <typename T>
464void
466{
468
469 for (NodeList::Iterator it = NodeList::Begin(); it != NodeList::End(); ++it)
470 {
471 Ptr<Node> node = *it;
472 Ptr<IpL3Protocol> ip = node->GetObject<IpL3Protocol>();
473
474 if (ip)
475 {
476 uint32_t numberOfDevices = node->GetNDevices();
477
478 for (uint32_t deviceId = 0; deviceId < numberOfDevices; deviceId++)
479 {
480 Ptr<NetDevice> device = node->GetDevice(deviceId);
481
482 // If this is not a loopback device add the IP address to the map
483 if (!DynamicCast<LoopbackNetDevice>(device))
484 {
485 int32_t interfaceIndex = (ip)->GetInterfaceForDevice(node->GetDevice(deviceId));
486 if (interfaceIndex != -1)
487 {
488 g_netdeviceToIpInterfaceMap[device] = (ip)->GetInterface(interfaceIndex);
489
490 uint32_t numberOfAddresses = ip->GetNAddresses(interfaceIndex);
491 for (uint32_t addressIndex = 0; addressIndex < numberOfAddresses;
492 addressIndex++)
493 {
494 IpInterfaceAddress ifAddr =
495 ip->GetAddress(interfaceIndex, addressIndex);
496 IpAddress addr = ifAddr.GetAddress();
497
499 g_ipAddressToNodeMap.count(addr),
500 "Duplicate IP address ("
501 << addr
502 << ") found during NIX Vector map construction for node "
503 << node->GetId());
504
505 NS_LOG_LOGIC("Adding IP address "
506 << addr << " for node " << node->GetId()
507 << " to NIX Vector IP address to node map");
508 g_ipAddressToNodeMap[addr] = node;
509 }
510 }
511 }
512 }
513 }
514 }
515}
516
517template <typename T>
520{
521 NS_LOG_FUNCTION(this << dest);
522
523 // Populate lookup table if is empty.
524 if (g_ipAddressToNodeMap.empty())
525 {
526 BuildIpAddressToNodeMap();
527 }
528
529 Ptr<Node> destNode;
530
531 typename IpAddressToNodeMap::iterator iter = g_ipAddressToNodeMap.find(dest);
532
533 if (iter == g_ipAddressToNodeMap.end())
534 {
535 NS_LOG_ERROR("Couldn't find dest node given the IP" << dest);
536 destNode = nullptr;
537 }
538 else
539 {
540 destNode = iter->second;
541 }
542
543 return destNode;
544}
545
546template <typename T>
549{
550 // Populate lookup table if is empty.
551 if (g_netdeviceToIpInterfaceMap.empty())
552 {
553 BuildIpAddressToNodeMap();
554 }
555
556 Ptr<IpInterface> ipInterface;
557
558 typename NetDeviceToIpInterfaceMap::iterator iter = g_netdeviceToIpInterfaceMap.find(netDevice);
559
560 if (iter == g_netdeviceToIpInterfaceMap.end())
561 {
562 NS_LOG_ERROR("Couldn't find IpInterface node given the NetDevice" << netDevice);
563 ipInterface = nullptr;
564 }
565 else
566 {
567 ipInterface = iter->second;
568 }
569
570 return ipInterface;
571}
572
573template <typename T>
576{
577 NS_LOG_FUNCTION(this << node);
578
579 uint32_t numberOfDevices = node->GetNDevices();
580 uint32_t totalNeighbors = 0;
581
582 // scan through the net devices on the T node
583 // and then look at the nodes adjacent to them
584 for (uint32_t i = 0; i < numberOfDevices; i++)
585 {
586 // Get a net device from the node
587 // as well as the channel, and figure
588 // out the adjacent net devices
589 Ptr<NetDevice> localNetDevice = node->GetDevice(i);
590 Ptr<Channel> channel = localNetDevice->GetChannel();
591 if (!channel)
592 {
593 continue;
594 }
595
596 // this function takes in the local net dev, and channel, and
597 // writes to the netDeviceContainer the adjacent net devs
598 NetDeviceContainer netDeviceContainer;
599 GetAdjacentNetDevices(localNetDevice, channel, netDeviceContainer);
600
601 totalNeighbors += netDeviceContainer.GetN();
602 }
603
604 return totalNeighbors;
605}
606
607template <typename T>
610{
611 NS_LOG_FUNCTION(this << nd);
612
613 Ptr<Node> node = nd->GetNode();
614 uint32_t nDevices = node->GetNDevices();
615
616 //
617 // There is no bit on a net device that says it is being bridged, so we have
618 // to look for bridges on the node to which the device is attached. If we
619 // find a bridge, we need to look through its bridge ports (the devices it
620 // bridges) to see if we find the device in question.
621 //
622 for (uint32_t i = 0; i < nDevices; ++i)
623 {
624 Ptr<NetDevice> ndTest = node->GetDevice(i);
625 NS_LOG_LOGIC("Examine device " << i << " " << ndTest);
626
627 if (ndTest->IsBridge())
628 {
629 NS_LOG_LOGIC("device " << i << " is a bridge net device");
630 Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice>();
632 bnd,
633 "NixVectorRouting::NetDeviceIsBridged (): GetObject for <BridgeNetDevice> failed");
634
635 for (uint32_t j = 0; j < bnd->GetNBridgePorts(); ++j)
636 {
637 NS_LOG_LOGIC("Examine bridge port " << j << " " << bnd->GetBridgePort(j));
638 if (bnd->GetBridgePort(j) == nd)
639 {
640 NS_LOG_LOGIC("Net device " << nd << " is bridged by " << bnd);
641 return bnd;
642 }
643 }
644 }
645 }
646 NS_LOG_LOGIC("Net device " << nd << " is not bridged");
647 return nullptr;
648}
649
650template <typename T>
653 uint32_t nodeIndex,
654 IpAddress& gatewayIp) const
655{
656 NS_LOG_FUNCTION(this << node << nodeIndex << gatewayIp);
657
658 uint32_t numberOfDevices = node->GetNDevices();
659 uint32_t index = 0;
660 uint32_t totalNeighbors = 0;
661
662 // scan through the net devices on the parent node
663 // and then look at the nodes adjacent to them
664 for (uint32_t i = 0; i < numberOfDevices; i++)
665 {
666 // Get a net device from the node
667 // as well as the channel, and figure
668 // out the adjacent net devices
669 Ptr<NetDevice> localNetDevice = node->GetDevice(i);
670 Ptr<Channel> channel = localNetDevice->GetChannel();
671 if (!channel)
672 {
673 continue;
674 }
675
676 // this function takes in the local net dev, and channel, and
677 // writes to the netDeviceContainer the adjacent net devs
678 NetDeviceContainer netDeviceContainer;
679 GetAdjacentNetDevices(localNetDevice, channel, netDeviceContainer);
680
681 // check how many neighbors we have
682 if (nodeIndex < (totalNeighbors + netDeviceContainer.GetN()))
683 {
684 // found the proper net device
685 index = i;
686 Ptr<NetDevice> gatewayDevice = netDeviceContainer.Get(nodeIndex - totalNeighbors);
687 Ptr<IpInterface> gatewayInterface = GetInterfaceByNetDevice(gatewayDevice);
688 IpInterfaceAddress ifAddr = gatewayInterface->GetAddress(0);
689 gatewayIp = ifAddr.GetAddress();
690 break;
691 }
692 totalNeighbors += netDeviceContainer.GetN();
693 }
694
695 return index;
696}
697
698template <typename T>
701 const IpHeader& header,
702 Ptr<NetDevice> oif,
703 Socket::SocketErrno& sockerr)
704{
705 NS_LOG_FUNCTION(this << header << oif);
706
707 Ptr<IpRoute> rtentry;
708 Ptr<NixVector> nixVectorInCache;
709 Ptr<NixVector> nixVectorForPacket;
710
711 CheckCacheStateAndFlush();
712
713 IpAddress destAddress = header.GetDestination();
714
715 NS_LOG_DEBUG("Dest IP from header: " << destAddress);
716
717 if (destAddress.IsLocalhost())
718 {
719 rtentry = Create<IpRoute>();
720 rtentry->SetSource(IpAddress::GetLoopback());
721 rtentry->SetDestination(destAddress);
722 rtentry->SetGateway(IpAddress::GetZero());
723 for (uint32_t i = 0; i < m_ip->GetNInterfaces(); i++)
724 {
725 Ptr<LoopbackNetDevice> loNetDevice =
726 DynamicCast<LoopbackNetDevice>(m_ip->GetNetDevice(i));
727 if (loNetDevice)
728 {
729 rtentry->SetOutputDevice(loNetDevice);
730 break;
731 }
732 }
733 return rtentry;
734 }
735
736 if constexpr (!IsIpv4)
737 {
738 /* when sending on link-local multicast, there have to be interface specified */
739 if (destAddress.IsLinkLocalMulticast())
740 {
742 oif,
743 "Try to send on link-local multicast address, and no interface index is given!");
744 rtentry = Create<IpRoute>();
745 rtentry->SetSource(
746 m_ip->SourceAddressSelection(m_ip->GetInterfaceForDevice(oif), destAddress));
747 rtentry->SetDestination(destAddress);
748 rtentry->SetGateway(Ipv6Address::GetZero());
749 rtentry->SetOutputDevice(oif);
750 return rtentry;
751 }
752 }
753 // Check the Nix cache
754 bool foundInCache = false;
755 nixVectorInCache = GetNixVectorInCache(destAddress, foundInCache);
756
757 // not in cache
758 if (!foundInCache)
759 {
760 NS_LOG_LOGIC("Nix-vector not in cache, build: ");
761 // Build the nix-vector, given this node and the
762 // dest IP address
763 nixVectorInCache = GetNixVector(m_node, destAddress, oif);
764 if (nixVectorInCache)
765 {
766 // cache it
767 m_nixCache.insert(typename NixMap_t::value_type(destAddress, nixVectorInCache));
768 }
769 }
770
771 // path exists
772 if (nixVectorInCache)
773 {
774 NS_LOG_LOGIC("Nix-vector contents: " << *nixVectorInCache);
775
776 // create a new nix vector to be used,
777 // we want to keep the cached version clean
778 nixVectorForPacket = nixVectorInCache->Copy();
779
780 // Get the interface number that we go out of, by extracting
781 // from the nix-vector
782 if (m_totalNeighbors == 0)
783 {
784 m_totalNeighbors = FindTotalNeighbors(m_node);
785 }
786
787 // Get the interface number that we go out of, by extracting
788 // from the nix-vector
789 uint32_t numberOfBits = nixVectorForPacket->BitCount(m_totalNeighbors);
790 uint32_t nodeIndex = nixVectorForPacket->ExtractNeighborIndex(numberOfBits);
791
792 // Search here in a cache for this node index
793 // and look for a IpRoute
794 rtentry = GetIpRouteInCache(destAddress);
795
796 if (!rtentry || !(rtentry->GetOutputDevice() == oif))
797 {
798 // not in cache or a different specified output
799 // device is to be used
800
801 // first, make sure we erase existing (incorrect)
802 // rtentry from the map
803 if (rtentry)
804 {
805 m_ipRouteCache.erase(destAddress);
806 }
807
808 NS_LOG_LOGIC("IpRoute not in cache, build: ");
809 IpAddress gatewayIp;
810 uint32_t index = FindNetDeviceForNixIndex(m_node, nodeIndex, gatewayIp);
811 int32_t interfaceIndex = 0;
812
813 if (!oif)
814 {
815 interfaceIndex = (m_ip)->GetInterfaceForDevice(m_node->GetDevice(index));
816 }
817 else
818 {
819 interfaceIndex = (m_ip)->GetInterfaceForDevice(oif);
820 }
821
822 NS_ASSERT_MSG(interfaceIndex != -1, "Interface index not found for device");
823
824 IpAddress sourceIPAddr = m_ip->SourceAddressSelection(interfaceIndex, destAddress);
825
826 // start filling in the IpRoute info
827 rtentry = Create<IpRoute>();
828 rtentry->SetSource(sourceIPAddr);
829
830 rtentry->SetGateway(gatewayIp);
831 rtentry->SetDestination(destAddress);
832
833 if (!oif)
834 {
835 rtentry->SetOutputDevice(m_ip->GetNetDevice(interfaceIndex));
836 }
837 else
838 {
839 rtentry->SetOutputDevice(oif);
840 }
841
842 sockerr = Socket::ERROR_NOTERROR;
843
844 // add rtentry to cache
845 m_ipRouteCache.insert(typename IpRouteMap_t::value_type(destAddress, rtentry));
846 }
847
848 NS_LOG_LOGIC("Nix-vector contents: " << *nixVectorInCache << " : Remaining bits: "
849 << nixVectorForPacket->GetRemainingBits());
850
851 // Add nix-vector in the packet class
852 // make sure the packet exists first
853 if (p)
854 {
855 NS_LOG_LOGIC("Adding Nix-vector to packet: " << *nixVectorForPacket);
856 p->SetNixVector(nixVectorForPacket);
857 }
858 }
859 else // path doesn't exist
860 {
861 NS_LOG_ERROR("No path to the dest: " << destAddress);
863 }
864
865 return rtentry;
866}
867
868template <typename T>
869bool
871 const IpHeader& header,
873 const UnicastForwardCallback& ucb,
874 const MulticastForwardCallback& mcb,
875 const LocalDeliverCallback& lcb,
876 const ErrorCallback& ecb)
877{
878 NS_LOG_FUNCTION(this << p << header << header.GetSource() << header.GetDestination() << idev);
879
880 CheckCacheStateAndFlush();
881
882 NS_ASSERT(m_ip);
883 // Check if input device supports IP
884 NS_ASSERT(m_ip->GetInterfaceForDevice(idev) >= 0);
885 uint32_t iif = m_ip->GetInterfaceForDevice(idev);
886 // Check if input device supports IP
887 NS_ASSERT(iif >= 0);
888
889 IpAddress destAddress = header.GetDestination();
890
891 if constexpr (IsIpv4)
892 {
893 // Local delivery
894 if (m_ip->IsDestinationAddress(destAddress, iif))
895 {
896 if (!lcb.IsNull())
897 {
898 NS_LOG_LOGIC("Local delivery to " << destAddress);
899 p->SetNixVector(nullptr);
900 lcb(p, header, iif);
901 return true;
902 }
903 else
904 {
905 // The local delivery callback is null. This may be a multicast
906 // or broadcast packet, so return false so that another
907 // multicast routing protocol can handle it. It should be possible
908 // to extend this to explicitly check whether it is a unicast
909 // packet, and invoke the error callback if so
910 return false;
911 }
912 }
913 }
914 else
915 {
916 if (destAddress.IsMulticast())
917 {
918 NS_LOG_LOGIC("Multicast route not supported by Nix-Vector routing " << destAddress);
919 return false; // Let other routing protocols try to handle this
920 }
921
922 // Check if input device supports IP forwarding
923 if (m_ip->IsForwarding(iif) == false)
924 {
925 NS_LOG_LOGIC("Forwarding disabled for this interface");
926 if (!ecb.IsNull())
927 {
928 ecb(p, header, Socket::ERROR_NOROUTETOHOST);
929 }
930 return true;
931 }
932 }
933
934 Ptr<IpRoute> rtentry;
935
936 // Get the nix-vector from the packet
937 Ptr<NixVector> nixVector = p->GetNixVector();
938
939 // If nixVector isn't in packet, something went wrong
940 NS_ASSERT(nixVector);
941
942 if (nixVector->GetEpoch() != g_epoch)
943 {
944 NS_LOG_LOGIC("NixVector epoch mismatch (" << nixVector->GetEpoch() << " Vs " << g_epoch
945 << ") - rebuilding it");
946 nixVector = GetNixVector(m_node, destAddress, nullptr);
947 p->SetNixVector(nixVector);
948 }
949
950 // Get the interface number that we go out of, by extracting
951 // from the nix-vector
952 if (m_totalNeighbors == 0)
953 {
954 m_totalNeighbors = FindTotalNeighbors(m_node);
955 }
956 uint32_t numberOfBits = nixVector->BitCount(m_totalNeighbors);
957 uint32_t nodeIndex = nixVector->ExtractNeighborIndex(numberOfBits);
958
959 rtentry = GetIpRouteInCache(destAddress);
960 // not in cache
961 if (!rtentry)
962 {
963 NS_LOG_LOGIC("IpRoute not in cache, build: ");
964 IpAddress gatewayIp;
965 uint32_t index = FindNetDeviceForNixIndex(m_node, nodeIndex, gatewayIp);
966 uint32_t interfaceIndex = (m_ip)->GetInterfaceForDevice(m_node->GetDevice(index));
967 IpInterfaceAddress ifAddr = m_ip->GetAddress(interfaceIndex, 0);
968
969 // start filling in the IpRoute info
970 rtentry = Create<IpRoute>();
971 rtentry->SetSource(ifAddr.GetAddress());
972
973 rtentry->SetGateway(gatewayIp);
974 rtentry->SetDestination(destAddress);
975 rtentry->SetOutputDevice(m_ip->GetNetDevice(interfaceIndex));
976
977 // add rtentry to cache
978 m_ipRouteCache.insert(typename IpRouteMap_t::value_type(destAddress, rtentry));
979 }
980
981 NS_LOG_LOGIC("At Node " << m_node->GetId() << ", Extracting " << numberOfBits
982 << " bits from Nix-vector: " << nixVector << " : " << *nixVector);
983
984 // call the unicast callback
985 // local deliver is handled by Ipv4StaticRoutingImpl
986 // so this code is never even called if the packet is
987 // destined for this node.
988 if constexpr (IsIpv4)
989 {
990 ucb(rtentry, p, header);
991 }
992 else
993 {
994 ucb(idev, rtentry, p, header);
995 }
996
997 return true;
998}
999
1000template <typename T>
1001void
1003{
1005
1006 CheckCacheStateAndFlush();
1007
1008 std::ostream* os = stream->GetStream();
1009 // Copy the current ostream state
1010 std::ios oldState(nullptr);
1011 oldState.copyfmt(*os);
1012
1013 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
1014
1015 *os << "Node: " << m_ip->template GetObject<Node>()->GetId() << ", Time: " << Now().As(unit)
1016 << ", Local time: " << m_ip->template GetObject<Node>()->GetLocalTime().As(unit)
1017 << ", Nix Routing" << std::endl;
1018
1019 *os << "NixCache:" << std::endl;
1020 if (m_nixCache.size() > 0)
1021 {
1022 *os << std::setw(30) << "Destination";
1023 *os << "NixVector" << std::endl;
1024 for (typename NixMap_t::const_iterator it = m_nixCache.begin(); it != m_nixCache.end();
1025 it++)
1026 {
1027 std::ostringstream dest;
1028 dest << it->first;
1029 *os << std::setw(30) << dest.str();
1030 if (it->second)
1031 {
1032 *os << *(it->second) << std::endl;
1033 }
1034 else
1035 {
1036 *os << "-" << std::endl;
1037 }
1038 }
1039 }
1040
1041 *os << "IpRouteCache:" << std::endl;
1042 if (m_ipRouteCache.size() > 0)
1043 {
1044 *os << std::setw(30) << "Destination";
1045 *os << std::setw(30) << "Gateway";
1046 *os << std::setw(30) << "Source";
1047 *os << "OutputDevice" << std::endl;
1048 for (typename IpRouteMap_t::const_iterator it = m_ipRouteCache.begin();
1049 it != m_ipRouteCache.end();
1050 it++)
1051 {
1052 std::ostringstream dest;
1053 std::ostringstream gw;
1054 std::ostringstream src;
1055 dest << it->second->GetDestination();
1056 *os << std::setw(30) << dest.str();
1057 gw << it->second->GetGateway();
1058 *os << std::setw(30) << gw.str();
1059 src << it->second->GetSource();
1060 *os << std::setw(30) << src.str();
1061 *os << " ";
1062 if (Names::FindName(it->second->GetOutputDevice()) != "")
1063 {
1064 *os << Names::FindName(it->second->GetOutputDevice());
1065 }
1066 else
1067 {
1068 *os << it->second->GetOutputDevice()->GetIfIndex();
1069 }
1070 *os << std::endl;
1071 }
1072 }
1073 *os << std::endl;
1074 // Restore the previous ostream state
1075 (*os).copyfmt(oldState);
1076}
1077
1078// virtual functions from Ipv4RoutingProtocol
1079template <typename T>
1080void
1082{
1083 g_isCacheDirty = true;
1084}
1085
1086template <typename T>
1087void
1089{
1090 g_isCacheDirty = true;
1091}
1092
1093template <typename T>
1094void
1096{
1097 g_isCacheDirty = true;
1098}
1099
1100template <typename T>
1101void
1103{
1104 g_isCacheDirty = true;
1105}
1106
1107template <typename T>
1108void
1110 Ipv6Prefix mask,
1111 IpAddress nextHop,
1112 uint32_t interface,
1113 IpAddress prefixToUse)
1114{
1115 g_isCacheDirty = true;
1116}
1117
1118template <typename T>
1119void
1121 Ipv6Prefix mask,
1122 IpAddress nextHop,
1123 uint32_t interface,
1124 IpAddress prefixToUse)
1125{
1126 g_isCacheDirty = true;
1127}
1128
1129template <typename T>
1130bool
1132 Ptr<Node> source,
1133 Ptr<Node> dest,
1134 std::vector<Ptr<Node>>& parentVector,
1135 Ptr<NetDevice> oif) const
1136{
1137 NS_LOG_FUNCTION(this << numberOfNodes << source << dest << parentVector << oif);
1138
1139 NS_LOG_LOGIC("Going from Node " << source->GetId() << " to Node " << dest->GetId());
1140 std::queue<Ptr<Node>> greyNodeList; // discovered nodes with unexplored children
1141
1142 // reset the parent vector
1143 parentVector.assign(numberOfNodes, nullptr); // initialize to 0
1144
1145 // Add the source node to the queue, set its parent to itself
1146 greyNodeList.push(source);
1147 parentVector.at(source->GetId()) = source;
1148
1149 // BFS loop
1150 while (!greyNodeList.empty())
1151 {
1152 Ptr<Node> currNode = greyNodeList.front();
1153 Ptr<IpL3Protocol> ip = currNode->GetObject<IpL3Protocol>();
1154
1155 if (currNode == dest)
1156 {
1157 NS_LOG_LOGIC("Made it to Node " << currNode->GetId());
1158 return true;
1159 }
1160
1161 // if this is the first iteration of the loop and a
1162 // specific output interface was given, make sure
1163 // we go this way
1164 if (currNode == source && oif)
1165 {
1166 // make sure that we can go this way
1167 if (ip)
1168 {
1169 uint32_t interfaceIndex = (ip)->GetInterfaceForDevice(oif);
1170 if (!(ip->IsUp(interfaceIndex)))
1171 {
1172 NS_LOG_LOGIC("IpInterface is down");
1173 return false;
1174 }
1175 }
1176 if (!(oif->IsLinkUp()))
1177 {
1178 NS_LOG_LOGIC("Link is down.");
1179 return false;
1180 }
1181 Ptr<Channel> channel = oif->GetChannel();
1182 if (!channel)
1183 {
1184 return false;
1185 }
1186
1187 // this function takes in the local net dev, and channel, and
1188 // writes to the netDeviceContainer the adjacent net devs
1189 NetDeviceContainer netDeviceContainer;
1190 GetAdjacentNetDevices(oif, channel, netDeviceContainer);
1191
1192 // Finally we can get the adjacent nodes
1193 // and scan through them. We push them
1194 // to the greyNode queue, if they aren't
1195 // already there.
1196 for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin();
1197 iter != netDeviceContainer.End();
1198 iter++)
1199 {
1200 Ptr<Node> remoteNode = (*iter)->GetNode();
1201 Ptr<IpInterface> remoteIpInterface = GetInterfaceByNetDevice(*iter);
1202 if (!remoteIpInterface || !(remoteIpInterface->IsUp()))
1203 {
1204 NS_LOG_LOGIC("IpInterface either doesn't exist or is down");
1205 continue;
1206 }
1207
1208 // check to see if this node has been pushed before
1209 // by checking to see if it has a parent
1210 // if it doesn't (null or 0), then set its parent and
1211 // push to the queue
1212 if (!parentVector.at(remoteNode->GetId()))
1213 {
1214 parentVector.at(remoteNode->GetId()) = currNode;
1215 greyNodeList.push(remoteNode);
1216 }
1217 }
1218 }
1219 else
1220 {
1221 // Iterate over the current node's adjacent vertices
1222 // and push them into the queue
1223 for (uint32_t i = 0; i < (currNode->GetNDevices()); i++)
1224 {
1225 // Get a net device from the node
1226 // as well as the channel, and figure
1227 // out the adjacent net device
1228 Ptr<NetDevice> localNetDevice = currNode->GetDevice(i);
1229
1230 // make sure that we can go this way
1231 if (ip)
1232 {
1233 uint32_t interfaceIndex = (ip)->GetInterfaceForDevice(currNode->GetDevice(i));
1234 if (!(ip->IsUp(interfaceIndex)))
1235 {
1236 NS_LOG_LOGIC("IpInterface is down");
1237 continue;
1238 }
1239 }
1240 if (!(localNetDevice->IsLinkUp()))
1241 {
1242 NS_LOG_LOGIC("Link is down.");
1243 continue;
1244 }
1245 Ptr<Channel> channel = localNetDevice->GetChannel();
1246 if (!channel)
1247 {
1248 continue;
1249 }
1250
1251 // this function takes in the local net dev, and channel, and
1252 // writes to the netDeviceContainer the adjacent net devs
1253 NetDeviceContainer netDeviceContainer;
1254 GetAdjacentNetDevices(localNetDevice, channel, netDeviceContainer);
1255
1256 // Finally we can get the adjacent nodes
1257 // and scan through them. We push them
1258 // to the greyNode queue, if they aren't
1259 // already there.
1260 for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin();
1261 iter != netDeviceContainer.End();
1262 iter++)
1263 {
1264 Ptr<Node> remoteNode = (*iter)->GetNode();
1265 Ptr<IpInterface> remoteIpInterface = GetInterfaceByNetDevice(*iter);
1266 if (!remoteIpInterface || !(remoteIpInterface->IsUp()))
1267 {
1268 NS_LOG_LOGIC("IpInterface either doesn't exist or is down");
1269 continue;
1270 }
1271
1272 // check to see if this node has been pushed before
1273 // by checking to see if it has a parent
1274 // if it doesn't (null or 0), then set its parent and
1275 // push to the queue
1276 if (!parentVector.at(remoteNode->GetId()))
1277 {
1278 parentVector.at(remoteNode->GetId()) = currNode;
1279 greyNodeList.push(remoteNode);
1280 }
1281 }
1282 }
1283 }
1284
1285 // Pop off the head grey node. We have all its children.
1286 // It is now black.
1287 greyNodeList.pop();
1288 }
1289
1290 // Didn't find the dest...
1291 return false;
1292}
1293
1294template <typename T>
1295void
1297 IpAddress dest,
1299 Time::Unit unit) const
1300{
1301 NS_LOG_FUNCTION(this << source << dest);
1302
1303 Ptr<NixVector> nixVectorInCache;
1304 Ptr<NixVector> nixVector;
1305 Ptr<IpRoute> rtentry;
1306
1307 CheckCacheStateAndFlush();
1308
1309 Ptr<Node> destNode = GetNodeByIp(dest);
1310 if (!destNode)
1311 {
1312 NS_LOG_ERROR("No routing path exists");
1313 return;
1314 }
1315
1316 std::ostream* os = stream->GetStream();
1317 // Copy the current ostream state
1318 std::ios oldState(nullptr);
1319 oldState.copyfmt(*os);
1320
1321 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
1322 *os << "Time: " << Now().As(unit) << ", Nix Routing" << std::endl;
1323 *os << "Route path from ";
1324 *os << "Node " << source->GetId() << " to Node " << destNode->GetId() << ", ";
1325 *os << "Nix Vector: ";
1326
1327 // Check the Nix cache
1328 bool foundInCache = true;
1329 nixVectorInCache = GetNixVectorInCache(dest, foundInCache);
1330
1331 // not in cache
1332 if (!foundInCache)
1333 {
1334 NS_LOG_LOGIC("Nix-vector not in cache, build: ");
1335 // Build the nix-vector, given the source node and the
1336 // dest IP address
1337 nixVectorInCache = GetNixVector(source, dest, nullptr);
1338 }
1339
1340 if (nixVectorInCache || (!nixVectorInCache && source == destNode))
1341 {
1342 Ptr<Node> curr = source;
1343 uint32_t totalNeighbors = 0;
1344
1345 if (nixVectorInCache)
1346 {
1347 // Make a NixVector copy to work with. This is because
1348 // we don't want to extract the bits from nixVectorInCache
1349 // which is stored in the m_nixCache.
1350 nixVector = nixVectorInCache->Copy();
1351
1352 *os << *nixVector;
1353 }
1354 *os << std::endl;
1355
1356 if (source == destNode)
1357 {
1358 std::ostringstream addr;
1359 std::ostringstream node;
1360 addr << dest;
1361 node << "(Node " << destNode->GetId() << ")";
1362 *os << std::setw(25) << addr.str();
1363 *os << std::setw(10) << node.str();
1364 *os << "----> ";
1365 *os << std::setw(25) << addr.str();
1366 *os << node.str() << std::endl;
1367 }
1368
1369 while (curr != destNode)
1370 {
1371 totalNeighbors = FindTotalNeighbors(curr);
1372 // Get the number of bits required
1373 // to represent all the neighbors
1374 uint32_t numberOfBits = nixVector->BitCount(totalNeighbors);
1375 // Get the nixIndex
1376 uint32_t nixIndex = nixVector->ExtractNeighborIndex(numberOfBits);
1377 // gatewayIP is the IP of next
1378 // node on channel found from nixIndex
1379 IpAddress gatewayIp;
1380 // Get the Net Device index from the nixIndex
1381 uint32_t netDeviceIndex = FindNetDeviceForNixIndex(curr, nixIndex, gatewayIp);
1382 // Get the interfaceIndex with the help of netDeviceIndex.
1383 // It will be used to get the IP address on interfaceIndex
1384 // interface of 'curr' node.
1385 Ptr<IpL3Protocol> ip = curr->GetObject<IpL3Protocol>();
1386 Ptr<NetDevice> outDevice = curr->GetDevice(netDeviceIndex);
1387 uint32_t interfaceIndex = ip->GetInterfaceForDevice(outDevice);
1388 IpAddress sourceIPAddr;
1389 if (curr == source)
1390 {
1391 sourceIPAddr = ip->SourceAddressSelection(interfaceIndex, dest);
1392 }
1393 else
1394 {
1395 // We use the first address because it's indifferent which one
1396 // we use to identify intermediate routers
1397 sourceIPAddr = ip->GetAddress(interfaceIndex, 0).GetAddress();
1398 }
1399
1400 std::ostringstream currAddr;
1401 std::ostringstream currNode;
1402 std::ostringstream nextAddr;
1403 std::ostringstream nextNode;
1404 currAddr << sourceIPAddr;
1405 currNode << "(Node " << curr->GetId() << ")";
1406 *os << std::setw(25) << currAddr.str();
1407 *os << std::setw(10) << currNode.str();
1408 // Replace curr with the next node
1409 curr = GetNodeByIp(gatewayIp);
1410 nextAddr << ((curr == destNode) ? dest : gatewayIp);
1411 nextNode << "(Node " << curr->GetId() << ")";
1412 *os << "----> ";
1413 *os << std::setw(25) << nextAddr.str();
1414 *os << nextNode.str() << std::endl;
1415 }
1416 *os << std::endl;
1417 }
1418 else
1419 {
1420 *os << ")" << std::endl;
1421 // No Route exists
1422 *os << "There does not exist a path from Node " << source->GetId() << " to Node "
1423 << destNode->GetId() << "." << std::endl;
1424 }
1425 // Restore the previous ostream state
1426 (*os).copyfmt(oldState);
1427}
1428
1429template <typename T>
1430void
1432{
1433 if (g_isCacheDirty)
1434 {
1435 FlushGlobalNixRoutingCache();
1436 g_epoch++;
1437 g_isCacheDirty = false;
1438 }
1439}
1440
1441/* Public template function declarations */
1447 Ptr<Node> source,
1448 IpAddress dest,
1450 Time::Unit unit) const;
1452 Ptr<Node> source,
1453 IpAddress dest,
1455 Time::Unit unit) const;
1456
1457} // namespace ns3
a virtual net device that bridges multiple LAN segments
Callback template class.
Definition: callback.h:438
bool IsNull() const
Check for null implementation.
Definition: callback.h:567
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
@ LINKLOCAL
Link-local address (fe80::/64)
Describes an IPv6 prefix.
Definition: ipv6-address.h:455
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Definition: names.cc:830
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
Iterator Begin() const
Get an iterator which refers to the first NetDevice in the container.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Iterator End() const
Get an iterator which indicates past-the-last NetDevice in the container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Nix-vector routing protocol.
void PrintRoutingPath(Ptr< Node > source, IpAddress dest, Ptr< OutputStreamWrapper > stream, Time::Unit unit) const
Print the Routing Path according to Nix Routing.
void BuildIpAddressToNodeMap() const
Build map from IP Address to Node for faster lookup.
Ptr< IpRoute > GetIpRouteInCache(IpAddress address)
Checks the cache based on dest IP for the IpRoute.
virtual void NotifyRemoveRoute(IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse=IpAddress::GetZero())
Notify route removing.
virtual void NotifyAddRoute(IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse=IpAddress::GetZero())
Notify a new route.
typename std::conditional_t< IsIpv4, Ipv4InterfaceAddress, Ipv6InterfaceAddress > IpInterfaceAddress
Alias for Ipv4InterfaceAddress and Ipv6InterfaceAddress classes.
bool BFS(uint32_t numberOfNodes, Ptr< Node > source, Ptr< Node > dest, std::vector< Ptr< Node > > &parentVector, Ptr< NetDevice > oif) const
Breadth first search algorithm.
static uint32_t g_epoch
Nix Epoch, incremented each time a flush is performed.
virtual void NotifyInterfaceUp(uint32_t interface)
void GetAdjacentNetDevices(Ptr< NetDevice > netDevice, Ptr< Channel > channel, NetDeviceContainer &netDeviceContainer) const
Given a net-device returns all the adjacent net-devices, essentially getting the neighbors on that ch...
std::conditional_t< IsIpv4, UnicastForwardCallbackv4, UnicastForwardCallbackv6 > UnicastForwardCallback
Callback for unicast packets to be forwarded.
virtual void NotifyInterfaceDown(uint32_t interface)
typename std::conditional_t< IsIpv4, Ipv4Address, Ipv6Address > IpAddress
Alias for Ipv4Address and Ipv6Address classes.
static IpAddressToNodeMap g_ipAddressToNodeMap
Address to node map.
void FlushGlobalNixRoutingCache() const
Called when run-time link topology change occurs which iterates through the node list and flushes any...
virtual void SetIpv6(Ptr< Ip > ipv6)
Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol.
virtual Ptr< IpRoute > RouteOutput(Ptr< Packet > p, const IpHeader &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
virtual void SetIpv4(Ptr< Ip > ipv4)
Typically, invoked directly or indirectly from ns3::Ipv4::SetRoutingProtocol.
Ptr< IpInterface > GetInterfaceByNetDevice(Ptr< NetDevice > netDevice) const
Iterates through the node list and finds the one corresponding to the given IpAddress.
uint32_t FindTotalNeighbors(Ptr< Node > node) const
Simply iterates through the nodes net-devices and determines how many neighbors the node has.
virtual void NotifyAddAddress(uint32_t interface, IpInterfaceAddress address)
std::conditional_t< IsIpv4, MulticastForwardCallbackv4, MulticastForwardCallbackv6 > MulticastForwardCallback
Callback for multicast packets to be forwarded.
void FlushIpRouteCache() const
Flushes the cache which stores the Ip route based on the destination IP.
virtual bool RouteInput(Ptr< const Packet > p, const IpHeader &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb)
Route an input packet (to be forwarded or locally delivered)
Ptr< NixVector > GetNixVector(Ptr< Node > source, IpAddress dest, Ptr< NetDevice > oif) const
Takes in the source node and dest IP and calls GetNodeByIp, BFS, accounting for any output interface ...
typename std::conditional_t< IsIpv4, Ipv4Header, Ipv6Header > IpHeader
Alias for Ipv4Header and Ipv6Header classes.
bool BuildNixVector(const std::vector< Ptr< Node > > &parentVector, uint32_t source, uint32_t dest, Ptr< NixVector > nixVector) const
Recurses the T vector, created by BFS and actually builds the nixvector.
Ptr< NixVector > GetNixVectorInCache(const IpAddress &address, bool &foundInCache) const
Checks the cache based on dest IP for the nix-vector.
uint32_t FindNetDeviceForNixIndex(Ptr< Node > node, uint32_t nodeIndex, IpAddress &gatewayIp) const
Nix index is with respect to the neighbors.
static NetDeviceToIpInterfaceMap g_netdeviceToIpInterfaceMap
NetDevice pointer to IpInterface pointer map.
void SetNode(Ptr< Node > node)
Set the Node pointer of the node for which this routing protocol is to be placed.
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print the Routing Table entries.
typename std::conditional_t< IsIpv4, Ipv4L3Protocol, Ipv6L3Protocol > IpL3Protocol
Alias for Ipv4L3Protocol and Ipv4L3Protocol classes.
virtual void NotifyRemoveAddress(uint32_t interface, IpInterfaceAddress address)
static TypeId GetTypeId()
The Interface ID of the Global Router interface.
static bool g_isCacheDirty
Flag to mark when caches are dirty and need to be flushed.
void CheckCacheStateAndFlush() const
Flushes routing caches if required.
std::unordered_map< IpAddress, ns3::Ptr< ns3::Node >, IpAddressHash > IpAddressToNodeMap
Mapping of IP address to ns-3 node.
std::unordered_map< Ptr< NetDevice >, Ptr< IpInterface > > NetDeviceToIpInterfaceMap
Mapping of Ptr<NetDevice> to Ptr<IpInterface>.
Ptr< BridgeNetDevice > NetDeviceIsBridged(Ptr< NetDevice > nd) const
Determine if the NetDevice is bridged.
void FlushNixCache() const
Flushes the cache which stores nix-vector based on destination IP.
Ptr< Node > GetNodeByIp(IpAddress dest) const
Iterates through the node list and finds the one corresponding to the given IpAddress.
static Iterator Begin()
Definition: node-list.cc:237
static uint32_t GetNNodes()
Definition: node-list.cc:258
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
Definition: node-list.h:44
static Iterator End()
Definition: node-list.cc:244
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
@ ERROR_NOROUTETOHOST
Definition: socket.h:95
@ ERROR_NOTERROR
Definition: socket.h:85
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:111
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
#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_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#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_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_TEMPLATE_CLASS_DEFINE(type, param)
Explicitly instantiate a template class with one template parameter and register the resulting instan...
Definition: object-base.h:78
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Every class exported by the ns3 library is enclosed in the ns3 namespace.