src/internet-stack/ipv4-l3-protocol.cc
changeset 4969 106e7a5e4efc
parent 4966 29d73c832841
parent 4379 44c7757fb216
child 5028 01f02baebba9
--- a/src/internet-stack/ipv4-l3-protocol.cc	Tue Apr 21 16:13:45 2009 +0400
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Tue Apr 21 16:22:45 2009 +0400
@@ -53,7 +53,7 @@
 Ipv4L3Protocol::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
-    .SetParent<Object> ()
+    .SetParent<Ipv4> ()
     .AddConstructor<Ipv4L3Protocol> ()
     .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
                    UintegerValue (64),
@@ -181,8 +181,8 @@
 
   Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> ();
   interface->SetNode (m_node);
-  interface->SetAddress (Ipv4Address::GetLoopback ());
-  interface->SetNetworkMask (Ipv4Mask::GetLoopback ());
+  Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
+  interface->AddAddress (ifaceAddr);
   uint32_t index = AddIpv4Interface (interface);
   AddHostRouteTo (Ipv4Address::GetLoopback (), index);
   interface->SetUp ();
@@ -248,17 +248,17 @@
 {
   NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply);
 
-  Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
+  Lookup (Ipv4RoutingProtocol::INTERFACE_ANY, ipHeader, packet, routeReply);
 }
 
 void
 Ipv4L3Protocol::Lookup (
-  uint32_t ifIndex,
+  uint32_t interface,
   Ipv4Header const &ipHeader,
   Ptr<Packet> packet,
   Ipv4RoutingProtocol::RouteReplyCallback routeReply)
 {
-  NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply);
+  NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply);
 
   for (Ipv4RoutingProtocolList::const_iterator rprotoIter = 
          m_routingProtocols.begin ();
@@ -266,13 +266,13 @@
        rprotoIter++)
     {
       NS_LOG_LOGIC ("Requesting route");
-      if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, 
+      if ((*rprotoIter).second->RequestRoute (interface, ipHeader, packet, 
                                               routeReply))
         return;
     }
 
   if (ipHeader.GetDestination ().IsMulticast () && 
-      ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
+      interface == Ipv4RoutingProtocol::INTERFACE_ANY)
     {
       NS_LOG_LOGIC ("Multicast destination with local source");
 //
@@ -304,7 +304,7 @@
 
 void
 Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
-                                    int priority)
+                                    int16_t priority)
 {
   NS_LOG_FUNCTION (this << &routingProtocol << priority);
   m_routingProtocols.push_back
@@ -319,11 +319,11 @@
   return m_staticRouting->GetNRoutes ();
 }
 
-Ipv4Route *
+Ipv4Route 
 Ipv4L3Protocol::GetRoute (uint32_t index)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  return m_staticRouting->GetRoute (index);
+  return *m_staticRouting->GetRoute (index);
 }
 
 void 
@@ -360,11 +360,11 @@
   return m_staticRouting->GetNMulticastRoutes ();
 }
 
-Ipv4MulticastRoute *
+Ipv4MulticastRoute 
 Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
 {
   NS_LOG_FUNCTION (this << index);
-  return m_staticRouting->GetMulticastRoute (index);
+  return *m_staticRouting->GetMulticastRoute (index);
 }
 
 void 
@@ -438,14 +438,17 @@
 {
   NS_LOG_FUNCTION (this << addr);
 
-  uint32_t ifIndex = 0;
+  uint32_t interface = 0;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
        i != m_interfaces.end (); 
-       i++, ifIndex++)
+       i++, interface++)
     {
-      if ((*i)->GetAddress () == addr)
+      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++) 
         {
-          return ifIndex;
+          if ((*i)->GetAddress (j).GetLocal () == addr)
+            {
+              return interface;
+            }
         }
     }
 
