A Discrete-Event Network Simulator
API
dhcp-server.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 UPB
3  * Copyright (c) 2017 NITK Surathkal
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Radu Lupu <rlupu@elcom.pub.ro>
19  * Ankit Deepak <adadeepak8@gmail.com>
20  * Deepti Rajagopal <deeptir96@gmail.com>
21  *
22  */
23 
24 #include "dhcp-server.h"
25 
26 #include "dhcp-header.h"
27 
28 #include "ns3/assert.h"
29 #include "ns3/ipv4-packet-info-tag.h"
30 #include "ns3/ipv4.h"
31 #include "ns3/log.h"
32 #include "ns3/nstime.h"
33 #include "ns3/packet.h"
34 #include "ns3/simulator.h"
35 #include "ns3/socket.h"
36 
37 #include <algorithm>
38 
39 namespace ns3
40 {
41 
42 NS_LOG_COMPONENT_DEFINE("DhcpServer");
43 NS_OBJECT_ENSURE_REGISTERED(DhcpServer);
44 
45 TypeId
47 {
48  static TypeId tid = TypeId("ns3::DhcpServer")
50  .AddConstructor<DhcpServer>()
51  .SetGroupName("Internet-Apps")
52  .AddAttribute("LeaseTime",
53  "Lease for which address will be leased.",
54  TimeValue(Seconds(30)),
57  .AddAttribute("RenewTime",
58  "Time after which client should renew.",
59  TimeValue(Seconds(15)),
62  .AddAttribute("RebindTime",
63  "Time after which client should rebind.",
64  TimeValue(Seconds(25)),
67  .AddAttribute("PoolAddresses",
68  "Pool of addresses to provide on request.",
69  Ipv4AddressValue(),
70  MakeIpv4AddressAccessor(&DhcpServer::m_poolAddress),
71  MakeIpv4AddressChecker())
72  .AddAttribute("FirstAddress",
73  "The First valid address that can be given.",
74  Ipv4AddressValue(),
75  MakeIpv4AddressAccessor(&DhcpServer::m_minAddress),
76  MakeIpv4AddressChecker())
77  .AddAttribute("LastAddress",
78  "The Last valid address that can be given.",
79  Ipv4AddressValue(),
80  MakeIpv4AddressAccessor(&DhcpServer::m_maxAddress),
81  MakeIpv4AddressChecker())
82  .AddAttribute("PoolMask",
83  "Mask of the pool of addresses.",
84  Ipv4MaskValue(),
85  MakeIpv4MaskAccessor(&DhcpServer::m_poolMask),
86  MakeIpv4MaskChecker())
87  .AddAttribute("Gateway",
88  "Address of default gateway",
89  Ipv4AddressValue(),
90  MakeIpv4AddressAccessor(&DhcpServer::m_gateway),
91  MakeIpv4AddressChecker());
92  return tid;
93 }
94 
96 {
97  NS_LOG_FUNCTION(this);
98 }
99 
101 {
102  NS_LOG_FUNCTION(this);
103 }
104 
105 void
107 {
108  NS_LOG_FUNCTION(this);
110 }
111 
112 void
114 {
115  NS_LOG_FUNCTION(this);
116 
117  NS_ASSERT_MSG(m_minAddress < m_maxAddress, "Invalid Address range");
118 
119  Ipv4Address myOwnAddress;
120 
121  if (m_socket)
122  {
123  NS_ABORT_MSG("DHCP daemon is not (yet) meant to be started twice or more.");
124  }
125 
126  uint32_t addrIndex;
127 
128  // add the DHCP local address to the leased addresses list, if it is defined!
130  int32_t ifIndex = ipv4->GetInterfaceForPrefix(m_poolAddress, m_poolMask);
131 
132  if (ifIndex < 0)
133  {
134  NS_ABORT_MSG("DHCP daemon must be run on the same subnet it is assigning the addresses.");
135  }
136 
137  for (addrIndex = 0; addrIndex < ipv4->GetNAddresses(ifIndex); addrIndex++)
138  {
139  if (ipv4->GetAddress(ifIndex, addrIndex).GetLocal().CombineMask(m_poolMask) ==
140  m_poolAddress &&
141  ipv4->GetAddress(ifIndex, addrIndex).GetLocal().Get() >= m_minAddress.Get() &&
142  ipv4->GetAddress(ifIndex, addrIndex).GetLocal().Get() <= m_maxAddress.Get())
143  {
144  // set infinite GRANTED_LEASED_TIME for my address
145 
146  myOwnAddress = ipv4->GetAddress(ifIndex, addrIndex).GetLocal();
147  m_leasedAddresses[Address()] = std::make_pair(myOwnAddress, 0xffffffff);
148  break;
149  }
150  }
151 
152  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
156  m_socket->BindToNetDevice(ipv4->GetNetDevice(ifIndex));
157  m_socket->Bind(local);
158  m_socket->SetRecvPktInfo(true);
159 
160  uint32_t range = m_maxAddress.Get() - m_minAddress.Get() + 1;
161  for (uint32_t searchSeq = 0; searchSeq < range; searchSeq++)
162  {
163  Ipv4Address poolAddress(m_minAddress.Get() + searchSeq);
164  if (poolAddress != myOwnAddress)
165  {
166  NS_LOG_LOGIC("Adding " << poolAddress << " to the pool");
167  m_availableAddresses.push_back(poolAddress);
168  }
169  }
170 
173 }
174 
175 void
177 {
178  NS_LOG_FUNCTION(this);
179 
180  if (m_socket)
181  {
183  }
184 
185  m_leasedAddresses.clear();
187 }
188 
189 void
191 {
192  NS_LOG_FUNCTION(this);
193 
194  // Set up timeout events and release of unsolicited addresses from the list
196  for (i = m_leasedAddresses.begin(); i != m_leasedAddresses.end(); i++)
197  {
198  // update the address state
199  if (i->second.second != 0xffffffff && i->second.second != 0)
200  {
201  i->second.second--;
202  if (i->second.second == 0)
203  {
204  NS_LOG_INFO("Address leased state expired, address removed - "
205  << "chaddr: " << i->first << " IP address " << i->second.first);
206  i->second.second = 0;
207  m_expiredAddresses.push_front(i->first);
208  }
209  }
210  }
212 }
213 
214 void
216 {
217  NS_LOG_FUNCTION(this << socket);
218 
219  DhcpHeader header;
220  Ptr<Packet> packet = nullptr;
221  Address from;
222  packet = m_socket->RecvFrom(from);
223 
225 
226  Ipv4PacketInfoTag interfaceInfo;
227  if (!packet->RemovePacketTag(interfaceInfo))
228  {
229  NS_ABORT_MSG("No incoming interface on DHCP message, aborting.");
230  }
231  uint32_t incomingIf = interfaceInfo.GetRecvIf();
232  Ptr<NetDevice> iDev = GetNode()->GetDevice(incomingIf);
233 
234  if (packet->RemoveHeader(header) == 0)
235  {
236  return;
237  }
238  if (header.GetType() == DhcpHeader::DHCPDISCOVER)
239  {
240  SendOffer(iDev, header, senderAddr);
241  }
242  if (header.GetType() == DhcpHeader::DHCPREQ && (header.GetReq()).Get() >= m_minAddress.Get() &&
243  (header.GetReq()).Get() <= m_maxAddress.Get())
244  {
245  SendAck(iDev, header, senderAddr);
246  }
247 }
248 
249 void
251 {
252  NS_LOG_FUNCTION(this << iDev << header << from);
253 
254  DhcpHeader newDhcpHeader;
255  Address sourceChaddr = header.GetChaddr();
256  uint32_t tran = header.GetTran();
257  Ptr<Packet> packet = nullptr;
258  Ipv4Address offeredAddress;
259 
260  NS_LOG_INFO("DHCP DISCOVER from: " << from.GetIpv4() << " source port: " << from.GetPort());
261 
262  auto iter = m_leasedAddresses.find(sourceChaddr);
263  if (iter != m_leasedAddresses.end())
264  {
265  // We know this client from some time ago
266  if (m_leasedAddresses[sourceChaddr].second != 0 &&
267  m_leasedAddresses[sourceChaddr].second != 0xffffffff)
268  {
269  NS_LOG_LOGIC("This client is sending a DISCOVER but it has still a lease active - "
270  "perhaps it didn't shut down gracefully: "
271  << sourceChaddr);
272  }
273 
274  m_expiredAddresses.remove(sourceChaddr);
275  offeredAddress = m_leasedAddresses[sourceChaddr].first;
276  }
277  else
278  {
279  // No previous record of the client, we must find a suitable address and create a record.
280  if (!m_availableAddresses.empty())
281  {
282  // use an address never used before (if there is one)
283  offeredAddress = m_availableAddresses.front();
284  m_availableAddresses.pop_front();
285  }
286  else
287  {
288  // there's still hope: reuse the old ones.
289  if (!m_expiredAddresses.empty())
290  {
291  Address oldestChaddr = m_expiredAddresses.back();
292  m_expiredAddresses.pop_back();
293  offeredAddress = m_leasedAddresses[oldestChaddr].first;
294  m_leasedAddresses.erase(oldestChaddr);
295  }
296  }
297  }
298 
299  if (offeredAddress != Ipv4Address())
300  {
301  m_leasedAddresses[sourceChaddr] = std::make_pair(offeredAddress, m_lease.GetSeconds());
302 
303  packet = Create<Packet>();
304  newDhcpHeader.ResetOpt();
305  newDhcpHeader.SetType(DhcpHeader::DHCPOFFER);
306  newDhcpHeader.SetChaddr(sourceChaddr);
307  newDhcpHeader.SetYiaddr(offeredAddress);
308 
310  Ipv4Address myAddress =
311  ipv4->SelectSourceAddress(iDev,
312  offeredAddress,
313  Ipv4InterfaceAddress::InterfaceAddressScope_e::GLOBAL);
314 
315  newDhcpHeader.SetDhcps(myAddress);
316  newDhcpHeader.SetMask(m_poolMask.Get());
317  newDhcpHeader.SetTran(tran);
318  newDhcpHeader.SetLease(m_lease.GetSeconds());
319  newDhcpHeader.SetRenew(m_renew.GetSeconds());
320  newDhcpHeader.SetRebind(m_rebind.GetSeconds());
321  newDhcpHeader.SetTime();
322  if (m_gateway != Ipv4Address())
323  {
324  newDhcpHeader.SetRouter(m_gateway);
325  }
326  packet->AddHeader(newDhcpHeader);
327 
328  if ((m_socket->SendTo(packet,
329  0,
330  InetSocketAddress(Ipv4Address("255.255.255.255"), from.GetPort()))) >=
331  0)
332  {
333  NS_LOG_INFO("DHCP OFFER"
334  << " Offered Address: " << offeredAddress);
335  }
336  else
337  {
338  NS_LOG_INFO("Error while sending DHCP OFFER");
339  }
340  }
341 }
342 
343 void
345 {
346  NS_LOG_FUNCTION(this << iDev << header << from);
347 
348  DhcpHeader newDhcpHeader;
349  Address sourceChaddr = header.GetChaddr();
350  uint32_t tran = header.GetTran();
351  Ptr<Packet> packet = nullptr;
352  Ipv4Address address = header.GetReq();
353 
354  NS_LOG_INFO("DHCP REQUEST from: " << from.GetIpv4() << " source port: " << from.GetPort()
355  << " - refreshed addr: " << address);
356 
357  LeasedAddressIter iter;
358  iter = m_leasedAddresses.find(sourceChaddr);
359  if (iter != m_leasedAddresses.end())
360  {
361  // update the lease time of this address - send ACK
362  (iter->second.second) += m_lease.GetSeconds();
363  packet = Create<Packet>();
364  newDhcpHeader.ResetOpt();
365  newDhcpHeader.SetType(DhcpHeader::DHCPACK);
366  newDhcpHeader.SetChaddr(sourceChaddr);
367  newDhcpHeader.SetYiaddr(address);
368  newDhcpHeader.SetTran(tran);
369  newDhcpHeader.SetTime();
370  packet->AddHeader(newDhcpHeader);
371  if (from.GetIpv4() != address)
372  {
373  m_socket->SendTo(packet,
374  0,
375  InetSocketAddress(Ipv4Address("255.255.255.255"), from.GetPort()));
376  }
377  else
378  {
379  m_socket->SendTo(packet, 0, from);
380  }
381  }
382  else
383  {
384  // Deleted or expired lease - send NACK
385  packet = Create<Packet>();
386  newDhcpHeader.ResetOpt();
387  newDhcpHeader.SetType(DhcpHeader::DHCPNACK);
388  newDhcpHeader.SetChaddr(sourceChaddr);
389  newDhcpHeader.SetYiaddr(address);
390  newDhcpHeader.SetTran(tran);
391  newDhcpHeader.SetTime();
392  packet->AddHeader(newDhcpHeader);
393  if (from.GetIpv4() != address)
394  {
395  m_socket->SendTo(packet,
396  0,
397  InetSocketAddress(Ipv4Address("255.255.255.255"), from.GetPort()));
398  }
399  else
400  {
401  m_socket->SendTo(packet, 0, from);
402  }
403  NS_LOG_INFO("IP addr does not exists or released!");
404  }
405 }
406 
407 void
409 {
410  NS_LOG_FUNCTION(this << chaddr << addr);
411  Address cleanedCaddr;
412 
413  NS_ASSERT_MSG(addr.Get() >= m_minAddress.Get() && addr.Get() <= m_maxAddress.Get(),
414  "Required address is not in the pool " << addr << " is not in [" << m_minAddress
415  << ", " << m_maxAddress << "]");
416 
417  // We need to cleanup the type from the stored chaddr, or later we'll fail to compare it.
418  // Moreover, the length is always 16, because chaddr is 16 bytes.
419  uint8_t buffer[Address::MAX_SIZE];
420  std::memset(buffer, 0, Address::MAX_SIZE);
421  uint32_t len = chaddr.CopyTo(buffer);
422  NS_ASSERT_MSG(len <= 16, "DHCP server can not handle a chaddr larger than 16 bytes");
423  cleanedCaddr.CopyFrom(buffer, 16);
424 
425  NS_ASSERT_MSG(m_leasedAddresses.find(cleanedCaddr) == m_leasedAddresses.end(),
426  "Client has already an active lease: " << m_leasedAddresses[cleanedCaddr].first);
427 
428  auto it = find(m_availableAddresses.begin(), m_availableAddresses.end(), addr);
430  it == m_availableAddresses.end(),
431  "Required address is not available (perhaps it has been already assigned): " << addr);
432 
433  m_availableAddresses.remove(addr);
434  m_leasedAddresses[cleanedCaddr] = std::make_pair(addr, 0xffffffff);
435 }
436 
437 } // Namespace ns3
a polymophic address class
Definition: address.h:101
uint32_t CopyFrom(const uint8_t *buffer, uint8_t len)
Definition: address.cc:106
static constexpr uint32_t MAX_SIZE
The maximum size of a byte buffer which can be stored in an Address instance.
Definition: address.h:107
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition: address.cc:86
The base class for all ns3 applications.
Definition: application.h:62
void DoDispose() override
Destructor implementation.
Definition: application.cc:86
Ptr< Node > GetNode() const
Definition: application.cc:108
BOOTP header with DHCP messages supports the following options: Subnet Mask (1), Address Request (50)...
Definition: dhcp-header.h:85
void SetTime()
Set the time when message is sent.
Definition: dhcp-header.cc:113
Ipv4Address GetReq() const
Get the IPv4Address requested by the client.
Definition: dhcp-header.cc:183
void ResetOpt()
Reset the BOOTP options.
Definition: dhcp-header.cc:274
void SetType(uint8_t type)
Set the type of BOOTP and DHCP messages.
Definition: dhcp-header.cc:76
@ DHCPACK
Code for DHCP ACK.
Definition: dhcp-header.h:123
@ DHCPOFFER
Code for DHCP Offer.
Definition: dhcp-header.h:121
@ DHCPDISCOVER
Code for DHCP Discover.
Definition: dhcp-header.h:120
@ DHCPREQ
Code for DHCP Request.
Definition: dhcp-header.h:122
@ DHCPNACK
Code for DHCP NACK.
Definition: dhcp-header.h:124
void SetTran(uint32_t tran)
Set the transaction ID.
Definition: dhcp-header.cc:101
Address GetChaddr()
Get the Address of the client.
Definition: dhcp-header.cc:135
void SetYiaddr(Ipv4Address addr)
Set the IPv4Address of the client.
Definition: dhcp-header.cc:143
void SetDhcps(Ipv4Address addr)
Set the DHCP server information.
Definition: dhcp-header.cc:155
uint8_t GetType() const
Return the type of DHCP message.
Definition: dhcp-header.cc:88
void SetRenew(uint32_t time)
Set the Renewal time of the IPv4Address.
Definition: dhcp-header.cc:240
uint32_t GetTran() const
Get the transaction id.
Definition: dhcp-header.cc:107
void SetLease(uint32_t time)
Set the lease time of the IPv4Address.
Definition: dhcp-header.cc:223
void SetRouter(Ipv4Address addr)
Set the Ipv4Address of gateway to be used.
Definition: dhcp-header.cc:206
void SetMask(uint32_t addr)
Set the mask of the IPv4Address.
Definition: dhcp-header.cc:189
void SetRebind(uint32_t time)
Set the Rebind time of the IPv4Address.
Definition: dhcp-header.cc:257
void SetChaddr(Address addr)
Set the Address of the device.
Definition: dhcp-header.cc:119
EventId m_expiredEvent
The Event to trigger TimerHandler.
Definition: dhcp-server.h:140
void StopApplication() override
Stops the DHCP client application.
Definition: dhcp-server.cc:176
static const int PORT
Port number of DHCP server.
Definition: dhcp-server.h:71
AvailableAddress m_availableAddresses
Available addresses to be used (IP addresses)
Definition: dhcp-server.h:136
Time m_rebind
The rebinding time for an address.
Definition: dhcp-server.h:139
Time m_lease
The granted lease time for an address.
Definition: dhcp-server.h:137
Ipv4Mask m_poolMask
The network mask of the pool.
Definition: dhcp-server.h:114
Ptr< Socket > m_socket
The socket bound to port 67.
Definition: dhcp-server.h:110
ExpiredAddress m_expiredAddresses
Expired addresses to be reused (chaddr of the clients)
Definition: dhcp-server.h:135
void StartApplication() override
Starts the DHCP Server application.
Definition: dhcp-server.cc:113
void AddStaticDhcpEntry(Address chaddr, Ipv4Address addr)
Add a static entry to the pool.
Definition: dhcp-server.cc:408
LeasedAddress m_leasedAddresses
Leased address and their status (cache memory)
Definition: dhcp-server.h:134
Ipv4Address m_minAddress
The first address in the address pool.
Definition: dhcp-server.h:112
Ipv4Address m_gateway
The gateway address.
Definition: dhcp-server.h:115
static TypeId GetTypeId()
Get the type ID.
Definition: dhcp-server.cc:46
Time m_renew
The renewal time for an address.
Definition: dhcp-server.h:138
Ipv4Address m_maxAddress
The last address in the address pool.
Definition: dhcp-server.h:113
Ipv4Address m_poolAddress
The network address available to the server.
Definition: dhcp-server.h:111
~DhcpServer() override
Definition: dhcp-server.cc:100
void TimerHandler()
Modifies the remaining lease time of addresses.
Definition: dhcp-server.cc:190
void NetHandler(Ptr< Socket > socket)
Handles incoming packets from the network.
Definition: dhcp-server.cc:215
void SendAck(Ptr< NetDevice > iDev, DhcpHeader header, InetSocketAddress from)
Sends DHCP ACK (or NACK) after receiving Request.
Definition: dhcp-server.cc:344
void SendOffer(Ptr< NetDevice > iDev, DhcpHeader header, InetSocketAddress from)
Sends DHCP offer after receiving DHCP Discover.
Definition: dhcp-server.cc:250
void DoDispose() override
Destructor implementation.
Definition: dhcp-server.cc:106
std::map< Address, std::pair< Ipv4Address, uint32_t > >::iterator LeasedAddressIter
Leased address iterator - chaddr + IP addr / lease time.
Definition: dhcp-server.h:120
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
an Inet address class
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
uint32_t Get() const
Get the host-order 32-bit IP address.
static Ipv4Address GetAny()
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
uint32_t Get() const
Get the host-order 32-bit IP mask.
Definition: ipv4-address.cc:84
This class implements Linux struct pktinfo in order to deliver ancillary information to the socket in...
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.
Definition: node.cc:152
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:967
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
virtual bool SetAllowBroadcast(bool allowBroadcast)=0
Configure whether broadcast datagram transmissions are allowed.
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:354
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:327
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...
Definition: socket.cc:72
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:835
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:747
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
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...
Definition: callback.h:704
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Definition: second.py:1