From 441cedb65539b228a872f3494b1d02661de01208 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sun, 21 Jun 2009 22:29:08 -0700 Subject: [PATCH] cleanup ip alias unfinished cases (bug 591) --- examples/csma-broadcast.cc | 6 +- src/internet-stack/arp-l3-protocol.cc | 119 +++++++++++------- src/internet-stack/icmpv4-l4-protocol.cc | 10 +- src/internet-stack/icmpv4-l4-protocol.h | 2 + src/internet-stack/ipv4-end-point-demux.cc | 18 ++- src/internet-stack/ipv4-l3-protocol.cc | 33 +++-- src/internet-stack/ipv4-l3-protocol.h | 1 + .../ipv4-static-routing-impl.cc | 50 ++++++-- src/internet-stack/ipv4-static-routing-impl.h | 2 + src/internet-stack/ipv4-test.cc | 87 +++++++++++++ src/internet-stack/wscript | 1 + 11 files changed, 246 insertions(+), 83 deletions(-) create mode 100644 src/internet-stack/ipv4-test.cc diff --git a/examples/csma-broadcast.cc b/examples/csma-broadcast.cc index a220b5277..b89f01ab5 100644 --- a/examples/csma-broadcast.cc +++ b/examples/csma-broadcast.cc @@ -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 diff --git a/src/internet-stack/arp-l3-protocol.cc b/src/internet-stack/arp-l3-protocol.cc index f0ff26da4..10a4342b5 100644 --- a/src/internet-stack/arp-l3-protocol.cc +++ b/src/internet-stack/arp-l3-protocol.cc @@ -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 device, Ptr 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="<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="<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="<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="<GetId ()<<", got reply from " << - arp.GetSourceIpv4Address () - << " for waiting entry -- flush"); - Address from_mac = arp.GetSourceHardwareAddress (); - entry->MarkAlive (from_mac); - Ptr 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 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="<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="<GetId ()<<", got reply from " << - arp.GetSourceIpv4Address () << - " for non-waiting entry -- drop"); + NS_LOG_LOGIC ("node="<GetId ()<<", got reply for unknown entry -- drop"); m_dropTrace (packet); } - } - else - { - NS_LOG_LOGIC ("node="<GetId ()<<", got reply for unknown entry -- drop"); - m_dropTrace (packet); + break; } } - else + if (found == false) { NS_LOG_LOGIC ("node="<GetId ()<<", got request from " << arp.GetSourceIpv4Address () << " for unknown address " << arp.GetDestinationIpv4Address () << " -- drop"); } } + bool ArpL3Protocol::Lookup (Ptr packet, Ipv4Address destination, Ptr device, @@ -301,14 +311,22 @@ ArpL3Protocol::SendArpRequest (Ptr cache, Ipv4Address to) { NS_LOG_FUNCTION (this << cache << to); ArpHeader arp; + // need to pick a source address; use routing implementation to select + Ptr ipv4 = m_node->GetObject (); + int32_t interface = ipv4->GetInterfaceForDevice (cache->GetDevice ()); + NS_ASSERT (interface >= 0); + Ipv4Header header; + header.SetDestination (to); + Socket::SocketErrno errno_; + Ptr route = ipv4->GetRoutingProtocol ()->RouteOutput (header, interface, errno_); + NS_ASSERT (route != 0); NS_LOG_LOGIC ("ARP: sending request from 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 = Create (); @@ -321,14 +339,21 @@ ArpL3Protocol::SendArpReply (Ptr 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 ipv4 = m_node->GetObject (); + int32_t interface = ipv4->GetInterfaceForDevice (cache->GetDevice ()); + NS_ASSERT (interface >= 0); + Ipv4Header header; + header.SetDestination (toIp); + Socket::SocketErrno errno_; + Ptr route = ipv4->GetRoutingProtocol ()->RouteOutput (header, interface, errno_); + NS_ASSERT (route != 0); NS_LOG_LOGIC ("ARP: sending reply from 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 = Create (); packet->AddHeader (arp); cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER); diff --git a/src/internet-stack/icmpv4-l4-protocol.cc b/src/internet-stack/icmpv4-l4-protocol.cc index b0c0ea6f2..6130c845e 100644 --- a/src/internet-stack/icmpv4-l4-protocol.cc +++ b/src/internet-stack/icmpv4-l4-protocol.cc @@ -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, Ipv4Address dest, uint8_t type, uint8_t code) @@ -111,7 +109,7 @@ Icmpv4L4Protocol::SendMessage (Ptr 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, diff --git a/src/internet-stack/icmpv4-l4-protocol.h b/src/internet-stack/icmpv4-l4-protocol.h index 27c834279..e13981145 100644 --- a/src/internet-stack/icmpv4-l4-protocol.h +++ b/src/internet-stack/icmpv4-l4-protocol.h @@ -15,6 +15,8 @@ class Icmpv4L4Protocol : public Ipv4L4Protocol { public: static TypeId GetTypeId (void); + static const uint8_t PROT_NUMBER; + Icmpv4L4Protocol (); virtual ~Icmpv4L4Protocol (); diff --git a/src/internet-stack/ipv4-end-point-demux.cc b/src/internet-stack/ipv4-end-point-demux.cc index ad98ede4b..e63f7d3d7 100644 --- a/src/internet-stack/ipv4-end-point-demux.cc +++ b/src/internet-stack/ipv4-end-point-demux.cc @@ -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(); diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index ac6f00c34..a356f45c8 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -526,8 +526,8 @@ Ipv4L3Protocol::Send (Ptr 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 rtentry, Ptr p, const Ip ipHeader.SetTtl (ipHeader.GetTtl () - 1); if (ipHeader.GetTtl () == 0) { - Ptr 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 icmp = GetIcmp (); icmp->SendTimeExceededTtl (ipHeader, packet); @@ -720,12 +719,26 @@ Ipv4L3Protocol::LocalDeliver (Ptr 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; } } } diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index cb28a7878..57e0dbf69 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -168,6 +168,7 @@ protected: */ virtual void NotifyNewAggregate (); private: + friend class Ipv4L3ProtocolTest; Ipv4L3Protocol(const Ipv4L3Protocol &); Ipv4L3Protocol &operator = (const Ipv4L3Protocol &); diff --git a/src/internet-stack/ipv4-static-routing-impl.cc b/src/internet-stack/ipv4-static-routing-impl.cc index d0a2d3ede..75f284d8c 100644 --- a/src/internet-stack/ipv4-static-routing-impl.cc +++ b/src/internet-stack/ipv4-static-routing-impl.cc @@ -224,11 +224,10 @@ Ipv4StaticRoutingImpl::LookupStatic (Ipv4Address dest) NS_LOG_LOGIC ("Found global host route" << *i); Ipv4RoutingTableEntry* route = (*i); rtentry = Create (); - 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 (); - 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 (); - 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 p, const Ipv4Header &ipHeader, Ptr idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, @@ -641,4 +639,30 @@ Ipv4StaticRoutingImpl::SetIpv4 (Ptr 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 diff --git a/src/internet-stack/ipv4-static-routing-impl.h b/src/internet-stack/ipv4-static-routing-impl.h index b701f085e..31690c321 100644 --- a/src/internet-stack/ipv4-static-routing-impl.h +++ b/src/internet-stack/ipv4-static-routing-impl.h @@ -358,6 +358,8 @@ private: Ptr LookupStatic (Ipv4Address origin, Ipv4Address group, uint32_t interface); + Ipv4Address SourceAddressSelection (uint32_t interface, Ipv4Address dest); + HostRoutes m_hostRoutes; NetworkRoutes m_networkRoutes; Ipv4RoutingTableEntry *m_defaultRoute; diff --git a/src/internet-stack/ipv4-test.cc b/src/internet-stack/ipv4-test.cc new file mode 100644 index 000000000..1ca51924b --- /dev/null +++ b/src/internet-stack/ipv4-test.cc @@ -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 = CreateObject (); + Ptr ipv4 = CreateObject (); + Ptr interface = CreateObject (); + Ptr device = CreateObject (); + 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 */ diff --git a/src/internet-stack/wscript b/src/internet-stack/wscript index 49f2f15f5..467929dfa 100644 --- a/src/internet-stack/wscript +++ b/src/internet-stack/wscript @@ -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',