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