app: E2E stats header

Right now, there is no way of extracting e2e statistics without using flow monitor. This patch enables, with an attribute, the possibility of adding a particular header to the outgoing packets, that will be read from PacketSink. The header contains Sequence, Size, and Timestamp, and therefore at the reception, it is possible to measure throughput and per-packet delay.
This commit is contained in:
N
2020-03-09 10:39:45 +00:00
parent 4d0fbd1df4
commit a9491c47ae
11 changed files with 443 additions and 30 deletions

View File

@@ -73,6 +73,7 @@ allows to choose between Block Ack policy and Implicit Block Ack Request policy
allows to request an acknowledgment after a configurable number of MPDUs have been
transmitted.</li>
<li>The MaxSize attribute is removed from the QueueBase base class and moved to subclasses. A new MaxSize attribute is therefore added to the DropTailQueue class, while the MaxQueueSize attribute of the WifiMacQueue class is renamed as MaxSize for API consistency.</li>
<li>The applications have now a "EnableE2EStats" attribute.</li>
</ul>
<h2>Changes to existing API:</h2>
<ul>

View File

@@ -29,6 +29,7 @@
#include "ns3/uinteger.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/tcp-socket-factory.h"
#include "ns3/boolean.h"
#include "bulk-send-application.h"
namespace ns3 {
@@ -52,6 +53,11 @@ BulkSendApplication::GetTypeId (void)
AddressValue (),
MakeAddressAccessor (&BulkSendApplication::m_peer),
MakeAddressChecker ())
.AddAttribute ("Local",
"The Address on which to bind the socket. If not set, it is generated automatically.",
AddressValue (),
MakeAddressAccessor (&BulkSendApplication::m_local),
MakeAddressChecker ())
.AddAttribute ("MaxBytes",
"The total number of bytes to send. "
"Once these bytes are sent, "
@@ -64,9 +70,17 @@ BulkSendApplication::GetTypeId (void)
TypeIdValue (TcpSocketFactory::GetTypeId ()),
MakeTypeIdAccessor (&BulkSendApplication::m_tid),
MakeTypeIdChecker ())
.AddAttribute ("EnableE2EStats",
"Enable E2E statistics (sequences, timestamps)",
BooleanValue (false),
MakeBooleanAccessor (&BulkSendApplication::m_enableE2EStats),
MakeBooleanChecker ())
.AddTraceSource ("Tx", "A new packet is created and is sent",
MakeTraceSourceAccessor (&BulkSendApplication::m_txTrace),
"ns3::Packet::TracedCallback")
.AddTraceSource ("TxE2EStat", "Statistic sent with the packet",
MakeTraceSourceAccessor (&BulkSendApplication::m_txTraceWithStats),
"ns3::PacketSink::E2EStatCallback")
;
return tid;
}
@@ -113,11 +127,13 @@ BulkSendApplication::DoDispose (void)
void BulkSendApplication::StartApplication (void) // Called at time specified by Start
{
NS_LOG_FUNCTION (this);
Address from;
// Create the socket if not already
if (!m_socket)
{
m_socket = Socket::CreateSocket (GetNode (), m_tid);
int ret = -1;
// Fatal error if socket type is not NS3_SOCK_STREAM or NS3_SOCK_SEQPACKET
if (m_socket->GetSocketType () != Socket::NS3_SOCK_STREAM &&
@@ -128,19 +144,28 @@ void BulkSendApplication::StartApplication (void) // Called at time specified by
"In other words, use TCP instead of UDP.");
}
if (Inet6SocketAddress::IsMatchingType (m_peer))
if (! m_local.IsInvalid())
{
if (m_socket->Bind6 () == -1)
NS_ABORT_MSG_IF ((Inet6SocketAddress::IsMatchingType (m_peer) && InetSocketAddress::IsMatchingType (m_local)) ||
(InetSocketAddress::IsMatchingType (m_peer) && Inet6SocketAddress::IsMatchingType (m_local)),
"Incompatible peer and local address IP version");
ret = m_socket->Bind (m_local);
}
else
{
if (Inet6SocketAddress::IsMatchingType (m_peer))
{
NS_FATAL_ERROR ("Failed to bind socket");
ret = m_socket->Bind6 ();
}
else if (InetSocketAddress::IsMatchingType (m_peer))
{
ret = m_socket->Bind ();
}
}
else if (InetSocketAddress::IsMatchingType (m_peer))
if (ret == -1)
{
if (m_socket->Bind () == -1)
{
NS_FATAL_ERROR ("Failed to bind socket");
}
NS_FATAL_ERROR ("Failed to bind socket");
}
m_socket->Connect (m_peer);
@@ -153,7 +178,8 @@ void BulkSendApplication::StartApplication (void) // Called at time specified by
}
if (m_connected)
{
SendData ();
m_socket->GetSockName (from);
SendData (from, m_peer);
}
}
@@ -175,7 +201,7 @@ void BulkSendApplication::StopApplication (void) // Called at time specified by
// Private helpers
void BulkSendApplication::SendData (void)
void BulkSendApplication::SendData (const Address &from, const Address &to)
{
NS_LOG_FUNCTION (this);
@@ -193,7 +219,24 @@ void BulkSendApplication::SendData (void)
}
NS_LOG_LOGIC ("sending packet at " << Simulator::Now ());
Ptr<Packet> packet = Create<Packet> (toSend);
Ptr<Packet> packet;
if (m_enableE2EStats)
{
// Should we add a trace for the sent tx and timestamp?
E2eStatsHeader header;
header.SetSeq (m_seq++);
header.SetSize (toSend);
NS_ABORT_IF (toSend < header.GetSerializedSize ());
packet = Create<Packet> (toSend - header.GetSerializedSize ());
packet->AddHeader (header);
m_txTraceWithStats (packet, from, to, header);
}
else
{
packet = Create<Packet> (toSend);
}
int actual = m_socket->Send (packet);
if (actual > 0)
{
@@ -221,7 +264,10 @@ void BulkSendApplication::ConnectionSucceeded (Ptr<Socket> socket)
NS_LOG_FUNCTION (this << socket);
NS_LOG_LOGIC ("BulkSendApplication Connection succeeded");
m_connected = true;
SendData ();
Address from, to;
socket->GetSockName (from);
socket->GetPeerName (to);
SendData (from, to);
}
void BulkSendApplication::ConnectionFailed (Ptr<Socket> socket)
@@ -230,13 +276,16 @@ void BulkSendApplication::ConnectionFailed (Ptr<Socket> socket)
NS_LOG_LOGIC ("BulkSendApplication, Connection Failed");
}
void BulkSendApplication::DataSend (Ptr<Socket>, uint32_t)
void BulkSendApplication::DataSend (Ptr<Socket> socket, uint32_t)
{
NS_LOG_FUNCTION (this);
if (m_connected)
{ // Only send new data if the connection has completed
SendData ();
Address from, to;
socket->GetSockName (from);
socket->GetPeerName (to);
SendData (from, to);
}
}

