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