merge from head

This commit is contained in:
Mathieu Lacage
2007-06-21 09:40:57 +02:00
24 changed files with 502 additions and 13 deletions

View File

@@ -1,3 +1,4 @@
56928998e05c9c11f5f3aefe79be8d2843e0db88 release ns-3.0.1
7ac5a4b0969b255c4824c926c2b37ef450136ce9 release ns-3.0.2
0dc81e76166c56aaae64da48b673b62155943aad packet-history-working
38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3

5
README
View File

@@ -23,7 +23,7 @@ will be contributed by the community in an open collaboration
process.
Contributing to the ns-3 project is still a very informal
process because that process depends heavily on the personality
process because that process depends heavily on the background
of the people involved, the amount of time they can invest
and the type of model they want to work on.
@@ -34,7 +34,7 @@ project. These steps are described in doc/contributing.txt
2) An overview of the ns-3 project
----------------------------------
This package contains the latest version of ns-3 which is aims
This package contains the latest version of ns-3 which aims
at being a replacement for ns-2. Currently, ns-3 provides a
number of very simple network simulation models:
- an ipv4 and udp stack
@@ -93,6 +93,7 @@ The current codebase is expected to fail to build on
the following platforms:
- gcc 3.3 and earlier
- optimized builds on linux x86 gcc 4.0
- cygwin
Other platforms may or may not work: we welcome
patches to improve the portability of the code to these

View File

@@ -422,6 +422,12 @@ sample_trace.add_dep('common')
sample_trace.set_executable()
sample_trace.add_source('main-trace.cc')
sample_query_interface = build.Ns3Module('sample-query-interface', 'samples')
ns3.add(sample_query_interface)
sample_query_interface.add_dep('common')
sample_query_interface.set_executable()
sample_query_interface.add_source('main-query-interface.cc')
sample_simu = build.Ns3Module('sample-simulator', 'samples')
ns3.add(sample_simu)
sample_simu.set_executable()

View File

@@ -1 +1 @@
3.0.2
3.0.3

19
doc/release_steps.txt Normal file
View File

@@ -0,0 +1,19 @@
Steps in doing an ns-3 release
1. prepare the source files
- revise and check in AUTHORS, if needed
- revise and check in RELEASE_NOTES
- update and check in VERSION to the latest release number
2. make a new "architecture.pdf" document and place it in the doc/ directory
3. scons dist
4. test tarball on release platforms (run-tests and simple-p2p)
5. tag ns-3-dev with "release ns-3.0.X"
6. clone the ns-3-dev and place it on the repository
7. upload "ns-3.0.x.tar.gz" to the releases/ directory on the server
8. update web page
- add link to news.html
- update download.html
- update roadmap.html
- build and update Doxygen directory on the server
- update and upload software architecture document (PDF, HTML)
9. announce to ns-developers, with summary of release notes

View File

