Fix bug 587 for ListRoutingProtocol bug; add unit test
authorTom Henderson <tomh@tomh.org>
Sat, 13 Jun 2009 14:59:35 -0700
changeset 4562 8539f55c6b55
parent 4561 cf6e27dd3a08
child 4563 55948d1baa64
Fix bug 587 for ListRoutingProtocol bug; add unit test
src/internet-stack/ipv4-list-routing.cc
src/internet-stack/ipv4-list-routing.h
--- a/src/internet-stack/ipv4-list-routing.cc	Fri Jun 12 14:43:22 2009 -0700
+++ b/src/internet-stack/ipv4-list-routing.cc	Sat Jun 13 14:59:35 2009 -0700
@@ -74,9 +74,10 @@
   NS_LOG_FUNCTION (this << header.GetDestination () << " " << header.GetSource () << " " << oif);
   Ptr<Ipv4Route> route;
 
-  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
-       i != m_routingProtocols.end ();
-       i++)
+  // Sorted lists are stored in lowest to highest order, so since we
+  // want to iterate from highest to lowest, use a reverse iterator
+  for (Ipv4RoutingProtocolList::const_reverse_iterator i = m_routingProtocols.rbegin ();
+       i != m_routingProtocols.rend (); i++)
     {
       NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first);
       NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestination ());
@@ -124,9 +125,11 @@
           // Fall through-- we may also need to forward this
           retVal = true;
         }
-      for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
-         m_routingProtocols.begin ();
-           rprotoIter != m_routingProtocols.end ();
+      // Sorted lists are stored in lowest to highest order, so since we
+      // want to iterate from highest to lowest, use a reverse iterator
+      for (Ipv4RoutingProtocolList::const_reverse_iterator rprotoIter =
+         m_routingProtocols.rbegin ();
+           rprotoIter != m_routingProtocols.rend ();
            rprotoIter++)
         {
           NS_LOG_LOGIC ("Multicast packet for me-- trying to forward");
@@ -179,10 +182,12 @@
           NS_LOG_LOGIC ("Address "<< addr << " not a match");
         }
     }
- // Next, try to find a route
-  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
-         m_routingProtocols.begin ();
-       rprotoIter != m_routingProtocols.end ();
+  // Next, try to find a route
+  // Sorted lists are stored in lowest to highest order, so since we
+  // want to iterate from highest to lowest, use a reverse iterator
+  for (Ipv4RoutingProtocolList::const_reverse_iterator rprotoIter =
+         m_routingProtocols.rbegin ();
+       rprotoIter != m_routingProtocols.rend ();
        rprotoIter++)
     {
       if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
@@ -261,7 +266,7 @@
 Ipv4ListRouting::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol, int16_t priority)
 {
   NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority);
-  m_routingProtocols.push_back (std::make_pair (-priority, routingProtocol));
+  m_routingProtocols.push_back (std::make_pair (priority, routingProtocol));
   m_routingProtocols.sort ();
   if (m_ipv4 != 0)
     {
@@ -285,8 +290,10 @@
       NS_FATAL_ERROR ("Ipv4ListRouting::GetRoutingProtocol():  index " << index << " out of range");
     }
   uint32_t i = 0;
