cleanup ip alias unfinished cases (bug 591)

This commit is contained in:
Tom Henderson
2009-06-21 22:29:08 -07:00
parent 21fb8dd090
commit 441cedb655
11 changed files with 246 additions and 83 deletions

View File

@@ -102,8 +102,10 @@ main (int argc, char *argv[])
// Create an optional packet sink to receive these packets
PacketSinkHelper sink ("ns3::UdpSocketFactory",
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
sink.Install (c0.Get (1));
sink.Install (c1.Get (1));
app = sink.Install (c0.Get (1));
app.Add (sink.Install (c1.Get (1)));
app.Start (Seconds (1.0));
app.Stop (Seconds (10.0));
// Also configure some tcpdump traces; each interface will be traced
// The output files will be named

View File

@@ -23,6 +23,7 @@
#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"
@@ -160,73 +161,82 @@ ArpL3Protocol::Receive(Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t prot
NS_LOG_LOGIC ("ARP: Cannot remove ARP header");
return;
}
// XXX multi-address case
NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") <<
" node="<<m_node->GetId ()<<", got request from " <<
arp.GetSourceIpv4Address () << " for address " <<
arp.GetDestinationIpv4Address () << "; we have address " <<
cache->GetInterface ()->GetAddress (0).GetLocal ());
arp.GetDestinationIpv4Address () << "; we have addresses: ");
for (uint32_t i = 0; i < cache->GetInterface ()->GetNAddresses (); i++)
{
NS_LOG_LOGIC (cache->GetInterface ()->GetAddress (i).GetLocal () << ", ");
}
/**
* Note: we do not update the ARP cache when we receive an ARP request
* from an unknown node. See bug #107
*/
// XXX multi-address case
if (arp.IsRequest () &&
arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress (0).GetLocal ())
bool found = false;
for (uint32_t i = 0; i < cache->GetInterface ()->GetNAddresses (); i++)
{
NS_LOG_LOGIC ("node="<<m_node->GetId () <<", got request from " <<
arp.GetSourceIpv4Address () << " -- send reply");
SendArpReply (cache, arp.GetSourceIpv4Address (),
arp.GetSourceHardwareAddress ());
}
// XXX multi-address case
else if (arp.IsReply () &&
arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress (0).GetLocal ()) &&
arp.GetDestinationHardwareAddress () == device->GetAddress ())
{
Ipv4Address from = arp.GetSourceIpv4Address ();
ArpCache::Entry *entry = cache->Lookup (from);
if (entry != 0)
if (arp.IsRequest () && arp.GetDestinationIpv4Address () ==
cache->GetInterface ()->GetAddress (i).GetLocal ())
{
if (entry->IsWaitReply ())
found = true;
NS_LOG_LOGIC ("node="<<m_node->GetId () <<", got request from " <<
arp.GetSourceIpv4Address () << " -- send reply");
SendArpReply (cache, arp.GetSourceIpv4Address (),
arp.GetSourceHardwareAddress ());
break;
}
else if (arp.IsReply () &&
arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress (i).GetLocal ()) &&
arp.GetDestinationHardwareAddress () == device->GetAddress ())
{
found = true;
Ipv4Address from = arp.GetSourceIpv4Address ();
ArpCache::Entry *entry = cache->Lookup (from);
if (entry != 0)
{
NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply from " <<
arp.GetSourceIpv4Address ()
<< " for waiting entry -- flush");
Address from_mac = arp.GetSourceHardwareAddress ();
entry->MarkAlive (from_mac);
Ptr<Packet> pending = entry->DequeuePending();
while (pending != 0)
if (entry->IsWaitReply ())
{
cache->GetInterface ()->Send (pending,
NS_LOG_LOGIC ("node="<< m_node->GetId () <<
", got reply from " << arp.GetSourceIpv4Address ()
<< " for waiting entry -- flush");
Address from_mac = arp.GetSourceHardwareAddress ();
entry->MarkAlive (from_mac);
Ptr<Packet> pending = entry->DequeuePending();
while (pending != 0)
{
cache->GetInterface ()->Send (pending,
arp.GetSourceIpv4Address ());
pending = entry->DequeuePending();
pending = entry->DequeuePending();
}
}
else
{
// ignore this reply which might well be an attempt
// at poisening my arp cache.
NS_LOG_LOGIC("node="<<m_node->GetId ()<<", got reply from " <<
arp.GetSourceIpv4Address () <<
" for non-waiting entry -- drop");
m_dropTrace (packet);
}
}
else
{
// ignore this reply which might well be an attempt
// at poisening my arp cache.
NS_LOG_LOGIC("node="<<m_node->GetId ()<<", got reply from " <<
arp.GetSourceIpv4Address () <<
" for non-waiting entry -- drop");
NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply for unknown entry -- drop");
m_dropTrace (packet);
}
}
else
{
NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply for unknown entry -- drop");
m_dropTrace (packet);
break;
}
}
else
if (found == false)
{
NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got request from " <<
arp.GetSourceIpv4Address () << " for unknown address " <<
arp.GetDestinationIpv4Address () << " -- drop");
}
}
bool
ArpL3Protocol::Lookup (Ptr<Packet> packet, Ipv4Address destination,
Ptr<NetDevice> device,
@@ -301,14 +311,22 @@ ArpL3Protocol::SendArpRequest (Ptr<const ArpCache> cache, Ipv4Address to)
{
NS_LOG_FUNCTION (this << cache << to);
ArpHeader arp;
// need to pick a source address; use routing implementation to select
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
int32_t interface = ipv4->GetInterfaceForDevice (cache->GetDevice ());
NS_ASSERT (interface >= 0);
Ipv4Header header;
header.SetDestination (to);
Socket::SocketErrno errno_;
Ptr<Ipv4Route> route = ipv4->GetRoutingProtocol ()->RouteOutput (header, interface, errno_);
NS_ASSERT (route != 0);
NS_LOG_LOGIC ("ARP: sending request from node "<<m_node->GetId ()<<
" || src: " << cache->GetDevice ()->GetAddress () <<
" / " << cache->GetInterface ()->GetAddress (0).GetLocal () <<
" / " << route->GetSource () <<
" || dst: " << cache->GetDevice ()->GetBroadcast () <<
" / " << to);
// XXX multi-address case
arp.SetRequest (cache->GetDevice ()->GetAddress (),
cache->GetInterface ()->GetAddress (0).GetLocal (),
route->GetSource (),
cache->GetDevice ()->GetBroadcast (),
to);
Ptr<Packet> packet = Create<Packet> ();
@@ -321,14 +339,21 @@ ArpL3Protocol::SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Addres
{
NS_LOG_FUNCTION (this << cache << toIp << toMac);
ArpHeader arp;
// need to pick a source address; use routing implementation to select
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
int32_t interface = ipv4->GetInterfaceForDevice (cache->GetDevice ());
NS_ASSERT (interface >= 0);
Ipv4Header header;
header.SetDestination (toIp);
Socket::SocketErrno errno_;
Ptr<Ipv4Route> route = ipv4->GetRoutingProtocol ()->RouteOutput (header, interface, errno_);
NS_ASSERT (route != 0);
NS_LOG_LOGIC ("ARP: sending reply from node "<<m_node->GetId ()<<
"|| src: " << cache->GetDevice ()->GetAddress () <<
" / " << cache->GetInterface ()->GetAddress (0).GetLocal () <<
" / " << route->GetSource () <<
" || dst: " << toMac << " / " << toIp);
// XXX multi-address case
arp.SetReply (cache->GetDevice ()->GetAddress (),
cache->GetInterface ()->GetAddress (0).GetLocal (),
toMac, toIp);
route->GetSource (), toMac, toIp);
Ptr<Packet> packet = Create<Packet> ();
packet->AddHeader (arp);
cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER);

View File

@@ -16,9 +16,7 @@ NS_LOG_COMPONENT_DEFINE ("Icmpv4L4Protocol");
NS_OBJECT_ENSURE_REGISTERED (Icmpv4L4Protocol);
// see rfc 792
enum {
ICMP_PROTOCOL = 1
};
const uint8_t Icmpv4L4Protocol::PROT_NUMBER = 1;
TypeId
Icmpv4L4Protocol::GetTypeId (void)
@@ -68,13 +66,13 @@ Icmpv4L4Protocol::NotifyNewAggregate ()
uint16_t
Icmpv4L4Protocol::GetStaticProtocolNumber (void)
{
return ICMP_PROTOCOL;
return PROT_NUMBER;
}
int
Icmpv4L4Protocol::GetProtocolNumber (void) const
{
return ICMP_PROTOCOL;
return PROT_NUMBER;
}
void
Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code)
@@ -111,7 +109,7 @@ Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Addre
icmp.EnableChecksum ();
}
packet->AddHeader (icmp);
ipv4->Send (packet, source, dest, ICMP_PROTOCOL, route);
ipv4->Send (packet, source, dest, PROT_NUMBER, route);
}
void
Icmpv4L4Protocol::SendDestUnreachFragNeeded (Ipv4Header header,

View File

@@ -15,6 +15,8 @@ class Icmpv4L4Protocol : public Ipv4L4Protocol
{
public:
static TypeId GetTypeId (void);
static const uint8_t PROT_NUMBER;
Icmpv4L4Protocol ();
virtual ~Icmpv4L4Protocol ();

View File

@@ -219,11 +219,19 @@ Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport,
<< " does not match packet dport " << dport);
continue;
}
// XXX handle multi-address case
bool isBroadcast = (daddr.IsBroadcast () ||
daddr.IsSubnetDirectedBroadcast (
incomingInterface->GetAddress (0).GetMask ()));
Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress (0).GetLocal ();
bool subnetDirected = false;
Ipv4Address incomingInterfaceAddr = daddr; // may be a broadcast
for (uint32_t i = 0; i < incomingInterface->GetNAddresses (); i++)
{
Ipv4InterfaceAddress addr = incomingInterface->GetAddress (i);
if (addr.GetLocal ().CombineMask (addr.GetMask ()) == daddr.CombineMask (addr.GetMask ()) &&
daddr.IsSubnetDirectedBroadcast (addr.GetMask ()))
{
subnetDirected = true;
incomingInterfaceAddr = addr.GetLocal ();
}
}
bool isBroadcast = (daddr.IsBroadcast () || subnetDirected == true);
NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast);
bool localAddressMatchesWildCard =
endP->GetLocalAddress() == Ipv4Address::GetAny();

