--- /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',