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
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("RxWithAddresses",
53 "A packet has been received",
55 "ns3::Packet::TwoAddressTracedCallback")
56 .AddTraceSource("RxWithSeqTsSize",
57 "A packet with SeqTsSize header has been received",
59 "ns3::PacketSink::SeqTsSizeCallback");
60 return tid;
61}
62
67
72
73uint64_t
75{
76 NS_LOG_FUNCTION(this);
77 return m_totalRx;
78}
79
82{
83 NS_LOG_FUNCTION(this);
84 return m_socket;
85}
86
87std::list<Ptr<Socket>>
89{
90 NS_LOG_FUNCTION(this);
91 return m_socketList;
92}
93
94void
96{
97 NS_LOG_FUNCTION(this);
98 m_socketList.clear();
99
100 // chain up
102}
103
104// Application Methods
105void
106PacketSink::DoStartApplication() // Called at time specified by Start
107{
108 NS_LOG_FUNCTION(this);
109
110 auto local = m_local;
111 if (local.IsInvalid())
112 {
114 NS_LOG_INFO(this << " Binding on port " << m_port << " / " << local << ".");
115 }
116 else if (InetSocketAddress::IsMatchingType(local))
117 {
119 const auto ipv4 = InetSocketAddress::ConvertFrom(local).GetIpv4();
120 NS_LOG_INFO(this << " Binding on " << ipv4 << " port " << m_port << " / " << local << ".");
121 }
123 {
125 const auto ipv6 = Inet6SocketAddress::ConvertFrom(local).GetIpv6();
126 NS_LOG_INFO(this << " Binding on " << ipv6 << " port " << m_port << " / " << local << ".");
127 }
128 if (m_socket->Bind(local) == -1)
129 {
130 NS_FATAL_ERROR("Failed to bind socket");
131 }
132 m_socket->Listen();
133 m_socket->ShutdownSend();
134 if (addressUtils::IsMulticast(local))
135 {
136 if (auto udpSocket = DynamicCast<UdpSocket>(m_socket))
137 {
138 // equivalent to setsockopt (MCAST_JOIN_GROUP)
139 udpSocket->MulticastJoinGroup(0, local);
140 }
141 else
142 {
143 NS_FATAL_ERROR("Error: joining multicast on a non-UDP socket");
144 }
145 }
146 m_socket->SetRecvCallback(MakeCallback(&PacketSink::HandleRead, this));
147 m_socket->SetRecvPktInfo(true);
148 m_socket->SetAcceptCallback(MakeNullCallback<bool, Ptr<Socket>, const Address&>(),
150 m_socket->SetCloseCallbacks(MakeCallback(&PacketSink::HandlePeerClose, this),
152
153 if (m_local.IsInvalid())
154 {
156 if (m_socket6->Bind(local) == -1)
157 {
158 NS_FATAL_ERROR("Failed to bind socket");
159 }
160 m_socket6->Listen();
161 m_socket6->ShutdownSend();
162 if (addressUtils::IsMulticast(local))
163 {
164 if (auto udpSocket = DynamicCast<UdpSocket>(m_socket6))
165 {
166 // equivalent to setsockopt (MCAST_JOIN_GROUP)
167 udpSocket->MulticastJoinGroup(0, local);
168 }
169 else
170 {
171 NS_FATAL_ERROR("Error: joining multicast on a non-UDP socket");
172 }
173 }
174 m_socket6->SetRecvCallback(MakeCallback(&PacketSink::HandleRead, this));
175 m_socket6->SetRecvPktInfo(true);
176 m_socket6->SetAcceptCallback(MakeNullCallback<bool, Ptr<Socket>, const Address&>(),
178 m_socket6->SetCloseCallbacks(MakeCallback(&PacketSink::HandlePeerClose, this),
180 }
181}
182
183void
184PacketSink::DoStopApplication() // Called at time specified by Stop
185{
186 NS_LOG_FUNCTION(this);
187 while (!m_socketList.empty()) // these are accepted sockets, close them
188 {
189 auto acceptedSocket = m_socketList.front();
190 m_socketList.pop_front();
191 acceptedSocket->Close();
192 }
193}
194
195void
197{
198 NS_LOG_FUNCTION(this << socket);
199 Address from;
200 while (auto packet = socket->RecvFrom(from))
201 {
202 if (packet->GetSize() == 0)
203 { // EOF
204 break;
205 }
206 m_totalRx += packet->GetSize();
208 {
209 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " packet sink received "
210 << packet->GetSize() << " bytes from "
211 << InetSocketAddress::ConvertFrom(from).GetIpv4() << " port "
212 << InetSocketAddress::ConvertFrom(from).GetPort() << " total Rx "
213 << m_totalRx << " bytes");
214 }
216 {
217 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " packet sink received "
218 << packet->GetSize() << " bytes from "
219 << Inet6SocketAddress::ConvertFrom(from).GetIpv6() << " port "
220 << Inet6SocketAddress::ConvertFrom(from).GetPort()
221 << " total Rx " << m_totalRx << " bytes");
222 }
223
224 if (!m_rxTrace.IsEmpty() || !m_rxTraceWithoutAddress.IsEmpty() ||
225 !m_rxTraceWithAddresses.IsEmpty() ||
227 {
228 Address localAddress;
229 Ipv4PacketInfoTag interfaceInfo;
230 Ipv6PacketInfoTag interface6Info;
231 if (packet->RemovePacketTag(interfaceInfo))
232 {
233 localAddress = InetSocketAddress(interfaceInfo.GetAddress(), m_port);
234 }
235 else if (packet->RemovePacketTag(interface6Info))
236 {
237 localAddress = Inet6SocketAddress(interface6Info.GetAddress(), m_port);
238 }
239 else
240 {
241 socket->GetSockName(localAddress);
242 }
244 m_rxTrace(packet, from);
245 m_rxTraceWithAddresses(packet, from, localAddress);
246
248 {
249 PacketReceived(packet, from, localAddress);
250 }
251 }
252 }
253}
254
255void
256PacketSink::PacketReceived(const Ptr<Packet>& p, const Address& from, const Address& localAddress)
257{
258 auto itBuffer = m_buffer.find(from);
259 if (itBuffer == m_buffer.end())
260 {
261 itBuffer = m_buffer.emplace(from, Create<Packet>(0)).first;
262 }
263
264 auto buffer = itBuffer->second;
265 buffer->AddAtEnd(p);
266
267 SeqTsSizeHeader header;
268 buffer->PeekHeader(header);
269
270 NS_ABORT_IF(header.GetSize() == 0);
271
272 while (buffer->GetSize() >= header.GetSize())
273 {
274 NS_LOG_DEBUG("Removing packet of size " << header.GetSize() << " from buffer of size "
275 << buffer->GetSize());
276 auto complete = buffer->CreateFragment(0, static_cast<uint32_t>(header.GetSize()));
277 buffer->RemoveAtStart(static_cast<uint32_t>(header.GetSize()));
278
279 complete->RemoveHeader(header);
280
281 m_rxTraceWithSeqTsSize(complete, from, localAddress, header);
282
283 if (buffer->GetSize() > header.GetSerializedSize())
284 {
285 buffer->PeekHeader(header);
286 }
287 else
288 {
289 break;
290 }
291 }
292}
293
294void
296{
297 NS_LOG_FUNCTION(this << socket);
298}
299
300void
302{
303 NS_LOG_FUNCTION(this << socket);
304}
305
306void
308{
309 NS_LOG_FUNCTION(this << s << from);
310 s->SetRecvCallback(MakeCallback(&PacketSink::HandleRead, this));
311 m_socketList.push_back(s);
312}
313
314} // Namespace ns3
a polymophic address class
Definition address.h:111
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:61
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 DoStartApplication() override
Application specific startup code for child subclasses.
Ptr< Socket > GetListeningSocket() const
std::list< Ptr< Socket > > m_socketList
the accepted sockets
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 DoStopApplication() override
Application specific shutdown code for child subclasses.
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 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.
void PacketReceived(const Ptr< Packet > &p, const Address &from, const Address &localAddress)
Packet received: assemble byte stream to extract SeqTsSizeHeader.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
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
ns3::TracedCallback< Ptr< const Packet > > m_rxTraceWithoutAddress
Callbacks for tracing the packet Rx events.
Ptr< Socket > m_socket6
IPv6 Socket (used if only port is specified).
void DoDispose() override
Destructor implementation.
TypeId m_protocolTid
Protocol TypeId value.
SinkApplication(uint16_t defaultPort=0)
Constructor.
Address m_local
Local address to bind to (address and port).
Ptr< Socket > m_socket
Socket (IPv4 or IPv6, depending on local address).
uint32_t m_port
Local port to bind to.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
Traced Callback: received packets, source address.
@ S
second
Definition nstime.h:107
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
AttributeValue implementation for TypeId.
Definition type-id.h:641
static TypeId GetTypeId()
Get the type ID.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:114
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:1335
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:641
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:439
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:585