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