@@ -459,14 +462,17 @@
 {
   NS_LOG_FUNCTION (this << addr << mask);
 
-  uint32_t ifIndex = 0;
+  uint32_t interface = 0;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
        i != m_interfaces.end (); 
-       i++, ifIndex++)
+       i++, interface++)
     {
-      if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask))
+      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
         {
-          return ifIndex;
+          if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == addr.CombineMask (mask))
+            {
+              return interface;
+            }
         }
     }
 
@@ -476,18 +482,18 @@
 }
 
 int32_t 
-Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr<NetDevice> device) const
+Ipv4L3Protocol::FindInterfaceForDevice (Ptr<NetDevice> device) const
 {
   NS_LOG_FUNCTION (this << device);
 
-  uint32_t ifIndex = 0;
+  uint32_t interface = 0;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
        i != m_interfaces.end (); 
-       i++, ifIndex++)
+       i++, interface++)
     {
       if ((*i)->GetDevice () == device)
         {
-          return ifIndex;
+          return interface;
         }
     }
 
@@ -647,11 +653,15 @@
            ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
         {
           Ptr<Ipv4Interface> outInterface = *ifaceIter;
-          if (destination.IsSubnetDirectedBroadcast (
-                outInterface->GetNetworkMask ()))
-          {
-            ipHeader.SetTtl (1);
-          }
+          // XXX this logic might not be completely correct for multi-addressed interface
+          for (uint32_t j = 0; j < outInterface->GetNAddresses(); j++)
+            {
+              if (destination.IsSubnetDirectedBroadcast (
+                outInterface->GetAddress (j).GetMask ()))
+                {
+                  ipHeader.SetTtl (1);
+                }
+            }
         }
     }
   if (destination.IsBroadcast ())
@@ -664,9 +674,10 @@
           Ptr<Packet> packetCopy = packet->Copy ();
 
           packetCopy->AddHeader (ipHeader);
+          // XXX Handle multiple address on interface
           if (packetCopy->GetSize () > outInterface->GetMtu () &&
               ipHeader.IsDontFragment () &&
-              IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ()))
+              IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
             {
               Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
               NS_ASSERT (icmp != 0);
@@ -728,9 +739,10 @@
   NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
 
   Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
+  // XXX handle multiple address on interface
   if (packet->GetSize () > outInterface->GetMtu () &&
       ipHeader.IsDontFragment () &&
-      IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ()))
+      IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
     {
       NS_LOG_LOGIC ("Too big: need fragmentation but not allowed");
       Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
@@ -782,21 +794,24 @@
 
 bool
 Ipv4L3Protocol::Forwarding (
-  uint32_t ifIndex, 
+  uint32_t interface, 
   Ptr<Packet> packet, 
   Ipv4Header &ipHeader, 
   Ptr<NetDevice> device)
 {
-  NS_LOG_FUNCTION (ifIndex << packet << &ipHeader<< device);
+  NS_LOG_FUNCTION (interface << packet << &ipHeader<< device);
   NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
 
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
        i != m_interfaces.end (); i++) 
     {
-      if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) 
+      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
         {
-          NS_LOG_LOGIC ("For me (destination match)");
-          return false;
+          if ((*i)->GetAddress (j).GetLocal ().IsEqual (ipHeader.GetDestination ())) 
+            {
+              NS_LOG_LOGIC ("For me (destination match)");
+              return false;
+            }
         }
     }
   
@@ -806,7 +821,8 @@
       Ptr<Ipv4Interface> interface = *i;
       if (interface->GetDevice () == device)
 	{
-	  if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) 
+          // XXX multi-address case
+	  if (ipHeader.GetDestination ().IsEqual (interface->GetAddress (0).GetBroadcast ())) 
 	    {
               NS_LOG_LOGIC ("For me (interface broadcast address)");
 	      return false;
@@ -840,26 +856,27 @@
           // We forward with a packet copy, since forwarding may change
           // the packet, affecting our local delivery
           NS_LOG_LOGIC ("Forwarding (multicast).");
-          DoForward (ifIndex, packet->Copy (), ipHeader);
+          DoForward (interface, packet->Copy (), ipHeader);
           return false;
         }   
     }
 
