Add new method for determining whether Ipv4 dest address is mine; add attribute to control RFC1122 behavior
authorTom Henderson <tomh@tomh.org>
Thu, 19 Nov 2009 14:39:01 -0800
changeset 5760 4f08a0837018
parent 5759 5d37cccf96c3
child 5761 55f21c521021
Add new method for determining whether Ipv4 dest address is mine; add attribute to control RFC1122 behavior
CHANGES.html
src/internet-stack/ipv4-l3-protocol.cc
src/internet-stack/ipv4-l3-protocol.h
src/node/ipv4.cc
src/node/ipv4.h
src/routing/list-routing/ipv4-list-routing.cc
--- a/CHANGES.html	Thu Nov 19 20:52:09 2009 +0100
+++ b/CHANGES.html	Thu Nov 19 14:39:01 2009 -0800
@@ -59,9 +59,10 @@
 by the ns-3 logging system to report the execution context of each log line.
 <li><b>Object::DoStart</b>: Users who need to complete their object setup at the start of a simulation
 can override this virtual method, perform their adhoc setup, and then, must chain up to their parent.
-
 <li><b>Aod hoc On-Demand Distance Vector (AODV)</b> routing model, 
 <a href=http://www.ietf.org/rfc/rfc3561.txt>RFC 3561</a> </li>
+<li><b>Ipv4::IsDestinationAddress (Ipv4Address address, uint32_t iif)</b> Method added to support checks of whether a destination address should be accepted 
+as one of the host's own addresses.  RFC 1122 Strong/Weak end system behavior can be changed with a new attribute (WeakEsModel) in class Ipv4.  </li>
 
 </ul>
 
--- a/src/internet-stack/ipv4-l3-protocol.cc	Thu Nov 19 20:52:09 2009 +0100
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Thu Nov 19 14:39:01 2009 -0800
@@ -355,6 +355,70 @@
   return -1;
 }
 
+bool
+Ipv4L3Protocol::IsDestinationAddress (Ipv4Address address, uint32_t iif) const
+{
+  NS_LOG_FUNCTION (this << address << " " << iif);
+
+  // First check the incoming interface for a unicast address match
+  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
+    {
+      Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
+      if (address == iaddr.GetLocal ())
+        {
+          NS_LOG_LOGIC ("For me (destination " << address << " match)");
+          return true;
+        }
+      if (address == iaddr.GetBroadcast ())
+        {
+          NS_LOG_LOGIC ("For me (interface broadcast address)");
+          return true;
+        }
+    }
+
+  if (address.IsMulticast ())
+    {
+#ifdef NOTYET
+      if (MulticastCheckGroup (iif, address ))
+#endif
+      if (true)
+        {
+          NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
+          return true;
+        }
+    }
+
+  if (address.IsBroadcast ())
+    {
+      NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
+      return true;
+    }
+
+  if (GetWeakEsModel ())  // Check other interfaces
+    { 
+      for (uint32_t j = 0; j < GetNInterfaces (); j++)
+        {
+          if (j == uint32_t (iif)) continue;
+          for (uint32_t i = 0; i < GetNAddresses (j); i++)
+            {
+              Ipv4InterfaceAddress iaddr = GetAddress (j, i);
+              if (address == iaddr.GetLocal ())
+                {
+                  NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
+                  return true;
+                }
+              //  This is a small corner case:  match another interface's broadcast address
+              if (address == iaddr.GetBroadcast ())
+                {
+                  NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
+                  return true;
+                }
+            }
+        }
+    }
+  return false;
+}
+
 void 
 Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
                          const Address &to, NetDevice::PacketType packetType)
@@ -901,6 +965,18 @@
   return m_ipForward;
 }
 
