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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
9#include "udp-l4-protocol.h"
10
12#include "ipv4-end-point.h"
13#include "ipv4-route.h"
14#include "ipv4.h"
16#include "ipv6-end-point.h"
17#include "ipv6-route.h"
18#include "ipv6.h"
19#include "udp-header.h"
21#include "udp-socket-impl.h"
22
23#include "ns3/assert.h"
24#include "ns3/boolean.h"
25#include "ns3/log.h"
26#include "ns3/node.h"
27#include "ns3/object-map.h"
28#include "ns3/packet.h"
29
30#include <unordered_map>
31
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("UdpL4Protocol");
36
37NS_OBJECT_ENSURE_REGISTERED(UdpL4Protocol);
38
39/* see http://www.iana.org/assignments/protocol-numbers */
40const uint8_t UdpL4Protocol::PROT_NUMBER = 17;
41
42TypeId
44{
45 static TypeId tid =
46 TypeId("ns3::UdpL4Protocol")
48 .SetGroupName("Internet")
49 .AddConstructor<UdpL4Protocol>()
50 .AddAttribute("SocketList",
51 "A container of sockets associated to this protocol. "
52 "The underlying type is an unordered map, the attribute name "
53 "is kept for backward compatibility.",
57 return tid;
58}
59
61 : m_endPoints(new Ipv4EndPointDemux()),
62 m_endPoints6(new Ipv6EndPointDemux())
63{
64 NS_LOG_FUNCTION(this);
65}
66
71
72void
74{
75 m_node = node;
76}
77
78/*
79 * This method is called by AggregateObject and completes the aggregation
80 * by setting the node in the udp stack and link it to the ipv4 object
81 * present in the node along with the socket factory
82 */
83void
85{
86 NS_LOG_FUNCTION(this);
87 Ptr<Node> node = this->GetObject<Node>();
88 Ptr<Ipv4> ipv4 = this->GetObject<Ipv4>();
89 Ptr<Ipv6> ipv6 = node->GetObject<Ipv6>();
90
91 if (!m_node)
92 {
93 if (node && (ipv4 || ipv6))
94 {
95 this->SetNode(node);
97 udpFactory->SetUdp(this);
98 node->AggregateObject(udpFactory);
99 }
100 }
101
102 // We set at least one of our 2 down targets to the IPv4/IPv6 send
103 // functions. Since these functions have different prototypes, we
104 // need to keep track of whether we are connected to an IPv4 or
105 // IPv6 lower layer and call the appropriate one.
106
107 if (ipv4 && m_downTarget.IsNull())
108 {
109 ipv4->Insert(this);
111 }
112 if (ipv6 && m_downTarget6.IsNull())
113 {
114 ipv6->Insert(this);
116 }
118}
119
120int
122{
123 return PROT_NUMBER;
124}
125
126void
128{
129 NS_LOG_FUNCTION(this);
130 for (auto i = m_sockets.begin(); i != m_sockets.end(); i++)
131 {
132 i->second = nullptr;
133 }
134 m_sockets.clear();
135
136 if (m_endPoints != nullptr)
137 {
138 delete m_endPoints;
139 m_endPoints = nullptr;
140 }
141 if (m_endPoints6 != nullptr)
142 {
143 delete m_endPoints6;
144 m_endPoints6 = nullptr;
145 }
146 m_node = nullptr;
149 /*
150 = MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
151 */
153}
154
157{
158 NS_LOG_FUNCTION(this);
160 socket->SetNode(m_node);
161 socket->SetUdp(this);
162 m_sockets[m_socketIndex++] = socket;
163 return socket;
164}
165
168{
169 NS_LOG_FUNCTION(this);
170 return m_endPoints->Allocate();
171}
172
175{
176 NS_LOG_FUNCTION(this << address);
177 return m_endPoints->Allocate(address);
178}
179
182{
183 NS_LOG_FUNCTION(this << boundNetDevice << port);
184 return m_endPoints->Allocate(boundNetDevice, port);
185}
186
188UdpL4Protocol::Allocate(Ptr<NetDevice> boundNetDevice, Ipv4Address address, uint16_t port)
189{
190 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
191 return m_endPoints->Allocate(boundNetDevice, address, port);
192}
193
196 Ipv4Address localAddress,
197 uint16_t localPort,
198 Ipv4Address peerAddress,
199 uint16_t peerPort)
200{
201 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
202 return m_endPoints->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
203}
204
205void
207{
208 NS_LOG_FUNCTION(this << endPoint);
209 m_endPoints->DeAllocate(endPoint);
210}
211
214{
215 NS_LOG_FUNCTION(this);
216 return m_endPoints6->Allocate();
217}
218
221{
222 NS_LOG_FUNCTION(this << address);
223 return m_endPoints6->Allocate(address);
224}
225
228{
229 NS_LOG_FUNCTION(this << boundNetDevice << port);
230 return m_endPoints6->Allocate(boundNetDevice, port);
231}
232
234UdpL4Protocol::Allocate6(Ptr<NetDevice> boundNetDevice, Ipv6Address address, uint16_t port)
235{
236 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
237 return m_endPoints6->Allocate(boundNetDevice, address, port);
238}
239
242 Ipv6Address localAddress,
243 uint16_t localPort,
244 Ipv6Address peerAddress,
245 uint16_t peerPort)
246{
247 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
248 return m_endPoints6->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
249}
250
251void
253{
254 NS_LOG_FUNCTION(this << endPoint);
255 m_endPoints6->DeAllocate(endPoint);
256}
257
258void
260 uint8_t icmpTtl,
261 uint8_t icmpType,
262 uint8_t icmpCode,
263 uint32_t icmpInfo,
264 Ipv4Address payloadSource,
265 Ipv4Address payloadDestination,
266 const uint8_t payload[8])
267{
268 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
269 << payloadSource << payloadDestination);
270 uint16_t src;
271 uint16_t dst;
272 src = payload[0] << 8;
273 src |= payload[1];
274 dst = payload[2] << 8;
275 dst |= payload[3];
276
277 Ipv4EndPoint* endPoint = m_endPoints->SimpleLookup(payloadSource, src, payloadDestination, dst);
278 if (endPoint != nullptr)
279 {
280 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
281 }
282 else
283 {
284 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
285 << ", destination=" << payloadDestination
286 << ", src=" << src << ", dst=" << dst);
287 }
288}
289
290void
292 uint8_t icmpTtl,
293 uint8_t icmpType,
294 uint8_t icmpCode,
295 uint32_t icmpInfo,
296 Ipv6Address payloadSource,
297 Ipv6Address payloadDestination,
298 const uint8_t payload[8])
299{
300 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
301 << payloadSource << payloadDestination);
302 uint16_t src;
303 uint16_t dst;
304 src = payload[0] << 8;
305 src |= payload[1];
306 dst = payload[2] << 8;
307 dst |= payload[3];
308
309 Ipv6EndPoint* endPoint =
310 m_endPoints6->SimpleLookup(payloadSource, src, payloadDestination, dst);
311 if (endPoint != nullptr)
312 {
313 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
314 }
315 else
316 {
317 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
318 << ", destination=" << payloadDestination
319 << ", src=" << src << ", dst=" << dst);
320 }
321}
322
325{
326 NS_LOG_FUNCTION(this << packet << header);
327 UdpHeader udpHeader;
329 {
330 udpHeader.EnableChecksums();
331 }
332
333 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
334
335 // We only peek at the header for now (instead of removing it) so that it will be intact
336 // if we have to pass it to a IPv6 endpoint via:
337 //
338 // UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
339
340 packet->PeekHeader(udpHeader);
341
342 if (!udpHeader.IsChecksumOk())
343 {
344 NS_LOG_INFO("Bad checksum : dropping packet!");
346 }
347
348 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
349 << udpHeader.GetDestinationPort());
351 udpHeader.GetDestinationPort(),
352 header.GetSource(),
353 udpHeader.GetSourcePort(),
354 interface);
355 if (endPoints.empty())
356 {
357 if (this->GetObject<Ipv6>())
358 {
359 NS_LOG_LOGIC(" No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 " << this);
360 Ptr<Ipv6Interface> fakeInterface;
361 Ipv6Header ipv6Header;
364 ipv6Header.SetSource(src);
365 ipv6Header.SetDestination(dst);
366 return (this->Receive(packet, ipv6Header, fakeInterface));
367 }
368
369 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
371 }
372
373 packet->RemoveHeader(udpHeader);
374 for (auto endPoint = endPoints.begin(); endPoint != endPoints.end(); endPoint++)
375 {
376 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
377 }
378 return IpL4Protocol::RX_OK;
379}
380
383{
384 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination());
385 UdpHeader udpHeader;
387 {
388 udpHeader.EnableChecksums();
389 }
390
391 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
392
393 packet->RemoveHeader(udpHeader);
394
395 if (!udpHeader.IsChecksumOk() && !header.GetSource().IsIpv4MappedAddress())
396 {
397 NS_LOG_INFO("Bad checksum : dropping packet!");
399 }
400
401 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
402 << udpHeader.GetDestinationPort());
404 udpHeader.GetDestinationPort(),
405 header.GetSource(),
406 udpHeader.GetSourcePort(),
407 interface);
408 if (endPoints.empty())
409 {
410 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
412 }
413 for (auto endPoint = endPoints.begin(); endPoint != endPoints.end(); endPoint++)
414 {
415 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
416 }
417 return IpL4Protocol::RX_OK;
418}
419
420void
422 Ipv4Address saddr,
423 Ipv4Address daddr,
424 uint16_t sport,
425 uint16_t dport)
426{
427 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
428
429 UdpHeader udpHeader;
431 {
432 udpHeader.EnableChecksums();
433 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
434 }
435 udpHeader.SetDestinationPort(dport);
436 udpHeader.SetSourcePort(sport);
437
438 packet->AddHeader(udpHeader);
439
440 m_downTarget(packet, saddr, daddr, PROT_NUMBER, nullptr);
441}
442
443void
445 Ipv4Address saddr,
446 Ipv4Address daddr,
447 uint16_t sport,
448 uint16_t dport,
449 Ptr<Ipv4Route> route)
450{
451 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
452
453 UdpHeader udpHeader;
455 {
456 udpHeader.EnableChecksums();
457 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
458 }
459 udpHeader.SetDestinationPort(dport);
460 udpHeader.SetSourcePort(sport);
461
462 packet->AddHeader(udpHeader);
463
464 m_downTarget(packet, saddr, daddr, PROT_NUMBER, route);
465}
466
467void
469 Ipv6Address saddr,
470 Ipv6Address daddr,
471 uint16_t sport,
472 uint16_t dport)
473{
474 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
475
476 UdpHeader udpHeader;
478 {
479 udpHeader.EnableChecksums();
480 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
481 }
482 udpHeader.SetDestinationPort(dport);
483 udpHeader.SetSourcePort(sport);
484
485 packet->AddHeader(udpHeader);
486
487 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, nullptr);
488}
489
490void
492 Ipv6Address saddr,
493 Ipv6Address daddr,
494 uint16_t sport,
495 uint16_t dport,
496 Ptr<Ipv6Route> route)
497{
498 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
499
500 UdpHeader udpHeader;
502 {
503 udpHeader.EnableChecksums();
504 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
505 }
506 udpHeader.SetDestinationPort(dport);
507 udpHeader.SetSourcePort(sport);
508
509 packet->AddHeader(udpHeader);
510
511 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, route);
512}
513
514void
520
523{
524 return m_downTarget;
525}
526
527void
533
536{
537 return m_downTarget6;
538}
539
540bool
542{
543 NS_LOG_FUNCTION(this << socket);
544
545 for (auto& socketItem : m_sockets)
546 {
547 if (socketItem.second == socket)
548 {
549 socketItem.second = nullptr;
550 m_sockets.erase(socketItem.first);
551 return true;
552 }
553 }
554 return false;
555}
556
557} // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition callback.h:561
bool IsNull() const
Check for null implementation.
Definition callback.h:555
L4 Protocol abstract base class.
RxStatus
Rx status codes.
Ipv4 addresses are stored in host order in this class.
Demultiplexes packets to various transport layer 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:23
Ipv4Address GetSource() const
Ipv4Address GetDestination() const
virtual void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)=0
Describes an IPv6 address.
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.
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:24
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
void SetSource(Ipv6Address src)
Set the "Source address" field.
Ipv6Address GetDestination() const
Get the "Destination address" field.
Ipv6Address GetSource() const
Get the "Source address" field.
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition ipv6.h:71
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:267
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition object.cc:412
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Packet header for UDP packets.
Definition udp-header.h:30
void EnableChecksums()
Enable checksum calculation for UDP.
Definition udp-header.cc:19
uint16_t GetDestinationPort() const
Definition udp-header.cc:43
uint16_t GetSourcePort() const
Definition udp-header.cc:37
bool IsChecksumOk() const
Is the UDP checksum correct ?
void InitializeChecksum(Address source, Address destination, uint8_t protocol)
Definition udp-header.cc:49
void SetSourcePort(uint16_t port)
Definition udp-header.cc:31
void SetDestinationPort(uint16_t port)
Definition udp-header.cc:25
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.
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:33
ObjectPtrContainerValue ObjectMapValue
ObjectMapValue is an alias for ObjectPtrContainerValue.
Definition object-map.h:29
Ptr< const AttributeAccessor > MakeObjectMapAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition object-map.h:65
Ptr< const AttributeChecker > MakeObjectMapChecker()
Definition object-map.h:110
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
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:684