Bug 385 - Add a generic "sequence number" class.

This commit is contained in:
Gustavo J. A. M. Carneiro
2010-07-11 22:32:34 +01:00
parent dc1ef073ac
commit f3b8aeb55c
16 changed files with 579 additions and 86 deletions

View File

@@ -0,0 +1,195 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2008-2010 INESC Porto
//
// 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
//
// Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
//
#include "sequence-number.h"
#include "ns3/test.h"
#include "ns3/object.h"
#include "ns3/traced-value.h"
#include "ns3/trace-source-accessor.h"
namespace ns3 {
class SequenceNumberTestObj : public Object
{
TracedValue<SequenceNumber32> m_testTracedSequenceNumber;
public:
SequenceNumberTestObj ()
{
m_testTracedSequenceNumber = SequenceNumber32 (0);
}
static TypeId GetTypeId (void)
{
static TypeId tid = TypeId("ns3::SequenceNumberTestObj")
.SetParent<Object> ()
.AddTraceSource ("TestTracedSequenceNumber",
"A traceable sequence number",
MakeTraceSourceAccessor (&SequenceNumberTestObj::m_testTracedSequenceNumber))
.AddConstructor<SequenceNumberTestObj> ()
;
return tid;
}
TypeId GetInstanceTypeId (void) const
{
return GetTypeId ();
}
void IncSequenceNumber ()
{
m_testTracedSequenceNumber += 1;
}
};
class SequenceNumberTestCase : public TestCase
{
SequenceNumber32 m_oldval;
SequenceNumber32 m_newval;
void SequenceNumberTracer (SequenceNumber32 oldval, SequenceNumber32 newval);
public:
SequenceNumberTestCase ();
virtual ~SequenceNumberTestCase ();
virtual bool DoRun (void);
};
SequenceNumberTestCase::SequenceNumberTestCase ()
: TestCase ("SequenceNumber")
{
m_oldval = 0;
m_newval = 0;
}
SequenceNumberTestCase::~SequenceNumberTestCase ()
{}
void
SequenceNumberTestCase::SequenceNumberTracer (SequenceNumber32 oldval, SequenceNumber32 newval)
{
m_oldval = oldval;
m_newval = newval;
}
bool SequenceNumberTestCase::DoRun (void)
{
#define NS_TEST_ASSERT_EQUAL(a,b) NS_TEST_ASSERT_MSG_EQ(a,b, "foo")
#define NS_TEST_ASSERT(a) NS_TEST_ASSERT_MSG_EQ(bool(a), true, "foo")
{
SequenceNumber32 num1 (3), num2 (5);
uint32_t value;
value = (num1 + num2).GetValue ();
NS_TEST_ASSERT_EQUAL (value, 8);
num1 += num2.GetValue ();
NS_TEST_ASSERT_EQUAL (num1, SequenceNumber32 (8));
++num1;
NS_TEST_ASSERT_EQUAL (num1, SequenceNumber32 (9));
--num1;
NS_TEST_ASSERT_EQUAL (num1, SequenceNumber32 (8));
num1++;
NS_TEST_ASSERT_EQUAL (num1, SequenceNumber32 (9));
num1--;
NS_TEST_ASSERT_EQUAL (num1, SequenceNumber32 (8));
}
{
SequenceNumber16 num1 (60900), num2 (5), num3 (10000);
NS_TEST_ASSERT (num1 == num1);
NS_TEST_ASSERT (num2 != num1);
NS_TEST_ASSERT (num3 > num2);
NS_TEST_ASSERT (num3 >= num2);
NS_TEST_ASSERT (num1 < num3);
NS_TEST_ASSERT (num1 <= num3);
NS_TEST_ASSERT (num1 < num2);
NS_TEST_ASSERT (num1 <= num2);
NS_TEST_ASSERT (num2 > num1);
NS_TEST_ASSERT (num2 >= num1);
NS_TEST_ASSERT (num1+num2 > num1);
NS_TEST_ASSERT (num1+num2 >= num1);
NS_TEST_ASSERT (num1 < num1+num2);
NS_TEST_ASSERT (num1 <= num1+num2);
NS_TEST_ASSERT (num1 < num1+num3);
NS_TEST_ASSERT (num1 <= num1+num3);
NS_TEST_ASSERT (num1+num3 > num1);
NS_TEST_ASSERT (num1+num3 >= num1);
}
{
NS_TEST_ASSERT_EQUAL ((SequenceNumber16 (1000) + SequenceNumber16 (6000)) - SequenceNumber16 (1000), 6000);
NS_TEST_ASSERT_EQUAL ((SequenceNumber16 (60000) + SequenceNumber16 (6000)) - SequenceNumber16 (60000), 6000);
NS_TEST_ASSERT_EQUAL (SequenceNumber16 (1000) - SequenceNumber16 (6000), -5000);
NS_TEST_ASSERT_EQUAL ((SequenceNumber16 (60000) + SequenceNumber16 (1000)) - SequenceNumber16 (65000), -4000);
}
{
SequenceNumber32 num1 (3);
NS_TEST_ASSERT_EQUAL (num1 + 10, SequenceNumber32 (13));
num1 += -1;
NS_TEST_ASSERT_EQUAL (num1, SequenceNumber32 (2));
NS_TEST_ASSERT_EQUAL (num1 - (num1 - 100), 100);
}
{
Ptr<SequenceNumberTestObj> obj = CreateObject<SequenceNumberTestObj> ();
obj->TraceConnectWithoutContext ("TestTracedSequenceNumber", MakeCallback (&SequenceNumberTestCase::SequenceNumberTracer, this));
obj->IncSequenceNumber ();
NS_TEST_ASSERT_EQUAL (m_oldval, SequenceNumber32 (0));
NS_TEST_ASSERT_EQUAL (m_newval, SequenceNumber32 (1));
obj->Dispose ();
}
return false;
}
static class SequenceNumberTestSuite : public TestSuite
{
public:
SequenceNumberTestSuite ()
: TestSuite ("SequenceNumber", UNIT)
{
AddTestCase (new SequenceNumberTestCase ());
}
} g_seqNumTests;
}

