Added an ErrorChannel aware of TCP

The class is responsible to take away the IP and TCP header from the packet,
and then to interrogate the pure virtual method ShouldDrop, dropping the packet
accordingly to the returned value. An implementation is a channel which
drops packet with specified flags.
This commit is contained in:
Natale Patriciello
2015-10-16 10:43:44 -07:00
parent 562c67c73a
commit 74beb15f40
3 changed files with 318 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "tcp-error-model.h"
#include "ns3/ipv4-header.h"
#include "ns3/packet.h"
#include "ns3/log.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("TcpGeneralErrorModel");
NS_OBJECT_ENSURE_REGISTERED (TcpGeneralErrorModel);
TypeId
TcpGeneralErrorModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpGeneralErrorModel")
.SetParent<ErrorModel> ()
;
return tid;
}
TcpGeneralErrorModel::TcpGeneralErrorModel ()
{
NS_LOG_FUNCTION (this);
}
bool
TcpGeneralErrorModel::DoCorrupt (Ptr<Packet> p)
{
NS_LOG_FUNCTION (this << p);
if (!IsEnabled ())
{
return false;
}
Ipv4Header ipHeader;
TcpHeader tcpHeader;
p->RemoveHeader (ipHeader);
p->RemoveHeader (tcpHeader);
bool toDrop = ShouldDrop (ipHeader, tcpHeader, p->GetSize ());
if (toDrop)
{
m_dropCallback (ipHeader, tcpHeader);
}
p->AddHeader (tcpHeader);
p->AddHeader (ipHeader);
return toDrop;
}
NS_OBJECT_ENSURE_REGISTERED (TcpSeqErrorModel);
TypeId
TcpSeqErrorModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpSeqErrorModel")
.SetParent<TcpGeneralErrorModel> ()
.AddConstructor<TcpSeqErrorModel> ()
;
return tid;
}
bool
TcpSeqErrorModel::ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
uint32_t packetSize)
{
NS_LOG_FUNCTION (this << ipHeader << tcpHeader);
bool toDrop = false;
if (m_seqToKill.begin() != m_seqToKill.end() && packetSize != 0)
{
SequenceNumber32 toKill = m_seqToKill.front();
NS_LOG_INFO ("Analyzing seq=" << tcpHeader.GetSequenceNumber () <<
" killing=" << toKill);
if (tcpHeader.GetSequenceNumber() >= toKill)
{
NS_LOG_INFO ("segment " << toKill << " dropped");
toDrop = true;
m_seqToKill.pop_front();
}
}
return toDrop;
}
void
TcpSeqErrorModel::DoReset()
{
m_seqToKill.erase (m_seqToKill.begin(), m_seqToKill.end());
}
NS_OBJECT_ENSURE_REGISTERED (TcpFlagErrorModel);
TypeId
TcpFlagErrorModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpFlagErrorModel")
.SetParent<TcpGeneralErrorModel> ()
.AddConstructor<TcpFlagErrorModel> ()
;
return tid;
}
TcpFlagErrorModel::TcpFlagErrorModel ()
: TcpGeneralErrorModel (),
m_flagsToKill (TcpHeader::NONE),
m_killNumber (0)
{
}
bool
TcpFlagErrorModel::ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
uint32_t packetSize)
{
NS_LOG_FUNCTION (this << ipHeader << tcpHeader);
(void) packetSize;
bool toDrop = false;
if ((tcpHeader.GetFlags () & m_flagsToKill) == m_flagsToKill)
{
if (m_killNumber > 0)
{
m_killNumber--;
if (m_killNumber > 0)
{
toDrop = true;
}
}
else if (m_killNumber < 0)
{
toDrop = true;
}
}
return toDrop;
}
void
TcpFlagErrorModel::DoReset (void)
{
m_flagsToKill = TcpHeader::NONE;
m_killNumber = 0;
}
} //namespace ns3

View File

@@ -0,0 +1,147 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef TCPERRORCHANNEL_H
#define TCPERRORCHANNEL_H
#include "ns3/error-model.h"
#include "ns3/tcp-header.h"
#include "ns3/ipv4-header.h"
namespace ns3 {
/**
* \brief A general (TCP-aware) error model
*
* The class is responsible to take away the IP and TCP header from the packet,
* and then to interrogate the method ShouldDrop, dropping the packet accordingly
* to the returned value.
*/
class TcpGeneralErrorModel : public ErrorModel
{
public:
static TypeId GetTypeId (void);
TcpGeneralErrorModel ();
void SetDropCallback (Callback<void, const Ipv4Header&, const TcpHeader&> cb)
{
m_dropCallback = cb;
}
protected:
virtual bool ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
uint32_t packetSize) = 0;
private:
virtual bool DoCorrupt (Ptr<Packet> p);
Callback<void, const Ipv4Header&, const TcpHeader&> m_dropCallback;
};
/**
* \brief An error model TCP aware: it drops the sequence number declared
*
* \see AddSeqToKill
*/
class TcpSeqErrorModel : public TcpGeneralErrorModel
{
public:
static TypeId GetTypeId (void);
TcpSeqErrorModel () : TcpGeneralErrorModel () { }
/**
* \brief Add the sequence number to the list of segments to be killed
*
* Calling x times this function indicates that you want to kill
* the segment x times.
*
* \param seq sequence number to be killed
*/
void AddSeqToKill (const SequenceNumber32 &seq)
{
m_seqToKill.insert(m_seqToKill.end(), seq);
}
protected:
virtual bool ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
uint32_t packetSize);
protected:
std::list<SequenceNumber32> m_seqToKill;
private:
virtual void DoReset (void);
};
/**
* \brief Error model which drop packets with specified TCP flags
*
* Set the flags with SetFlagToKill and the number of the packets with such flags
* which should be killed.
*
* \see SetFlagToKill
* \see SetKillRepeat
*
*/
class TcpFlagErrorModel : public TcpGeneralErrorModel
{
public:
static TypeId GetTypeId (void);
TcpFlagErrorModel ();
/**
* \brief Set the flags of the segment that should be killed
*
* \param flags Flags
*/
void SetFlagToKill (TcpHeader::Flags_t flags)
{
m_flagsToKill = flags;
}
/**
* \brief Set how many packets should be killed
*
* If the flags are the same, this specified the numbers of drops:
*
* # -1 for infinite drops
* # 0 for no drops
* # >1 the number of drops
*
* \param killNumber Specifies the number of times the packet should be killed
*/
void SetKillRepeat (int killNumber)
{
m_killNumber = killNumber;
}
protected:
virtual bool ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
uint32_t packetSize);
protected:
TcpHeader::Flags_t m_flagsToKill;
int m_killNumber;
private:
virtual void DoReset (void);
};
} // namespace ns3
#endif // TCPERRORCHANNEL_H

View File

@@ -232,6 +232,7 @@ def build(bld):
'test/tcp-option-test.cc',
'test/tcp-header-test.cc',
'test/tcp-general-test.cc',
'test/tcp-error-model.cc',
'test/udp-test.cc',
'test/ipv6-address-generator-test-suite.cc',
'test/ipv6-dual-stack-test-suite.cc',