# HG changeset patch # User Tom Henderson # Date 1260602617 28800 # Node ID b40d352e92bc4f4b0ab0abc863658382312c266e # Parent 74d9ac708677fd927b3893ab63e12fd50f4c0232 possible fix for bug 606 diff -r 74d9ac708677 -r b40d352e92bc src/internet-stack/arp-l3-protocol.cc --- a/src/internet-stack/arp-l3-protocol.cc Fri Dec 11 11:48:12 2009 -0500 +++ b/src/internet-stack/arp-l3-protocol.cc Fri Dec 11 23:23:37 2009 -0800 @@ -23,7 +23,6 @@ #include "ns3/net-device.h" #include "ns3/object-vector.h" #include "ns3/trace-source-accessor.h" -#include "ns3/ipv4-route.h" #include "ipv4-l3-protocol.h" #include "arp-l3-protocol.h" @@ -320,19 +319,15 @@ NS_ASSERT (interface >= 0); Ipv4Header header; header.SetDestination (to); - Socket::SocketErrno errno_; Ptr packet = Create (); - Ptr route = ipv4->GetRoutingProtocol ()->RouteOutput (packet, header, interface, errno_); - NS_ASSERT (route != 0); + Ipv4Address source = ipv4->SelectSourceAddress (cache->GetDevice (), to, Ipv4InterfaceAddress::GLOBAL); NS_LOG_LOGIC ("ARP: sending request from node "<GetId ()<< " || src: " << cache->GetDevice ()->GetAddress () << - " / " << route->GetSource () << + " / " << source << " || dst: " << cache->GetDevice ()->GetBroadcast () << " / " << to); - arp.SetRequest (cache->GetDevice ()->GetAddress (), - route->GetSource (), - cache->GetDevice ()->GetBroadcast (), - to); + arp.SetRequest (cache->GetDevice ()->GetAddress (), source, + cache->GetDevice ()->GetBroadcast (), to); packet->AddHeader (arp); cache->GetDevice ()->Send (packet, cache->GetDevice ()->GetBroadcast (), PROT_NUMBER); } diff -r 74d9ac708677 -r b40d352e92bc src/internet-stack/ipv4-l3-protocol.cc --- a/src/internet-stack/ipv4-l3-protocol.cc Fri Dec 11 11:48:12 2009 -0500 +++ b/src/internet-stack/ipv4-l3-protocol.cc Fri Dec 11 23:23:37 2009 -0800 @@ -866,6 +866,59 @@ return false; } +Ipv4Address +Ipv4L3Protocol::SelectSourceAddress (Ptr device, + Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope) +{ + NS_LOG_FUNCTION (device << dst << scope); + Ipv4Address addr ("0.0.0.0"); + Ipv4InterfaceAddress iaddr; + bool found = false; + + if (device != 0) + { + int32_t i = GetInterfaceForDevice (device); + NS_ASSERT_MSG (i >= 0, "No device found on node"); + for (uint32_t j = 0; j < GetNAddresses (i); j++) + { + iaddr = GetAddress (i, j); + if (iaddr.IsSecondary ()) continue; + if (iaddr.GetScope () > scope) continue; + if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) ) + { + return iaddr.GetLocal (); + } + if (!found) + { + addr = iaddr.GetLocal (); + found = true; + } + } + } + if (found) + { + return addr; + } + + // Iterate among all interfaces + for (uint32_t i = 0; i < GetNInterfaces (); i++) + { + for (uint32_t j = 0; j < GetNAddresses (i); j++) + { + iaddr = GetAddress (i, j); + if (iaddr.IsSecondary ()) continue; + if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK + && iaddr.GetScope () <= scope) + { + return iaddr.GetLocal (); + } + } + } + NS_LOG_WARN ("Could not find source address for " << dst << " and scope " + << scope << ", returning 0"); + return addr; +} + void Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric) { diff -r 74d9ac708677 -r b40d352e92bc src/internet-stack/ipv4-l3-protocol.h --- a/src/internet-stack/ipv4-l3-protocol.h Fri Dec 11 11:48:12 2009 -0500 +++ b/src/internet-stack/ipv4-l3-protocol.h Fri Dec 11 23:23:37 2009 -0800 @@ -176,6 +176,9 @@ Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; uint32_t GetNAddresses (uint32_t interface) const; bool RemoveAddress (uint32_t interfaceIndex, uint32_t addressIndex); + Ipv4Address SelectSourceAddress (Ptr device, + Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope); + void SetMetric (uint32_t i, uint16_t metric); uint16_t GetMetric (uint32_t i) const; diff -r 74d9ac708677 -r b40d352e92bc src/node/ipv4.h --- a/src/node/ipv4.h Fri Dec 11 11:48:12 2009 -0500 +++ b/src/node/ipv4.h Fri Dec 11 23:23:37 2009 -0800 @@ -216,6 +216,44 @@ virtual bool RemoveAddress (uint32_t interface, uint32_t addressIndex) = 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 + * destination dst out of the specified device. + * + * This method mirrors the behavior of Linux inet_select_addr() and is + * provided because interfaces may have multiple IP addresses configured + * on them with different scopes, and with a primary and secondary status. + * Secondary addresses are never returned. + * \see Ipv4InterfaceAddress + * + * If a non-zero device pointer is provided, the method first tries to + * return a primary address that is configured on that device, and whose + * subnet matches that of dst and whose scope is less than or equal to + * the requested scope. If a primary address does not match the + * subnet of dst but otherwise matches the scope, it is returned. + * If no such address on the device is found, the other devices are + * searched in order of their interface index, but not considering dst + * as a factor in the search. Because a loopback interface is typically + * the first one configured on a node, it will be the first alternate + * device to be tried. Addresses scoped at LINK scope are not returned + * in this phase. + * + * If no device pointer is provided, the same logic as above applies, only + * that there is no preferred device that is consulted first. This means + * that if the device pointer is null, input parameter dst will be ignored. + * + * If there are no possible addresses to return, a warning log message + * is issued and the all-zeroes address is returned. + * + * \param device output NetDevice (optionally provided, only to constrain the search) + * \param dst Destination address to match, if device is provided + * \param scope Scope of returned address must be less than or equal to this + * \returns the first primary Ipv4Address that meets the search criteria + */ + virtual Ipv4Address SelectSourceAddress (Ptr device, + Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope) = 0; + + /** * \param interface The interface number of an Ipv4 interface * \param metric routing metric (cost) associated to the underlying * Ipv4 interface