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