diff --git a/CHANGES.html b/CHANGES.html index e1d17779b..58b766810 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -69,6 +69,8 @@ us a note on ns-developers mailing list.

an Autoconfigured address.
  • Mac64Address support has been extended. It can now be used with IPv6 to make an Autoconfigured address.
  • +
  • IPv6 can now detect and use Path-MTU. See + examples/ipv6/fragmentation-ipv6-two-MTU.cc for an example.
  • Changes to existing API:

    diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 9603f2f34..7e3525720 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -39,6 +39,8 @@ New user-visible features - PHY support for UE measurements (RSRP and RSRQ) - RRC support for UE measurements (configuration, execution, reporting) - Automatic Handover trigger based on RRC UE measurement reports +- IPv6 can now detect and use Path-MTU. See + examples/ipv6/fragmentation-ipv6-two-MTU.cc for an example. Bugs fixed ---------- @@ -63,6 +65,7 @@ Bugs fixed - Bug 1712 - The IP (v4 and v6) forwarding needs a test - Bug 1718 - Ipv4StaticRouting log component is misspelled - Bug 1720 - IPv6 Fragmentation cause crashes +- Bug 1721 - Path MTU isn't handled properly - Bug 1727 - Ping6 should use a proper source address - Bug 1731 - lte-phy-error-model passes unexpectedly - Bug 1742 - IPv6 HbH and Dst Extension Header size is not correctly calculated diff --git a/examples/ipv6/fragmentation-ipv6-two-MTU.cc b/examples/ipv6/fragmentation-ipv6-two-MTU.cc new file mode 100644 index 000000000..fe7cf0e70 --- /dev/null +++ b/examples/ipv6/fragmentation-ipv6-two-MTU.cc @@ -0,0 +1,169 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008-2009 Strasbourg University + * Copyright (c) 2013 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: David Gross + * Sebastien Vincent + * Modified by Tommaso Pecorella + */ + +// Network topology +// // +// // Src n0 r n1 Dst +// // | _ | +// // MTU ====|_|==== MTU +// // 5000 router 1500 +// // +// // - Tracing of queues and packet receptions to file "fragmentation-ipv6-two-mtu.tr" + +#include +#include "ns3/core-module.h" +#include "ns3/internet-module.h" +#include "ns3/csma-module.h" +#include "ns3/applications-module.h" +#include "ns3/ipv6-static-routing-helper.h" + +#include "ns3/ipv6-routing-table-entry.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("FragmentationIpv6TwoMtuExample"); + +/** + * \class StackHelper + * \brief Helper to set or get some IPv6 information about nodes. + */ +class StackHelper +{ +public: + /** + * \brief Add an address to a IPv6 node. + * \param n node + * \param interface interface index + * \param address IPv6 address to add + */ + inline void AddAddress (Ptr& n, uint32_t interface, Ipv6Address address) + { + Ptr ipv6 = n->GetObject (); + ipv6->AddAddress (interface, address); + } + + /** + * \brief Print the routing table. + * \param n the node + */ + inline void PrintRoutingTable (Ptr& n) + { + Ptr routing = 0; + Ipv6StaticRoutingHelper routingHelper; + Ptr ipv6 = n->GetObject (); + uint32_t nbRoutes = 0; + Ipv6RoutingTableEntry route; + + routing = routingHelper.GetStaticRouting (ipv6); + + std::cout << "Routing table of " << n << " : " << std::endl; + std::cout << "Destination\t\t\t\t" << "Gateway\t\t\t\t\t" << "Interface\t" << "Prefix to use" << std::endl; + + nbRoutes = routing->GetNRoutes (); + for (uint32_t i = 0; i < nbRoutes; i++) + { + route = routing->GetRoute (i); + std::cout << route.GetDest () << "\t" + << route.GetGateway () << "\t" + << route.GetInterface () << "\t" + << route.GetPrefixToUse () << "\t" + << std::endl; + } + } +}; + +int main (int argc, char** argv) +{ +#if 0 + LogComponentEnable ("Ipv6L3Protocol", LOG_LEVEL_ALL); + LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL); + LogComponentEnable ("Ipv6StaticRouting", LOG_LEVEL_ALL); + LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL); + LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL); +#endif + + CommandLine cmd; + cmd.Parse (argc, argv); + + StackHelper stackHelper; + + NS_LOG_INFO ("Create nodes."); + Ptr n0 = CreateObject (); + Ptr r = CreateObject (); + Ptr n1 = CreateObject (); + + NodeContainer net1 (n0, r); + NodeContainer net2 (r, n1); + NodeContainer all (n0, r, n1); + + NS_LOG_INFO ("Create IPv6 Internet Stack"); + InternetStackHelper internetv6; + internetv6.Install (all); + + NS_LOG_INFO ("Create channels."); + CsmaHelper csma; + csma.SetChannelAttribute ("DataRate", DataRateValue (5000000)); + csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2))); + NetDeviceContainer d2 = csma.Install (net2); + csma.SetDeviceAttribute ("Mtu", UintegerValue (5000)); + NetDeviceContainer d1 = csma.Install (net1); + + NS_LOG_INFO ("Create networks and assign IPv6 Addresses."); + Ipv6AddressHelper ipv6; + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer i1 = ipv6.Assign (d1); + i1.SetForwarding (1, true); + i1.SetDefaultRouteInAllNodes (1); + ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer i2 = ipv6.Assign (d2); + i2.SetForwarding (0, true); + i2.SetDefaultRouteInAllNodes (0); + + stackHelper.PrintRoutingTable (n0); + + /* Create a Ping6 application to send ICMPv6 echo request from n0 to n1 via r */ + uint32_t packetSize = 4096; + uint32_t maxPacketCount = 5; + Time interPacketInterval = Seconds (1.0); + Ping6Helper ping6; + + ping6.SetLocal (i1.GetAddress (0, 1)); + ping6.SetRemote (i2.GetAddress (1, 1)); + + ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount)); + ping6.SetAttribute ("Interval", TimeValue (interPacketInterval)); + ping6.SetAttribute ("PacketSize", UintegerValue (packetSize)); + ApplicationContainer apps = ping6.Install (net1.Get (0)); + apps.Start (Seconds (2.0)); + apps.Stop (Seconds (20.0)); + + AsciiTraceHelper ascii; + csma.EnableAsciiAll (ascii.CreateFileStream ("fragmentation-ipv6-two-mtu.tr")); + csma.EnablePcapAll (std::string ("fragmentation-ipv6-two-mtu"), true); + + NS_LOG_INFO ("Run Simulation."); + Simulator::Run (); + Simulator::Destroy (); + NS_LOG_INFO ("Done."); +} + diff --git a/examples/ipv6/wscript b/examples/ipv6/wscript index 5c3b86be9..609f3b637 100644 --- a/examples/ipv6/wscript +++ b/examples/ipv6/wscript @@ -18,6 +18,9 @@ def build(bld): obj = bld.create_ns3_program('fragmentation-ipv6', ['csma', 'internet']) obj.source = 'fragmentation-ipv6.cc' + + obj = bld.create_ns3_program('fragmentation-ipv6-two-MTU', ['csma', 'internet']) + obj.source = 'fragmentation-ipv6-two-MTU.cc' obj = bld.create_ns3_program('loose-routing-ipv6', ['csma', 'internet']) obj.source = 'loose-routing-ipv6.cc' diff --git a/src/internet/model/icmpv6-l4-protocol.cc b/src/internet/model/icmpv6-l4-protocol.cc index 827b37cb2..3ec0fe413 100644 --- a/src/internet/model/icmpv6-l4-protocol.cc +++ b/src/internet/model/icmpv6-l4-protocol.cc @@ -835,6 +835,10 @@ void Icmpv6L4Protocol::HandlePacketTooBig (Ptr p, Ipv6Address const &src origPkt->RemoveHeader (ipHeader); uint8_t payload[8]; origPkt->CopyData (payload, 8); + + Ptr ipv6 = m_node->GetObject (); + ipv6->SetPmtu(ipHeader.GetDestinationAddress(), tooBig.GetMtu ()); + Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload); } diff --git a/src/internet/model/ipv6-l3-protocol.cc b/src/internet/model/ipv6-l3-protocol.cc index 0ef79e0ac..7ac57c146 100644 --- a/src/internet/model/ipv6-l3-protocol.cc +++ b/src/internet/model/ipv6-l3-protocol.cc @@ -44,6 +44,9 @@ #include "icmpv6-l4-protocol.h" #include "ndisc-cache.h" +// Minimum IPv6 MTU, as defined by RFC 2460 +#define IPV6_MIN_MTU 1280 + namespace ns3 { NS_OBJECT_ENSURE_REGISTERED (Ipv6L3Protocol); @@ -88,6 +91,7 @@ Ipv6L3Protocol::Ipv6L3Protocol () : m_nInterfaces (0) { NS_LOG_FUNCTION_NOARGS (); + m_pmtuCache = CreateObject (); } Ipv6L3Protocol::~Ipv6L3Protocol () @@ -131,6 +135,7 @@ void Ipv6L3Protocol::DoDispose () m_node = 0; m_routingProtocol = 0; + m_pmtuCache = 0; Object::DoDispose (); } @@ -449,10 +454,24 @@ uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const uint16_t Ipv6L3Protocol::GetMtu (uint32_t i) const { NS_LOG_FUNCTION (this << i); + + // RFC 1981, if PMTU is disabled, return the minimum MTU + if (!m_mtuDiscover) + { + return IPV6_MIN_MTU; + } + Ptr interface = GetInterface (i); return interface->GetDevice ()->GetMtu (); } +void Ipv6L3Protocol::SetPmtu (Ipv6Address dst, uint32_t pmtu) +{ + NS_LOG_FUNCTION (this << dst << int(pmtu)); + m_pmtuCache->SetPmtu (dst, pmtu); +} + + bool Ipv6L3Protocol::IsUp (uint32_t i) const { NS_LOG_FUNCTION (this << i); @@ -556,6 +575,18 @@ bool Ipv6L3Protocol::GetIpForward () const return m_ipForward; } +void Ipv6L3Protocol::SetMtuDiscover (bool mtuDiscover) +{ + NS_LOG_FUNCTION (this << int(mtuDiscover)); + m_mtuDiscover = mtuDiscover; +} + +bool Ipv6L3Protocol::GetMtuDiscover () const +{ + NS_LOG_FUNCTION (this); + return m_mtuDiscover; +} + void Ipv6L3Protocol::SetSendIcmpv6Redirect (bool sendIcmpv6Redirect) { NS_LOG_FUNCTION (this << sendIcmpv6Redirect); @@ -848,7 +879,14 @@ void Ipv6L3Protocol::SendRealOut (Ptr route, Ptr packet, Ipv6 // Check packet size std::list > fragments; - if (packet->GetSize () > (size_t)(dev->GetMtu () + 40)) /* 40 => size of IPv6 header */ + // Check if we have a Path MTU stored. If so, use it. Else, use the link MTU. + size_t targetMtu = (size_t)(m_pmtuCache->GetPmtu (ipHeader.GetDestinationAddress())); + if (targetMtu == 0) + { + targetMtu = dev->GetMtu (); + } + + if (packet->GetSize () > targetMtu + 40) /* 40 => size of IPv6 header */ { // Router => drop @@ -882,7 +920,7 @@ void Ipv6L3Protocol::SendRealOut (Ptr route, Ptr packet, Ipv6 // To get specific method GetFragments from Ipv6ExtensionFragmentation Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION))); NS_ASSERT (ipv6Fragment != 0); - ipv6Fragment->GetFragments (packet, outInterface->GetDevice ()->GetMtu (), fragments); + ipv6Fragment->GetFragments (packet, targetMtu, fragments); } if (!route->GetGateway ().IsEqual (Ipv6Address::GetAny ())) diff --git a/src/internet/model/ipv6-l3-protocol.h b/src/internet/model/ipv6-l3-protocol.h index 116d27a6b..e6118e103 100644 --- a/src/internet/model/ipv6-l3-protocol.h +++ b/src/internet/model/ipv6-l3-protocol.h @@ -28,6 +28,7 @@ #include "ns3/ipv6.h" #include "ns3/ipv6-address.h" #include "ns3/ipv6-header.h" +#include "ns3/ipv6-pmtu-cache.h" namespace ns3 { @@ -277,6 +278,13 @@ public: */ uint16_t GetMtu (uint32_t i) const; + /** + * \brief Set the Path MTU for the specified IPv6 destination address. + * \param dst Ipv6 destination address + * \param pmtu the Path MTU + */ + virtual void SetPmtu (Ipv6Address dst, uint32_t pmtu); + /** * \brief Is specified interface up ? * \param i interface index @@ -484,6 +492,18 @@ private: */ virtual bool GetIpForward () const; + /** + * \brief Set IPv6 MTU discover state. + * \param mtuDiscover IPv6 MTU discover enabled or not + */ + virtual void SetMtuDiscover (bool mtuDiscover); + + /** + * \brief Get IPv6 MTU discover state. + * \return MTU discover state (enabled or not) + */ + virtual bool GetMtuDiscover (void) const; + /** * \brief Set the ICMPv6 Redirect sending state. * \param sendIcmpv6Redirect ICMPv6 Redirect sending enabled or not @@ -506,6 +526,16 @@ private: */ bool m_ipForward; + /** + * \brief MTU Discover (i.e. Path MTU) state. + */ + bool m_mtuDiscover; + + /** + * \brief Path MTU Cache. + */ + Ptr m_pmtuCache; + /** * \brief List of transport protocol. */ diff --git a/src/internet/model/ipv6-pmtu-cache.cc b/src/internet/model/ipv6-pmtu-cache.cc new file mode 100644 index 000000000..33197e091 --- /dev/null +++ b/src/internet/model/ipv6-pmtu-cache.cc @@ -0,0 +1,115 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 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 "ipv6-pmtu-cache.h" +#include "ns3/log.h" + +NS_LOG_COMPONENT_DEFINE ("Ipv6PmtuCache"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv6PmtuCache); + +TypeId Ipv6PmtuCache::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Ipv6PmtuCache") + .SetParent () + .AddAttribute ("CacheExpiryTime", + "Validity time for a Path MTU entry. Default is 10 minutes, minimum is 5 minutes.", + TimeValue (Seconds (60 * 10)), + MakeTimeAccessor (&Ipv6PmtuCache::m_validityTime), + MakeTimeChecker (Time (Seconds (60 * 5)))) + ; + return tid; +} + +Ipv6PmtuCache::Ipv6PmtuCache () +{ +} + +Ipv6PmtuCache::~Ipv6PmtuCache () +{ +} + +void Ipv6PmtuCache::DoDispose () +{ + for (pathMtuTimerIter iter = m_pathMtuTimer.begin (); iter != m_pathMtuTimer.end (); iter++) + { + iter->second.Cancel (); + } + m_pathMtuTimer.clear (); + m_pathMtu.clear (); +} + +uint32_t Ipv6PmtuCache::GetPmtu (Ipv6Address dst) +{ + NS_LOG_FUNCTION (this << dst); + + if (m_pathMtu.find (dst) != m_pathMtu.end ()) + { + return m_pathMtu[dst]; + } + return 0; +} + +void Ipv6PmtuCache::SetPmtu (Ipv6Address dst, uint32_t pmtu) +{ + NS_LOG_FUNCTION (this << dst << pmtu); + + m_pathMtu[dst] = pmtu; + if (m_pathMtuTimer.find (dst) != m_pathMtuTimer.end ()) + { + m_pathMtuTimer[dst].Cancel (); + } + EventId pMtuTimer; + pMtuTimer = Simulator::Schedule (m_validityTime, &Ipv6PmtuCache::ClearPmtu, this, dst); + m_pathMtuTimer[dst] = pMtuTimer; +} + +Time Ipv6PmtuCache::GetPmtuValidityTime () const +{ + NS_LOG_FUNCTION (this); + return m_validityTime; +} + +bool Ipv6PmtuCache::SetPmtuValidityTime (Time validity) +{ + NS_LOG_FUNCTION (this << validity); + + if (validity > Seconds (60 * 5)) + { + m_validityTime = validity; + return true; + } + + NS_LOG_LOGIC ("rejecting a PMTU validity timer lesser than 5 minutes"); + return false; +} + +void Ipv6PmtuCache::ClearPmtu (Ipv6Address dst) +{ + NS_LOG_FUNCTION (this << dst); + + m_pathMtu.erase (dst); + m_pathMtuTimer.erase (dst); +} + +} + diff --git a/src/internet/model/ipv6-pmtu-cache.h b/src/internet/model/ipv6-pmtu-cache.h new file mode 100644 index 000000000..e934ee787 --- /dev/null +++ b/src/internet/model/ipv6-pmtu-cache.h @@ -0,0 +1,122 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 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 + */ + +#ifndef IPV6_PMTU_CACHE_H +#define IPV6_PMTU_CACHE_H + +#include + +#include "ns3/core-module.h" +#include "ns3/ipv6-address.h" + +namespace ns3 { + +/** + * \ingroup ipv6 + * \brief This class implements the Path MTU cache, as defined by RFC 1981. + * + * The Path MTU is stored according to the destination address, and it is + * cleared upon expiration (default validity time is 10 minutes). + * + * The "infinite lifetime" PMTU entry type is not implemented, since it is + * useful only in an very limited number of cases. See the RFC for further + * details. + */ + +class Ipv6PmtuCache : public Object +{ +public: + class Entry; + + /** + * \brief Get the type ID + * \return type ID + */ + static TypeId GetTypeId (); + + /** + * \brief Constructor. + */ + Ipv6PmtuCache (); + + /** + * \brief Destructor. + */ + ~Ipv6PmtuCache (); + + /** + * \brief Dispose object. + */ + virtual void DoDispose (); + + /** + * \brief Gets the known Path MTU for the specific destination + * \param dst the destination + * \return the Path MTU (zero if unknown) + */ + uint32_t GetPmtu (Ipv6Address dst); + + /** + * \brief Sets the Path MTU for the specific destination + * \param dst the destination + * \param pmtu the Path MTU + */ + void SetPmtu (Ipv6Address dst, uint32_t pmtu); + + /** + * \brief Gets the Path MTU validity time + * \return the Path MTU validity time + */ + Time GetPmtuValidityTime () const; + + /** + * \brief Sets the Path MTU validity time (minimum is 5 minutes) + * \param validity the Path MTU validity time + * \return true if the change was successful + */ + bool SetPmtuValidityTime (Time validity); + +private: + /** + * \brief Clears the Path MTU for the specific destination + * \param dst the destination + */ + void ClearPmtu (Ipv6Address dst); + + /** + * \brief Path MTU table + */ + std::map m_pathMtu; + + typedef std::map ::iterator pathMtuTimerIter; + /** + * \brief Path MTU Expiration table + */ + std::map m_pathMtuTimer; + + /** + * \brief Path MTU entry validity time + */ + Time m_validityTime; +}; + +} + +#endif /* IPV6_PMTU_CACHE_H */ diff --git a/src/internet/model/ipv6.cc b/src/internet/model/ipv6.cc index 91465ca19..6e3bab17a 100644 --- a/src/internet/model/ipv6.cc +++ b/src/internet/model/ipv6.cc @@ -40,13 +40,11 @@ TypeId Ipv6::GetTypeId (void) MakeBooleanAccessor (&Ipv6::SetIpForward, &Ipv6::GetIpForward), MakeBooleanChecker ()) -#if 0 - .AddAttribute ("MtuDiscover", "If enabled, every outgoing IPv6 packet will have the DF flag set.", - BooleanValue (false), - MakeBooleanAccessor (&UdpSocket::SetMtuDiscover, - &UdpSocket::GetMtuDiscover), + .AddAttribute ("MtuDiscover", "If disabled, every interface will have its MTU set to 1280 bytes.", + BooleanValue (true), + MakeBooleanAccessor (&Ipv6::SetMtuDiscover, + &Ipv6::GetMtuDiscover), MakeBooleanChecker ()) -#endif ; return tid; } diff --git a/src/internet/model/ipv6.h b/src/internet/model/ipv6.h index c42a29495..a108ee522 100644 --- a/src/internet/model/ipv6.h +++ b/src/internet/model/ipv6.h @@ -252,6 +252,13 @@ public: */ virtual uint16_t GetMtu (uint32_t interface) const = 0; + /** + * \brief Set the Path MTU for the specified IPv6 destination address. + * \param dst Ipv6 destination address + * \param pmtu the Path MTU + */ + virtual void SetPmtu (Ipv6Address dst, uint32_t pmtu) = 0; + /** * \brief If the specified interface index is in "up" state. * \param interface Interface number of IPv6 interface @@ -320,6 +327,18 @@ private: * \return forwarding state (enabled or not) */ virtual bool GetIpForward (void) const = 0; + + /** + * \brief Set IPv6 MTU discover state. + * \param mtuDiscover IPv6 MTU discover enabled or not + */ + virtual void SetMtuDiscover (bool mtuDiscover) = 0; + + /** + * \brief Get IPv6 MTU discover state. + * \return MTU discover state (enabled or not) + */ + virtual bool GetMtuDiscover (void) const = 0; }; } // namespace ns3 diff --git a/src/internet/wscript b/src/internet/wscript index 61dcfa0a9..8376db7e7 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -191,6 +191,7 @@ def build(bld): 'model/ipv6-address-generator.cc', 'model/ipv4-packet-probe.cc', 'model/ipv6-packet-probe.cc', + 'model/ipv6-pmtu-cache.cc', ] internet_test = bld.create_ns3_module_test_library('internet') @@ -304,6 +305,7 @@ def build(bld): 'model/rtt-estimator.h', 'model/ipv4-packet-probe.h', 'model/ipv6-packet-probe.h', + 'model/ipv6-pmtu-cache.h', ] if bld.env['NSC_ENABLED']: