tcp: Added definitions of Sack options
This commit is contained in:
107
src/internet/model/tcp-option-sack-permitted.cc
Normal file
107
src/internet/model/tcp-option-sack-permitted.cc
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Adrian Sai-wah Tam
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Original Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
|
||||
* Documentation, test cases: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* The University of Kansas
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
*/
|
||||
|
||||
#include "tcp-option-sack-permitted.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpOptionSackPermitted");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (TcpOptionSackPermitted);
|
||||
|
||||
TcpOptionSackPermitted::TcpOptionSackPermitted ()
|
||||
: TcpOption ()
|
||||
{
|
||||
}
|
||||
|
||||
TcpOptionSackPermitted::~TcpOptionSackPermitted ()
|
||||
{
|
||||
}
|
||||
|
||||
TypeId
|
||||
TcpOptionSackPermitted::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::TcpOptionSackPermitted")
|
||||
.SetParent<TcpOption> ()
|
||||
.SetGroupName ("Internet")
|
||||
.AddConstructor<TcpOptionSackPermitted> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
TcpOptionSackPermitted::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
void
|
||||
TcpOptionSackPermitted::Print (std::ostream &os) const
|
||||
{
|
||||
os << "[sack_perm]";
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpOptionSackPermitted::GetSerializedSize (void) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
TcpOptionSackPermitted::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i.WriteU8 (GetKind ()); // Kind
|
||||
i.WriteU8 (2); // Length
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpOptionSackPermitted::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
|
||||
uint8_t readKind = i.ReadU8 ();
|
||||
if (readKind != GetKind ())
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Sack-Permitted option");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t size = i.ReadU8 ();
|
||||
if (size != 2)
|
||||
{
|
||||
NS_LOG_WARN ("Malformed Sack-Permitted option");
|
||||
return 0;
|
||||
}
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
|
||||
uint8_t
|
||||
TcpOptionSackPermitted::GetKind (void) const
|
||||
{
|
||||
return TcpOption::SACKPERMITTED;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
65
src/internet/model/tcp-option-sack-permitted.h
Normal file
65
src/internet/model/tcp-option-sack-permitted.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Adrian Sai-wah Tam
|
||||
* Copyright (c) 2015 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
|
||||
*
|
||||
* Original Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
|
||||
* Documentation, test cases: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* The University of Kansas
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
*/
|
||||
|
||||
#ifndef TCP_OPTION_SACK_PERMITTED_H
|
||||
#define TCP_OPTION_SACK_PERMITTED_H
|
||||
|
||||
#include "ns3/tcp-option.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Defines the TCP option of kind 4 (selective acknowledgment permitted
|
||||
* option) as in \RFC{2018}
|
||||
*
|
||||
* TCP Sack-Permitted Option is 2-byte in length and sent in a SYN segment by a
|
||||
* TCP host that can recognize and process SACK option during the lifetime of a
|
||||
* connection.
|
||||
*/
|
||||
|
||||
class TcpOptionSackPermitted : public TcpOption
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
|
||||
TcpOptionSackPermitted ();
|
||||
virtual ~TcpOptionSackPermitted ();
|
||||
|
||||
virtual void Print (std::ostream &os) const;
|
||||
virtual void Serialize (Buffer::Iterator start) const;
|
||||
virtual uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
virtual uint8_t GetKind (void) const;
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* TCP_OPTION_SACK_PERMITTED */
|
||||
159
src/internet/model/tcp-option-sack.cc
Normal file
159
src/internet/model/tcp-option-sack.cc
Normal file
@@ -0,0 +1,159 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Adrian Sai-wah Tam
|
||||
* Copyright (c) 2015 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
|
||||
*
|
||||
* Original Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
|
||||
* Documentation, test cases: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* The University of Kansas
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
*/
|
||||
|
||||
#include "tcp-option-sack.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpOptionSack");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (TcpOptionSack);
|
||||
|
||||
TcpOptionSack::TcpOptionSack ()
|
||||
: TcpOption ()
|
||||
{
|
||||
}
|
||||
|
||||
TcpOptionSack::~TcpOptionSack ()
|
||||
{
|
||||
}
|
||||
|
||||
TypeId
|
||||
TcpOptionSack::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::TcpOptionSack")
|
||||
.SetParent<TcpOption> ()
|
||||
.SetGroupName ("Internet")
|
||||
.AddConstructor<TcpOptionSack> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
TcpOptionSack::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
void
|
||||
TcpOptionSack::Print (std::ostream &os) const
|
||||
{
|
||||
os << "blocks: " << GetNumSackBlocks () << ",";
|
||||
for (SackList::const_iterator it = m_sackList.begin (); it != m_sackList.end (); ++it)
|
||||
{
|
||||
os << "[" << it->first << "," << it->second << "]";
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpOptionSack::GetSerializedSize (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_LOGIC ("Serialized size: " << 2 + GetNumSackBlocks () * 8);
|
||||
return 2 + GetNumSackBlocks () * 8;
|
||||
}
|
||||
|
||||
void
|
||||
TcpOptionSack::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Buffer::Iterator i = start;
|
||||
i.WriteU8 (GetKind ()); // Kind
|
||||
uint8_t length = GetNumSackBlocks () * 8 + 2;
|
||||
i.WriteU8 (length); // Length
|
||||
|
||||
for (SackList::const_iterator it = m_sackList.begin (); it != m_sackList.end (); ++it)
|
||||
{
|
||||
SequenceNumber32 leftEdge = it->first;
|
||||
SequenceNumber32 rightEdge = it->second;
|
||||
i.WriteHtonU32 (leftEdge.GetValue ()); // Left edge of the block
|
||||
i.WriteHtonU32 (rightEdge.GetValue ()); // Right edge of the block
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpOptionSack::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Buffer::Iterator i = start;
|
||||
uint8_t readKind = i.ReadU8 ();
|
||||
if (readKind != GetKind ())
|
||||
{
|
||||
NS_LOG_WARN ("Malformed SACK option, wrong type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t size = i.ReadU8 ();
|
||||
NS_LOG_LOGIC ("Size: " << (uint32_t)size);
|
||||
m_sackList.empty ();
|
||||
uint8_t sackCount = (size - 2) / 8;
|
||||
while (sackCount)
|
||||
{
|
||||
SequenceNumber32 leftEdge = SequenceNumber32 (i.ReadNtohU32 ());
|
||||
SequenceNumber32 rightEdge = SequenceNumber32 (i.ReadNtohU32 ());
|
||||
SackBlock s (leftEdge, rightEdge);
|
||||
AddSackBlock (s);
|
||||
sackCount--;
|
||||
}
|
||||
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
|
||||
uint8_t
|
||||
TcpOptionSack::GetKind (void) const
|
||||
{
|
||||
return TcpOption::SACK;
|
||||
}
|
||||
|
||||
void
|
||||
TcpOptionSack::AddSackBlock (SackBlock s)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_sackList.push_back (s);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpOptionSack::GetNumSackBlocks (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_LOGIC ("Number of SACK blocks appended: " << m_sackList.size ());
|
||||
return m_sackList.size ();
|
||||
}
|
||||
|
||||
void
|
||||
TcpOptionSack::ClearSackList (void)
|
||||
{
|
||||
m_sackList.clear ();
|
||||
}
|
||||
|
||||
TcpOptionSack::SackList
|
||||
TcpOptionSack::GetSackList (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_sackList;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
101
src/internet/model/tcp-option-sack.h
Normal file
101
src/internet/model/tcp-option-sack.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Adrian Sai-wah Tam
|
||||
* Copyright (c) 2015 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
|
||||
*
|
||||
* Original Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
|
||||
* Documentation, test cases: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* The University of Kansas
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
*/
|
||||
|
||||
#ifndef TCP_OPTION_SACK_H
|
||||
#define TCP_OPTION_SACK_H
|
||||
|
||||
#include "ns3/tcp-option.h"
|
||||
#include "ns3/sequence-number.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Defines the TCP option of kind 5 (selective acknowledgment option) as
|
||||
* in \RFC{2018}
|
||||
*
|
||||
* TCP SACK Option is used by a receiver to report non-contiguous blocks of data
|
||||
* that have been received and queued in the receiving buffer. Using the
|
||||
* information conveyed in SACK option sender retransmits only the segments that
|
||||
* have actually been lost, allowing the recovery of multiple packet losses per
|
||||
* sending window.
|
||||
*
|
||||
* Each SACK block is defined by two 32-bit unsigned integers specifying the
|
||||
* left and the right edge of the block. It means that with the 40-byte TCP
|
||||
* option limitation in addition to the presence of TCP Timestamp Option, the
|
||||
* maximum number of SACK blocks that can be appended to each segment is 3.
|
||||
*/
|
||||
class TcpOptionSack : public TcpOption
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
|
||||
typedef std::pair<SequenceNumber32, SequenceNumber32> SackBlock; //!< SACK block definition
|
||||
typedef std::list<SackBlock> SackList; //!< SACK list definition
|
||||
|
||||
TcpOptionSack ();
|
||||
virtual ~TcpOptionSack ();
|
||||
|
||||
virtual void Print (std::ostream &os) const;
|
||||
virtual void Serialize (Buffer::Iterator start) const;
|
||||
virtual uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
virtual uint8_t GetKind (void) const;
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
|
||||
/**
|
||||
* \brief Add a SACK block
|
||||
* \param s the SACK block to be added
|
||||
*/
|
||||
void AddSackBlock (SackBlock s);
|
||||
|
||||
/**
|
||||
* \brief Count the total number of SACK blocks
|
||||
* \return the total number of SACK blocks
|
||||
*/
|
||||
uint32_t GetNumSackBlocks (void) const;
|
||||
|
||||
/**
|
||||
* \brief Clear the SACK list
|
||||
*/
|
||||
void ClearSackList (void);
|
||||
|
||||
/**
|
||||
* \brief Get the SACK list
|
||||
* \return the SACK list
|
||||
*/
|
||||
SackList GetSackList (void) const;
|
||||
|
||||
protected:
|
||||
SackList m_sackList; //!< the list of SACK blocks
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* TCP_OPTION_SACK */
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "tcp-option-rfc793.h"
|
||||
#include "tcp-option-winscale.h"
|
||||
#include "tcp-option-ts.h"
|
||||
#include "tcp-option-sack-permitted.h"
|
||||
#include "tcp-option-sack.h"
|
||||
|
||||
#include "ns3/type-id.h"
|
||||
#include "ns3/log.h"
|
||||
@@ -71,11 +73,13 @@ TcpOption::CreateOption (uint8_t kind)
|
||||
static ObjectFactory objectFactory;
|
||||
static kindToTid toTid[] =
|
||||
{
|
||||
{ TcpOption::END, TcpOptionEnd::GetTypeId () },
|
||||
{ TcpOption::MSS, TcpOptionMSS::GetTypeId () },
|
||||
{ TcpOption::NOP, TcpOptionNOP::GetTypeId () },
|
||||
{ TcpOption::TS, TcpOptionTS::GetTypeId () },
|
||||
{ TcpOption::WINSCALE, TcpOptionWinScale::GetTypeId () },
|
||||
{ TcpOption::END, TcpOptionEnd::GetTypeId () },
|
||||
{ TcpOption::MSS, TcpOptionMSS::GetTypeId () },
|
||||
{ TcpOption::NOP, TcpOptionNOP::GetTypeId () },
|
||||
{ TcpOption::TS, TcpOptionTS::GetTypeId () },
|
||||
{ TcpOption::WINSCALE, TcpOptionWinScale::GetTypeId () },
|
||||
{ TcpOption::SACKPERMITTED, TcpOptionSackPermitted::GetTypeId () },
|
||||
{ TcpOption::SACK, TcpOptionSack::GetTypeId () },
|
||||
{ TcpOption::UNKNOWN, TcpOptionUnknown::GetTypeId () }
|
||||
};
|
||||
|
||||
@@ -100,8 +104,10 @@ TcpOption::IsKindKnown (uint8_t kind)
|
||||
case NOP:
|
||||
case MSS:
|
||||
case WINSCALE:
|
||||
case SACKPERMITTED:
|
||||
case SACK:
|
||||
case TS:
|
||||
// Do not add UNKNOWN here
|
||||
// Do not add UNKNOWN here
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -161,7 +167,7 @@ TcpOptionUnknown::Serialize (Buffer::Iterator i) const
|
||||
|
||||
i.WriteU8 (GetKind ());
|
||||
i.WriteU8 (GetSerializedSize ());
|
||||
i.Write (m_content, m_size-2);
|
||||
i.Write (m_content, m_size - 2);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -179,7 +185,7 @@ TcpOptionUnknown::Deserialize (Buffer::Iterator start)
|
||||
return 0;
|
||||
}
|
||||
|
||||
i.Read (m_content, m_size-2);
|
||||
i.Read (m_content, m_size - 2);
|
||||
|
||||
return m_size;
|
||||
}
|
||||
|
||||
@@ -54,12 +54,14 @@ public:
|
||||
{
|
||||
// Remember to extend IsKindKnown() with new value, when adding values here
|
||||
//
|
||||
END = 0, //!< END
|
||||
NOP = 1, //!< NOP
|
||||
MSS = 2, //!< MSS
|
||||
WINSCALE = 3, //!< WINSCALE
|
||||
TS = 8, //!< TS
|
||||
UNKNOWN = 255 //!< not a standardized value; for unknown recv'd options
|
||||
END = 0, //!< END
|
||||
NOP = 1, //!< NOP
|
||||
MSS = 2, //!< MSS
|
||||
WINSCALE = 3, //!< WINSCALE
|
||||
SACKPERMITTED = 4, //!< SACKPERMITTED
|
||||
SACK = 5, //!< SACK
|
||||
TS = 8, //!< TS
|
||||
UNKNOWN = 255 //!< not a standardized value; for unknown recv'd options
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -162,6 +162,8 @@ def build(bld):
|
||||
'model/tcp-option-rfc793.cc',
|
||||
'model/tcp-option-winscale.cc',
|
||||
'model/tcp-option-ts.cc',
|
||||
'model/tcp-option-sack-permitted.cc',
|
||||
'model/tcp-option-sack.cc',
|
||||
'model/ipv4-packet-info-tag.cc',
|
||||
'model/ipv6-packet-info-tag.cc',
|
||||
'model/ipv4-interface-address.cc',
|
||||
@@ -290,6 +292,8 @@ def build(bld):
|
||||
'model/tcp-option.h',
|
||||
'model/tcp-option-winscale.h',
|
||||
'model/tcp-option-ts.h',
|
||||
'model/tcp-option-sack-permitted.h',
|
||||
'model/tcp-option-sack.h',
|
||||
'model/tcp-option-rfc793.h',
|
||||
'model/icmpv4.h',
|
||||
'model/icmpv6-header.h',
|
||||
|
||||
Reference in New Issue
Block a user