A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
packet-sink.cc
Go to the documentation of this file.
1/*
2 * Copyright 2007 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Tom Henderson (tomhend@u.washington.edu)
7 */
8
9#include "packet-sink.h"
10
11#include "ns3/address-utils.h"
12#include "ns3/boolean.h"
13#include "ns3/inet-socket-address.h"
14#include "ns3/inet6-socket-address.h"
15#include "ns3/ipv4-packet-info-tag.h"
16#include "ns3/ipv6-packet-info-tag.h"
17#include "ns3/log.h"
18#include "ns3/node.h"
19#include "ns3/packet.h"
20#include "ns3/simulator.h"
21#include "ns3/socket-factory.h"
22#include "ns3/socket.h"
23#include "ns3/trace-source-accessor.h"
24#include "ns3/udp-socket-factory.h"
25#include "ns3/udp-socket.h"
26
27namespace ns3
28{
29
30NS_LOG_COMPONENT_DEFINE("PacketSink");
31
33
34TypeId
36{
37 static TypeId tid =
38 TypeId("ns3::PacketSink")
40 .SetGroupName("Applications")
41 .AddConstructor<PacketSink>()
42 .AddAttribute("Protocol",
43 "The type id of the protocol to use for the rx socket.",
47 .AddAttribute("EnableSeqTsSizeHeader",
48 "Enable optional header tracing of SeqTsSizeHeader",
49 BooleanValue(false),
52 .AddTraceSource("Rx",
53 "A packet has been received",
55 "ns3::Packet::AddressTracedCallback")
56 .AddTraceSource("RxWithAddresses",
57 "A packet has been received",
59 "ns3::Packet::TwoAddressTracedCallback")
60 .AddTraceSource("RxWithSeqTsSize",
61 "A packet with SeqTsSize header has been received",
63 "ns3::PacketSink::SeqTsSizeCallback");
64 return tid;
65}
66
68 : m_buffer{},
69 m_socket{nullptr},
70 m_socket6{nullptr},
71 m_socketList{},
72 m_totalRx{0},
73 m_enableSeqTsSizeHeader{false}
74{
75 NS_LOG_FUNCTION(this);
76}
77
82
83uint64_t
85{
86 NS_LOG_FUNCTION(this);
87 return m_totalRx;
88}
89
92{
93 NS_LOG_FUNCTION(this);
94 return m_socket;
95}
96
97std::list<Ptr<Socket>>
99{
100 NS_LOG_FUNCTION(this);
101 return m_socketList;
102}
103
104void
106{
107 NS_LOG_FUNCTION(this);
108 m_socket = nullptr;
109 m_socketList.clear();
110
111 // chain up
113}
114
115// Application Methods
116void
117PacketSink::StartApplication() // Called at time specified by Start
118{
119 NS_LOG_FUNCTION(this);
120
121 // Create the socket if not already
122 if (!m_socket)
123 {
125 auto local = m_local;
126 if (local.IsInvalid())
127 {
129 NS_LOG_INFO(this << " Binding on port " << m_port << " / " << local << ".");
130 }
131 else if (InetSocketAddress::IsMatchingType(local))
132 {
134 const auto ipv4 = InetSocketAddress::ConvertFrom(local).GetIpv4();
135 NS_LOG_INFO(this << " Binding on " << ipv4 << " port " << m_port << " / " << local
136 << ".");
137 }
139 {
141 const auto ipv6 = Inet6SocketAddress::ConvertFrom(local).GetIpv6();
142 NS_LOG_INFO(this << " Binding on " << ipv6 << " port " << m_port << " / " << local
143 << ".");
144 }
145 if (m_socket->Bind(local) == -1)
146 {
147 NS_FATAL_ERROR("Failed to bind socket");
148 }
149 m_socket->Listen();
151 if (addressUtils::IsMulticast(local))
152 {
153 if (auto udpSocket = DynamicCast<UdpSocket>(m_socket))
154 {
155 // equivalent to setsockopt (MCAST_JOIN_GROUP)
156 udpSocket->MulticastJoinGroup(0, local);
157 }
158 else
159 {
160 NS_FATAL_ERROR("Error: joining multicast on a non-UDP socket");
161 }
162 }
169 }
170
171 if (m_local.IsInvalid() && !m_socket6)
172 {
173 // local address is not specified, so create another socket to also listen to all IPv6
174 // addresses
177 if (m_socket6->Bind(local) == -1)
178 {
179 NS_FATAL_ERROR("Failed to bind socket");
180 }
181 m_socket6->Listen();
183 if (addressUtils::IsMulticast(local))
184 {
185 if (auto udpSocket = DynamicCast<UdpSocket>(m_socket6))
186 {
187 // equivalent to setsockopt (MCAST_JOIN_GROUP)
188 udpSocket->MulticastJoinGroup(0, local);
189 }
190 else
191 {
192 NS_FATAL_ERROR("Error: joining multicast on a non-UDP socket");
193 }
194 }
201 }
202}
203
204void
205PacketSink::StopApplication() // Called at time specified by Stop
206{
207 NS_LOG_FUNCTION(this);
208 while (!m_socketList.empty()) // these are accepted sockets, close them
209 {
210 auto acceptedSocket = m_socketList.front();
211 m_socketList.pop_front();
212 acceptedSocket->Close();
213 }
214 if (m_socket)
215 {
216 m_socket->Close();
218 }
219 if (m_socket6)
220 {
221 m_socket6->Close();
223 }
224}
225
226void
228{
229 NS_LOG_FUNCTION(this << socket);
230 Address from;
231 while (auto packet = socket->RecvFrom(from))
232 {
233 if (packet->GetSize() == 0)
234 { // EOF
235 break;
236 }
237 m_totalRx += packet->GetSize();
239 {
240 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " packet sink received "
241 << packet->GetSize() << " bytes from "
242 << InetSocketAddress::ConvertFrom(from).GetIpv4() << " port "
243 << InetSocketAddress::ConvertFrom(from).GetPort() << " total Rx "
244 << m_totalRx << " bytes");
245 }
247 {
248 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " packet sink received "
249 << packet->GetSize() << " bytes from "
250 << Inet6SocketAddress::ConvertFrom(from).GetIpv6() << " port "
252 << " total Rx " << m_totalRx << " bytes");
253 }
254
255 if (!m_rxTrace.IsEmpty() || !m_rxTraceWithAddresses.IsEmpty() ||
257 {
258 Address localAddress;
259 Ipv4PacketInfoTag interfaceInfo;
260 Ipv6PacketInfoTag interface6Info;
261 if (packet->RemovePacketTag(interfaceInfo))
262 {
263 localAddress = InetSocketAddress(interfaceInfo.GetAddress(), m_port);
264 }
265 else if (packet->RemovePacketTag(interface6Info))
266 {
267 localAddress = Inet6SocketAddress(interface6Info.GetAddress(), m_port);
268 }
269 else
270 {
271 socket->GetSockName(localAddress);
272 }
273 m_rxTrace(packet, from);
274 m_rxTraceWithAddresses(packet, from, localAddress);
275
277 {
278 PacketReceived(packet, from, localAddress);
279 }
280 }
281 }
282}
283
284void
285PacketSink::PacketReceived(const Ptr<Packet>& p, const Address& from, const Address& localAddress)
286{
287 auto itBuffer = m_buffer.find(from);
288 if (itBuffer == m_buffer.end())
289 {
290 itBuffer = m_buffer.emplace(from, Create<Packet>(0)).first;
291 }
292
293 auto buffer = itBuffer->second;
294 buffer->AddAtEnd(p);
295
296 SeqTsSizeHeader header;
297 buffer->PeekHeader(header);
298
299 NS_ABORT_IF(header.GetSize() == 0);
300
301 while (buffer->GetSize() >= header.GetSize())
302 {
303 NS_LOG_DEBUG("Removing packet of size " << header.GetSize() << " from buffer of size "
304 << buffer->GetSize());
305 auto complete = buffer->CreateFragment(0, static_cast<uint32_t>(header.GetSize()));
306 buffer->RemoveAtStart(static_cast<uint32_t>(header.GetSize()));
307
308 complete->RemoveHeader(header);
309
310 m_rxTraceWithSeqTsSize(complete, from, localAddress, header);
311
312 if (buffer->GetSize() > header.GetSerializedSize())
313 {
314 buffer->PeekHeader(header);
315 }
316 else
317 {
318 break;
319 }
320 }
321}
322
323void
325{
326 NS_LOG_FUNCTION(this << socket);
327}
328
329void
331{
332 NS_LOG_FUNCTION(this << socket);
333}
334
335void
337{
338 NS_LOG_FUNCTION(this << s << from);
339 s->SetRecvCallback(MakeCallback(&PacketSink::HandleRead, this));
340 m_socketList.push_back(s);
341}
342
343} // Namespace ns3
a polymophic address class
Definition address.h:90
bool IsInvalid() const
Definition address.cc:60
void DoDispose() override
Destructor implementation.
Ptr< Node > GetNode() const
AttributeValue implementation for Boolean.
Definition boolean.h:26
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
uint16_t GetPort() const
Get the port.
static bool IsMatchingType(const Address &addr)
If the address match.
Ipv6Address GetIpv6() const
Get the IPv6 address.
an Inet address class
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
static Ipv4Address GetAny()
This class implements Linux struct pktinfo in order to deliver ancillary information to the socket in...
Ipv4Address GetAddress() const
Get the tag's address.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
This class implements a tag that carries socket ancillary data to the socket interface.
Ipv6Address GetAddress() const
Get the tag's address.
Receive and consume traffic generated to an IP address and port.
Definition packet-sink.h:62
static TypeId GetTypeId()
Get the type ID.
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer
Buffer for received packets.
TracedCallback< Ptr< const Packet >, const Address &, const Address & > m_rxTraceWithAddresses
Callback for tracing the packet Rx events, includes source and destination addresses.
void StopApplication() override
Application specific shutdown code.
TypeId m_tid
Protocol TypeId.
Ptr< Socket > GetListeningSocket() const
std::list< Ptr< Socket > > m_socketList
the accepted sockets
Ptr< Socket > m_socket6
IPv6 Socket (used if only port is specified)
void HandleRead(Ptr< Socket > socket)
Handle a packet received by the application.
uint64_t GetTotalRx() const
void HandleAccept(Ptr< Socket > socket, const Address &from)
Handle an incoming connection.
void HandlePeerError(Ptr< Socket > socket)
Handle an connection error.
TracedCallback< Ptr< const Packet >, const Address &, const Address &, const SeqTsSizeHeader & > m_rxTraceWithSeqTsSize
Callbacks for tracing the packet Rx events, includes source, destination addresses,...
uint64_t m_totalRx
Total bytes received.
~PacketSink() override
void StartApplication() override
Application specific startup code.
void DoDispose() override
Destructor implementation.
bool m_enableSeqTsSizeHeader
Enable or disable the export of SeqTsSize header.
std::list< Ptr< Socket > > GetAcceptedSockets() const
void HandlePeerClose(Ptr< Socket > socket)
Handle an connection close.
Ptr< Socket > m_socket
Socket.
void PacketReceived(const Ptr< Packet > &p, const Address &from, const Address &localAddress)
Packet received: assemble byte stream to extract SeqTsSizeHeader.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
Traced Callback: received packets, source address.
Smart pointer class similar to boost::intrusive_ptr.
Header with a sequence, a timestamp, and a "size" attribute.
uint32_t GetSerializedSize() const override
uint64_t GetSize() const
Get the size information that the header is carrying.
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Base class for sink applications.
Address m_local
Local address to bind to (address and port)
uint32_t m_port
Local port to bind to.
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition socket.cc:343
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
Definition socket.cc:94
virtual int ShutdownSend()=0
void SetCloseCallbacks(Callback< void, Ptr< Socket > > normalClose, Callback< void, Ptr< Socket > > errorClose)
Detect socket recv() events such as graceful shutdown or error.
Definition socket.cc:85
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition socket.cc:117
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition socket.cc:61
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int Listen()=0
Listen for incoming connections.
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
AttributeValue implementation for TypeId.
Definition type-id.h:617
static TypeId GetTypeId()
Get the type ID.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition type-id.cc:1320
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition type-id.h:617
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#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_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
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
bool IsMulticast(const Address &ad)
Address family-independent test for a multicast address.
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
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580