View File

@@ -0,0 +1,298 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2008-2010 INESC Porto
//
// 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
//
// Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
//
#ifndef __NS3_SEQ_NUM_H__
#define __NS3_SEQ_NUM_H__
#include <limits>
#include <iostream>
#include <stdint.h>
namespace ns3 {
/**
* \brief Generic "sequence number" class
*
* This class can be used to handle sequence numbers. In networking
* protocols, sequence numbers are fixed precision integer numbers
* that are used to order events relative to each other. A sequence
* number is expected to increase over time but, since it has a
* limited number of bits, the number will "wrap around" from the
* maximum value that can represented with the given number of bits
* back to zero. For this reason, comparison of two sequence numbers,
* and subtraction, is non-trivial. The SequenceNumber class behaves
* like a number, with the usual arythmetic operators implemented, but
* knows how to correctly compare and subtract sequence numbers.
*
* This is a templated class. To use it you need to supply two
* fundamental types as template parameters: NUMERIC_TYPE and
* SIGNED_TYPE. For instance, SequenceNumber<uint32_t, int32_t> gives
* you a 32-bit sequence number, while SequenceNumber<uint16_t,
* int16_t> is a 16-bit one. For your convenience, these are
* typedef'ed as SequenceNumber32 and SequenceNumber16, respectively.
*/
template<typename NUMERIC_TYPE, typename SIGNED_TYPE>
class SequenceNumber
{
public:
SequenceNumber ()
: m_value (0)
{}
/**
* \brief Constructs a SequenceNumber with the given value
* \param value the sequence number value
*/
explicit SequenceNumber (NUMERIC_TYPE value)
: m_value (value)
{}
// copy contructor
SequenceNumber (SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> const &value)
: m_value (value.m_value)
{}
// assignment from a plain number
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator= (NUMERIC_TYPE value)
{
m_value = value;
return *this;
}
// assignment from a sequence number
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator= (SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> const &value)
{
m_value = value.m_value;
return *this;
}
#if 0
// a SequenceNumber implicitly converts to a plain number, but not the other way around
operator NUMERIC_TYPE () const
{
return m_value;
}
#endif
/**
* \brief Extracts the numeric value of the sequence number
* \returns the sequence number value
*/
NUMERIC_TYPE GetValue () const
{
return m_value;
}
// prefix ++
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator++ ()
{
m_value++;
return *this;
}
// postfix ++
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator++ (int)
{
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> retval (m_value);
m_value++;
return retval;
}
// prefix --
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator-- ()
{
m_value--;
return *this;
}
// postfix --
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator-- (int)
{
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> retval (m_value);
m_value--;
return retval;
}
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator+= (SIGNED_TYPE value)
{
m_value += value;
return *this;
}
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator-= (SIGNED_TYPE value)
{
m_value -= value;
return *this;
}
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator + (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
return SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> (m_value + other.m_value);
}
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator + (SIGNED_TYPE delta) const
{
return SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> (m_value + delta);
}
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator - (SIGNED_TYPE delta) const
{
return SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> (m_value - delta);
}
SIGNED_TYPE operator - (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
static const NUMERIC_TYPE maxValue = std::numeric_limits<NUMERIC_TYPE>::max ();
static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max () / 2;
if (m_value > other.m_value)
{
NUMERIC_TYPE diff = m_value - other.m_value;
if (diff < halfMaxValue)
{
return static_cast<SIGNED_TYPE> (diff);
}
else
{
// |------------|------------|
// ==== ===
// ^ ^
// other.m_value m_value
return -(static_cast<SIGNED_TYPE> (maxValue - m_value + 1 + other.m_value));
}
}
else
{
NUMERIC_TYPE diff = other.m_value - m_value;
if (diff < halfMaxValue)
{
// |------------|------------|
// ========
// ^ ^
// m_value other.m_value
return -(static_cast<SIGNED_TYPE> (diff));
}
else
{
// |------------|------------|
// ==== ===
// ^ ^
// m_value other.m_value
return static_cast<SIGNED_TYPE> (maxValue - other.m_value + 1 + m_value);
}
}
}
// Here is the critical part, how the comparison is made taking into
// account wrap-around. From RFC 3626:
//
// The sequence number S1 is said to be "greater than" the sequence
// number S2 if:
//
// S1 > S2 AND S1 - S2 <= MAXVALUE/2 OR
//
// S2 > S1 AND S2 - S1 > MAXVALUE/2
bool operator > (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max () / 2;
return (((m_value > other.m_value) && (m_value - other.m_value) <= halfMaxValue)
|| ((other.m_value > m_value) && (other.m_value - m_value) > halfMaxValue));
}
bool operator == (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
return (m_value == other.m_value);
}
bool operator != (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
return (m_value != other.m_value);
}
bool operator <= (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
return (!this->operator> (other));
}
bool operator >= (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
return (this->operator> (other) || this->operator== (other));
}
bool operator < (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
{
return !this->operator> (other) && m_value != other.m_value;
}
template<typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
friend std::ostream & operator<< (std::ostream& os, const SequenceNumber<NUMERIC_TYPE2, SIGNED_TYPE2> &val);
template<typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
friend std::istream & operator >> (std::istream &is, const SequenceNumber<NUMERIC_TYPE2, SIGNED_TYPE2> &val);
private: // unimplemented operators
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator+= (SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> const &value);
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator-= (SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> const &value);
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator* (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator/ (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator% (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
bool operator ! () const;
bool operator && (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
bool operator || (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator~ () const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator& (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator| (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator^ (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator<< (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator>> (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
int operator* ();
//SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>* operator& ();
private:
NUMERIC_TYPE m_value;
};
template<typename NUMERIC_TYPE, typename SIGNED_TYPE>
std::ostream &
operator<< (std::ostream& os, const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &val)
{
os << val.m_value;
return os;
}
template<typename NUMERIC_TYPE, typename SIGNED_TYPE>
std::istream & operator >> (std::istream &is, const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &val)
{
is >> val.m_value;
return is;
}
typedef SequenceNumber<uint32_t, int32_t> SequenceNumber32;
typedef SequenceNumber<uint16_t, int16_t> SequenceNumber16;
} // namespace ns3
#endif

View File

@@ -34,6 +34,7 @@ def build(bld):
'spectrum-type.cc',
'spectrum-propagation-loss-model.cc',
'friis-spectrum-propagation-loss.cc',
'sequence-number.cc',
]
headers = bld.new_task_gen('ns3header')
@@ -67,4 +68,5 @@ def build(bld):
'spectrum-type.h',
'spectrum-propagation-loss-model.h',
'friis-spectrum-propagation-loss.h',
'sequence-number.h',
]

View File

@@ -25,6 +25,7 @@
#include "ns3/log.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/sequence-number.h"
#include <list>
NS_LOG_COMPONENT_DEFINE ("MacRxMiddle");
@@ -269,8 +270,7 @@ MacRxMiddle::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
* So, this check cannot be used to discard old duplicate frames. It is
* thus here only for documentation purposes.
*/
if (!SequenceControlSmaller (originator->GetLastSequenceControl (),
hdr->GetSequenceControl ()))
if (!(SequenceNumber16 (originator->GetLastSequenceControl ()) < SequenceNumber16 (hdr->GetSequenceControl ())))
{
NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded="<<originator->GetLastSequenceControl ()<<
" currently seen="<< hdr->GetSequenceControl ());

View File

@@ -29,7 +29,7 @@
#include "ns3/event-id.h"
#include "tcp-typedefs.h"
#include "pending-data.h"
#include "sequence-number.h"
#include "ns3/sequence-number.h"
struct INetStreamSocket;

View File

@@ -119,7 +119,7 @@ void PendingData::Add (Ptr<Packet> p)
size += p->GetSize();
}
uint32_t PendingData::SizeFromSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset)
uint32_t PendingData::SizeFromSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset)
{
NS_LOG_FUNCTION (this << seqFront << seqOffset);
uint32_t o1 = OffsetFromSeq (seqFront, seqOffset); // Offset to start of unused data
@@ -134,7 +134,7 @@ uint32_t PendingData::SizeFromOffset (uint32_t offset)
return size - offset; // Available data after offset
}
uint32_t PendingData::OffsetFromSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset)
uint32_t PendingData::OffsetFromSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset)
{ // f is the first sequence number in this data, o is offset sequence
NS_LOG_FUNCTION (this << seqFront << seqOffset);
if (seqOffset < seqFront)
@@ -215,14 +215,14 @@ Ptr<Packet> PendingData::CopyFromOffset (uint32_t s, uint32_t o)
}
}
Ptr<Packet> PendingData::CopyFromSeq (uint32_t s, const SequenceNumber& f, const SequenceNumber& o)
Ptr<Packet> PendingData::CopyFromSeq (uint32_t s, const SequenceNumber32& f, const SequenceNumber32& o)
{
NS_LOG_FUNCTION (this << s << f << o);
return CopyFromOffset (s, OffsetFromSeq(f,o));
}
uint32_t
PendingData::RemoveToSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset)
PendingData::RemoveToSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset)
{
NS_LOG_FUNCTION (this << seqFront << seqOffset);
uint32_t count = OffsetFromSeq (seqFront, seqOffset);

View File

@@ -26,7 +26,7 @@
#include "ns3/packet.h"
#include "pending-data.h"
#include "sequence-number.h"
#include "ns3/sequence-number.h"
#include "ns3/ptr.h"
namespace ns3
@@ -72,7 +72,7 @@ public:
* \param seqFront sequence number of assumed first byte in the PendingData
* \param seqOffset sequence number of offset
*/
virtual uint32_t SizeFromSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset);
virtual uint32_t SizeFromSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset);
// Inquire available data from offset
/**
* \return number of bytes in the data buffer beyond the offset specified
@@ -88,10 +88,10 @@ public:
* \param seqOffset higher sequence number
* \return seqOffset-seqFront
*/
virtual uint32_t OffsetFromSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset);
virtual uint32_t OffsetFromSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset);
virtual Ptr<Packet> CopyFromOffset (uint32_t, uint32_t); // Size, offset, ret packet
// Copy data, size, offset specified by sequence difference
virtual Ptr<Packet> CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&);
virtual Ptr<Packet> CopyFromSeq (uint32_t, const SequenceNumber32&, const SequenceNumber32&);
/**
* Permits object to clear any pending data between seqFront and
* seqOffset - 1). Callers should check the return value to determine
@@ -101,7 +101,7 @@ public:
* \param seqOffset first sequence number in buffer that should be retained
* \return number of bytes from the front that were removed from the buffer
*/
virtual uint32_t RemoveToSeq (const SequenceNumber& seqFront, const SequenceNumber& seqOffset);
virtual uint32_t RemoveToSeq (const SequenceNumber32& seqFront, const SequenceNumber32& seqOffset);
PendingData* Copy () const; // Create a copy of this header
PendingData* CopyS (uint32_t); // Copy with new size
PendingData* CopySD (uint32_t, uint8_t*); // Copy with new size, new data

