applications: Align E2eStatsHeader with other application headers (!211)
* E2eStatsHeader renamed to SeqTsSizeHeader, for module naming consistency * BulkSendApplication::EnableE2EStats attribute renamed to EnableSeqTsSizeHeader * BulkSendApplication::TxE2EStat trace source renamed to TxWithSeqTsSize * OnOffApplication::EnableE2EStats attribute renamed to EnableSeqTsSizeHeader * OnOffApplication::TxE2EStat trace source renamed to TxWithSeqTsSize * PacketSink::EnableE2EStats attribute renamed to EnableSeqTsSizeHeader * PacketSink::RxE2EStat trace source renamed to RxWithSeqTsSize * Cache outgoing packet based on Socket::Send () failure (due to full buffer) * Add test suite for BulkSendApplication, checking sequence number operation * Various other review comments addressed, and doxygen alignments
This commit is contained in:
@@ -74,6 +74,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> TCP-based applications (OnOffApplication, BulkSendApplication, and PacketSink) support a new header to convey sequence number, timestamp, and size data. Use is controlled by the "EnableSeqTsSizeHeader" attribute.</li>
|
||||
<li>Added a new trace source <b>PhyRxPayloadBegin</b> in WifiPhy for tracing begin of PSDU reception.</li>
|
||||
<li> A new sequence and timestamp header variant for applications has been added. The SeqTsEchoHeader contains an additional timestamp field for use in echoing a timestamp back to a sender.</li>
|
||||
</ul>
|
||||
|
||||
@@ -70,17 +70,17 @@ BulkSendApplication::GetTypeId (void)
|
||||
TypeIdValue (TcpSocketFactory::GetTypeId ()),
|
||||
MakeTypeIdAccessor (&BulkSendApplication::m_tid),
|
||||
MakeTypeIdChecker ())
|
||||
.AddAttribute ("EnableE2EStats",
|
||||
"Enable E2E statistics (sequences, timestamps)",
|
||||
.AddAttribute ("EnableSeqTsSizeHeader",
|
||||
"Add SeqTsSizeHeader to each packet",
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&BulkSendApplication::m_enableE2EStats),
|
||||
MakeBooleanAccessor (&BulkSendApplication::m_enableSeqTsSizeHeader),
|
||||
MakeBooleanChecker ())
|
||||
.AddTraceSource ("Tx", "A new packet is created and is sent",
|
||||
.AddTraceSource ("Tx", "A new packet is sent",
|
||||
MakeTraceSourceAccessor (&BulkSendApplication::m_txTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource ("TxE2EStat", "Statistic sent with the packet",
|
||||
MakeTraceSourceAccessor (&BulkSendApplication::m_txTraceWithStats),
|
||||
"ns3::PacketSink::E2EStatCallback")
|
||||
.AddTraceSource ("TxWithSeqTsSize", "A new packet is created with SeqTsSizeHeader",
|
||||
MakeTraceSourceAccessor (&BulkSendApplication::m_txTraceWithSeqTsSize),
|
||||
"ns3::PacketSink::SeqTsSizeCallback")
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@@ -89,7 +89,8 @@ BulkSendApplication::GetTypeId (void)
|
||||
BulkSendApplication::BulkSendApplication ()
|
||||
: m_socket (0),
|
||||
m_connected (false),
|
||||
m_totBytes (0)
|
||||
m_totBytes (0),
|
||||
m_unsentPacket (0)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
@@ -119,6 +120,7 @@ BulkSendApplication::DoDispose (void)
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
m_socket = 0;
|
||||
m_unsentPacket = 0;
|
||||
// chain up
|
||||
Application::DoDispose ();
|
||||
}
|
||||
@@ -221,16 +223,20 @@ void BulkSendApplication::SendData (const Address &from, const Address &to)
|
||||
NS_LOG_LOGIC ("sending packet at " << Simulator::Now ());
|
||||
|
||||
Ptr<Packet> packet;
|
||||
if (m_enableE2EStats)
|
||||
if (m_unsentPacket)
|
||||
{
|
||||
// Should we add a trace for the sent tx and timestamp?
|
||||
E2eStatsHeader header;
|
||||
packet = m_unsentPacket;
|
||||
}
|
||||
else if (m_enableSeqTsSizeHeader)
|
||||
{
|
||||
SeqTsSizeHeader header;
|
||||
header.SetSeq (m_seq++);
|
||||
header.SetSize (toSend);
|
||||
NS_ABORT_IF (toSend < header.GetSerializedSize ());
|
||||
packet = Create<Packet> (toSend - header.GetSerializedSize ());
|
||||
// Trace before adding header, for consistency with PacketSink
|
||||
m_txTraceWithSeqTsSize (packet, from, to, header);
|
||||
packet->AddHeader (header);
|
||||
m_txTraceWithStats (packet, from, to, header);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -238,18 +244,25 @@ void BulkSendApplication::SendData (const Address &from, const Address &to)
|
||||
}
|
||||
|
||||
int actual = m_socket->Send (packet);
|
||||
if (actual > 0)
|
||||
if ((unsigned) actual == toSend)
|
||||
{
|
||||
m_totBytes += actual;
|
||||
m_txTrace (packet);
|
||||
m_unsentPacket = 0;
|
||||
}
|
||||
// We exit this loop when actual < toSend as the send side
|
||||
// buffer is full. The "DataSent" callback will pop when
|
||||
// some buffer space has freed up.
|
||||
if ((unsigned)actual != toSend)
|
||||
else if (actual == -1)
|
||||
{
|
||||
// We exit this loop when actual < toSend as the send side
|
||||
// buffer is full. The "DataSent" callback will pop when
|
||||
// some buffer space has freed up.
|
||||
NS_LOG_DEBUG ("Unable to send packet; caching for later attempt");
|
||||
m_unsentPacket = packet;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unexpected return value from m_socket->Send ()");
|
||||
}
|
||||
}
|
||||
// Check if time to close (all sent)
|
||||
if (m_totBytes == m_maxBytes && m_connected)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/e2e-stats-header.h"
|
||||
#include "ns3/seq-ts-size-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -65,12 +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).
|
||||
* If the attribute "EnableSeqTsSizeHeader" is enabled, the application will
|
||||
* use some bytes of the payload to store an header with a sequence number,
|
||||
* a timestamp, and the size of the packet sent. Support for extracting
|
||||
* statistics from this header have been added to \c ns3::PacketSink
|
||||
* (enable its "EnableSeqTsSizeHeader" attribute), or users may extract
|
||||
* the header via trace sources.
|
||||
*/
|
||||
class BulkSendApplication : public Application
|
||||
{
|
||||
@@ -129,14 +129,14 @@ private:
|
||||
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
|
||||
|
||||
Ptr<Packet> m_unsentPacket; //!< Variable to cache unsent packet
|
||||
bool m_enableSeqTsSizeHeader {false}; //!< Enable or disable the SeqTsSizeHeader
|
||||
|
||||
/// 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;
|
||||
/// Callback for tracing the packet Tx events, includes source, destination, the packet sent, and header
|
||||
TracedCallback<Ptr<const Packet>, const Address &, const Address &, const SeqTsSizeHeader &> m_txTraceWithSeqTsSize;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -94,10 +94,10 @@ OnOffApplication::GetTypeId (void)
|
||||
MakeTypeIdAccessor (&OnOffApplication::m_tid),
|
||||
// This should check for SocketFactory as a parent
|
||||
MakeTypeIdChecker ())
|
||||
.AddAttribute ("EnableE2EStats",
|
||||
"Enable E2E statistics (sequences, timestamps)",
|
||||
.AddAttribute ("EnableSeqTsSizeHeader",
|
||||
"Enable use of SeqTsSizeHeader for sequence number and timestamp",
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&OnOffApplication::m_enableE2EStats),
|
||||
MakeBooleanAccessor (&OnOffApplication::m_enableSeqTsSizeHeader),
|
||||
MakeBooleanChecker ())
|
||||
.AddTraceSource ("Tx", "A new packet is created and is sent",
|
||||
MakeTraceSourceAccessor (&OnOffApplication::m_txTrace),
|
||||
@@ -105,9 +105,9 @@ OnOffApplication::GetTypeId (void)
|
||||
.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")
|
||||
.AddTraceSource ("TxWithSeqTsSize", "A new packet is created with SeqTsSizeHeader",
|
||||
MakeTraceSourceAccessor (&OnOffApplication::m_txTraceWithSeqTsSize),
|
||||
"ns3::PacketSink::SeqTsSizeCallback")
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@@ -118,7 +118,8 @@ OnOffApplication::OnOffApplication ()
|
||||
m_connected (false),
|
||||
m_residualBits (0),
|
||||
m_lastStartTime (Seconds (0)),
|
||||
m_totBytes (0)
|
||||
m_totBytes (0),
|
||||
m_unsentPacket (0)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
@@ -158,6 +159,7 @@ OnOffApplication::DoDispose (void)
|
||||
|
||||
CancelEvents ();
|
||||
m_socket = 0;
|
||||
m_unsentPacket = 0;
|
||||
// chain up
|
||||
Application::DoDispose ();
|
||||
}
|
||||
@@ -245,6 +247,13 @@ void OnOffApplication::CancelEvents ()
|
||||
m_cbrRateFailSafe = m_cbrRate;
|
||||
Simulator::Cancel (m_sendEvent);
|
||||
Simulator::Cancel (m_startStopEvent);
|
||||
// Canceling events may cause discontinuity in sequence number if the
|
||||
// SeqTsSizeHeader is header, and m_unsentPacket is true
|
||||
if (m_unsentPacket)
|
||||
{
|
||||
NS_LOG_DEBUG ("Discarding cached packet upon CancelEvents ()");
|
||||
}
|
||||
m_unsentPacket = 0;
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
@@ -271,17 +280,19 @@ void OnOffApplication::ScheduleNextTx ()
|
||||
|
||||
if (m_maxBytes == 0 || m_totBytes < m_maxBytes)
|
||||
{
|
||||
NS_ABORT_MSG_IF (m_residualBits > m_pktSize * 8, "Calculation to compute next send time will overflow");
|
||||
uint32_t bits = m_pktSize * 8 - m_residualBits;
|
||||
NS_LOG_LOGIC ("bits = " << bits);
|
||||
Time nextTime (Seconds (bits /
|
||||
static_cast<double>(m_cbrRate.GetBitRate ()))); // Time till next packet
|
||||
NS_LOG_LOGIC ("nextTime = " << nextTime);
|
||||
NS_LOG_LOGIC ("nextTime = " << nextTime.As (Time::S));
|
||||
m_sendEvent = Simulator::Schedule (nextTime,
|
||||
&OnOffApplication::SendPacket, this);
|
||||
}
|
||||
else
|
||||
{ // All done, cancel any pending events
|
||||
StopApplication ();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +301,7 @@ void OnOffApplication::ScheduleStartEvent ()
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Time offInterval = Seconds (m_offTime->GetValue ());
|
||||
NS_LOG_LOGIC ("start at " << offInterval);
|
||||
NS_LOG_LOGIC ("start at " << offInterval.As (Time::S));
|
||||
m_startStopEvent = Simulator::Schedule (offInterval, &OnOffApplication::StartSending, this);
|
||||
}
|
||||
|
||||
@@ -299,7 +310,7 @@ void OnOffApplication::ScheduleStopEvent ()
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Time onInterval = Seconds (m_onTime->GetValue ());
|
||||
NS_LOG_LOGIC ("stop at " << onInterval);
|
||||
NS_LOG_LOGIC ("stop at " << onInterval.As (Time::S));
|
||||
m_startStopEvent = Simulator::Schedule (onInterval, &OnOffApplication::StopSending, this);
|
||||
}
|
||||
|
||||
@@ -311,51 +322,65 @@ void OnOffApplication::SendPacket ()
|
||||
NS_ASSERT (m_sendEvent.IsExpired ());
|
||||
|
||||
Ptr<Packet> packet;
|
||||
if (m_enableE2EStats)
|
||||
if (m_unsentPacket)
|
||||
{
|
||||
packet = m_unsentPacket;
|
||||
}
|
||||
else if (m_enableSeqTsSizeHeader)
|
||||
{
|
||||
Address from, to;
|
||||
m_socket->GetSockName (from);
|
||||
m_socket->GetPeerName (to);
|
||||
E2eStatsHeader header;
|
||||
SeqTsSizeHeader header;
|
||||
header.SetSeq (m_seq++);
|
||||
header.SetSize (m_pktSize);
|
||||
NS_ABORT_IF (m_pktSize < header.GetSerializedSize ());
|
||||
packet = Create<Packet> (m_pktSize - header.GetSerializedSize ());
|
||||
// Trace before adding header, for consistency with PacketSink
|
||||
m_txTraceWithSeqTsSize (packet, from, to, header);
|
||||
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;
|
||||
Address localAddress;
|
||||
m_socket->GetSockName (localAddress);
|
||||
if (InetSocketAddress::IsMatchingType (m_peer))
|
||||
int actual = m_socket->Send (packet);
|
||||
if ((unsigned) actual == m_pktSize)
|
||||
{
|
||||
NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
|
||||
<< "s on-off application sent "
|
||||
<< packet->GetSize () << " bytes to "
|
||||
<< InetSocketAddress::ConvertFrom(m_peer).GetIpv4 ()
|
||||
<< " port " << InetSocketAddress::ConvertFrom (m_peer).GetPort ()
|
||||
<< " total Tx " << m_totBytes << " bytes");
|
||||
m_txTraceWithAddresses (packet, localAddress, InetSocketAddress::ConvertFrom (m_peer));
|
||||
m_txTrace (packet);
|
||||
m_totBytes += m_pktSize;
|
||||
m_unsentPacket = 0;
|
||||
Address localAddress;
|
||||
m_socket->GetSockName (localAddress);
|
||||
if (InetSocketAddress::IsMatchingType (m_peer))
|
||||
{
|
||||
NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
|
||||
<< "s on-off application sent "
|
||||
<< packet->GetSize () << " bytes to "
|
||||
<< InetSocketAddress::ConvertFrom(m_peer).GetIpv4 ()
|
||||
<< " port " << InetSocketAddress::ConvertFrom (m_peer).GetPort ()
|
||||
<< " total Tx " << m_totBytes << " bytes");
|
||||
m_txTraceWithAddresses (packet, localAddress, InetSocketAddress::ConvertFrom (m_peer));
|
||||
}
|
||||
else if (Inet6SocketAddress::IsMatchingType (m_peer))
|
||||
{
|
||||
NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
|
||||
<< "s on-off application sent "
|
||||
<< packet->GetSize () << " bytes to "
|
||||
<< Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6 ()
|
||||
<< " port " << Inet6SocketAddress::ConvertFrom (m_peer).GetPort ()
|
||||
<< " total Tx " << m_totBytes << " bytes");
|
||||
m_txTraceWithAddresses (packet, localAddress, Inet6SocketAddress::ConvertFrom(m_peer));
|
||||
}
|
||||
}
|
||||
else if (Inet6SocketAddress::IsMatchingType (m_peer))
|
||||
else
|
||||
{
|
||||
NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
|
||||
<< "s on-off application sent "
|
||||
<< packet->GetSize () << " bytes to "
|
||||
<< Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6 ()
|
||||
<< " port " << Inet6SocketAddress::ConvertFrom (m_peer).GetPort ()
|
||||
<< " total Tx " << m_totBytes << " bytes");
|
||||
m_txTraceWithAddresses (packet, localAddress, Inet6SocketAddress::ConvertFrom(m_peer));
|
||||
NS_LOG_DEBUG ("Unable to send packet; actual " << actual << " size " << m_pktSize << "; caching for later attempt");
|
||||
m_unsentPacket = packet;
|
||||
}
|
||||
m_lastStartTime = Simulator::Now ();
|
||||
m_residualBits = 0;
|
||||
m_lastStartTime = Simulator::Now ();
|
||||
ScheduleNextTx ();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/e2e-stats-header.h"
|
||||
#include "ns3/seq-ts-size-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -84,12 +84,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).
|
||||
* If the attribute "EnableSeqTsSizeHeader" is enabled, the application will
|
||||
* use some bytes of the payload to store an header with a sequence number,
|
||||
* a timestamp, and the size of the packet sent. Support for extracting
|
||||
* statistics from this header have been added to \c ns3::PacketSink
|
||||
* (enable its "EnableSeqTsSizeHeader" attribute), or users may extract
|
||||
* the header via trace sources. Note that the continuity of the sequence
|
||||
* number may be disrupted across On/Off cycles.
|
||||
*/
|
||||
class OnOffApplication : public Application
|
||||
{
|
||||
@@ -173,7 +174,8 @@ private:
|
||||
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
|
||||
Ptr<Packet> m_unsentPacket; //!< Unsent packet cached for future attempt
|
||||
bool m_enableSeqTsSizeHeader {false}; //!< Enable or disable the use of SeqTsSizeHeader
|
||||
|
||||
|
||||
/// Traced Callback: transmitted packets.
|
||||
@@ -182,8 +184,8 @@ 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;
|
||||
/// Callback for tracing the packet Tx events, includes source, destination, the packet sent, and header
|
||||
TracedCallback<Ptr<const Packet>, const Address &, const Address &, const SeqTsSizeHeader &> m_txTraceWithSeqTsSize;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -56,10 +56,10 @@ PacketSink::GetTypeId (void)
|
||||
TypeIdValue (UdpSocketFactory::GetTypeId ()),
|
||||
MakeTypeIdAccessor (&PacketSink::m_tid),
|
||||
MakeTypeIdChecker ())
|
||||
.AddAttribute ("EnableE2EStats",
|
||||
"Enable E2E statistics (sequences, timestamps)",
|
||||
.AddAttribute ("EnableSeqTsSizeHeader",
|
||||
"Enable optional header tracing of SeqTsSizeHeader",
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&PacketSink::m_enableE2EStats),
|
||||
MakeBooleanAccessor (&PacketSink::m_enableSeqTsSizeHeader),
|
||||
MakeBooleanChecker ())
|
||||
.AddTraceSource ("Rx",
|
||||
"A packet has been received",
|
||||
@@ -68,10 +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")
|
||||
.AddTraceSource ("RxWithSeqTsSize",
|
||||
"A packet with SeqTsSize header has been received",
|
||||
MakeTraceSourceAccessor (&PacketSink::m_rxTraceWithSeqTsSize),
|
||||
"ns3::PacketSink::SeqTsSizeCallback")
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@@ -208,7 +208,7 @@ void PacketSink::HandleRead (Ptr<Socket> socket)
|
||||
m_rxTrace (packet, from);
|
||||
m_rxTraceWithAddresses (packet, from, localAddress);
|
||||
|
||||
if (m_enableE2EStats)
|
||||
if (m_enableSeqTsSizeHeader)
|
||||
{
|
||||
PacketReceived (packet, from, localAddress);
|
||||
}
|
||||
@@ -219,7 +219,7 @@ void
|
||||
PacketSink::PacketReceived (const Ptr<Packet> &p, const Address &from,
|
||||
const Address &localAddress)
|
||||
{
|
||||
E2eStatsHeader header;
|
||||
SeqTsSizeHeader header;
|
||||
Ptr<Packet> buffer;
|
||||
|
||||
auto itBuffer = m_buffer.find (from);
|
||||
@@ -236,14 +236,15 @@ PacketSink::PacketReceived (const Ptr<Packet> &p, const Address &from,
|
||||
|
||||
while (buffer->GetSize () >= header.GetSize ())
|
||||
{
|
||||
NS_LOG_DEBUG ("Removing packet of size " << header.GetSize () << " from buffer of size " << buffer->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);
|
||||
m_rxTraceWithSeqTsSize (complete, from, localAddress, header);
|
||||
|
||||
if (buffer->GetSize () > 0)
|
||||
if (buffer->GetSize () > header.GetSerializedSize ())
|
||||
{
|
||||
buffer->PeekHeader (header);
|
||||
}
|
||||
@@ -254,7 +255,6 @@ PacketSink::PacketReceived (const Ptr<Packet> &p, const Address &from,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PacketSink::HandlePeerClose (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << socket);
|
||||
@@ -264,7 +264,6 @@ void PacketSink::HandlePeerError (Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << socket);
|
||||
}
|
||||
|
||||
|
||||
void PacketSink::HandleAccept (Ptr<Socket> s, const Address& from)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/e2e-stats-header.h"
|
||||
#include "ns3/seq-ts-size-header.h"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ns3 {
|
||||
@@ -96,16 +96,15 @@ public:
|
||||
std::list<Ptr<Socket> > GetAcceptedSockets (void) const;
|
||||
|
||||
/**
|
||||
* TracedCallback signature for an E2E stat callback
|
||||
* TracedCallback signature for a reception with addresses and SeqTsSizeHeader
|
||||
*
|
||||
* \param p The packet received
|
||||
* \param p The packet received (without the SeqTsSize header)
|
||||
* \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
|
||||
* \param header The SeqTsSize header
|
||||
*/
|
||||
typedef void (* E2EStatCallback)(Ptr<const Packet> p, const Address &from, const Address & to,
|
||||
const E2eStatsHeader &header);
|
||||
typedef void (* SeqTsSizeCallback)(Ptr<const Packet> p, const Address &from, const Address & to,
|
||||
const SeqTsSizeHeader &header);
|
||||
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
@@ -137,14 +136,13 @@ private:
|
||||
void HandlePeerError (Ptr<Socket> socket);
|
||||
|
||||
/**
|
||||
* \brief Packet received: calculation of the e2e statistics
|
||||
* \brief Packet received: assemble byte stream to extract SeqTsSizeHeader
|
||||
* \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.
|
||||
* The method assembles a received byte stream and extracts SeqTsSizeHeader
|
||||
* instances from the stream to export in a trace source.
|
||||
*/
|
||||
void PacketReceived (const Ptr<Packet> &p, const Address &from, const Address &localAddress);
|
||||
|
||||
@@ -182,14 +180,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
|
||||
bool m_enableSeqTsSizeHeader {false}; //!< Enable or disable the export of SeqTsSize header
|
||||
|
||||
/// 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;
|
||||
/// Callbacks for tracing the packet Rx events, includes source, destination addresses, and headers
|
||||
TracedCallback<Ptr<const Packet>, const Address &, const Address &, const SeqTsSizeHeader&> m_rxTraceWithSeqTsSize;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze
|
||||
* Copyright (c) 2009 INRIA
|
||||
* Copyright (c) 2016 Universita' di Firenze (added echo fields)
|
||||
*
|
||||
* 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
|
||||
@@ -55,7 +56,7 @@ SeqTsEchoHeader::GetSeq (void) const
|
||||
void
|
||||
SeqTsEchoHeader::SetTsValue (Time ts)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_FUNCTION (this << ts);
|
||||
m_tsValue = ts;
|
||||
}
|
||||
|
||||
@@ -69,7 +70,7 @@ SeqTsEchoHeader::GetTsValue (void) const
|
||||
void
|
||||
SeqTsEchoHeader::SetTsEchoReply (Time ts)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_FUNCTION (this << ts);
|
||||
m_tsEchoReply = ts;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze
|
||||
* Copyright (c) 2009 INRIA
|
||||
* Copyright (c) 2016 Universita' di Firenze (added echo fields)
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -26,13 +26,20 @@
|
||||
|
||||
namespace ns3 {
|
||||
/**
|
||||
* \ingroup udpclientserver
|
||||
* \ingroup applications
|
||||
*
|
||||
* \brief Packet header for UDP client/server application.
|
||||
* \brief Packet header to carry sequence number and timestamp
|
||||
*
|
||||
* The header is made of a 32bits sequence number followed by
|
||||
* a 64bits time stamp. If you need to use this header with a transport protocol
|
||||
* such as TCP, please consider to use SizeHeader.
|
||||
* The header is used as a payload in applications (typically UDP) to convey
|
||||
* a 32 bit sequence number followed by a 64 bit timestamp (12 bytes total).
|
||||
*
|
||||
* The timestamp is not set explicitly but automatically set to the
|
||||
* simulation time upon creation.
|
||||
*
|
||||
* If you need space for an application data unit size field (e.g. for
|
||||
* stream-based protocols like TCP), use ns3::SeqTsSizeHeader.
|
||||
*
|
||||
* \sa ns3::SeqTsSizeHeader
|
||||
*/
|
||||
class SeqTsHeader : public Header
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 INRIA
|
||||
* Copyright (c) 2018 Natale Patriciello <natale.patriciello@gmail.com>
|
||||
* (added timestamp and size fields)
|
||||
*
|
||||
* 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
|
||||
@@ -18,39 +20,51 @@
|
||||
*/
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "e2e-stats-header.h"
|
||||
#include "seq-ts-size-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SizeHeader");
|
||||
NS_LOG_COMPONENT_DEFINE ("SeqTsSizeHeader");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (E2eStatsHeader);
|
||||
NS_OBJECT_ENSURE_REGISTERED (SeqTsSizeHeader);
|
||||
|
||||
E2eStatsHeader::E2eStatsHeader ()
|
||||
SeqTsSizeHeader::SeqTsSizeHeader ()
|
||||
: SeqTsHeader ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
TypeId
|
||||
E2eStatsHeader::GetTypeId (void)
|
||||
SeqTsSizeHeader::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::SizeHeader")
|
||||
static TypeId tid = TypeId ("ns3::SeqTsSizeHeader")
|
||||
.SetParent<SeqTsHeader> ()
|
||||
.SetGroupName ("Applications")
|
||||
.AddConstructor<E2eStatsHeader> ()
|
||||
.AddConstructor<SeqTsSizeHeader> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
E2eStatsHeader::GetInstanceTypeId (void) const
|
||||
SeqTsSizeHeader::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
void
|
||||
E2eStatsHeader::Print (std::ostream &os) const
|
||||
SeqTsSizeHeader::SetSize (uint64_t size)
|
||||
{
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
SeqTsSizeHeader::GetSize (void) const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void
|
||||
SeqTsSizeHeader::Print (std::ostream &os) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &os);
|
||||
os << "(size=" << m_size << ") AND ";
|
||||
@@ -58,14 +72,13 @@ E2eStatsHeader::Print (std::ostream &os) const
|
||||
}
|
||||
|
||||
uint32_t
|
||||
E2eStatsHeader::GetSerializedSize (void) const
|
||||
SeqTsSizeHeader::GetSerializedSize (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return SeqTsHeader::GetSerializedSize () + 8;
|
||||
}
|
||||
|
||||
void
|
||||
E2eStatsHeader::Serialize (Buffer::Iterator start) const
|
||||
SeqTsSizeHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &start);
|
||||
Buffer::Iterator i = start;
|
||||
@@ -74,7 +87,7 @@ E2eStatsHeader::Serialize (Buffer::Iterator start) const
|
||||
}
|
||||
|
||||
uint32_t
|
||||
E2eStatsHeader::Deserialize (Buffer::Iterator start)
|
||||
SeqTsSizeHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &start);
|
||||
Buffer::Iterator i = start;
|
||||
@@ -1,6 +1,8 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 INRIA
|
||||
* Copyright (c) 2018 Natale Patriciello <natale.patriciello@gmail.com>
|
||||
* (added timestamp and size fields)
|
||||
*
|
||||
* 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
|
||||
@@ -16,7 +18,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef SEQ_TS_SIZE_HEADER_H
|
||||
#define SEQ_TS_SIZE_HEADER_H
|
||||
|
||||
#include <ns3/seq-ts-header.h>
|
||||
|
||||
@@ -25,17 +28,13 @@ 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 adds a size attribute to the sequence number and timestamp
|
||||
* of class \c SeqTsHeader. The size attribute can be used to track
|
||||
* application data units for stream-based sockets such as TCP.
|
||||
*
|
||||
* 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?".
|
||||
* \sa ns3::SeqTsHeader
|
||||
*/
|
||||
class E2eStatsHeader : public SeqTsHeader
|
||||
class SeqTsSizeHeader : public SeqTsHeader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -45,35 +44,21 @@ public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* @brief SizeHeader constructor
|
||||
* \brief constructor
|
||||
*/
|
||||
E2eStatsHeader ();
|
||||
SeqTsSizeHeader ();
|
||||
|
||||
/**
|
||||
* \brief ~SizeHeader
|
||||
*
|
||||
* Nothing much to add here
|
||||
* \brief Set the size information that the header will carry
|
||||
* \param size the size
|
||||
*/
|
||||
virtual ~E2eStatsHeader () override
|
||||
{
|
||||
}
|
||||
void SetSize (uint64_t size);
|
||||
|
||||
/**
|
||||
* @brief Set the size information that the header will carry
|
||||
* @param size the size
|
||||
* \brief Get the size information that the header is carrying
|
||||
* \return 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;
|
||||
}
|
||||
uint64_t GetSize (void) const;
|
||||
|
||||
// Inherited
|
||||
virtual TypeId GetInstanceTypeId (void) const override;
|
||||
@@ -87,3 +72,5 @@ private:
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* SEQ_TS_SIZE_HEADER */
|
||||
233
src/applications/test/bulk-send-application-test-suite.cc
Normal file
233
src/applications/test/bulk-send-application-test-suite.cc
Normal file
@@ -0,0 +1,233 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 Tom Henderson (tomh@tomh.org)
|
||||
*
|
||||
* 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/test.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/node-container.h"
|
||||
#include "ns3/application-container.h"
|
||||
#include "ns3/point-to-point-helper.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/internet-stack-helper.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/ipv4-interface-container.h"
|
||||
#include "ns3/bulk-send-application.h"
|
||||
#include "ns3/bulk-send-helper.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/packet-sink-helper.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
class BulkSendBasicTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
BulkSendBasicTestCase ();
|
||||
virtual ~BulkSendBasicTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
void SendTx (Ptr<const Packet> p);
|
||||
void ReceiveRx (Ptr<const Packet> p, const Address& addr);
|
||||
uint64_t m_sent {0};
|
||||
uint64_t m_received {0};
|
||||
};
|
||||
|
||||
BulkSendBasicTestCase::BulkSendBasicTestCase ()
|
||||
: TestCase ("Check a basic 300KB transfer")
|
||||
{
|
||||
}
|
||||
|
||||
BulkSendBasicTestCase::~BulkSendBasicTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BulkSendBasicTestCase::SendTx (Ptr<const Packet> p)
|
||||
{
|
||||
m_sent += p->GetSize ();
|
||||
}
|
||||
|
||||
void
|
||||
BulkSendBasicTestCase::ReceiveRx (Ptr<const Packet> p, const Address& addr)
|
||||
{
|
||||
m_received += p->GetSize ();
|
||||
}
|
||||
|
||||
void
|
||||
BulkSendBasicTestCase::DoRun (void)
|
||||
{
|
||||
Ptr<Node> sender = CreateObject<Node> ();
|
||||
Ptr<Node> receiver = CreateObject<Node> ();
|
||||
NodeContainer nodes;
|
||||
nodes.Add (sender);
|
||||
nodes.Add (receiver);
|
||||
PointToPointHelper p2pHelper;
|
||||
p2pHelper.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2pHelper.SetChannelAttribute ("Delay", StringValue ("10ms"));
|
||||
NetDeviceContainer devices;
|
||||
devices = p2pHelper.Install (nodes);
|
||||
InternetStackHelper internet;
|
||||
internet.Install (nodes);
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i = ipv4.Assign (devices);
|
||||
uint16_t port = 9;
|
||||
BulkSendHelper sourceHelper ("ns3::TcpSocketFactory",
|
||||
InetSocketAddress (i.GetAddress (1), port));
|
||||
sourceHelper.SetAttribute ("MaxBytes", UintegerValue (300000));
|
||||
ApplicationContainer sourceApp = sourceHelper.Install (nodes.Get (0));
|
||||
sourceApp.Start (Seconds (0.0));
|
||||
sourceApp.Stop (Seconds (10.0));
|
||||
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (nodes.Get (1));
|
||||
sinkApp.Start (Seconds (0.0));
|
||||
sinkApp.Stop (Seconds (10.0));
|
||||
|
||||
Ptr<BulkSendApplication> source = DynamicCast<BulkSendApplication> (sourceApp.Get (0));
|
||||
Ptr<PacketSink> sink = DynamicCast<PacketSink> (sinkApp.Get (0));
|
||||
|
||||
source->TraceConnectWithoutContext ("Tx", MakeCallback (&BulkSendBasicTestCase::SendTx, this));
|
||||
sink->TraceConnectWithoutContext ("Rx", MakeCallback (&BulkSendBasicTestCase::ReceiveRx, this));
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_sent, 300000, "Sent the full 300000 bytes");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_received, 300000, "Received the full 300000 bytes");
|
||||
}
|
||||
|
||||
// This test checks that the sequence number is sent and received in sequence
|
||||
// despite the sending application having to pause and restart its sending
|
||||
// due to a temporarily full transmit buffer.
|
||||
class BulkSendSeqTsSizeTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
BulkSendSeqTsSizeTestCase ();
|
||||
virtual ~BulkSendSeqTsSizeTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
void SendTx (Ptr<const Packet> p, const Address &from, const Address & to, const SeqTsSizeHeader &header);
|
||||
void ReceiveRx (Ptr<const Packet> p, const Address &from, const Address & to, const SeqTsSizeHeader &header);
|
||||
uint64_t m_sent {0};
|
||||
uint64_t m_received {0};
|
||||
uint64_t m_seqTxCounter {0};
|
||||
uint64_t m_seqRxCounter {0};
|
||||
Time m_lastTxTs {Seconds (0)};
|
||||
Time m_lastRxTs {Seconds (0)};
|
||||
};
|
||||
|
||||
BulkSendSeqTsSizeTestCase::BulkSendSeqTsSizeTestCase ()
|
||||
: TestCase ("Check a 300KB transfer with SeqTsSize header enabled")
|
||||
{
|
||||
}
|
||||
|
||||
BulkSendSeqTsSizeTestCase::~BulkSendSeqTsSizeTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BulkSendSeqTsSizeTestCase::SendTx (Ptr<const Packet> p, const Address &from, const Address & to, const SeqTsSizeHeader &header)
|
||||
{
|
||||
// The header is not serialized onto the packet in this trace
|
||||
m_sent += p->GetSize () + header.GetSerializedSize ();
|
||||
NS_TEST_ASSERT_MSG_EQ (header.GetSeq (), m_seqTxCounter, "Missing sequence number");
|
||||
m_seqTxCounter++;
|
||||
NS_TEST_ASSERT_MSG_GT_OR_EQ (header.GetTs (), m_lastTxTs, "Timestamp less than last time");
|
||||
m_lastTxTs = header.GetTs ();
|
||||
}
|
||||
|
||||
void
|
||||
BulkSendSeqTsSizeTestCase::ReceiveRx (Ptr<const Packet> p, const Address &from, const Address & to, const SeqTsSizeHeader &header)
|
||||
{
|
||||
// The header is not serialized onto the packet in this trace
|
||||
m_received += p->GetSize () + header.GetSerializedSize ();
|
||||
NS_TEST_ASSERT_MSG_EQ (header.GetSeq (), m_seqRxCounter, "Missing sequence number");
|
||||
m_seqRxCounter++;
|
||||
NS_TEST_ASSERT_MSG_GT_OR_EQ (header.GetTs (), m_lastRxTs, "Timestamp less than last time");
|
||||
m_lastRxTs = header.GetTs ();
|
||||
}
|
||||
|
||||
void
|
||||
BulkSendSeqTsSizeTestCase::DoRun (void)
|
||||
{
|
||||
Ptr<Node> sender = CreateObject<Node> ();
|
||||
Ptr<Node> receiver = CreateObject<Node> ();
|
||||
NodeContainer nodes;
|
||||
nodes.Add (sender);
|
||||
nodes.Add (receiver);
|
||||
PointToPointHelper p2pHelper;
|
||||
p2pHelper.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
p2pHelper.SetChannelAttribute ("Delay", StringValue ("10ms"));
|
||||
NetDeviceContainer devices;
|
||||
devices = p2pHelper.Install (nodes);
|
||||
InternetStackHelper internet;
|
||||
internet.Install (nodes);
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i = ipv4.Assign (devices);
|
||||
uint16_t port = 9;
|
||||
BulkSendHelper sourceHelper ("ns3::TcpSocketFactory",
|
||||
InetSocketAddress (i.GetAddress (1), port));
|
||||
sourceHelper.SetAttribute ("MaxBytes", UintegerValue (300000));
|
||||
sourceHelper.SetAttribute ("EnableSeqTsSizeHeader", BooleanValue (true));
|
||||
ApplicationContainer sourceApp = sourceHelper.Install (nodes.Get (0));
|
||||
sourceApp.Start (Seconds (0.0));
|
||||
sourceApp.Stop (Seconds (10.0));
|
||||
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
sinkHelper.SetAttribute ("EnableSeqTsSizeHeader", BooleanValue (true));
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (nodes.Get (1));
|
||||
sinkApp.Start (Seconds (0.0));
|
||||
sinkApp.Stop (Seconds (10.0));
|
||||
|
||||
Ptr<BulkSendApplication> source = DynamicCast<BulkSendApplication> (sourceApp.Get (0));
|
||||
Ptr<PacketSink> sink = DynamicCast<PacketSink> (sinkApp.Get (0));
|
||||
|
||||
source->TraceConnectWithoutContext ("TxWithSeqTsSize", MakeCallback (&BulkSendSeqTsSizeTestCase::SendTx, this));
|
||||
sink->TraceConnectWithoutContext ("RxWithSeqTsSize", MakeCallback (&BulkSendSeqTsSizeTestCase::ReceiveRx, this));
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_sent, 300000, "Sent the full 300000 bytes");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_received, 300000, "Received the full 300000 bytes");
|
||||
}
|
||||
|
||||
class BulkSendTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
BulkSendTestSuite ();
|
||||
};
|
||||
|
||||
BulkSendTestSuite::BulkSendTestSuite ()
|
||||
: TestSuite ("bulk-send-application", UNIT)
|
||||
{
|
||||
AddTestCase (new BulkSendBasicTestCase, TestCase::QUICK);
|
||||
AddTestCase (new BulkSendSeqTsSizeTestCase, TestCase::QUICK);
|
||||
}
|
||||
|
||||
static BulkSendTestSuite g_bulkSendTestSuite;
|
||||
|
||||
@@ -31,6 +31,7 @@ def build(bld):
|
||||
applications_test = bld.create_ns3_module_test_library('applications')
|
||||
applications_test.source = [
|
||||
'test/three-gpp-http-client-server-test.cc',
|
||||
'test/bulk-send-application-test-suite.cc',
|
||||
'test/udp-client-server-test.cc'
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user