A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv4-global-routing.cc
Go to the documentation of this file.
1//
2// Copyright (c) 2008 University of Washington
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License version 2 as
6// published by the Free Software Foundation;
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16//
17
18#include "ipv4-global-routing.h"
19
21#include "ipv4-route.h"
23
24#include "ns3/boolean.h"
25#include "ns3/log.h"
26#include "ns3/names.h"
27#include "ns3/net-device.h"
28#include "ns3/node.h"
29#include "ns3/object.h"
30#include "ns3/packet.h"
31#include "ns3/simulator.h"
32
33#include <iomanip>
34#include <vector>
35
36namespace ns3
37{
38
39NS_LOG_COMPONENT_DEFINE("Ipv4GlobalRouting");
40
41NS_OBJECT_ENSURE_REGISTERED(Ipv4GlobalRouting);
42
43TypeId
45{
46 static TypeId tid =
47 TypeId("ns3::Ipv4GlobalRouting")
49 .SetGroupName("Internet")
50 .AddAttribute("RandomEcmpRouting",
51 "Set to true if packets are randomly routed among ECMP; set to false for "
52 "using only one route consistently",
53 BooleanValue(false),
56 .AddAttribute("RespondToInterfaceEvents",
57 "Set to true if you want to dynamically recompute the global routes upon "
58 "Interface notification events (up/down, or add/remove address)",
59 BooleanValue(false),
62 return tid;
63}
64
66 : m_randomEcmpRouting(false),
67 m_respondToInterfaceEvents(false)
68{
69 NS_LOG_FUNCTION(this);
70
71 m_rand = CreateObject<UniformRandomVariable>();
72}
73
75{
76 NS_LOG_FUNCTION(this);
77}
78
79void
81{
82 NS_LOG_FUNCTION(this << dest << nextHop << interface);
84 *route = Ipv4RoutingTableEntry::CreateHostRouteTo(dest, nextHop, interface);
85 m_hostRoutes.push_back(route);
86}
87
88void
90{
91 NS_LOG_FUNCTION(this << dest << interface);
93 *route = Ipv4RoutingTableEntry::CreateHostRouteTo(dest, interface);
94 m_hostRoutes.push_back(route);
95}
96
97void
99 Ipv4Mask networkMask,
100 Ipv4Address nextHop,
101 uint32_t interface)
102{
103 NS_LOG_FUNCTION(this << network << networkMask << nextHop << interface);
105 *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, nextHop, interface);
106 m_networkRoutes.push_back(route);
107}
108
109void
111{
112 NS_LOG_FUNCTION(this << network << networkMask << interface);
114 *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, interface);
115 m_networkRoutes.push_back(route);
116}
117
118void
120 Ipv4Mask networkMask,
121 Ipv4Address nextHop,
122 uint32_t interface)
123{
124 NS_LOG_FUNCTION(this << network << networkMask << nextHop << interface);
126 *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, nextHop, interface);
127 m_ASexternalRoutes.push_back(route);
128}
129
132{
133 NS_LOG_FUNCTION(this << dest << oif);
134 NS_LOG_LOGIC("Looking for route for destination " << dest);
135 Ptr<Ipv4Route> rtentry = nullptr;
136 // store all available routes that bring packets to their destination
137 typedef std::vector<Ipv4RoutingTableEntry*> RouteVec_t;
138 RouteVec_t allRoutes;
139
140 NS_LOG_LOGIC("Number of m_hostRoutes = " << m_hostRoutes.size());
141 for (HostRoutesCI i = m_hostRoutes.begin(); i != m_hostRoutes.end(); i++)
142 {
143 NS_ASSERT((*i)->IsHost());
144 if ((*i)->GetDest() == dest)
145 {
146 if (oif)
147 {
148 if (oif != m_ipv4->GetNetDevice((*i)->GetInterface()))
149 {
150 NS_LOG_LOGIC("Not on requested interface, skipping");
151 continue;
152 }
153 }
154 allRoutes.push_back(*i);
155 NS_LOG_LOGIC(allRoutes.size() << "Found global host route" << *i);
156 }
157 }
158 if (allRoutes.empty()) // if no host route is found
159 {
160 NS_LOG_LOGIC("Number of m_networkRoutes" << m_networkRoutes.size());
161 for (NetworkRoutesI j = m_networkRoutes.begin(); j != m_networkRoutes.end(); j++)
162 {
163 Ipv4Mask mask = (*j)->GetDestNetworkMask();
164 Ipv4Address entry = (*j)->GetDestNetwork();
165 if (mask.IsMatch(dest, entry))
166 {
167 if (oif)
168 {
169 if (oif != m_ipv4->GetNetDevice((*j)->GetInterface()))
170 {
171 NS_LOG_LOGIC("Not on requested interface, skipping");
172 continue;
173 }
174 }
175 allRoutes.push_back(*j);
176 NS_LOG_LOGIC(allRoutes.size() << "Found global network route" << *j);
177 }
178 }
179 }
180 if (allRoutes.empty()) // consider external if no host/network found
181 {
182 for (ASExternalRoutesI k = m_ASexternalRoutes.begin(); k != m_ASexternalRoutes.end(); k++)
183 {
184 Ipv4Mask mask = (*k)->GetDestNetworkMask();
185 Ipv4Address entry = (*k)->GetDestNetwork();
186 if (mask.IsMatch(dest, entry))
187 {
188 NS_LOG_LOGIC("Found external route" << *k);
189 if (oif)
190 {
191 if (oif != m_ipv4->GetNetDevice((*k)->GetInterface()))
192 {
193 NS_LOG_LOGIC("Not on requested interface, skipping");
194 continue;
195 }
196 }
197 allRoutes.push_back(*k);
198 break;
199 }
200 }
201 }
202 if (!allRoutes.empty()) // if route(s) is found
203 {
204 // pick up one of the routes uniformly at random if random
205 // ECMP routing is enabled, or always select the first route
206 // consistently if random ECMP routing is disabled
207 uint32_t selectIndex;
209 {
210 selectIndex = m_rand->GetInteger(0, allRoutes.size() - 1);
211 }
212 else
213 {
214 selectIndex = 0;
215 }
216 Ipv4RoutingTableEntry* route = allRoutes.at(selectIndex);
217 // create a Ipv4Route object from the selected routing table entry
218 rtentry = Create<Ipv4Route>();
219 rtentry->SetDestination(route->GetDest());
221 rtentry->SetSource(m_ipv4->GetAddress(route->GetInterface(), 0).GetLocal());
222 rtentry->SetGateway(route->GetGateway());
223 uint32_t interfaceIdx = route->GetInterface();
224 rtentry->SetOutputDevice(m_ipv4->GetNetDevice(interfaceIdx));
225 return rtentry;
226 }
227 else
228 {
229 return nullptr;
230 }
231}
232
235{
236 NS_LOG_FUNCTION(this);
237 uint32_t n = 0;
238 n += m_hostRoutes.size();
239 n += m_networkRoutes.size();
240 n += m_ASexternalRoutes.size();
241 return n;
242}
243
246{
247 NS_LOG_FUNCTION(this << index);
248 if (index < m_hostRoutes.size())
249 {
250 uint32_t tmp = 0;
251 for (HostRoutesCI i = m_hostRoutes.begin(); i != m_hostRoutes.end(); i++)
252 {
253 if (tmp == index)
254 {
255 return *i;
256 }
257 tmp++;
258 }
259 }
260 index -= m_hostRoutes.size();
261 uint32_t tmp = 0;
262 if (index < m_networkRoutes.size())
263 {
264 for (NetworkRoutesCI j = m_networkRoutes.begin(); j != m_networkRoutes.end(); j++)
265 {
266 if (tmp == index)
267 {
268 return *j;
269 }
270 tmp++;
271 }
272 }
273 index -= m_networkRoutes.size();
274 tmp = 0;
275 for (ASExternalRoutesCI k = m_ASexternalRoutes.begin(); k != m_ASexternalRoutes.end(); k++)
276 {
277 if (tmp == index)
278 {
279 return *k;
280 }
281 tmp++;
282 }
283 NS_ASSERT(false);
284 // quiet compiler.
285 return nullptr;
286}
287
288void
290{
291 NS_LOG_FUNCTION(this << index);
292 if (index < m_hostRoutes.size())
293 {
294 uint32_t tmp = 0;
295 for (HostRoutesI i = m_hostRoutes.begin(); i != m_hostRoutes.end(); i++)
296 {
297 if (tmp == index)
298 {
299 NS_LOG_LOGIC("Removing route " << index << "; size = " << m_hostRoutes.size());
300 delete *i;
301 m_hostRoutes.erase(i);
302 NS_LOG_LOGIC("Done removing host route "
303 << index << "; host route remaining size = " << m_hostRoutes.size());
304 return;
305 }
306 tmp++;
307 }
308 }
309 index -= m_hostRoutes.size();
310 uint32_t tmp = 0;
311 for (NetworkRoutesI j = m_networkRoutes.begin(); j != m_networkRoutes.end(); j++)
312 {
313 if (tmp == index)
314 {
315 NS_LOG_LOGIC("Removing route " << index << "; size = " << m_networkRoutes.size());
316 delete *j;
317 m_networkRoutes.erase(j);
318 NS_LOG_LOGIC("Done removing network route "
319 << index << "; network route remaining size = " << m_networkRoutes.size());
320 return;
321 }
322 tmp++;
323 }
324 index -= m_networkRoutes.size();
325 tmp = 0;
326 for (ASExternalRoutesI k = m_ASexternalRoutes.begin(); k != m_ASexternalRoutes.end(); k++)
327 {
328 if (tmp == index)
329 {
330 NS_LOG_LOGIC("Removing route " << index << "; size = " << m_ASexternalRoutes.size());
331 delete *k;
332 m_ASexternalRoutes.erase(k);
333 NS_LOG_LOGIC("Done removing network route "
334 << index << "; network route remaining size = " << m_networkRoutes.size());
335 return;
336 }
337 tmp++;
338 }
339 NS_ASSERT(false);
340}
341
342int64_t
344{
345 NS_LOG_FUNCTION(this << stream);
346 m_rand->SetStream(stream);
347 return 1;
348}
349
350void
352{
353 NS_LOG_FUNCTION(this);
354 for (HostRoutesI i = m_hostRoutes.begin(); i != m_hostRoutes.end(); i = m_hostRoutes.erase(i))
355 {
356 delete (*i);
357 }
358 for (NetworkRoutesI j = m_networkRoutes.begin(); j != m_networkRoutes.end();
359 j = m_networkRoutes.erase(j))
360 {
361 delete (*j);
362 }
363 for (ASExternalRoutesI l = m_ASexternalRoutes.begin(); l != m_ASexternalRoutes.end();
364 l = m_ASexternalRoutes.erase(l))
365 {
366 delete (*l);
367 }
368
370}
371
372// Formatted like output of "route -n" command
373void
375{
376 NS_LOG_FUNCTION(this << stream);
377 std::ostream* os = stream->GetStream();
378 // Copy the current ostream state
379 std::ios oldState(nullptr);
380 oldState.copyfmt(*os);
381
382 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
383
384 *os << "Node: " << m_ipv4->GetObject<Node>()->GetId() << ", Time: " << Now().As(unit)
385 << ", Local time: " << m_ipv4->GetObject<Node>()->GetLocalTime().As(unit)
386 << ", Ipv4GlobalRouting table" << std::endl;
387
388 if (GetNRoutes() > 0)
389 {
390 *os << "Destination Gateway Genmask Flags Metric Ref Use Iface"
391 << std::endl;
392 for (uint32_t j = 0; j < GetNRoutes(); j++)
393 {
394 std::ostringstream dest;
395 std::ostringstream gw;
396 std::ostringstream mask;
397 std::ostringstream flags;
399 dest << route.GetDest();
400 *os << std::setw(16) << dest.str();
401 gw << route.GetGateway();
402 *os << std::setw(16) << gw.str();
403 mask << route.GetDestNetworkMask();
404 *os << std::setw(16) << mask.str();
405 flags << "U";
406 if (route.IsHost())
407 {
408 flags << "H";
409 }
410 else if (route.IsGateway())
411 {
412 flags << "G";
413 }
414 *os << std::setw(6) << flags.str();
415 // Metric not implemented
416 *os << "-"
417 << " ";
418 // Ref ct not implemented
419 *os << "-"
420 << " ";
421 // Use not implemented
422 *os << "-"
423 << " ";
424 if (!Names::FindName(m_ipv4->GetNetDevice(route.GetInterface())).empty())
425 {
426 *os << Names::FindName(m_ipv4->GetNetDevice(route.GetInterface()));
427 }
428 else
429 {
430 *os << route.GetInterface();
431 }
432 *os << std::endl;
433 }
434 }
435 *os << std::endl;
436 // Restore the previous ostream state
437 (*os).copyfmt(oldState);
438}
439
442 const Ipv4Header& header,
443 Ptr<NetDevice> oif,
444 Socket::SocketErrno& sockerr)
445{
446 NS_LOG_FUNCTION(this << p << &header << oif << &sockerr);
447 //
448 // First, see if this is a multicast packet we have a route for. If we
449 // have a route, then send the packet down each of the specified interfaces.
450 //
451 if (header.GetDestination().IsMulticast())
452 {
453 NS_LOG_LOGIC("Multicast destination-- returning false");
454 return nullptr; // Let other routing protocols try to handle this
455 }
456 //
457 // See if this is a unicast packet we have a route for.
458 //
459 NS_LOG_LOGIC("Unicast destination- looking up");
460 Ptr<Ipv4Route> rtentry = LookupGlobal(header.GetDestination(), oif);
461 if (rtentry)
462 {
463 sockerr = Socket::ERROR_NOTERROR;
464 }
465 else
466 {
468 }
469 return rtentry;
470}
471
472bool
474 const Ipv4Header& header,
476 const UnicastForwardCallback& ucb,
477 const MulticastForwardCallback& mcb,
478 const LocalDeliverCallback& lcb,
479 const ErrorCallback& ecb)
480{
481 NS_LOG_FUNCTION(this << p << header << header.GetSource() << header.GetDestination() << idev
482 << &lcb << &ecb);
483 // Check if input device supports IP
484 NS_ASSERT(m_ipv4->GetInterfaceForDevice(idev) >= 0);
485 uint32_t iif = m_ipv4->GetInterfaceForDevice(idev);
486
487 if (m_ipv4->IsDestinationAddress(header.GetDestination(), iif))
488 {
489 if (!lcb.IsNull())
490 {
491 NS_LOG_LOGIC("Local delivery to " << header.GetDestination());
492 lcb(p, header, iif);
493 return true;
494 }
495 else
496 {
497 // The local delivery callback is null. This may be a multicast
498 // or broadcast packet, so return false so that another
499 // multicast routing protocol can handle it. It should be possible
500 // to extend this to explicitly check whether it is a unicast
501 // packet, and invoke the error callback if so
502 return false;
503 }
504 }
505
506 // Check if input device supports IP forwarding
507 if (!m_ipv4->IsForwarding(iif))
508 {
509 NS_LOG_LOGIC("Forwarding disabled for this interface");
510 ecb(p, header, Socket::ERROR_NOROUTETOHOST);
511 return true;
512 }
513 // Next, try to find a route
514 NS_LOG_LOGIC("Unicast destination- looking up global route");
515 Ptr<Ipv4Route> rtentry = LookupGlobal(header.GetDestination());
516 if (rtentry)
517 {
518 NS_LOG_LOGIC("Found unicast destination- calling unicast callback");
519 ucb(rtentry, p, header);
520 return true;
521 }
522 else
523 {
524 NS_LOG_LOGIC("Did not find unicast destination- returning false");
525 return false; // Let other routing protocols try to handle this
526 // route request.
527 }
528}
529
530void
532{
533 NS_LOG_FUNCTION(this << i);
534 if (m_respondToInterfaceEvents && Simulator::Now().GetSeconds() > 0) // avoid startup events
535 {
539 }
540}
541
542void
544{
545 NS_LOG_FUNCTION(this << i);
546 if (m_respondToInterfaceEvents && Simulator::Now().GetSeconds() > 0) // avoid startup events
547 {
551 }
552}
553
554void
556{
557 NS_LOG_FUNCTION(this << interface << address);
558 if (m_respondToInterfaceEvents && Simulator::Now().GetSeconds() > 0) // avoid startup events
559 {
563 }
564}
565
566void
568{
569 NS_LOG_FUNCTION(this << interface << address);
570 if (m_respondToInterfaceEvents && Simulator::Now().GetSeconds() > 0) // avoid startup events
571 {
575 }
576}
577
578void
580{
581 NS_LOG_FUNCTION(this << ipv4);
582 NS_ASSERT(!m_ipv4 && ipv4);
583 m_ipv4 = ipv4;
584}
585
586} // namespace ns3
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsNull() const
Check for null implementation.
Definition: callback.h:567
static void DeleteGlobalRoutes()
Delete all static routes on all nodes that have a GlobalRouterInterface.
static void InitializeRoutes()
Compute routes using a Dijkstra SPF computation and populate per-node forwarding tables.
static void BuildGlobalRoutingDatabase()
Build the routing database by gathering Link State Advertisements from each node exporting a GlobalRo...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
bool IsMulticast() const
void AddHostRouteTo(Ipv4Address dest, Ipv4Address nextHop, uint32_t interface)
Add a host route to the global routing table.
std::list< Ipv4RoutingTableEntry * >::iterator HostRoutesI
iterator of container of Ipv4RoutingTableEntry (routes to hosts)
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb) override
Route an input packet (to be forwarded or locally delivered)
void AddASExternalRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
Add an external route to the global routing table.
Ipv4RoutingTableEntry * GetRoute(uint32_t i) const
Get a route from the global unicast routing table.
static TypeId GetTypeId()
Get the type ID.
void DoDispose() override
Destructor implementation.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< UniformRandomVariable > m_rand
A uniform random number generator for randomly routing packets among ECMP.
void RemoveRoute(uint32_t i)
Remove a route from the global unicast routing table.
void NotifyInterfaceDown(uint32_t interface) override
void NotifyInterfaceUp(uint32_t interface) override
void SetIpv4(Ptr< Ipv4 > ipv4) override
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
uint32_t GetNRoutes() const
Get the number of individual unicast routes that have been added to the routing table.
std::list< Ipv4RoutingTableEntry * >::iterator ASExternalRoutesI
iterator of container of Ipv4RoutingTableEntry (routes to external AS)
Ipv4GlobalRouting()
Construct an empty Ipv4GlobalRouting routing protocol,.
std::list< Ipv4RoutingTableEntry * >::const_iterator NetworkRoutesCI
const iterator of container of Ipv4RoutingTableEntry (routes to networks)
Ptr< Ipv4 > m_ipv4
associated IPv4 instance
Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr) override
Query routing cache for an existing route, for an outbound packet.
void AddNetworkRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
Add a network route to the global routing table.
std::list< Ipv4RoutingTableEntry * >::const_iterator HostRoutesCI
const iterator of container of Ipv4RoutingTableEntry (routes to hosts)
void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address) override
std::list< Ipv4RoutingTableEntry * >::iterator NetworkRoutesI
iterator of container of Ipv4RoutingTableEntry (routes to networks)
ASExternalRoutes m_ASexternalRoutes
External routes imported.
HostRoutes m_hostRoutes
Routes to hosts.
bool m_respondToInterfaceEvents
Set to true if this interface should respond to interface events by globallly recomputing routes.
void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address) override
bool m_randomEcmpRouting
Set to true if packets are randomly routed among ECMP; set to false for using only one route consiste...
NetworkRoutes m_networkRoutes
Routes to networks.
std::list< Ipv4RoutingTableEntry * >::const_iterator ASExternalRoutesCI
const iterator of container of Ipv4RoutingTableEntry (routes to external AS)
Ptr< Ipv4Route > LookupGlobal(Ipv4Address dest, Ptr< NetDevice > oif=nullptr)
Lookup in the forwarding table for destination.
Packet header for IPv4.
Definition: ipv4-header.h:34
Ipv4Address GetSource() const
Definition: ipv4-header.cc:302
Ipv4Address GetDestination() const
Definition: ipv4-header.cc:316
a class to store IPv4 address information on an interface
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
bool IsMatch(Ipv4Address a, Ipv4Address b) const
Definition: ipv4-address.cc:77
A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting.
Ipv4Address GetDest() const
Ipv4Address GetGateway() const
bool IsHost() const
bool IsGateway() const
uint32_t GetInterface() const
static Ipv4RoutingTableEntry CreateNetworkRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
static Ipv4RoutingTableEntry CreateHostRouteTo(Ipv4Address dest, Ipv4Address nextHop, uint32_t interface)
Ipv4Mask GetDestNetworkMask() const
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:830
A network Node.
Definition: node.h:56
A base class which provides memory management and object aggregation.
Definition: object.h:89
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
@ ERROR_NOROUTETOHOST
Definition: socket.h:95
@ ERROR_NOTERROR
Definition: socket.h:85
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:111
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
#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_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Every class exported by the ns3 library is enclosed in the ns3 namespace.