--- a/RELEASE_NOTES Thu Nov 13 23:34:10 2014 +0100
+++ b/RELEASE_NOTES Wed Nov 19 00:13:58 2014 +0100
@@ -42,6 +42,7 @@
- Bug 1991 - PcapFileWrapper::CaptureSize attribute (snaplen) has no effect.
- Bug 1997 - Fix PlotProbe() documentation and usage for GnuplotHelper and FileHelper
- Bug 2011 - Default Speed attribute in ConstantSpeedPropagationDelayModel
+- Bug 2016 - Radvd do not consider the SendAdvert option and don't reply to RS
Known issues
------------
--- a/examples/ipv6/radvd.cc Thu Nov 13 23:34:10 2014 +0100
+++ b/examples/ipv6/radvd.cc Wed Nov 19 00:13:58 2014 +0100
@@ -115,10 +115,15 @@
/* radvd configuration */
RadvdHelper radvdHelper;
+
/* R interface (n0 - R) */
- radvdHelper.AddAnnouncedPrefix(iic1.GetInterfaceIndex (1), Ipv6Address("2001:1::0"), 64);
+ /* n0 will receive unsolicited (periodic) RA */
+ radvdHelper.AddAnnouncedPrefix (iic1.GetInterfaceIndex (1), Ipv6Address("2001:1::0"), 64);
+
/* R interface (R - n1) */
+ /* n1 will have to use RS, as RA are not sent automatically */
radvdHelper.AddAnnouncedPrefix(iic2.GetInterfaceIndex (1), Ipv6Address("2001:2::0"), 64);
+ radvdHelper.GetRadvdInterface (iic2.GetInterfaceIndex (1))->SetSendAdvert (false);
ApplicationContainer radvdApps = radvdHelper.Install (r);
radvdApps.Start (Seconds (1.0));
--- a/src/applications/bindings/modulegen__gcc_ILP32.py Thu Nov 13 23:34:10 2014 +0100
+++ b/src/applications/bindings/modulegen__gcc_ILP32.py Wed Nov 19 00:13:58 2014 +0100
@@ -4193,7 +4193,6 @@
return
def register_Ns3Int64x64_t_methods(root_module, cls):
- cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('!=')
cls.add_inplace_numeric_operator('+=', param('ns3::int64x64_t const &', u'right'))
cls.add_binary_numeric_operator('*', root_module['ns3::int64x64_t'], root_module['ns3::int64x64_t'], param('ns3::int64x64_t const &', u'right'))
@@ -4207,6 +4206,7 @@
cls.add_inplace_numeric_operator('-=', param('ns3::int64x64_t const &', u'right'))
cls.add_inplace_numeric_operator('/=', param('ns3::int64x64_t const &', u'right'))
cls.add_output_stream_operator()
+ cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('==')
cls.add_binary_comparison_operator('>=')
## int64x64-double.h (module 'core'): ns3::int64x64_t::int64x64_t() [constructor]
@@ -5913,7 +5913,6 @@
return
def register_Ns3Time_methods(root_module, cls):
- cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('!=')
cls.add_inplace_numeric_operator('+=', param('ns3::Time const &', u'right'))
cls.add_binary_numeric_operator('*', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right'))
@@ -5924,6 +5923,7 @@
cls.add_binary_comparison_operator('>')
cls.add_inplace_numeric_operator('-=', param('ns3::Time const &', u'right'))
cls.add_output_stream_operator()
+ cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('==')
cls.add_binary_comparison_operator('>=')
## nstime.h (module 'core'): ns3::Time::Time() [constructor]
@@ -7000,14 +7000,14 @@
cls.add_constructor([param('ns3::EnumChecker const &', 'arg0')])
## enum.h (module 'core'): ns3::EnumChecker::EnumChecker() [constructor]
cls.add_constructor([])
- ## enum.h (module 'core'): void ns3::EnumChecker::Add(int v, std::string name) [member function]
+ ## enum.h (module 'core'): void ns3::EnumChecker::Add(int value, std::string name) [member function]
cls.add_method('Add',
'void',
- [param('int', 'v'), param('std::string', 'name')])
- ## enum.h (module 'core'): void ns3::EnumChecker::AddDefault(int v, std::string name) [member function]
+ [param('int', 'value'), param('std::string', 'name')])
+ ## enum.h (module 'core'): void ns3::EnumChecker::AddDefault(int value, std::string name) [member function]
cls.add_method('AddDefault',
'void',
- [param('int', 'v'), param('std::string', 'name')])
+ [param('int', 'value'), param('std::string', 'name')])
## enum.h (module 'core'): bool ns3::EnumChecker::Check(ns3::AttributeValue const & value) const [member function]
cls.add_method('Check',
'bool',
@@ -7045,8 +7045,8 @@
cls.add_constructor([param('ns3::EnumValue const &', 'arg0')])
## enum.h (module 'core'): ns3::EnumValue::EnumValue() [constructor]
cls.add_constructor([])
- ## enum.h (module 'core'): ns3::EnumValue::EnumValue(int v) [constructor]
- cls.add_constructor([param('int', 'v')])
+ ## enum.h (module 'core'): ns3::EnumValue::EnumValue(int value) [constructor]
+ cls.add_constructor([param('int', 'value')])
## enum.h (module 'core'): ns3::Ptr<ns3::AttributeValue> ns3::EnumValue::Copy() const [member function]
cls.add_method('Copy',
'ns3::Ptr< ns3::AttributeValue >',
@@ -7067,10 +7067,10 @@
'std::string',
[param('ns3::Ptr< ns3::AttributeChecker const >', 'checker')],
is_const=True, is_virtual=True)
- ## enum.h (module 'core'): void ns3::EnumValue::Set(int v) [member function]
+ ## enum.h (module 'core'): void ns3::EnumValue::Set(int value) [member function]
cls.add_method('Set',
'void',
- [param('int', 'v')])
+ [param('int', 'value')])
return
def register_Ns3ErlangRandomVariable_methods(root_module, cls):
@@ -9869,8 +9869,14 @@
'ns3::TypeId',
[],
is_static=True)
+ ## radvd.h (module 'applications'): ns3::Radvd::MAX_INITIAL_RTR_ADVERTISEMENTS [variable]
+ cls.add_static_attribute('MAX_INITIAL_RTR_ADVERTISEMENTS', 'uint32_t const', is_const=True)
+ ## radvd.h (module 'applications'): ns3::Radvd::MAX_INITIAL_RTR_ADVERT_INTERVAL [variable]
+ cls.add_static_attribute('MAX_INITIAL_RTR_ADVERT_INTERVAL', 'uint32_t const', is_const=True)
## radvd.h (module 'applications'): ns3::Radvd::MAX_RA_DELAY_TIME [variable]
cls.add_static_attribute('MAX_RA_DELAY_TIME', 'uint32_t const', is_const=True)
+ ## radvd.h (module 'applications'): ns3::Radvd::MIN_DELAY_BETWEEN_RAS [variable]
+ cls.add_static_attribute('MIN_DELAY_BETWEEN_RAS', 'uint32_t const', is_const=True)
## radvd.h (module 'applications'): void ns3::Radvd::DoDispose() [member function]
cls.add_method('DoDispose',
'void',
@@ -9929,6 +9935,10 @@
'uint32_t',
[],
is_const=True)
+ ## radvd-interface.h (module 'applications'): ns3::Time ns3::RadvdInterface::GetLastRaTxTime() [member function]
+ cls.add_method('GetLastRaTxTime',
+ 'ns3::Time',
+ [])
## radvd-interface.h (module 'applications'): uint32_t ns3::RadvdInterface::GetLinkMtu() const [member function]
cls.add_method('GetLinkMtu',
'uint32_t',
@@ -9974,6 +9984,10 @@
'bool',
[],
is_const=True)
+ ## radvd-interface.h (module 'applications'): bool ns3::RadvdInterface::IsInitialRtrAdv() [member function]
+ cls.add_method('IsInitialRtrAdv',
+ 'bool',
+ [])
## radvd-interface.h (module 'applications'): bool ns3::RadvdInterface::IsIntervalOpt() const [member function]
cls.add_method('IsIntervalOpt',
'bool',
@@ -10036,6 +10050,10 @@
cls.add_method('SetIntervalOpt',
'void',
[param('bool', 'intervalOpt')])
+ ## radvd-interface.h (module 'applications'): void ns3::RadvdInterface::SetLastRaTxTime(ns3::Time now) [member function]
+ cls.add_method('SetLastRaTxTime',
+ 'void',
+ [param('ns3::Time', 'now')])
## radvd-interface.h (module 'applications'): void ns3::RadvdInterface::SetLinkMtu(uint32_t linkMtu) [member function]
cls.add_method('SetLinkMtu',
'void',
--- a/src/applications/bindings/modulegen__gcc_LP64.py Thu Nov 13 23:34:10 2014 +0100
+++ b/src/applications/bindings/modulegen__gcc_LP64.py Wed Nov 19 00:13:58 2014 +0100
@@ -4193,7 +4193,6 @@
return
def register_Ns3Int64x64_t_methods(root_module, cls):
- cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('!=')
cls.add_inplace_numeric_operator('+=', param('ns3::int64x64_t const &', u'right'))
cls.add_binary_numeric_operator('*', root_module['ns3::int64x64_t'], root_module['ns3::int64x64_t'], param('ns3::int64x64_t const &', u'right'))
@@ -4207,6 +4206,7 @@
cls.add_inplace_numeric_operator('-=', param('ns3::int64x64_t const &', u'right'))
cls.add_inplace_numeric_operator('/=', param('ns3::int64x64_t const &', u'right'))
cls.add_output_stream_operator()
+ cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('==')
cls.add_binary_comparison_operator('>=')
## int64x64-double.h (module 'core'): ns3::int64x64_t::int64x64_t() [constructor]
@@ -5913,7 +5913,6 @@
return
def register_Ns3Time_methods(root_module, cls):
- cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('!=')
cls.add_inplace_numeric_operator('+=', param('ns3::Time const &', u'right'))
cls.add_binary_numeric_operator('*', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right'))
@@ -5924,6 +5923,7 @@
cls.add_binary_comparison_operator('>')
cls.add_inplace_numeric_operator('-=', param('ns3::Time const &', u'right'))
cls.add_output_stream_operator()
+ cls.add_binary_comparison_operator('<=')
cls.add_binary_comparison_operator('==')
cls.add_binary_comparison_operator('>=')
## nstime.h (module 'core'): ns3::Time::Time() [constructor]
@@ -7000,14 +7000,14 @@
cls.add_constructor([param('ns3::EnumChecker const &', 'arg0')])
## enum.h (module 'core'): ns3::EnumChecker::EnumChecker() [constructor]
cls.add_constructor([])
- ## enum.h (module 'core'): void ns3::EnumChecker::Add(int v, std::string name) [member function]
+ ## enum.h (module 'core'): void ns3::EnumChecker::Add(int value, std::string name) [member function]
cls.add_method('Add',
'void',
- [param('int', 'v'), param('std::string', 'name')])
- ## enum.h (module 'core'): void ns3::EnumChecker::AddDefault(int v, std::string name) [member function]
+ [param('int', 'value'), param('std::string', 'name')])
+ ## enum.h (module 'core'): void ns3::EnumChecker::AddDefault(int value, std::string name) [member function]
cls.add_method('AddDefault',
'void',
- [param('int', 'v'), param('std::string', 'name')])
+ [param('int', 'value'), param('std::string', 'name')])
## enum.h (module 'core'): bool ns3::EnumChecker::Check(ns3::AttributeValue const & value) const [member function]
cls.add_method('Check',
'bool',
@@ -7045,8 +7045,8 @@
cls.add_constructor([param('ns3::EnumValue const &', 'arg0')])
## enum.h (module 'core'): ns3::EnumValue::EnumValue() [constructor]
cls.add_constructor([])
- ## enum.h (module 'core'): ns3::EnumValue::EnumValue(int v) [constructor]
- cls.add_constructor([param('int', 'v')])
+ ## enum.h (module 'core'): ns3::EnumValue::EnumValue(int value) [constructor]
+ cls.add_constructor([param('int', 'value')])
## enum.h (module 'core'): ns3::Ptr<ns3::AttributeValue> ns3::EnumValue::Copy() const [member function]
cls.add_method('Copy',
'ns3::Ptr< ns3::AttributeValue >',
@@ -7067,10 +7067,10 @@
'std::string',
[param('ns3::Ptr< ns3::AttributeChecker const >', 'checker')],
is_const=True, is_virtual=True)
- ## enum.h (module 'core'): void ns3::EnumValue::Set(int v) [member function]
+ ## enum.h (module 'core'): void ns3::EnumValue::Set(int value) [member function]
cls.add_method('Set',
'void',
- [param('int', 'v')])
+ [param('int', 'value')])
return
def register_Ns3ErlangRandomVariable_methods(root_module, cls):
@@ -9869,8 +9869,14 @@
'ns3::TypeId',
[],
is_static=True)
+ ## radvd.h (module 'applications'): ns3::Radvd::MAX_INITIAL_RTR_ADVERTISEMENTS [variable]
+ cls.add_static_attribute('MAX_INITIAL_RTR_ADVERTISEMENTS', 'uint32_t const', is_const=True)
+ ## radvd.h (module 'applications'): ns3::Radvd::MAX_INITIAL_RTR_ADVERT_INTERVAL [variable]
+ cls.add_static_attribute('MAX_INITIAL_RTR_ADVERT_INTERVAL', 'uint32_t const', is_const=True)
## radvd.h (module 'applications'): ns3::Radvd::MAX_RA_DELAY_TIME [variable]
cls.add_static_attribute('MAX_RA_DELAY_TIME', 'uint32_t const', is_const=True)
+ ## radvd.h (module 'applications'): ns3::Radvd::MIN_DELAY_BETWEEN_RAS [variable]
+ cls.add_static_attribute('MIN_DELAY_BETWEEN_RAS', 'uint32_t const', is_const=True)
## radvd.h (module 'applications'): void ns3::Radvd::DoDispose() [member function]
cls.add_method('DoDispose',
'void',
@@ -9929,6 +9935,10 @@
'uint32_t',
[],
is_const=True)
+ ## radvd-interface.h (module 'applications'): ns3::Time ns3::RadvdInterface::GetLastRaTxTime() [member function]
+ cls.add_method('GetLastRaTxTime',
+ 'ns3::Time',
+ [])
## radvd-interface.h (module 'applications'): uint32_t ns3::RadvdInterface::GetLinkMtu() const [member function]
cls.add_method('GetLinkMtu',
'uint32_t',
@@ -9974,6 +9984,10 @@
'bool',
[],
is_const=True)
+ ## radvd-interface.h (module 'applications'): bool ns3::RadvdInterface::IsInitialRtrAdv() [member function]
+ cls.add_method('IsInitialRtrAdv',
+ 'bool',
+ [])
## radvd-interface.h (module 'applications'): bool ns3::RadvdInterface::IsIntervalOpt() const [member function]
cls.add_method('IsIntervalOpt',
'bool',
@@ -10036,6 +10050,10 @@
cls.add_method('SetIntervalOpt',
'void',
[param('bool', 'intervalOpt')])
+ ## radvd-interface.h (module 'applications'): void ns3::RadvdInterface::SetLastRaTxTime(ns3::Time now) [member function]
+ cls.add_method('SetLastRaTxTime',
+ 'void',
+ [param('ns3::Time', 'now')])
## radvd-interface.h (module 'applications'): void ns3::RadvdInterface::SetLinkMtu(uint32_t linkMtu) [member function]
cls.add_method('SetLinkMtu',
'void',
--- a/src/applications/model/radvd-interface.cc Thu Nov 13 23:34:10 2014 +0100
+++ b/src/applications/model/radvd-interface.cc Wed Nov 19 00:13:58 2014 +0100
@@ -50,6 +50,7 @@
m_homeAgentPreference = 0;
m_mobRtrSupportFlag = false;
m_intervalOpt = false;
+ m_initialRtrAdvertisementsLeft = 3;
}
RadvdInterface::RadvdInterface (uint32_t interface, uint32_t maxRtrAdvInterval, uint32_t minRtrAdvInterval)
@@ -76,6 +77,7 @@
m_homeAgentPreference = 0;
m_mobRtrSupportFlag = false;
m_intervalOpt = false;
+ m_initialRtrAdvertisementsLeft = 3;
}
RadvdInterface::~RadvdInterface ()
@@ -335,5 +337,25 @@
NS_LOG_FUNCTION (this << intervalOpt);
m_intervalOpt = intervalOpt;
}
+
+Time RadvdInterface::GetLastRaTxTime ()
+{
+ return m_lastSendTime;
+}
+
+void RadvdInterface::SetLastRaTxTime (Time now)
+{
+ m_lastSendTime = now;
+ if (m_initialRtrAdvertisementsLeft)
+ {
+ m_initialRtrAdvertisementsLeft --;
+ }
+}
+
+bool RadvdInterface::IsInitialRtrAdv ()
+{
+ return m_initialRtrAdvertisementsLeft;
+}
+
} /* namespace ns3 */
--- a/src/applications/model/radvd-interface.h Thu Nov 13 23:34:10 2014 +0100
+++ b/src/applications/model/radvd-interface.h Wed Nov 19 00:13:58 2014 +0100
@@ -23,6 +23,7 @@
#include <list>
#include "ns3/simple-ref-count.h"
+#include "ns3/nstime.h"
#include "radvd-prefix.h"
namespace ns3
@@ -308,6 +309,24 @@
*/
void SetIntervalOpt (bool intervalOpt);
+ /**
+ * \brief Get the last time a RA has been sent.
+ * \returns the last RA send time
+ */
+ Time GetLastRaTxTime ();
+
+ /**
+ * \brief Set the last RA send time. It also decrements the initial Rtr Advertisements counter.
+ * \param the last RA send time
+ */
+ void SetLastRaTxTime (Time now);
+
+ /**
+ * \brief Checks if the interface is subject to the initial Rtr Advertisements rule.
+ * \returns true if the initial Rtr Advertisements counter is greater than zero.
+ */
+ bool IsInitialRtrAdv ();
+
private:
/**
@@ -418,6 +437,17 @@
* \brief Flag to add Advertisement Interval option in RA.
*/
bool m_intervalOpt;
+
+ /**
+ * \brief Last RA send time.
+ */
+ Time m_lastSendTime;
+
+ /**
+ * \brief Number of fast announcement to do
+ */
+ uint8_t m_initialRtrAdvertisementsLeft;
+
};
} /* namespace ns3 */
--- a/src/applications/model/radvd.cc Thu Nov 13 23:34:10 2014 +0100
+++ b/src/applications/model/radvd.cc Wed Nov 19 00:13:58 2014 +0100
@@ -21,6 +21,7 @@
*/
#include "ns3/log.h"
+#include "ns3/abort.h"
#include "ns3/ipv6-address.h"
#include "ns3/nstime.h"
#include "ns3/simulator.h"
@@ -29,7 +30,10 @@
#include "ns3/uinteger.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/ipv6.h"
+#include "ns3/ipv6-l3-protocol.h"
+#include "ns3/ipv6-interface.h"
#include "ns3/ipv6-raw-socket-factory.h"
+#include "ns3/ipv6-packet-info-tag.h"
#include "ns3/ipv6-header.h"
#include "ns3/icmpv6-header.h"
#include "ns3/string.h"
@@ -71,12 +75,22 @@
*it = 0;
}
m_configurations.clear ();
- m_socket = 0;
+ m_recvSocket = 0;
}
void Radvd::DoDispose ()
{
NS_LOG_FUNCTION (this);
+
+ m_recvSocket->Close ();
+ m_recvSocket = 0;
+
+ for (SocketMapI it = m_sendSockets.begin (); it != m_sendSockets.end (); ++it)
+ {
+ it->second->Close ();
+ it->second = 0;
+ }
+
Application::DoDispose ();
}
@@ -84,23 +98,39 @@
{
NS_LOG_FUNCTION (this);
- if (!m_socket)
+ TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
+
+ if (!m_recvSocket)
{
- TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
- m_socket = Socket::CreateSocket (GetNode (), tid);
+ m_recvSocket = Socket::CreateSocket (GetNode (), tid);
- NS_ASSERT (m_socket);
+ NS_ASSERT (m_recvSocket);
- /* m_socket->Bind (Inet6SocketAddress (m_localAddress, 0)); */
- /* m_socket->Connect (Inet6SocketAddress (Ipv6Address::GetAllNodesMulticast (), 0)); */
- m_socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
- m_socket->SetRecvCallback (MakeCallback (&Radvd::HandleRead, this));
+ m_recvSocket->Bind (Inet6SocketAddress (Ipv6Address::GetAllRoutersMulticast (), 0));
+ m_recvSocket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
+ m_recvSocket->SetRecvCallback (MakeCallback (&Radvd::HandleRead, this));
+ m_recvSocket->ShutdownSend ();
+ m_recvSocket->SetRecvPktInfo (true);
}
for (RadvdInterfaceListCI it = m_configurations.begin (); it != m_configurations.end (); it++)
{
- m_eventIds[(*it)->GetInterface ()] = EventId ();
- ScheduleTransmit (Seconds (0.), (*it), m_eventIds[(*it)->GetInterface ()], Ipv6Address::GetAllNodesMulticast (), true);
+ if ((*it)->IsSendAdvert ())
+ {
+ m_unsolicitedEventIds[(*it)->GetInterface ()] = Simulator::Schedule (Seconds (0.), &Radvd::Send,
+ this, (*it), Ipv6Address::GetAllNodesMulticast (), true);
+ }
+
+ if (m_sendSockets.find ((*it)->GetInterface ()) == m_sendSockets.end ())
+ {
+ Ptr<Ipv6L3Protocol> ipv6 = GetNode ()->GetObject<Ipv6L3Protocol> ();
+ Ptr<Ipv6Interface> iFace = ipv6->GetInterface ((*it)->GetInterface ());
+
+ m_sendSockets[(*it)->GetInterface ()] = Socket::CreateSocket (GetNode (), tid);
+ m_sendSockets[(*it)->GetInterface ()]->Bind (Inet6SocketAddress (iFace->GetLinkLocalAddress ().GetAddress (), 0));
+ m_sendSockets[(*it)->GetInterface ()]->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
+ m_sendSockets[(*it)->GetInterface ()]->ShutdownRecv ();
+ }
}
}
@@ -108,16 +138,22 @@
{
NS_LOG_FUNCTION (this);
- if (m_socket)
+ if (m_recvSocket)
{
- m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
+ m_recvSocket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
}
- for (EventIdMapI it = m_eventIds.begin (); it != m_eventIds.end (); ++it)
+ for (EventIdMapI it = m_unsolicitedEventIds.begin (); it != m_unsolicitedEventIds.end (); ++it)
{
Simulator::Cancel ((*it).second);
}
- m_eventIds.clear ();
+ m_unsolicitedEventIds.clear ();
+
+ for (EventIdMapI it = m_solicitedEventIds.begin (); it != m_solicitedEventIds.end (); ++it)
+ {
+ Simulator::Cancel ((*it).second);
+ }
+ m_solicitedEventIds.clear ();
}
void Radvd::AddConfiguration (Ptr<RadvdInterface> routerInterface)
@@ -134,26 +170,20 @@
return 1;
}
-void Radvd::ScheduleTransmit (Time dt, Ptr<RadvdInterface> config, EventId& eventId, Ipv6Address dst, bool reschedule)
-{
- NS_LOG_FUNCTION (this << dt << config << &eventId << dst << reschedule);
- eventId = Simulator::Schedule (dt, &Radvd::Send, this, config, dst, reschedule);
-}
-
void Radvd::Send (Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
{
NS_LOG_FUNCTION (this << dst << reschedule);
- NS_ASSERT (m_eventIds[config->GetInterface ()].IsExpired ());
+
+ if (reschedule == true)
+ {
+ config->SetLastRaTxTime (Simulator::Now ());
+ }
+
Icmpv6RA raHdr;
Icmpv6OptionLinkLayerAddress llaHdr;
Icmpv6OptionMtu mtuHdr;
Icmpv6OptionPrefixInformation prefixHdr;
- if (m_eventIds.size () == 0)
- {
- return;
- }
-
std::list<Ptr<RadvdPrefix> > prefixes = config->GetPrefixes ();
Ptr<Packet> p = Create<Packet> ();
Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
@@ -212,9 +242,9 @@
p->AddHeader (prefixHdr);
}
- Ipv6Address src = ipv6->GetAddress (config->GetInterface (), 0).GetAddress ();
- m_socket->Bind (Inet6SocketAddress (src, 0));
- m_socket->Connect (Inet6SocketAddress (dst, 0));
+ Address sockAddr;
+ m_sendSockets[config->GetInterface ()]->GetSockName (sockAddr);
+ Ipv6Address src = Inet6SocketAddress::ConvertFrom (sockAddr).GetIpv6 ();
/* as we know interface index that will be used to send RA and
* we always send RA with router's link-local address, we can
@@ -231,15 +261,21 @@
p->AddPacketTag (ttl);
/* send RA */
- NS_LOG_LOGIC ("Send RA");
- m_socket->Send (p, 0);
+ NS_LOG_LOGIC ("Send RA to " << dst);
+ m_sendSockets[config->GetInterface ()]->SendTo (p, 0, Inet6SocketAddress (dst, 0));
if (reschedule)
{
uint64_t delay = static_cast<uint64_t> (m_jitter->GetValue (config->GetMinRtrAdvInterval (), config->GetMaxRtrAdvInterval ()) + 0.5);
+ if (config->IsInitialRtrAdv ())
+ {
+ if (delay > MAX_INITIAL_RTR_ADVERT_INTERVAL)
+ delay = MAX_INITIAL_RTR_ADVERT_INTERVAL;
+ }
+
NS_LOG_INFO ("Reschedule in " << delay);
Time t = MilliSeconds (delay);
- ScheduleTransmit (t, config, m_eventIds[config->GetInterface ()], Ipv6Address::GetAllNodesMulticast (), reschedule);
+ m_unsolicitedEventIds[config->GetInterface ()] = Simulator::Schedule (t, &Radvd::Send, this, config, Ipv6Address::GetAllNodesMulticast (), true);
}
}
@@ -253,9 +289,18 @@
{
if (Inet6SocketAddress::IsMatchingType (from))
{
+ Ipv6PacketInfoTag interfaceInfo;
+ if (!packet->RemovePacketTag (interfaceInfo))
+ {
+ NS_ABORT_MSG ("No incoming interface on RADVD message, aborting.");
+ }
+ uint32_t incomingIf = interfaceInfo.GetRecvIf ();
+ Ptr<NetDevice> dev = GetNode ()->GetDevice (incomingIf);
+ Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
+ uint32_t ipInterfaceIndex = ipv6->GetInterfaceForDevice (dev);
+
Ipv6Header hdr;
Icmpv6RS rsHdr;
- Inet6SocketAddress address = Inet6SocketAddress::ConvertFrom (from);
uint64_t delay = 0;
Time t;
@@ -269,20 +314,44 @@
packet->RemoveHeader (rsHdr);
NS_LOG_INFO ("Received ICMPv6 Router Solicitation from " << hdr.GetSourceAddress () << " code = " << (uint32_t)rsHdr.GetCode ());
- /* XXX advertise just prefix(es) for the interface not all */
for (RadvdInterfaceListCI it = m_configurations.begin (); it != m_configurations.end (); it++)
{
- /* calculate minimum delay between RA */
- delay = static_cast<uint64_t> (m_jitter->GetValue (0, MAX_RA_DELAY_TIME) + 0.5);
- t = Simulator::Now () + MilliSeconds (delay); /* absolute time of solicited RA */
+ if (ipInterfaceIndex == (*it)->GetInterface ())
+ {
+ /* calculate minimum delay between RA */
+ delay = static_cast<uint64_t> (m_jitter->GetValue (0, MAX_RA_DELAY_TIME) + 0.5);
+ t = Simulator::Now () + MilliSeconds (delay); /* absolute time of solicited RA */
+
+ if (Simulator::Now () < (*it)->GetLastRaTxTime () + MilliSeconds (MIN_DELAY_BETWEEN_RAS) )
+ {
+ t += MilliSeconds (MIN_DELAY_BETWEEN_RAS);
+ }
+
+ /* if our solicited RA is before the next periodic RA, we schedule it */
+ bool scheduleSingle = true;
- /* if our solicited RA is before the next periodic RA, we schedule it */
- if (t.GetTimeStep () < static_cast<int64_t> (m_eventIds[(*it)->GetInterface ()].GetTs ()))
- {
- NS_LOG_INFO ("schedule new RA");
- EventId ei;
+ if (m_solicitedEventIds.find ((*it)->GetInterface ()) != m_solicitedEventIds.end ())
+ {
+ if (m_solicitedEventIds[(*it)->GetInterface ()].IsRunning ())
+ {
+ scheduleSingle = false;
+ }
+ }
- ScheduleTransmit (MilliSeconds (delay), (*it), ei, address.GetIpv6 (), false);
+ if (m_unsolicitedEventIds.find ((*it)->GetInterface ()) != m_unsolicitedEventIds.end ())
+ {
+ if (t.GetTimeStep () > static_cast<int64_t> (m_unsolicitedEventIds[(*it)->GetInterface ()].GetTs ()))
+ {
+ scheduleSingle = false;
+ }
+ }
+
+ if (scheduleSingle)
+ {
+ NS_LOG_INFO ("schedule new RA");
+ m_solicitedEventIds[(*it)->GetInterface ()] = Simulator::Schedule (MilliSeconds (delay), &Radvd::Send,
+ this, (*it), Ipv6Address::GetAllNodesMulticast (), false);
+ }
}
}
break;
--- a/src/applications/model/radvd.h Thu Nov 13 23:34:10 2014 +0100
+++ b/src/applications/model/radvd.h Wed Nov 19 00:13:58 2014 +0100
@@ -67,6 +67,18 @@
* \brief Default value for maximum delay of RA (ms)
*/
static const uint32_t MAX_RA_DELAY_TIME = 500;
+ /**
+ * \brief Default value for maximum initial RA advertisements
+ */
+ static const uint32_t MAX_INITIAL_RTR_ADVERTISEMENTS = 3;
+ /**
+ * \brief Default value for maximum initial RA advertisements interval (ms)
+ */
+ static const uint32_t MAX_INITIAL_RTR_ADVERT_INTERVAL = 16000;
+ /**
+ * \brief Default value for minimum delay between RA advertisements (ms)
+ */
+ static const uint32_t MIN_DELAY_BETWEEN_RAS = 3000;
/**
* \brief Add configuration for an interface;
@@ -105,6 +117,13 @@
/// Container Const Iterator: interface number, EventId
typedef std::map<uint32_t, EventId>::const_iterator EventIdMapCI;
+ /// Container: interface number, Socket
+ typedef std::map<uint32_t, Ptr<Socket> > SocketMap;
+ /// Container Iterator: interface number, Socket
+ typedef std::map<uint32_t, Ptr<Socket> >::iterator SocketMapI;
+ /// Container Const Iterator: interface number, Socket
+ typedef std::map<uint32_t, Ptr<Socket> >::const_iterator SocketMapCI;
+
/**
* \brief Start the application.
*/
@@ -116,16 +135,6 @@
virtual void StopApplication ();
/**
- * \brief Schedule sending a packet.
- * \param dt interval between packet
- * \param config interface configuration
- * \param eventId event ID associated
- * \param dst IPv6 destination address
- * \param reschedule if true another send will be reschedule (periodic)
- */
- void ScheduleTransmit (Time dt, Ptr<RadvdInterface> config, EventId& eventId, Ipv6Address dst = Ipv6Address::GetAllNodesMulticast (), bool reschedule = false);
-
- /**
* \brief Send a packet.
* \param config interface configuration
* \param dst destination address (default ff02::1)
@@ -140,9 +149,14 @@
void HandleRead (Ptr<Socket> socket);
/**
+ * \brief Raw socket to receive RS.
+ */
+ Ptr<Socket> m_recvSocket;
+
+ /**
* \brief Raw socket to send RA.
*/
- Ptr<Socket> m_socket;
+ SocketMap m_sendSockets;
/**
* \brief List of configuration for interface.
@@ -150,9 +164,14 @@
RadvdInterfaceList m_configurations;
/**
- * \brief Event ID map.
+ * \brief Event ID map for unsolicited RAs.
*/
- EventIdMap m_eventIds;
+ EventIdMap m_unsolicitedEventIds;
+
+ /**
+ * \brief Event ID map for solicited RAs.
+ */
+ EventIdMap m_solicitedEventIds;
/**
* \brief Variable to provide jitter in advertisement interval