View | Details | Raw Unified | Return to bug 2221
Collapse All | Expand All

(-)a/src/network/model/packet-tag-list.cc (-15 / +31 lines)
 Lines 34-39    Link Here 
34
34
35
NS_LOG_COMPONENT_DEFINE ("PacketTagList");
35
NS_LOG_COMPONENT_DEFINE ("PacketTagList");
36
36
37
PacketTagList::TagData *
38
PacketTagList::CreateTagData (size_t dataSize)
39
{
40
  NS_ASSERT_MSG (dataSize
41
                 < std::numeric_limits<decltype(TagData::size)>::max (),
42
                 "Requested TagData size " << dataSize
43
                 << " exceeds maximum "
44
                 << std::numeric_limits<decltype(TagData::size)>::max () );
45
46
  void * p = std::malloc (sizeof (TagData) + dataSize - 1);
47
  // The matching frees are in RemoveAll and RemoveWriter
48
49
  TagData * tag = new (p) TagData;
50
  tag->size = dataSize;
51
  return tag;
52
}
53
37
bool
54
bool
38
PacketTagList::COWTraverse (Tag & tag, PacketTagList::COWWriter Writer)
55
PacketTagList::COWTraverse (Tag & tag, PacketTagList::COWWriter Writer)
39
{
56
{
 Lines 133-142    Link Here 
133
      NS_ASSERT (cur != 0);
150
      NS_ASSERT (cur != 0);
134
      NS_ASSERT (cur->count > 1);
151
      NS_ASSERT (cur->count > 1);
135
      cur->count--;                       // unmerge cur
152
      cur->count--;                       // unmerge cur
136
      struct TagData * copy = new struct TagData ();
153
      struct TagData * copy = CreateTagData (cur->size);
137
      copy->tid = cur->tid;
154
      copy->tid = cur->tid;
138
      copy->count = 1;
155
      copy->count = 1;
139
      memcpy (copy->data, cur->data, TagData::MAX_SIZE);
156
      copy->size = cur->size;
157
      memcpy (copy->data, cur->data, copy->size);
140
      copy->next = cur->next;             // merge into tail
158
      copy->next = cur->next;             // merge into tail
141
      copy->next->count++;                // mark new merge
159
      copy->next->count++;                // mark new merge
142
      *prevNext = copy;                   // point prior list at copy
160
      *prevNext = copy;                   // point prior list at copy
 Lines 170-183    Link Here 
170
188
171
  // found tid
189
  // found tid
172
  bool found = true;
190
  bool found = true;
173
  tag.Deserialize (TagBuffer (cur->data,
191
  tag.Deserialize (TagBuffer (cur->data, cur->data + cur->size));
174
                              cur->data + TagData::MAX_SIZE));
175
  *prevNext = cur->next;            // link around cur
192
  *prevNext = cur->next;            // link around cur
176
193
177
  if (preMerge)
194
  if (preMerge)
178
    {
195
    {
179
      // found tid before first merge, so delete cur
196
      // found tid before first merge, so delete cur
180
      delete cur;
197
      cur->~TagData ();
198
      std::free (cur);
181
    }
199
    }
182
  else
200
  else
183
    {
201
    {
 Lines 217-235    Link Here 
217
  if (preMerge)
235
  if (preMerge)
218
    {
236
    {
219
      // found tid before first merge, so just rewrite
237
      // found tid before first merge, so just rewrite
220
      tag.Serialize (TagBuffer (cur->data,
238
      tag.Serialize (TagBuffer (cur->data, cur->data + cur->size));
221
                                cur->data + tag.GetSerializedSize ()));
222
    }
239
    }
223
  else
240
  else
224
    {
241
    {
225
      // cur is always a merge at this point
242
      // cur is always a merge at this point
226
      // need to copy, replace, and link past cur
243
      // need to copy, replace, and link past cur
227
      cur->count--;                     // unmerge cur
244
      cur->count--;                     // unmerge cur
228
      struct TagData * copy = new struct TagData ();
245
      struct TagData * copy = CreateTagData (tag.GetSerializedSize ());
229
      copy->tid = tag.GetInstanceTypeId ();
246
      copy->tid = tag.GetInstanceTypeId ();
230
      copy->count = 1;
247
      copy->count = 1;
231
      tag.Serialize (TagBuffer (copy->data,
248
      tag.Serialize (TagBuffer (copy->data, copy->data + copy->size));
232
                                copy->data + tag.GetSerializedSize ()));
233
      copy->next = cur->next;           // merge into tail
249
      copy->next = cur->next;           // merge into tail
234
      if (copy->next != 0)
250
      if (copy->next != 0)
235
        {
251
        {
 Lines 247-261    Link Here 
247
  // ensure this id was not yet added
263
  // ensure this id was not yet added
248
  for (struct TagData *cur = m_next; cur != 0; cur = cur->next) 
264
  for (struct TagData *cur = m_next; cur != 0; cur = cur->next) 
249
    {
265
    {
250
      NS_ASSERT_MSG (cur->tid != tag.GetInstanceTypeId (), "Error: cannot add the same kind of tag twice.");
266
      NS_ASSERT_MSG (cur->tid != tag.GetInstanceTypeId (),
267
                     "Error: cannot add the same kind of tag twice.");
251
    }
268
    }
252
  struct TagData * head = new struct TagData ();
269
  struct TagData * head = CreateTagData (tag.GetSerializedSize ());
253
  head->count = 1;
270
  head->count = 1;
254
  head->next = 0;
271
  head->next = 0;
255
  head->tid = tag.GetInstanceTypeId ();
272
  head->tid = tag.GetInstanceTypeId ();
256
  head->next = m_next;
273
  head->next = m_next;
257
  NS_ASSERT (tag.GetSerializedSize () <= TagData::MAX_SIZE);
274
  tag.Serialize (TagBuffer (head->data, head->data + head->size));
258
  tag.Serialize (TagBuffer (head->data, head->data + tag.GetSerializedSize ()));
259
275
260
  const_cast<PacketTagList *> (this)->m_next = head;
276
  const_cast<PacketTagList *> (this)->m_next = head;
261
}
277
}
 Lines 270-276    Link Here 
270
      if (cur->tid == tid) 
286
      if (cur->tid == tid) 
271
        {
287
        {
272
          /* found tag */
288
          /* found tag */
273
          tag.Deserialize (TagBuffer (cur->data, cur->data + TagData::MAX_SIZE));
289
          tag.Deserialize (TagBuffer (cur->data, cur->data + cur->size));
274
          return true;
290
          return true;
275
        }
291
        }
276
    }
292
    }
(-)a/src/network/model/packet-tag-list.h (-38 / +31 lines)
 Lines 119-130    Link Here 
119
 *       The portion of the list between the first branch and the target is
119
 *       The portion of the list between the first branch and the target is
120
 *       shared. This portion is copied before the #Remove or #Replace is
120
 *       shared. This portion is copied before the #Remove or #Replace is
121
 *       performed.
121
 *       performed.
122
 *
123
 * \par <b> Memory Management: </b>
124
 * \n
125
 * Packet tags must serialize to a finite maximum size, see TagData
126
 *
127
 * This documentation entitles the original author to a free beer.
128
 */
122
 */
129
class PacketTagList 
123
class PacketTagList 
130
{
124
{
 Lines 134-170    Link Here 
134
   *
128
   *
135
   * See PacketTagList for a discussion of the data structure.
129
   * See PacketTagList for a discussion of the data structure.
136
   *
130
   *
137
   * See TagData::TagData_e for a discussion of the size limit on
131
   * \internal
138
   * tag serialization.
132
   * Unfortunately this has to be public, because
133
   * PacketTagIterator::Item::GetTag() needs the data and size values.
134
   * The Item nested class can't be forward declared, so friending isn't
135
   * possible.
136
   *
137
   * We use placement new so we can allocate enough room for the Tag
138
   * type which will be serialized into data.  See Object::Aggregates
139
   * for a similar construction.
139
   */
140
   */
140
  struct TagData
141
  struct TagData
141
  {
142
  {
142
    /**
143
    struct TagData * next;      /**< Pointer to next in list */
143
     * \brief Packet Tag maximum size
144
    uint32_t count;             /**< Number of incoming links */
144
     *
145
    TypeId tid;                 /**< Type of the tag serialized into #data */
145
     * The maximum size (in bytes) of a Tag is stored
146
    uint32_t size;              /**< Size of the \c data buffer */
146
     * in this constant.
147
    uint8_t data[1];            /**< Serialization buffer */
147
     *
148
     * \internal
149
     * Ideally, TagData would be 32 bytes in size, so they require
150
     * no padding on 64-bit architectures.  (The architecture
151
     * affects the size because of the \c #next pointer.)
152
     * This would leave 18 bytes for \c #data.  However,
153
     * ns3:Ipv6PacketInfoTag needs 19 bytes!  The current
154
     * implementation allows 20 bytes, which gives TagData
155
     * a size of 30 bytes on 32-byte machines (which gets
156
     * padded with 2 bytes), and 34 bytes on 64-bit machines, which
157
     * gets padded to 40 bytes.
158
     */
159
    enum TagData_e
160
    {
161
      MAX_SIZE = 21           /**< Size of serialization buffer #data */
162
  };
163
164
    uint8_t data[MAX_SIZE];   /**< Serialization buffer */
165
    struct TagData * next;   /**< Pointer to next in list */
166
    TypeId tid;               /**< Type of the tag serialized into #data */
167
    uint32_t count;           /**< Number of incoming links */
168
  };  /* struct TagData */
148
  };  /* struct TagData */
169
149
170
  /**
150
  /**
 Lines 240-245    Link Here 
240
220
241
private:
221
private:
242
  /**
222
  /**
223
   * Allocate and construct a TagData struct, sizing the data area
224
   * large enough to serialize dataSize bytes from a Tag.
225
   *
226
   * \param [in] dataSize The serialized size of the Tag.
227
   * \returns The newly constructed TagData object.
228
   */
229
  static
230
  TagData * CreateTagData (size_t dataSize);
231
  
232
  /**
243
   * Typedef of method function pointer for copy-on-write operations
233
   * Typedef of method function pointer for copy-on-write operations
244
   *
234
   *
245
   * \param [in] tag The tag type to operate on.
235
   * \param [in] tag The tag type to operate on.
 Lines 272-278    Link Here 
272
   *          pointing to \pname{cur}.
262
   *          pointing to \pname{cur}.
273
   * \returns True, since tag will definitely be removed.
263
   * \returns True, since tag will definitely be removed.
274
   */
264
   */
275
  bool RemoveWriter  (Tag       & tag, bool         preMerge,
265
  bool RemoveWriter  (Tag & tag, bool preMerge,
276
                      struct TagData * cur, struct TagData ** prevNext);
266
                      struct TagData * cur, struct TagData ** prevNext);
277
  /**
267
  /**
278
   * Copy-on-write implementing Replace
268
   * Copy-on-write implementing Replace
 Lines 285-291    Link Here 
285
   *          pointing to \pname{cur}.
275
   *          pointing to \pname{cur}.
286
   * \returns True, since tag value will definitely be replaced.
276
   * \returns True, since tag value will definitely be replaced.
287
   */
277
   */
288
  bool ReplaceWriter (Tag & tag, bool preMerge, struct TagData * cur, struct TagData ** prevNext);
278
  bool ReplaceWriter (Tag & tag, bool preMerge,
279
                      struct TagData * cur, struct TagData ** prevNext);
289
280
290
  /**
281
  /**
291
   * Pointer to first \ref TagData on the list
282
   * Pointer to first \ref TagData on the list
 Lines 350-362    Link Here 
350
        }
341
        }
351
      if (prev != 0) 
342
      if (prev != 0) 
352
        {
343
        {
353
	  delete prev;
344
          prev->~TagData ();
345
          std::free (prev);
354
        }
346
        }
355
      prev = cur;
347
      prev = cur;
356
    }
348
    }
357
  if (prev != 0) 
349
  if (prev != 0) 
358
    {
350
    {
359
      delete prev;
351
      prev->~TagData ();
352
      std::free (prev);
360
    }
353
    }
361
  m_next = 0;
354
  m_next = 0;
362
}
355
}
(-)a/src/network/model/packet.cc (-2 / +1 lines)
 Lines 113-120    Link Here 
113
{
113
{
114
  NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
114
  NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
115
  tag.Deserialize (TagBuffer ((uint8_t*)m_data->data,
115
  tag.Deserialize (TagBuffer ((uint8_t*)m_data->data,
116
                              (uint8_t*)m_data->data
116
                              (uint8_t*)m_data->data + m_data->size));
117
                              + PacketTagList::TagData::MAX_SIZE));
118
}
117
}
119
118
120
119
(-)a/src/network/utils/packet-socket.cc (-3 lines)
 Lines 643-649    Link Here 
643
DeviceNameTag::GetSerializedSize (void) const
643
DeviceNameTag::GetSerializedSize (void) const
644
{
644
{
645
  uint32_t s = 1 + m_deviceName.size();  // +1 for name length field
645
  uint32_t s = 1 + m_deviceName.size();  // +1 for name length field
646
  s = std::min (s, (uint32_t)PacketTagList::TagData::MAX_SIZE);
647
  return s;
646
  return s;
648
}
647
}
649
void
648
void
 Lines 652-659    Link Here 
652
  const char *n = m_deviceName.c_str();
651
  const char *n = m_deviceName.c_str();
653
  uint8_t l = (uint8_t) m_deviceName.size ();
652
  uint8_t l = (uint8_t) m_deviceName.size ();
654
653
655
  l = std::min ((uint32_t)l, (uint32_t)PacketTagList::TagData::MAX_SIZE - 1);
656
657
  i.WriteU8 (l);
654
  i.WriteU8 (l);
658
  i.Write ( (uint8_t*) n , (uint32_t) l);
655
  i.Write ( (uint8_t*) n , (uint32_t) l);
659
}
656
}

Return to bug 2221