-  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
-       rprotoIter != m_routingProtocols.end (); rprotoIter++, i++)
+  // Sorted lists are stored in lowest to highest order, so since we
+  // want to iterate from highest to lowest, use a reverse iterator
+  for (Ipv4RoutingProtocolList::const_reverse_iterator rprotoIter = m_routingProtocols.rbegin ();
+       rprotoIter != m_routingProtocols.rend (); rprotoIter++, i++)
     {
       if (i == index)
         {
@@ -318,4 +325,89 @@
 
 }
 
-}//namespace ns3
+} // namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+#include "ipv4-list-routing.h"
+#include "ns3/ipv4-routing-protocol.h"
+
+namespace ns3 {
+
+class Ipv4ARouting : public Ipv4RoutingProtocol {
+public:
+  Ptr<Ipv4Route> RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr)  { return 0;}
+  bool RouteInput  (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb) {return false;}
+  void NotifyInterfaceUp (uint32_t interface) {}
+  void NotifyInterfaceDown (uint32_t interface) {}
+  void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address) {}
+  void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address) {}
+  void SetIpv4 (Ptr<Ipv4> ipv4) {}
+};
+
+class Ipv4BRouting : public Ipv4RoutingProtocol {
+public:
+  Ptr<Ipv4Route> RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr)  { return 0;}
+  bool RouteInput  (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb) {return false;}
+  void NotifyInterfaceUp (uint32_t interface) {}
+  void NotifyInterfaceDown (uint32_t interface) {}
+  void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address) {}
+  void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address) {}
+  void SetIpv4 (Ptr<Ipv4> ipv4) {}
+};
+
+class Ipv4ListRoutingTest: public Test {
+public:
+  virtual bool RunTests (void);
+  Ipv4ListRoutingTest ();
+};
+
+Ipv4ListRoutingTest::Ipv4ListRoutingTest ()
+  : Test ("Ipv4ListRouting") {}
+
+bool
+Ipv4ListRoutingTest::RunTests (void)
+{
+  bool result = true;
+  Ptr<Ipv4ListRouting> lr = CreateObject<Ipv4ListRouting> ();
+  Ptr<Ipv4RoutingProtocol> aRouting = CreateObject<Ipv4ARouting> ();
+  Ptr<Ipv4RoutingProtocol> bRouting = CreateObject<Ipv4BRouting> ();
+  // The Ipv4ARouting should be added with higher priority (larger integer 
+  // value) and will be fetched first below
+  lr->AddRoutingProtocol (aRouting, 10);
+  lr->AddRoutingProtocol (bRouting, 5);
+  int16_t first = 3;
+  int16_t second = 3;
+  uint32_t num = lr->GetNRoutingProtocols ();
+  NS_TEST_ASSERT_EQUAL (num, 2);
+  Ptr<Ipv4RoutingProtocol> firstRp = lr->GetRoutingProtocol (0, first);
+  NS_TEST_ASSERT_EQUAL (10, first);
+  NS_TEST_ASSERT_EQUAL (firstRp, aRouting);
+  Ptr<Ipv4RoutingProtocol> secondRp = lr->GetRoutingProtocol (1, second);
+  NS_TEST_ASSERT_EQUAL (5, second);
+  NS_TEST_ASSERT_EQUAL (secondRp, bRouting);
+
+  // Test negative values
+  lr = CreateObject<Ipv4ListRouting> ();
+  // The Ipv4BRouting should be added with higher priority (larger integer value)
+  lr->AddRoutingProtocol (aRouting, -10);
+  lr->AddRoutingProtocol (bRouting, -5);
+  num = lr->GetNRoutingProtocols ();
+  NS_TEST_ASSERT_EQUAL (num, 2);
+  firstRp = lr->GetRoutingProtocol (0, first);
+  NS_TEST_ASSERT_EQUAL (-5, first);
+  NS_TEST_ASSERT_EQUAL (firstRp, bRouting);
+  
+  return result;
+}
+
+static Ipv4ListRoutingTest gIpv4ListRoutingTest;
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- a/src/internet-stack/ipv4-list-routing.h	Fri Jun 12 14:43:22 2009 -0700
+++ b/src/internet-stack/ipv4-list-routing.h	Sat Jun 13 14:59:35 2009 -0700
@@ -32,7 +32,7 @@
  * This class is a specialization of Ipv4RoutingProtocol that allows 
  * other instances of Ipv4RoutingProtocol to be inserted in a 
  * prioritized list.  Routing protocols in the list are consulted one
- * by one, from highest to lowest proirity, until a routing protocol
+ * by one, from highest to lowest priority, until a routing protocol
  * is found that will take the packet (this corresponds to a non-zero
  * return value to RouteOutput, or a return value of true to RouteInput).
  * The order by which routing protocols with the same priority value 
@@ -60,6 +60,11 @@
    */
   virtual uint32_t GetNRoutingProtocols (void) const;
   /**
+   * Return pointer to routing protocol stored at index, with the
+   * first protocol (index 0) the highest priority, the next one (index 1)
+   * the second highest priority, and so on.  The priority parameter is an
+   * output parameter and it returns the integer priority of the protocol.
+   * 
    * \return pointer to routing protocol indexed by 
    * \param index index of protocol to return
    * \param priority output parameter, set to the priority of the protocol