14#include "ns3/address-utils.h" 
   15#include "ns3/icmpv6-l4-protocol.h" 
   16#include "ns3/ipv6-interface.h" 
   17#include "ns3/ipv6-l3-protocol.h" 
   18#include "ns3/ipv6-packet-info-tag.h" 
   21#include "ns3/loopback-net-device.h" 
   22#include "ns3/mac48-address.h" 
   23#include "ns3/net-device-container.h" 
   24#include "ns3/object.h" 
   25#include "ns3/pointer.h" 
   27#include "ns3/random-variable-stream.h" 
   28#include "ns3/simulator.h" 
   29#include "ns3/socket.h" 
   30#include "ns3/string.h" 
   31#include "ns3/trace-source-accessor.h" 
   32#include "ns3/traced-value.h" 
   33#include "ns3/trickle-timer.h" 
   48            .AddConstructor<Dhcp6Client>()
 
   49            .SetGroupName(
"InternetApps")
 
   50            .AddAttribute(
"Transactions",
 
   51                          "A value to be used as the transaction ID.",
 
   52                          StringValue(
"ns3::UniformRandomVariable[Min=0.0|Max=1000000.0]"),
 
   55            .AddAttribute(
"SolicitJitter",
 
   56                          "The jitter in ms that a node waits before sending any solicitation. By " 
   57                          "default, the model will wait for a duration in ms defined by a uniform " 
   58                          "random-variable between 0 and SolicitJitter. This is equivalent to" 
   59                          "SOL_MAX_DELAY (RFC 8415, Section 7.6).",
 
   60                          StringValue(
"ns3::UniformRandomVariable[Min=0.0|Max=1000.0]"),
 
   63            .AddAttribute(
"IaidValue",
 
   64                          "The identifier for a new IA created by a client.",
 
   65                          StringValue(
"ns3::UniformRandomVariable[Min=0.0|Max=1000000.0]"),
 
   68            .AddAttribute(
"SolicitInterval",
 
   69                          "Time after which the client resends the Solicit." 
   70                          "Equivalent to SOL_MAX_RT (RFC 8415, Section 7.6)",
 
   74            .AddTraceSource(
"NewLease",
 
   75                            "The client has obtained a lease",
 
   77                            "ns3::Ipv6Address::TracedCallback");
 
 
   93        itr.second->Cleanup();
 
 
  117    int32_t ifIndex = ipv6->GetInterfaceForDevice(iDev);
 
  121    if (clientTransactId != receivedTransactId)
 
 
  145    int32_t ifIndex = ipv6->GetInterfaceForDevice(iDev);
 
  159        (
Simulator::Now() - dhcpInterface->m_msgStartTime).GetMilliSeconds() / 10;
 
  160    uint16_t elapsed = actualElapsedTime > 65535 ? 65535 : actualElapsedTime;
 
  167    for (
const auto& iaOpt : ianaOptionsList)
 
  171        for (
const auto& iaAddrOpt : iaOpt.m_iaAddressOption)
 
  173            requestHeader.
AddIanaOption(iaOpt.GetIaid(), iaOpt.GetT1(), iaOpt.GetT2());
 
  175                                     iaAddrOpt.GetIaAddress(),
 
  176                                     iaAddrOpt.GetPreferredLifetime(),
 
  177                                     iaAddrOpt.GetValidLifetime());
 
  179            NS_LOG_DEBUG(
"Requesting " << iaAddrOpt.GetIaAddress());
 
  186    packet->AddHeader(requestHeader);
 
  192    if (dhcpInterface->m_socket->SendTo(
 
  201        NS_LOG_INFO(
"DHCPv6 client: Error while sending Request.");
 
 
  216    std::cout << 
"InterfaceConfig::~InterfaceConfig" << std::endl;
 
  222    m_solicitTimer.Stop();
 
  223    m_declinedAddresses.clear();
 
  225    m_renewEvent.Cancel();
 
  226    m_rebindEvent.Cancel();
 
  228    for (
auto& itr : m_releaseEvent)
 
 
  241    for (
auto& addr : m_offeredAddresses)
 
  243        if (addr == offeredAddress)
 
  252        m_nAcceptedAddresses += 1;
 
  255        m_client->m_newLease(offeredAddress);
 
  256        std::cerr << 
"* got a new lease " << offeredAddress << std::endl;
 
 
  263    NS_LOG_DEBUG(
"Address to be declined " << offeredAddress);
 
  267    for (
auto& addr : m_offeredAddresses)
 
  269        if (addr == offeredAddress)
 
  278        m_declinedAddresses.emplace_back(offeredAddress);
 
  279        if (m_declinedAddresses.size() + m_nAcceptedAddresses == m_offeredAddresses.size())
 
 
  289    if (m_declinedAddresses.empty())
 
  295    m_renewEvent.Cancel();
 
  296    m_rebindEvent.Cancel();
 
  297    for (
auto itr : m_releaseEvent)
 
  306    for (
const auto& offer : m_declinedAddresses)
 
  308        uint32_t iaid = m_client->m_iaidMap[offer];
 
  311        declineHeader.
AddIanaOption(iaid, m_renewTime.GetSeconds(), m_rebindTime.GetSeconds());
 
  314                                 m_prefLifetime.GetSeconds(),
 
  315                                 m_validLifetime.GetSeconds());
 
  319    m_transactId = 
static_cast<uint32_t>(m_client->m_transactionId->GetValue());
 
  332    packet->AddHeader(declineHeader);
 
  333    if ((m_socket->SendTo(packet,
 
  342        NS_LOG_INFO(
"DHCPv6 client: Error while sending Decline");
 
 
  351    m_solicitTimer.Stop();
 
  353    for (
auto& releaseEvent : m_releaseEvent)
 
  355        releaseEvent.Cancel();
 
  358    m_renewEvent.Cancel();
 
  359    m_rebindEvent.Cancel();
 
  367    for (
uint32_t i = 0; i < ipv6->GetNAddresses(m_interfaceIndex); i++)
 
  369        for (
const auto& addr : m_offeredAddresses)
 
  371            if (ipv6->GetAddress(m_interfaceIndex, i) == addr)
 
  373                ipv6->RemoveAddress(m_interfaceIndex, i);
 
  378    m_offeredAddresses.clear();
 
  383    icmpv6->TraceDisconnectWithoutContext(
"DadSuccess", m_acceptedAddressCb.value());
 
  385    icmpv6->TraceDisconnectWithoutContext(
"DadFailure", m_declinedAddressCb.value());
 
 
  397    NS_LOG_DEBUG(
"Received status " << (uint16_t)statusCode << 
" from DHCPv6 server");
 
  400        NS_LOG_INFO(
"DHCPv6 client: Server bindings updated successfully.");
 
  404        NS_LOG_INFO(
"DHCPv6 client: Server bindings update failed.");
 
 
  414    int32_t ifIndex = ipv6->GetInterfaceForDevice(iDev);
 
  421    dhcpInterface->m_declinedAddresses.clear();
 
  425    std::vector<uint32_t> iaidList;
 
  427    for (
const auto& iaOpt : ianaOptionsList)
 
  431        for (
const auto& iaAddrOpt : iaOpt.m_iaAddressOption)
 
  433            Ipv6Address offeredAddress = iaAddrOpt.GetIaAddress();
 
  437            ipv6->AddAddress(ifIndex, addr);
 
  438            ipv6->SetUp(ifIndex);
 
  441            dhcpInterface->m_prefLifetime = 
Seconds(iaAddrOpt.GetPreferredLifetime());
 
  442            dhcpInterface->m_validLifetime = 
Seconds(iaAddrOpt.GetValidLifetime());
 
  445            m_iaidMap[offeredAddress] = iaOpt.GetIaid();
 
  448            dhcpInterface->m_releaseEvent.emplace_back(
 
  454            dhcpInterface->m_offeredAddresses.push_back(offeredAddress);
 
  457        earliestRenew = std::min(earliestRenew, 
Seconds(iaOpt.GetT1()));
 
  458        earliestRebind = std::min(earliestRebind, 
Seconds(iaOpt.GetT2()));
 
  459        iaidList.emplace_back(iaOpt.GetIaid());
 
  464    dhcpInterface->m_renewTime = earliestRenew;
 
  465    dhcpInterface->m_renewEvent.Cancel();
 
  466    dhcpInterface->m_renewEvent =
 
  470    dhcpInterface->m_rebindTime = earliestRebind;
 
  471    dhcpInterface->m_rebindEvent.Cancel();
 
  472    dhcpInterface->m_rebindEvent =
 
  475    int32_t interfaceId = ipv6->GetInterfaceForDevice(iDev);
 
  481    if (!dhcpInterface->m_acceptedAddressCb.has_value())
 
  483        dhcpInterface->m_acceptedAddressCb =
 
  485        icmpv6->TraceConnectWithoutContext(
"DadSuccess",
 
  486                                           dhcpInterface->m_acceptedAddressCb.value());
 
  489    if (!dhcpInterface->m_declinedAddressCb.has_value())
 
  491        dhcpInterface->m_declinedAddressCb =
 
  493        icmpv6->TraceConnectWithoutContext(
"DadFailure",
 
  494                                           dhcpInterface->m_declinedAddressCb.value());
 
 
  522    for (
const auto& iaidRenew : 
m_interfaces[dhcpInterfaceIndex]->m_iaids)
 
  525                             m_interfaces[dhcpInterfaceIndex]->m_renewTime.GetSeconds(),
 
  526                             m_interfaces[dhcpInterfaceIndex]->m_rebindTime.GetSeconds());
 
  534            if (iaid == iaidRenew)
 
  538                                  m_interfaces[dhcpInterfaceIndex]->m_prefLifetime.GetSeconds(),
 
  539                                  m_interfaces[dhcpInterfaceIndex]->m_validLifetime.GetSeconds());
 
  543        NS_LOG_DEBUG(
"Renewing addresses in IAID " << iaidRenew);
 
  549    packet->AddHeader(header);
 
  550    if ((
m_interfaces[dhcpInterfaceIndex]->m_socket->SendTo(
 
  560        NS_LOG_INFO(
"DHCPv6 client: Error while sending Renew");
 
 
  587    for (
const auto& iaid : 
m_interfaces[dhcpInterfaceIndex]->m_iaids)
 
  590                             m_interfaces[dhcpInterfaceIndex]->m_renewTime.GetSeconds(),
 
  591                             m_interfaces[dhcpInterfaceIndex]->m_rebindTime.GetSeconds());
 
  599    packet->AddHeader(header);
 
  600    if ((
m_interfaces[dhcpInterfaceIndex]->m_socket->SendTo(
 
  610        NS_LOG_INFO(
"DHCPv6 client: Error while sending Rebind");
 
 
  632        bool removed = ipv6->RemoveAddress(ifIndex, address);
 
  639        header.SetTransactId(dhcpInterface->m_transactId);
 
  646        header.AddServerIdentifier(dhcpInterface->m_serverDuid);
 
  649        header.AddElapsedTime(0);
 
  653        header.AddIanaOption(iaid,
 
  654                             dhcpInterface->m_renewTime.GetSeconds(),
 
  655                             dhcpInterface->m_rebindTime.GetSeconds());
 
  656        header.AddAddress(iaid,
 
  658                          dhcpInterface->m_prefLifetime.GetSeconds(),
 
  659                          dhcpInterface->m_validLifetime.GetSeconds());
 
  663        packet->AddHeader(header);
 
  664        if ((dhcpInterface->m_socket->SendTo(packet,
 
  673            NS_LOG_INFO(
"DHCPv6 client: Error while sending Release");
 
 
  693                  "No incoming interface on DHCPv6 message.");
 
  698    uint32_t iIf = ipv6->GetInterfaceForDevice(iDev);
 
  701    if (packet->RemoveHeader(header) == 0 || !dhcpInterface)
 
  709        dhcpInterface->m_solicitTimer.Stop();
 
  721        dhcpInterface->m_renewEvent.Cancel();
 
  722        dhcpInterface->m_rebindEvent.Cancel();
 
  723        for (
auto itr : dhcpInterface->m_releaseEvent)
 
 
  751        dhcpInterface->Cleanup();
 
 
  768    NS_ASSERT_MSG(node, 
"Dhcp6Client::StartApplication: cannot get the node from the device.");
 
  771    NS_ASSERT_MSG(ipv6, 
"Dhcp6Client::StartApplication: node does not have IPv6.");
 
  773    NS_LOG_DEBUG(
"Starting DHCPv6 application on node " << node->GetId());
 
  776    uint32_t nInterfaces = ipv6->GetNInterfaces();
 
  779    for (
uint32_t ifIndex = 1; ifIndex < nInterfaces; ifIndex++)
 
 
  802        dhcpInterface->m_client = 
this;
 
  803        dhcpInterface->m_interfaceIndex = recvInterface;
 
  804        dhcpInterface->m_socket = 
nullptr;
 
  809        std::vector<uint32_t> existingIaNaIds;
 
  813            if (std::find(existingIaNaIds.begin(), existingIaNaIds.end(), iaid) ==
 
  814                existingIaNaIds.end())
 
  816                dhcpInterface->m_iaids.push_back(iaid);
 
  817                existingIaNaIds.emplace_back(iaid);
 
  824        ipv6Interface->TraceConnectWithoutContext(
 
  837        if (interface == recvInterface && 
m_interfaces[interface])
 
  842                    ipv6l3->GetInterface(interface)->GetLinkLocalAddress().GetAddress();
 
  847                socket->BindToNetDevice(device);
 
  848                socket->SetRecvPktInfo(
true);
 
  862                dhcpInterface->m_solicitTimer.Enable();
 
 
  873    int32_t ifIndex = ipv6->GetInterfaceForDevice(device);
 
  900    for (
auto iaid : dhcpInterface->m_iaids)
 
  903                             dhcpInterface->m_renewTime.GetSeconds(),
 
  904                             dhcpInterface->m_rebindTime.GetSeconds());
 
  907    packet->AddHeader(header);
 
  909    if ((dhcpInterface->m_socket->SendTo(packet,
 
  918        NS_LOG_INFO(
"DHCPv6 client: Error while sending Solicit");
 
 
  936        itr.second->Cleanup();
 
 
a polymophic address class
The base class for all ns3 applications.
void DoDispose() override
Destructor implementation.
Ptr< Node > GetNode() const
void DeclineOffer()
Send a Decline message to the DHCPv6 server.
uint8_t m_nAcceptedAddresses
Number of addresses accepted by client.
Time m_prefLifetime
Preferred lifetime of the address.
Time m_rebindTime
REB_MAX_RT, Time after which client should send a Rebind message.
~InterfaceConfig()
Destructor.
void AcceptedAddress(const Ipv6Address &offeredAddress)
Accept the DHCPv6 offer.
InterfaceConfig()
The default constructor.
void DeclinedAddress(const Ipv6Address &offeredAddress)
Add a declined address to the list maintained by the client.
void Cleanup()
Cleanup the internal callbacks and timers.
Time m_renewTime
REN_MAX_RT, Time after which lease should be renewed.
Time m_validLifetime
Valid lifetime of the address.
void CheckLeaseStatus(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress server) const
Check lease status after sending a Decline or Release message.
Duid GetSelfDuid() const
Get the DUID.
std::unordered_map< uint32_t, Ptr< InterfaceConfig > > m_interfaces
Map each interface to its corresponding configuration details.
std::unordered_map< Ipv6Address, uint32_t, Ipv6AddressHash > m_iaidMap
Track the IPv6 Address - IAID association.
void ReceiveMflag(uint32_t recvInterface)
Callback for when an M flag is received.
void LinkStateHandler(bool isUp, int32_t ifIndex)
Handle changes in the link state.
Ptr< RandomVariableStream > m_solicitJitter
Random jitter before sending the first Solicit.
void SendRelease(Ipv6Address address)
Send a Release message to the DHCPv6 server.
static TypeId GetTypeId()
Get the type ID.
TracedCallback< const Ipv6Address & > m_newLease
Trace the new lease.
bool ValidateAdvertise(Dhcp6Header header, Ptr< NetDevice > iDev)
Verify the incoming advertise message.
void Boot(Ptr< NetDevice > device)
Used to send the Solicit message and start the DHCPv6 client.
@ WAIT_REPLY_AFTER_DECLINE
@ WAIT_REPLY_AFTER_RELEASE
void ProcessReply(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress server)
Send a request to the DHCPv6 server.
Ptr< RandomVariableStream > m_transactionId
Random variable to set transaction ID.
void SendRequest(Ptr< NetDevice > iDev, Dhcp6Header header, Inet6SocketAddress server)
Send a request to the DHCPv6 server.
void StartApplication() override
Application specific startup code.
void StopApplication() override
Application specific shutdown code.
void NetHandler(Ptr< Socket > socket)
Handles incoming packets from the network.
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this Application object.
Ptr< RandomVariableStream > m_iaidStream
Random variable used to create the IAID.
void SendRebind(uint32_t interfaceIndex)
Send a rebind message to the DHCPv6 server.
void SendRenew(uint32_t interfaceIndex)
Send a renew message to the DHCPv6 server.
Time m_solicitInterval
SOL_MAX_RT, time between solicitations.
Duid m_clientDuid
The client DUID.
void DoDispose() override
Destructor implementation.
Implements the unique identifier for DHCPv6.
bool IsInvalid() const
Check if the DUID is invalid.
void Initialize(Ptr< Node > node)
Initialize the DUID for a client or server.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
Duid GetDuid() const
Get the DUID object.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
Describes an IPv6 address.
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
Access to the IPv6 forwarding table, interfaces, and configuration.
IPv6 address associated with an interface.
IPv6 layer implementation.
This class implements a tag that carries socket ancillary data to the socket interface.
uint32_t GetRecvIf() const
Get the tag's receiving interface.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
StatusCodeValues
Enum to identify the status code of the operation.
Smart pointer class similar to boost::intrusive_ptr.
virtual double GetValue()=0
Get the next random value drawn from the distribution.
virtual uint32_t GetInteger()
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
StatusCodeValues GetStatusCode() const
Get the status code of the operation.
Hold variables of type string.
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
AttributeValue implementation for Time.
A Trickle Timer following RFC 6206 .
a unique identifier for an interface.
static TypeId LookupByName(std::string name)
Get a TypeId by name.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Callback< R, Args... > MakeNullCallback()
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time Seconds(double value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.