internet: (fixes #400) Adds RS retransmission if no reply
This commit is contained in:
committed by
Tommaso Pecorella
parent
cc9928f8a1
commit
60449cfbaa
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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> ();
|
||||
@@ -1100,8 +1138,58 @@ 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)
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
};
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user