ip helper and find ip interface for device method on ipv4
authorCraig Dowell <craigdo@ee.washington.edu>
Fri, 21 Mar 2008 17:26:01 -0700
changeset 2711 83addb15f632
parent 2697 cab2a59cba8f
child 2712 02f089bd33f0
ip helper and find ip interface for device method on ipv4
src/helper/ipv4-address-helper.cc
src/helper/ipv4-address-helper.h
src/helper/waf
src/helper/wscript
src/internet-node/ipv4-impl.cc
src/internet-node/ipv4-impl.h
src/internet-node/ipv4-l3-protocol.cc
src/internet-node/ipv4-l3-protocol.h
src/node/ipv4.h
src/node/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv4-address-helper.cc	Fri Mar 21 17:26:01 2008 -0700
@@ -0,0 +1,273 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/ptr.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/ipv4.h"
+#include "ipv4-address-helper.h"
+
+NS_LOG_COMPONENT_DEFINE("Ipv4AddressHelper");
+
+namespace ns3 {
+
+Ipv4AddressHelper::Ipv4AddressHelper () 
+{
+  NS_LOG_FUNCTION;
+
+//
+// Set the default values to an illegal state.  Do this so the client is 
+// forced to think at least briefly about what addresses get used and what
+// is going on here.
+//
+  m_network = 0xffffffff;
+  m_mask = 0;
+  m_address = 0xffffffff;
+  m_base = 0xffffffff;
+  m_shift = 0xffffffff;
+  m_max = 0xffffffff;
+}
+
+  void
+Ipv4AddressHelper::SetBase (
+  const Ipv4Address network, 
+  const Ipv4Mask mask,
+  const Ipv4Address address)
+{
+  NS_LOG_FUNCTION;
+
+  m_network = network.GetHostOrder ();
+  m_mask = mask.GetHostOrder ();
+  m_base = m_address = address.GetHostOrder ();
+
+//
+// Some quick reasonableness testing.
+//
+  NS_ASSERT_MSG((m_network & ~m_mask) == 0,
+    "Ipv4AddressHelper::SetBase(): Inconsistent network and mask");
+
+  NS_ASSERT_MSG((m_address & m_mask) == 0,
+    "Ipv4AddressHelper::SetBase(): Inconsistent address and mask");
+
+//
+// Figure out how much to shift network numbers to get them aligned, and what
+// the maximum allowed address is with respect to the current mask.
+//
+  m_shift = NumAddressBits (m_mask);
+  m_max = (1 << m_shift) - 1;
+
+  NS_ASSERT_MSG(m_shift <= 32,
+    "Ipv4AddressHelper::SetBase(): Unreasonable address length");
+
+//
+// Shift the network down into the normalized position.
+//
+  m_network >>= m_shift;
+
+  NS_LOG_LOGIC ("m_network == " << m_network);
+  NS_LOG_LOGIC ("m_mask == " << m_mask);
+  NS_LOG_LOGIC ("m_address == " << m_address);
+}
+
+  Ipv4Address
+Ipv4AddressHelper::NewAddress (void)
+{
+//
+// The way this is expected to be used is that an address and network number
+// are initialized, and then NewAddress() is called repeatedly to allocate and
+// get new addresses on a given subnet.  The client will expect that the first
+// address she gets back is the one she used to initialize the generator with.
+// This implies that this operation is a post-increment.
+//
+  NS_ASSERT_MSG (m_address <= m_max,
+    "Ipv4AddressHelper::NewAddress(): Address overflow");
+
+  Ipv4Address addr ((m_network << m_shift) | m_address);
+  ++m_address;
+
+  return addr;
+}
+
+  Ipv4Address
+Ipv4AddressHelper::NewNetwork (void)
+{
+  NS_LOG_FUNCTION;
+  ++m_network;
+  m_address = m_base;
+  return Ipv4Address (m_network << m_shift);
+}
+
+  void
+Ipv4AddressHelper::Allocate (const NetDeviceContainer &c)
+{
+  NS_LOG_FUNCTION;
+  for (uint32_t i = 0; i < c.GetN (); ++i) {
+    Ptr<NetDevice> device = c.Get (i);
+
+    Ptr<Node> node = device->GetNode ();
+    NS_ASSERT_MSG (node, "Ipv4AddressHelper::Allocate(): Bad node");
+
+    Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+    NS_ASSERT_MSG (ipv4, "Ipv4AddressHelper::Allocate(): Bad ipv4");
+
+    int32_t ifIndex = ipv4->FindInterfaceForDevice (device);
+    NS_ASSERT_MSG (ifIndex >= 0, "Ipv4AddressHelper::Allocate(): "
+      "Interface index not found");
+
+    ipv4->SetAddress (ifIndex, NewAddress ());
+    ipv4->SetNetworkMask (ifIndex, m_mask);
+    ipv4->SetMetric (ifIndex, 1);
+    ipv4->SetUp (ifIndex);
+  }
+}
+
+const uint32_t N_BITS = 32;
+
+  uint32_t
+Ipv4AddressHelper::NumAddressBits (uint32_t maskbits) const
+{
+  NS_LOG_FUNCTION;
+  for (uint32_t i = 0; i < N_BITS; ++i)
+    {
+      if (maskbits & 1)
+        {
+          NS_LOG_LOGIC ("NumAddressBits -> " << i);
+          return i;
+        }
+      maskbits >>= 1;
+    }
+
+  NS_ASSERT_MSG(false, "Ipv4AddressHelper::NumAddressBits(): Bad Mask");
+  return 0;
+}
+
+}; // namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+
+namespace ns3 {
+
+class AddressHelperTest : public Test
+{
+public:
+  AddressHelperTest ();
+  virtual bool RunTests (void);
+};
+
+static AddressHelperTest g_addressHelperTest;
+
+AddressHelperTest::AddressHelperTest ()
+  : Test ("AddressHelper")
+{
+}
+
+  bool
+AddressHelperTest::RunTests (void)
+{
+  bool result = true;
+  Ipv4Address network;
+  Ipv4Address address;
+
+//
+// Make sure the network allocator part is working on some common network
+// prefixes.
+//
+  Ipv4AddressHelper h;
+
+  h.SetBase ("1.0.0.0", "255.0.0.0");
+  network = h.NewNetwork();
+  NS_TEST_ASSERT_EQUAL (network, Ipv4Address ("2.0.0.0"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("2.0.0.0"));
+
+  h.SetBase ("0.1.0.0", "255.255.0.0");
+  network = h.NewNetwork();
+  NS_TEST_ASSERT_EQUAL (network, Ipv4Address ("0.2.0.0"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.2.0.0"));
+
+  h.SetBase ("0.0.1.0", "255.255.255.0");
+  network = h.NewNetwork();
+  NS_TEST_ASSERT_EQUAL (network, Ipv4Address ("0.0.2.0"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.0.2.0"));
+
+//
+// Make sure the address allocator part is working.
+//
+  h.SetBase ("1.0.0.0", "255.0.0.0", "0.0.0.3");
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("1.0.0.3"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("1.0.0.4"));
+
+  h.SetBase ("0.1.0.0", "255.255.0.0", "0.0.0.3");
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.1.0.3"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.1.0.4"));
+
+  h.SetBase ("0.0.1.0", "255.255.255.0", "0.0.0.3");
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.0.1.3"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.0.1.4"));
+
+//
+// Make sure the reset to base behavior is working.
+//
+  h.SetBase ("1.0.0.0", "255.0.0.0", "0.0.0.3");
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("1.0.0.3"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("1.0.0.4"));
+  network = h.NewNetwork();
+  NS_TEST_ASSERT_EQUAL (network, Ipv4Address ("2.0.0.0"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("2.0.0.3"));
+
+  h.SetBase ("0.1.0.0", "255.255.0.0", "0.0.0.3");
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.1.0.3"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.1.0.4"));
+  network = h.NewNetwork();
+  NS_TEST_ASSERT_EQUAL (network, Ipv4Address ("0.2.0.0"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.2.0.3"));
+
+  h.SetBase ("0.0.1.0", "255.255.255.0", "0.0.0.3");
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.0.1.3"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.0.1.4"));
+  network = h.NewNetwork();
+  NS_TEST_ASSERT_EQUAL (network, Ipv4Address ("0.0.2.0"));
+  address = h.NewAddress();
+  NS_TEST_ASSERT_EQUAL (address, Ipv4Address ("0.0.2.3"));
+
+  return true;
+}
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TEST */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv4-address-helper.h	Fri Mar 21 17:26:01 2008 -0700
@@ -0,0 +1,180 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IPV4_ADDRESS_HELPER_H
+#define IPV4_ADDRESS_HELPER_H
+
+#include "ns3/ipv4-address.h"
+#include "ns3/net-device-container.h"
+
+namespace ns3 {
+
+/**
+ * @brief A helper class to make life easier while doing simple IPv4 address
+ * assignment in scripts.
+ *
+ * This class is a very simple IPv4 address generator.  You can think of it
+ * as a simple local number incrementer.  It has no notion that IP addresses
+ * are part of a global address space.  If you have a complicated address 
+ * assignment situation you may want to look at the Ipv4AddressGenerator which
+ * does recognize that IP address and netowrk number generation is part of a
+ * global problem.  Ipv4AddressHelper is a simple class to make simple problems
+ * easy to handle.
+ *
+ * We do call into the global address generator to make sure that there are
+ * no duplicate addresses generated.
+ *
+ * @see Ipv4AddressGenerator
+ */
+class Ipv4AddressHelper
+{
+public:
+/**
+ * @brief Construct a helper class to make life easier while doing simple IPv4
+ * address assignment in scripts.
+ */
+  Ipv4AddressHelper ();
+
+/**
+ * @brief Set the base network mumber, network mask and base address.
+ *
+ * The address helper allocates IP addresses based on a given network number
+ * and mask combination along with an initial IP address.
+ *
+ * For example, if you want to use a /24 prefix with an initial network number
+ * of 192.168.1 (corresponding to a mask of 255.255.255.0) and you want to 
+ * start allocating IP addresses out of that network beginning at 192.168.1.3,
+ * you would call 
+ *
+ *   SetBase ("192.168.1.0", "255.255.255.0", "0.0.0.3");
+ *
+ * If you don't care about the initial address it defaults to "0.0.0.0" in 
+ * which case you can simply use,
+ *
+ *   SetBase ("192.168.1.0", "255.255.255.0", "0.0.0.3");
+ *
+ * @param network The Ipv4Address containing the initial network number to
+ * use during allocation.  The bits outside the nework mask are not used.
+ * @param mask The Ipv4Mask containing one bits in each bit position of the 
+ * network number.
+ * @param base An optional Ipv4Address containing the initial address used for 
+ * IP address alloction.  Will be combined (ORed) with the network number to
+ * generate the first IP address.  Defaults to 0.0.0.0
+ * @returns Nothing.
+ */
+  void SetBase (Ipv4Address network, Ipv4Mask mask, 
+    Ipv4Address base = "0.0.0.0");
+
+/**
+ * @brief Increment the network number and reset the IP address counter to 
+ * the base value provided in the SetBase method.
+ *
+ * The address helper allocates IP addresses based on a given network number
+ * and initial IP address.  In order to separate the network number and IP 
+ * address parts, SetBase was given an initial network number value, a network
+ * mask and an initial address base.
+ *
+ * This method increments the network number and resets the IP address
+ * counter to the last base value used.  For example, if the network number was
+ * set to 192.168.0.0 with a mask of 255.255.255.0 and a base address of
+ * 0.0.0.3 in the SetBase call; a call to NewNetwork will increment the 
+ * network number counter resulting in network numbers incrementing as
+ * 192.168.1.0, 192.168.2.0, etc.  After each network number increment, the
+ * IP address counter is reset to the initial value specified in SetBase.  In 
+ * this case, that would be 0.0.0.3. so if you were to call NewAddress after
+ * the increment that resulted in a network numebr of 192.168.2.0, the 
+ * allocated addresses returned by NewAddress would be 192.168.2.3, 
+ * 192.168.2.4, etc.
+ *
+ * @returns The value of the incremented network number that will be used in
+ * following address allocations.
+ * @see SetBase
+ * @see NewAddress
+ */
+  Ipv4Address NewNetwork (void);
+
+/**
+ * @brief Increment the IP address counter used to allocate IP addresses
+ *
+ * The address helper allocates IP addresses based on a given network number
+ * and initial IP address.  In order to separate the network number and IP 
+ * address parts, SetBase was given an initial network number value, a network
+ * mask and an initial address base.
+ *
+ * This method increments IP address counter.  A check is made to ensure that
+ * the address returned will not overflow the number of bits allocated to IP
+ * addresses in SetBase (the number of address bits is defined by the number
+ * of mask bits that are not '1').
+ *
+ * For example, if the network number was set to 192.168.0.0 with a mask of 
+ * 255.255.255.0 and a base address of 0.0.0.3 in SetBase, the next call to
+ * NewAddress will return 192.168.1.3.  The NewAddress method 
+ * has post-increment semantics.  A following NewAddress would return 
+ * 192.168.0.4, etc., until the 256th call which would assert due to an address
+ * overflow.
+ *
+ * @returns The value of the newly allocated IP address.
+ * @see SetBase
+ * @see NewNetwork
+ */
+  Ipv4Address NewAddress (void);
+
+/**
+ * @brief Assign IP addresses to the net devices specified in the container
+ * based on the current network prefix and address base.
+ *
+ * The address helper allocates IP addresses based on a given network number
+ * and initial IP address.  In order to separate the network number and IP 
+ * address parts, SetBase was given an initial value and a network mask.
+ * The one bits of this mask define the prefix category from which the helper
+ * will allocate new network numbers.  An initial value for the network
+ * numbers was provided in the base parameter of the SetBase method in the 
+ * bits corresponding to positions in the mask that were 1.  An initial value
+ * for the IP address counter was also provided in the base parameter in the 
+ * bits corresponding to positions in the mask that were 0.
+ *
+ * This method gets new addresses for each net device in the container.  For
+ * each net device in the container, the helper finds the associated node and
+ * looks up the Ipv4 interface corresponding to the net device.  It then sets
+ * the Ipv4Address and mask in the interface to the appropriate values.  If 
+ * the addresses overflow the number of bits allocated for them by the network 
+ * mask in the SetBase method, the system will NS_ASSERT and halt.
+ *
+ * @param c The NetDeviceContainer holding the collection of net devices we
+ * are asked to assign Ipv4 addresses to.
+ *
+ * @returns Nothing
+ * @see SetBase
+ * @see NewNetwork
+ */
+  void Allocate (const NetDeviceContainer &c);
+
+private:
+  uint32_t NumAddressBits (uint32_t maskbits) const;
+
+  uint32_t m_network;
+  uint32_t m_mask;
+  uint32_t m_address;
+  uint32_t m_base;
+  uint32_t m_shift;
+  uint32_t m_max;
+};
+
+}; // namespace ns3
+
+#endif /* IPV4_ADDRESS_HELPER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/waf	Fri Mar 21 17:26:01 2008 -0700
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../waf "$@"
\ No newline at end of file
--- a/src/helper/wscript	Fri Mar 21 15:58:20 2008 -0700
+++ b/src/helper/wscript	Fri Mar 21 17:26:01 2008 -0700
@@ -11,6 +11,7 @@
         'csma-helper.cc',
         'mobility-helper.cc',
         'ns2-mobility-helper.cc',
+        'ipv4-address-helper.cc',
         ]
 
     headers = bld.create_obj('ns3header')
