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