View File

@@ -61,7 +61,7 @@ RttEstimator::GetTypeId (void)
}
//RttHistory methods
RttHistory::RttHistory (SequenceNumber s, uint32_t c, Time t)
RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
: seq (s), count (c), time (t), retx (false)
{
}
@@ -89,25 +89,25 @@ RttEstimator::~RttEstimator ()
{
}
void RttEstimator::SentSeq (SequenceNumber s, uint32_t c)
void RttEstimator::SentSeq (SequenceNumber32 s, uint32_t c)
{ // Note that a particular sequence has been sent
if (s == next)
{ // This is the next expected one, just log at end
history.push_back (RttHistory (s, c, Simulator::Now () ));
next = s + SequenceNumber (c); // Update next expected
next = s + SequenceNumber32 (c); // Update next expected
}
else
{ // This is a retransmit, find in list and mark as re-tx
for (RttHistory_t::iterator i = history.begin (); i != history.end (); ++i)
{
if ((s >= i->seq) && (s < (i->seq + SequenceNumber (i->count))))
if ((s >= i->seq) && (s < (i->seq + SequenceNumber32 (i->count))))
{ // Found it
i->retx = true;
// One final test..be sure this re-tx does not extend "next"
if ((s + SequenceNumber (c)) > next)
if ((s + SequenceNumber32 (c)) > next)
{
next = s + SequenceNumber (c);
i->count = ((s + SequenceNumber (c)) - i->seq); // And update count in hist
next = s + SequenceNumber32 (c);
i->count = ((s + SequenceNumber32 (c)) - i->seq); // And update count in hist
}
break;
}
@@ -115,14 +115,14 @@ void RttEstimator::SentSeq (SequenceNumber s, uint32_t c)
}
}
Time RttEstimator::AckSeq (SequenceNumber a)
Time RttEstimator::AckSeq (SequenceNumber32 a)
{ // An ack has been received, calculate rtt and log this measurement
// Note we use a linear search (O(n)) for this since for the common
// case the ack'ed packet will be at the head of the list
Time m = Seconds (0.0);
if (history.size () == 0) return (m); // No pending history, just exit
RttHistory& h = history.front ();
if (!h.retx && a >= (h.seq + SequenceNumber (h.count)))
if (!h.retx && a >= (h.seq + SequenceNumber32 (h.count)))
{ // Ok to use this sample
m = Simulator::Now () - h.time; // Elapsed time
Measurement(m); // Log the measurement
@@ -132,7 +132,7 @@ Time RttEstimator::AckSeq (SequenceNumber a)
while(history.size() > 0)
{
RttHistory& h = history.front ();
if ((h.seq + SequenceNumber(h.count)) > a) break; // Done removing
if ((h.seq + SequenceNumber32(h.count)) > a) break; // Done removing
history.pop_front (); // Remove
}
return m;

View File

@@ -26,7 +26,7 @@
#define __rtt_estimator_h__
#include <deque>
#include "sequence-number.h"
#include "ns3/sequence-number.h"
#include "ns3/nstime.h"
#include "ns3/object.h"
@@ -39,10 +39,10 @@ namespace ns3 {
*/
class RttHistory {
public:
RttHistory (SequenceNumber s, uint32_t c, Time t);
RttHistory (SequenceNumber32 s, uint32_t c, Time t);
RttHistory (const RttHistory& h); // Copy constructor
public:
SequenceNumber seq; // First sequence number in packet sent
SequenceNumber32 seq; // First sequence number in packet sent
uint32_t count; // Number of bytes sent
Time time; // Time this one was sent
bool retx; // True if this has been retransmitted
@@ -58,20 +58,20 @@ public:
RttEstimator(const RttEstimator&); // Copy constructor
virtual ~RttEstimator();
virtual void SentSeq(SequenceNumber, uint32_t);
virtual Time AckSeq(SequenceNumber);
virtual void SentSeq(SequenceNumber32, uint32_t);
virtual Time AckSeq(SequenceNumber32);
virtual void ClearSent();
virtual void Measurement(Time t) = 0;
virtual Time Estimate() = 0;
virtual Time RetransmitTimeout() = 0;
void Init(SequenceNumber s) { next = s;}
void Init(SequenceNumber32 s) { next = s;}
virtual Ptr<RttEstimator> Copy() const = 0;
virtual void IncreaseMultiplier();
virtual void ResetMultiplier();
virtual void Reset();
private:
SequenceNumber next; // Next expected sequence to be sent
SequenceNumber32 next; // Next expected sequence to be sent
RttHistory_t history; // List of sent packet
double m_maxMultiplier;
public:

View File

@@ -59,11 +59,11 @@ void TcpHeader::SetDestinationPort (uint16_t port)
{
m_destinationPort = port;
}
void TcpHeader::SetSequenceNumber (SequenceNumber sequenceNumber)
void TcpHeader::SetSequenceNumber (SequenceNumber32 sequenceNumber)
{
m_sequenceNumber = sequenceNumber;
}
void TcpHeader::SetAckNumber (SequenceNumber ackNumber)
void TcpHeader::SetAckNumber (SequenceNumber32 ackNumber)
{
m_ackNumber = ackNumber;
}
@@ -92,11 +92,11 @@ uint16_t TcpHeader::GetDestinationPort () const
{
return m_destinationPort;
}
SequenceNumber TcpHeader::GetSequenceNumber () const
SequenceNumber32 TcpHeader::GetSequenceNumber () const
{
return m_sequenceNumber;
}
SequenceNumber TcpHeader::GetAckNumber () const
SequenceNumber32 TcpHeader::GetAckNumber () const
{
return m_ackNumber;
}
@@ -209,8 +209,8 @@ void TcpHeader::Serialize (Buffer::Iterator start) const
Buffer::Iterator i = start;
i.WriteHtonU16 (m_sourcePort);
i.WriteHtonU16 (m_destinationPort);
i.WriteHtonU32 (m_sequenceNumber);
i.WriteHtonU32 (m_ackNumber);
i.WriteHtonU32 (m_sequenceNumber.GetValue ());
i.WriteHtonU32 (m_ackNumber.GetValue ());
i.WriteHtonU16 (m_length << 12 | m_flags); //reserved bits are all zero
i.WriteHtonU16 (m_windowSize);
i.WriteHtonU16 (0);

View File

@@ -61,11 +61,11 @@ public:
/**
* \param sequenceNumber the sequence number for this TcpHeader
*/
void SetSequenceNumber (SequenceNumber sequenceNumber);
void SetSequenceNumber (SequenceNumber32 sequenceNumber);
/**
* \param ackNumber the ACK number for this TcpHeader
*/
void SetAckNumber (SequenceNumber ackNumber);
void SetAckNumber (SequenceNumber32 ackNumber);
/**
* \param length the length of this TcpHeader
*/
@@ -96,11 +96,11 @@ public:
/**
* \return the sequence number for this TcpHeader
*/
SequenceNumber GetSequenceNumber () const;
SequenceNumber32 GetSequenceNumber () const;
/**
* \return the ACK number for this TcpHeader
*/
SequenceNumber GetAckNumber () const;
SequenceNumber32 GetAckNumber () const;
/**
* \return the length of this TcpHeader
*/
@@ -153,8 +153,8 @@ private:
uint16_t CalculateHeaderChecksum (uint16_t size) const;
uint16_t m_sourcePort;
uint16_t m_destinationPort;
uint32_t m_sequenceNumber;
uint32_t m_ackNumber;
SequenceNumber32 m_sequenceNumber;
SequenceNumber32 m_ackNumber;
uint8_t m_length; // really a uint4_t
uint8_t m_flags; // really a uint6_t
uint16_t m_windowSize;

View File

@@ -534,8 +534,8 @@ TcpL4Protocol::Receive (Ptr<Packet> packet,
else
{
header.SetFlags (TcpHeader::RST | TcpHeader::ACK);
header.SetSequenceNumber (SequenceNumber (0));
header.SetAckNumber (header.GetSequenceNumber () + SequenceNumber (1));
header.SetSequenceNumber (SequenceNumber32 (0));
header.SetAckNumber (header.GetSequenceNumber () + SequenceNumber32 (1));
}
header.SetSourcePort (tcpHeader.GetDestinationPort ());
header.SetDestinationPort (tcpHeader.GetSourcePort ());
@@ -571,7 +571,7 @@ TcpL4Protocol::Send (Ptr<Packet> packet,
daddr,
PROT_NUMBER);
tcpHeader.SetFlags (TcpHeader::ACK);
tcpHeader.SetAckNumber (0);
tcpHeader.SetAckNumber (SequenceNumber32 (0));
packet->AddHeader (tcpHeader);

View File

@@ -347,7 +347,7 @@ TcpSocketImpl::Close (void)
" deferring close, state " << m_state);
return 0;
}
m_finSequence = m_nextTxSequence + SequenceNumber (1);
m_finSequence = m_nextTxSequence + SequenceNumber32 (1);
Actions_t action = ProcessEvent (APP_CLOSE);
ProcessAction (action);
return 0;
@@ -548,7 +548,7 @@ TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
<< m_bufferedData.size ()
<< " time " << Simulator::Now ());
i = m_bufferedData.begin ();
SequenceNumber s1 = 0;
SequenceNumber32 s1 (0);
if (i->first > m_nextRxSequence)
{
break; // we're done, no more in-sequence data exits
@@ -588,7 +588,7 @@ TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
uint32_t avail = maxSize - outPacket->GetSize();
outPacket->AddAtEnd(i->second->CreateFragment(0,avail));
//put the rest back into the buffer
m_bufferedData[i->first+SequenceNumber(avail)]
m_bufferedData[i->first+SequenceNumber32(avail)]
= i->second->CreateFragment(avail,i->second->GetSize()-avail);
m_rxAvailable += i->second->GetSize()-avail;
m_rxBufSize += i->second->GetSize()-avail;
@@ -971,7 +971,7 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
// This is the cloned endpoint
// TCP SYN consumes one byte
m_nextRxSequence = tcpHeader.GetSequenceNumber ()
+ SequenceNumber (1);
+ SequenceNumber32 (1);
SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
}
@@ -979,7 +979,7 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
case ACK_TX_1:
NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1");
// TCP SYN consumes one byte
m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber32(1);
m_nextTxSequence = tcpHeader.GetAckNumber ();
m_firstPendingSequence = m_nextTxSequence; //bug 166
NS_LOG_DEBUG ("TcpSocketImpl " << this << " ACK_TX_1" <<
@@ -1045,7 +1045,7 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
if (m_finSequence != m_nextRxSequence)
{
// process close later
m_finSequence = tcpHeader.GetSequenceNumber () + SequenceNumber (p->GetSize ());
m_finSequence = tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ());
m_pendingClose = true;
NS_LOG_LOGIC ("TcpSocketImpl " << this << " setting pendingClose"
<< " rxseq " << tcpHeader.GetSequenceNumber ()
@@ -1168,10 +1168,10 @@ bool TcpSocketImpl::SendPendingData (bool withAck)
uint32_t sz = p->GetSize (); // Size of packet
uint32_t remainingData = m_pendingData->SizeFromSeq(
m_firstPendingSequence,
m_nextTxSequence + SequenceNumber (sz));
m_nextTxSequence + SequenceNumber32 (sz));
if (m_closeOnEmpty && (remainingData == 0))
{
m_finSequence = m_nextTxSequence + SequenceNumber (1 + sz);
m_finSequence = m_nextTxSequence + SequenceNumber32 (1 + sz);
flags = TcpHeader::FIN;
m_state = FIN_WAIT_1;
}
@@ -1303,8 +1303,8 @@ void TcpSocketImpl::NewRx (Ptr<Packet> p,
UnAckData_t::iterator next = m_bufferedData.upper_bound (m_nextRxSequence);
if (next != m_bufferedData.end ())
{
SequenceNumber nextBufferedSeq = next->first;
if (m_nextRxSequence + SequenceNumber(s) > nextBufferedSeq)
SequenceNumber32 nextBufferedSeq = next->first;
if (m_nextRxSequence + SequenceNumber32(s) > nextBufferedSeq)
{//tail end isn't all new, trim enough off the end
s = nextBufferedSeq - m_nextRxSequence;
}
@@ -1344,14 +1344,14 @@ void TcpSocketImpl::NewRx (Ptr<Packet> p,
NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () );
UnAckData_t::iterator previous =
m_bufferedData.lower_bound (tcpHeader.GetSequenceNumber ());
SequenceNumber startSeq = tcpHeader.GetSequenceNumber();
SequenceNumber32 startSeq = tcpHeader.GetSequenceNumber();
if (previous != m_bufferedData.begin ())
{
--previous;
startSeq = previous->first + SequenceNumber(previous->second->GetSize());
startSeq = previous->first + SequenceNumber32(previous->second->GetSize());
if (startSeq > tcpHeader.GetSequenceNumber ())
{
s = tcpHeader.GetSequenceNumber () + SequenceNumber(s) - startSeq;
s = tcpHeader.GetSequenceNumber () + SequenceNumber32(s) - startSeq;
}
else
{
@@ -1362,8 +1362,8 @@ void TcpSocketImpl::NewRx (Ptr<Packet> p,
UnAckData_t::iterator next = m_bufferedData.upper_bound (tcpHeader.GetSequenceNumber());
if (next != m_bufferedData.end ())
{
SequenceNumber nextBufferedSeq = next->first;
if (startSeq + SequenceNumber(s) > nextBufferedSeq)
SequenceNumber32 nextBufferedSeq = next->first;
if (startSeq + SequenceNumber32(s) > nextBufferedSeq)
{//tail end isn't all new either, trim enough off the end
s = nextBufferedSeq - startSeq;
}
@@ -1390,25 +1390,25 @@ void TcpSocketImpl::NewRx (Ptr<Packet> p,
++next;
if(next != m_bufferedData.end())
{
NS_ASSERT(next->first >= i->first + SequenceNumber(i->second->GetSize ()));
NS_ASSERT(next->first >= i->first + SequenceNumber32(i->second->GetSize ()));
}
}
else if (tcpHeader.GetSequenceNumber () + SequenceNumber(s) > m_nextRxSequence)
else if (tcpHeader.GetSequenceNumber () + SequenceNumber32(s) > m_nextRxSequence)
{//parial new data case, only part of the packet is new data
//trim the beginning
s = tcpHeader.GetSequenceNumber () + SequenceNumber(s) - m_nextRxSequence; //how much new
s = tcpHeader.GetSequenceNumber () + SequenceNumber32(s) - m_nextRxSequence; //how much new
//possibly trim off the end
UnAckData_t::iterator next = m_bufferedData.upper_bound (m_nextRxSequence);
if (next != m_bufferedData.end ())
{
SequenceNumber nextBufferedSeq = next->first;
if (m_nextRxSequence + SequenceNumber(s) > nextBufferedSeq)
SequenceNumber32 nextBufferedSeq = next->first;
if (m_nextRxSequence + SequenceNumber32(s) > nextBufferedSeq)
{//tail end isn't all new either, trim enough off the end
s = nextBufferedSeq - m_nextRxSequence;
}
}
p = p->CreateFragment (m_nextRxSequence - tcpHeader.GetSequenceNumber (),s);
SequenceNumber start = m_nextRxSequence;
SequenceNumber32 start = m_nextRxSequence;
m_nextRxSequence += s; // Advance next expected sequence
//buffer the new fragment, it'll be read by call to Recv
UnAckData_t::iterator i = m_bufferedData.find (start);
@@ -1449,7 +1449,7 @@ void TcpSocketImpl::NewRx (Ptr<Packet> p,
}
}
void TcpSocketImpl::RxBufFinishInsert (SequenceNumber seq)
void TcpSocketImpl::RxBufFinishInsert (SequenceNumber32 seq)
{
//putting data into the buffer might have filled in a sequence gap so we have
//to iterate through the list to find the largest contiguous sequenced chunk,
@@ -1460,11 +1460,11 @@ void TcpSocketImpl::RxBufFinishInsert (SequenceNumber seq)
//make sure the buffer is logically sequenced
if(next != m_bufferedData.end())
{
NS_ASSERT(next->first >= i->first + SequenceNumber(i->second->GetSize ()));
NS_ASSERT(next->first >= i->first + SequenceNumber32(i->second->GetSize ()));
}
while(next != m_bufferedData.end())
{
if(i->first + SequenceNumber(i->second->GetSize ()) == next->first)
if(i->first + SequenceNumber32(i->second->GetSize ()) == next->first)
{
//next packet is in sequence, count it
m_rxAvailable += next->second->GetSize();
@@ -1485,7 +1485,7 @@ void TcpSocketImpl::DelAckTimeout ()
SendEmptyPacket (TcpHeader::ACK);
}
void TcpSocketImpl::CommonNewAck (SequenceNumber ack, bool skipTimer)
void TcpSocketImpl::CommonNewAck (SequenceNumber32 ack, bool skipTimer)
{ // CommonNewAck is called only for "New" (non-duplicate) acks
// and MUST be called by any subclass, from the NewAck function
// Always cancel any pending re-tx timer on new acknowledgement
@@ -1566,7 +1566,7 @@ Ptr<TcpSocketImpl> TcpSocketImpl::Copy ()
return CopyObject<TcpSocketImpl> (this);
}
void TcpSocketImpl::NewAck (SequenceNumber seq)
void TcpSocketImpl::NewAck (SequenceNumber32 seq)
{ // New acknowledgement up to sequence number "seq"
// Adjust congestion window in response to new ack's received
NS_LOG_FUNCTION (this << seq);
@@ -1704,7 +1704,7 @@ void TcpSocketImpl::Retransmit ()
// Calculate remaining data for COE check
uint32_t remainingData = m_pendingData->SizeFromSeq (
m_firstPendingSequence,
m_nextTxSequence + SequenceNumber(p->GetSize ()));
m_nextTxSequence + SequenceNumber32(p->GetSize ()));
if (m_closeOnEmpty && remainingData == 0)
{ // Add the FIN flag
flags = flags | TcpHeader::FIN;

View File

@@ -30,7 +30,7 @@
#include "ns3/event-id.h"
#include "tcp-typedefs.h"
#include "pending-data.h"
#include "sequence-number.h"
#include "ns3/sequence-number.h"
#include "rtt-estimator.h"
@@ -133,16 +133,16 @@ private:
// Manage data tx/rx
void NewRx (Ptr<Packet>, const TcpHeader&, const Address& fromAddress, const Address& toAddress);
void RxBufFinishInsert (SequenceNumber);
void RxBufFinishInsert (SequenceNumber32);
Ptr<TcpSocketImpl> Copy ();
virtual void NewAck (SequenceNumber seq);
virtual void NewAck (SequenceNumber32 seq);
virtual void DupAck (const TcpHeader& t, uint32_t count);
virtual void ReTxTimeout ();
void DelAckTimeout ();
void LastAckTimeout ();
void PersistTimeout ();
void Retransmit ();
void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
void CommonNewAck (SequenceNumber32 seq, bool skipTimer = false);
// All timers are cancelled when the endpoint is deleted, to insure
// we don't have additional activity
void CancelAllTimers();
@@ -194,16 +194,16 @@ private:
//sequence info, sender side
SequenceNumber m_nextTxSequence;
SequenceNumber m_highTxMark;
SequenceNumber m_highestRxAck;
SequenceNumber m_lastRxAck;
SequenceNumber32 m_nextTxSequence;
SequenceNumber32 m_highTxMark;
SequenceNumber32 m_highestRxAck;
SequenceNumber32 m_lastRxAck;
//sequence info, receiver side
SequenceNumber m_nextRxSequence; //next expected sequence
SequenceNumber32 m_nextRxSequence; //next expected sequence
//sequence number where fin was sent or received
SequenceNumber m_finSequence;
SequenceNumber32 m_finSequence;
//Rx buffer
UnAckData_t m_bufferedData; //buffer which sorts out of sequence data
@@ -216,7 +216,7 @@ private:
//this is kind of the tx buffer
PendingData* m_pendingData;
SequenceNumber m_firstPendingSequence;
SequenceNumber32 m_firstPendingSequence;
// Window management
uint32_t m_segmentSize; //SegmentSize

View File

@@ -21,7 +21,7 @@
#include <vector>
#include <map>
#include "sequence-number.h"
#include "ns3/sequence-number.h"
#ifndef TCP_TYPEDEFS_H
#define TCP_TYPEDEFS_H
@@ -95,7 +95,7 @@ typedef std::vector<StateActionVec_t> StateActions_t; // One per current state
typedef std::vector<Events_t> EventVec_t; // For flag events lookup
//type for managing buffered out of sequence data
typedef std::map<SequenceNumber, Ptr<Packet> > UnAckData_t;
typedef std::map<SequenceNumber32, Ptr<Packet> > UnAckData_t;
class TcpStateMachine {
public:

View File

@@ -93,7 +93,6 @@ def build(bld):
'udp-socket-factory-impl.cc',
'tcp-socket-factory-impl.cc',
'pending-data.cc',
'sequence-number.cc',
'rtt-estimator.cc',
'ipv4-raw-socket-factory-impl.cc',
'ipv4-raw-socket-impl.cc',
@@ -126,7 +125,6 @@ def build(bld):
headers.source = [
'udp-header.h',
'tcp-header.h',
'sequence-number.h',
'icmpv4.h',
'icmpv6-header.h',
# used by routing