branch merge
authorCraig Dowell <craigdo@ee.washington.edu>
Thu Nov 05 19:15:28 2009 -0800 (3 months ago)
changeset 5532fbfdb256aaed
parent 5531 de01c67af975
parent 5530 83baafea199f
child 5533 ad83d869c08c
branch merge
     1.1 --- a/src/contrib/net-anim/animation-interface.cc	Thu Nov 05 19:14:37 2009 -0800
     1.2 +++ b/src/contrib/net-anim/animation-interface.cc	Thu Nov 05 19:15:28 2009 -0800
     1.3 @@ -21,9 +21,15 @@
     1.4  #include <stdio.h>
     1.5  #include <sstream>
     1.6  
     1.7 +#include "ns3/net-anim-config.h"
     1.8 +
     1.9  // Socket related includes
    1.10 -#include <sys/socket.h>
    1.11 -#include <netinet/in.h>
    1.12 +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
    1.13 +# include <sys/socket.h>
    1.14 +# include <netinet/in.h>
    1.15 +#else
    1.16 +#include <fcntl.h>
    1.17 +#endif
    1.18  
    1.19  // ns3 includes
    1.20  #include "ns3/animation-interface.h"
    1.21 @@ -58,6 +64,7 @@
    1.22  
    1.23  bool AnimationInterface::SetServerPort (uint16_t port)
    1.24  {
    1.25 +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
    1.26    int s = socket (AF_INET, SOCK_STREAM, 0);
    1.27    struct sockaddr_in addr;
    1.28    addr.sin_family = AF_INET;
    1.29 @@ -77,6 +84,8 @@
    1.30    int t = 1;
    1.31    setsockopt (s, SOL_SOCKET, SO_LINGER, &t, sizeof(t));
    1.32    return true;
    1.33 +#endif
    1.34 +  return false;//never reached unless the above is disabled
    1.35  }
    1.36  
    1.37  bool AnimationInterface::SetInternalAnimation ()
     2.1 --- a/src/contrib/net-anim/point-to-point-dumbbell-helper.cc	Thu Nov 05 19:14:37 2009 -0800
     2.2 +++ b/src/contrib/net-anim/point-to-point-dumbbell-helper.cc	Thu Nov 05 19:15:28 2009 -0800
     2.3 @@ -21,10 +21,6 @@
     2.4  #include <iostream>
     2.5  #include <sstream>
     2.6  
     2.7 -// Socket related includes
     2.8 -#include <sys/socket.h>
     2.9 -#include <netinet/in.h>
    2.10 -
    2.11  // ns3 includes
    2.12  #include "ns3/animation-interface.h"
    2.13  #include "ns3/point-to-point-dumbbell-helper.h"
     3.1 --- a/src/contrib/net-anim/wscript	Thu Nov 05 19:14:37 2009 -0800
     3.2 +++ b/src/contrib/net-anim/wscript	Thu Nov 05 19:15:28 2009 -0800
     3.3 @@ -1,5 +1,11 @@
     3.4  ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
     3.5  
     3.6 +def configure(conf):
     3.7 +    conf.check(header_name='sys/socket.h', define_name='HAVE_SYS_SOCKET_H')
     3.8 +    conf.check(header_name='netinet/in.h', define_name='HAVE_NETINET_IN_H')
     3.9 +    conf.write_config_header('ns3/net-anim-config.h', top=True)
    3.10 +
    3.11 +
    3.12  def build(bld):
    3.13      obj = bld.create_ns3_module('net-anim')
    3.14      obj.source = [
     4.1 --- a/src/contrib/wscript	Thu Nov 05 19:14:37 2009 -0800
     4.2 +++ b/src/contrib/wscript	Thu Nov 05 19:15:28 2009 -0800
     4.3 @@ -14,9 +14,11 @@
     4.4      conf.report_optional_feature("XmlIo", "XmlIo",
     4.5                                   conf.env['ENABLE_LIBXML2'],
     4.6                                   "library 'libxml-2.0 >= 2.7' not found")
     4.7 +    conf.write_config_header('ns3/contrib-config.h', top=True)
     4.8 +
     4.9      conf.sub_config('stats')
    4.10 +    conf.sub_config('net-anim')
    4.11  
    4.12 -    conf.write_config_header('ns3/contrib-config.h', top=True)
    4.13  
    4.14  def build(bld):
    4.15      module = bld.create_ns3_module('contrib', ['simulator', 'common'])
     5.1 --- a/src/core/object.cc	Thu Nov 05 19:14:37 2009 -0800
     5.2 +++ b/src/core/object.cc	Thu Nov 05 19:15:28 2009 -0800
     5.3 @@ -28,6 +28,8 @@
     5.4  #include "string.h"
     5.5  #include <vector>
     5.6  #include <sstream>
     5.7 +#include <stdlib.h>
     5.8 +#include <string.h>
     5.9  
    5.10  NS_LOG_COMPONENT_DEFINE ("Object");
    5.11  
    5.12 @@ -40,28 +42,23 @@
    5.13  NS_OBJECT_ENSURE_REGISTERED (Object);
    5.14  
    5.15  Object::AggregateIterator::AggregateIterator ()
    5.16 -  : m_first (0),
    5.17 +  : m_object (0),
    5.18      m_current (0)
    5.19  {}
    5.20  
    5.21  bool 
    5.22  Object::AggregateIterator::HasNext (void) const
    5.23  {
    5.24 -  if (m_current != 0 && m_current->m_next != PeekPointer (m_first))
    5.25 -    {
    5.26 -      return true;
    5.27 -    }
    5.28 -  return false;
    5.29 +  return m_current < m_object->m_aggregates->n;
    5.30  }
    5.31  Ptr<const Object> 
    5.32  Object::AggregateIterator::Next (void)
    5.33  {
    5.34 -  m_current = m_current->m_next;
    5.35 -  return m_current;
    5.36 +  return m_object->m_aggregates->buffer[m_current];
    5.37  }
    5.38 -Object::AggregateIterator::AggregateIterator (Ptr<const Object> first)
    5.39 -  : m_first (first),
    5.40 -    m_current (first)
    5.41 +Object::AggregateIterator::AggregateIterator (Ptr<const Object> object)
    5.42 +  : m_object (object),
    5.43 +    m_current (0)
    5.44  {}
    5.45  
    5.46  
    5.47 @@ -85,18 +82,45 @@
    5.48    : m_count (1),
    5.49      m_tid (Object::GetTypeId ()),
    5.50      m_disposed (false),
    5.51 -    m_next (this)
    5.52 -{}
    5.53 +    m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
    5.54 +    m_getObjectCount (0)
    5.55 +{
    5.56 +  m_aggregates->n = 1;
    5.57 +  m_aggregates->buffer[0] = this;
    5.58 +}
    5.59  Object::~Object () 
    5.60  {
    5.61 -  m_next = 0;
    5.62 +  // remove this object from the aggregate list
    5.63 +  uint32_t n = m_aggregates->n;
    5.64 +  for (uint32_t i = 0; i < n; i++)
    5.65 +    {
    5.66 +      Object *current = m_aggregates->buffer[i];
    5.67 +      if (current == this)
    5.68 +        {
    5.69 +          memmove (&m_aggregates->buffer[i], 
    5.70 +                   &m_aggregates->buffer[i+1],
    5.71 +                   sizeof (Object *)*(m_aggregates->n - (i+1)));
    5.72 +          m_aggregates->n--;
    5.73 +        }
    5.74 +    }
    5.75 +  // finally, if all objects have been removed from the list,
    5.76 +  // delete the aggregate list
    5.77 +  if (m_aggregates->n == 0)
    5.78 +    {
    5.79 +      free (m_aggregates);
    5.80 +    }
    5.81 +  m_aggregates = 0;
    5.82  }
    5.83  Object::Object (const Object &o)
    5.84    : m_count (1),
    5.85      m_tid (o.m_tid),
    5.86      m_disposed (false),
    5.87 -    m_next (this)
    5.88 -{}
    5.89 +    m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
    5.90 +    m_getObjectCount (0)
    5.91 +{
    5.92 +  m_aggregates->n = 1;
    5.93 +  m_aggregates->buffer[0] = this;
    5.94 +}
    5.95  uint32_t
    5.96  Object::GetReferenceCount (void) const
    5.97  {
    5.98 @@ -112,48 +136,58 @@
    5.99  Object::DoGetObject (TypeId tid) const
   5.100  {
   5.101    NS_ASSERT (CheckLoose ());
   5.102 -  const Object *currentObject = this;
   5.103 -  const Object *prevObject = 0;
   5.104 +
   5.105 +  uint32_t n = m_aggregates->n;
   5.106    TypeId objectTid = Object::GetTypeId ();
   5.107 -  do {
   5.108 -    NS_ASSERT (currentObject != 0);
   5.109 -    TypeId cur = currentObject->GetInstanceTypeId ();
   5.110 -    while (cur != tid && cur != objectTid)
   5.111 -      {
   5.112 -        cur = cur.GetParent ();
   5.113 -      }
   5.114 -    if (cur == tid)
   5.115 -      {
   5.116 -        if (prevObject != 0)
   5.117 -          {
   5.118 -            // This is an attempt to 'cache' the result of this lookup.
   5.119 -            // the idea is that if we perform a lookup for a TypdId on this object,
   5.120 -            // we are likely to perform the same lookup later so, we re-order
   5.121 -            // the circular linked-list of objects here by putting the object we 
   5.122 -            // just found at the head of the list. This optimization is
   5.123 -            // _extremely_ effective in general.
   5.124 -            const_cast<Object*>(prevObject)->m_next = currentObject->m_next;
   5.125 -            const_cast<Object*>(currentObject)->m_next = m_next;
   5.126 -            const_cast<Object*>(this)->m_next = (Object*)currentObject;
   5.127 -          }
   5.128 -        return const_cast<Object *> (currentObject);
   5.129 -      }
   5.130 -    prevObject = currentObject;
   5.131 -    currentObject = currentObject->m_next;
   5.132 -  } while (currentObject != this);
   5.133 +  for (uint32_t i = 0; i < n; i++)
   5.134 +    {
   5.135 +      Object *current = m_aggregates->buffer[i];
   5.136 +      TypeId cur = current->GetInstanceTypeId ();
   5.137 +      while (cur != tid && cur != objectTid)
   5.138 +        {
   5.139 +          cur = cur.GetParent ();
   5.140 +        }
   5.141 +      if (cur == tid)
   5.142 +        {
   5.143 +          // This is an attempt to 'cache' the result of this lookup.
   5.144 +          // the idea is that if we perform a lookup for a TypeId on this object,
   5.145 +          // we are likely to perform the same lookup later so, we make sure
   5.146 +          // that the aggregate array is sorted by the number of accesses
   5.147 +          // to each object.
   5.148 +
   5.149 +          // first, increment the access count
   5.150 +          current->m_getObjectCount++;
   5.151 +          // then, update the sort
   5.152 +          UpdateSortedArray (m_aggregates, i);
   5.153 +          // finally, return the match
   5.154 +          return const_cast<Object *> (current);
   5.155 +        }
   5.156 +    }
   5.157    return 0;
   5.158  }
   5.159  void 
   5.160  Object::Dispose (void)
   5.161  {
   5.162 -  Object *current = this;
   5.163 -  do {
   5.164 -    NS_ASSERT (current != 0);
   5.165 -    NS_ASSERT (!current->m_disposed);
   5.166 -    current->DoDispose ();
   5.167 -    current->m_disposed = true;
   5.168 -    current = current->m_next;
   5.169 -  } while (current != this);
   5.170 +  uint32_t n = m_aggregates->n;
   5.171 +  for (uint32_t i = 0; i < n; i++)
   5.172 +    {
   5.173 +      Object *current = m_aggregates->buffer[i];
   5.174 +      NS_ASSERT (!current->m_disposed);
   5.175 +      current->DoDispose ();
   5.176 +      current->m_disposed = true;
   5.177 +    }
   5.178 +}
   5.179 +void
   5.180 +Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
   5.181 +{
   5.182 +  while (j > 0 && 
   5.183 +         aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount)
   5.184 +    {
   5.185 +      Object *tmp = aggregates->buffer[j-1];
   5.186 +      aggregates->buffer[j-1] = aggregates->buffer[j];
   5.187 +      aggregates->buffer[j] = tmp;
   5.188 +      j--;
   5.189 +    }
   5.190  }
   5.191  void 
   5.192  Object::AggregateObject (Ptr<Object> o)
   5.193 @@ -171,20 +205,38 @@
   5.194      }
   5.195  
   5.196    Object *other = PeekPointer (o);
   5.197 -  Object *next = m_next;
   5.198 -  m_next = other->m_next;
   5.199 -  other->m_next = next;
   5.200 -  NS_ASSERT (CheckLoose ());
   5.201 -  NS_ASSERT (o->CheckLoose ());
   5.202 -  // call NotifyNewAggregate in the listed chain
   5.203 -  Object *currentObject = this;
   5.204 -  do 
   5.205 +  // first create the new aggregate buffer.
   5.206 +  uint32_t total = m_aggregates->n + other->m_aggregates->n;
   5.207 +  struct Aggregates *aggregates = 
   5.208 +    (struct Aggregates *)malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*));
   5.209 +  aggregates->n = total;
   5.210 +  memcpy (&aggregates->buffer[0], 
   5.211 +          &m_aggregates->buffer[0], 
   5.212 +          m_aggregates->n*sizeof(Object*));
   5.213 +  // append the other aggregates in the new buffer
   5.214 +  for (uint32_t i = 0; i < other->m_aggregates->n; i++)
   5.215      {
   5.216 -      // the NotifyNewAggregate of the current object implementation
   5.217 -      // should be called on the next object in the linked chain
   5.218 -      currentObject->NotifyNewAggregate ();
   5.219 -      currentObject = currentObject->m_next;
   5.220 -    } while (currentObject != this);
   5.221 +      aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i];
   5.222 +      UpdateSortedArray (aggregates, m_aggregates->n + i);
   5.223 +    }
   5.224 +
   5.225 +  // free both aggregate buffers
   5.226 +  free (m_aggregates);
   5.227 +  free (other->m_aggregates);
   5.228 +
   5.229 +  // Then, assign that buffer to every object
   5.230 +  uint32_t n = aggregates->n;
   5.231 +  for (uint32_t i = 0; i < n; i++)
   5.232 +    {
   5.233 +      Object *current = aggregates->buffer[i];
   5.234 +      current->m_aggregates = aggregates;
   5.235 +    }
   5.236 +  // Finally, call NotifyNewAggregate in the listed chain
   5.237 +  for (uint32_t i = 0; i < n; i++)
   5.238 +    {
   5.239 +      Object *current = m_aggregates->buffer[i];
   5.240 +      current->NotifyNewAggregate ();
   5.241 +    }
   5.242  }
   5.243  /**
   5.244   * This function must be implemented in the stack that needs to notify
   5.245 @@ -233,14 +285,12 @@
   5.246  Object::CheckLoose (void) const
   5.247  {
   5.248    uint32_t refcount = 0;
   5.249 -  const Object *current = this;
   5.250 -  do
   5.251 +  uint32_t n = m_aggregates->n;
   5.252 +  for (uint32_t i = 0; i < n; i++)
   5.253      {
   5.254 +      Object *current = m_aggregates->buffer[i];
   5.255        refcount += current->m_count;
   5.256 -      current = current->m_next;
   5.257      }
   5.258 -  while (current != this);
   5.259 -
   5.260    return (refcount > 0);
   5.261  }
   5.262  
   5.263 @@ -249,38 +299,38 @@
   5.264  {
   5.265    // First, check if any of the attached
   5.266    // Object has a non-zero count.
   5.267 -  const Object *current = this;
   5.268 -  do {
   5.269 -    NS_ASSERT (current != 0);
   5.270 -    if (current->m_count != 0)
   5.271 -      {
   5.272 -        return;
   5.273 -      }
   5.274 -    current = current->m_next;
   5.275 -  } while (current != this);
   5.276 +  uint32_t n = m_aggregates->n;
   5.277 +  for (uint32_t i = 0; i < n; i++)
   5.278 +    {
   5.279 +      Object *current = m_aggregates->buffer[i];
   5.280 +      if (current->m_count != 0)
   5.281 +        {
   5.282 +          return;
   5.283 +        }
   5.284 +    }
   5.285  
   5.286    // Ensure we are disposed.
   5.287 -  Object *tmp = const_cast<Object *> (this);
   5.288 -  const Object *end = this;
   5.289 -  do {
   5.290 -    NS_ASSERT (current != 0);
   5.291 -    Object *next = tmp->m_next;
   5.292 -    if (!tmp->m_disposed)
   5.293 -      {
   5.294 -        tmp->DoDispose ();
   5.295 -      }
   5.296 -    tmp = next;
   5.297 -  } while (tmp != end);
   5.298 +  for (uint32_t i = 0; i < n; i++)
   5.299 +    {
   5.300 +      Object *current = m_aggregates->buffer[i];
   5.301 +      if (!current->m_disposed)
   5.302 +        {
   5.303 +          current->DoDispose ();
   5.304 +        }
   5.305 +    }
   5.306  
   5.307    // all attached objects have a zero count so, 
   5.308 -  // we can delete all attached objects.
   5.309 -  current = this;
   5.310 -  do {
   5.311 -    NS_ASSERT (current != 0);
   5.312 -    Object *next = current->m_next;
   5.313 -    delete current;
   5.314 -    current = next;
   5.315 -  } while (current != end);
   5.316 +  // we can delete them all.
   5.317 +  struct Aggregates *aggregates = m_aggregates;
   5.318 +  for (uint32_t i = 0; i < n; i++)
   5.319 +    {
   5.320 +      // There is a trick here: each time we call delete below,
   5.321 +      // the deleted object is removed from the aggregate buffer
   5.322 +      // in the destructor so, the index of the next element to 
   5.323 +      // lookup is always zero
   5.324 +      Object *current = aggregates->buffer[0];
   5.325 +      delete current;
   5.326 +    }
   5.327  }
   5.328  } // namespace ns3
   5.329  
     6.1 --- a/src/core/object.h	Thu Nov 05 19:14:37 2009 -0800
     6.2 +++ b/src/core/object.h	Thu Nov 05 19:15:28 2009 -0800
     6.3 @@ -85,9 +85,9 @@
     6.4      Ptr<const Object> Next (void);
     6.5    private:
     6.6      friend class Object;
     6.7 -    AggregateIterator (Ptr<const Object> first);
     6.8 -    Ptr<const Object> m_first;
     6.9 -    Ptr<const Object> m_current;
    6.10 +    AggregateIterator (Ptr<const Object> object);
    6.11 +    Ptr<const Object> m_object;
    6.12 +    uint32_t m_current;
    6.13    };
    6.14  
    6.15    Object ();
    6.16 @@ -215,6 +215,21 @@
    6.17    friend class ObjectFactory;
    6.18    friend class AggregateIterator;
    6.19  
    6.20 +  /**
    6.21 +   * This data structure uses a classic C-style trick to 
    6.22 +   * hold an array of variable size without performing
    6.23 +   * two memory allocations: the declaration of the structure
    6.24 +   * declares a one-element array but when we allocate
    6.25 +   * memory for this struct, we effectively allocate a larger
    6.26 +   * chunk of memory than the struct to allow space for a larger
    6.27 +   * variable sized buffer whose size is indicated by the element
    6.28 +   * 'n'
    6.29 +   */
    6.30 +  struct Aggregates {
    6.31 +    uint32_t n;
    6.32 +    Object *buffer[1];
    6.33 +  };
    6.34 +
    6.35    Ptr<Object> DoGetObject (TypeId tid) const;
    6.36    bool Check (void) const;
    6.37    bool CheckLoose (void) const;
    6.38 @@ -243,6 +258,8 @@
    6.39     */
    6.40    void Construct (const AttributeList &attributes);
    6.41  
    6.42 +  void UpdateSortedArray (struct Aggregates *aggregates, uint32_t i) const;
    6.43 +
    6.44    /**
    6.45     * The reference count for this object. Each aggregate
    6.46     * has an individual reference count. When the global
    6.47 @@ -261,13 +278,19 @@
    6.48     */
    6.49    bool m_disposed;
    6.50    /**
    6.51 -   * A pointer to the next aggregate object. This is a circular
    6.52 -   * linked list of aggregated objects: the last one points
    6.53 -   * back to the first one. If an object is not aggregated to
    6.54 -   * any other object, the value of this field is equal to the
    6.55 -   * value of the 'this' pointer.
    6.56 +   * a pointer to an array of 'aggregates'. i.e., a pointer to
    6.57 +   * each object aggregated to this object is stored in this 
    6.58 +   * array. The array is shared by all aggregated objects
    6.59 +   * so the size of the array is indirectly a reference count.
    6.60     */
    6.61 -  Object *m_next;
    6.62 +  struct Aggregates * m_aggregates;
    6.63 +  /**
    6.64 +   * Indicates the number of times the object was accessed with a
    6.65 +   * call to GetObject. This integer is used to implement a
    6.66 +   * heuristic to sort the array of aggregates to put at the start
    6.67 +   * of the array the most-frequently accessed elements.
    6.68 +   */
    6.69 +  uint32_t m_getObjectCount;
    6.70  };
    6.71  
    6.72  /**
     7.1 --- a/src/devices/mesh/dot11s/hwmp-protocol.cc	Thu Nov 05 19:14:37 2009 -0800
     7.2 +++ b/src/devices/mesh/dot11s/hwmp-protocol.cc	Thu Nov 05 19:15:28 2009 -0800
     7.3 @@ -401,6 +401,7 @@
     7.4    //acceptance cretirea:
     7.5    std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
     7.6        preq.GetOriginatorAddress ());
     7.7 +  bool freshInfo (true);
     7.8    if (i != m_hwmpSeqnoMetricDatabase.end ())
     7.9      {
    7.10        if ((int32_t)(i->second.first - preq.GetOriginatorSeqNumber ())  > 0)
    7.11 @@ -409,6 +410,7 @@
    7.12          }
    7.13        if (i->second.first == preq.GetOriginatorSeqNumber ())
    7.14          {
    7.15 +          freshInfo = false;
    7.16            if (i->second.second <= preq.GetMetric ())
    7.17              {
    7.18                return;
    7.19 @@ -421,7 +423,7 @@
    7.20    std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
    7.21    //Add reactive path to originator:
    7.22    if (
    7.23 -      ((int32_t)(i->second.first - preq.GetOriginatorSeqNumber ())  < 0) ||
    7.24 +      (freshInfo) ||
    7.25        (
    7.26          (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).retransmitter == Mac48Address::GetBroadcast ()) ||
    7.27          (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).metric > preq.GetMetric ())
    7.28 @@ -562,9 +564,17 @@
    7.29    //acceptance cretirea:
    7.30    std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
    7.31        prep.GetOriginatorAddress ());
    7.32 -  if ((i != m_hwmpSeqnoMetricDatabase.end ()) && ((int32_t)(i->second.first - prep.GetOriginatorSeqNumber ()) > 0))
    7.33 +  bool freshInfo (true);
    7.34 +  if (i != m_hwmpSeqnoMetricDatabase.end ())
    7.35      {
    7.36 -      return;
    7.37 +      if ((int32_t)(i->second.first - prep.GetOriginatorSeqNumber ()) > 0)
    7.38 +        {
    7.39 +          return;
    7.40 +        }
    7.41 +      if (i->second.first == prep.GetOriginatorSeqNumber ())
    7.42 +        {
    7.43 +          freshInfo = false;
    7.44 +        }
    7.45      }
    7.46    m_hwmpSeqnoMetricDatabase[prep.GetOriginatorAddress ()] = std::make_pair (prep.GetOriginatorSeqNumber (), prep.GetMetric ());
    7.47    //update routing info
    7.48 @@ -574,7 +584,7 @@
    7.49    //Add a reactive path only if seqno is fresher or it improves the
    7.50    //metric
    7.51    if (
    7.52 -      (((int32_t)(i->second.first - prep.GetOriginatorSeqNumber ()) < 0)) ||
    7.53 +      (freshInfo) ||
    7.54        (
    7.55         ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
    7.56         ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).metric > prep.GetMetric ())