View File

@@ -526,8 +526,8 @@ Ipv4L3Protocol::Send (Ptr<Packet> packet,
// This could arise because the synchronous RouteOutput() call
// returned to the transport protocol with a source address but
// there was no next hop available yet (since a route may need
// to be queried). So, call asynchronous version of RouteOutput?
NS_FATAL_ERROR("XXX This case not yet implemented");
// to be queried).
NS_FATAL_ERROR ("This case not yet implemented");
}
// 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4: passed in with no route " << destination);
@@ -684,11 +684,10 @@ Ipv4L3Protocol::IpForward (Ptr<Ipv4Route> rtentry, Ptr<const Packet> p, const Ip
ipHeader.SetTtl (ipHeader.GetTtl () - 1);
if (ipHeader.GetTtl () == 0)
{
Ptr<NetDevice> outDev = rtentry->GetOutputDevice ();
int32_t interface = GetInterfaceForDevice (outDev);
NS_ASSERT (interface >= 0);
// XXX No check here for possibly multiple addresses on this interface
if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetAddress (0).GetMask ()))
// Do not reply to ICMP or to multicast/broadcast IP address
if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER &&
ipHeader.GetDestination ().IsBroadcast () == false &&
ipHeader.GetDestination ().IsMulticast () == false)
{
Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
icmp->SendTimeExceededTtl (ipHeader, packet);
@@ -720,12 +719,26 @@ Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uin
case Ipv4L4Protocol::RX_CSUM_FAILED:
break;
case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
// XXX handle possibly multiple IP addresses on the interface
if (IsUnicast (ip.GetDestination (), GetInterface (iif)->GetAddress (0).GetMask ()))
if (ip.GetDestination ().IsBroadcast () == true ||
ip.GetDestination ().IsMulticast () == true)
{
break; // Do not reply to broadcast or multicast
}
// Another case to suppress ICMP is a subnet-directed broadcast
bool subnetDirected = false;
for (uint32_t i = 0; i < GetNAddresses (iif); i++)
{
Ipv4InterfaceAddress addr = GetAddress (iif, i);
if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination().CombineMask (addr.GetMask ()) &&
ip.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
{
subnetDirected = true;
}
}
if (subnetDirected == false)
{
GetIcmp ()->SendDestUnreachPort (ip, copy);
}
break;
}
}
}