@@ -0,0 +1,280 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 University of Washington
* Authors: Tom Henderson, Craig Dowell
*
* 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 "ns3/debug.h"
#include "ns3/object.h"
#include "ns3/component-manager.h"
using namespace ns3;
//
// This sample file shows examples of how to use QueryInterface.
//
// QueryInterface is a templated method of class Object, defined in
// src/core/object.h. ns-3 objects that derive from class Object
// can have QueryInterface invoked on them.
//
// QueryInterface is a type-safe way to ask an object, at run-time,
// "Do you support the interface identified by the given InterfaceId?"
// It avoids deprecated techniques of having to downcast pointers to
// an object to ask questions about its type. One or more interfaces
// may be associated with a given object.
//
// QueryInterface is of most use when working with base class
// pointers of objects that may be subclassed. For instance,
// one may have a pointer to a Node, but not know whether it has
// an IPv4 stack. Another example might be to determine whether
// a Node has an EnergyModel, to which calls to decrement energy
// from the node's battery might be made.
//
//
// Object is the base class for ns-3 node-related objects used at
// the public API. Object provides reference counting implementations
// and the QueryInterface.
//
// A common design paradigm for an ns-3 node object, such as a Queue,
// is that we provide an abstract base class that inherits from
// Object. This class is assigned an interface ID (iid) and
// contains the basic API for objects in this class and subclasses.
// This base class is specialized to provide implementations of
// the object in question (such as a DropTailQueue).
//
// The design pattern commonly used is known as the "non-virtual
// public interface" pattern, whereby the public API for this
// object is a set of public non-virtual functions that forward
// to private virtual functions. The forwarding functions can
// impose pre- and post-conditions on the forwarding call at
// the base class level.
//
// We'll call this base class "AnInterface" in the example below.
//
//
class AnInterface : public Object
{
public:
static const InterfaceId iid;
void methodA (void);
private:
virtual void domethodA (void) = 0;
};
void
AnInterface::methodA (void)
{
// pre-dispatch asserts
NS_DEBUG_UNCOND("AnInterface pre-condition::methodA");
domethodA ();
NS_DEBUG_UNCOND("AnInterface post-condition::methodA\n");
// post-dispatch asserts
}
//
// The below assignment assigns the InterfaceId of the class AnInterface,
// and declares that the parent iid is that of class Object.
//
const InterfaceId AnInterface::iid = MakeInterfaceId ("AnInterface", Object::iid);
//
// AnImplementation is an implementation of the abstract base class
// defined above. It provides implementation for the virtual functions
// in the base class. It defines one ClassId for each constructor,
// and can also provide an interface itself (in this example,
// a methodImpl is available)
//
class AnImplementation : public AnInterface
{
public:
static const InterfaceId iid;
static const ClassId cid;
AnImplementation ();
void methodImpl (void);
private:
virtual void domethodA (void);
};
void
AnImplementation::methodImpl (void)
{
NS_DEBUG_UNCOND("AnImplementation::methodImpl\n");
}
AnImplementation::AnImplementation (void)
{
// enable our interface
SetInterfaceId (AnImplementation::iid);
}
void
AnImplementation::domethodA ()
{
NS_DEBUG_UNCOND("AnImplementation::domethodA");
}
//
// The below assignment assigns the InterfaceId of the class AnImplementation,
// and declares that the parent iid is that of class Object.
//
const InterfaceId AnImplementation::iid =
MakeInterfaceId ("AnImplementation", AnInterface::iid);
//
// The next few lines are used by the component manager. They
// state that the component manager can create a new object
// AnImplementation and return an interface corresponding to
// the AnImplementation iid.
//
const ClassId AnImplementation::cid =
MakeClassId<AnImplementation>
("AnImplementation", AnImplementation::iid);
//
// Extending interfaces
// ==================
// What if AnInterface doesn't provide enough API for your
// object type?
// - if you aren't concerned about backward compatibility and
// don't mind recompiling, you just add new methods to AnInterface
// and recompile.
// - if you want to address backward compatibiliy, or allow part
// of the system to use the old interface, you have to do more.
// You have to declare a new interface with the new functionality.
//
class AnExtendedInterface : public AnInterface
{
public:
static const InterfaceId iid;
void methodB (void);
private:
virtual void domethodB (void) = 0;
};
const InterfaceId AnExtendedInterface::iid =
MakeInterfaceId ("AnExtendedInterface", AnInterface::iid);
//
// Then you need provide an implementation for the virtual
// methods. If you are providing a new implementation for
// everything, the answer is straightforward
//
class ANewImplementation : public AnExtendedInterface
{
public:
static const InterfaceId iid;
static const ClassId cid;
ANewImplementation ();
void methodImpl (void);
private:
virtual void domethodA (void) { /* new-implementation-behavior (); */}
virtual void domethodB (void) { /* new-implementation-behavior (); */}
};
ANewImplementation::ANewImplementation (void)
{
// enable our interface
SetInterfaceId (ANewImplementation::iid);
}
void
ANewImplementation::methodImpl (void)
{
NS_DEBUG_UNCOND("ANewImplementation::methodImpl\n");
}
const InterfaceId ANewImplementation::iid =
MakeInterfaceId ("ANewImplementation", AnExtendedInterface::iid);
//
// If you want to extend an existing implementation, you can use
// the existing class to instantiate an implementation of its
// methods (hasa) and do the following if you can use stuff from
// the existing class.
//
class AnExtendedImplementation : public AnExtendedInterface
{
public:
static const InterfaceId iid;
static const ClassId cid;
AnExtendedImplementation ();
void methodImpl (void) { /* pImpl->methodImpl (); */ }
void methodExtendedImpl (void);
private:
virtual void domethodA (void) { /* new-implementation-behavior (); */}
virtual void domethodB (void) { /* new-implementation-behavior (); */}
Ptr<AnImplementation> pImpl;
};
AnExtendedImplementation::AnExtendedImplementation (void)
{
pImpl = Create<AnImplementation> ();
SetInterfaceId (AnExtendedImplementation::iid);
}
void
AnExtendedImplementation::methodExtendedImpl (void)
{
NS_DEBUG_UNCOND("AnExtendedImplementation::methodExtendedImpl\n");
}
const InterfaceId AnExtendedImplementation::iid =
MakeInterfaceId ("AnExtendedImplementation", AnExtendedInterface::iid);
//
// Inheriting from an existing implementation (isa) and an extended
// interface is tricky, because of the diamond multiple inheritance
// problem. If the pImpl method above is not desirable, it may
// be that the implementation extension could be aggregated.
//
// The extension will not have access to the base implementation,
// so this design pattern may be more appropriate if the extension
// is very modular (e.g., add an EnergyModel to a wireless interface)
//
// EXAMPLE NOT YET PROVIDED
int main (int argc, char *argv[])
{
Ptr<AnInterface> aBase = ComponentManager::Create<AnImplementation>
(AnImplementation::cid, AnInterface::iid);
NS_ASSERT (aBase != 0);
aBase->methodA ();
//aBase->methodImpl (); // XXX won't compile, aBase not right ptr type
Ptr<AnImplementation> aBaseImplPtr =
aBase-> QueryInterface<AnImplementation> (AnImplementation::iid);
aBaseImplPtr->methodImpl ();
aBaseImplPtr->methodA();
// Test symmetric property of QueryInterface
Ptr<AnInterface> aBase2 =
aBaseImplPtr-> QueryInterface<AnInterface> (AnInterface::iid);
aBase2->methodA ();
return 0;
}

