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
39TypeId
41{
42 static TypeId tid =
43 TypeId("ns3::UdpL4Protocol")
45 .SetGroupName("Internet")
46 .AddConstructor<UdpL4Protocol>()
47 .AddAttribute("SocketList",
48 "A container of sockets associated to this protocol. "
49 "The underlying type is an unordered map, the attribute name "
50 "is kept for backward compatibility.",
54 return tid;
55}
56
58 : m_endPoints(new Ipv4EndPointDemux()),
59 m_endPoints6(new Ipv6EndPointDemux())
60{
61 NS_LOG_FUNCTION(this);
62}
63
68
69void
71{
72 m_node = node;
73}
74
75/*
76 * This method is called by AggregateObject and completes the aggregation
77 * by setting the node in the udp stack and link it to the ipv4 object
78 * present in the node along with the socket factory
79 */
80void
82{
83 NS_LOG_FUNCTION(this);
84 Ptr<Node> node = this->GetObject<Node>();
85 Ptr<Ipv4> ipv4 = this->GetObject<Ipv4>();
86 Ptr<Ipv6> ipv6 = node->GetObject<Ipv6>();
87
88 if (!m_node)
89 {
90 if (node && (ipv4 || ipv6))
91 {
92 this->SetNode(node);
94 udpFactory->SetUdp(this);
95 node->AggregateObject(udpFactory);
96 }
97 }
98
99 // We set at least one of our 2 down targets to the IPv4/IPv6 send
100 // functions. Since these functions have different prototypes, we
101 // need to keep track of whether we are connected to an IPv4 or
102 // IPv6 lower layer and call the appropriate one.
103
104 if (ipv4 && m_downTarget.IsNull())
105 {
106 ipv4->Insert(this);
108 }
109 if (ipv6 && m_downTarget6.IsNull())
110 {
111 ipv6->Insert(this);
113 }
115}
116
117int
119{
120 return PROT_NUMBER;
121}
122
123void
125{
126 NS_LOG_FUNCTION(this);
127 for (auto i = m_sockets.begin(); i != m_sockets.end(); i++)
128 {
129 i->second = nullptr;
130 }
131 m_sockets.clear();
132
133 if (m_endPoints != nullptr)
134 {
135 delete m_endPoints;
136 m_endPoints = nullptr;
137 }
138 if (m_endPoints6 != nullptr)
139 {
140 delete m_endPoints6;
141 m_endPoints6 = nullptr;
142 }
143 m_node = nullptr;
146 /*
147 = MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
148 */
150}
151
154{
155 NS_LOG_FUNCTION(this);
157 socket->SetNode(m_node);
158 socket->SetUdp(this);
159 m_sockets[m_socketIndex++] = socket;
160 return socket;
161}
162
165{
166 NS_LOG_FUNCTION(this);
167 return m_endPoints->Allocate();
168}
169
172{
173 NS_LOG_FUNCTION(this << address);
174 return m_endPoints->Allocate(address);
175}
176
179{
180 NS_LOG_FUNCTION(this << boundNetDevice << port);
181 return m_endPoints->Allocate(boundNetDevice, port);
182}
183
185UdpL4Protocol::Allocate(Ptr<NetDevice> boundNetDevice, Ipv4Address address, uint16_t port)
186{
187 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
188 return m_endPoints->Allocate(boundNetDevice, address, port);
189}
190
193 Ipv4Address localAddress,
194 uint16_t localPort,
195 Ipv4Address peerAddress,
196 uint16_t peerPort)
197{
198 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
199 return m_endPoints->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
200}
201
202void
204{
205 NS_LOG_FUNCTION(this << endPoint);
206 m_endPoints->DeAllocate(endPoint);
207}
208
211{
212 NS_LOG_FUNCTION(this);
213 return m_endPoints6->Allocate();
214}
215
218{
219 NS_LOG_FUNCTION(this << address);
220 return m_endPoints6->Allocate(address);
221}
222
225{
226 NS_LOG_FUNCTION(this << boundNetDevice << port);
227 return m_endPoints6->Allocate(boundNetDevice, port);
228}
229
231UdpL4Protocol::Allocate6(Ptr<NetDevice> boundNetDevice, Ipv6Address address, uint16_t port)
232{
233 NS_LOG_FUNCTION(this << boundNetDevice << address << port);
234 return m_endPoints6->Allocate(boundNetDevice, address, port);
235}
236
239 Ipv6Address localAddress,
240 uint16_t localPort,
241 Ipv6Address peerAddress,
242 uint16_t peerPort)
243{
244 NS_LOG_FUNCTION(this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
245 return m_endPoints6->Allocate(boundNetDevice, localAddress, localPort, peerAddress, peerPort);
246}
247
248void
250{
251 NS_LOG_FUNCTION(this << endPoint);
252 m_endPoints6->DeAllocate(endPoint);
253}
254
255void
257 uint8_t icmpTtl,
258 uint8_t icmpType,
259 uint8_t icmpCode,
260 uint32_t icmpInfo,
261 Ipv4Address payloadSource,
262 Ipv4Address payloadDestination,
263 const uint8_t payload[8])
264{
265 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
266 << payloadSource << payloadDestination);
267 uint16_t src;
268 uint16_t dst;
269 src = payload[0] << 8;
270 src |= payload[1];
271 dst = payload[2] << 8;
272 dst |= payload[3];
273
274 Ipv4EndPoint* endPoint = m_endPoints->SimpleLookup(payloadSource, src, payloadDestination, dst);
275 if (endPoint != nullptr)
276 {
277 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
278 }
279 else
280 {
281 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
282 << ", destination=" << payloadDestination
283 << ", src=" << src << ", dst=" << dst);
284 }
285}
286
287void
289 uint8_t icmpTtl,
290 uint8_t icmpType,
291 uint8_t icmpCode,
292 uint32_t icmpInfo,
293 Ipv6Address payloadSource,
294 Ipv6Address payloadDestination,
295 const uint8_t payload[8])
296{
297 NS_LOG_FUNCTION(this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
298 << payloadSource << payloadDestination);
299 uint16_t src;
300 uint16_t dst;
301 src = payload[0] << 8;
302 src |= payload[1];
303 dst = payload[2] << 8;
304 dst |= payload[3];
305
306 Ipv6EndPoint* endPoint =
307 m_endPoints6->SimpleLookup(payloadSource, src, payloadDestination, dst);
308 if (endPoint != nullptr)
309 {
310 endPoint->ForwardIcmp(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
311 }
312 else
313 {
314 NS_LOG_DEBUG("no endpoint found source=" << payloadSource
315 << ", destination=" << payloadDestination
316 << ", src=" << src << ", dst=" << dst);
317 }
318}
319
322{
323 NS_LOG_FUNCTION(this << packet << header);
324 UdpHeader udpHeader;
326 {
327 udpHeader.EnableChecksums();
328 }
329
330 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
331
332 // We only peek at the header for now (instead of removing it) so that it will be intact
333 // if we have to pass it to a IPv6 endpoint via:
334 //
335 // UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
336
337 packet->PeekHeader(udpHeader);
338
339 if (!udpHeader.IsChecksumOk())
340 {
341 NS_LOG_INFO("Bad checksum : dropping packet!");
343 }
344
345 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
346 << udpHeader.GetDestinationPort());
348 udpHeader.GetDestinationPort(),
349 header.GetSource(),
350 udpHeader.GetSourcePort(),
351 interface);
352 if (endPoints.empty())
353 {
354 if (this->GetObject<Ipv6>())
355 {
356 NS_LOG_LOGIC(" No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 " << this);
357 Ptr<Ipv6Interface> fakeInterface;
358 Ipv6Header ipv6Header;
361 ipv6Header.SetSource(src);
362 ipv6Header.SetDestination(dst);
363 return (this->Receive(packet, ipv6Header, fakeInterface));
364 }
365
366 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
368 }
369
370 packet->RemoveHeader(udpHeader);
371 for (auto endPoint = endPoints.begin(); endPoint != endPoints.end(); endPoint++)
372 {
373 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
374 }
375 return IpL4Protocol::RX_OK;
376}
377
380{
381 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination());
382 UdpHeader udpHeader;
384 {
385 udpHeader.EnableChecksums();
386 }
387
388 udpHeader.InitializeChecksum(header.GetSource(), header.GetDestination(), PROT_NUMBER);
389
390 packet->RemoveHeader(udpHeader);
391
392 if (!udpHeader.IsChecksumOk() && !header.GetSource().IsIpv4MappedAddress())
393 {
394 NS_LOG_INFO("Bad checksum : dropping packet!");
396 }
397
398 NS_LOG_DEBUG("Looking up dst " << header.GetDestination() << " port "
399 << udpHeader.GetDestinationPort());
401 udpHeader.GetDestinationPort(),
402 header.GetSource(),
403 udpHeader.GetSourcePort(),
404 interface);
405 if (endPoints.empty())
406 {
407 NS_LOG_LOGIC("RX_ENDPOINT_UNREACH");
409 }
410 for (auto endPoint = endPoints.begin(); endPoint != endPoints.end(); endPoint++)
411 {
412 (*endPoint)->ForwardUp(packet->Copy(), header, udpHeader.GetSourcePort(), interface);
413 }
414 return IpL4Protocol::RX_OK;
415}
416
417void
419 Ipv4Address saddr,
420 Ipv4Address daddr,
421 uint16_t sport,
422 uint16_t dport)
423{
424 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
425
426 UdpHeader udpHeader;
428 {
429 udpHeader.EnableChecksums();
430 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
431 }
432 udpHeader.SetDestinationPort(dport);
433 udpHeader.SetSourcePort(sport);
434
435 packet->AddHeader(udpHeader);
436
437 m_downTarget(packet, saddr, daddr, PROT_NUMBER, nullptr);
438}
439
440void
442 Ipv4Address saddr,
443 Ipv4Address daddr,
444 uint16_t sport,
445 uint16_t dport,
446 Ptr<Ipv4Route> route)
447{
448 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
449
450 UdpHeader udpHeader;
452 {
453 udpHeader.EnableChecksums();
454 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
455 }
456 udpHeader.SetDestinationPort(dport);
457 udpHeader.SetSourcePort(sport);
458
459 packet->AddHeader(udpHeader);
460
461 m_downTarget(packet, saddr, daddr, PROT_NUMBER, route);
462}
463
464void
466 Ipv6Address saddr,
467 Ipv6Address daddr,
468 uint16_t sport,
469 uint16_t dport)
470{
471 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport);
472
473 UdpHeader udpHeader;
475 {
476 udpHeader.EnableChecksums();
477 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
478 }
479 udpHeader.SetDestinationPort(dport);
480 udpHeader.SetSourcePort(sport);
481
482 packet->AddHeader(udpHeader);
483
484 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, nullptr);
485}
486
487void
489 Ipv6Address saddr,
490 Ipv6Address daddr,
491 uint16_t sport,
492 uint16_t dport,
493 Ptr<Ipv6Route> route)
494{
495 NS_LOG_FUNCTION(this << packet << saddr << daddr << sport << dport << route);
496
497 UdpHeader udpHeader;
499 {
500 udpHeader.EnableChecksums();
501 udpHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
502 }
503 udpHeader.SetDestinationPort(dport);
504 udpHeader.SetSourcePort(sport);
505
506 packet->AddHeader(udpHeader);
507
508 m_downTarget6(packet, saddr, daddr, PROT_NUMBER, route);
509}
510
511void
517
520{
521 return m_downTarget;
522}
523
524void
530
533{
534 return m_downTarget6;
535}
536
537bool
539{
540 NS_LOG_FUNCTION(this << socket);
541
542 for (auto& socketItem : m_sockets)
543 {
544 if (socketItem.second == socket)
545 {
546 socketItem.second = nullptr;
547 m_sockets.erase(socketItem.first);
548 return true;
549 }
550 }
551 return false;
552}
553
554} // 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:49
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 constexpr uint8_t PROT_NUMBER
Protocol number (see http://www.iana.org/assignments/protocol-numbers)
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