A Discrete-Event Network Simulator
API
arp-cache.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2006 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20#include "ns3/assert.h"
21#include "ns3/packet.h"
22#include "ns3/simulator.h"
23#include "ns3/uinteger.h"
24#include "ns3/log.h"
25#include "ns3/node.h"
26#include "ns3/trace-source-accessor.h"
27#include "ns3/names.h"
28
29#include "arp-cache.h"
30#include "arp-header.h"
31#include "ipv4-interface.h"
32#include "ipv4-header.h"
33
34namespace ns3 {
35
36NS_LOG_COMPONENT_DEFINE ("ArpCache");
37
39
40TypeId
42{
43 static TypeId tid = TypeId ("ns3::ArpCache")
44 .SetParent<Object> ()
45 .SetGroupName ("Internet")
46 .AddAttribute ("AliveTimeout",
47 "When this timeout expires, "
48 "the matching cache entry needs refreshing",
49 TimeValue (Seconds (120)),
52 .AddAttribute ("DeadTimeout",
53 "When this timeout expires, "
54 "a new attempt to resolve the matching entry is made",
55 TimeValue (Seconds (100)),
58 .AddAttribute ("WaitReplyTimeout",
59 "When this timeout expires, "
60 "the cache entries will be scanned and "
61 "entries in WaitReply state will resend ArpRequest "
62 "unless MaxRetries has been exceeded, "
63 "in which case the entry is marked dead",
64 TimeValue (Seconds (1)),
67 .AddAttribute ("MaxRetries",
68 "Number of retransmissions of ArpRequest "
69 "before marking dead",
70 UintegerValue (3),
72 MakeUintegerChecker<uint32_t> ())
73 .AddAttribute ("PendingQueueSize",
74 "The size of the queue for packets pending an arp reply.",
75 UintegerValue (3),
77 MakeUintegerChecker<uint32_t> ())
78 .AddTraceSource ("Drop",
79 "Packet dropped due to ArpCache entry "
80 "in WaitReply expiring.",
82 "ns3::Packet::TracedCallback")
83 ;
84 return tid;
85}
86
88 : m_device (0),
89 m_interface (0)
90{
91 NS_LOG_FUNCTION (this);
92}
93
95{
96 NS_LOG_FUNCTION (this);
97}
98
99void
101{
102 NS_LOG_FUNCTION (this);
103 Flush ();
104 m_device = 0;
105 m_interface = 0;
107 {
109 }
111}
112
113void
115{
116 NS_LOG_FUNCTION (this << device << interface);
117 m_device = device;
118 m_interface = interface;
119}
120
123{
124 NS_LOG_FUNCTION (this);
125 return m_device;
126}
127
130{
131 NS_LOG_FUNCTION (this);
132 return m_interface;
133}
134
135void
137{
138 NS_LOG_FUNCTION (this << aliveTimeout);
139 m_aliveTimeout = aliveTimeout;
140}
141void
143{
144 NS_LOG_FUNCTION (this << deadTimeout);
145 m_deadTimeout = deadTimeout;
146}
147void
149{
150 NS_LOG_FUNCTION (this << waitReplyTimeout);
151 m_waitReplyTimeout = waitReplyTimeout;
152}
153
154Time
156{
157 NS_LOG_FUNCTION (this);
158 return m_aliveTimeout;
159}
160Time
162{
163 NS_LOG_FUNCTION (this);
164 return m_deadTimeout;
165}
166Time
168{
169 NS_LOG_FUNCTION (this);
170 return m_waitReplyTimeout;
171}
172
173void
175 Ipv4Address> arpRequestCallback)
176{
177 NS_LOG_FUNCTION (this << &arpRequestCallback);
178 m_arpRequestCallback = arpRequestCallback;
179}
180
181void
183{
184 NS_LOG_FUNCTION (this);
186 {
187 NS_LOG_LOGIC ("Starting WaitReplyTimer at " << Simulator::Now () << " for " <<
191 }
192}
193
194void
196{
197 NS_LOG_FUNCTION (this);
198 ArpCache::Entry* entry;
199 bool restartWaitReplyTimer = false;
200 for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
201 {
202 entry = (*i).second;
203 if (entry != 0 && entry->IsWaitReply ())
204 {
205 if (entry->GetRetries () < m_maxRetries)
206 {
207 NS_LOG_LOGIC ("node="<< m_device->GetNode ()->GetId () <<
208 ", ArpWaitTimeout for " << entry->GetIpv4Address () <<
209 " expired -- retransmitting arp request since retries = " <<
210 entry->GetRetries ());
211 m_arpRequestCallback (this, entry->GetIpv4Address ());
212 restartWaitReplyTimer = true;
213 entry->IncrementRetries ();
214 }
215 else
216 {
217 NS_LOG_LOGIC ("node="<< m_device->GetNode ()->GetId () <<
218 ", wait reply for " << entry->GetIpv4Address () <<
219 " expired -- drop since max retries exceeded: " <<
220 entry->GetRetries ());
221 entry->MarkDead ();
222 entry->ClearRetries ();
223 Ipv4PayloadHeaderPair pending = entry->DequeuePending ();
224 while (pending.first)
225 {
226 // add the Ipv4 header for tracing purposes
227 pending.first->AddHeader (pending.second);
228 m_dropTrace (pending.first);
229 pending = entry->DequeuePending ();
230 }
231 }
232 }
233
234 }
235 if (restartWaitReplyTimer)
236 {
237 NS_LOG_LOGIC ("Restarting WaitReplyTimer at " << Simulator::Now ().GetSeconds ());
240 }
241}
242
243void
245{
246 NS_LOG_FUNCTION (this);
247 for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
248 {
249 delete (*i).second;
250 }
251 m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ());
253 {
254 NS_LOG_LOGIC ("Stopping WaitReplyTimer at " << Simulator::Now ().GetSeconds () << " due to ArpCache flush");
256 }
257}
258
259void
261{
262 NS_LOG_FUNCTION (this << stream);
263 std::ostream* os = stream->GetStream ();
264
265 for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
266 {
267 *os << i->first << " dev ";
268 std::string found = Names::FindName (m_device);
269 if (Names::FindName (m_device) != "")
270 {
271 *os << found;
272 }
273 else
274 {
275 *os << static_cast<int> (m_device->GetIfIndex ());
276 }
277
278 *os << " lladdr " << i->second->GetMacAddress ();
279
280 if (i->second->IsAlive ())
281 {
282 *os << " REACHABLE\n";
283 }
284 else if (i->second->IsWaitReply ())
285 {
286 *os << " DELAY\n";
287 }
288 else if (i->second->IsPermanent ())
289 {
290 *os << " PERMANENT\n";
291 }
292 else if (i->second->IsAutoGenerated ())
293 {
294 *os << " STATIC_AUTOGENERATED\n";
295 }
296 else
297 {
298 *os << " STALE\n";
299 }
300 }
301}
302
303void
305{
306 NS_LOG_FUNCTION (this);
307 for (CacheI i = m_arpCache.begin (); i != m_arpCache.end ();)
308 {
309 if (i->second->IsAutoGenerated ())
310 {
311 i->second->ClearPendingPacket (); //clear the pending packets for entry's ipaddress
312 delete i->second;
313 m_arpCache.erase (i++);
314 continue;
315 }
316 i++;
317 }
318}
319
320std::list<ArpCache::Entry *>
322{
323 NS_LOG_FUNCTION (this << to);
324
325 std::list<ArpCache::Entry *> entryList;
326 for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
327 {
328 ArpCache::Entry *entry = (*i).second;
329 if (entry->GetMacAddress () == to)
330 {
331 entryList.push_back (entry);
332 }
333 }
334 return entryList;
335}
336
337
340{
341 NS_LOG_FUNCTION (this << to);
342 CacheI it = m_arpCache.find (to);
343 if (it != m_arpCache.end ())
344 {
345 return it->second;
346 }
347 return 0;
348}
349
352{
353 NS_LOG_FUNCTION (this << to);
354 NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());
355
356 ArpCache::Entry *entry = new ArpCache::Entry (this);
357 m_arpCache[to] = entry;
358 entry->SetIpv4Address (to);
359 return entry;
360}
361
362void
364{
365 NS_LOG_FUNCTION (this << entry);
366
367 for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
368 {
369 if ((*i).second == entry)
370 {
371 m_arpCache.erase (i);
372 entry->ClearPendingPacket (); //clear the pending packets for entry's ipaddress
373 delete entry;
374 return;
375 }
376 }
377 NS_LOG_WARN ("Entry not found in this ARP Cache");
378}
379
381 : m_arp (arp),
382 m_state (ALIVE),
383 m_retries (0)
384{
385 NS_LOG_FUNCTION (this << arp);
386}
387
388
389bool
391{
392 NS_LOG_FUNCTION (this);
393 return (m_state == DEAD);
394}
395bool
397{
398 NS_LOG_FUNCTION (this);
399 return (m_state == ALIVE);
400}
401bool
403{
404 NS_LOG_FUNCTION (this);
405 return (m_state == WAIT_REPLY);
406}
407bool
409{
410 NS_LOG_FUNCTION (this);
411 return (m_state == PERMANENT);
412}
413bool
415{
416 NS_LOG_FUNCTION (this);
417 return (m_state == STATIC_AUTOGENERATED);
418}
419
420
421void
423{
424 NS_LOG_FUNCTION (this);
425 NS_ASSERT (m_state == ALIVE || m_state == WAIT_REPLY || m_state == DEAD);
426 m_state = DEAD;
427 ClearRetries ();
428 UpdateSeen ();
429}
430void
432{
433 NS_LOG_FUNCTION (this << macAddress);
434 NS_ASSERT (m_state == WAIT_REPLY);
435 m_macAddress = macAddress;
436 m_state = ALIVE;
437 ClearRetries ();
438 UpdateSeen ();
439}
440void
442{
443 NS_LOG_FUNCTION (this << m_macAddress);
444 NS_ASSERT (!m_macAddress.IsInvalid ());
445
446 m_state = PERMANENT;
447 ClearRetries ();
448 UpdateSeen ();
449}
450void
452{
453 NS_LOG_FUNCTION (this << m_macAddress);
454 NS_ASSERT (!m_macAddress.IsInvalid ());
455
456 m_state = STATIC_AUTOGENERATED;
457 ClearRetries ();
458 UpdateSeen ();
459}
460bool
462{
463 NS_LOG_FUNCTION (this << waiting.first);
464 NS_ASSERT (m_state == WAIT_REPLY);
465 /* We are already waiting for an answer so
466 * we dump the previously waiting packet and
467 * replace it with this one.
468 */
469 if (m_pending.size () >= m_arp->m_pendingQueueSize)
470 {
471 return false;
472 }
473 m_pending.push_back (waiting);
474 return true;
475}
476void
478{
479 NS_LOG_FUNCTION (this << waiting.first);
480 NS_ASSERT (m_state == ALIVE || m_state == DEAD);
481 NS_ASSERT (m_pending.empty ());
482 NS_ASSERT_MSG (waiting.first, "Can not add a null packet to the ARP queue");
483
484 m_state = WAIT_REPLY;
485 m_pending.push_back (waiting);
486 UpdateSeen ();
487 m_arp->StartWaitReplyTimer ();
488}
489
492{
493 NS_LOG_FUNCTION (this);
494 return m_macAddress;
495}
496void
498{
499 NS_LOG_FUNCTION (this);
500 m_macAddress = macAddress;
501}
504{
505 NS_LOG_FUNCTION (this);
506 return m_ipv4Address;
507}
508void
510{
511 NS_LOG_FUNCTION (this << destination);
512 m_ipv4Address = destination;
513}
514Time
516{
517 NS_LOG_FUNCTION (this);
518 switch (m_state)
519 {
521 return m_arp->GetWaitReplyTimeout ();
523 return m_arp->GetDeadTimeout ();
525 return m_arp->GetAliveTimeout ();
527 return Time::Max ();
529 return Time::Max ();
530 }
531 return Time (); // Silence compiler warning
532}
533bool
535{
536 NS_LOG_FUNCTION (this);
537 Time timeout = GetTimeout ();
538 Time delta = Simulator::Now () - m_lastSeen;
539 NS_LOG_DEBUG ("delta=" << delta.GetSeconds () << "s");
540 if (delta > timeout)
541 {
542 return true;
543 }
544 return false;
545}
548{
549 NS_LOG_FUNCTION (this);
550 if (m_pending.empty ())
551 {
552 Ipv4Header h;
553 return Ipv4PayloadHeaderPair (0, h);
554 }
555 else
556 {
557 Ipv4PayloadHeaderPair p = m_pending.front ();
558 m_pending.pop_front ();
559 return p;
560 }
561}
562void
564{
565 NS_LOG_FUNCTION (this);
566 m_pending.clear ();
567}
568void
570{
571 NS_LOG_FUNCTION (this);
572 m_lastSeen = Simulator::Now ();
573}
576{
577 NS_LOG_FUNCTION (this);
578 return m_retries;
579}
580void
582{
583 NS_LOG_FUNCTION (this);
584 m_retries++;
585 UpdateSeen ();
586}
587void
589{
590 NS_LOG_FUNCTION (this);
591 m_retries = 0;
592}
593
594} // namespace ns3
595
a polymophic address class
Definition: address.h:91
A record that that holds information about an ArpCache entry.
Definition: arp-cache.h:183
void SetIpv4Address(Ipv4Address destination)
Definition: arp-cache.cc:509
void ClearRetries(void)
Zero the counter of number of retries for an entry.
Definition: arp-cache.cc:588
bool UpdateWaitReply(Ipv4PayloadHeaderPair waiting)
Definition: arp-cache.cc:461
void MarkAutoGenerated(void)
Changes the state of this entry to auto-generated.
Definition: arp-cache.cc:451
Time GetTimeout(void) const
Returns the entry timeout.
Definition: arp-cache.cc:515
bool IsAlive(void)
Definition: arp-cache.cc:396
Ipv4PayloadHeaderPair DequeuePending(void)
Definition: arp-cache.cc:547
void MarkPermanent(void)
Changes the state of this entry to Permanent.
Definition: arp-cache.cc:441
bool IsWaitReply(void)
Definition: arp-cache.cc:402
bool IsAutoGenerated(void)
Definition: arp-cache.cc:414
void ClearPendingPacket(void)
Clear the pending packet list.
Definition: arp-cache.cc:563
bool IsDead(void)
Definition: arp-cache.cc:390
@ WAIT_REPLY
Definition: arp-cache.h:298
@ ALIVE
Definition: arp-cache.h:297
@ STATIC_AUTOGENERATED
Definition: arp-cache.h:301
@ PERMANENT
Definition: arp-cache.h:300
@ DEAD
Definition: arp-cache.h:299
bool IsPermanent(void)
Definition: arp-cache.cc:408
void MarkDead(void)
Changes the state of this entry to dead.
Definition: arp-cache.cc:422
void IncrementRetries(void)
Increment the counter of number of retries for an entry.
Definition: arp-cache.cc:581
void MarkAlive(Address macAddress)
Definition: arp-cache.cc:431
void SetMacAddress(Address macAddress)
Definition: arp-cache.cc:497
Ipv4Address GetIpv4Address(void) const
Definition: arp-cache.cc:503
void MarkWaitReply(Ipv4PayloadHeaderPair waiting)
Definition: arp-cache.cc:477
void UpdateSeen(void)
Update the entry when seeing a packet.
Definition: arp-cache.cc:569
uint32_t GetRetries(void) const
Definition: arp-cache.cc:575
Address GetMacAddress(void) const
Definition: arp-cache.cc:491
bool IsExpired(void) const
Definition: arp-cache.cc:534
Entry(ArpCache *arp)
Constructor.
Definition: arp-cache.cc:380
An ARP cache.
Definition: arp-cache.h:52
void Remove(ArpCache::Entry *entry)
Remove an entry.
Definition: arp-cache.cc:363
void SetWaitReplyTimeout(Time waitReplyTimeout)
Set the time the entry will be in WAIT_REPLY state.
Definition: arp-cache.cc:148
uint32_t m_maxRetries
max retries for a resolution
Definition: arp-cache.h:338
EventId m_waitReplyTimer
cache alive state timer
Definition: arp-cache.h:336
Time m_aliveTimeout
cache alive state timeout
Definition: arp-cache.h:333
void SetArpRequestCallback(Callback< void, Ptr< const ArpCache >, Ipv4Address > arpRequestCallback)
This callback is set when the ArpCache is set up and allows the cache to generate an Arp request when...
Definition: arp-cache.cc:174
Time m_deadTimeout
cache dead state timeout
Definition: arp-cache.h:334
Time m_waitReplyTimeout
cache reply state timeout
Definition: arp-cache.h:335
Ptr< Ipv4Interface > m_interface
Ipv4Interface associated with the cache.
Definition: arp-cache.h:332
void PrintArpCache(Ptr< OutputStreamWrapper > stream)
Print the ARP cache entries.
Definition: arp-cache.cc:260
void SetAliveTimeout(Time aliveTimeout)
Set the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:136
uint32_t m_pendingQueueSize
number of packets waiting for a resolution
Definition: arp-cache.h:346
Ptr< Ipv4Interface > GetInterface(void) const
Returns the Ipv4Interface that this ARP cache is associated with.
Definition: arp-cache.cc:129
Time GetAliveTimeout(void) const
Get the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:155
TracedCallback< Ptr< const Packet > > m_dropTrace
trace for packets dropped by the ARP cache queue
Definition: arp-cache.h:348
ArpCache::Entry * Add(Ipv4Address to)
Add an Ipv4Address to this ARP cache.
Definition: arp-cache.cc:351
void Flush(void)
Clear the ArpCache of all entries.
Definition: arp-cache.cc:244
virtual void DoDispose(void)
Destructor implementation.
Definition: arp-cache.cc:100
void HandleWaitReplyTimeout(void)
This function is an event handler for the event that the ArpCache wants to check whether it must retr...
Definition: arp-cache.cc:195
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv4Interface > interface)
Set the NetDevice and Ipv4Interface associated with the ArpCache.
Definition: arp-cache.cc:114
std::list< ArpCache::Entry * > LookupInverse(Address destination)
Do lookup in the ARP cache against a MAC address.
Definition: arp-cache.cc:321
Callback< void, Ptr< const ArpCache >, Ipv4Address > m_arpRequestCallback
reply timeout callback
Definition: arp-cache.h:337
Time GetDeadTimeout(void) const
Get the time the entry will be in DEAD state before being removed.
Definition: arp-cache.cc:161
std::map< Ipv4Address, ArpCache::Entry * >::iterator CacheI
ARP Cache container iterator.
Definition: arp-cache.h:327
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:339
Cache m_arpCache
the ARP cache
Definition: arp-cache.h:347
Ptr< NetDevice > GetDevice(void) const
Returns the NetDevice that this ARP cache is associated with.
Definition: arp-cache.cc:122
Ptr< NetDevice > m_device
NetDevice associated with the cache.
Definition: arp-cache.h:331
std::pair< Ptr< Packet >, Ipv4Header > Ipv4PayloadHeaderPair
Pair of a packet and an Ipv4 header.
Definition: arp-cache.h:178
void RemoveAutoGeneratedEntries(void)
Clear the ArpCache of all Auto-Generated entries.
Definition: arp-cache.cc:304
void StartWaitReplyTimer(void)
This method will schedule a timeout at WaitReplyTimeout interval in the future, unless a timer is alr...
Definition: arp-cache.cc:182
Time GetWaitReplyTimeout(void) const
Get the time the entry will be in WAIT_REPLY state.
Definition: arp-cache.cc:167
static TypeId GetTypeId(void)
Get the type ID.
Definition: arp-cache.cc:41
void SetDeadTimeout(Time deadTimeout)
Set the time the entry will be in DEAD state before being removed.
Definition: arp-cache.cc:142
Callback template class.
Definition: callback.h:422
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
Packet header for IPv4.
Definition: ipv4-header.h:34
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Definition: names.cc:817
A base class which provides memory management and object aggregation.
Definition: object.h:88
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:555
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition: nstime.h:283
AttributeValue implementation for Time.
Definition: nstime.h:1309
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:88
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1310
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:45
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:206
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:274
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:290
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:266
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1245
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:794
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:522
ns3::Time timeout