From 5f8291006dcce2ea83c756e48ad070d510e7b3fa Mon Sep 17 00:00:00 2001 From: Tommaso Pecorella Date: Fri, 1 May 2020 14:21:04 +0000 Subject: [PATCH] (internet): IPv6 Duplicate Address Detection (DAD) must use Solicited-Node multicast address --- src/internet/model/icmpv6-l4-protocol.cc | 11 +- .../test/ipv6-address-duplication-test.cc | 134 ++++++++++++++++++ src/internet/wscript | 1 + 3 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 src/internet/test/ipv6-address-duplication-test.cc diff --git a/src/internet/model/icmpv6-l4-protocol.cc b/src/internet/model/icmpv6-l4-protocol.cc index a3a8c7869..59972d34f 100644 --- a/src/internet/model/icmpv6-l4-protocol.cc +++ b/src/internet/model/icmpv6-l4-protocol.cc @@ -572,7 +572,10 @@ void Icmpv6L4Protocol::HandleNS (Ptr packet, Ipv6Address const &src, Ipv } hardwareAddress = interface->GetDevice ()->GetAddress (); - NdiscCache::Ipv6PayloadHeaderPair p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (), src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src, &hardwareAddress, flags ); + NdiscCache::Ipv6PayloadHeaderPair p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (), + src.IsAny () ? dst : src, // DAD replies must go to the multicast group it was sent to. + &hardwareAddress, + flags ); interface->Send (p.first, p.second, src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src); /* not a NS for us discard it */ @@ -1253,12 +1256,6 @@ NdiscCache::Ipv6PayloadHeaderPair Icmpv6L4Protocol::ForgeNS (Ipv6Address src, Ip Icmpv6NS ns (target); Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */ - /* if the source is unspec, multicast the NA to all-nodes multicast */ - if (src == Ipv6Address::GetAny ()) - { - dst = Ipv6Address::GetAllNodesMulticast (); - } - NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")"); p->AddHeader (llOption); diff --git a/src/internet/test/ipv6-address-duplication-test.cc b/src/internet/test/ipv6-address-duplication-test.cc new file mode 100644 index 000000000..bddd1fead --- /dev/null +++ b/src/internet/test/ipv6-address-duplication-test.cc @@ -0,0 +1,134 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2020 Universita' di Firenze + * + * 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 + * + * Author: Tommaso Pecorella + */ + +#include "ns3/test.h" +#include "ns3/socket-factory.h" +#include "ns3/udp-socket-factory.h" +#include "ns3/simulator.h" +#include "ns3/simple-channel.h" +#include "ns3/simple-net-device.h" +#include "ns3/simple-net-device-helper.h" +#include "ns3/socket.h" +#include "ns3/boolean.h" + +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/inet6-socket-address.h" + +#include "ns3/ipv6-l3-protocol.h" +#include "ns3/icmpv6-l4-protocol.h" +#include "ns3/udp-l4-protocol.h" +#include "ns3/ipv6-static-routing.h" +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv6-address-helper.h" +#include "ns3/ipv6-routing-helper.h" + +#include +#include + +using namespace ns3; + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief IPv6 Duplicate Address Detection Test + */ +class Ipv6DadTest : public TestCase +{ +public: + virtual void DoRun (void); + Ipv6DadTest (); +}; + +Ipv6DadTest::Ipv6DadTest () + : TestCase ("IPv6 Duplicate Address Detection") +{ +} + +void +Ipv6DadTest::DoRun (void) +{ + // Create topology + + Ptr Node1 = CreateObject (); + Ptr Node2 = CreateObject (); + + NodeContainer nodes (Node1, Node2); + + SimpleNetDeviceHelper helperChannel; + helperChannel.SetNetDevicePointToPointMode (true); + NetDeviceContainer net = helperChannel.Install (nodes); + + InternetStackHelper internetv6; + internetv6.Install (nodes); + + Ipv6AddressHelper ipv6helper; + Ipv6InterfaceContainer iic = ipv6helper.AssignWithoutAddress (net); + + Ptr device; + Ipv6InterfaceAddress ipv6Addr; + + Ptr ipv6node1; + int32_t ifIndexNode1; + ipv6node1 = Node1->GetObject (); + device = net.Get (0); + ifIndexNode1 = ipv6node1->GetInterfaceForDevice (device); + ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:1::1"), Ipv6Prefix (64)); + ipv6node1->AddAddress (ifIndexNode1, ipv6Addr); + + Ptr ipv6node2; + int32_t ifIndexNode2; + ipv6node2 = Node2->GetObject (); + device = net.Get (1); + ifIndexNode2 = ipv6node2->GetInterfaceForDevice (device); + ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:1::1"), Ipv6Prefix (64)); + ipv6node2->AddAddress (ifIndexNode2, ipv6Addr); + + Simulator::Run (); + + Ipv6InterfaceAddress addr1 = ipv6node1->GetAddress (ifIndexNode1, 1); + Ipv6InterfaceAddress::State_e node1AddrState = addr1.GetState(); + NS_TEST_ASSERT_MSG_EQ (node1AddrState, Ipv6InterfaceAddress::INVALID, "Failed to detect duplicate address on node 1"); + + Ipv6InterfaceAddress addr2 = ipv6node2->GetAddress (ifIndexNode2, 1); + Ipv6InterfaceAddress::State_e node2AddrState = addr2.GetState(); + NS_TEST_ASSERT_MSG_EQ (node2AddrState, Ipv6InterfaceAddress::INVALID, "Failed to detect duplicate address on node 2"); + + Simulator::Destroy (); +} + + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief IPv6 Duplicate Address Detection TestSuite + */ +class Ipv6DadTestSuite : public TestSuite +{ +public: + Ipv6DadTestSuite () : TestSuite ("ipv6-duplicate-address-detection", UNIT) + { + AddTestCase (new Ipv6DadTest, TestCase::QUICK); + } +}; + +static Ipv6DadTestSuite g_ipv6dadTestSuite; //!< Static variable for test initialization diff --git a/src/internet/wscript b/src/internet/wscript index 9b04c2182..a1cc7f6b7 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -251,6 +251,7 @@ def build(bld): 'test/ipv6-packet-info-tag-test-suite.cc', 'test/ipv6-test.cc', 'test/ipv6-raw-test.cc', + 'test/ipv6-address-duplication-test.cc', 'test/tcp-test.cc', 'test/tcp-timestamp-test.cc', 'test/tcp-sack-permitted-test.cc',