@@ -24,4 +25,5 @@
         'csma-helper.h',
         'mobility-helper.h',
         'ns2-mobility-helper.h',
+        'ipv4-address-helper.h',
         ]
--- a/src/internet-node/ipv4-impl.cc	Fri Mar 21 15:58:20 2008 -0700
+++ b/src/internet-node/ipv4-impl.cc	Fri Mar 21 17:26:01 2008 -0700
@@ -166,6 +166,12 @@
   return m_ipv4->FindInterfaceForAddr (addr, mask);
 }
 
+int32_t 
+Ipv4Impl::FindInterfaceForDevice (Ptr<NetDevice> device) const
+{
+  return m_ipv4->FindInterfaceIndexForDevice (device);
+}
+
 Ptr<NetDevice>
 Ipv4Impl::GetNetDevice (uint32_t i)
 {
--- a/src/internet-node/ipv4-impl.h	Fri Mar 21 15:58:20 2008 -0700
+++ b/src/internet-node/ipv4-impl.h	Fri Mar 21 17:26:01 2008 -0700
@@ -81,6 +81,8 @@
   virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, 
     Ipv4Mask mask) const;
 
+  virtual int32_t FindInterfaceForDevice (Ptr<NetDevice> device) const;
+
   virtual Ptr<NetDevice> GetNetDevice(uint32_t i);
 
   virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
