A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
udp-l4-protocol.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005 INRIA
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 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19
20#include "udp-l4-protocol.h"
21
23#include "ipv4-end-point.h"
24#include "ipv4-route.h"
25#include "ipv4.h"
27#include "ipv6-end-point.h"
28#include "ipv6-route.h"
29#include "ipv6.h"
30#include "udp-header.h"
32#include "udp-socket-impl.h"
33
34#include "ns3/assert.h"
35#include "ns3/boolean.h"
36#include "ns3/log.h"
37#include "ns3/node.h"
38#include "ns3/object-map.h"
39#include "ns3/packet.h"
40
41#include <unordered_map>
42
43namespace ns3
44{
45
46NS_LOG_COMPONENT_DEFINE("UdpL4Protocol");
47
48NS_OBJECT_ENSURE_REGISTERED(UdpL4Protocol);
49
50/* see http://www.iana.org/assignments/protocol-numbers */
51const uint8_t UdpL4Protocol::PROT_NUMBER = 17;
52
53TypeId
55{
56 static TypeId tid =
57 TypeId("ns3::UdpL4Protocol")
59 .SetGroupName("Internet")
60 .AddConstructor<UdpL4Protocol>()
61 .AddAttribute("SocketList",
62 "A container of sockets associated to this protocol. "
63 "The underlying type is an unordered map, the attribute name "
64 "is kept for backward compatibility.",
67 MakeObjectMapChecker<UdpSocketImpl>());
68 return tid;
69}
70
72 : m_endPoints(new Ipv4EndPointDemux()),
73 m_endPoints6(new Ipv6EndPointDemux())
74{
75 NS_LOG_FUNCTION(this);
76}
77
79{
80 NS_LOG_FUNCTION(this);
81}
82
83void
85{
86 m_node = node;
87}
88
89/*
90 * This method is called by AggregateObject and completes the aggregation
91 * by setting the node in the udp stack and link it to the ipv4 object
92 * present in the node along with the socket factory
93 */
94void
96{
97 NS_LOG_FUNCTION(this);
98 Ptr<Node> node = this->GetObject<Node>();
99 Ptr<Ipv4> ipv4 = this->GetObject<Ipv4>();
100 Ptr<Ipv6> ipv6 = node->GetObject<Ipv6>();
101
102 if (!m_node)
103 {
104 if (node && (ipv4 || ipv6))
105 {
106 this->SetNode(node);
107 Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl>();
108 udpFactory->SetUdp(this);
109 node->AggregateObject(udpFactory);
110 }
111 }
112
113 // We set at least one of our 2 down targets to the IPv4/IPv6 send
114 // functions. Since these functions have different prototypes, we
115 // need to keep track of whether we are connected to an IPv4 or
116 // IPv6 lower layer and call the appropriate one.
117
118 if (ipv4 && m_downTarget.IsNull())
119 {
120 ipv4->Insert(this);
122 }
123 if (ipv6 && m_downTarget6.IsNull())
124 {
125 ipv6->Insert(this);
127 }
129}
130
131int
133{
134 return PROT_NUMBER;
135}
136
137void
139{
140 NS_LOG_FUNCTION(this);
141 for (auto i = m_sockets.begin(); i != m_sockets.end(); i++)
142 {
143 i->second = nullptr;
144 }
145 m_sockets.clear();
146
147 if (m_endPoints != nullptr)
148 {
149 delete m_endPoints;
150 m_endPoints = nullptr;
151 }
152 if (m_endPoints6 != nullptr)
153 {
154 delete m_endPoints6;
155 m_endPoints6 = nullptr;
156 }
157 m_node = nullptr;
160 /*
161 = MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
162 */
164}
165
168{
169 NS_LOG_FUNCTION(this);
170 Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl>();
171 socket->SetNode(m_node);
172 socket->SetUdp(this);
173 m_sockets[m_socketIndex++] = socket;
174 return socket;
175}
176
179{
180 NS_LOG_FUNCTION(this);
181 return m_endPoints->Allocate();
182}
183
186{
187 NS_LOG_FUNCTION(this << address);
188 return m_endPoints->Allocate(address);
189}
190
193{
194 NS_LOG_FUNCTION(this << boundNetDevice << port);
195 return m_endPoints->Allocate(boundNetDevice, port);
196}
197
199UdpL4Protocol::Allocate(Ptr<NetDevice> boundNetDevice, Ipv4Address address, uint16_t port)
200{
201 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
202 return m_endPoints->Allocate(boundNetDevice, address, port);
203}
204
207 Ipv4Address localAddress,
208 uint16_t localPort,
209 Ipv4Address peerAddress,
210 uint16_t peerPort)
211{
212 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
213 return m_endPoints->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
214}
215
216void
218{
219 NS_LOG_FUNCTION(this << endPoint);
220 m_endPoints->DeAllocate(endPoint);
221}
222
225{
226 NS_LOG_FUNCTION(this);
227 return m_endPoints6->Allocate();
228}
229
232{
233 NS_LOG_FUNCTION(this << address);
234 return m_endPoints6->Allocate(address);
235}
236
239{
240 NS_LOG_FUNCTION(this << boundNetDevice << port);
241 return m_endPoints6->Allocate(boundNetDevice, port);
242}
243
245UdpL4Protocol::Allocate6(Ptr<NetDevice> boundNetDevice, Ipv6Address address, uint16_t port)
246{
247 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
248 return m_endPoints6->Allocate(boundNetDevice, address, port);
249}
250
253 Ipv6Address localAddress,
254 uint16_t localPort,
255 Ipv6Address peerAddress,
256 uint16_t peerPort)
257{
258 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
259 return m_endPoints6->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
260}
261
262void
264{
265 NS_LOG_FUNCTION(this << endPoint);
266 m_endPoints6->DeAllocate(endPoint);
267}
268
269void
271 uint8_t icmpTtl,
272 uint8_t icmpType,
273 uint8_t icmpCode,
274 uint32_t icmpInfo,
275 Ipv4Address payloadSource,
276 Ipv4Address payloadDestination,
277 const uint8_t payload[8])
278{
279 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
280 << payloadSource << payloadDestination);
281 uint16_t src;
282 uint16_t dst;
283 src = payload[0] << 8;
284 src |= payload[1];
285 dst = payload[2] << 8;
286 dst |= payload[3];
287
288 Ipv4EndPoint* endPoint = m_endPoints->SimpleLookup(payloadSource, src, payloadDestination, dst);
289 if (endPoint != nullptr)
290 {
291 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
292 }
293 else
294 {
295 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
296 << ", destination=" << payloadDestination
297 << ", src=" << src << ", dst=" << dst);
298 }
299}
300
301void
303 uint8_t icmpTtl,
304 uint8_t icmpType,
305 uint8_t icmpCode,
306 uint32_t icmpInfo,
307 Ipv6Address payloadSource,
308 Ipv6Address payloadDestination,
309 const uint8_t payload[8])
310{
311 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
312 << payloadSource << payloadDestination);
313 uint16_t src;
314 uint16_t dst;
315 src = payload[0] << 8;
316 src |= payload[1];
317 dst = payload[2] << 8;
318 dst |= payload[3];
319
320 Ipv6EndPoint* endPoint =
321 m_endPoints6->SimpleLookup(payloadSource, src, payloadDestination, dst);
322 if (endPoint != nullptr)
323 {
324 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
325 }
326 else
327 {
328 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
329 << ", destination=" << payloadDestination
330 << ", src=" << src << ", dst=" << dst);
331 }
332}
333
336{
337 NS_LOG_FUNCTION(this << packet << header);
338 UdpHeader udpHeader;
340 {
341 udpHeader.EnableChecksums();
342 }
343
344 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
345
346 // We only peek at the header for now (instead of removing it) so that it will be intact
347 // if we have to pass it to a IPv6 endpoint via:
348 //
349 // UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
350
351 packet->PeekHeader(udpHeader);
352
353 if (!udpHeader.IsChecksumOk())
354 {
355 NS_LOG_INFO("Bad checksum : dropping packet!");
357 }
358
359 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
360 << udpHeader.GetDestinationPort());
362 udpHeader.GetDestinationPort(),
363 header.GetSource(),
364 udpHeader.GetSourcePort(),
365 interface);
366 if (endPoints.empty())
367 {
368 if (this->GetObject<Ipv6>())
369 {
370 NS_LOG_LOGIC(" No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 " << this);
371 Ptr<Ipv6Interface> fakeInterface;
372 Ipv6Header ipv6Header;
375 ipv6Header.SetSource(src);
376 ipv6Header.SetDestination(dst);
377 return (this->Receive(packet, ipv6Header, fakeInterface));
378 }
379
380 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
382 }
383
384 packet->RemoveHeader(udpHeader);
385 for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin(); endPoint != endPoints.end();
386 endPoint++)
387 {
388 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
389 }
390 return IpL4Protocol::RX_OK;
391}
392
395{
396 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination());
397 UdpHeader udpHeader;
399 {
400 udpHeader.EnableChecksums();
401 }
402
403 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
404
405 packet->RemoveHeader(udpHeader);
406
407 if (!udpHeader.IsChecksumOk() && !header.GetSource().IsIpv4MappedAddress())
408 {
409 NS_LOG_INFO("Bad checksum : dropping packet!");
411 }
412
413 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
414 << udpHeader.GetDestinationPort());
416 udpHeader.GetDestinationPort(),
417 header.GetSource(),
418 udpHeader.GetSourcePort(),
419 interface);
420 if (endPoints.empty())
421 {
422 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
424 }
425 for (Ipv6EndPointDemux::EndPointsI endPoint = endPoints.begin(); endPoint != endPoints.end();
426 endPoint++)
427 {
428 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
429 }
430 return IpL4Protocol::RX_OK;
431}
432
433void
435 Ipv4Address saddr,
436 Ipv4Address daddr,
437 uint16_t sport,
438 uint16_t dport)
439{
440 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
441
442 UdpHeader udpHeader;
444 {
445 udpHeader.EnableChecksums();
446 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
447 }
448 udpHeader.SetDestinationPort(dport);
449 udpHeader.SetSourcePort(sport);
450
451 packet->AddHeader(udpHeader);
452
453 m_downTarget(packet, saddr, daddr, PROT_NUMBER, nullptr);
454}
455
456void
458 Ipv4Address saddr,
459 Ipv4Address daddr,
460 uint16_t sport,
461 uint16_t dport,
462 Ptr<Ipv4Route> route)
463{
464 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
465
466 UdpHeader udpHeader;
468 {
469 udpHeader.EnableChecksums();
470 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
471 }
472 udpHeader.SetDestinationPort(dport);
473 udpHeader.SetSourcePort(sport);
474
475 packet->AddHeader(udpHeader);
476
477 m_downTarget(packet, saddr, daddr, PROT_NUMBER, route);
478}
479
480void
482 Ipv6Address saddr,
483 Ipv6Address daddr,
484 uint16_t sport,
485 uint16_t dport)
486{
487 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
488
489 UdpHeader udpHeader;
491 {
492 udpHeader.EnableChecksums();
493 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
494 }
495 udpHeader.SetDestinationPort(dport);
496 udpHeader.SetSourcePort(sport);
497
498 packet->AddHeader(udpHeader);
499
500 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, nullptr);
501}
502
503void
505 Ipv6Address saddr,
506 Ipv6Address daddr,
507 uint16_t sport,
508 uint16_t dport,
509 Ptr<Ipv6Route> route)
510{
511 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
512
513 UdpHeader udpHeader;
515 {
516 udpHeader.EnableChecksums();
517 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
518 }
519 udpHeader.SetDestinationPort(dport);
520 udpHeader.SetSourcePort(sport);
521
522 packet->AddHeader(udpHeader);
523
524 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, route);
525}
526
527void
529{
530 NS_LOG_FUNCTION(this);
531 m_downTarget = callback;
532}
533
536{
537 return m_downTarget;
538}
539
540void
542{
543 NS_LOG_FUNCTION(this);
544 m_downTarget6 = callback;
545}
546
549{
550 return m_downTarget6;
551}
552
553bool
555{
556 NS_LOG_FUNCTION(this << socket);
557
558 for (auto& socketItem : m_sockets)
559 {
560 if (socketItem.second == socket)
561 {
562 socketItem.second = nullptr;
563 m_sockets.erase(socketItem.first);
564 return true;
565 }
566 }
567 return false;
568}
569
570} // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:573
bool IsNull() const
Check for null implementation.
Definition: callback.h:567
L4 Protocol abstract base class.
RxStatus
Rx status codes.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Demultiplexes packets to various transport layer endpoints.
std::list< Ipv4EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv4 endpoints.
Ipv4EndPoint * SimpleLookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport)
simple lookup for a match with all the parameters.
EndPoints Lookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport, Ptr< Ipv4Interface > incomingInterface)
lookup for a match with all the parameters.
void DeAllocate(Ipv4EndPoint *endPoint)
Remove a end point.
Ipv4EndPoint * Allocate()
Allocate a Ipv4EndPoint.
std::list< Ipv4EndPoint * > EndPoints
Container of the IPv4 endpoints.
A representation of an internet endpoint/connection.
void ForwardIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Forward the ICMP packet to the upper level.
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
virtual void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)=0
Describes an IPv6 address.
Definition: ipv6-address.h:49
bool IsIpv4MappedAddress() const
If the address is an IPv4-mapped address.
static Ipv6Address MakeIpv4MappedAddress(Ipv4Address addr)
Make the Ipv4-mapped IPv6 address.
Demultiplexer for end points.
EndPoints Lookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport, Ptr< Ipv6Interface > incomingInterface)
lookup for a match with all the parameters.
Ipv6EndPoint * Allocate()
Allocate a Ipv6EndPoint.
std::list< Ipv6EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv6 endpoints.
Ipv6EndPoint * SimpleLookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
Simple lookup for a four-tuple match.
void DeAllocate(Ipv6EndPoint *endPoint)
Remove a end point.
std::list< Ipv6EndPoint * > EndPoints
Container of the IPv6 endpoints.
A representation of an IPv6 endpoint/connection.
void ForwardIcmp(Ipv6Address src, uint8_t ttl, uint8_t type, uint8_t code, uint32_t info)
Forward the ICMP packet to the upper level.
Packet header for IPv6.
Definition: ipv6-header.h:35
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:118
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:106
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
virtual void Send(Ptr< Packet > packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr< Ipv6Route > route)=0
Higher-level layers call this method to send a packet down the stack to the MAC and PHY layers.
static bool ChecksumEnabled()
Definition: node.cc:290
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:332
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
Packet header for UDP packets.
Definition: udp-header.h:41
void EnableChecksums()
Enable checksum calculation for UDP.
Definition: udp-header.cc:51
uint16_t GetDestinationPort() const
Definition: udp-header.cc:75
uint16_t GetSourcePort() const
Definition: udp-header.cc:69
bool IsChecksumOk() const
Is the UDP checksum correct ?
Definition: udp-header.cc:139
void InitializeChecksum(Address source, Address destination, uint8_t protocol)
Definition: udp-header.cc:81
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:63
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:57
Implementation of the UDP protocol.
void SetDownTarget6(IpL4Protocol::DownTargetCallback6 cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv6 ca...
Ptr< Socket > CreateSocket()
void Send(Ptr< Packet > packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport, uint16_t dport)
Send a packet via UDP (IPv4)
Ipv6EndPoint * Allocate6()
Allocate an IPv6 Endpoint.
void SetDownTarget(IpL4Protocol::DownTargetCallback cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv4 ca...
std::unordered_map< uint64_t, Ptr< UdpSocketImpl > > m_sockets
Unordered map of socket IDs and corresponding sockets.
~UdpL4Protocol() override
Ipv6EndPointDemux * m_endPoints6
A list of IPv6 end points.
int GetProtocolNumber() const override
Returns the protocol number of this protocol.
Ptr< Node > m_node
The node this stack is associated with.
Ipv4EndPointDemux * m_endPoints
A list of IPv4 end points.
void ReceiveIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, Ipv4Address payloadSource, Ipv4Address payloadDestination, const uint8_t payload[8]) override
Called from lower-level layers to send the ICMP packet up in the stack.
void SetNode(Ptr< Node > node)
Set node associated with this stack.
IpL4Protocol::DownTargetCallback GetDownTarget() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv4 ca...
static TypeId GetTypeId()
Get the type ID.
IpL4Protocol::DownTargetCallback6 GetDownTarget6() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv6 ca...
Ipv4EndPoint * Allocate()
Allocate an IPv4 Endpoint.
IpL4Protocol::RxStatus Receive(Ptr< Packet > p, const Ipv4Header &header, Ptr< Ipv4Interface > interface) override
Called from lower-level layers to send the packet up in the stack.
bool RemoveSocket(Ptr< UdpSocketImpl > socket)
Remove a socket from the internal list.
IpL4Protocol::DownTargetCallback m_downTarget
Callback to send packets over IPv4.
IpL4Protocol::DownTargetCallback6 m_downTarget6
Callback to send packets over IPv6.
void DoDispose() override
Destructor implementation.
void NotifyNewAggregate() override
Notify all Objects aggregated to this one of a new Object being aggregated.
void DeAllocate(Ipv4EndPoint *endPoint)
Remove an IPv4 Endpoint.
static const uint8_t PROT_NUMBER
protocol number (0x11)
uint64_t m_socketIndex
Index of the next socket to be created.
uint16_t port
Definition: dsdv-manet.cc:44
ObjectPtrContainerValue ObjectMapValue
ObjectMapValue is an alias for ObjectPtrContainerValue.
Definition: object-map.h:40
Ptr< const AttributeAccessor > MakeObjectMapAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-map.h:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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
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...
Definition: callback.h:702