tcp: Added definitions of Sack options

This commit is contained in:
Natale Patriciello
2017-02-03 14:01:42 +01:00
parent 555f5654d1
commit b2bd923d9f
7 changed files with 458 additions and 14 deletions

View 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

View 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 */

View 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

View 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 */

View File

@@ -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;
}

View File

@@ -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
};
/**

View File

@@ -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',