A Discrete-Event Network Simulator
API
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-l3-protocol.h"
26#include "ipv6-end-point.h"
27#include "ipv6-l3-protocol.h"
28#include "udp-header.h"
30#include "udp-socket-impl.h"
31
32#include "ns3/assert.h"
33#include "ns3/boolean.h"
34#include "ns3/ipv4-route.h"
35#include "ns3/ipv6-header.h"
36#include "ns3/ipv6-route.h"
37#include "ns3/ipv6.h"
38#include "ns3/log.h"
39#include "ns3/node.h"
40#include "ns3/object-vector.h"
41#include "ns3/packet.h"
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 = TypeId("ns3::UdpL4Protocol")
58 .SetGroupName("Internet")
59 .AddConstructor<UdpL4Protocol>()
60 .AddAttribute("SocketList",
61 "The list of sockets associated to this protocol.",
64 MakeObjectVectorChecker<UdpSocketImpl>());
65 return tid;
66}
67
69 : m_endPoints(new Ipv4EndPointDemux()),
70 m_endPoints6(new Ipv6EndPointDemux())
71{
72 NS_LOG_FUNCTION(this);
73}
74
76{
77 NS_LOG_FUNCTION(this);
78}
79
80void
82{
83 m_node = node;
84}
85
86/*
87 * This method is called by AggregateObject and completes the aggregation
88 * by setting the node in the udp stack and link it to the ipv4 object
89 * present in the node along with the socket factory
90 */
91void
93{
94 NS_LOG_FUNCTION(this);
95 Ptr<Node> node = this->GetObject<Node>();
96 Ptr<Ipv4> ipv4 = this->GetObject<Ipv4>();
97 Ptr<Ipv6> ipv6 = node->GetObject<Ipv6>();
98
99 if (!m_node)
100 {
101 if (node && (ipv4 || ipv6))
102 {
103 this->SetNode(node);
104 Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl>();
105 udpFactory->SetUdp(this);
106 node->AggregateObject(udpFactory);
107 }
108 }
109
110 // We set at least one of our 2 down targets to the IPv4/IPv6 send
111 // functions. Since these functions have different prototypes, we
112 // need to keep track of whether we are connected to an IPv4 or
113 // IPv6 lower layer and call the appropriate one.
114
115 if (ipv4 && m_downTarget.IsNull())
116 {
117 ipv4->Insert(this);
119 }
120 if (ipv6 && m_downTarget6.IsNull())
121 {
122 ipv6->Insert(this);
124 }
126}
127
128int
130{
131 return PROT_NUMBER;
132}
133
134void
136{
137 NS_LOG_FUNCTION(this);
138 for (std::vector<Ptr<UdpSocketImpl>>::iterator i = m_sockets.begin(); i != m_sockets.end(); i++)
139 {
140 *i = nullptr;
141 }
142 m_sockets.clear();
143
144 if (m_endPoints != nullptr)
145 {
146 delete m_endPoints;
147 m_endPoints = nullptr;
148 }
149 if (m_endPoints6 != nullptr)
150 {
151 delete m_endPoints6;
152 m_endPoints6 = nullptr;
153 }
154 m_node = nullptr;
157 /*
158 = MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
159 */
161}
162
165{
166 NS_LOG_FUNCTION(this);
167 Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl>();
168 socket->SetNode(m_node);
169 socket->SetUdp(this);
170 m_sockets.push_back(socket);
171 return socket;
172}
173
176{
177 NS_LOG_FUNCTION(this);
178 return m_endPoints->Allocate();
179}
180
183{
184 NS_LOG_FUNCTION(this << address);
186}
187
190{
191 NS_LOG_FUNCTION(this << boundNetDevice << port);
192 return m_endPoints->Allocate(boundNetDevice, port);
193}
194
197{
198 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
199 return m_endPoints->Allocate(boundNetDevice, address, port);
200}
201
204 Ipv4Address localAddress,
205 uint16_t localPort,
206 Ipv4Address peerAddress,
207 uint16_t peerPort)
208{
209 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
210 return m_endPoints->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
211}
212
213void
215{
216 NS_LOG_FUNCTION(this << endPoint);
217 m_endPoints->DeAllocate(endPoint);
218}
219
222{
223 NS_LOG_FUNCTION(this);
224 return m_endPoints6->Allocate();
225}
226
229{
230 NS_LOG_FUNCTION(this << address);
232}
233
236{
237 NS_LOG_FUNCTION(this << boundNetDevice << port);
238 return m_endPoints6->Allocate(boundNetDevice, port);
239}
240
243{
244 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
245 return m_endPoints6->Allocate(boundNetDevice, address, port);
246}
247
250 Ipv6Address localAddress,
251 uint16_t localPort,
252 Ipv6Address peerAddress,
253 uint16_t peerPort)
254{
255 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
256 return m_endPoints6->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
257}
258
259void
261{
262 NS_LOG_FUNCTION(this << endPoint);
263 m_endPoints6->DeAllocate(endPoint);
264}
265
266void
268 uint8_t icmpTtl,
269 uint8_t icmpType,
270 uint8_t icmpCode,
271 uint32_t icmpInfo,
272 Ipv4Address payloadSource,
273 Ipv4Address payloadDestination,
274 const uint8_t payload[8])
275{
276 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
277 << payloadSource << payloadDestination);
278 uint16_t src;
279 uint16_t dst;
280 src = payload[0] << 8;
281 src |= payload[1];
282 dst = payload[2] << 8;
283 dst |= payload[3];
284
285 Ipv4EndPoint* endPoint = m_endPoints->SimpleLookup(payloadSource, src, payloadDestination, dst);
286 if (endPoint != nullptr)
287 {
288 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
289 }
290 else
291 {
292 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
293 << ", destination=" << payloadDestination
294 << ", src=" << src << ", dst=" << dst);
295 }
296}
297
298void
300 uint8_t icmpTtl,
301 uint8_t icmpType,
302 uint8_t icmpCode,
303 uint32_t icmpInfo,
304 Ipv6Address payloadSource,
305 Ipv6Address payloadDestination,
306 const uint8_t payload[8])
307{
308 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
309 << payloadSource << payloadDestination);
310 uint16_t src;
311 uint16_t dst;
312 src = payload[0] << 8;
313 src |= payload[1];
314 dst = payload[2] << 8;
315 dst |= payload[3];
316
317 Ipv6EndPoint* endPoint =
318 m_endPoints6->SimpleLookup(payloadSource, src, payloadDestination, dst);
319 if (endPoint != nullptr)
320 {
321 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
322 }
323 else
324 {
325 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
326 << ", destination=" << payloadDestination
327 << ", src=" << src << ", dst=" << dst);
328 }
329}
330
333{
334 NS_LOG_FUNCTION(this << packet << header);
335 UdpHeader udpHeader;
337 {
338 udpHeader.EnableChecksums();
339 }
340
341 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
342
343 // We only peek at the header for now (instead of removing it) so that it will be intact
344 // if we have to pass it to a IPv6 endpoint via:
345 //
346 // UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
347
348 packet->PeekHeader(udpHeader);
349
350 if (!udpHeader.IsChecksumOk())
351 {
352 NS_LOG_INFO("Bad checksum : dropping packet!");
354 }
355
356 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
357 << udpHeader.GetDestinationPort());
359 udpHeader.GetDestinationPort(),
360 header.GetSource(),
361 udpHeader.GetSourcePort(),
362 interface);
363 if (endPoints.empty())
364 {
365 if (this->GetObject<Ipv6L3Protocol>())
366 {
367 NS_LOG_LOGIC(" No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 " << this);
368 Ptr<Ipv6Interface> fakeInterface;
369 Ipv6Header ipv6Header;
372 ipv6Header.SetSource(src);
373 ipv6Header.SetDestination(dst);
374 return (this->Receive(packet, ipv6Header, fakeInterface));
375 }
376
377 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
379 }
380
381 packet->RemoveHeader(udpHeader);
382 for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin(); endPoint != endPoints.end();
383 endPoint++)
384 {
385 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
386 }
387 return IpL4Protocol::RX_OK;
388}
389
392{
393 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination());
394 UdpHeader udpHeader;
396 {
397 udpHeader.EnableChecksums();
398 }
399
400 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
401
402 packet->RemoveHeader(udpHeader);
403
404 if (!udpHeader.IsChecksumOk() && !header.GetSource().IsIpv4MappedAddress())
405 {
406 NS_LOG_INFO("Bad checksum : dropping packet!");
408 }
409
410 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
411 << udpHeader.GetDestinationPort());
413 udpHeader.GetDestinationPort(),
414 header.GetSource(),
415 udpHeader.GetSourcePort(),
416 interface);
417 if (endPoints.empty())
418 {
419 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
421 }
422 for (Ipv6EndPointDemux::EndPointsI endPoint = endPoints.begin(); endPoint != endPoints.end();
423 endPoint++)
424 {
425 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
426 }
427 return IpL4Protocol::RX_OK;
428}
429
430void
432 Ipv4Address saddr,
433 Ipv4Address daddr,
434 uint16_t sport,
435 uint16_t dport)
436{
437 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
438
439 UdpHeader udpHeader;
441 {
442 udpHeader.EnableChecksums();
443 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
444 }
445 udpHeader.SetDestinationPort(dport);
446 udpHeader.SetSourcePort(sport);
447
448 packet->AddHeader(udpHeader);
449
450 m_downTarget(packet, saddr, daddr, PROT_NUMBER, nullptr);
451}
452
453void
455 Ipv4Address saddr,
456 Ipv4Address daddr,
457 uint16_t sport,
458 uint16_t dport,
459 Ptr<Ipv4Route> route)
460{
461 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
462
463 UdpHeader udpHeader;
465 {
466 udpHeader.EnableChecksums();
467 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
468 }
469 udpHeader.SetDestinationPort(dport);
470 udpHeader.SetSourcePort(sport);
471
472 packet->AddHeader(udpHeader);
473
474 m_downTarget(packet, saddr, daddr, PROT_NUMBER, route);
475}
476
477void
479 Ipv6Address saddr,
480 Ipv6Address daddr,
481 uint16_t sport,
482 uint16_t dport)
483{
484 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
485
486 UdpHeader udpHeader;
488 {
489 udpHeader.EnableChecksums();
490 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
491 }
492 udpHeader.SetDestinationPort(dport);
493 udpHeader.SetSourcePort(sport);
494
495 packet->AddHeader(udpHeader);
496
497 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, nullptr);
498}
499
500void
502 Ipv6Address saddr,
503 Ipv6Address daddr,
504 uint16_t sport,
505 uint16_t dport,
506 Ptr<Ipv6Route> route)
507{
508 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
509
510 UdpHeader udpHeader;
512 {
513 udpHeader.EnableChecksums();
514 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
515 }
516 udpHeader.SetDestinationPort(dport);
517 udpHeader.SetSourcePort(sport);
518
519 packet->AddHeader(udpHeader);
520
521 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, route);
522}
523
524void
526{
527 NS_LOG_FUNCTION(this);
528 m_downTarget = callback;
529}
530
533{
534 return m_downTarget;
535}
536
537void
539{
540 NS_LOG_FUNCTION(this);
541 m_downTarget6 = callback;
542}
543
546{
547 return m_downTarget6;
548}
549
550} // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:562
bool IsNull() const
Check for null implementation.
Definition: callback.h:556
L4 Protocol abstract base class.
RxStatus
Rx status codes.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
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:50
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:36
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:130
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:142
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:118
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
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:259
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
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
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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...
~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::DownTargetCallback m_downTarget
Callback to send packets over IPv4.
IpL4Protocol::DownTargetCallback6 m_downTarget6
Callback to send packets over IPv6.
void DoDispose() override
Destructor implementation.
std::vector< Ptr< UdpSocketImpl > > m_sockets
list of sockets
enum 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.
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)
uint16_t port
Definition: dsdv-manet.cc:45
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Definition: object-vector.h:40
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.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:45
address
Definition: first.py:40
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:691