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