-  DoForward (ifIndex, packet, ipHeader);
+  DoForward (interface, packet, ipHeader);
   return true;
 }
 
 void
-Ipv4L3Protocol::DoForward (uint32_t ifIndex, 
+Ipv4L3Protocol::DoForward (uint32_t interface, 
                            Ptr<Packet> packet, 
                            Ipv4Header ipHeader)
 {
-  NS_LOG_FUNCTION (this << ifIndex << packet << ipHeader);
+  NS_LOG_FUNCTION (this << interface << packet << ipHeader);
 
   ipHeader.SetTtl (ipHeader.GetTtl () - 1);
+  // XXX handle multi-interfaces
   if (ipHeader.GetTtl () == 0)
     {
-      if (IsUnicast (ipHeader.GetDestination (), GetInterface (ifIndex)->GetNetworkMask ()))
+      if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetAddress (0).GetMask ()))
         {
           Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
           icmp->SendTimeExceededTtl (ipHeader, packet);
@@ -869,7 +886,7 @@
       return;
     }  
   NS_LOG_LOGIC ("Not for me, forwarding.");
-  Lookup (ifIndex, ipHeader, packet,
+  Lookup (interface, ipHeader, packet,
           MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
 }
 
@@ -894,7 +911,8 @@
       case Ipv4L4Protocol::RX_CSUM_FAILED:
         break;
       case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
-        if (IsUnicast (ip.GetDestination (), incomingInterface->GetNetworkMask ()))
+        // XXX handle multi-interface case
+        if (IsUnicast (ip.GetDestination (), incomingInterface->GetAddress (0).GetMask ()))
           {
             GetIcmp ()->SendDestUnreachPort (ip, copy);
           }
@@ -928,36 +946,28 @@
     }
 }
 
-void 
-Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
+uint32_t
+Ipv4L3Protocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
 {
   NS_LOG_FUNCTION (this << i << address);
   Ptr<Ipv4Interface> interface = GetInterface (i);
-  interface->SetAddress (address);
-}
-
-void 
-Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask)
-{
-  NS_LOG_FUNCTION (this << i << mask);
-  Ptr<Ipv4Interface> interface = GetInterface (i);
-  interface->SetNetworkMask (mask);
+  return interface->AddAddress (address);
 }
 
-Ipv4Mask 
-Ipv4L3Protocol::GetNetworkMask (uint32_t i) const
+Ipv4InterfaceAddress
+Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
 {
-  NS_LOG_FUNCTION (this << i);
-  Ptr<Ipv4Interface> interface = GetInterface (i);
-  return interface->GetNetworkMask ();
+  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
+  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
+  return interface->GetAddress (addressIndex);
 }
 
-Ipv4Address 
-Ipv4L3Protocol::GetAddress (uint32_t i) const
+uint32_t
+Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
 {
-  NS_LOG_FUNCTION (this << i);
-  Ptr<Ipv4Interface> interface = GetInterface (i);
-  return interface->GetAddress ();
+  NS_LOG_FUNCTION (this << interface);
+  Ptr<Ipv4Interface> iface = GetInterface (interface);
+  return iface->GetNAddresses ();
 }
 
 void 
@@ -977,10 +987,10 @@
 }
 
 bool
-Ipv4L3Protocol::GetIfIndexForDestination (
-  Ipv4Address destination, uint32_t& ifIndex) const
+Ipv4L3Protocol::GetInterfaceForDestination (
+  Ipv4Address destination, uint32_t& interface) const
 {
-  NS_LOG_FUNCTION (this << destination << &ifIndex);
+  NS_LOG_FUNCTION (this << destination << &interface);
 //
 // The first thing we do in trying to determine a source address is to 
 // consult the routing protocols.  These will also check for a default route
@@ -991,12 +1001,12 @@
        i++)
     {
       NS_LOG_LOGIC ("Requesting Source Address");
-      uint32_t ifIndexTmp;
+      uint32_t interfaceTmp;
 
-      if ((*i).second->RequestIfIndex (destination, ifIndexTmp))
+      if ((*i).second->RequestInterface (destination, interfaceTmp))
         {
-          NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp);
-          ifIndex = ifIndexTmp;
+          NS_LOG_LOGIC ("Found interface " << interfaceTmp);
+          interface = interfaceTmp;
           return true;
         }
     }