View File

@@ -168,6 +168,7 @@ protected:
*/
virtual void NotifyNewAggregate ();
private:
friend class Ipv4L3ProtocolTest;
Ipv4L3Protocol(const Ipv4L3Protocol &);
Ipv4L3Protocol &operator = (const Ipv4L3Protocol &);

View File

@@ -224,11 +224,10 @@ Ipv4StaticRoutingImpl::LookupStatic (Ipv4Address dest)
NS_LOG_LOGIC ("Found global host route" << *i);
Ipv4RoutingTableEntry* route = (*i);
rtentry = Create<Ipv4Route> ();
rtentry->SetDestination (route->GetDest ());
// XXX handle multi-address case
rtentry->SetSource (m_ipv4->GetAddress (route->GetInterface(), 0).GetLocal ());
rtentry->SetGateway (route->GetGateway ());
uint32_t interfaceIdx = route->GetInterface ();
rtentry->SetDestination (route->GetDest ());
rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetDest ()));
rtentry->SetGateway (route->GetGateway ());
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
return rtentry;
}
@@ -245,11 +244,10 @@ Ipv4StaticRoutingImpl::LookupStatic (Ipv4Address dest)
NS_LOG_LOGIC ("Found global network route" << *j);
Ipv4RoutingTableEntry* route = (*j);
rtentry = Create<Ipv4Route> ();
rtentry->SetDestination (route->GetDest ());
// XXX handle multi-address case
rtentry->SetSource (m_ipv4->GetAddress (route->GetInterface(), 0).GetLocal ());
rtentry->SetGateway (route->GetGateway ());
uint32_t interfaceIdx = route->GetInterface ();
rtentry->SetDestination (route->GetDest ());
rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetDest ()));
rtentry->SetGateway (route->GetGateway ());
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
return rtentry;
}
@@ -260,11 +258,10 @@ Ipv4StaticRoutingImpl::LookupStatic (Ipv4Address dest)
NS_LOG_LOGIC ("Found global network route" << m_defaultRoute);
Ipv4RoutingTableEntry* route = m_defaultRoute;
rtentry = Create<Ipv4Route> ();
rtentry->SetDestination (route->GetDest ());
// XXX handle multi-address case
rtentry->SetSource (m_ipv4->GetAddress (route->GetInterface(), 0).GetLocal ());
rtentry->SetGateway (route->GetGateway ());
uint32_t interfaceIdx = route->GetInterface ();
rtentry->SetDestination (route->GetDest ());
rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetDest ()));
rtentry->SetGateway (route->GetGateway ());
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
return rtentry;
}
@@ -469,7 +466,8 @@ Ipv4StaticRoutingImpl::RouteOutput (const Ipv4Header &header, uint32_t oif, Sock
return rtentry;
}
// XXX this method not robust enough to work independent of ListRouting
// XXX this method not robust enough to work outside of ListRouting context
// because it will not perform local delivery
bool
Ipv4StaticRoutingImpl::RouteInput (Ptr<const Packet> p, const Ipv4Header &ipHeader, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
@@ -641,4 +639,30 @@ Ipv4StaticRoutingImpl::SetIpv4 (Ptr<Ipv4> ipv4)
}
}
Ipv4Address
Ipv4StaticRoutingImpl::SourceAddressSelection (uint32_t interfaceIdx, Ipv4Address dest)
{
if (m_ipv4->GetNAddresses (interfaceIdx) == 1) // common case
{
return m_ipv4->GetAddress (interfaceIdx, 0).GetLocal ();
}
// no way to determine the scope of the destination, so adopt the
// following rule: pick the first available address (index 0) unless
// a subsequent address is on link (in which case, pick the primary
// address if there are multiple)
Ipv4Address candidate = m_ipv4->GetAddress (interfaceIdx, 0).GetLocal ();
for (uint32_t i = 0; i < m_ipv4->GetNAddresses (interfaceIdx); i++)
{
Ipv4InterfaceAddress test = m_ipv4->GetAddress (interfaceIdx, i);
if (test.GetLocal ().CombineMask (test.GetMask ()) == dest.CombineMask (test.GetMask ()))
{
if (test.IsSecondary () == false)
{
return test.GetLocal ();
}
}
}
return candidate;
}
}//namespace ns3