+void 
+Ipv4L3Protocol::SetWeakEsModel (bool model)
+{
+  m_weakEsModel = model;
+}
+
+bool 
+Ipv4L3Protocol::GetWeakEsModel (void) const
+{
+  return m_weakEsModel;
+}
+
 void
 Ipv4L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv4Header & ipHeader, Socket::SocketErrno sockErrno)
 {
--- a/src/internet-stack/ipv4-l3-protocol.h	Thu Nov 19 20:52:09 2009 +0100
+++ b/src/internet-stack/ipv4-l3-protocol.h	Thu Nov 19 14:39:01 2009 -0800
@@ -170,6 +170,7 @@
   int32_t GetInterfaceForAddress (Ipv4Address addr) const;
   int32_t GetInterfaceForPrefix (Ipv4Address addr, Ipv4Mask mask) const;
   int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const;
+  bool IsDestinationAddress (Ipv4Address address, uint32_t iif) const;
 
   bool AddAddress (uint32_t i, Ipv4InterfaceAddress address);
   Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const;
@@ -200,8 +201,11 @@
   Ipv4L3Protocol(const Ipv4L3Protocol &);
   Ipv4L3Protocol &operator = (const Ipv4L3Protocol &);
 
+  // class Ipv4 attributes
   virtual void SetIpForward (bool forward);
   virtual bool GetIpForward (void) const;
+  virtual void SetWeakEsModel (bool model);
+  virtual bool GetWeakEsModel (void) const;
 
   Ipv4Header BuildHeader (
             Ipv4Address source,
@@ -239,6 +243,7 @@
   typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
 
   bool m_ipForward;
+  bool m_weakEsModel;
   L4List_t m_protocols;
   Ipv4InterfaceList m_interfaces;
   uint8_t m_defaultTtl;
--- a/src/node/ipv4.cc	Thu Nov 19 20:52:09 2009 +0100
+++ b/src/node/ipv4.cc	Thu Nov 19 14:39:01 2009 -0800
@@ -37,6 +37,12 @@
                    MakeBooleanAccessor (&Ipv4::SetIpForward,
                                         &Ipv4::GetIpForward),
                    MakeBooleanChecker ())
+    .AddAttribute ("WeakEsModel", 
+                   "RFC1122 term for whether host accepts datagram with a dest. address on another interface",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&Ipv4::SetWeakEsModel,
+                                        &Ipv4::GetWeakEsModel),
+                   MakeBooleanChecker ())
 #if 0
     .AddAttribute ("MtuDiscover", "If enabled, every outgoing ip packet will have the DF flag set.",
                    BooleanValue (false),
--- a/src/node/ipv4.h	Thu Nov 19 20:52:09 2009 +0100
+++ b/src/node/ipv4.h	Thu Nov 19 14:39:01 2009 -0800
@@ -123,11 +123,33 @@
    * This method searches the list of interfaces for one that holds a
    * particular address.  This call takes an IP address as a parameter and
    * returns the interface number of the first interface that has been assigned
-   * that address, or -1 if not found.  There must be an exact match.
+   * that address, or -1 if not found.  There must be an exact match; this
+   * method will not match broadcast or multicast addresses.
    */
   virtual int32_t GetInterfaceForAddress (Ipv4Address address) const = 0;
 
   /**
+   * \brief Determine whether address and interface corresponding to
+   *        received packet can be accepted for local delivery
+   *
+   * \param address The IP address being considered
+   * \param iif The incoming Ipv4 interface index
+   *
+   * This method can be used to determine whether a received packet has
+   * an acceptable address for local delivery on the host.  The address
+   * may be a unicast, multicast, or broadcast address.  This method will
+   * return true if address is an exact match of a unicast address on
+   * one of the host's interfaces (see below), if address corresponds to 
+   * a multicast group that the host has joined (and the incoming device
+   * is acceptable), or if address corresponds to a broadcast address.
+   *
+   * If the Ipv4 attribute WeakEsModel is true, the unicast address may
+   * match any of the Ipv4 addresses on any interface.  If the attribute is
+   * false, the address must match one assigned to the incoming device.
+   */
+  virtual bool IsDestinationAddress (Ipv4Address address, uint32_t iif) const = 0;
+
+  /**
    * \brief Return the interface number of first interface found that 
    *  has an Ipv4 address within the prefix specified by the input
    *  address and mask parameters
@@ -257,6 +279,8 @@
   // Indirect the Ipv4 attributes through private pure virtual methods
   virtual void SetIpForward (bool forward) = 0;
   virtual bool GetIpForward (void) const = 0;
+  virtual void SetWeakEsModel (bool model) = 0;
+  virtual bool GetWeakEsModel (void) const = 0;
 };
 
 } // namespace ns3 
--- a/src/routing/list-routing/ipv4-list-routing.cc	Thu Nov 19 20:52:09 2009 +0100
+++ b/src/routing/list-routing/ipv4-list-routing.cc	Thu Nov 19 14:39:01 2009 -0800
@@ -121,75 +121,21 @@
   NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
   uint32_t iif = m_ipv4->GetInterfaceForDevice (idev); 
 
-  // Multicast recognition; handle local delivery here
-  //
-  if (header.GetDestination().IsMulticast ())
-    {
-#ifdef NOTYET
-      if (m_ipv4->MulticastCheckGroup (iif, header.GetDestination ()))
-#endif
-      if (true)
-        {
-          NS_LOG_LOGIC ("Multicast packet for me-- local deliver");
-          Ptr<Packet> packetCopy = p->Copy();
-          // Here may want to disable lcb callback in recursive RouteInput
-          // call below
-          lcb (packetCopy, header, iif);
-          // Fall through-- we may also need to forward this
-          retVal = true;
-        }
-      for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
-         m_routingProtocols.begin (); rprotoIter != m_routingProtocols.end ();
-           rprotoIter++)
-        {
-          NS_LOG_LOGIC ("Multicast packet for me-- trying to forward");
-          if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
-            {
-              retVal = true;
-            }
-        }
-      return retVal;
-    }
-
-  if (header.GetDestination ().IsBroadcast ())
+  retVal = m_ipv4->IsDestinationAddress (header.GetDestination (), iif);
+  if (retVal == true)
     {
-      NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
-      // TODO:  Local Deliver for broadcast
-      // TODO:  Forward broadcast
-    }
-
- // TODO:  Configurable option to enable RFC 1222 Strong End System Model
- // Right now, we will be permissive and allow a source to send us
- // a packet to one of our other interface addresses; that is, the
- // destination unicast address does not match one of the iif addresses,
- // but we check our other interfaces.  This could be an option
- // (to remove the outer loop immediately below and just check iif).
-  for (uint32_t j = 0; j < m_ipv4->GetNInterfaces (); j++)
-    {
-      for (uint32_t i = 0; i < m_ipv4->GetNAddresses (j); i++)
+      NS_LOG_LOGIC ("Address "<< header.GetDestination () << " is a match for local delivery");
+      if (header.GetDestination ().IsMulticast ())
         {
-          Ipv4InterfaceAddress iaddr = m_ipv4->GetAddress (j, i);
-          Ipv4Address addr = iaddr.GetLocal ();
-          if (addr.IsEqual (header.GetDestination ()))
-            {
-              if (j == iif)
-                {
-                  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
-                }
-              else
-                {
-                  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestination ());
-                }
-              lcb (p, header, iif);
-              return true;
-            }
-          if (header.GetDestination ().IsEqual (iaddr.GetBroadcast ()))
-            {
-              NS_LOG_LOGIC ("For me (interface broadcast address)");
-              lcb (p, header, iif);
-              return true;
-            }
-          NS_LOG_LOGIC ("Address "<< addr << " not a match");
+          Ptr<Packet> packetCopy = p->Copy();
+          lcb (packetCopy, header, iif);
+          retVal = true;
+          // Fall through
+        }
+      else
+        {
+          lcb (p, header, iif);
+          return true;
         }
     }
   // Check if input device supports IP forwarding
@@ -200,13 +146,21 @@
       return false;
     }
   // Next, try to find a route
+  // If we have already delivered a packet locally (e.g. multicast)
+  // we suppress further downstream local delivery by nulling the callback
+  LocalDeliverCallback downstreamLcb = lcb;
+  if (retVal == true)
+    {
+      downstreamLcb = MakeNullCallback<void, Ptr<const Packet>, const Ipv4Header &, uint32_t > ();
+    }
   for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
          m_routingProtocols.begin ();
        rprotoIter != m_routingProtocols.end ();
        rprotoIter++)
     {
-      if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
+      if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, downstreamLcb, ecb))
         {
+          NS_LOG_LOGIC ("Route found to forward packet in protocol " << (*rprotoIter).second->GetInstanceTypeId ().GetName ()); 
           return true;
         }
     }