Westwood and Westwood+
This commit is contained in:
@@ -13,6 +13,7 @@ cpp_examples = [
|
||||
("tcp-nsc-lfn", "NSC_ENABLED == True", "False"),
|
||||
("tcp-nsc-zoo", "NSC_ENABLED == True", "False"),
|
||||
("tcp-star-server", "True", "True"),
|
||||
("tcp-variants-comparison", "True", "True"),
|
||||
]
|
||||
|
||||
# A list of Python examples to run in order to ensure that they remain
|
||||
|
||||
360
examples/tcp/tcp-variants-comparison.cc
Normal file
360
examples/tcp/tcp-variants-comparison.cc
Normal file
@@ -0,0 +1,360 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2013 ResiliNets, ITTC, University of Kansas
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Justin P. Rohrer, Truc Anh N. Nguyen <annguyen@ittc.ku.edu>, Siddharth Gangadhar <siddharth@ittc.ku.edu>
|
||||
*
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* Information and Telecommunication Technology Center (ITTC)
|
||||
* and Department of Electrical Engineering and Computer Science
|
||||
* The University of Kansas Lawrence, KS USA.
|
||||
*
|
||||
* Work supported in part by NSF FIND (Future Internet Design) Program
|
||||
* under grant CNS-0626918 (Postmodern Internet Architecture),
|
||||
* NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
|
||||
* US Department of Defense (DoD), and ITTC at The University of Kansas.
|
||||
*
|
||||
* “TCP Westwood(+) Protocol Implementation in ns-3”
|
||||
* Siddharth Gangadhar, Trúc Anh Ngọc Nguyễn , Greeshma Umapathi, and James P.G. Sterbenz,
|
||||
* ICST SIMUTools Workshop on ns-3 (WNS3), Cannes, France, March 2013
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/tcp-header.h"
|
||||
#include "ns3/udp-header.h"
|
||||
#include "ns3/enum.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/flow-monitor-helper.h"
|
||||
#include "ns3/ipv4-global-routing-helper.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpVariantsComparison");
|
||||
|
||||
double old_time = 0.0;
|
||||
EventId output;
|
||||
Time current = Time::FromInteger(3, Time::S); //Only record cwnd and ssthresh values every 3 seconds
|
||||
bool first = true;
|
||||
|
||||
static void
|
||||
OutputTrace ()
|
||||
{
|
||||
// *stream->GetStream() << newtime << " " << newval << std::endl;
|
||||
// old_time = newval;
|
||||
}
|
||||
|
||||
static void
|
||||
CwndTracer (Ptr<OutputStreamWrapper>stream, uint32_t oldval, uint32_t newval)
|
||||
{
|
||||
double new_time = Simulator::Now().GetSeconds();
|
||||
if (old_time == 0 && first)
|
||||
{
|
||||
double mycurrent = current.GetSeconds();
|
||||
*stream->GetStream() << new_time << " " << mycurrent << " " << newval << std::endl;
|
||||
first = false;
|
||||
output = Simulator::Schedule(current,&OutputTrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output.IsExpired())
|
||||
{
|
||||
*stream->GetStream() << new_time << " " << newval << std::endl;
|
||||
output.Cancel();
|
||||
output = Simulator::Schedule(current,&OutputTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SsThreshTracer (Ptr<OutputStreamWrapper>stream, uint32_t oldval, uint32_t newval)
|
||||
{
|
||||
double new_time = Simulator::Now().GetSeconds();
|
||||
if (old_time == 0 && first)
|
||||
{
|
||||
double mycurrent = current.GetSeconds();
|
||||
*stream->GetStream() << new_time << " " << mycurrent << " " << newval << std::endl;
|
||||
first = false;
|
||||
output = Simulator::Schedule(current,&OutputTrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output.IsExpired())
|
||||
{
|
||||
*stream->GetStream() << new_time << " " << newval << std::endl;
|
||||
output.Cancel();
|
||||
output = Simulator::Schedule(current,&OutputTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
TraceCwnd (std::string cwnd_tr_file_name)
|
||||
{
|
||||
AsciiTraceHelper ascii;
|
||||
if (cwnd_tr_file_name.compare("") == 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("No trace file for cwnd provided");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream(cwnd_tr_file_name.c_str());
|
||||
Config::ConnectWithoutContext ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",MakeBoundCallback (&CwndTracer, stream));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
TraceSsThresh(std::string ssthresh_tr_file_name)
|
||||
{
|
||||
AsciiTraceHelper ascii;
|
||||
if (ssthresh_tr_file_name.compare("") == 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("No trace file for ssthresh provided");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream(ssthresh_tr_file_name.c_str());
|
||||
Config::ConnectWithoutContext ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/SlowStartThreshold",MakeBoundCallback (&SsThreshTracer, stream));
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
std::string transport_prot = "TcpWestwood";
|
||||
double error_p = 0.0;
|
||||
std::string bandwidth = "2Mbps";
|
||||
std::string access_bandwidth = "10Mbps";
|
||||
std::string access_delay = "45ms";
|
||||
bool tracing = false;
|
||||
std::string tr_file_name = "";
|
||||
std::string cwnd_tr_file_name = "";
|
||||
std::string ssthresh_tr_file_name = "";
|
||||
double data_mbytes = 0;
|
||||
uint32_t mtu_bytes = 400;
|
||||
uint16_t num_flows = 1;
|
||||
float duration = 100;
|
||||
uint32_t run = 0;
|
||||
bool flow_monitor = true;
|
||||
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue("transport_prot", "Transport protocol to use: TcpTahoe, TcpReno, TcpNewReno, TcpWestwood, TcpWestwoodPlus ", transport_prot);
|
||||
cmd.AddValue("error_p", "Packet error rate", error_p);
|
||||
cmd.AddValue("bandwidth", "Bottleneck bandwidth", bandwidth);
|
||||
cmd.AddValue("access_bandwidth", "Access link bandwidth", access_bandwidth);
|
||||
cmd.AddValue("delay", "Access link delay", access_delay);
|
||||
cmd.AddValue("tracing", "Flag to enable/disable tracing", tracing);
|
||||
cmd.AddValue("tr_name", "Name of output trace file", tr_file_name);
|
||||
cmd.AddValue("cwnd_tr_name", "Name of output trace file", cwnd_tr_file_name);
|
||||
cmd.AddValue("ssthresh_tr_name", "Name of output trace file", ssthresh_tr_file_name);
|
||||
cmd.AddValue("data", "Number of Megabytes of data to transmit", data_mbytes);
|
||||
cmd.AddValue("mtu", "Size of IP packets to send in bytes", mtu_bytes);
|
||||
cmd.AddValue("num_flows", "Number of flows", num_flows);
|
||||
cmd.AddValue("duration", "Time to allow flows to run in seconds", duration);
|
||||
cmd.AddValue("run", "Run index (for setting repeatable seeds)", run);
|
||||
cmd.AddValue("flow_monitor", "Enable flow monitor", flow_monitor);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
SeedManager::SetSeed(1);
|
||||
SeedManager::SetRun(run);
|
||||
|
||||
// User may find it convenient to enable logging
|
||||
//LogComponentEnable("TcpVariantsComparison", LOG_LEVEL_ALL);
|
||||
//LogComponentEnable("BulkSendApplication", LOG_LEVEL_INFO);
|
||||
//LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL);
|
||||
|
||||
// Calculate the ADU size
|
||||
Header* temp_header = new Ipv4Header();
|
||||
uint32_t ip_header = temp_header->GetSerializedSize();
|
||||
NS_LOG_LOGIC ("IP Header size is: " << ip_header);
|
||||
delete temp_header;
|
||||
temp_header = new TcpHeader();
|
||||
uint32_t tcp_header = temp_header->GetSerializedSize();
|
||||
NS_LOG_LOGIC ("TCP Header size is: " << tcp_header);
|
||||
delete temp_header;
|
||||
uint32_t tcp_adu_size = mtu_bytes - (ip_header + tcp_header);
|
||||
NS_LOG_LOGIC ("TCP ADU size is: " << tcp_adu_size);
|
||||
|
||||
// Set the simulation start and stop time
|
||||
float start_time = 0.1;
|
||||
float stop_time = start_time + duration;
|
||||
|
||||
// Select TCP variant
|
||||
if (transport_prot.compare("TcpTahoe") == 0)
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpTahoe::GetTypeId()));
|
||||
else if (transport_prot.compare("TcpReno") == 0)
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpReno::GetTypeId()));
|
||||
else if (transport_prot.compare("TcpNewReno") == 0)
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpNewReno::GetTypeId()));
|
||||
else if (transport_prot.compare("TcpWestwood") == 0)
|
||||
{// the default protocol type in ns3::TcpWestwood is WESTWOOD
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpWestwood::GetTypeId()));
|
||||
Config::SetDefault("ns3::TcpWestwood::FilterType", EnumValue(TcpWestwood::TUSTIN));
|
||||
}
|
||||
else if (transport_prot.compare("TcpWestwoodPlus") == 0)
|
||||
{
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpWestwood::GetTypeId()));
|
||||
Config::SetDefault("ns3::TcpWestwood::ProtocolType", EnumValue(TcpWestwood::WESTWOODPLUS));
|
||||
Config::SetDefault("ns3::TcpWestwood::FilterType", EnumValue(TcpWestwood::TUSTIN));
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Invalid TCP version");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
// Create gateways, sources, and sinks
|
||||
NodeContainer gateways;
|
||||
gateways.Create (1);
|
||||
NodeContainer sources;
|
||||
sources.Create(num_flows);
|
||||
NodeContainer sinks;
|
||||
sinks.Create(num_flows);
|
||||
|
||||
// Configure the error model
|
||||
// Here we use RateErrorModel with packet error rate
|
||||
Ptr<UniformRandomVariable> uv = CreateObject<UniformRandomVariable>();
|
||||
uv->SetStream (50);
|
||||
RateErrorModel error_model;
|
||||
error_model.SetRandomVariable(uv);
|
||||
error_model.SetUnit(RateErrorModel::ERROR_UNIT_PACKET);
|
||||
error_model.SetRate(error_p);
|
||||
|
||||
PointToPointHelper UnReLink;
|
||||
UnReLink.SetDeviceAttribute ("DataRate", StringValue (bandwidth));
|
||||
UnReLink.SetChannelAttribute ("Delay", StringValue ("0.01ms"));
|
||||
UnReLink.SetDeviceAttribute ("ReceiveErrorModel", PointerValue (&error_model));
|
||||
|
||||
|
||||
InternetStackHelper stack;
|
||||
stack.InstallAll ();
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase ("10.0.0.0", "255.255.255.0");
|
||||
|
||||
// Configure the sources and sinks net devices
|
||||
// and the channels between the sources/sinks and the gateways
|
||||
PointToPointHelper LocalLink;
|
||||
LocalLink.SetDeviceAttribute ("DataRate", StringValue (access_bandwidth));
|
||||
LocalLink.SetChannelAttribute ("Delay", StringValue (access_delay));
|
||||
Ipv4InterfaceContainer sink_interfaces;
|
||||
for (int i=0; i<num_flows; i++)
|
||||
{
|
||||
NetDeviceContainer devices;
|
||||
devices = LocalLink.Install(sources.Get(i), gateways.Get(0));
|
||||
address.NewNetwork();
|
||||
Ipv4InterfaceContainer interfaces = address.Assign (devices);
|
||||
devices = UnReLink.Install(gateways.Get(0), sinks.Get(i));
|
||||
address.NewNetwork();
|
||||
interfaces = address.Assign (devices);
|
||||
sink_interfaces.Add(interfaces.Get(1));
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Initialize Global Routing.");
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
|
||||
uint16_t port = 50000;
|
||||
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
|
||||
for(uint16_t i=0; i<sources.GetN(); i++)
|
||||
{
|
||||
AddressValue remoteAddress (InetSocketAddress (sink_interfaces.GetAddress(i, 0), port));
|
||||
|
||||
if (transport_prot.compare("TcpTahoe") == 0
|
||||
|| transport_prot.compare("TcpReno") == 0
|
||||
|| transport_prot.compare("TcpNewReno") == 0
|
||||
|| transport_prot.compare("TcpWestwood") == 0
|
||||
|| transport_prot.compare("TcpWestwoodPlus") == 0)
|
||||
{
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (tcp_adu_size));
|
||||
BulkSendHelper ftp("ns3::TcpSocketFactory", Address());
|
||||
ftp.SetAttribute ("Remote", remoteAddress);
|
||||
ftp.SetAttribute ("SendSize", UintegerValue (tcp_adu_size));
|
||||
ftp.SetAttribute ("MaxBytes", UintegerValue (int(data_mbytes*1000000)));
|
||||
|
||||
ApplicationContainer sourceApp = ftp.Install (sources.Get(i));
|
||||
sourceApp.Start (Seconds (start_time*i));
|
||||
sourceApp.Stop (Seconds (stop_time - 3));
|
||||
Time check_start (Seconds((start_time*i)+3));
|
||||
|
||||
sinkHelper.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (sinks);
|
||||
sinkApp.Start (Seconds (start_time*i));
|
||||
sinkApp.Stop (Seconds (stop_time));
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Invalid transport protocol " << transport_prot << " specified");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up tracing if enabled
|
||||
if (tracing)
|
||||
{
|
||||
std::ofstream ascii;
|
||||
Ptr<OutputStreamWrapper> ascii_wrap;
|
||||
if (tr_file_name.compare("") == 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("No trace file provided");
|
||||
exit (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ascii.open (tr_file_name.c_str());
|
||||
ascii_wrap = new OutputStreamWrapper(tr_file_name.c_str(), std::ios::out);
|
||||
}
|
||||
|
||||
stack.EnableAsciiIpv4All (ascii_wrap);
|
||||
|
||||
Simulator::Schedule(Seconds(0.00001), &TraceCwnd, cwnd_tr_file_name);
|
||||
Simulator::Schedule(Seconds(0.00001), &TraceSsThresh, ssthresh_tr_file_name);
|
||||
}
|
||||
|
||||
UnReLink.EnablePcapAll("TcpVariantsComparison", true);
|
||||
LocalLink.EnablePcapAll("TcpVariantsComparison", true);
|
||||
|
||||
// Flow monitor
|
||||
Ptr<FlowMonitor> flowMonitor;
|
||||
if (flow_monitor)
|
||||
{
|
||||
FlowMonitorHelper flowHelper;
|
||||
flowMonitor = flowHelper.InstallAll();
|
||||
}
|
||||
|
||||
Simulator::Stop (Seconds(stop_time));
|
||||
Simulator::Run ();
|
||||
|
||||
if (flow_monitor)
|
||||
{
|
||||
flowMonitor->SerializeToXmlFile("TcpVariantsComparison.flowmonitor", true, true);
|
||||
}
|
||||
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
@@ -26,6 +26,12 @@ def build(bld):
|
||||
obj.source = 'tcp-bulk-send.cc'
|
||||
|
||||
obj = bld.create_ns3_program('tcp-nsc-comparison',
|
||||
['point-to-point', 'internet', 'applications', 'flow-monitor'])
|
||||
['point-to-point', 'internet', 'applications'])
|
||||
|
||||
obj.source = 'tcp-nsc-comparison.cc'
|
||||
|
||||
obj = bld.create_ns3_program('tcp-variants-comparison',
|
||||
['point-to-point', 'internet', 'applications', 'flow-monitor'])
|
||||
|
||||
obj.source = 'tcp-variants-comparison.cc'
|
||||
|
||||
|
||||
419
src/internet/model/tcp-westwood.cc
Normal file
419
src/internet/model/tcp-westwood.cc
Normal file
@@ -0,0 +1,419 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2013 ResiliNets, ITTC, University of Kansas
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Siddharth Gangadhar <siddharth@ittc.ku.edu>, Truc Anh N. Nguyen <annguyen@ittc.ku.edu>,
|
||||
* and Greeshma Umapathi
|
||||
*
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* Information and Telecommunication Technology Center (ITTC)
|
||||
* and Department of Electrical Engineering and Computer Science
|
||||
* The University of Kansas Lawrence, KS USA.
|
||||
*
|
||||
* Work supported in part by NSF FIND (Future Internet Design) Program
|
||||
* under grant CNS-0626918 (Postmodern Internet Architecture),
|
||||
* NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
|
||||
* US Department of Defense (DoD), and ITTC at The University of Kansas.
|
||||
*/
|
||||
|
||||
#define NS_LOG_APPEND_CONTEXT \
|
||||
if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
|
||||
|
||||
#include "tcp-westwood.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/sequence-number.h"
|
||||
#include "rtt-estimator.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("TcpWestwood");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(TcpWestwood);
|
||||
|
||||
TypeId
|
||||
TcpWestwood::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId("ns3::TcpWestwood")
|
||||
.SetParent<TcpSocketBase>()
|
||||
.AddConstructor<TcpWestwood>()
|
||||
.AddTraceSource("CongestionWindow", "The TCP connection's congestion window",
|
||||
MakeTraceSourceAccessor(&TcpWestwood::m_cWnd))
|
||||
.AddAttribute("FilterType", "Use this to choose no filter or Tustin's approximation filter",
|
||||
EnumValue(TcpWestwood::TUSTIN), MakeEnumAccessor(&TcpWestwood::m_fType),
|
||||
MakeEnumChecker(TcpWestwood::NONE, "None", TcpWestwood::TUSTIN, "Tustin"))
|
||||
.AddAttribute("ProtocolType", "Use this to let the code run as Westwood or WestwoodPlus",
|
||||
EnumValue(TcpWestwood::WESTWOOD),
|
||||
MakeEnumAccessor(&TcpWestwood::m_pType),
|
||||
MakeEnumChecker(TcpWestwood::WESTWOOD, "Westwood",TcpWestwood::WESTWOODPLUS, "WestwoodPlus"))
|
||||
.AddTraceSource("EstimatedBW", "The estimated bandwidth",
|
||||
MakeTraceSourceAccessor(&TcpWestwood::m_currentBW));
|
||||
return tid;
|
||||
}
|
||||
|
||||
TcpWestwood::TcpWestwood (void) :
|
||||
m_inFastRec(false),
|
||||
m_currentBW(0),
|
||||
m_lastSampleBW(0),
|
||||
m_lastBW(0),
|
||||
m_minRtt(0),
|
||||
m_lastAck(0),
|
||||
m_prevAckNo(0),
|
||||
m_accountedFor(0),
|
||||
m_ackedSegments(0),
|
||||
m_IsCount(false)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
TcpWestwood::TcpWestwood (const TcpWestwood& sock) :
|
||||
TcpSocketBase(sock),
|
||||
m_cWnd(sock.m_cWnd),
|
||||
m_ssThresh(sock.m_ssThresh),
|
||||
m_initialCWnd(sock.m_initialCWnd),
|
||||
m_inFastRec(false),
|
||||
m_currentBW(sock.m_currentBW),
|
||||
m_lastSampleBW(sock.m_lastSampleBW),
|
||||
m_lastBW(sock.m_lastBW),
|
||||
m_minRtt(sock.m_minRtt),
|
||||
m_lastAck(sock.m_lastAck),
|
||||
m_prevAckNo(sock.m_prevAckNo),
|
||||
m_accountedFor(sock.m_accountedFor)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_LOGIC ("Invoked the copy constructor");
|
||||
NS_LOG_INFO ("m_minRtt at copy constructor" << m_minRtt);
|
||||
}
|
||||
|
||||
TcpWestwood::~TcpWestwood (void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
TcpWestwood::Listen (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
InitializeCwnd();
|
||||
return TcpSocketBase::Listen();
|
||||
}
|
||||
|
||||
int
|
||||
TcpWestwood::Connect (const Address & address)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << address);
|
||||
InitializeCwnd();
|
||||
return TcpSocketBase::Connect(address);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpWestwood::Window (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return std::min (m_rWnd.Get (), m_cWnd.Get ());
|
||||
}
|
||||
|
||||
Ptr<TcpSocketBase>
|
||||
TcpWestwood::Fork (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return CopyObject<TcpWestwood>(this);
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::NewAck (const SequenceNumber32& seq)
|
||||
{ // Same as Reno
|
||||
NS_LOG_FUNCTION (this << seq);
|
||||
NS_LOG_LOGIC ("TcpWestwood receieved ACK for seq " << seq <<
|
||||
" cwnd " << m_cWnd <<
|
||||
" ssthresh " << m_ssThresh);
|
||||
|
||||
// Check for exit condition of fast recovery
|
||||
if (m_inFastRec)
|
||||
{// First new ACK after fast recovery, reset cwnd as in Reno
|
||||
m_cWnd = m_ssThresh;
|
||||
m_inFastRec = false;
|
||||
NS_LOG_INFO ("Reset cwnd to " << m_cWnd);
|
||||
};
|
||||
|
||||
// Increase of cwnd based on current phase (slow start or congestion avoidance)
|
||||
if (m_cWnd < m_ssThresh)
|
||||
{ // Slow start mode, add one segSize to cWnd as in Reno
|
||||
m_cWnd += m_segmentSize;
|
||||
NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
|
||||
}
|
||||
else
|
||||
{ // Congestion avoidance mode, increase by (segSize*segSize)/cwnd as in Reno
|
||||
double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get();
|
||||
adder = std::max(1.0, adder);
|
||||
m_cWnd += static_cast<uint32_t>(adder);
|
||||
NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
|
||||
}
|
||||
|
||||
// Complete newAck processing
|
||||
TcpSocketBase::NewAck(seq);
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
int acked = 0;
|
||||
if ((0 != (tcpHeader.GetFlags () & TcpHeader::ACK)) && tcpHeader.GetAckNumber() >= m_prevAckNo)
|
||||
{// It is a duplicate ACK or a new ACK. Old ACK is ignored.
|
||||
if (m_pType == TcpWestwood::WESTWOOD)
|
||||
{// For Westwood, calculate the number of ACKed segments and estimate the BW
|
||||
acked = CountAck (tcpHeader);
|
||||
EstimateBW (acked, tcpHeader, Time(0));
|
||||
}
|
||||
else if (m_pType == TcpWestwood::WESTWOODPLUS)
|
||||
{// For Weswood+, calculate the number of ACKed segments and update m_ackedSegments
|
||||
if (m_IsCount)
|
||||
{
|
||||
acked = CountAck (tcpHeader);
|
||||
UpdateAckedSegments (acked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TcpSocketBase::ReceivedAck (packet, tcpHeader);
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::EstimateBW (int acked, const TcpHeader& tcpHeader, Time rtt)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_pType == TcpWestwood::WESTWOOD)
|
||||
{
|
||||
// Get the time when the current ACK is received
|
||||
double currentAck = static_cast<double> (Simulator::Now().GetSeconds());
|
||||
// Calculate the BW
|
||||
m_currentBW = acked * m_segmentSize / (currentAck - m_lastAck);
|
||||
// Update the last ACK time
|
||||
m_lastAck = currentAck;
|
||||
}
|
||||
else if (m_pType == TcpWestwood::WESTWOODPLUS)
|
||||
{
|
||||
// Calculate the BW
|
||||
m_currentBW = m_ackedSegments * m_segmentSize / rtt.GetSeconds();
|
||||
// Reset m_ackedSegments and m_IsCount for the next sampling
|
||||
m_ackedSegments = 0;
|
||||
m_IsCount = false;
|
||||
}
|
||||
|
||||
// Filter the BW sample
|
||||
Filtering();
|
||||
}
|
||||
|
||||
int
|
||||
TcpWestwood::CountAck (const TcpHeader& tcpHeader)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Calculate the number of acknowledged segments based on the received ACK number
|
||||
int cumul_ack = (tcpHeader.GetAckNumber() - m_prevAckNo) / m_segmentSize;
|
||||
|
||||
if (cumul_ack == 0)
|
||||
{// A DUPACK counts for 1 segment delivered successfully
|
||||
m_accountedFor++;
|
||||
cumul_ack = 1;
|
||||
}
|
||||
if (cumul_ack > 1)
|
||||
{// A delayed ACK or a cumulative ACK after a retransmission
|
||||
// Check how much new data it ACKs
|
||||
if (m_accountedFor >= cumul_ack)
|
||||
{
|
||||
m_accountedFor -= cumul_ack;
|
||||
cumul_ack = 1;
|
||||
}
|
||||
else if (m_accountedFor < cumul_ack)
|
||||
{
|
||||
cumul_ack -= m_accountedFor;
|
||||
m_accountedFor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the previous ACK number
|
||||
m_prevAckNo = tcpHeader.GetAckNumber();
|
||||
|
||||
return cumul_ack;
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::UpdateAckedSegments (int acked)
|
||||
{
|
||||
m_ackedSegments += acked;
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::DupAck (const TcpHeader& header, uint32_t count)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << count << m_cWnd);
|
||||
|
||||
if (count == 3 && !m_inFastRec)
|
||||
{// Triple duplicate ACK triggers fast retransmit
|
||||
// Adjust cwnd and ssthresh based on the estimated BW
|
||||
m_ssThresh = m_currentBW * static_cast<double> (m_minRtt.GetSeconds());
|
||||
if (m_cWnd > m_ssThresh)
|
||||
{
|
||||
m_cWnd = m_ssThresh;
|
||||
}
|
||||
m_inFastRec = true;
|
||||
NS_LOG_INFO ("Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd <<", ssthresh to " << m_ssThresh);
|
||||
DoRetransmit ();
|
||||
}
|
||||
else if (m_inFastRec)
|
||||
{// Increase cwnd for every additional DUPACK as in Reno
|
||||
m_cWnd += m_segmentSize;
|
||||
NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd);
|
||||
SendPendingData (m_connected);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::Retransmit (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
|
||||
m_inFastRec = false;
|
||||
|
||||
// If erroneous timeout in closed/timed-wait state, just return
|
||||
if (m_state == CLOSED || m_state == TIME_WAIT)
|
||||
return;
|
||||
// If all data are received, just return
|
||||
if (m_txBuffer.HeadSequence() >= m_nextTxSequence)
|
||||
return;
|
||||
|
||||
// Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
|
||||
m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get() * static_cast<double> (m_minRtt.GetSeconds()));
|
||||
m_cWnd = m_segmentSize;
|
||||
|
||||
// Restart from highest ACK
|
||||
m_nextTxSequence = m_txBuffer.HeadSequence();
|
||||
NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
|
||||
", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
|
||||
|
||||
// Double the next RTO
|
||||
m_rtt->IncreaseMultiplier();
|
||||
|
||||
// Retransmit the packet
|
||||
DoRetransmit();
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::EstimateRtt (const TcpHeader& tcpHeader)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
// Calculate m_lastRtt
|
||||
TcpSocketBase::EstimateRtt (tcpHeader);
|
||||
|
||||
// Update minRtt
|
||||
if (m_minRtt == 0)
|
||||
{
|
||||
m_minRtt = m_lastRtt;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_lastRtt < m_minRtt)
|
||||
{
|
||||
m_minRtt = m_lastRtt;
|
||||
}
|
||||
}
|
||||
|
||||
// For Westwood+, start running a clock on the currently estimated RTT if possible
|
||||
// to trigger a new BW sampling event
|
||||
if (m_pType == TcpWestwood::WESTWOODPLUS)
|
||||
{
|
||||
if(m_lastRtt != 0 && m_state == ESTABLISHED && !m_IsCount)
|
||||
{
|
||||
m_IsCount = true;
|
||||
m_bwEstimateEvent.Cancel();
|
||||
m_bwEstimateEvent = Simulator::Schedule (m_lastRtt, &TcpWestwood::EstimateBW,this,m_ackedSegments,tcpHeader,m_lastRtt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::Filtering ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
double alpha = 0.9;
|
||||
|
||||
if (m_fType == TcpWestwood::NONE)
|
||||
{
|
||||
}
|
||||
else if (m_fType == TcpWestwood::TUSTIN)
|
||||
{
|
||||
double sample_bwe = m_currentBW;
|
||||
m_currentBW = (alpha * m_lastBW) + ((1 - alpha) * ((sample_bwe + m_lastSampleBW) / 2));
|
||||
m_lastSampleBW = sample_bwe;
|
||||
m_lastBW = m_currentBW;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::SetSegSize (uint32_t size)
|
||||
{
|
||||
NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetSegSize() cannot change segment size after connection started.");
|
||||
m_segmentSize = size;
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::SetSSThresh (uint32_t threshold)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_ssThresh = threshold;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpWestwood::GetSSThresh (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_ssThresh;
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::SetInitialCwnd (uint32_t cwnd)
|
||||
{
|
||||
NS_ABORT_MSG_UNLESS(m_state == CLOSED, "TcpWestwood::SetInitialCwnd() cannot change initial cwnd after connection started.");
|
||||
m_initialCWnd = cwnd;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpWestwood::GetInitialCwnd (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_initialCWnd;
|
||||
}
|
||||
|
||||
void
|
||||
TcpWestwood::InitializeCwnd(void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
/*
|
||||
* Initialize congestion window, default to 1 MSS (RFC2001, sec.1) and must
|
||||
* not be larger than 2 MSS (RFC2581, sec.3.1). Both m_initiaCWnd and
|
||||
* m_segmentSize are set by the attribute system in ns3::TcpSocket.
|
||||
*/
|
||||
m_cWnd = m_initialCWnd * m_segmentSize;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
222
src/internet/model/tcp-westwood.h
Normal file
222
src/internet/model/tcp-westwood.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2013 ResiliNets, ITTC, University of Kansas
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Siddharth Gangadhar <siddharth@ittc.ku.edu>, Truc Anh N. Nguyen <annguyen@ittc.ku.edu>,
|
||||
* and Greeshma Umapathi
|
||||
*
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* Information and Telecommunication Technology Center (ITTC)
|
||||
* and Department of Electrical Engineering and Computer Science
|
||||
* The University of Kansas Lawrence, KS USA.
|
||||
*
|
||||
* Work supported in part by NSF FIND (Future Internet Design) Program
|
||||
* under grant CNS-0626918 (Postmodern Internet Architecture),
|
||||
* NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
|
||||
* US Department of Defense (DoD), and ITTC at The University of Kansas.
|
||||
*/
|
||||
|
||||
#ifndef TCP_WESTWOOD_H
|
||||
#define TCP_WESTWOOD_H
|
||||
|
||||
#include "tcp-socket-base.h"
|
||||
#include "ns3/packet.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup socket
|
||||
* \ingroup tcp
|
||||
*
|
||||
* \brief An implementation of a stream socket using TCP.
|
||||
*
|
||||
* This class contains the implementation of TCP Westwood and Westwood+.
|
||||
*
|
||||
* Westwood and Westwood+ employ the AIAD (Additive Increase/Adaptive Decrease)
|
||||
* congestion control paradigm. When a congestion episode happens,
|
||||
* instead of halving the cwnd, these protocols try to estimate the network's
|
||||
* bandwidth and use the estimated value to adjust the cwnd.
|
||||
* While Westwood performs the bandwidth sampling every ACK reception,
|
||||
* Westwood+ samples the bandwidth every RTT.
|
||||
*
|
||||
* The two main methods in the implementation are the CountAck (const TCPHeader&)
|
||||
* and the EstimateBW (int, const, Time). The CountAck method calculates
|
||||
* the number of acknowledged segments on the receipt of an ACK.
|
||||
* The EstimateBW estimates the bandwidth based on the value returned by CountAck
|
||||
* and the sampling interval (last ACK inter-arrival time for Westwood and last RTT for Westwood+).
|
||||
*/
|
||||
class TcpWestwood : public TcpSocketBase
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
TcpWestwood (void);
|
||||
TcpWestwood (const TcpWestwood& sock);
|
||||
virtual ~TcpWestwood (void);
|
||||
|
||||
enum ProtocolType
|
||||
{
|
||||
WESTWOOD,
|
||||
WESTWOODPLUS
|
||||
};
|
||||
|
||||
enum FilterType
|
||||
{
|
||||
NONE,
|
||||
TUSTIN
|
||||
};
|
||||
|
||||
// From TcpSocketBase
|
||||
virtual int Connect (const Address &address);
|
||||
virtual int Listen (void);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Limit the size of outstanding data based on the cwnd and the receiver's advertised window
|
||||
*
|
||||
* \return the max. possible number of unacked bytes
|
||||
*/
|
||||
virtual uint32_t Window (void);
|
||||
|
||||
/**
|
||||
* Call CopyObject<TcpWestwood> to clone me
|
||||
*/
|
||||
virtual Ptr<TcpSocketBase> Fork (void);
|
||||
|
||||
/**
|
||||
* Process the newly received ACK
|
||||
*
|
||||
* \param packet the received ACK packet
|
||||
* \param tcpHeader the header attached to the ACK packet
|
||||
*/
|
||||
virtual void ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader);
|
||||
|
||||
/**
|
||||
* Adjust the cwnd based on the current congestion control phase,
|
||||
* and then call the TcpSocketBase::NewAck() to complete the processing
|
||||
*
|
||||
* \param seq the acknowledgment number
|
||||
*/
|
||||
virtual void NewAck (SequenceNumber32 const& seq);
|
||||
|
||||
/**
|
||||
* Adjust the cwnd using the currently estimated bandwidth,
|
||||
* retransmit the missing packet, and enter fast recovery if 3 DUPACKs are received
|
||||
*
|
||||
* \param header the TCP header of the ACK packet
|
||||
* \param count the number of DUPACKs
|
||||
*/
|
||||
virtual void DupAck (const TcpHeader& header, uint32_t count);
|
||||
|
||||
/**
|
||||
* Upon an RTO event, adjust the cwnd using the currently estimated bandwidth,
|
||||
* retransmit the missing packet, and exit fast recovery
|
||||
*/
|
||||
virtual void Retransmit (void);
|
||||
|
||||
/**
|
||||
* Estimate the RTT, record the minimum value,
|
||||
* and run a clock on the RTT to trigger Westwood+ bandwidth sampling
|
||||
*/
|
||||
virtual void EstimateRtt (const TcpHeader& header);
|
||||
|
||||
// Implementing ns3::TcpSocket -- Attribute get/set
|
||||
/**
|
||||
* \param size the segment size to be used in a connection
|
||||
*/
|
||||
virtual void SetSegSize (uint32_t size);
|
||||
|
||||
/**
|
||||
* \param the slow-start threshold
|
||||
*/
|
||||
virtual void SetSSThresh (uint32_t threshold);
|
||||
|
||||
/**
|
||||
* \return the slow-start threshold
|
||||
*/
|
||||
virtual uint32_t GetSSThresh (void) const;
|
||||
|
||||
/**
|
||||
* \param cwnd the initial cwnd
|
||||
*/
|
||||
virtual void SetInitialCwnd (uint32_t cwnd);
|
||||
|
||||
/**
|
||||
* \return the initial cwnd
|
||||
*/
|
||||
virtual uint32_t GetInitialCwnd (void) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize cwnd at the beginning of a connection
|
||||
*/
|
||||
void InitializeCwnd (void);
|
||||
|
||||
/**
|
||||
* Calculate the number of acknowledged packets upon the receipt of an ACK packet
|
||||
*
|
||||
* \param tcpHeader the header of the received ACK packet
|
||||
* \return the number of ACKed packets
|
||||
*/
|
||||
int CountAck (const TcpHeader& tcpHeader);
|
||||
|
||||
/**
|
||||
* Update the total number of acknowledged packets during the current RTT
|
||||
*
|
||||
* \param acked the number of packets the currently received ACK acknowledges
|
||||
*/
|
||||
void UpdateAckedSegments (int acked);
|
||||
|
||||
/**
|
||||
* Estimate the network's bandwidth
|
||||
*
|
||||
* \param acked the number of acknowledged packets returned by CountAck
|
||||
* \param tcpHeader the header of the packet
|
||||
* \param rtt the RTT estimation
|
||||
*/
|
||||
void EstimateBW (int acked, const TcpHeader& tcpHeader, Time rtt);
|
||||
|
||||
/**
|
||||
* Tustin filter
|
||||
*/
|
||||
void Filtering (void);
|
||||
|
||||
protected:
|
||||
TracedValue<uint32_t> m_cWnd; //< Congestion window
|
||||
uint32_t m_ssThresh; //< Slow Start Threshold
|
||||
uint32_t m_initialCWnd; //< Initial cWnd value
|
||||
bool m_inFastRec; //< Currently in fast recovery if TRUE
|
||||
|
||||
TracedValue<double> m_currentBW; //< Current value of the estimated BW
|
||||
double m_lastSampleBW; //< Last bandwidth sample
|
||||
double m_lastBW; //< Last bandwidth sample after being filtered
|
||||
Time m_minRtt; //< Minimum RTT
|
||||
double m_lastAck; //< The time last ACK was received
|
||||
SequenceNumber32 m_prevAckNo; //< Previously received ACK number
|
||||
int m_accountedFor; //< The number of received DUPACKs
|
||||
enum ProtocolType m_pType; //< 0 for Westwood, 1 for Westwood+
|
||||
enum FilterType m_fType; //< 0 for none, 1 for Tustin
|
||||
|
||||
int m_ackedSegments; //< The number of segments ACKed between RTTs
|
||||
bool m_IsCount; //< Start keeping track of m_ackedSegments for Westwood+ if TRUE
|
||||
EventId m_bwEstimateEvent; //< The BW estimation event for Westwood+
|
||||
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* TCP_WESTWOOD_H */
|
||||
@@ -135,6 +135,7 @@ def build(bld):
|
||||
'model/tcp-tahoe.cc',
|
||||
'model/tcp-reno.cc',
|
||||
'model/tcp-newreno.cc',
|
||||
'model/tcp-westwood.cc',
|
||||
'model/tcp-rx-buffer.cc',
|
||||
'model/tcp-tx-buffer.cc',
|
||||
'model/ipv4-packet-info-tag.cc',
|
||||
@@ -281,6 +282,15 @@ def build(bld):
|
||||
'helper/ipv6-interface-container.h',
|
||||
'helper/ipv6-routing-helper.h',
|
||||
'model/ipv6-address-generator.h',
|
||||
'model/tcp-rfc793.h',
|
||||
'model/tcp-tahoe.h',
|
||||
'model/tcp-reno.h',
|
||||
'model/tcp-newreno.h',
|
||||
'model/tcp-westwood.h',
|
||||
'model/tcp-socket-base.h',
|
||||
'model/tcp-tx-buffer.h',
|
||||
'model/tcp-rx-buffer.h',
|
||||
'model/rtt-estimator.h',
|
||||
]
|
||||
|
||||
if bld.env['NSC_ENABLED']:
|
||||
|
||||
@@ -38,12 +38,13 @@
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3tcp-socket-writer.h"
|
||||
#include "ns3/tcp-westwood.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Ns3TcpLossTest");
|
||||
|
||||
const bool WRITE_VECTORS = false; // set to true to write response vectors
|
||||
const bool WRITE_VECTORS = false; // set to true to write response vectors
|
||||
const bool WRITE_LOGGING = false; // set to true to write logging
|
||||
const uint32_t PCAP_LINK_TYPE = 1187373557; // Some large random number -- we use to verify data was written by this program
|
||||
const uint32_t PCAP_SNAPLEN = 64; // Don't bother to save much data
|
||||
@@ -95,7 +96,7 @@ Ns3TcpLossTestCase::Ns3TcpLossTestCase ()
|
||||
m_writeResults (false),
|
||||
m_writeLogging (WRITE_LOGGING),
|
||||
m_needToClose (true),
|
||||
m_tcpModel ("ns3::TcpTahoe")
|
||||
m_tcpModel ("ns3::TcpWestwood")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -121,7 +122,7 @@ Ns3TcpLossTestCase::DoSetup (void)
|
||||
//
|
||||
std::ostringstream oss;
|
||||
oss << "/response-vectors/ns3tcp-loss-" << m_tcpModel << m_testCase << "-response-vectors.pcap";
|
||||
m_pcapFilename = CreateDataDirFilename(oss.str ());
|
||||
m_pcapFilename = CreateDataDirFilename(oss.str ());
|
||||
|
||||
if (m_writeVectors)
|
||||
{
|
||||
@@ -286,8 +287,19 @@ Ns3TcpLossTestCase::DoRun (void)
|
||||
|
||||
std::ostringstream tcpModel;
|
||||
tcpModel << "ns3::Tcp" << m_tcpModel;
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType",
|
||||
if (m_tcpModel.compare("WestwoodPlus") == 0)
|
||||
{
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
|
||||
TypeIdValue (TcpWestwood::GetTypeId()));
|
||||
Config::SetDefault("ns3::TcpWestwood::ProtocolType",
|
||||
EnumValue(TcpWestwood::WESTWOODPLUS));
|
||||
}
|
||||
else
|
||||
{
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType",
|
||||
StringValue (tcpModel.str ()));
|
||||
}
|
||||
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000));
|
||||
Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1));
|
||||
|
||||
@@ -297,6 +309,7 @@ Ns3TcpLossTestCase::DoRun (void)
|
||||
LogComponentEnable ("TcpLossResponse", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("ErrorModel", LOG_LEVEL_DEBUG);
|
||||
LogComponentEnable ("TcpLossResponse", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("TcpWestwood", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("TcpNewReno", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("TcpReno", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("TcpTahoe", LOG_LEVEL_INFO);
|
||||
@@ -465,6 +478,19 @@ Ns3TcpLossTestSuite::Ns3TcpLossTestSuite ()
|
||||
AddTestCase (new Ns3TcpLossTestCase ("NewReno", 3), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("NewReno", 4), TestCase::QUICK);
|
||||
|
||||
AddTestCase (new Ns3TcpLossTestCase ("Westwood", 0), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("Westwood", 1), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("Westwood", 2), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("Westwood", 3), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("Westwood", 4), TestCase::QUICK);
|
||||
|
||||
AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 0), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 1), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 2), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 3), TestCase::QUICK);
|
||||
AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 4), TestCase::QUICK);
|
||||
|
||||
}
|
||||
|
||||
static Ns3TcpLossTestSuite ns3TcpLossTestSuite;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user