View File

@@ -1,6 +1,10 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-applications')
def build(bld):
obj = bld.create_obj('cpp', 'shlib')
obj.name = 'ns3-applications'

View File

@@ -53,6 +53,10 @@ private:
/**
* \returns the size of the serialized Header.
*
* This method is used by Packet::AddHeader to reserve
* enough room in the packet byte buffer prior to calling
* Header::Serialize.
*/
virtual uint32_t GetSerializedSize (void) const = 0;
@@ -67,6 +71,10 @@ private:
* deserialize itself. This iterator identifies
* the start of the buffer.
* \returns the number of bytes read from the buffer
*
* The value returned is used to trim the packet byte buffer of the
* corresponding amount when this method is invoked from
* Packet::RemoveHeader
*/
virtual uint32_t DeserializeFrom (Buffer::Iterator start) = 0;
};

View File

@@ -144,3 +144,58 @@ Packet::EnableMetadata (void)
}
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
#include <string>
namespace ns3 {
class PacketTest: public Test {
public:
virtual bool RunTests (void);
PacketTest ();
};
PacketTest::PacketTest ()
: Test ("Packet") {}
bool
PacketTest::RunTests (void)
{
bool ok = true;
Packet pkt1 (reinterpret_cast<const uint8_t*> ("hello"), 5);
Packet pkt2 (reinterpret_cast<const uint8_t*> (" world"), 6);
Packet packet;
packet.AddAtEnd (pkt1);
packet.AddAtEnd (pkt2);
if (packet.GetSize () != 11)
{
Failure () << "expected size 11, got " << packet.GetSize () << std::endl;
ok = false;
}
std::string msg = std::string (reinterpret_cast<const char *>(packet.PeekData ()),
packet.GetSize ());
if (msg != "hello world")
{
Failure () << "expected size 'hello world', got " << msg << std::endl;
ok = false;
}
return ok;
}
static PacketTest gPacketTest;
}; // namespace ns3
#endif /* RUN_SELF_TESTS */

View File

