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 
37 namespace ns3 {
38 
39 NS_LOG_COMPONENT_DEFINE ("NixVectorRouting");
40 
41 NS_OBJECT_TEMPLATE_CLASS_DEFINE (NixVectorRouting, Ipv4RoutingProtocol);
42 NS_OBJECT_TEMPLATE_CLASS_DEFINE (NixVectorRouting, Ipv6RoutingProtocol);
43 
44 template <typename T>
46 
47 // Epoch starts from one to make it easier to spot an uninitialized NixVector during debug.
48 template <typename T>
49 uint32_t NixVectorRouting<T>::g_epoch = 1;
50 
51 template <typename T>
53 
54 template <typename T>
56 
57 template <typename T>
58 TypeId
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 
71 template <typename T>
73  : m_totalNeighbors (0)
74 {
76 }
77 
78 template <typename T>
80 {
82 }
83 
84 template <typename T>
85 void
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 
95 template <typename T>
96 void
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 
106 template <typename T>
107 void
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 
120 template <typename T>
121 void
123 {
125 
126  m_node = 0;
127  m_ip = 0;
128 
129  T::DoDispose ();
130 }
131 
132 template <typename T>
133 void
135 {
137 
138  m_node = node;
139 }
140 
141 template <typename T>
142 void
144 {
146 
147  NodeList::Iterator listEnd = NodeList::End ();
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 
167 template <typename T>
168 void
170 {
172  m_nixCache.clear ();
173 }
174 
175 template <typename T>
176 void
178 {
180  m_ipRouteCache.clear ();
181 }
182 
183 template <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 
237 template <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 
258 template <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 
277 template <typename T>
278 bool
279 NixVectorRouting<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 
351 template <typename T>
352 void
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 
450 template <typename T>
451 void
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 
496 template <typename T>
497 Ptr<Node>
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 
525 template <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 
552 template <typename T>
553 uint32_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 
586 template <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 
627 template <typename T>
628 uint32_t
629 NixVectorRouting<T>::FindNetDeviceForNixIndex (Ptr<Node> node, uint32_t nodeIndex, IpAddress & gatewayIp) const
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 
673 template <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);
829  sockerr = Socket::ERROR_NOROUTETOHOST;
830  }
831 
832  return rtentry;
833 }
834 
835 template <typename T>
836 bool
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 
963 template <typename T>
964 void
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
1038 template <typename T>
1039 void
1041 {
1042  g_isCacheDirty = true;
1043 }
1044 template <typename T>
1045 void
1047 {
1048  g_isCacheDirty = true;
1049 }
1050 template <typename T>
1051 void
1053 {
1054  g_isCacheDirty = true;
1055 }
1056 template <typename T>
1057 void
1059 {
1060  g_isCacheDirty = true;
1061 }
1062 template <typename T>
1063 void
1064 NixVectorRouting<T>::NotifyAddRoute (IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse)
1065 {
1066  g_isCacheDirty = true;
1067 }
1068 template <typename T>
1069 void
1070 NixVectorRouting<T>::NotifyRemoveRoute (IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse)
1071 {
1072  g_isCacheDirty = true;
1073 }
1074 
1075 template <typename T>
1076 bool
1077 NixVectorRouting<T>::BFS (uint32_t numberOfNodes, Ptr<Node> source,
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  }
1125  Ptr<Channel> channel = oif->GetChannel ();
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 
1234 template <typename T>
1235 void
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.
1323  Ptr<IpL3Protocol> ip = curr->GetObject<IpL3Protocol> ();
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 
1364 template <typename T>
1365 void
1367 {
1368  if (g_isCacheDirty)
1369  {
1370  FlushGlobalNixRoutingCache ();
1371  g_epoch++;
1372  g_isCacheDirty = false;
1373  }
1374 }
1375 
1376 /* Public template function declarations */
1381 template void NixVectorRouting<Ipv4RoutingProtocol>::PrintRoutingPath (Ptr<Node> source, IpAddress dest,
1382  Ptr<OutputStreamWrapper> stream, Time::Unit unit) const;
1383 template 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
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.
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
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 Ptr< Node > GetNode(void) const =0
virtual Ptr< Channel > GetChannel(void) const =0
virtual bool IsBridge(void) const =0
Return true if the net device is acting as a bridge.
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)
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...
std::conditional< IsIpv4::value, UnicastForwardCallbackv4, UnicastForwardCallbackv6 >::type UnicastForwardCallback
Callback for unicast packets to be forwarded.
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: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 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