View File

@@ -26,6 +26,7 @@
#include "ns3/event-id.h"
#include "ns3/ptr.h"
#include "ns3/traced-callback.h"
#include "ns3/e2e-stats-header.h"
namespace ns3 {
@@ -64,6 +65,12 @@ class Socket;
* For example, TCP sockets can be used, but
* UDP sockets can not be used.
*
* If the attribute "EnableE2EStats" is enabled, the application will use
* some byte of the payload to store an header with a sequence number,
* a timestamp, and the size of the packet sent. To get these statistics,
* please use PacketSink (and enable its "EnableE2EStats" attribute) or extract
* the header yourself in your application (you can see how PacketSink is working
* with such headers).
*/
class BulkSendApplication : public Application
{
@@ -108,20 +115,29 @@ private:
/**
* \brief Send data until the L4 transmission buffer is full.
* \param from From address
* \param to To address
*/
void SendData ();
void SendData (const Address &from, const Address &to);
Ptr<Socket> m_socket; //!< Associated socket
Address m_peer; //!< Peer address
Address m_local; //!< Local address to bind to
bool m_connected; //!< True if connected
uint32_t m_sendSize; //!< Size of data to send each time
uint64_t m_maxBytes; //!< Limit total number of bytes sent
uint64_t m_totBytes; //!< Total bytes sent so far
TypeId m_tid; //!< The type of protocol to use.
uint32_t m_seq {0}; //!< Sequence
bool m_enableE2EStats {false}; //!< Enable or disable the e2e statistic generation
/// Traced Callback: sent packets
TracedCallback<Ptr<const Packet> > m_txTrace;
/// Callback for tracing the packet Tx events, includes source, destination, and the packet sent
TracedCallback<Ptr<const Packet>, const Address &, const Address &, const E2eStatsHeader &> m_txTraceWithStats;
private:
/**
* \brief Connection Succeeded (called by Socket through a callback)

View File

@@ -0,0 +1,86 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 Natale Patriciello <natale.patriciello@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "ns3/log.h"
#include "e2e-stats-header.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("SizeHeader");
NS_OBJECT_ENSURE_REGISTERED (E2eStatsHeader);
E2eStatsHeader::E2eStatsHeader ()
: SeqTsHeader ()
{
NS_LOG_FUNCTION (this);
}
TypeId
E2eStatsHeader::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::SizeHeader")
.SetParent<SeqTsHeader> ()
.SetGroupName ("Applications")
.AddConstructor<E2eStatsHeader> ()
;
return tid;
}
TypeId
E2eStatsHeader::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
void
E2eStatsHeader::Print (std::ostream &os) const
{
NS_LOG_FUNCTION (this << &os);
os << "(size=" << m_size << ") AND ";
SeqTsHeader::Print (os);
}
uint32_t
E2eStatsHeader::GetSerializedSize (void) const
{
NS_LOG_FUNCTION (this);
return SeqTsHeader::GetSerializedSize () + 8;
}
void
E2eStatsHeader::Serialize (Buffer::Iterator start) const
{
NS_LOG_FUNCTION (this << &start);
Buffer::Iterator i = start;
i.WriteHtonU64 (m_size);
SeqTsHeader::Serialize (i);
}
uint32_t
E2eStatsHeader::Deserialize (Buffer::Iterator start)
{
NS_LOG_FUNCTION (this << &start);
Buffer::Iterator i = start;
m_size = i.ReadNtohU64 ();
SeqTsHeader::Deserialize (i);
return GetSerializedSize ();
}
} // namespace ns3

View File

@@ -0,0 +1,89 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 Natale Patriciello <natale.patriciello@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include <ns3/seq-ts-header.h>
namespace ns3 {
/**
* \ingroup applications
* \brief Header with a sequence, a timestamp, and a "size" attribute
*
* Sometimes, you would need an header that not only track an application
* sequence number, or an application timestamp, but also track
* how big are these application packets.
*
* This header extends SeqTsHeader, adding space to store the information
* about the size of these packets.
*
* When you will use a protocol like TCP, you will find the answer to the question
* "isn't SeqTsHeader enough?".
*/
class E2eStatsHeader : public SeqTsHeader
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
/**
* @brief SizeHeader constructor
*/
E2eStatsHeader ();
/**
* \brief ~SizeHeader
*
* Nothing much to add here
*/
virtual ~E2eStatsHeader () override
{
}
/**
* @brief Set the size information that the header will carry
* @param size the size
*/
void SetSize (uint64_t size)
{
m_size = size;
}
/**
* @brief Get the size information that the header is carrying
* @return the size
*/
uint64_t GetSize (void) const
{
return m_size;
}
// Inherited
virtual TypeId GetInstanceTypeId (void) const override;
virtual void Print (std::ostream &os) const override;
virtual uint32_t GetSerializedSize (void) const override;
virtual void Serialize (Buffer::Iterator start) const override;
virtual uint32_t Deserialize (Buffer::Iterator start) override;
private:
uint64_t m_size {0}; //!< The 'size' information that the header is carrying
};
} // namespace ns3