@@ -36,6 +36,32 @@ namespace ns3 {
* - ns3::Trailer::DeserializeFrom
* - ns3::Trailer::GetSerializedSize
* - ns3::Trailer::PrintTo
*
* Note that the SerializeTo and DeserializeFrom methods behave
* in a way which might seem surprising to users: the input iterator
* really points to the end of the buffer to which and from which
* the user is expected to write and read respectively. This means that
* if the trailer has a fixed size and if the user wishes to read or
* write that trailer from front to back, the user must rewind the
* iterator by hand to go to the start of the trailer. Typical code
* looks like this:
* \code
* void CrcTrailer::SerializeTo (Buffer::Iterator end)
* {
* end.Prev (4);
* end.WriteHtonU32 (m_crc);
* }
* \endcode
*
* Some users would have expected that the iterator would be rewinded
* to the "start" of the trailer before calling SerializeTo and DeserializeFrom.
* However, this behavior was not implemented because it cannot be made to
* work reliably for trailers which have a variable size. i.e., if the trailer
* contains options, the code which calls DeserializeFrom cannot rewind
* to the start of the trailer because it does not know the real size of the
* trailer. Hence, to make this legitimate use-case work (variable-sized
* trailers), the input iterator to DeserializeFrom and SerializeTo points
* to the end of the trailer, and not its start.
*/
class Trailer : public Chunk {
public:
@@ -53,6 +79,10 @@ private:
/**
* \returns the size of the serialized Trailer.
*
* This method is used by Packet::AddTrailer to reserve
* enough room in the packet byte buffer prior to calling
* Trailer::Serialize.
*/
virtual uint32_t GetSerializedSize (void) const = 0;
@@ -60,6 +90,9 @@ private:
* \param end the buffer iterator in which the protocol trailer
* must serialize itself. This iterator identifies
* the end of the buffer.
*
* This iterator must be typically moved with the Buffer::Iterator::Prev
* method before writing any byte in the buffer.
*/
virtual void SerializeTo (Buffer::Iterator end) const = 0;
/**
@@ -67,6 +100,11 @@ private:
* deserialize itself. This iterator identifies
* the end of the buffer.
* \returns the number of bytes read from the buffer
*
* This iterator must be typically moved with the Buffer::Iterator::Prev
* method before reading any byte in the buffer. The value returned
* is used to trim the packet byte buffer of the corresponding
* amount when this method is invoked from Packet::RemoveTrailer
*/
virtual uint32_t DeserializeFrom (Buffer::Iterator end) = 0;
};

View File

@@ -1,5 +1,7 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-common')
def build(bld):
common = bld.create_obj('cpp', 'shlib')

View File

@@ -101,6 +101,41 @@ private:
};
}; // namespace ns3
/**
* Convenience macro to check that a value returned by a test is what
* is expected. Note: this macro assumes a 'bool result = true'
* declaration exists in the test function body, and that the function
* returns that value.
*
* \param got value obtained from the test
* \param expected value that the test is expected to return
*/
#define NS_TEST_ASSERT_EQUAL(got, expected) \
if ((got) != (expected)) \
{ \
Failure () << __FILE__ << ":" <<__LINE__ \
<< ": expected " << (expected) \
<< ", got " << (got) << std::endl; \
result = false; \
}
/**
* Convenience macro to check an assertion is held during an unit
* test. Note: this macro assumes a 'bool result = true' declaration
* exists in the test function body, and that the function returns
* that value.
*
* \param assertion expression that must be true if the test did not fail
*/
#define NS_TEST_ASSERT(assertion) \
if (!(assertion)) \
{ \
Failure () << __FILE__ << ":" <<__LINE__ \
<< ": assertion `" << (assertion) \
<< "'failed." << std::endl; \
result = false; \
}
#endif /* RUN_SELF_TESTS */
#endif /* TEST_H */

View File

@@ -3,6 +3,8 @@ import sys
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-core')
e = conf.create_header_configurator()
e.mandatory = False
e.name = 'stdlib.h'

View File

@@ -1,6 +1,10 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-p2p')
def build(bld):
p2p = bld.create_obj('cpp', 'shlib')
p2p.name = 'ns3-p2p'

View File

@@ -1,6 +1,10 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-internet-node')
def build(bld):
obj = bld.create_obj('cpp', 'shlib')
obj.name = 'ns3-internet-node'

View File

@@ -215,6 +215,11 @@ bool operator != (Ipv4Address const &a, Ipv4Address const &b)
{
return !a.IsEqual (b);
}
bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB)
{
return (addrA.GetHostOrder () < addrB.GetHostOrder ());
}
size_t Ipv4AddressHash::operator()(Ipv4Address const &x) const
{
return x.GetHostOrder ();
@@ -230,6 +235,14 @@ std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask)
mask.Print (os);
return os;
}
bool operator == (Ipv4Mask const &a, Ipv4Mask const &b)
{
return a.IsEqual (b);
}
bool operator != (Ipv4Mask const &a, Ipv4Mask const &b)
{
return !a.IsEqual (b);
}
}; // namespace ns3

View File

