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