View File

@@ -41,6 +41,7 @@
#include "ns3/udp-socket-factory.h"
#include "ns3/string.h"
#include "ns3/pointer.h"
#include "ns3/boolean.h"
namespace ns3 {
@@ -67,6 +68,11 @@ OnOffApplication::GetTypeId (void)
AddressValue (),
MakeAddressAccessor (&OnOffApplication::m_peer),
MakeAddressChecker ())
.AddAttribute ("Local",
"The Address on which to bind the socket. If not set, it is generated automatically.",
AddressValue (),
MakeAddressAccessor (&OnOffApplication::m_local),
MakeAddressChecker ())
.AddAttribute ("OnTime", "A RandomVariableStream used to pick the duration of the 'On' state.",
StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
MakePointerAccessor (&OnOffApplication::m_onTime),
@@ -88,12 +94,20 @@ OnOffApplication::GetTypeId (void)
MakeTypeIdAccessor (&OnOffApplication::m_tid),
// This should check for SocketFactory as a parent
MakeTypeIdChecker ())
.AddAttribute ("EnableE2EStats",
"Enable E2E statistics (sequences, timestamps)",
BooleanValue (false),
MakeBooleanAccessor (&OnOffApplication::m_enableE2EStats),
MakeBooleanChecker ())
.AddTraceSource ("Tx", "A new packet is created and is sent",
MakeTraceSourceAccessor (&OnOffApplication::m_txTrace),
"ns3::Packet::TracedCallback")
.AddTraceSource ("TxWithAddresses", "A new packet is created and is sent",
MakeTraceSourceAccessor (&OnOffApplication::m_txTraceWithAddresses),
"ns3::Packet::TwoAddressTracedCallback")
.AddTraceSource ("TxE2EStat", "Statistic sent with the packet",
MakeTraceSourceAccessor (&OnOffApplication::m_txTraceWithStats),
"ns3::PacketSink::E2EStatCallback")
;
return tid;
}
@@ -157,21 +171,33 @@ void OnOffApplication::StartApplication () // Called at time specified by Start
if (!m_socket)
{
m_socket = Socket::CreateSocket (GetNode (), m_tid);
if (Inet6SocketAddress::IsMatchingType (m_peer))
int ret = -1;
if (! m_local.IsInvalid())
{
if (m_socket->Bind6 () == -1)
NS_ABORT_MSG_IF ((Inet6SocketAddress::IsMatchingType (m_peer) && InetSocketAddress::IsMatchingType (m_local)) ||
(InetSocketAddress::IsMatchingType (m_peer) && Inet6SocketAddress::IsMatchingType (m_local)),
"Incompatible peer and local address IP version");
ret = m_socket->Bind (m_local);
}
else
{
if (Inet6SocketAddress::IsMatchingType (m_peer))
{
NS_FATAL_ERROR ("Failed to bind socket");
ret = m_socket->Bind6 ();
}
else if (InetSocketAddress::IsMatchingType (m_peer) ||
PacketSocketAddress::IsMatchingType (m_peer))
{
ret = m_socket->Bind ();
}
}
else if (InetSocketAddress::IsMatchingType (m_peer) ||
PacketSocketAddress::IsMatchingType (m_peer))
if (ret == -1)
{
if (m_socket->Bind () == -1)
{
NS_FATAL_ERROR ("Failed to bind socket");
}
NS_FATAL_ERROR ("Failed to bind socket");
}
m_socket->Connect (m_peer);
m_socket->SetAllowBroadcast (true);
m_socket->ShutdownRecv ();
@@ -283,7 +309,26 @@ void OnOffApplication::SendPacket ()
NS_LOG_FUNCTION (this);
NS_ASSERT (m_sendEvent.IsExpired ());
Ptr<Packet> packet = Create<Packet> (m_pktSize);
Ptr<Packet> packet;
if (m_enableE2EStats)
{
Address from, to;
m_socket->GetSockName (from);
m_socket->GetPeerName (to);
E2eStatsHeader header;
header.SetSeq (m_seq++);
header.SetSize (m_pktSize);
NS_ABORT_IF (m_pktSize < header.GetSerializedSize ());
packet = Create<Packet> (m_pktSize - header.GetSerializedSize ());
packet->AddHeader (header);
m_txTraceWithStats (packet, from, to, header);
}
else
{
packet = Create<Packet> (m_pktSize);
}
m_txTrace (packet);
m_socket->Send (packet);
m_totBytes += m_pktSize;
@@ -324,6 +369,7 @@ void OnOffApplication::ConnectionSucceeded (Ptr<Socket> socket)
void OnOffApplication::ConnectionFailed (Ptr<Socket> socket)
{
NS_LOG_FUNCTION (this << socket);
NS_FATAL_ERROR ("Can't connect");
}

View File

@@ -31,6 +31,7 @@
#include "ns3/ptr.h"
#include "ns3/data-rate.h"
#include "ns3/traced-callback.h"
#include "ns3/e2e-stats-header.h"
namespace ns3 {
@@ -82,6 +83,13 @@ class Socket;
*
* If the underlying socket type supports broadcast, this application
* will automatically enable the SetAllowBroadcast(true) socket option.
*
* If the attribute "EnableE2EStats" is enabled, the application will use
* some byte of the payload to store an header with a sequence number,
* a timestamp, and the size of the packet sent. To get these statistics,
* please use PacketSink (and enable its "EnableE2EStats" attribute) or extract
* the header yourself in your application (you can see how PacketSink is working
* with such headers).
*/
class OnOffApplication : public Application
{
@@ -150,6 +158,7 @@ private:
Ptr<Socket> m_socket; //!< Associated socket
Address m_peer; //!< Peer address
Address m_local; //!< Local address to bind to
bool m_connected; //!< True if connected
Ptr<RandomVariableStream> m_onTime; //!< rng for On Time
Ptr<RandomVariableStream> m_offTime; //!< rng for Off Time
@@ -163,6 +172,9 @@ private:
EventId m_startStopEvent; //!< Event id for next start or stop event
EventId m_sendEvent; //!< Event id of pending "send packet" event
TypeId m_tid; //!< Type of the socket used
uint32_t m_seq {0}; //!< Sequence
bool m_enableE2EStats {false}; //!< Enable or disable the e2e statistic generation
/// Traced Callback: transmitted packets.
TracedCallback<Ptr<const Packet> > m_txTrace;
@@ -170,6 +182,9 @@ private:
/// Callbacks for tracing the packet Tx events, includes source and destination addresses
TracedCallback<Ptr<const Packet>, const Address &, const Address &> m_txTraceWithAddresses;
/// Callback for tracing the packet Tx events, includes source, destination, and the packet sent
TracedCallback<Ptr<const Packet>, const Address &, const Address &, const E2eStatsHeader &> m_txTraceWithStats;
private:
/**
* \brief Schedule the next packet transmission

View File

@@ -31,6 +31,7 @@
#include "ns3/trace-source-accessor.h"
#include "ns3/udp-socket-factory.h"
#include "packet-sink.h"
#include "ns3/boolean.h"
namespace ns3 {
@@ -55,6 +56,11 @@ PacketSink::GetTypeId (void)
TypeIdValue (UdpSocketFactory::GetTypeId ()),
MakeTypeIdAccessor (&PacketSink::m_tid),
MakeTypeIdChecker ())
.AddAttribute ("EnableE2EStats",
"Enable E2E statistics (sequences, timestamps)",
BooleanValue (false),
MakeBooleanAccessor (&PacketSink::m_enableE2EStats),
MakeBooleanChecker ())
.AddTraceSource ("Rx",
"A packet has been received",
MakeTraceSourceAccessor (&PacketSink::m_rxTrace),
@@ -62,6 +68,10 @@ PacketSink::GetTypeId (void)
.AddTraceSource ("RxWithAddresses", "A packet has been received",
MakeTraceSourceAccessor (&PacketSink::m_rxTraceWithAddresses),
"ns3::Packet::TwoAddressTracedCallback")
.AddTraceSource ("RxE2EStat",
"A sequence number and a timestamp have been received",
MakeTraceSourceAccessor (&PacketSink::m_rxTraceWithAddressesAndSeqTs),
"ns3::PacketSink::E2EStatCallback")
;
return tid;
}
@@ -197,6 +207,50 @@ void PacketSink::HandleRead (Ptr<Socket> socket)
socket->GetSockName (localAddress);
m_rxTrace (packet, from);
m_rxTraceWithAddresses (packet, from, localAddress);
if (m_enableE2EStats)
{
PacketReceived (packet, from, localAddress);
}
}
}
void
PacketSink::PacketReceived (const Ptr<Packet> &p, const Address &from,
const Address &localAddress)
{
E2eStatsHeader header;
Ptr<Packet> buffer;
auto itBuffer = m_buffer.find (from);
if (itBuffer == m_buffer.end ())
{
itBuffer = m_buffer.insert (std::make_pair (from, Create<Packet> (0))).first;
}
buffer = itBuffer->second;
buffer->AddAtEnd (p);
buffer->PeekHeader (header);
NS_ABORT_IF (header.GetSize () == 0);
while (buffer->GetSize () >= header.GetSize ())
{
Ptr<Packet> complete = buffer->CreateFragment (0, static_cast<uint32_t> (header.GetSize ()));
buffer->RemoveAtStart (static_cast<uint32_t> (header.GetSize ()));
complete->RemoveHeader (header);
m_rxTraceWithAddressesAndSeqTs (complete, from, localAddress, header);
if (buffer->GetSize () > 0)
{
buffer->PeekHeader (header);
}
else
{
break;
}
}
}

View File

@@ -26,6 +26,9 @@
#include "ns3/ptr.h"
#include "ns3/traced-callback.h"
#include "ns3/address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/e2e-stats-header.h"
#include <unordered_map>
namespace ns3 {
@@ -91,7 +94,19 @@ public:
* \return list of pointers to accepted sockets
*/
std::list<Ptr<Socket> > GetAcceptedSockets (void) const;
/**
* TracedCallback signature for an E2E stat callback
*
* \param p The packet received
* \param from From address
* \param to Local address
* \param seq The sequence received
* \param time The delay the sequence has needed from the sender to the receiver
*/
typedef void (* E2EStatCallback)(Ptr<const Packet> p, const Address &from, const Address & to,
const E2eStatsHeader &header);
protected:
virtual void DoDispose (void);
private:
@@ -121,7 +136,44 @@ private:
*/
void HandlePeerError (Ptr<Socket> socket);
// In the case of TCP, each socket accept returns a new socket, so the
/**
* \brief Packet received: calculation of the e2e statistics
* \param p received packet
* \param from from address
* \param localAddress local address
*
* The method calculates e2e statistics about the received packet. If
* the transport protocol is stream-based, then reconstruct first the
* original packet, and then extract the statistic header from it.
*/
void PacketReceived (const Ptr<Packet> &p, const Address &from, const Address &localAddress);
/**
* \brief Hashing for the Address class
*/
struct AddressHash
{
/**
* \brief operator ()
* \param x the address of which calculate the hash
* \return the hash of x
*
* Should this method go in address.h?
*
* It calculates the hash taking the uint32_t hash value of the ipv4 address.
* It works only for InetSocketAddresses (Ipv4 version)
*/
size_t operator() (const Address &x) const
{
NS_ABORT_IF (!InetSocketAddress::IsMatchingType (x));
InetSocketAddress a = InetSocketAddress::ConvertFrom (x);
return std::hash<uint32_t>()(a.GetIpv4 ().Get ());
}
};
std::unordered_map<Address, Ptr<Packet>, AddressHash> m_buffer; //!< Buffer for received packets
// In the case of TCP, each socket accept returns a new socket, so the
// listening socket is stored separately from the accepted sockets
Ptr<Socket> m_socket; //!< Listening socket
std::list<Ptr<Socket> > m_socketList; //!< the accepted sockets
@@ -130,12 +182,14 @@ private:
uint64_t m_totalRx; //!< Total bytes received
TypeId m_tid; //!< Protocol TypeId
bool m_enableE2EStats {false}; //!< Enable or disable the E2E statistics generation
/// Traced Callback: received packets, source address.
TracedCallback<Ptr<const Packet>, const Address &> m_rxTrace;
/// Callback for tracing the packet Rx events, includes source and destination addresses
TracedCallback<Ptr<const Packet>, const Address &, const Address &> m_rxTraceWithAddresses;
/// Callback for tracing the packet Rx events, includes source, destination addresses, sequence and timestamp
TracedCallback<Ptr<const Packet>, const Address &, const Address &, const E2eStatsHeader&> m_rxTraceWithAddressesAndSeqTs;
};
} // namespace ns3

View File

@@ -31,7 +31,8 @@ namespace ns3 {
* \brief Packet header for UDP client/server application.
*
* The header is made of a 32bits sequence number followed by
* a 64bits time stamp.
* a 64bits time stamp. If you need to use this header with a transport protocol
* such as TCP, please consider to use SizeHeader.
*/
class SeqTsHeader : public Header
{

View File

@@ -9,6 +9,7 @@ def build(bld):
'model/udp-client.cc',
'model/udp-server.cc',
'model/seq-ts-header.cc',
'model/e2e-stats-header.cc',
'model/udp-trace-client.cc',
'model/packet-loss-counter.cc',
'model/udp-echo-client.cc',
@@ -41,6 +42,7 @@ def build(bld):
'model/udp-client.h',
'model/udp-server.h',
'model/seq-ts-header.h',
'model/e2e-stats-header.h',
'model/udp-trace-client.h',
'model/packet-loss-counter.h',
'model/udp-echo-client.h',