From 74beb15f40e8b9302a8ae27dec18fe882e5456b1 Mon Sep 17 00:00:00 2001 From: Natale Patriciello Date: Fri, 16 Oct 2015 10:43:44 -0700 Subject: [PATCH] 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. --- src/internet/test/tcp-error-model.cc | 170 +++++++++++++++++++++++++++ src/internet/test/tcp-error-model.h | 147 +++++++++++++++++++++++ src/internet/wscript | 1 + 3 files changed, 318 insertions(+) create mode 100644 src/internet/test/tcp-error-model.cc create mode 100644 src/internet/test/tcp-error-model.h diff --git a/src/internet/test/tcp-error-model.cc b/src/internet/test/tcp-error-model.cc new file mode 100644 index 000000000..dea1b60ac --- /dev/null +++ b/src/internet/test/tcp-error-model.cc @@ -0,0 +1,170 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Natale Patriciello + * + * 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 () + ; + return tid; +} + +TcpGeneralErrorModel::TcpGeneralErrorModel () +{ + NS_LOG_FUNCTION (this); +} + +bool +TcpGeneralErrorModel::DoCorrupt (Ptr 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 + diff --git a/src/internet/test/tcp-error-model.h b/src/internet/test/tcp-error-model.h new file mode 100644 index 000000000..9a81ef662 --- /dev/null +++ b/src/internet/test/tcp-error-model.h @@ -0,0 +1,147 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Natale Patriciello + * + * 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 cb) + { + m_dropCallback = cb; + } + +protected: + virtual bool ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader, + uint32_t packetSize) = 0; + + +private: + virtual bool DoCorrupt (Ptr p); + Callback 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 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 diff --git a/src/internet/wscript b/src/internet/wscript index c0a79c860..cf5a6b975 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -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',