@@ -122,11 +122,15 @@ std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
bool operator == (Ipv4Address const &a, Ipv4Address const &b);
bool operator != (Ipv4Address const &a, Ipv4Address const &b);
bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB);
class Ipv4AddressHash : public std::unary_function<Ipv4Address, size_t> {
public:
size_t operator()(Ipv4Address const &x) const;
};
bool operator != (Ipv4Address const &a, Ipv4Address const &b);
bool operator == (Ipv4Mask const &a, Ipv4Mask const &b);
bool operator != (Ipv4Mask const &a, Ipv4Mask const &b);
}; // namespace ns3

View File

@@ -1,5 +1,8 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-node')
def build(bld):
node = bld.create_obj('cpp', 'shlib')

View File

@@ -658,7 +658,7 @@ _cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den)
* Compute a 32 bit quotient and 64 bit remainder of a 96 bit unsigned
* dividend and 64 bit divisor. If the quotient doesn't fit into 32
* bits then the returned remainder is equal to the divisor, and the
* qoutient is the largest representable 64 bit integer. It is an
* quotient is the largest representable 64 bit integer. It is an
* error to call this function with the high 32 bits of @num being
* non-zero. */
cairo_uquorem64_t
@@ -776,7 +776,7 @@ _cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den)
{
int num_neg = _cairo_int128_negative (num);
int den_neg = _cairo_int64_negative (den);
cairo_int64_t nonneg_den = den;
cairo_uint64_t nonneg_den;
cairo_uquorem64_t uqr;
cairo_quorem64_t qr;
@@ -784,9 +784,11 @@ _cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den)
num = _cairo_int128_negate (num);
if (den_neg)
nonneg_den = _cairo_int64_negate (den);
else
nonneg_den = den;
uqr = _cairo_uint_96by64_32x64_divrem (num, nonneg_den);
if (_cairo_uint64_eq (uqr.rem, nonneg_den)) {
if (_cairo_uint64_eq (uqr.rem, _cairo_int64_to_uint64 (nonneg_den))) {
/* bail on overflow. */
qr.quo = _cairo_uint32s_to_uint64 (0x7FFFFFFF, -1U);;
qr.rem = den;

View File

@@ -13,6 +13,8 @@ def set_options(opt):
def configure(conf):
conf.env.append_value('NS3_MODULES', 'ns3-simulator')
if Params.g_options.high_precision_as_double:
conf.add_define('USE_HIGH_PRECISION_DOUBLE', 1)
conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1

View File

@@ -29,6 +29,7 @@ def configure(conf):
blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
for module in all_modules:
conf.sub_config(module)
conf.env.append_value('NS3_MODULE_PATH', os.path.join(blddir, 'src', module))

View File

@@ -1,23 +1,23 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import sys
import Params
def build(bld):
env = bld.env_of_name('default')
def create_ns_prog(name, source):
obj = bld.create_obj('cpp', 'program')
obj.target = name
obj.uselib_local = "ns3-core ns3-common ns3-simulator"
obj.source = source
return obj
unit_tests = create_ns_prog('run-tests', 'run-tests.cc')
unit_tests.install_var = 0 # do not install
unit_tests.unit_test = 1 # runs on 'waf check'
## link unit test program with all ns3 modules
unit_tests.uselib_local = env['NS3_MODULES']
#if sys.platform != 'win32':
obj = create_ns_prog('bench-simulator', 'bench-simulator.cc')
obj.uselib_local = "ns3-core ns3-common ns3-simulator"
obj = create_ns_prog('replay-simulation', 'replay-simulation.cc')
## bench-packets requires missing header files
#obj = create_ns_prog('bench-packets', 'bench-packets.cc')
obj.uselib_local = "ns3-core ns3-common ns3-simulator"

1
waf.bat Executable file
View File

@@ -0,0 +1 @@
@python -x waf %* & exit /b

View File

@@ -79,6 +79,7 @@ def configure(conf):
conf.setenv(variant_name)
variant_env.append_value('CXXDEFINES', 'RUN_SELF_TESTS')
variant_env.append_value('CXXFLAGS', ['-Wall', '-Werror'])
if 'debug' in Params.g_options.debug_level.lower():
variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE')
variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')
@@ -141,6 +142,9 @@ def _run_argv(argv):
elif sys.platform == 'win32':
pathvar = 'PATH'
pathsep = ';'
elif sys.platform == 'cygwin':
pathvar = 'PATH'
pathsep = ':'
else:
Params.warning(("Don't know how to configure "
"dynamic library path for the platform '%s'") % (sys.platform,))