diff -r 0acf7562923c src/routing/aodv/aodv-routing-protocol.cc --- a/src/routing/aodv/aodv-routing-protocol.cc Thu Aug 05 19:45:55 2010 +0200 +++ b/src/routing/aodv/aodv-routing-protocol.cc Sat Aug 07 15:37:04 2010 -0700 @@ -265,7 +265,7 @@ NS_LOG_FUNCTION (this << header << (oif? oif->GetIfIndex () : 0)); if (! p) { - return LoopbackRoute (header); // later + return LoopbackRoute (header, oif); // later } if (m_socketAddresses.empty ()) { @@ -303,7 +303,7 @@ { p->AddPacketTag (tag); } - return LoopbackRoute (header); + return LoopbackRoute (header, oif); } void @@ -689,13 +689,48 @@ } Ptr -RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr) const +RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr, Ptr oif) const { NS_LOG_FUNCTION (this << hdr); NS_ASSERT (m_lo != 0); Ptr rt = Create (); rt->SetDestination (hdr.GetDestination ()); - rt->SetSource (Ipv4Address ("127.0.0.1")); + // + // Source address selection here is tricky. The loopback route is + // returned when AODV does not have a route; this causes the packet + // to be looped back and handled (cached) in RouteInput() method + // while a route is found. However, connection-oriented protocols + // like TCP need to create an endpoint four-tuple (src, src port, + // dst, dst port) and create a pseudo-header for checksumming. So, + // AODV needs to guess correctly what the eventual source address + // will be. + // + // For single interface, single address nodes, this is not a problem. + // When there are possibly multiple outgoing interfaces, the policy + // implemented here is to pick the first available AODV interface. + // If RouteOutput() caller specified an outgoing interface, that + // further constrains the selection of source address + // + std::map , Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); + if (oif) + { + // Iterate to find an address on the oif device + for (j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j) + { + Ipv4Address addr = j->second.GetLocal (); + int32_t interface = m_ipv4->GetInterfaceForAddress (addr); + if (oif == m_ipv4->GetNetDevice (static_cast (interface))) + { + rt->SetSource (addr); + break; + } + } + } + else + { + rt->SetSource (j->second.GetLocal ()); + } + NS_ASSERT_MSG (rt->GetSource() != Ipv4Address (), "Valid AODV source address not found"); rt->SetGateway (Ipv4Address ("127.0.0.1")); rt->SetOutputDevice (m_lo); return rt; diff -r 0acf7562923c src/routing/aodv/aodv-routing-protocol.h --- a/src/routing/aodv/aodv-routing-protocol.h Thu Aug 05 19:45:55 2010 +0200 +++ b/src/routing/aodv/aodv-routing-protocol.h Sat Aug 07 15:37:04 2010 -0700 @@ -180,7 +180,7 @@ /// Process hello message void ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiverIfaceAddr); /// Create loopback route for given header - Ptr LoopbackRoute (const Ipv4Header & header) const; + Ptr LoopbackRoute (const Ipv4Header & header, Ptr oif) const; ///\name Receive control packets //\{