--- a/src/internet-node/ipv4-l3-protocol.cc	Fri Mar 21 15:58:20 2008 -0700
+++ b/src/internet-node/ipv4-l3-protocol.cc	Fri Mar 21 17:26:01 2008 -0700
@@ -415,6 +415,26 @@
   return 0;
 }
 
+int32_t 
+Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr<NetDevice> device) const
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAMS (this << device);
+
+  uint32_t ifIndex = 0;
+  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
+       i != m_interfaces.end (); 
+       i++, ifIndex++)
+    {
+      if ((*i)->GetDevice () == device)
+        {
+          return ifIndex;
+        }
+    }
+
+  return -1;
+}
+
 Ptr<Ipv4Interface>
 Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
 {
--- a/src/internet-node/ipv4-l3-protocol.h	Fri Mar 21 15:58:20 2008 -0700
+++ b/src/internet-node/ipv4-l3-protocol.h	Fri Mar 21 17:26:01 2008 -0700
@@ -138,6 +138,7 @@
 
   uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
   uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const;
+  int32_t FindInterfaceIndexForDevice (Ptr<NetDevice> device) const;
   
   void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
   void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
--- a/src/node/ipv4.h	Fri Mar 21 15:58:20 2008 -0700
+++ b/src/node/ipv4.h	Fri Mar 21 17:26:01 2008 -0700
@@ -342,6 +342,21 @@
     Ipv4Mask mask) const = 0;
 
   /**
+   * \brief Find and return the interface ID of the interface that has been
+   *        associated with the specified (masked) NetDevice
+   * \param nd The net device of the interface of interest.
+   * \returns The index of the ipv4 interface associated with the given net 
+   *          device or -1 if not found.
+   *
+   * Each IP interface is associated with a net device.  It is often 
+   * useful to search the list of interfaces for one that corresponds to 
+   * a known net device.  This call takes an smart pointer to a net device
+   * and returns the interface index of the first interface that matches the
+   * net device.
+   */
+  virtual int32_t FindInterfaceForDevice(Ptr<NetDevice> nd) const = 0;
+
+  /**
    * \param i index of ipv4 interface
    * \returns the NetDevice associated with the ipv4 interface index
    */
--- a/src/node/wscript	Fri Mar 21 15:58:20 2008 -0700
+++ b/src/node/wscript	Fri Mar 21 17:26:01 2008 -0700
@@ -10,6 +10,7 @@
         'packet-socket-address.cc',
         'node.cc',
         'ipv4-address.cc',
+        'ipv4-address-generator.cc',
         'net-device.cc',
 	'address-utils.cc',
         'llc-snap-header.cc',
@@ -42,6 +43,7 @@
         'packet-socket-address.h',
         'node.h',
         'ipv4-address.h',
+        'ipv4-address-generator.h',
         'net-device.h',
 	'address-utils.h',
         'ipv4-route.h',