View File

@@ -358,6 +358,8 @@ private:
Ptr<Ipv4MulticastRoute> LookupStatic (Ipv4Address origin, Ipv4Address group,
uint32_t interface);
Ipv4Address SourceAddressSelection (uint32_t interface, Ipv4Address dest);
HostRoutes m_hostRoutes;
NetworkRoutes m_networkRoutes;
Ipv4RoutingTableEntry *m_defaultRoute;

View File

@@ -0,0 +1,87 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* 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
*
*/
/**
* This is the test code for ipv4-l3-protocol.cc
*/
#ifdef RUN_SELF_TESTS
#include "ns3/simulator.h"
#include "ns3/test.h"
#include "ns3/log.h"
#include "ns3/inet-socket-address.h"
#include "ns3/node.h"
#include "ipv4-l3-protocol.h"
#include "arp-l3-protocol.h"
#include "ipv4-interface.h"
#include "loopback-net-device.h"
namespace ns3 {
class Ipv4L3ProtocolTest: public Test
{
public:
virtual bool RunTests (void);
Ipv4L3ProtocolTest ();
};
Ipv4L3ProtocolTest::Ipv4L3ProtocolTest ()
: Test ("Ipv4L3Protocol")
{
}
bool
Ipv4L3ProtocolTest::RunTests (void)
{
bool result = true;
Ptr<Node> node = CreateObject<Node> ();
Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
Ptr<LoopbackNetDevice> device = CreateObject<LoopbackNetDevice> ();
node->AddDevice (device);
interface->SetDevice (device);
interface->SetNode (node);
uint32_t index = ipv4->AddIpv4Interface (interface);
NS_TEST_ASSERT_EQUAL (index, 0);
interface->SetUp ();
Ipv4InterfaceAddress ifaceAddr1 = Ipv4InterfaceAddress ("192.168.0.1", "255.255.255.0");
interface->AddAddress (ifaceAddr1);
Ipv4InterfaceAddress ifaceAddr2 = Ipv4InterfaceAddress ("192.168.0.2", "255.255.255.0");
interface->AddAddress (ifaceAddr2);
Ipv4InterfaceAddress ifaceAddr3 = Ipv4InterfaceAddress ("10.30.0.1", "255.255.255.0");
interface->AddAddress (ifaceAddr3);
Ipv4InterfaceAddress ifaceAddr4 = Ipv4InterfaceAddress ("250.0.0.1", "255.255.255.0");
interface->AddAddress (ifaceAddr4);
uint32_t num = interface->GetNAddresses ();
NS_TEST_ASSERT_EQUAL (num, 4);
interface->RemoveAddress (2);
num = interface->GetNAddresses ();
NS_TEST_ASSERT_EQUAL (num, 3);
Ipv4InterfaceAddress output = interface->GetAddress (2);
NS_TEST_ASSERT_EQUAL (ifaceAddr4, output);
return result;
}
static Ipv4L3ProtocolTest gIpv4L3ProtocolTest;
}; // namespace ns3
#endif /* RUN_SELF_TESTS */

View File

@@ -74,6 +74,7 @@ def build(bld):
obj.source = [
'tcp-test.cc',
'udp-test.cc',
'ipv4-test.cc',
'ipv4-l4-protocol.cc',
'udp-header.cc',
'tcp-header.cc',