internet: (fixes #400) Adds RS retransmission if no reply

This commit is contained in:
Tommaso Pecorella
2022-06-20 22:06:24 -05:00
committed by Tommaso Pecorella
parent cc9928f8a1
commit 60449cfbaa
5 changed files with 174 additions and 11 deletions

View File

@@ -28,6 +28,7 @@ Changes from ns-3.36 to ns-3.37
* Adds supporting structures used by **LrWpanMac** (PAN descriptor, Command Payload Header, Capability Field).
* Mac(8|16|48|64)Address address allocation pool is now reset between consecutive runs.
* Adds support for **LrWpanMac** energy detection (ED) scan.
* IPv6 Router Solicitations (RS) are now retrnamitted up to 4 times, following RFC 5779.
### Changes to build system

View File

@@ -18,6 +18,8 @@ Release 3-dev
- (lr-wpan) Adds PAN descriptor, CommandPayload Header and Capability Field
- (wifi) !984 - MultiUserScheduler can request channel access periodically
- (lr-wpan) !991 - Adds MAC ED scan support
- (internet) !996 - IPv6 Router Solicitations (RS) are now retrnamitted up to 4 times, following RFC 5779.
### Bugs fixed

View File

@@ -31,6 +31,8 @@
#include "ns3/pointer.h"
#include "ns3/string.h"
#include "ns3/integer.h"
#include "ns3/uinteger.h"
#include "ns3/double.h"
#include "ipv6-l3-protocol.h"
#include "ipv6-interface.h"
@@ -94,6 +96,33 @@ TypeId Icmpv6L4Protocol::GetTypeId ()
TimeValue (Seconds (5)),
MakeTimeAccessor (&Icmpv6L4Protocol::m_delayFirstProbe),
MakeTimeChecker ())
.AddAttribute ("DadTimeout", "Duplicate Address Detection (DAD) timeout",
TimeValue (Seconds (1)),
MakeTimeAccessor (&Icmpv6L4Protocol::m_dadTimeout),
MakeTimeChecker ())
.AddAttribute ("RsRetransmissionJitter", "Multicast RS retransmission randomization quantity",
StringValue ("ns3::UniformRandomVariable[Min=-0.1|Max=0.1]"),
MakePointerAccessor (&Icmpv6L4Protocol::m_rsRetransmissionJitter),
MakePointerChecker<RandomVariableStream> ())
.AddAttribute ("RsInitialRetransmissionTime", "Multicast RS initial retransmission time.",
TimeValue (Seconds (4)),
MakeTimeAccessor (&Icmpv6L4Protocol::m_rsInitialRetransmissionTime),
MakeTimeChecker ())
.AddAttribute ("RsMaxRetransmissionTime", "Multicast RS maximum retransmission time (0 means unbound).",
TimeValue (Seconds (3600)),
MakeTimeAccessor (&Icmpv6L4Protocol::m_rsMaxRetransmissionTime),
MakeTimeChecker ())
.AddAttribute ("RsMaxRetransmissionCount",
"Multicast RS maximum retransmission count (0 means unbound). "
"Note: RFC 7559 suggest a zero value (infinite). The default is 4 to avoid "
"non-terminating simulations.",
UintegerValue (4),
MakeUintegerAccessor (&Icmpv6L4Protocol::m_rsMaxRetransmissionCount),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("RsMaxRetransmissionDuration", "Multicast RS maximum retransmission duration (0 means unbound).",
TimeValue (Seconds (0)),
MakeTimeAccessor (&Icmpv6L4Protocol::m_rsMaxRetransmissionDuration),
MakeTimeChecker ())
;
return tid;
}
@@ -135,7 +164,8 @@ int64_t Icmpv6L4Protocol::AssignStreams (int64_t stream)
{
NS_LOG_FUNCTION (this << stream);
m_solicitationJitter->SetStream (stream);
return 1;
m_rsRetransmissionJitter->SetStream (stream+1);
return 2;
}
void Icmpv6L4Protocol::NotifyNewAggregate ()
@@ -325,6 +355,14 @@ void Icmpv6L4Protocol::HandleEchoRequest (Ptr<Packet> packet, Ipv6Address const
void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << packet << src << dst << interface);
if (m_handleRsTimeoutEvent.IsRunning ())
{
m_handleRsTimeoutEvent.Cancel ();
// We need to update this in case we need to restart RS retransmissions.
m_rsRetransmissionCount = 0;
}
Ptr<Packet> p = packet->Copy ();
Icmpv6RA raHeader;
Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
@@ -1074,7 +1112,7 @@ void Icmpv6L4Protocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address tar
}
}
void Icmpv6L4Protocol::SendRS (Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
void Icmpv6L4Protocol::SendRS (Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
{
NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
Ptr<Packet> p = Create<Packet> ();
@@ -1100,10 +1138,60 @@ void Icmpv6L4Protocol::SendRS (Ipv6Address src, Ipv6Address dst, Address hardwa
else
{
NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
Simulator::Schedule (Time (MilliSeconds (m_solicitationJitter->GetValue ())), &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
Time rsDelay = Time (0);
Time rsTimeout = Time (0);
if (m_rsRetransmissionCount == 0)
{
// First RS transmission - also add some jitter to desynchronize nodes.
m_rsInitialRetransmissionTime = Simulator::Now ();
rsTimeout = m_rsInitialRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue ());
rsDelay = Time (MilliSeconds (m_solicitationJitter->GetValue ()));
}
else
{
// Following RS transmission - adding further jitter is unnecesary.
rsTimeout = m_rsPrevRetransmissionTimeout * (2 + m_rsRetransmissionJitter->GetValue ());
if (rsTimeout > m_rsMaxRetransmissionTime)
{
rsTimeout = m_rsMaxRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue ());
}
}
m_rsPrevRetransmissionTimeout = rsTimeout;
Simulator::Schedule (rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
m_handleRsTimeoutEvent = Simulator::Schedule (rsDelay+m_rsPrevRetransmissionTimeout, &Icmpv6L4Protocol::HandleRsTimeout, this, src, dst, hardwareAddress);
}
}
void Icmpv6L4Protocol::HandleRsTimeout (Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
{
NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
if (m_rsMaxRetransmissionCount == 0)
{
// Unbound number of retransmissions - just add one to signal that we're in retransmission mode.
m_rsRetransmissionCount = 1;
}
else
{
m_rsRetransmissionCount ++;
if (m_rsRetransmissionCount > m_rsMaxRetransmissionCount)
{
NS_LOG_LOGIC ("Maximum number of multicast RS reached, giving up.");
return;
}
}
if (m_rsMaxRetransmissionDuration != Time (0) &&
Simulator::Now () - m_rsInitialRetransmissionTime > m_rsMaxRetransmissionDuration)
{
NS_LOG_LOGIC ("Maximum RS retransmission time reached, giving up.");
return;
}
SendRS (src, dst, hardwareAddress);
}
void Icmpv6L4Protocol::SendErrorDestinationUnreachable (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
{
NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code);
@@ -1490,7 +1578,8 @@ void Icmpv6L4Protocol::FunctionDadTimeout (Ipv6Interface* interface, Ipv6Address
/* \todo Add random delays before sending RS
* because all nodes start at the same time, there will be many of RS around 1 second of simulation time
*/
NS_LOG_LOGIC ("Scheduled a Router Solicitation");
NS_LOG_LOGIC ("Scheduled a first Router Solicitation");
m_rsRetransmissionCount = 0;
Simulator::Schedule (Seconds (0.0), &Icmpv6L4Protocol::SendRS, this, ifaddr.GetAddress (), Ipv6Address::GetAllRoutersMulticast (), interface->GetDevice ()->GetAddress ());
}
else
@@ -1557,6 +1646,12 @@ Icmpv6L4Protocol::GetDelayFirstProbe () const
return m_delayFirstProbe;
}
Time
Icmpv6L4Protocol::GetDadTimeout () const
{
return m_dadTimeout;
}
} /* namespace ns3 */

View File

@@ -127,7 +127,7 @@ public:
* by setting the node in the ICMPv6 stack and adding ICMPv6 factory to
* IPv6 stack connected to the node.
*/
void NotifyNewAggregate ();
virtual void NotifyNewAggregate ();
/**
* \brief Get the protocol number.
@@ -319,7 +319,7 @@ public:
* \param interface the interface
* \param addr the IPv6 address
*/
void FunctionDadTimeout (Ipv6Interface* interface, Ipv6Address addr);
virtual void FunctionDadTimeout (Ipv6Interface* interface, Ipv6Address addr);
/**
* \brief Lookup in the ND cache for the IPv6 address
@@ -332,7 +332,7 @@ public:
* \param hardwareDestination hardware address
* \return true if the address is in the ND cache, the hardwareDestination is updated.
*/
bool Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination);
virtual bool Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination);
/**
* \brief Lookup in the ND cache for the IPv6 address (similar as ARP protocol).
@@ -346,12 +346,12 @@ public:
* \param hardwareDestination hardware address
* \return true if the address is in the ND cache, the hardwareDestination is updated.
*/
bool Lookup (Ptr<Packet> p, const Ipv6Header & ipHeader, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination);
virtual bool Lookup (Ptr<Packet> p, const Ipv6Header & ipHeader, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination);
/**
* \brief Send a Router Solicitation.
* \param src link-local source address
* \param dst destination address (usually ff02::2 i.e all-routers)
* \param dst destination address (usually ff02::2 i.e., all-routers)
* \param hardwareAddress link-layer address (SHOULD be included if src is not ::)
*/
void SendRS (Ipv6Address src, Ipv6Address dst, Address hardwareAddress);
@@ -380,6 +380,12 @@ public:
*/
int64_t AssignStreams (int64_t stream);
/**
* Get the DAD timeout
* \return the DAD timeout
*/
Time GetDadTimeout () const;
protected:
/**
* \brief Dispose this object.
@@ -418,6 +424,14 @@ protected:
*/
void HandleRS (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
/**
* \brief Router Solicitation Timeout handler.
* \param src link-local source address
* \param dst destination address (usually ff02::2 i.e all-routers)
* \param hardwareAddress link-layer address (SHOULD be included if src is not ::)
*/
virtual void HandleRsTimeout (Ipv6Address src, Ipv6Address dst, Address hardwareAddress);
/**
* \brief Receive Router Advertisement method.
* \param p the packet
@@ -523,7 +537,6 @@ protected:
*/
CacheList m_cacheList;
private:
/**
* \brief Neighbor Discovery node constants: max multicast solicitations.
*/
@@ -534,6 +547,43 @@ private:
*/
uint8_t m_maxUnicastSolicit;
/**
* \brief Initial multicast RS retransmission time [\RFC{7559}].
*/
Time m_rsInitialRetransmissionTime;
/**
* \brief Maximum time between multicast RS retransmissions [\RFC{7559}]. Zero means unbound.
*/
Time m_rsMaxRetransmissionTime;
/**
* \brief Maximum number of multicast RS retransmissions [\RFC{7559}]. Zero means unbound.
*/
uint32_t m_rsMaxRetransmissionCount;
/**
* \brief Maximum duration of multicast RS retransmissions [\RFC{7559}]. Zero means unbound.
*/
Time m_rsMaxRetransmissionDuration;
/**
* \brief Multicast RS retransmissions counter [\RFC{7559}].
*
* Zero indicate a first transmission, greater than zero means retranmsisisons.
*/
uint32_t m_rsRetransmissionCount {0};
/**
* \brief Previous multicast RS retransmissions timeout [\RFC{7559}].
*/
Time m_rsPrevRetransmissionTimeout;
/**
* \brief First multicast RS transmissions [\RFC{7559}].
*/
Time m_rsFirstTransmissionTime;
/**
* \brief Neighbor Discovery node constants: reachable time.
*/
@@ -559,6 +609,21 @@ private:
*/
Ptr<RandomVariableStream> m_solicitationJitter;
/**
* \brief Random jitter for RS retransmissions
*/
Ptr<UniformRandomVariable> m_rsRetransmissionJitter;
/**
* \brief DAD timeout
*/
Time m_dadTimeout;
/**
* RS timeout handler event
*/
EventId m_handleRsTimeoutEvent;
IpL4Protocol::DownTargetCallback6 m_downTarget; //!< callback to Ipv6::Send
};

View File

@@ -222,7 +222,7 @@ bool Ipv6Interface::AddAddress (Ipv6InterfaceAddress iface)
if (icmpv6->IsAlwaysDad ())
{
Simulator::Schedule (Seconds (0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this);
Simulator::Schedule (Seconds (1.), &Icmpv6L4Protocol::FunctionDadTimeout, icmpv6, this, addr);
Simulator::Schedule (icmpv6->GetDadTimeout (), &Icmpv6L4Protocol::FunctionDadTimeout, icmpv6, this, addr);
}
else
{