A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv4-nix-vector-routing.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 The Georgia Institute of Technology
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  * Authors: Josh Pelkey <jpelkey@gatech.edu>
19  */
20 
21 #include <queue>
22 #include <iomanip>
23 
24 #include "ns3/log.h"
25 #include "ns3/abort.h"
26 #include "ns3/names.h"
27 #include "ns3/ipv4-list-routing.h"
28 
29 #include "ipv4-nix-vector-routing.h"
30 
31 NS_LOG_COMPONENT_DEFINE ("Ipv4NixVectorRouting");
32 
33 namespace ns3 {
34 
35 NS_OBJECT_ENSURE_REGISTERED (Ipv4NixVectorRouting);
36 
37 TypeId
39 {
40  static TypeId tid = TypeId ("ns3::Ipv4NixVectorRouting")
42  .AddConstructor<Ipv4NixVectorRouting> ()
43  ;
44  return tid;
45 }
46 
47 Ipv4NixVectorRouting::Ipv4NixVectorRouting ()
48  : m_totalNeighbors (0)
49 {
51 }
52 
53 Ipv4NixVectorRouting::~Ipv4NixVectorRouting ()
54 {
56 }
57 
58 void
60 {
61  NS_ASSERT (ipv4 != 0);
62  NS_ASSERT (m_ipv4 == 0);
63  NS_LOG_DEBUG ("Created Ipv4NixVectorProtocol");
64 
65  m_ipv4 = ipv4;
66 }
67 
68 void
70 {
72 
73  m_node = 0;
74  m_ipv4 = 0;
75 
77 }
78 
79 
80 void
82 {
84 
85  m_node = node;
86 }
87 
88 void
90 {
92  NodeList::Iterator listEnd = NodeList::End ();
93  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
94  {
95  Ptr<Node> node = *i;
97  if (!rp)
98  {
99  continue;
100  }
101  NS_LOG_LOGIC ("Flushing Nix caches.");
102  rp->FlushNixCache ();
103  rp->FlushIpv4RouteCache ();
104  }
105 }
106 
107 void
108 Ipv4NixVectorRouting::FlushNixCache ()
109 {
111  m_nixCache.clear ();
112 }
113 
114 void
115 Ipv4NixVectorRouting::FlushIpv4RouteCache ()
116 {
118  m_ipv4RouteCache.clear ();
119 }
120 
121 Ptr<NixVector>
122 Ipv4NixVectorRouting::GetNixVector (Ptr<Node> source, Ipv4Address dest, Ptr<NetDevice> oif)
123 {
125 
126  Ptr<NixVector> nixVector = Create<NixVector> ();
127 
128  // not in cache, must build the nix vector
129  // First, we have to figure out the nodes
130  // associated with these IPs
131  Ptr<Node> destNode = GetNodeByIp (dest);
132  if (destNode == 0)
133  {
134  NS_LOG_ERROR ("No routing path exists");
135  return 0;
136  }
137 
138  // if source == dest, then we have a special case
139  // Do not process packets to self (see bug 1308)
140  if (source == destNode)
141  {
142  NS_LOG_DEBUG ("Do not processs packets to self");
143  return 0;
144  }
145  else
146  {
147  // otherwise proceed as normal
148  // and build the nix vector
149  std::vector< Ptr<Node> > parentVector;
150 
151  BFS (NodeList::GetNNodes (), source, destNode, parentVector, oif);
152 
153  if (BuildNixVector (parentVector, source->GetId (), destNode->GetId (), nixVector))
154  {
155  return nixVector;
156  }
157  else
158  {
159  NS_LOG_ERROR ("No routing path exists");
160  return 0;
161  }
162  }
163 }
164 
165 Ptr<NixVector>
166 Ipv4NixVectorRouting::GetNixVectorInCache (Ipv4Address address)
167 {
169 
170  NixMap_t::iterator iter = m_nixCache.find (address);
171  if (iter != m_nixCache.end ())
172  {
173  NS_LOG_LOGIC ("Found Nix-vector in cache.");
174  return iter->second;
175  }
176 
177  // not in cache
178  return 0;
179 }
180 
181 Ptr<Ipv4Route>
182 Ipv4NixVectorRouting::GetIpv4RouteInCache (Ipv4Address address)
183 {
185 
186  Ipv4RouteMap_t::iterator iter = m_ipv4RouteCache.find (address);
187  if (iter != m_ipv4RouteCache.end ())
188  {
189  NS_LOG_LOGIC ("Found Ipv4Route in cache.");
190  return iter->second;
191  }
192 
193  // not in cache
194  return 0;
195 }
196 
197 bool
198 Ipv4NixVectorRouting::BuildNixVectorLocal (Ptr<NixVector> nixVector)
199 {
201 
202  uint32_t numberOfDevices = m_node->GetNDevices ();
203 
204  // here we are building a nix vector to
205  // ourself, so we need to find the loopback
206  // interface and add that to the nix vector
207  Ipv4Address loopback ("127.0.0.1");
208  for (uint32_t i = 0; i < numberOfDevices; i++)
209  {
210  uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice (m_node->GetDevice (i));
211  Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0);
212  if (ifAddr.GetLocal () == loopback)
213  {
214  NS_LOG_LOGIC ("Adding loopback to nix.");
215  NS_LOG_LOGIC ("Adding Nix: " << i << " with " << nixVector->BitCount (numberOfDevices)
216  << " bits, for node " << m_node->GetId ());
217  nixVector->AddNeighborIndex (i, nixVector->BitCount (numberOfDevices));
218  return true;
219  }
220  }
221  return false;
222 }
223 
224 bool
225 Ipv4NixVectorRouting::BuildNixVector (const std::vector< Ptr<Node> > & parentVector, uint32_t source, uint32_t dest, Ptr<NixVector> nixVector)
226 {
228 
229  if (source == dest)
230  {
231  return true;
232  }
233 
234  if (parentVector.at (dest) == 0)
235  {
236  return false;
237  }
238 
239  Ptr<Node> parentNode = parentVector.at (dest);
240 
241  uint32_t numberOfDevices = parentNode->GetNDevices ();
242  uint32_t destId = 0;
243  uint32_t totalNeighbors = 0;
244 
245  // scan through the net devices on the parent node
246  // and then look at the nodes adjacent to them
247  for (uint32_t i = 0; i < numberOfDevices; i++)
248  {
249  // Get a net device from the node
250  // as well as the channel, and figure
251  // out the adjacent net devices
252  Ptr<NetDevice> localNetDevice = parentNode->GetDevice (i);
253  if (localNetDevice->IsBridge ())
254  {
255  continue;
256  }
257  Ptr<Channel> channel = localNetDevice->GetChannel ();
258  if (channel == 0)
259  {
260  continue;
261  }
262 
263  // this function takes in the local net dev, and channnel, and
264  // writes to the netDeviceContainer the adjacent net devs
265  NetDeviceContainer netDeviceContainer;
266  GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
267 
268  // Finally we can get the adjacent nodes
269  // and scan through them. If we find the
270  // node that matches "dest" then we can add
271  // the index to the nix vector.
272  // the index corresponds to the neighbor index
273  uint32_t offset = 0;
274  for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin (); iter != netDeviceContainer.End (); iter++)
275  {
276  Ptr<Node> remoteNode = (*iter)->GetNode ();
277 
278  if (remoteNode->GetId () == dest)
279  {
280  destId = totalNeighbors + offset;
281  }
282  offset += 1;
283  }
284 
285  totalNeighbors += netDeviceContainer.GetN ();
286  }
287  NS_LOG_LOGIC ("Adding Nix: " << destId << " with "
288  << nixVector->BitCount (totalNeighbors) << " bits, for node " << parentNode->GetId ());
289  nixVector->AddNeighborIndex (destId, nixVector->BitCount (totalNeighbors));
290 
291  // recurse through parent vector, grabbing the path
292  // and building the nix vector
293  BuildNixVector (parentVector, source, (parentVector.at (dest))->GetId (), nixVector);
294  return true;
295 }
296 
297 void
298 Ipv4NixVectorRouting::GetAdjacentNetDevices (Ptr<NetDevice> netDevice, Ptr<Channel> channel, NetDeviceContainer & netDeviceContainer)
299 {
301 
302  for (uint32_t i = 0; i < channel->GetNDevices (); i++)
303  {
304  Ptr<NetDevice> remoteDevice = channel->GetDevice (i);
305  if (remoteDevice != netDevice)
306  {
307  Ptr<BridgeNetDevice> bd = NetDeviceIsBridged (remoteDevice);
308  // we have a bridged device, we need to add all
309  // bridged devices
310  if (bd)
311  {
312  NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bd);
313  for (uint32_t j = 0; j < bd->GetNBridgePorts (); ++j)
314  {
315  Ptr<NetDevice> ndBridged = bd->GetBridgePort (j);
316  if (ndBridged == remoteDevice)
317  {
318  NS_LOG_LOGIC ("That bridge port is me, don't walk backward");
319  continue;
320  }
321  Ptr<Channel> chBridged = ndBridged->GetChannel ();
322  if (chBridged == 0)
323  {
324  continue;
325  }
326  GetAdjacentNetDevices (ndBridged, chBridged, netDeviceContainer);
327  }
328  }
329  else
330  {
331  netDeviceContainer.Add (channel->GetDevice (i));
332  }
333  }
334  }
335 }
336 
337 Ptr<Node>
338 Ipv4NixVectorRouting::GetNodeByIp (Ipv4Address dest)
339 {
341 
342  NodeContainer allNodes = NodeContainer::GetGlobal ();
343  Ptr<Node> destNode;
344 
345  for (NodeContainer::Iterator i = allNodes.Begin (); i != allNodes.End (); ++i)
346  {
347  Ptr<Node> node = *i;
348  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
349  if (ipv4->GetInterfaceForAddress (dest) != -1)
350  {
351  destNode = node;
352  break;
353  }
354  }
355 
356  if (!destNode)
357  {
358  NS_LOG_ERROR ("Couldn't find dest node given the IP" << dest);
359  return 0;
360  }
361 
362  return destNode;
363 }
364 
365 uint32_t
366 Ipv4NixVectorRouting::FindTotalNeighbors ()
367 {
368  uint32_t numberOfDevices = m_node->GetNDevices ();
369  uint32_t totalNeighbors = 0;
370 
371  // scan through the net devices on the parent node
372  // and then look at the nodes adjacent to them
373  for (uint32_t i = 0; i < numberOfDevices; i++)
374  {
375  // Get a net device from the node
376  // as well as the channel, and figure
377  // out the adjacent net devices
378  Ptr<NetDevice> localNetDevice = m_node->GetDevice (i);
379  Ptr<Channel> channel = localNetDevice->GetChannel ();
380  if (channel == 0)
381  {
382  continue;
383  }
384 
385  // this function takes in the local net dev, and channnel, and
386  // writes to the netDeviceContainer the adjacent net devs
387  NetDeviceContainer netDeviceContainer;
388  GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
389 
390  totalNeighbors += netDeviceContainer.GetN ();
391  }
392 
393  return totalNeighbors;
394 }
395 
396 Ptr<BridgeNetDevice>
397 Ipv4NixVectorRouting::NetDeviceIsBridged (Ptr<NetDevice> nd) const
398 {
399  NS_LOG_FUNCTION (nd);
400 
401  Ptr<Node> node = nd->GetNode ();
402  uint32_t nDevices = node->GetNDevices ();
403 
404  //
405  // There is no bit on a net device that says it is being bridged, so we have
406  // to look for bridges on the node to which the device is attached. If we
407  // find a bridge, we need to look through its bridge ports (the devices it
408  // bridges) to see if we find the device in question.
409  //
410  for (uint32_t i = 0; i < nDevices; ++i)
411  {
412  Ptr<NetDevice> ndTest = node->GetDevice (i);
413  NS_LOG_LOGIC ("Examine device " << i << " " << ndTest);
414 
415  if (ndTest->IsBridge ())
416  {
417  NS_LOG_LOGIC ("device " << i << " is a bridge net device");
418  Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice> ();
419  NS_ABORT_MSG_UNLESS (bnd, "Ipv4NixVectorRouting::NetDeviceIsBridged (): GetObject for <BridgeNetDevice> failed");
420 
421  for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
422  {
423  NS_LOG_LOGIC ("Examine bridge port " << j << " " << bnd->GetBridgePort (j));
424  if (bnd->GetBridgePort (j) == nd)
425  {
426  NS_LOG_LOGIC ("Net device " << nd << " is bridged by " << bnd);
427  return bnd;
428  }
429  }
430  }
431  }
432  NS_LOG_LOGIC ("Net device " << nd << " is not bridged");
433  return 0;
434 }
435 
436 uint32_t
437 Ipv4NixVectorRouting::FindNetDeviceForNixIndex (uint32_t nodeIndex, Ipv4Address & gatewayIp)
438 {
439  uint32_t numberOfDevices = m_node->GetNDevices ();
440  uint32_t index = 0;
441  uint32_t totalNeighbors = 0;
442 
443  // scan through the net devices on the parent node
444  // and then look at the nodes adjacent to them
445  for (uint32_t i = 0; i < numberOfDevices; i++)
446  {
447  // Get a net device from the node
448  // as well as the channel, and figure
449  // out the adjacent net devices
450  Ptr<NetDevice> localNetDevice = m_node->GetDevice (i);
451  Ptr<Channel> channel = localNetDevice->GetChannel ();
452  if (channel == 0)
453  {
454  continue;
455  }
456 
457  // this function takes in the local net dev, and channnel, and
458  // writes to the netDeviceContainer the adjacent net devs
459  NetDeviceContainer netDeviceContainer;
460  GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
461 
462  // check how many neighbors we have
463  if (nodeIndex < (totalNeighbors + netDeviceContainer.GetN ()))
464  {
465  // found the proper net device
466  index = i;
467  Ptr<NetDevice> gatewayDevice = netDeviceContainer.Get (nodeIndex-totalNeighbors);
468  Ptr<Node> gatewayNode = gatewayDevice->GetNode ();
469  Ptr<Ipv4> ipv4 = gatewayNode->GetObject<Ipv4> ();
470 
471  uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice (gatewayDevice);
472  Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (interfaceIndex, 0);
473  gatewayIp = ifAddr.GetLocal ();
474  break;
475  }
476  totalNeighbors += netDeviceContainer.GetN ();
477  }
478 
479  return index;
480 }
481 
482 Ptr<Ipv4Route>
483 Ipv4NixVectorRouting::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
484 {
486  Ptr<Ipv4Route> rtentry;
487  Ptr<NixVector> nixVectorInCache;
488  Ptr<NixVector> nixVectorForPacket;
489 
490  NS_LOG_DEBUG ("Dest IP from header: " << header.GetDestination ());
491  // check if cache
492  nixVectorInCache = GetNixVectorInCache (header.GetDestination ());
493 
494  // not in cache
495  if (!nixVectorInCache)
496  {
497  NS_LOG_LOGIC ("Nix-vector not in cache, build: ");
498  // Build the nix-vector, given this node and the
499  // dest IP address
500  nixVectorInCache = GetNixVector (m_node, header.GetDestination (), oif);
501 
502  // cache it
503  m_nixCache.insert (NixMap_t::value_type (header.GetDestination (), nixVectorInCache));
504  }
505 
506  // path exists
507  if (nixVectorInCache)
508  {
509  NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache);
510 
511  // create a new nix vector to be used,
512  // we want to keep the cached version clean
513  nixVectorForPacket = Create<NixVector> ();
514  nixVectorForPacket = nixVectorInCache->Copy ();
515 
516  // Get the interface number that we go out of, by extracting
517  // from the nix-vector
518  if (m_totalNeighbors == 0)
519  {
520  m_totalNeighbors = FindTotalNeighbors ();
521  }
522 
523  // Get the interface number that we go out of, by extracting
524  // from the nix-vector
525  uint32_t numberOfBits = nixVectorForPacket->BitCount (m_totalNeighbors);
526  uint32_t nodeIndex = nixVectorForPacket->ExtractNeighborIndex (numberOfBits);
527 
528  // Search here in a cache for this node index
529  // and look for a Ipv4Route
530  rtentry = GetIpv4RouteInCache (header.GetDestination ());
531 
532  if (!rtentry || !(rtentry->GetOutputDevice () == oif))
533  {
534  // not in cache or a different specified output
535  // device is to be used
536 
537  // first, make sure we erase existing (incorrect)
538  // rtentry from the map
539  if (rtentry)
540  {
541  m_ipv4RouteCache.erase (header.GetDestination ());
542  }
543 
544  NS_LOG_LOGIC ("Ipv4Route not in cache, build: ");
545  Ipv4Address gatewayIp;
546  uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp);
547  int32_t interfaceIndex = 0;
548 
549  if (!oif)
550  {
551  interfaceIndex = (m_ipv4)->GetInterfaceForDevice (m_node->GetDevice (index));
552  }
553  else
554  {
555  interfaceIndex = (m_ipv4)->GetInterfaceForDevice (oif);
556  }
557 
558  NS_ASSERT_MSG (interfaceIndex != -1, "Interface index not found for device");
559 
560  Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0);
561 
562  // start filling in the Ipv4Route info
563  rtentry = Create<Ipv4Route> ();
564  rtentry->SetSource (ifAddr.GetLocal ());
565 
566  rtentry->SetGateway (gatewayIp);
567  rtentry->SetDestination (header.GetDestination ());
568 
569  if (!oif)
570  {
571  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex));
572  }
573  else
574  {
575  rtentry->SetOutputDevice (oif);
576  }
577 
578  sockerr = Socket::ERROR_NOTERROR;
579 
580  // add rtentry to cache
581  m_ipv4RouteCache.insert (Ipv4RouteMap_t::value_type (header.GetDestination (), rtentry));
582  }
583 
584  NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache << " : Remaining bits: " << nixVectorForPacket->GetRemainingBits ());
585 
586  // Add nix-vector in the packet class
587  // make sure the packet exists first
588  if (p)
589  {
590  NS_LOG_LOGIC ("Adding Nix-vector to packet: " << *nixVectorForPacket);
591  p->SetNixVector (nixVectorForPacket);
592  }
593  }
594  else // path doesn't exist
595  {
596  NS_LOG_ERROR ("No path to the dest: " << header.GetDestination ());
597  sockerr = Socket::ERROR_NOROUTETOHOST;
598  }
599 
600  return rtentry;
601 }
602 
603 bool
607 {
609 
610  Ptr<Ipv4Route> rtentry;
611 
612  // Get the nix-vector from the packet
613  Ptr<NixVector> nixVector = p->GetNixVector ();
614 
615  // If nixVector isn't in packet, something went wrong
616  NS_ASSERT (nixVector);
617 
618  // Get the interface number that we go out of, by extracting
619  // from the nix-vector
620  if (m_totalNeighbors == 0)
621  {
622  m_totalNeighbors = FindTotalNeighbors ();
623  }
624  uint32_t numberOfBits = nixVector->BitCount (m_totalNeighbors);
625  uint32_t nodeIndex = nixVector->ExtractNeighborIndex (numberOfBits);
626 
627  rtentry = GetIpv4RouteInCache (header.GetDestination ());
628  // not in cache
629  if (!rtentry)
630  {
631  NS_LOG_LOGIC ("Ipv4Route not in cache, build: ");
632  Ipv4Address gatewayIp;
633  uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp);
634  uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice (m_node->GetDevice (index));
635  Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0);
636 
637  // start filling in the Ipv4Route info
638  rtentry = Create<Ipv4Route> ();
639  rtentry->SetSource (ifAddr.GetLocal ());
640 
641  rtentry->SetGateway (gatewayIp);
642  rtentry->SetDestination (header.GetDestination ());
643  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex));
644 
645  // add rtentry to cache
646  m_ipv4RouteCache.insert (Ipv4RouteMap_t::value_type (header.GetDestination (), rtentry));
647  }
648 
649  NS_LOG_LOGIC ("At Node " << m_node->GetId () << ", Extracting " << numberOfBits <<
650  " bits from Nix-vector: " << nixVector << " : " << *nixVector);
651 
652  // call the unicast callback
653  // local deliver is handled by Ipv4StaticRoutingImpl
654  // so this code is never even called if the packet is
655  // destined for this node.
656  ucb (rtentry, p, header);
657 
658  return true;
659 }
660 
661 void
663 {
664 
665  std::ostream* os = stream->GetStream ();
666  *os << "NixCache:" << std::endl;
667  if (m_nixCache.size () > 0)
668  {
669  *os << "Destination NixVector" << std::endl;
670  for (NixMap_t::const_iterator it = m_nixCache.begin (); it != m_nixCache.end (); it++)
671  {
672  std::ostringstream dest;
673  dest << it->first;
674  *os << std::setiosflags (std::ios::left) << std::setw (16) << dest.str ();
675  *os << *(it->second) << std::endl;
676  }
677  }
678  *os << "Ipv4RouteCache:" << std::endl;
679  if (m_ipv4RouteCache.size () > 0)
680  {
681  *os << "Destination Gateway Source OutputDevice" << std::endl;
682  for (Ipv4RouteMap_t::const_iterator it = m_ipv4RouteCache.begin (); it != m_ipv4RouteCache.end (); it++)
683  {
684  std::ostringstream dest, gw, src;
685  dest << it->second->GetDestination ();
686  *os << std::setiosflags (std::ios::left) << std::setw (16) << dest.str ();
687  gw << it->second->GetGateway ();
688  *os << std::setiosflags (std::ios::left) << std::setw (16) << gw.str ();
689  src << it->second->GetSource ();
690  *os << std::setiosflags (std::ios::left) << std::setw (16) << src.str ();
691  *os << " ";
692  if (Names::FindName (it->second->GetOutputDevice ()) != "")
693  {
694  *os << Names::FindName (it->second->GetOutputDevice ());
695  }
696  else
697  {
698  *os << it->second->GetOutputDevice ()->GetIfIndex ();
699  }
700  *os << std::endl;
701  }
702  }
703 }
704 
705 // virtual functions from Ipv4RoutingProtocol
706 void
708 {
710 }
711 void
713 {
715 }
716 void
718 {
720 }
721 void
723 {
725 }
726 
727 bool
728 Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr<Node> source,
729  Ptr<Node> dest, std::vector< Ptr<Node> > & parentVector,
730  Ptr<NetDevice> oif)
731 {
733 
734  NS_LOG_LOGIC ("Going from Node " << source->GetId () << " to Node " << dest->GetId ());
735  std::queue< Ptr<Node> > greyNodeList; // discovered nodes with unexplored children
736 
737  // reset the parent vector
738  parentVector.clear ();
739  parentVector.reserve (sizeof (Ptr<Node>)*numberOfNodes);
740  parentVector.insert (parentVector.begin (), sizeof (Ptr<Node>)*numberOfNodes, 0); // initialize to 0
741 
742  // Add the source node to the queue, set its parent to itself
743  greyNodeList.push (source);
744  parentVector.at (source->GetId ()) = source;
745 
746  // BFS loop
747  while (greyNodeList.size () != 0)
748  {
749  Ptr<Node> currNode = greyNodeList.front ();
750  Ptr<Ipv4> ipv4 = currNode->GetObject<Ipv4> ();
751 
752  if (currNode == dest)
753  {
754  NS_LOG_LOGIC ("Made it to Node " << currNode->GetId ());
755  return true;
756  }
757 
758  // if this is the first iteration of the loop and a
759  // specific output interface was given, make sure
760  // we go this way
761  if (currNode == source && oif)
762  {
763  // make sure that we can go this way
764  if (ipv4)
765  {
766  uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice (oif);
767  if (!(ipv4->IsUp (interfaceIndex)))
768  {
769  NS_LOG_LOGIC ("Ipv4Interface is down");
770  return false;
771  }
772  }
773  if (!(oif->IsLinkUp ()))
774  {
775  NS_LOG_LOGIC ("Link is down.");
776  return false;
777  }
778  Ptr<Channel> channel = oif->GetChannel ();
779  if (channel == 0)
780  {
781  return false;
782  }
783 
784  // this function takes in the local net dev, and channnel, and
785  // writes to the netDeviceContainer the adjacent net devs
786  NetDeviceContainer netDeviceContainer;
787  GetAdjacentNetDevices (oif, channel, netDeviceContainer);
788 
789  // Finally we can get the adjacent nodes
790  // and scan through them. We push them
791  // to the greyNode queue, if they aren't
792  // already there.
793  for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin (); iter != netDeviceContainer.End (); iter++)
794  {
795  Ptr<Node> remoteNode = (*iter)->GetNode ();
796 
797  // check to see if this node has been pushed before
798  // by checking to see if it has a parent
799  // if it doesn't (null or 0), then set its parent and
800  // push to the queue
801  if (parentVector.at (remoteNode->GetId ()) == 0)
802  {
803  parentVector.at (remoteNode->GetId ()) = currNode;
804  greyNodeList.push (remoteNode);
805  }
806  }
807  }
808  else
809  {
810  // Iterate over the current node's adjacent vertices
811  // and push them into the queue
812  for (uint32_t i = 0; i < (currNode->GetNDevices ()); i++)
813  {
814  // Get a net device from the node
815  // as well as the channel, and figure
816  // out the adjacent net device
817  Ptr<NetDevice> localNetDevice = currNode->GetDevice (i);
818 
819  // make sure that we can go this way
820  if (ipv4)
821  {
822  uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice (currNode->GetDevice (i));
823  if (!(ipv4->IsUp (interfaceIndex)))
824  {
825  NS_LOG_LOGIC ("Ipv4Interface is down");
826  continue;
827  }
828  }
829  if (!(localNetDevice->IsLinkUp ()))
830  {
831  NS_LOG_LOGIC ("Link is down.");
832  continue;
833  }
834  Ptr<Channel> channel = localNetDevice->GetChannel ();
835  if (channel == 0)
836  {
837  continue;
838  }
839 
840  // this function takes in the local net dev, and channnel, and
841  // writes to the netDeviceContainer the adjacent net devs
842  NetDeviceContainer netDeviceContainer;
843  GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
844 
845  // Finally we can get the adjacent nodes
846  // and scan through them. We push them
847  // to the greyNode queue, if they aren't
848  // already there.
849  for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin (); iter != netDeviceContainer.End (); iter++)
850  {
851  Ptr<Node> remoteNode = (*iter)->GetNode ();
852 
853  // check to see if this node has been pushed before
854  // by checking to see if it has a parent
855  // if it doesn't (null or 0), then set its parent and
856  // push to the queue
857  if (parentVector.at (remoteNode->GetId ()) == 0)
858  {
859  parentVector.at (remoteNode->GetId ()) = currNode;
860  greyNodeList.push (remoteNode);
861  }
862  }
863  }
864  }
865 
866  // Pop off the head grey node. We have all its children.
867  // It is now black.
868  greyNodeList.pop ();
869  }
870 
871  // Didn't find the dest...
872  return false;
873 }
874 
875 } // namespace ns3
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
static uint32_t GetNNodes(void)
Definition: node-list.cc:198
Callback template class.
Definition: callback.h:369
Ptr< NixVector > Copy(void) const
Definition: nix-vector.cc:71
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:131
void SetSource(Ipv4Address src)
Definition: ipv4-route.cc:49
Ptr< NetDevice > GetOutputDevice(void) const
Definition: ipv4-route.cc:84
Packet header for IPv4.
Definition: ipv4-header.h:31
uint32_t ExtractNeighborIndex(uint32_t numberOfBits)
Definition: nix-vector.cc:159
void SetNode(Ptr< Node > node)
Set the Node pointer of the node for which this routing protocol is to be placed. ...
void FlushGlobalNixRoutingCache(void)
Called when run-time link topology change occurs which iterates through the node list and flushes any...
void SetGateway(Ipv4Address gw)
Definition: ipv4-route.cc:63
static Iterator End(void)
Definition: node-list.cc:186
Ptr< NetDevice > GetDevice(uint32_t index) const
Definition: node.cc:133
static TypeId GetTypeId(void)
The Interface ID of the Global Router interface.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual void NotifyInterfaceDown(uint32_t interface)
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:75
uint32_t GetNDevices(void) const
Definition: node.cc:141
virtual void NotifyInterfaceUp(uint32_t interface)
void SetOutputDevice(Ptr< NetDevice > outputDevice)
Definition: ipv4-route.cc:77
virtual void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address)
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
static NodeContainer GetGlobal(void)
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
virtual Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
virtual void SetIpv4(Ptr< Ipv4 > ipv4)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
uint32_t GetId(void) const
Definition: node.cc:105
a class to store IPv4 address information on an interface
static Iterator Begin(void)
Definition: node-list.cc:180
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
virtual bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
Route an input packet (to be forwarded or locally delivered)
static std::string FindName(Ptr< Object > object)
Definition: names.cc:664
Abstract base class for IPv4 routing protocols.
#define NS_LOG_ERROR(msg)
Definition: log.h:237
virtual void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address)
Ptr< T > GetObject(void) const
Definition: object.h:332
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream) const
Print the Routing Table entries.
uint32_t BitCount(uint32_t numberOfNeighbors) const
Definition: nix-vector.cc:364
std::ostream * GetStream(void)
void SetDestination(Ipv4Address dest)
Definition: ipv4-route.cc:35