Bug 760 - IP address removal can be painful
authorAlexander D'souza (moijes12@gmail.com)
Tue, 09 Jul 2013 19:21:07 +0200
changeset 9915 d4c2228d3c30
parent 9914 201715662b32
child 9916 725d7c8811b8
Bug 760 - IP address removal can be painful
RELEASE_NOTES
src/internet/model/ipv4-interface.cc
src/internet/model/ipv4-interface.h
src/internet/model/ipv4-l3-protocol.cc
src/internet/model/ipv4-l3-protocol.h
src/internet/model/ipv4.h
src/internet/model/ipv6-interface.cc
src/internet/model/ipv6-interface.h
src/internet/model/ipv6-l3-protocol.cc
src/internet/model/ipv6-l3-protocol.h
src/internet/model/ipv6.h
src/internet/test/ipv4-test.cc
src/internet/test/ipv6-test.cc
--- a/RELEASE_NOTES	Tue Jul 09 19:15:20 2013 +0200
+++ b/RELEASE_NOTES	Tue Jul 09 19:21:07 2013 +0200
@@ -25,6 +25,7 @@
 
 Bugs fixed
 ----------
+- Bug 760 - IP address removal can be painful
 - Bug 1390 - ICMPv6 Redirect are handled correctly only for /64 networks
 - Bug 1643 - NdiscCache creation and existence checks
 - Bug 1646 - ICMPv6 Redirect are sent from global address instead of link-local
--- a/src/internet/model/ipv4-interface.cc	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv4-interface.cc	Tue Jul 09 19:21:07 2013 +0200
@@ -346,5 +346,28 @@
   return (addr);  // quiet compiler
 }
 
+Ipv4InterfaceAddress
+Ipv4Interface::RemoveAddress(Ipv4Address address)
+{
+  NS_LOG_FUNCTION(this << address);
+
+  if (address == address.GetLoopback())
+    {
+      NS_LOG_WARN ("Cannot remove loopback address.");
+      return Ipv4InterfaceAddress();
+    }
+
+  for(Ipv4InterfaceAddressListI it = m_ifaddrs.begin(); it != m_ifaddrs.end(); it++)
+    {
+      if((*it).GetLocal() == address)
+        {
+          Ipv4InterfaceAddress ifAddr = *it;
+          m_ifaddrs.erase(it);
+          return ifAddr;
+        }
+    }
+  return Ipv4InterfaceAddress();
+}
+
 } // namespace ns3
 
--- a/src/internet/model/ipv4-interface.h	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv4-interface.h	Tue Jul 09 19:21:07 2013 +0200
@@ -152,6 +152,15 @@
    */
   Ipv4InterfaceAddress RemoveAddress (uint32_t index);
 
+  /**
+   * \brief Remove the given Ipv4 address from the interface.
+   * \param address The Ipv4 address to remove
+   * \returns The removed Ipv4 interface address 
+   * \returns The null interface address if the interface did not contain the 
+   * address or if loopback address was passed as argument
+   */
+  Ipv4InterfaceAddress RemoveAddress (Ipv4Address address);
+
 protected:
   virtual void DoDispose (void);
 private:
--- a/src/internet/model/ipv4-l3-protocol.cc	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv4-l3-protocol.cc	Tue Jul 09 19:21:07 2013 +0200
@@ -979,6 +979,29 @@
   return false;
 }
 
+bool
+Ipv4L3Protocol::RemoveAddress (uint32_t i, Ipv4Address address)
+{
+  NS_LOG_FUNCTION (this << i << address);
+
+  if (address == Ipv4Address::GetLoopback())
+    {
+      NS_LOG_WARN ("Cannot remove loopback address.");
+      return false;
+    }
+  Ptr<Ipv4Interface> interface = GetInterface (i);
+  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
+  if (ifAddr != Ipv4InterfaceAddress ())
+    {
+      if (m_routingProtocol != 0)
+        {
+          m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
+        }
+      return true;
+    }
+  return false;
+}
+
 Ipv4Address 
 Ipv4L3Protocol::SelectSourceAddress (Ptr<const NetDevice> device,
                                      Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
--- a/src/internet/model/ipv4-l3-protocol.h	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv4-l3-protocol.h	Tue Jul 09 19:21:07 2013 +0200
@@ -194,6 +194,7 @@
   Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const;
   uint32_t GetNAddresses (uint32_t interface) const;
   bool RemoveAddress (uint32_t interfaceIndex, uint32_t addressIndex);
+  bool RemoveAddress (uint32_t interface, Ipv4Address address);
   Ipv4Address SelectSourceAddress (Ptr<const NetDevice> device,
                                    Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope);
 
--- a/src/internet/model/ipv4.h	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv4.h	Tue Jul 09 19:21:07 2013 +0200
@@ -248,6 +248,15 @@
    */
   virtual bool RemoveAddress (uint32_t interface, uint32_t addressIndex) = 0;
 
+   /**
+   * \brief Remove the given address on named Ipv4 interface
+   *
+   * \param interface Interface number of an Ipv4 interface
+   * \param address The address to remove
+   * \returns true if the operation succeeded
+   */
+  virtual bool RemoveAddress (uint32_t interface, Ipv4Address address) = 0;
+
   /**
    * \brief Return the first primary source address with scope less than 
    * or equal to the requested scope, to use in sending a packet to 
--- a/src/internet/model/ipv6-interface.cc	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv6-interface.cc	Tue Jul 09 19:21:07 2013 +0200
@@ -291,6 +291,29 @@
   return addr;  /* quiet compiler */
 }
 