@@ -1012,7 +1022,7 @@
   if (GetNInterfaces () == 2)
     {
       NS_LOG_LOGIC ("One Interface.  Using interface 1.");
-      ifIndex = 1;
+      interface = 1;
       return true;
     }
 //
@@ -1035,14 +1045,14 @@
 
   if (route == NULL)
     {
-      NS_LOG_LOGIC ("Ipv4L3Protocol::GetIfIndexForDestination (): "
+      NS_LOG_LOGIC ("Ipv4L3Protocol::GetInterfaceForDestination (): "
                     "Unable to determine outbound interface.  No default route set");
       return false;
     }
 
-  ifIndex = route->GetInterface ();
+  interface = route->GetInterface ();
 
-  NS_LOG_LOGIC ("Default route specifies interface " << ifIndex);
+  NS_LOG_LOGIC ("Default route specifies interface " << interface);
   return true;
 }
 
@@ -1072,11 +1082,13 @@
   // If interface address and network mask have been set, add a route
   // to the network of the interface (like e.g. ifconfig does on a
   // Linux box)
-  if (((interface->GetAddress ()) != (Ipv4Address ()))
-      && (interface->GetNetworkMask ()) != (Ipv4Mask ()))
+  for (uint32_t j = 0; j < interface->GetNAddresses (); j++)
     {
-      AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()),
-                         interface->GetNetworkMask (), i);
+      if (((interface->GetAddress (j).GetLocal ()) != (Ipv4Address ()))
+          && (interface->GetAddress (j).GetMask ()) != (Ipv4Mask ()))
+        {
+          AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()), interface->GetAddress (j).GetMask (), i);
+        }
     }
 }
 
@@ -1094,8 +1106,8 @@
       modified = false;
       for (uint32_t i = 0; i < GetNRoutes (); i++)
         {
-          Ipv4Route *route = GetRoute (i);
-          if (route->GetInterface () == ifaceIndex)
+          Ipv4Route route = GetRoute (i);
+          if (route.GetInterface () == ifaceIndex)
             {
               RemoveRoute (i);
               modified = true;
@@ -1105,4 +1117,43 @@
     }
 }
 
+// Note:  This method will be removed in Ipv4 routing work
+Ipv4Address
+Ipv4L3Protocol::GetSourceAddress (Ipv4Address destination) const
+{
+  uint32_t interface = 0xffffffff;
+
+  bool result = GetInterfaceForDestination (destination, interface);
+
+  if (result)
+    {
+      // if multiple addresses exist, search for the first one on the same subnet
+      for (uint32_t i = 0; i < GetNAddresses (interface); i++)
+        {
+          Ipv4InterfaceAddress ipv4InAddr = GetAddress (interface, i);
+          if (ipv4InAddr.GetLocal().CombineMask(ipv4InAddr.GetMask ()) == destination.CombineMask (ipv4InAddr.GetMask ()))
+            {
+              return ipv4InAddr.GetLocal ();
+            }
+        }
+      // Destination is off-link, so return first address.
+      return GetAddress (interface, 0).GetLocal ();
+    }
+  else
+    {
+//
+// If we can't find any address, just leave it 0.0.0.0
+//
+      return Ipv4Address::GetAny ();
+    }
+}
+
+Ptr<NetDevice>
+Ipv4L3Protocol::GetNetDevice (uint32_t i)
+{
+  return GetInterface (i)-> GetDevice ();
+}
+
+
+
 }//namespace ns3