1.1 --- a/AUTHORS Mon Nov 09 13:32:18 2009 -0500
1.2 +++ b/AUTHORS Mon Nov 09 13:36:23 2009 -0500
1.3 @@ -12,23 +12,33 @@
1.4 Craig Dowell (craigdo@ee.washington.edu)
1.5 David Gross (gdavid.devel@gmail.com)
1.6 Tom Henderson (tomhend@u.washington.edu)
1.7 -Andrey Mazo (mazo@iitp.ru)
1.8 Sam Jansen (sam.jansen@gmail.com)
1.9 Liu Jian (liujatp@gmail.com)
1.10 Joe Kopena (tjkopena@cs.drexel.edu)
1.11 Aleksey Kovalenko (kovalenko@iitp.ru)
1.12 Mathieu Lacage (mathieu.lacage@sophia.inria.fr)
1.13 Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca)
1.14 +Keith Ma (keith.nwsuaf@gmail.com)
1.15 Federico Maguolo (maguolof@dei.unipd.it)
1.16 +Antti Makela (zarhan@cc.hut.fi)
1.17 Francesco Malandrino (francesco.malandrino@gmail.com)
1.18 +Fabian Mauchle (f1mauchl@hsr.ch)
1.19 +Andrey Mazo (mazo@iitp.ru)
1.20 Faker Moatamri (faker.moatamri@sophia.inria.fr)
1.21 Duy Nguyen (duy@soe.ucsc.edu)
1.22 +Tommaso Pecorella (tommaso.pecorella@unifi.it)
1.23 +Yana Podkosova (yanapdk@rambler.ru)
1.24 Guangyu Pei (guangyu.pei@boeing.com)
1.25 George F. Riley (riley@ece.gatech.edu)
1.26 Providence Salumu Munga (Providence.Salumu@gmail.com, Providence.Salumu_Munga@it-sudparis.eu)
1.27 +Guillaume Seguin (guillaume.seguin@sophia.inria.fr)
1.28 Kulin Shah (m.kulin@gmail.com)
1.29 +Ewgenij Starostin (estar@cs.tu-berlin.de)
1.30 +Adrian S. W. Tam (adrian.sw.tam@gmail.com)
1.31 +Wilson Thong (wilsonwk@ee.cityu.edu.hk)
1.32 Mauro Tortonesi (mauro.tortonesi@unife.it)
1.33 Sebastien Vincent (vincent@clarinet.u-strasbg.fr)
1.34 Guillaume Vu-Brugier (gvubrugier@gmail.com)
1.35 +Tom Wambold (tom5760@gmail.com)
1.36 Florian Westphal (fw@strlen.de)
1.37 Josh Pelkey (jpelkey@gatech.edu)
2.1 --- a/RELEASE_NOTES Mon Nov 09 13:32:18 2009 -0500
2.2 +++ b/RELEASE_NOTES Mon Nov 09 13:36:23 2009 -0500
2.3 @@ -21,7 +21,6 @@
2.4 - linux x86_64 gcc 4.4.0, 4.3.2, 4.2.3, 4.2.1, 4.1.3, 3.4.6
2.5 - MacOS X ppc and x86 (gcc 4.0.x and 4.2.x)
2.6 - cygwin gcc 3.4.4 (debug only), gcc 4.3.2 (debug and optimized)
2.7 - - mingw gcc 3.4.5 (debug only)
2.8
2.9 Not all ns-3 options are available on all platforms; consult the
2.10 wiki for more information:
2.11 @@ -78,7 +77,7 @@
2.12
2.13 Known issues
2.14 ------------
2.15 -ns-3 build is known to fail on the following platforms:
2.16 +ns-3.6 build is known to fail on the following platforms:
2.17 - gcc 3.3 and earlier
2.18 - optimized builds on gcc 3.4.4 and 3.4.5
2.19 - optimized builds on linux x86 gcc 4.0.x
3.1 --- a/src/common/pcap-file-test-suite.cc Mon Nov 09 13:32:18 2009 -0500
3.2 +++ b/src/common/pcap-file-test-suite.cc Mon Nov 09 13:36:23 2009 -0500
3.3 @@ -107,7 +107,7 @@
3.4 std::stringstream filename;
3.5 uint32_t n = rand ();
3.6 filename << n;
3.7 - m_testFilename = "/tmp/" + filename.str () + ".pcap";
3.8 + m_testFilename = GetTempDir () + filename.str () + ".pcap";
3.9 }
3.10
3.11 void
3.12 @@ -218,7 +218,7 @@
3.13 std::stringstream filename;
3.14 uint32_t n = rand ();
3.15 filename << n;
3.16 - m_testFilename = "/tmp/" + filename.str () + ".pcap";
3.17 + m_testFilename = GetTempDir () + filename.str () + ".pcap";
3.18 }
3.19
3.20 void
3.21 @@ -317,7 +317,7 @@
3.22 std::stringstream filename;
3.23 uint32_t n = rand ();
3.24 filename << n;
3.25 - m_testFilename = "/tmp/" + filename.str () + ".pcap";
3.26 + m_testFilename = GetTempDir () + filename.str () + ".pcap";
3.27 }
3.28
3.29 void
3.30 @@ -416,7 +416,7 @@
3.31 std::stringstream filename;
3.32 uint32_t n = rand ();
3.33 filename << n;
3.34 - m_testFilename = "/tmp/" + filename.str () + ".pcap";
3.35 + m_testFilename = GetTempDir () + filename.str () + ".pcap";
3.36 }
3.37
3.38 void
3.39 @@ -607,7 +607,7 @@
3.40 std::stringstream filename;
3.41 uint32_t n = rand ();
3.42 filename << n;
3.43 - m_testFilename = "/tmp/" + filename.str () + ".pcap";
3.44 + m_testFilename = GetTempDir () + filename.str () + ".pcap";
3.45 }
3.46
3.47 void
4.1 --- a/src/contrib/net-anim/animation-interface.cc Mon Nov 09 13:32:18 2009 -0500
4.2 +++ b/src/contrib/net-anim/animation-interface.cc Mon Nov 09 13:36:23 2009 -0500
4.3 @@ -21,9 +21,15 @@
4.4 #include <stdio.h>
4.5 #include <sstream>
4.6
4.7 +#include "ns3/net-anim-config.h"
4.8 +
4.9 // Socket related includes
4.10 -#include <sys/socket.h>
4.11 -#include <netinet/in.h>
4.12 +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
4.13 +# include <sys/socket.h>
4.14 +# include <netinet/in.h>
4.15 +#else
4.16 +#include <fcntl.h>
4.17 +#endif
4.18
4.19 // ns3 includes
4.20 #include "ns3/animation-interface.h"
4.21 @@ -58,6 +64,7 @@
4.22
4.23 bool AnimationInterface::SetServerPort (uint16_t port)
4.24 {
4.25 +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
4.26 int s = socket (AF_INET, SOCK_STREAM, 0);
4.27 struct sockaddr_in addr;
4.28 addr.sin_family = AF_INET;
4.29 @@ -77,6 +84,8 @@
4.30 int t = 1;
4.31 setsockopt (s, SOL_SOCKET, SO_LINGER, &t, sizeof(t));
4.32 return true;
4.33 +#endif
4.34 + return false;//never reached unless the above is disabled
4.35 }
4.36
4.37 bool AnimationInterface::SetInternalAnimation ()
5.1 --- a/src/contrib/net-anim/point-to-point-dumbbell-helper.cc Mon Nov 09 13:32:18 2009 -0500
5.2 +++ b/src/contrib/net-anim/point-to-point-dumbbell-helper.cc Mon Nov 09 13:36:23 2009 -0500
5.3 @@ -21,10 +21,6 @@
5.4 #include <iostream>
5.5 #include <sstream>
5.6
5.7 -// Socket related includes
5.8 -#include <sys/socket.h>
5.9 -#include <netinet/in.h>
5.10 -
5.11 // ns3 includes
5.12 #include "ns3/animation-interface.h"
5.13 #include "ns3/point-to-point-dumbbell-helper.h"
6.1 --- a/src/contrib/net-anim/wscript Mon Nov 09 13:32:18 2009 -0500
6.2 +++ b/src/contrib/net-anim/wscript Mon Nov 09 13:36:23 2009 -0500
6.3 @@ -1,5 +1,11 @@
6.4 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
6.5
6.6 +def configure(conf):
6.7 + conf.check(header_name='sys/socket.h', define_name='HAVE_SYS_SOCKET_H')
6.8 + conf.check(header_name='netinet/in.h', define_name='HAVE_NETINET_IN_H')
6.9 + conf.write_config_header('ns3/net-anim-config.h', top=True)
6.10 +
6.11 +
6.12 def build(bld):
6.13 obj = bld.create_ns3_module('net-anim')
6.14 obj.source = [
7.1 --- a/src/contrib/wscript Mon Nov 09 13:32:18 2009 -0500
7.2 +++ b/src/contrib/wscript Mon Nov 09 13:36:23 2009 -0500
7.3 @@ -14,9 +14,11 @@
7.4 conf.report_optional_feature("XmlIo", "XmlIo",
7.5 conf.env['ENABLE_LIBXML2'],
7.6 "library 'libxml-2.0 >= 2.7' not found")
7.7 + conf.write_config_header('ns3/contrib-config.h', top=True)
7.8 +
7.9 conf.sub_config('stats')
7.10 + conf.sub_config('net-anim')
7.11
7.12 - conf.write_config_header('ns3/contrib-config.h', top=True)
7.13
7.14 def build(bld):
7.15 module = bld.create_ns3_module('contrib', ['simulator', 'common'])
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/src/core/object-ref-count.h Mon Nov 09 13:36:23 2009 -0500
8.3 @@ -0,0 +1,120 @@
8.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
8.5 +/*
8.6 + * Copyright (c) 2009 Mathieu Lacage
8.7 + *
8.8 + * This program is free software; you can redistribute it and/or modify
8.9 + * it under the terms of the GNU General Public License version 2 as
8.10 + * published by the Free Software Foundation;
8.11 + *
8.12 + * This program is distributed in the hope that it will be useful,
8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.15 + * GNU General Public License for more details.
8.16 + *
8.17 + * You should have received a copy of the GNU General Public License
8.18 + * along with this program; if not, write to the Free Software
8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8.20 + *
8.21 + * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
8.22 + */
8.23 +#ifndef OBJECT_REF_COUNT_H
8.24 +#define OBJECT_REF_COUNT_H
8.25 +
8.26 +#include "empty.h"
8.27 +
8.28 +namespace ns3 {
8.29 +
8.30 +/**
8.31 + * This templated class provides the refcounting implementation
8.32 + * for the ns3::Object class.
8.33 + *
8.34 + * The tricky aspect of the implementation of this class is that
8.35 + * instead of storing a count directly, it keeps track of a pointer
8.36 + * to a count to allow multiple instances of the class to share the
8.37 + * same pointer/count. This is mainly used by the aggregation support
8.38 + * of the ns3::Object class
8.39 + */
8.40 +template <typename T, typename PARENT = empty>
8.41 +class ObjectRefCount : public PARENT
8.42 +{
8.43 +public:
8.44 + ObjectRefCount ()
8.45 + : m_count (new int (1))
8.46 + {}
8.47 + ObjectRefCount (const ObjectRefCount &o)
8.48 + : m_count (new int (1))
8.49 + {}
8.50 + ObjectRefCount & operator = (const ObjectRefCount &o)
8.51 + {
8.52 + return *this;
8.53 + }
8.54 + ~ObjectRefCount ()
8.55 + {
8.56 + m_count = 0;
8.57 + }
8.58 +
8.59 + /**
8.60 + * Get the reference count of the object. Normally not needed; for language bindings.
8.61 + */
8.62 + int GetReferenceCount (void) const {
8.63 + return *m_count;
8.64 + }
8.65 + /**
8.66 + * Increment the reference count. This method should not be called
8.67 + * by user code. Object instances are expected to be used in conjunction
8.68 + * of the Ptr template which would make calling Ref unecessary and
8.69 + * dangerous.
8.70 + */
8.71 + inline void Ref (void) const
8.72 + {
8.73 + (*m_count)++;
8.74 + }
8.75 + /**
8.76 + * Decrement the reference count. This method should not be called
8.77 + * by user code. Object instances are expected to be used in conjunction
8.78 + * of the Ptr template which would make calling Ref unecessary and
8.79 + * dangerous.
8.80 + */
8.81 + inline void Unref (void) const
8.82 + {
8.83 + (*m_count)--;
8.84 + if ((*m_count) == 0)
8.85 + {
8.86 + const_cast<ObjectRefCount<T,PARENT>*>(this)->DoDelete ();
8.87 + }
8.88 + }
8.89 +protected:
8.90 + /**
8.91 + * \param other another object
8.92 + *
8.93 + * This method makes this object and the input other object
8.94 + * share the same reference count.
8.95 + */
8.96 + void ShareCount (ObjectRefCount *other)
8.97 + {
8.98 + (*m_count) += (*other->m_count);
8.99 + delete other->m_count;
8.100 + other->m_count = m_count;
8.101 + }
8.102 + /**
8.103 + * Called just before deleting this object: when two
8.104 + * objects share the same reference count, the user
8.105 + * who is deleting them must be careful to delete the
8.106 + * associated count only once and this is done by calling
8.107 + * this method to get a reference to the count and, then,
8.108 + * calling delete on the count.
8.109 + *
8.110 + * \sa ns3::Object::DoDelete
8.111 + */
8.112 + int *PeekCountPtr (void) const
8.113 + {
8.114 + return m_count;
8.115 + }
8.116 +private:
8.117 + virtual void DoDelete (void) = 0;
8.118 + mutable int *m_count;
8.119 +};
8.120 +
8.121 +} // namespace ns3
8.122 +
8.123 +#endif /* OBJECT_REF_COUNT_H */
9.1 --- a/src/core/object.cc Mon Nov 09 13:32:18 2009 -0500
9.2 +++ b/src/core/object.cc Mon Nov 09 13:36:23 2009 -0500
9.3 @@ -28,6 +28,8 @@
9.4 #include "string.h"
9.5 #include <vector>
9.6 #include <sstream>
9.7 +#include <stdlib.h>
9.8 +#include <string.h>
9.9
9.10 NS_LOG_COMPONENT_DEFINE ("Object");
9.11
9.12 @@ -40,28 +42,23 @@
9.13 NS_OBJECT_ENSURE_REGISTERED (Object);
9.14
9.15 Object::AggregateIterator::AggregateIterator ()
9.16 - : m_first (0),
9.17 + : m_object (0),
9.18 m_current (0)
9.19 {}
9.20
9.21 bool
9.22 Object::AggregateIterator::HasNext (void) const
9.23 {
9.24 - if (m_current != 0 && m_current->m_next != PeekPointer (m_first))
9.25 - {
9.26 - return true;
9.27 - }
9.28 - return false;
9.29 + return m_current < m_object->m_aggregates->n;
9.30 }
9.31 Ptr<const Object>
9.32 Object::AggregateIterator::Next (void)
9.33 {
9.34 - m_current = m_current->m_next;
9.35 - return m_current;
9.36 + return m_object->m_aggregates->buffer[m_current];
9.37 }
9.38 -Object::AggregateIterator::AggregateIterator (Ptr<const Object> first)
9.39 - : m_first (first),
9.40 - m_current (first)
9.41 +Object::AggregateIterator::AggregateIterator (Ptr<const Object> object)
9.42 + : m_object (object),
9.43 + m_current (0)
9.44 {}
9.45
9.46
9.47 @@ -82,25 +79,45 @@
9.48
9.49
9.50 Object::Object ()
9.51 - : m_count (1),
9.52 - m_tid (Object::GetTypeId ()),
9.53 + : m_tid (Object::GetTypeId ()),
9.54 m_disposed (false),
9.55 - m_next (this)
9.56 -{}
9.57 + m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
9.58 + m_getObjectCount (0)
9.59 +{
9.60 + m_aggregates->n = 1;
9.61 + m_aggregates->buffer[0] = this;
9.62 +}
9.63 Object::~Object ()
9.64 {
9.65 - m_next = 0;
9.66 + // remove this object from the aggregate list
9.67 + uint32_t n = m_aggregates->n;
9.68 + for (uint32_t i = 0; i < n; i++)
9.69 + {
9.70 + Object *current = m_aggregates->buffer[i];
9.71 + if (current == this)
9.72 + {
9.73 + memmove (&m_aggregates->buffer[i],
9.74 + &m_aggregates->buffer[i+1],
9.75 + sizeof (Object *)*(m_aggregates->n - (i+1)));
9.76 + m_aggregates->n--;
9.77 + }
9.78 + }
9.79 + // finally, if all objects have been removed from the list,
9.80 + // delete the aggregate list
9.81 + if (m_aggregates->n == 0)
9.82 + {
9.83 + free (m_aggregates);
9.84 + }
9.85 + m_aggregates = 0;
9.86 }
9.87 Object::Object (const Object &o)
9.88 - : m_count (1),
9.89 - m_tid (o.m_tid),
9.90 + : m_tid (o.m_tid),
9.91 m_disposed (false),
9.92 - m_next (this)
9.93 -{}
9.94 -uint32_t
9.95 -Object::GetReferenceCount (void) const
9.96 + m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
9.97 + m_getObjectCount (0)
9.98 {
9.99 - return m_count;
9.100 + m_aggregates->n = 1;
9.101 + m_aggregates->buffer[0] = this;
9.102 }
9.103 void
9.104 Object::Construct (const AttributeList &attributes)
9.105 @@ -112,34 +129,58 @@
9.106 Object::DoGetObject (TypeId tid) const
9.107 {
9.108 NS_ASSERT (CheckLoose ());
9.109 - const Object *currentObject = this;
9.110 +
9.111 + uint32_t n = m_aggregates->n;
9.112 TypeId objectTid = Object::GetTypeId ();
9.113 - do {
9.114 - NS_ASSERT (currentObject != 0);
9.115 - TypeId cur = currentObject->GetInstanceTypeId ();
9.116 - while (cur != tid && cur != objectTid)
9.117 - {
9.118 - cur = cur.GetParent ();
9.119 - }
9.120 - if (cur == tid)
9.121 - {
9.122 - return const_cast<Object *> (currentObject);
9.123 - }
9.124 - currentObject = currentObject->m_next;
9.125 - } while (currentObject != this);
9.126 + for (uint32_t i = 0; i < n; i++)
9.127 + {
9.128 + Object *current = m_aggregates->buffer[i];
9.129 + TypeId cur = current->GetInstanceTypeId ();
9.130 + while (cur != tid && cur != objectTid)
9.131 + {
9.132 + cur = cur.GetParent ();
9.133 + }
9.134 + if (cur == tid)
9.135 + {
9.136 + // This is an attempt to 'cache' the result of this lookup.
9.137 + // the idea is that if we perform a lookup for a TypeId on this object,
9.138 + // we are likely to perform the same lookup later so, we make sure
9.139 + // that the aggregate array is sorted by the number of accesses
9.140 + // to each object.
9.141 +
9.142 + // first, increment the access count
9.143 + current->m_getObjectCount++;
9.144 + // then, update the sort
9.145 + UpdateSortedArray (m_aggregates, i);
9.146 + // finally, return the match
9.147 + return const_cast<Object *> (current);
9.148 + }
9.149 + }
9.150 return 0;
9.151 }
9.152 void
9.153 Object::Dispose (void)
9.154 {
9.155 - Object *current = this;
9.156 - do {
9.157 - NS_ASSERT (current != 0);
9.158 - NS_ASSERT (!current->m_disposed);
9.159 - current->DoDispose ();
9.160 - current->m_disposed = true;
9.161 - current = current->m_next;
9.162 - } while (current != this);
9.163 + uint32_t n = m_aggregates->n;
9.164 + for (uint32_t i = 0; i < n; i++)
9.165 + {
9.166 + Object *current = m_aggregates->buffer[i];
9.167 + NS_ASSERT (!current->m_disposed);
9.168 + current->DoDispose ();
9.169 + current->m_disposed = true;
9.170 + }
9.171 +}
9.172 +void
9.173 +Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
9.174 +{
9.175 + while (j > 0 &&
9.176 + aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount)
9.177 + {
9.178 + Object *tmp = aggregates->buffer[j-1];
9.179 + aggregates->buffer[j-1] = aggregates->buffer[j];
9.180 + aggregates->buffer[j] = tmp;
9.181 + j--;
9.182 + }
9.183 }
9.184 void
9.185 Object::AggregateObject (Ptr<Object> o)
9.186 @@ -157,20 +198,42 @@
9.187 }
9.188
9.189 Object *other = PeekPointer (o);
9.190 - Object *next = m_next;
9.191 - m_next = other->m_next;
9.192 - other->m_next = next;
9.193 - NS_ASSERT (CheckLoose ());
9.194 - NS_ASSERT (o->CheckLoose ());
9.195 - // call NotifyNewAggregate in the listed chain
9.196 - Object *currentObject = this;
9.197 - do
9.198 + // first create the new aggregate buffer.
9.199 + uint32_t total = m_aggregates->n + other->m_aggregates->n;
9.200 + struct Aggregates *aggregates =
9.201 + (struct Aggregates *)malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*));
9.202 + aggregates->n = total;
9.203 + memcpy (&aggregates->buffer[0],
9.204 + &m_aggregates->buffer[0],
9.205 + m_aggregates->n*sizeof(Object*));
9.206 + // append the other aggregates in the new buffer
9.207 + for (uint32_t i = 0; i < other->m_aggregates->n; i++)
9.208 {
9.209 - // the NotifyNewAggregate of the current object implementation
9.210 - // should be called on the next object in the linked chain
9.211 - currentObject->NotifyNewAggregate ();
9.212 - currentObject = currentObject->m_next;
9.213 - } while (currentObject != this);
9.214 + aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i];
9.215 + UpdateSortedArray (aggregates, m_aggregates->n + i);
9.216 + }
9.217 +
9.218 + // free both aggregate buffers
9.219 + free (m_aggregates);
9.220 + free (other->m_aggregates);
9.221 +
9.222 + // Then, assign that buffer to every object
9.223 + uint32_t n = aggregates->n;
9.224 + for (uint32_t i = 0; i < n; i++)
9.225 + {
9.226 + Object *current = aggregates->buffer[i];
9.227 + current->m_aggregates = aggregates;
9.228 + }
9.229 +
9.230 + // share the counts
9.231 + ShareCount (other);
9.232 +
9.233 + // Finally, call NotifyNewAggregate in the listed chain
9.234 + for (uint32_t i = 0; i < n; i++)
9.235 + {
9.236 + Object *current = m_aggregates->buffer[i];
9.237 + current->NotifyNewAggregate ();
9.238 + }
9.239 }
9.240 /**
9.241 * This function must be implemented in the stack that needs to notify
9.242 @@ -205,7 +268,7 @@
9.243 bool
9.244 Object::Check (void) const
9.245 {
9.246 - return (m_count > 0);
9.247 + return (GetReferenceCount () > 0);
9.248 }
9.249
9.250 /* In some cases, when an event is scheduled against a subclass of
9.251 @@ -219,54 +282,43 @@
9.252 Object::CheckLoose (void) const
9.253 {
9.254 uint32_t refcount = 0;
9.255 - const Object *current = this;
9.256 - do
9.257 + uint32_t n = m_aggregates->n;
9.258 + for (uint32_t i = 0; i < n; i++)
9.259 {
9.260 - refcount += current->m_count;
9.261 - current = current->m_next;
9.262 + Object *current = m_aggregates->buffer[i];
9.263 + refcount += current->GetReferenceCount ();
9.264 }
9.265 - while (current != this);
9.266 -
9.267 return (refcount > 0);
9.268 }
9.269 +void
9.270 +Object::DoDelete (void)
9.271 +{
9.272 + uint32_t n = m_aggregates->n;
9.273 + // Ensure we are disposed.
9.274 + for (uint32_t i = 0; i < n; i++)
9.275 + {
9.276 + Object *current = m_aggregates->buffer[i];
9.277 + if (!current->m_disposed)
9.278 + {
9.279 + current->DoDispose ();
9.280 + }
9.281 + }
9.282
9.283 -void
9.284 -Object::MaybeDelete (void) const
9.285 -{
9.286 - // First, check if any of the attached
9.287 - // Object has a non-zero count.
9.288 - const Object *current = this;
9.289 - do {
9.290 - NS_ASSERT (current != 0);
9.291 - if (current->m_count != 0)
9.292 - {
9.293 - return;
9.294 - }
9.295 - current = current->m_next;
9.296 - } while (current != this);
9.297 + int *count = PeekCountPtr ();
9.298
9.299 - // Ensure we are disposed.
9.300 - Object *tmp = const_cast<Object *> (this);
9.301 - const Object *end = this;
9.302 - do {
9.303 - NS_ASSERT (current != 0);
9.304 - Object *next = tmp->m_next;
9.305 - if (!tmp->m_disposed)
9.306 - {
9.307 - tmp->DoDispose ();
9.308 - }
9.309 - tmp = next;
9.310 - } while (tmp != end);
9.311 + // Now, actually delete all objects
9.312 + struct Aggregates *aggregates = m_aggregates;
9.313 + for (uint32_t i = 0; i < n; i++)
9.314 + {
9.315 + // There is a trick here: each time we call delete below,
9.316 + // the deleted object is removed from the aggregate buffer
9.317 + // in the destructor so, the index of the next element to
9.318 + // lookup is always zero
9.319 + Object *current = aggregates->buffer[0];
9.320 + delete current;
9.321 + }
9.322
9.323 - // all attached objects have a zero count so,
9.324 - // we can delete all attached objects.
9.325 - current = this;
9.326 - do {
9.327 - NS_ASSERT (current != 0);
9.328 - Object *next = current->m_next;
9.329 - delete current;
9.330 - current = next;
9.331 - } while (current != end);
9.332 + delete count;
9.333 }
9.334 } // namespace ns3
9.335
10.1 --- a/src/core/object.h Mon Nov 09 13:32:18 2009 -0500
10.2 +++ b/src/core/object.h Mon Nov 09 13:36:23 2009 -0500
10.3 @@ -28,6 +28,7 @@
10.4 #include "attribute.h"
10.5 #include "object-base.h"
10.6 #include "attribute-list.h"
10.7 +#include "object-ref-count.h"
10.8
10.9
10.10 namespace ns3 {
10.11 @@ -55,7 +56,7 @@
10.12 * invoked from the Object::Unref method before destroying the object, even if the user
10.13 * did not call Object::Dispose directly.
10.14 */
10.15 -class Object : public ObjectBase
10.16 +class Object : public ObjectRefCount<Object,ObjectBase>
10.17 {
10.18 public:
10.19 static TypeId GetTypeId (void);
10.20 @@ -85,9 +86,9 @@
10.21 Ptr<const Object> Next (void);
10.22 private:
10.23 friend class Object;
10.24 - AggregateIterator (Ptr<const Object> first);
10.25 - Ptr<const Object> m_first;
10.26 - Ptr<const Object> m_current;
10.27 + AggregateIterator (Ptr<const Object> object);
10.28 + Ptr<const Object> m_object;
10.29 + uint32_t m_current;
10.30 };
10.31
10.32 Object ();
10.33 @@ -99,30 +100,10 @@
10.34 virtual TypeId GetInstanceTypeId (void) const;
10.35
10.36 /**
10.37 - * Increment the reference count. This method should not be called
10.38 - * by user code. Object instances are expected to be used in conjunction
10.39 - * of the Ptr template which would make calling Ref unecessary and
10.40 - * dangerous.
10.41 - */
10.42 - inline void Ref (void) const;
10.43 - /**
10.44 - * Decrement the reference count. This method should not be called
10.45 - * by user code. Object instances are expected to be used in conjunction
10.46 - * of the Ptr template which would make calling Ref unecessary and
10.47 - * dangerous.
10.48 - */
10.49 - inline void Unref (void) const;
10.50 -
10.51 - /**
10.52 - * Get the reference count of the object. Normally not needed; for language bindings.
10.53 - */
10.54 - uint32_t GetReferenceCount (void) const;
10.55 -
10.56 - /**
10.57 * \returns a pointer to the requested interface or zero if it could not be found.
10.58 */
10.59 template <typename T>
10.60 - Ptr<T> GetObject (void) const;
10.61 + inline Ptr<T> GetObject (void) const;
10.62 /**
10.63 * \param tid the interface id of the requested interface
10.64 * \returns a pointer to the requested interface or zero if it could not be found.
10.65 @@ -215,17 +196,25 @@
10.66 friend class ObjectFactory;
10.67 friend class AggregateIterator;
10.68
10.69 + /**
10.70 + * This data structure uses a classic C-style trick to
10.71 + * hold an array of variable size without performing
10.72 + * two memory allocations: the declaration of the structure
10.73 + * declares a one-element array but when we allocate
10.74 + * memory for this struct, we effectively allocate a larger
10.75 + * chunk of memory than the struct to allow space for a larger
10.76 + * variable sized buffer whose size is indicated by the element
10.77 + * 'n'
10.78 + */
10.79 + struct Aggregates {
10.80 + uint32_t n;
10.81 + Object *buffer[1];
10.82 + };
10.83 +
10.84 Ptr<Object> DoGetObject (TypeId tid) const;
10.85 bool Check (void) const;
10.86 bool CheckLoose (void) const;
10.87 /**
10.88 - * Attempt to delete this object. This method iterates
10.89 - * over all aggregated objects to check if they all
10.90 - * have a zero refcount. If yes, the object and all
10.91 - * its aggregates are deleted. If not, nothing is done.
10.92 - */
10.93 - void MaybeDelete (void) const;
10.94 - /**
10.95 * \param tid an TypeId
10.96 *
10.97 * Invoked from ns3::CreateObject only.
10.98 @@ -243,14 +232,15 @@
10.99 */
10.100 void Construct (const AttributeList &attributes);
10.101
10.102 + void UpdateSortedArray (struct Aggregates *aggregates, uint32_t i) const;
10.103 /**
10.104 - * The reference count for this object. Each aggregate
10.105 - * has an individual reference count. When the global
10.106 - * reference count (the sum of all reference counts)
10.107 - * reaches zero, the object and all its aggregates is
10.108 - * deleted.
10.109 + * Attempt to delete this object. This method iterates
10.110 + * over all aggregated objects to check if they all
10.111 + * have a zero refcount. If yes, the object and all
10.112 + * its aggregates are deleted. If not, nothing is done.
10.113 */
10.114 - mutable uint32_t m_count;
10.115 + virtual void DoDelete (void);
10.116 +
10.117 /**
10.118 * Identifies the type of this object instance.
10.119 */
10.120 @@ -261,13 +251,19 @@
10.121 */
10.122 bool m_disposed;
10.123 /**
10.124 - * A pointer to the next aggregate object. This is a circular
10.125 - * linked list of aggregated objects: the last one points
10.126 - * back to the first one. If an object is not aggregated to
10.127 - * any other object, the value of this field is equal to the
10.128 - * value of the 'this' pointer.
10.129 + * a pointer to an array of 'aggregates'. i.e., a pointer to
10.130 + * each object aggregated to this object is stored in this
10.131 + * array. The array is shared by all aggregated objects
10.132 + * so the size of the array is indirectly a reference count.
10.133 */
10.134 - Object *m_next;
10.135 + struct Aggregates * m_aggregates;
10.136 + /**
10.137 + * Indicates the number of times the object was accessed with a
10.138 + * call to GetObject. This integer is used to implement a
10.139 + * heuristic to sort the array of aggregates to put at the start
10.140 + * of the array the most-frequently accessed elements.
10.141 + */
10.142 + uint32_t m_getObjectCount;
10.143 };
10.144
10.145 /**
10.146 @@ -340,26 +336,15 @@
10.147 * The Object implementation which depends on templates
10.148 *************************************************************************/
10.149
10.150 -void
10.151 -Object::Ref (void) const
10.152 -{
10.153 - m_count++;
10.154 -}
10.155 -void
10.156 -Object::Unref (void) const
10.157 -{
10.158 - NS_ASSERT (Check ());
10.159 - m_count--;
10.160 - if (m_count == 0)
10.161 - {
10.162 - MaybeDelete ();
10.163 - }
10.164 -}
10.165 -
10.166 template <typename T>
10.167 Ptr<T>
10.168 Object::GetObject () const
10.169 {
10.170 + T *result = dynamic_cast<T *> (m_aggregates->buffer[0]);
10.171 + if (result != 0)
10.172 + {
10.173 + return Ptr<T> (result);
10.174 + }
10.175 Ptr<Object> found = DoGetObject (T::GetTypeId ());
10.176 if (found != 0)
10.177 {
11.1 --- a/src/core/test.cc Mon Nov 09 13:32:18 2009 -0500
11.2 +++ b/src/core/test.cc Mon Nov 09 13:36:23 2009 -0500
11.3 @@ -87,6 +87,7 @@
11.4 m_continueOnFailure (false),
11.5 m_detailsReported (false),
11.6 m_basedir ("invalid"),
11.7 + m_tempdir ("invalid"),
11.8 m_ofs (0),
11.9 m_error (false)
11.10 {
11.11 @@ -203,7 +204,18 @@
11.12 void
11.13 TestCase::SetBaseDir (std::string basedir)
11.14 {
11.15 - m_basedir = basedir;
11.16 + //
11.17 + // C and C++ allow one to use forward slashes even on systems where the
11.18 + // separator is actually a backslash.
11.19 + //
11.20 + if (basedir[basedir.length () - 1] != '/')
11.21 + {
11.22 + m_basedir = basedir + "/";
11.23 + }
11.24 + else
11.25 + {
11.26 + m_basedir = basedir;
11.27 + }
11.28 }
11.29
11.30 std::string
11.31 @@ -212,13 +224,52 @@
11.32 return m_basedir;
11.33 }
11.34
11.35 +void
11.36 +TestCase::SetTempDir (std::string tempdir)
11.37 +{
11.38 + //
11.39 + // C and C++ allow one to use forward slashes even on systems where the
11.40 + // separator is actually a backslash.
11.41 + //
11.42 + if (tempdir[tempdir.length () - 1] != '/')
11.43 + {
11.44 + m_tempdir = tempdir + "/";
11.45 + }
11.46 + else
11.47 + {
11.48 + m_tempdir = tempdir;
11.49 + }
11.50 +}
11.51 +
11.52 +std::string
11.53 +TestCase::GetTempDir (void)
11.54 +{
11.55 + return m_tempdir;
11.56 +}
11.57 +
11.58 std::string
11.59 TestCase::GetSourceDir (std::string file)
11.60 {
11.61 + //
11.62 + // The <file> parameter is actually going to be __FILE__ which may have
11.63 + // backslashes in it on win32 systems. For example,
11.64 + //
11.65 + // ..\src\common\pcap-file-test-suite.cc (win32)
11.66 + //
11.67 + // or
11.68 + //
11.69 + // ../src/common/pcap-file-test-suite.cc (grown-up systems)
11.70 + //
11.71 +#ifdef WIN32
11.72 + std::string::size_type relPathBegin = file.find_first_of ("\\");
11.73 + std::string::size_type relPathEnd = file.find_last_of ("\\");
11.74 +#else
11.75 std::string::size_type relPathBegin = file.find_first_of ("/");
11.76 - NS_ABORT_MSG_IF (relPathBegin == std::string::npos, "TestCase::GetSrouceDir(): Internal Error");
11.77 std::string::size_type relPathEnd = file.find_last_of ("/");
11.78 - NS_ABORT_MSG_IF (relPathEnd == std::string::npos, "TestCase::GetSrouceDir(): Internal Error");
11.79 +#endif
11.80 +
11.81 + NS_ABORT_MSG_IF (relPathBegin == std::string::npos, "TestCase::GetSourceDir(): Internal Error");
11.82 + NS_ABORT_MSG_IF (relPathEnd == std::string::npos, "TestCase::GetSourceDir(): Internal Error");
11.83
11.84 return GetBaseDir () + file.substr (relPathBegin, relPathEnd + 1 - relPathBegin);
11.85 }
11.86 @@ -353,6 +404,7 @@
11.87 : m_name (name),
11.88 m_verbose (false),
11.89 m_basedir ("invalid"),
11.90 + m_tempdir ("invalid"),
11.91 m_ofs (0),
11.92 m_error (false),
11.93 m_type (type)
11.94 @@ -476,7 +528,18 @@
11.95 void
11.96 TestSuite::SetBaseDir (std::string basedir)
11.97 {
11.98 - m_basedir = basedir;
11.99 + //
11.100 + // C and C++ allow one to use forward slashes even on systems where the
11.101 + // separator is actually a backslash.
11.102 + //
11.103 + if (basedir[basedir.length () - 1] != '/')
11.104 + {
11.105 + m_basedir = basedir + "/";
11.106 + }
11.107 + else
11.108 + {
11.109 + m_basedir = basedir;
11.110 + }
11.111 }
11.112
11.113 std::string
11.114 @@ -486,6 +549,29 @@
11.115 }
11.116
11.117 void
11.118 +TestSuite::SetTempDir (std::string tempdir)
11.119 +{
11.120 + //
11.121 + // C and C++ allow one to use forward slashes even on systems where the
11.122 + // separator is actually a backslash.
11.123 + //
11.124 + if (tempdir[tempdir.length () - 1] != '/')
11.125 + {
11.126 + m_tempdir = tempdir + "/";
11.127 + }
11.128 + else
11.129 + {
11.130 + m_tempdir = tempdir;
11.131 + }
11.132 +}
11.133 +
11.134 +std::string
11.135 +TestSuite::GetTempDir (void)
11.136 +{
11.137 + return m_tempdir;
11.138 +}
11.139 +
11.140 +void
11.141 TestSuite::SetStream (std::ofstream *ofs)
11.142 {
11.143 m_ofs = ofs;
11.144 @@ -589,6 +675,7 @@
11.145 (*i)->SetVerbose (m_verbose);
11.146 (*i)->SetContinueOnFailure (m_continueOnFailure);
11.147 (*i)->SetBaseDir (m_basedir);
11.148 + (*i)->SetTempDir (m_tempdir);
11.149 (*i)->SetStream (m_ofs);
11.150
11.151 //
12.1 --- a/src/core/test.h Mon Nov 09 13:32:18 2009 -0500
12.2 +++ b/src/core/test.h Mon Nov 09 13:36:23 2009 -0500
12.3 @@ -662,6 +662,16 @@
12.4 */
12.5 std::string GetBaseDir (void);
12.6
12.7 + /**
12.8 + * \brief Set the temporary file directory (where to write temporary files).
12.9 + */
12.10 + void SetTempDir (std::string dir);
12.11 +
12.12 + /**
12.13 + * \brief Get the temporary file directory .
12.14 + */
12.15 + std::string GetTempDir (void);
12.16 +
12.17 /**
12.18 * \brief Get the source directory of the current source file.
12.19 *
12.20 @@ -830,6 +840,7 @@
12.21 bool m_continueOnFailure;
12.22 bool m_detailsReported;
12.23 std::string m_basedir;
12.24 + std::string m_tempdir;
12.25 std::ofstream *m_ofs;
12.26 bool m_error;
12.27 };
12.28 @@ -945,6 +956,16 @@
12.29 std::string GetBaseDir (void);
12.30
12.31 /**
12.32 + * \brief Set the temporary file directory (where to write temporary files).
12.33 + */
12.34 + void SetTempDir (std::string dir);
12.35 +
12.36 + /**
12.37 + * \brief Get the temporary file directory.
12.38 + */
12.39 + std::string GetTempDir (void);
12.40 +
12.41 + /**
12.42 * \brief Set the stream to which status and result messages will be written.
12.43 *
12.44 * We really don't want to have to pass an ofstream around to every function
12.45 @@ -1064,6 +1085,7 @@
12.46 bool m_verbose;
12.47 bool m_continueOnFailure;
12.48 std::string m_basedir;
12.49 + std::string m_tempdir;
12.50 std::ofstream *m_ofs;
12.51 bool m_error;
12.52 TestType m_type;
13.1 --- a/src/core/wscript Mon Nov 09 13:32:18 2009 -0500
13.2 +++ b/src/core/wscript Mon Nov 09 13:36:23 2009 -0500
13.3 @@ -126,6 +126,7 @@
13.4 'abort.h',
13.5 'names.h',
13.6 'vector.h',
13.7 + 'object-ref-count.h',
13.8 ]
13.9
13.10 if sys.platform == 'win32':
14.1 --- a/src/devices/mesh/dot11s/dot11s-test-suite.cc Mon Nov 09 13:32:18 2009 -0500
14.2 +++ b/src/devices/mesh/dot11s/dot11s-test-suite.cc Mon Nov 09 13:36:23 2009 -0500
14.3 @@ -174,9 +174,9 @@
14.4 {
14.5 for (std::vector<Mac48Address>::const_iterator i = precursors.begin (); i != precursors.end (); i++)
14.6 {
14.7 - table->AddPrecursor (dst, iface, *i);
14.8 + table->AddPrecursor (dst, iface, *i, Seconds (100));
14.9 // Check that duplicates are filtered
14.10 - table->AddPrecursor (dst, iface, *i);
14.11 + table->AddPrecursor (dst, iface, *i, Seconds (100));
14.12 }
14.13 }
14.14
15.1 --- a/src/devices/mesh/dot11s/hwmp-protocol.cc Mon Nov 09 13:32:18 2009 -0500
15.2 +++ b/src/devices/mesh/dot11s/hwmp-protocol.cc Mon Nov 09 13:36:23 2009 -0500
15.3 @@ -401,6 +401,7 @@
15.4 //acceptance cretirea:
15.5 std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
15.6 preq.GetOriginatorAddress ());
15.7 + bool freshInfo (true);
15.8 if (i != m_hwmpSeqnoMetricDatabase.end ())
15.9 {
15.10 if ((int32_t)(i->second.first - preq.GetOriginatorSeqNumber ()) > 0)
15.11 @@ -409,21 +410,25 @@
15.12 }
15.13 if (i->second.first == preq.GetOriginatorSeqNumber ())
15.14 {
15.15 + freshInfo = false;
15.16 if (i->second.second <= preq.GetMetric ())
15.17 {
15.18 return;
15.19 }
15.20 }
15.21 }
15.22 - m_hwmpSeqnoMetricDatabase[preq.GetOriginatorAddress ()] = std::make_pair (preq.GetOriginatorSeqNumber (), preq.GetMetric ());
15.23 -
15.24 + m_hwmpSeqnoMetricDatabase[preq.GetOriginatorAddress ()] =
15.25 + std::make_pair (preq.GetOriginatorSeqNumber (), preq.GetMetric ());
15.26 NS_LOG_DEBUG("I am " << GetAddress () << "Accepted preq from address" << from << ", preq:" << preq);
15.27 std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
15.28 //Add reactive path to originator:
15.29 if (
15.30 - ((m_rtable->LookupReactive (preq.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
15.31 - ((m_rtable->LookupReactive (preq.GetOriginatorAddress ())).metric > preq.GetMetric ())
15.32 + (freshInfo) ||
15.33 + (
15.34 + (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).retransmitter == Mac48Address::GetBroadcast ()) ||
15.35 + (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).metric > preq.GetMetric ())
15.36 )
15.37 + )
15.38 {
15.39 m_rtable->AddReactivePath (
15.40 preq.GetOriginatorAddress (),
15.41 @@ -432,13 +437,12 @@
15.42 preq.GetMetric (),
15.43 MicroSeconds (preq.GetLifetime () * 1024),
15.44 preq.GetOriginatorSeqNumber ()
15.45 - );
15.46 + );
15.47 ReactivePathResolved (preq.GetOriginatorAddress ());
15.48 }
15.49 - //Add reactive path for precursor:
15.50 if (
15.51 - ((m_rtable->LookupReactive (fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
15.52 - ((m_rtable->LookupReactive (fromMp)).metric > preq.GetMetric ())
15.53 + (m_rtable->LookupReactive (fromMp).retransmitter == Mac48Address::GetBroadcast ()) ||
15.54 + (m_rtable->LookupReactive (fromMp).metric > metric)
15.55 )
15.56 {
15.57 m_rtable->AddReactivePath (
15.58 @@ -477,15 +481,6 @@
15.59 preq.GetOriginatorSeqNumber ()
15.60 );
15.61 ProactivePathResolved ();
15.62 - m_rtable->AddReactivePath (
15.63 - preq.GetOriginatorAddress (),
15.64 - from,
15.65 - interface,
15.66 - preq.GetMetric (),
15.67 - MicroSeconds (preq.GetLifetime () * 1024),
15.68 - preq.GetOriginatorSeqNumber ()
15.69 - );
15.70 - ReactivePathResolved (preq.GetOriginatorAddress ());
15.71 }
15.72 if (!preq.IsNeedNotPrep ())
15.73 {
15.74 @@ -493,7 +488,7 @@
15.75 GetAddress (),
15.76 preq.GetOriginatorAddress (),
15.77 from,
15.78 - preq.GetMetric (),
15.79 + (uint32_t)0,
15.80 preq.GetOriginatorSeqNumber (),
15.81 GetNextHwmpSeqno (),
15.82 preq.GetLifetime (),
15.83 @@ -523,9 +518,6 @@
15.84 if ((! ((*i)->IsDo ())) && (result.retransmitter != Mac48Address::GetBroadcast ()))
15.85 {
15.86 //have a valid information and can answer
15.87 - //!NB: If there is information from peer - set lifetime as
15.88 - //we have got from PREQ, and set the rest lifetime of the
15.89 - //route if the information is correct
15.90 uint32_t lifetime = result.lifetime.GetMicroSeconds () / 1024;
15.91 if ((lifetime > 0) && ((int32_t)(result.seqnum - (*i)->GetDestSeqNumber ()) >= 0))
15.92 {
15.93 @@ -539,6 +531,8 @@
15.94 lifetime,
15.95 interface
15.96 );
15.97 + m_rtable->AddPrecursor ((*i)->GetDestinationAddress (), interface, from,
15.98 + MicroSeconds (preq.GetLifetime () * 1024));
15.99 if ((*i)->IsRf ())
15.100 {
15.101 (*i)->SetFlags (true, false, (*i)->IsUsn ()); //DO = 1, RF = 0
15.102 @@ -570,38 +564,52 @@
15.103 //acceptance cretirea:
15.104 std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
15.105 prep.GetOriginatorAddress ());
15.106 - if ((i != m_hwmpSeqnoMetricDatabase.end ()) && ((int32_t)(i->second.first - prep.GetOriginatorSeqNumber ()) > 0))
15.107 + bool freshInfo (true);
15.108 + if (i != m_hwmpSeqnoMetricDatabase.end ())
15.109 {
15.110 - return;
15.111 + if ((int32_t)(i->second.first - prep.GetOriginatorSeqNumber ()) > 0)
15.112 + {
15.113 + return;
15.114 + }
15.115 + if (i->second.first == prep.GetOriginatorSeqNumber ())
15.116 + {
15.117 + freshInfo = false;
15.118 + }
15.119 }
15.120 m_hwmpSeqnoMetricDatabase[prep.GetOriginatorAddress ()] = std::make_pair (prep.GetOriginatorSeqNumber (), prep.GetMetric ());
15.121 //update routing info
15.122 //Now add a path to destination and add precursor to source
15.123 NS_LOG_DEBUG ("I am " << GetAddress () << ", received prep from " << prep.GetOriginatorAddress () << ", receiver was:" << from);
15.124 HwmpRtable::LookupResult result = m_rtable->LookupReactive (prep.GetDestinationAddress ());
15.125 - //Add a reactive path only if it is better than existing:
15.126 + //Add a reactive path only if seqno is fresher or it improves the
15.127 + //metric
15.128 if (
15.129 - ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
15.130 - ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
15.131 + (freshInfo) ||
15.132 + (
15.133 + ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
15.134 + ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
15.135 )
15.136 + )
15.137 {
15.138 m_rtable->AddReactivePath (
15.139 prep.GetOriginatorAddress (),
15.140 from,
15.141 interface,
15.142 prep.GetMetric (),
15.143 - MicroSeconds(prep.GetLifetime () * 1024),
15.144 + MicroSeconds (prep.GetLifetime () * 1024),
15.145 prep.GetOriginatorSeqNumber ());
15.146 - m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from);
15.147 + m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from,
15.148 + MicroSeconds (prep.GetLifetime () * 1024));
15.149 if (result.retransmitter != Mac48Address::GetBroadcast ())
15.150 {
15.151 - m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter);
15.152 + m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter,
15.153 + result.lifetime);
15.154 }
15.155 ReactivePathResolved (prep.GetOriginatorAddress ());
15.156 }
15.157 if (
15.158 ((m_rtable->LookupReactive (fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
15.159 - ((m_rtable->LookupReactive (fromMp)).metric > prep.GetMetric ())
15.160 + ((m_rtable->LookupReactive (fromMp)).metric > metric)
15.161 )
15.162 {
15.163 m_rtable->AddReactivePath (
15.164 @@ -669,7 +677,7 @@
15.165 prep.SetDestinationAddress (dst);
15.166 prep.SetDestinationSeqNumber (destinationSN);
15.167 prep.SetLifetime (lifetime);
15.168 - prep.SetMetric (0);
15.169 + prep.SetMetric (initMetric);
15.170 prep.SetOriginatorAddress (src);
15.171 prep.SetOriginatorSeqNumber (originatorDsn);
15.172 HwmpProtocolMacMap::const_iterator prep_sender = m_interfaces.find (interface);
16.1 --- a/src/devices/mesh/dot11s/hwmp-rtable.cc Mon Nov 09 13:32:18 2009 -0500
16.2 +++ b/src/devices/mesh/dot11s/hwmp-rtable.cc Mon Nov 09 13:36:23 2009 -0500
16.3 @@ -84,11 +84,12 @@
16.4 }
16.5 void
16.6 HwmpRtable::AddPrecursor (Mac48Address destination, uint32_t precursorInterface,
16.7 - Mac48Address precursorAddress)
16.8 + Mac48Address precursorAddress, Time lifetime)
16.9 {
16.10 - std::pair<uint32_t, Mac48Address> precursor;
16.11 - precursor.first = precursorInterface;
16.12 - precursor.second = precursorAddress;
16.13 + Precursor precursor;
16.14 + precursor.interface = precursorInterface;
16.15 + precursor.address = precursorAddress;
16.16 + precursor.whenExpire = Simulator::Now () + lifetime;
16.17 std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
16.18 if (i != m_routes.end ())
16.19 {
16.20 @@ -97,9 +98,10 @@
16.21 {
16.22 //NB: Only one active route may exist, so do not check
16.23 //interface ID, just address
16.24 - if (i->second.precursors[j].second == precursorAddress)
16.25 + if (i->second.precursors[j].address == precursorAddress)
16.26 {
16.27 should_add = false;
16.28 + i->second.precursors[j].whenExpire = precursor.whenExpire;
16.29 break;
16.30 }
16.31 }
16.32 @@ -108,17 +110,6 @@
16.33 i->second.precursors.push_back (precursor);
16.34 }
16.35 }
16.36 - if (m_root.root == destination)
16.37 - {
16.38 - for (unsigned int j = 0; j < m_root.precursors.size (); j++)
16.39 - {
16.40 - if (m_root.precursors[j].second == precursorAddress)
16.41 - {
16.42 - return;
16.43 - }
16.44 - }
16.45 - }
16.46 - m_root.precursors.push_back (precursor);
16.47 }
16.48 void
16.49 HwmpRtable::DeleteProactivePath ()
16.50 @@ -221,27 +212,12 @@
16.51 std::map<Mac48Address, ReactiveRoute>::iterator route = m_routes.find (destination);
16.52 if (route != m_routes.end ())
16.53 {
16.54 - for (unsigned int i = 0; i < route->second.precursors.size (); i++)
16.55 + for (std::vector<Precursor>::const_iterator i = route->second.precursors.begin ();
16.56 + i != route->second.precursors.end (); i++)
16.57 {
16.58 - retval.push_back (route->second.precursors[i]);
16.59 - }
16.60 - }
16.61 - if (m_root.root == destination)
16.62 - {
16.63 - for (unsigned int i = 0; i < m_root.precursors.size (); i++)
16.64 - {
16.65 - bool should_add = true;
16.66 - for (unsigned int j = 0; j < retval.size (); j++)
16.67 + if (i->whenExpire > Simulator::Now ())
16.68 {
16.69 - if (retval[j].second == m_root.precursors[i].second)
16.70 - {
16.71 - should_add = false;
16.72 - break;
16.73 - }
16.74 - }
16.75 - if (should_add)
16.76 - {
16.77 - retval.push_back (m_root.precursors[i]);
16.78 + retval.push_back (std::make_pair(i->interface, i->address));
16.79 }
16.80 }
16.81 }
17.1 --- a/src/devices/mesh/dot11s/hwmp-rtable.h Mon Nov 09 13:32:18 2009 -0500
17.2 +++ b/src/devices/mesh/dot11s/hwmp-rtable.h Mon Nov 09 13:36:23 2009 -0500
17.3 @@ -85,7 +85,7 @@
17.4 Time lifetime,
17.5 uint32_t seqnum
17.6 );
17.7 - void AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress);
17.8 + void AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress, Time lifetime);
17.9 PrecursorList GetPrecursors (Mac48Address destination);
17.10 void DeleteProactivePath ();
17.11 void DeleteProactivePath (Mac48Address root);
17.12 @@ -109,6 +109,12 @@
17.13
17.14 private:
17.15 /// Route found in reactive mode
17.16 + struct Precursor
17.17 + {
17.18 + Mac48Address address;
17.19 + uint32_t interface;
17.20 + Time whenExpire;
17.21 + };
17.22 struct ReactiveRoute
17.23 {
17.24 Mac48Address retransmitter;
17.25 @@ -116,7 +122,7 @@
17.26 uint32_t metric;
17.27 Time whenExpire;
17.28 uint32_t seqnum;
17.29 - std::vector<std::pair<uint32_t, Mac48Address> > precursors;
17.30 + std::vector<Precursor> precursors;
17.31 };
17.32 /// Route fond in proactive mode
17.33 struct ProactiveRoute
17.34 @@ -127,7 +133,7 @@
17.35 uint32_t metric;
17.36 Time whenExpire;
17.37 uint32_t seqnum;
17.38 - std::vector<std::pair<uint32_t, Mac48Address> > precursors;
17.39 + std::vector<Precursor> precursors;
17.40 };
17.41
17.42 /// List of routes
18.1 --- a/src/devices/mesh/dot11s/ie-dot11s-prep.cc Mon Nov 09 13:32:18 2009 -0500
18.2 +++ b/src/devices/mesh/dot11s/ie-dot11s-prep.cc Mon Nov 09 13:36:23 2009 -0500
18.3 @@ -135,6 +135,7 @@
18.4 IePrep::DecrementTtl ()
18.5 {
18.6 m_ttl--;
18.7 + m_hopcount ++;
18.8 }
18.9
18.10 void
19.1 --- a/src/devices/mesh/dot11s/ie-dot11s-preq.cc Mon Nov 09 13:32:18 2009 -0500
19.2 +++ b/src/devices/mesh/dot11s/ie-dot11s-preq.cc Mon Nov 09 13:36:23 2009 -0500
19.3 @@ -317,17 +317,17 @@
19.4 IePreq::Print (std::ostream &os) const
19.5 {
19.6 os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
19.7 - os << " originator address = " << m_originatorAddress << "std::endl";
19.8 - os << " TTL = " << (uint16_t) m_ttl << "std::endl";
19.9 - os << " hop count = " << (uint16_t) m_hopCount << "std::endl";
19.10 - os << " metric = " << m_metric << "std::endl";
19.11 - os << " seqno = " << m_originatorSeqNumber << "std::endl";
19.12 - os << " lifetime = " << m_lifetime << "std::endl";
19.13 - os << " preq ID = " << m_preqId << "std::endl";
19.14 - os << " Destinations are:std::endl";
19.15 + os << " originator address = " << m_originatorAddress << std::endl;
19.16 + os << " TTL = " << (uint16_t) m_ttl << std::endl;
19.17 + os << " hop count = " << (uint16_t) m_hopCount << std::endl;
19.18 + os << " metric = " << m_metric << std::endl;
19.19 + os << " seqno = " << m_originatorSeqNumber << std::endl;
19.20 + os << " lifetime = " << m_lifetime << std::endl;
19.21 + os << " preq ID = " << m_preqId << std::endl;
19.22 + os << " Destinations are:" << std::endl;
19.23 for (int j = 0; j < m_destCount; j++)
19.24 {
19.25 - os << " " << m_destinations[j]->GetDestinationAddress () << "std::endl";
19.26 + os << " " << m_destinations[j]->GetDestinationAddress () << std::endl;
19.27 }
19.28 os << "</information_element>" << std::endl;
19.29 }
20.1 --- a/src/devices/mesh/dot11s/ie-dot11s-rann.cc Mon Nov 09 13:32:18 2009 -0500
20.2 +++ b/src/devices/mesh/dot11s/ie-dot11s-rann.cc Mon Nov 09 13:36:23 2009 -0500
20.3 @@ -152,12 +152,12 @@
20.4 IeRann::Print (std::ostream &os) const
20.5 {
20.6 os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
20.7 - os << " flags = " << (int) m_flags << "std::endl";
20.8 - os << " hop count = " << (int) m_hopcount << "std::endl";
20.9 - os << " TTL = " << (int) m_ttl << "std::endl";
20.10 - os << " originator address = " << m_originatorAddress << "std::endl";
20.11 - os << " dst seq. number = " << m_destSeqNumber << "std::endl";
20.12 - os << " metric = " << m_metric << "std::endl";
20.13 + os << " flags = " << (int) m_flags << std::endl;
20.14 + os << " hop count = " << (int) m_hopcount << std::endl;
20.15 + os << " TTL = " << (int) m_ttl << std::endl;
20.16 + os << " originator address = " << m_originatorAddress << std::endl;
20.17 + os << " dst seq. number = " << m_destSeqNumber << std::endl;
20.18 + os << " metric = " << m_metric << std::endl;
20.19 os << "</information_element>" << std::endl;
20.20 }
20.21
21.1 --- a/src/internet-stack/ipv4-l3-protocol.cc Mon Nov 09 13:32:18 2009 -0500
21.2 +++ b/src/internet-stack/ipv4-l3-protocol.cc Mon Nov 09 13:36:23 2009 -0500
21.3 @@ -82,8 +82,7 @@
21.4 }
21.5
21.6 Ipv4L3Protocol::Ipv4L3Protocol()
21.7 - : m_nInterfaces (0),
21.8 - m_identification (0)
21.9 + : m_identification (0)
21.10 {
21.11 NS_LOG_FUNCTION_NOARGS ();
21.12 }
21.13 @@ -266,9 +265,8 @@
21.14 Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
21.15 {
21.16 NS_LOG_FUNCTION (this << interface);
21.17 - uint32_t index = m_nInterfaces;
21.18 + uint32_t index = m_interfaces.size ();
21.19 m_interfaces.push_back (interface);
21.20 - m_nInterfaces++;
21.21 return index;
21.22 }
21.23
21.24 @@ -276,14 +274,9 @@
21.25 Ipv4L3Protocol::GetInterface (uint32_t index) const
21.26 {
21.27 NS_LOG_FUNCTION (this << index);
21.28 - uint32_t tmp = 0;
21.29 - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
21.30 + if (index < m_interfaces.size ())
21.31 {
21.32 - if (index == tmp)
21.33 - {
21.34 - return *i;
21.35 - }
21.36 - tmp++;
21.37 + return m_interfaces[index];
21.38 }
21.39 return 0;
21.40 }
21.41 @@ -292,7 +285,7 @@
21.42 Ipv4L3Protocol::GetNInterfaces (void) const
21.43 {
21.44 NS_LOG_FUNCTION_NOARGS ();
21.45 - return m_nInterfaces;
21.46 + return m_interfaces.size ();
21.47 }
21.48
21.49 int32_t
22.1 --- a/src/internet-stack/ipv4-l3-protocol.h Mon Nov 09 13:32:18 2009 -0500
22.2 +++ b/src/internet-stack/ipv4-l3-protocol.h Mon Nov 09 13:36:23 2009 -0500
22.3 @@ -22,6 +22,7 @@
22.4 #define IPV4_L3_PROTOCOL_H
22.5
22.6 #include <list>
22.7 +#include <vector>
22.8 #include <stdint.h>
22.9 #include "ns3/ipv4-address.h"
22.10 #include "ns3/ptr.h"
22.11 @@ -233,7 +234,7 @@
22.12 Ptr<Icmpv4L4Protocol> GetIcmp (void) const;
22.13 bool IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const;
22.14
22.15 - typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
22.16 + typedef std::vector<Ptr<Ipv4Interface> > Ipv4InterfaceList;
22.17 typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
22.18 typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
22.19
23.1 --- a/test.py Mon Nov 09 13:32:18 2009 -0500
23.2 +++ b/test.py Mon Nov 09 13:36:23 2009 -0500
23.3 @@ -132,6 +132,7 @@
23.4 ("tutorial/second", "True", "True"),
23.5 ("tutorial/third", "True", "True"),
23.6 ("tutorial/fourth", "True", "True"),
23.7 + ("tutorial/fifth", "True", "True"),
23.8
23.9 ("udp/udp-echo", "True", "True"),
23.10
23.11 @@ -616,6 +617,7 @@
23.12 self.shell_command = ""
23.13 self.display_name = ""
23.14 self.basedir = ""
23.15 + self.tempdir = ""
23.16 self.cwd = ""
23.17 self.tmp_file_name = ""
23.18 self.returncode = False
23.19 @@ -674,6 +676,13 @@
23.20 self.basedir = basedir
23.21
23.22 #
23.23 + # This is the directory to which a running test suite should write any
23.24 + # temporary files.
23.25 + #
23.26 + def set_tempdir(self, tempdir):
23.27 + self.tempdir = tempdir
23.28 +
23.29 + #
23.30 # This is the current working directory that will be given to an executing
23.31 # test as it is being run. It will be used for examples to tell them where
23.32 # to write all of the pcap files that we will be carefully ignoring. For
23.33 @@ -766,7 +775,8 @@
23.34 # file name
23.35 #
23.36 (job.returncode, standard_out, standard_err, et) = run_job_synchronously(job.shell_command +
23.37 - " --basedir=%s --out=%s" % (job.basedir, job.tmp_file_name), job.cwd, options.valgrind)
23.38 + " --basedir=%s --tempdir=%s --out=%s" % (job.basedir, job.tempdir, job.tmp_file_name),
23.39 + job.cwd, options.valgrind)
23.40
23.41 job.set_elapsed_time(et)
23.42
23.43 @@ -1004,6 +1014,7 @@
23.44 job.set_tmp_file_name(os.path.join(testpy_output_dir, "%s.xml" % test))
23.45 job.set_cwd(os.getcwd())
23.46 job.set_basedir(os.getcwd())
23.47 + job.set_tempdir(testpy_output_dir)
23.48 if (options.multiple):
23.49 multiple = " --multiple"
23.50 else:
23.51 @@ -1074,6 +1085,7 @@
23.52 job.set_tmp_file_name("")
23.53 job.set_cwd(testpy_output_dir)
23.54 job.set_basedir(os.getcwd())
23.55 + job.set_tempdir(testpy_output_dir)
23.56 job.set_shell_command("examples/%s" % test)
23.57
23.58 if options.valgrind and not eval(do_valgrind_run):
23.59 @@ -1097,6 +1109,7 @@
23.60 job.set_tmp_file_name("")
23.61 job.set_cwd(testpy_output_dir)
23.62 job.set_basedir(os.getcwd())
23.63 + job.set_tempdir(testpy_output_dir)
23.64 job.set_shell_command("examples/%s" % options.example)
23.65
23.66 if options.verbose:
24.1 --- a/utils/test-runner.cc Mon Nov 09 13:32:18 2009 -0500
24.2 +++ b/utils/test-runner.cc Mon Nov 09 13:36:23 2009 -0500
24.3 @@ -40,11 +40,13 @@
24.4 bool doKinds = false;
24.5
24.6 bool haveBasedir = false;
24.7 + bool haveTempdir = false;
24.8 bool haveOutfile = false;
24.9 bool haveType = false;
24.10
24.11 std::string suiteName;
24.12 std::string basedir;
24.13 + std::string tempdir;
24.14 std::string outfileName;
24.15 std::string typeName;
24.16
24.17 @@ -96,6 +98,12 @@
24.18 doSuite = true;
24.19 }
24.20
24.21 + if (arg.find ("--tempdir=") != std::string::npos)
24.22 + {
24.23 + tempdir = arg.substr (arg.find_first_of ("=") + 1, 9999);
24.24 + haveTempdir = true;
24.25 + }
24.26 +
24.27 if (arg.compare ("--verbose") == 0)
24.28 {
24.29 doVerbose = true;
24.30 @@ -247,6 +255,7 @@
24.31 if (doSuite == false || (doSuite == true && suiteName == testSuite->GetName ()))
24.32 {
24.33 testSuite->SetBaseDir (basedir);
24.34 + testSuite->SetTempDir (tempdir);
24.35 testSuite->SetStream (pofs);
24.36 testSuite->SetVerbose (doVerbose);
24.37 testSuite->SetContinueOnFailure (doMultiple);