+Ipv6InterfaceAddress 
+Ipv6Interface::RemoveAddress(Ipv6Address address)
+{
+  NS_LOG_FUNCTION(this << address);
+
+  if (address == address.GetLoopback())
+    {
+      NS_LOG_WARN ("Cannot remove loopback address.");
+      return Ipv6InterfaceAddress();
+    }
+
+  for (Ipv6InterfaceAddressListI it = m_addresses.begin (); it != m_addresses.end (); ++it)
+    {
+      if((*it).GetAddress() == address)
+        {
+          Ipv6InterfaceAddress iface = (*it);
+          m_addresses.erase(it);
+          return iface;
+        }
+    }
+  return Ipv6InterfaceAddress();
+}
+
 Ipv6InterfaceAddress Ipv6Interface::GetAddressMatchingDestination (Ipv6Address dst)
 {
   NS_LOG_FUNCTION (this << dst);
--- a/src/internet/model/ipv6-interface.h	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv6-interface.h	Tue Jul 09 19:21:07 2013 +0200
@@ -228,6 +228,15 @@
   Ipv6InterfaceAddress RemoveAddress (uint32_t index);
 
   /**
+   * \brief Remove the given Ipv6 address from the interface.
+   * \param address The Ipv6 address to remove
+   * \returns The removed Ipv6 interface address 
+   * \returns The null interface address if the interface did not contain the 
+   * address or if loopback address was passed as argument
+   */
+  Ipv6InterfaceAddress RemoveAddress (Ipv6Address address);
+
+  /**
    * \brief Update state of an interface address.
    * \param address IPv6 address
    * \param state new state
--- a/src/internet/model/ipv6-l3-protocol.cc	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv6-l3-protocol.cc	Tue Jul 09 19:21:07 2013 +0200
@@ -381,6 +381,29 @@
   return false;
 }
 
+bool 
+Ipv6L3Protocol::RemoveAddress (uint32_t i, Ipv6Address address)
+{
+  NS_LOG_FUNCTION (this << i << address);
+
+  if (address == Ipv6Address::GetLoopback())
+    {
+      NS_LOG_WARN ("Cannot remove loopback address.");
+      return false;
+    }
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  Ipv6InterfaceAddress ifAddr = interface->RemoveAddress (address);
+  if (ifAddr != Ipv6InterfaceAddress ())
+  {
+    if (m_routingProtocol != 0)
+    {
+      m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
+    }
+    return true;
+  }
+  return false;
+}
+
 void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric)
 {
   NS_LOG_FUNCTION (this << i << metric);
--- a/src/internet/model/ipv6-l3-protocol.h	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv6-l3-protocol.h	Tue Jul 09 19:21:07 2013 +0200
@@ -249,6 +249,14 @@
   bool RemoveAddress (uint32_t interfaceIndex, uint32_t addressIndex);
 
   /**
+   * \brief Remove a specified Ipv6 address from an interface.
+   * \param interfaceIndex interface index
+   * \param address Ipv6Address to be removed from the interface
+   * \returns true if the operation succeeded
+   */
+  bool RemoveAddress (uint32_t interface, Ipv6Address address);
+
+  /**
    * \brief Set metric for an interface.
    * \param i index
    * \param metric
--- a/src/internet/model/ipv6.h	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/model/ipv6.h	Tue Jul 09 19:21:07 2013 +0200
@@ -218,6 +218,15 @@
   virtual bool RemoveAddress (uint32_t interface, uint32_t addressIndex) = 0;
 
   /**
+   * \brief Remove the given address on named Ipv6 interface
+   *
+   * \param interface Interface number of an IPv6 interface
+   * \param address the address to remove
+   * \returns true if the operation succeeded
+   */
+  virtual bool RemoveAddress (uint32_t interface, Ipv6Address address) = 0;
+
+  /**
    * \brief Set metric on specified Ipv6 interface.
    *
    * \param interface The interface number of an IPv6 interface
--- a/src/internet/test/ipv4-test.cc	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/test/ipv4-test.cc	Tue Jul 09 19:21:07 2013 +0200
@@ -94,9 +94,53 @@
   Ipv4InterfaceAddress output = interface->GetAddress (2);
   NS_TEST_ASSERT_MSG_EQ (ifaceAddr4, output,
                          "The addresses should be identical");
+
+  /* Test Ipv4Interface()::RemoveAddress(address) */
+  output = interface->RemoveAddress (Ipv4Address ("250.0.0.1"));
+  NS_TEST_ASSERT_MSG_EQ (ifaceAddr4, output,
+                         "Wrong Interface Address Removed??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 2, "Should find 2 addresses??");
+  
+  /* Remove a non-existent Address */
+  output = interface->RemoveAddress (Ipv4Address ("253.123.9.81"));
+  NS_TEST_ASSERT_MSG_EQ (Ipv4InterfaceAddress (), output,
+                         "Removed non-existent address??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 2, "Should find 2 addresses??");
+  
+  /* Remove a Loopback Address */
+  output = interface->RemoveAddress (Ipv4Address::GetLoopback ());
+  NS_TEST_ASSERT_MSG_EQ (Ipv4InterfaceAddress (), output,
+                         "Able to remove loopback address??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 2, "Should find 2 addresses??");
+
+  /* Test Ipv4Address::RemoveAddress(i, addresss) */
+  bool result = ipv4->RemoveAddress (index, Ipv4Address
+("192.168.0.2"));
+  NS_TEST_ASSERT_MSG_EQ (true, result, "Unable to remove Address??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Should find 1 addresses??");
+
+  /* Remove a non-existent Address */
+  result = ipv4->RemoveAddress (index, Ipv4Address ("189.0.0.1"));
+  NS_TEST_ASSERT_MSG_EQ (false, result,
+                         "Removed non-existent address??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Should find 1 addresses??");
+
+  /* Remove a loopback Address */
+  result = ipv4->RemoveAddress (index, Ipv4Address::GetLoopback ());
+  NS_TEST_ASSERT_MSG_EQ (false, result,
+                         "Able to remove loopback address??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Should find 1 addresses??");
+
   Simulator::Destroy ();
 }
 
+  
 static class IPv4L3ProtocolTestSuite : public TestSuite
 {
 public:
--- a/src/internet/test/ipv6-test.cc	Tue Jul 09 19:15:20 2013 +0200
+++ b/src/internet/test/ipv6-test.cc	Tue Jul 09 19:21:07 2013 +0200
@@ -136,6 +136,48 @@
 
   index = ipv6->GetInterfaceForAddress ("2001:ffff:5678:9000::1"); /* address we just remove */
   NS_TEST_ASSERT_MSG_EQ (index, (uint32_t) -1, "Address should not be found??");
+
+  /* Test Ipv6Interface()::RemoveAddress(address) */
+  output = interface->RemoveAddress (Ipv6Address ("2001:1234:5678:9000::1"));
+  NS_TEST_ASSERT_MSG_EQ (ifaceAddr1, output, "Wrong Interface Address Removed??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Number of addresses should be 1??");
+  
+  /* Remove a non-existent Address */
+  output = interface->RemoveAddress (Ipv6Address ("2001:1234:5678:9000::1"));
+  NS_TEST_ASSERT_MSG_EQ (Ipv6InterfaceAddress (), output, 
+                         "Removed non-existent address??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Number of addresses should be 1??");
+
+  /* Remove a loopback Address */
+  output = interface->RemoveAddress (Ipv6Address::GetLoopback ());
+  NS_TEST_ASSERT_MSG_EQ (Ipv6InterfaceAddress (), output, 
+                         "Able to remove loopback address??");
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Number of addresses should be 1??");
+
+  /* Test Ipv6Address::RemoveAddress(index, addresss) */
+  index = ipv6->GetInterfaceForAddress ("2001:ffff:5678:9001::2");
+  bool result = ipv6->RemoveAddress (index, Ipv6Address 
+                                     ("2001:ffff:5678:9001::2"));
+  NS_TEST_ASSERT_MSG_EQ (result, true, "Unable to remove Address??");
+  num = interface2->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Number of addresses should be 1??");
+
+  /* Remove a non-existent Address */
+  result = ipv6->RemoveAddress (index, Ipv6Address  
+                                ("2001:ffff:5678:9001::2"));
+  NS_TEST_ASSERT_MSG_EQ (result, false, "Removed Non-existent address??");
+  num = interface2->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Number of addresses should be 1??");
+ 
+  /* Remove a loopback Address */
+  result = ipv6->RemoveAddress (index, Ipv6Address::GetLoopback ());
+  NS_TEST_ASSERT_MSG_EQ (result, false, "Able to remove loopback address??");
+  num = interface2->GetNAddresses ();
+  NS_TEST_ASSERT_MSG_EQ (num, 1, "Number of addresses should be 1??");
+
   Simulator::Destroy ();
 } //end DoRun
 static class IPv6L3ProtocolTestSuite : public TestSuite