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