68 * a public method named GetUid, as documented in the ns3::Header and ns::Trailer |
68 * a public method named GetUid, as documented in the ns3::Header and ns::Trailer |
69 * API documentations. |
69 * API documentations. |
70 * |
70 * |
71 * Implementing a new type of Tag requires roughly the same amount of |
71 * Implementing a new type of Tag requires roughly the same amount of |
72 * work: users must implement a total of 6 methods which are described in |
72 * work: users must implement a total of 6 methods which are described in |
73 * the ns3::Tags API documentation. |
73 * \ref tags |
74 * |
74 * |
|
75 * The performance aspects of the Packet API are discussed in |
|
76 * \ref packetperf |
|
77 */ |
|
78 class Packet { |
|
79 public: |
|
80 /** |
|
81 * Create an empty packet with a new uid (as returned |
|
82 * by getUid). |
|
83 */ |
|
84 Packet (); |
|
85 /** |
|
86 * Create a packet with a zero-filled payload. |
|
87 * The memory necessary for the payload is not allocated: |
|
88 * it will be allocated at any later point if you attempt |
|
89 * to fragment this packet or to access the zero-filled |
|
90 * bytes. The packet is allocated with a new uid (as |
|
91 * returned by getUid). |
|
92 * |
|
93 * \param size the size of the zero-filled payload |
|
94 */ |
|
95 Packet (uint32_t size); |
|
96 /** |
|
97 * Create a packet with payload filled with the content |
|
98 * of this buffer. The input data is copied: the input |
|
99 * buffer is untouched. |
|
100 * |
|
101 * \param buffer the data to store in the packet. |
|
102 * \param size the size of the input buffer. |
|
103 */ |
|
104 Packet (uint8_t const*buffer, uint32_t size); |
|
105 /** |
|
106 * Create a new packet which contains a fragment of the original |
|
107 * packet. The returned packet shares the same uid as this packet. |
|
108 * |
|
109 * \param start offset from start of packet to start of fragment to create |
|
110 * \param length length of fragment to create |
|
111 * \returns a fragment of the original packet |
|
112 */ |
|
113 Packet CreateFragment (uint32_t start, uint32_t length) const; |
|
114 /** |
|
115 * \returns the size in bytes of the packet (including the zero-filled |
|
116 * initial payload) |
|
117 */ |
|
118 uint32_t GetSize (void) const; |
|
119 /** |
|
120 * Add header to this packet. This method invokes the |
|
121 * ns3::Chunk::GetSerializedSize and ns3::Chunk::SerializeTo |
|
122 * methods to reserve space in the buffer and request the |
|
123 * header to serialize itself in the packet buffer. |
|
124 * |
|
125 * \param header a reference to the header to add to this packet. |
|
126 */ |
|
127 template <typename T> |
|
128 void AddHeader (T const &header); |
|
129 /** |
|
130 * Deserialize and remove the header from the internal buffer. |
|
131 * This method invokes ns3::Chunk::DeserializeFrom. |
|
132 * |
|
133 * \param header a reference to the header to remove from the internal buffer. |
|
134 * \returns the number of bytes removed from the packet. |
|
135 */ |
|
136 template <typename T> |
|
137 uint32_t RemoveHeader (T &header); |
|
138 /** |
|
139 * Add trailer to this packet. This method invokes the |
|
140 * ns3::Chunk::GetSerializedSize and ns3::Trailer::serializeTo |
|
141 * methods to reserve space in the buffer and request the trailer |
|
142 * to serialize itself in the packet buffer. |
|
143 * |
|
144 * \param trailer a reference to the trailer to add to this packet. |
|
145 */ |
|
146 template <typename T> |
|
147 void AddTrailer (T const &trailer); |
|
148 /** |
|
149 * Remove a deserialized trailer from the internal buffer. |
|
150 * This method invokes the ns3::Chunk::DeserializeFrom method. |
|
151 * |
|
152 * \param trailer a reference to the trailer to remove from the internal buffer. |
|
153 * \returns the number of bytes removed from the end of the packet. |
|
154 */ |
|
155 template <typename T> |
|
156 uint32_t RemoveTrailer (T &trailer); |
|
157 /** |
|
158 * Attach a tag to this packet. The tag is fully copied |
|
159 * in a packet-specific internal buffer. This operation |
|
160 * is expected to be really fast. |
|
161 * |
|
162 * \param tag a pointer to the tag to attach to this packet. |
|
163 */ |
|
164 template <typename T> |
|
165 void AddTag (T const &tag); |
|
166 /** |
|
167 * Remove a tag from this packet. The data stored internally |
|
168 * for this tag is copied in the input tag if an instance |
|
169 * of this tag type is present in the internal buffer. If this |
|
170 * tag type is not present, the input tag is not modified. |
|
171 * |
|
172 * This operation can be potentially slow and might trigger |
|
173 * unexpectedly large memory allocations. It is thus |
|
174 * usually a better idea to create a copy of this packet, |
|
175 * and invoke removeAllTags on the copy to remove all |
|
176 * tags rather than remove the tags one by one from a packet. |
|
177 * |
|
178 * \param tag a pointer to the tag to remove from this packet |
|
179 * \returns true if an instance of this tag type is stored |
|
180 * in this packet, false otherwise. |
|
181 */ |
|
182 template <typename T> |
|
183 bool RemoveTag (T &tag); |
|
184 /** |
|
185 * Copy a tag stored internally to the input tag. If no instance |
|
186 * of this tag is present internally, the input tag is not modified. |
|
187 * |
|
188 * \param tag a pointer to the tag to read from this packet |
|
189 * \returns true if an instance of this tag type is stored |
|
190 * in this packet, false otherwise. |
|
191 */ |
|
192 template <typename T> |
|
193 bool PeekTag (T &tag) const; |
|
194 /** |
|
195 * Remove all the tags stored in this packet. This operation is |
|
196 * much much faster than invoking removeTag n times. |
|
197 */ |
|
198 void RemoveAllTags (void); |
|
199 /** |
|
200 * Concatenate the input packet at the end of the current |
|
201 * packet. This does not alter the uid of either packet. |
|
202 * |
|
203 * \param packet packet to concatenate |
|
204 */ |
|
205 void AddAtEnd (Packet packet); |
|
206 /** |
|
207 * \param size number of padding bytes to add. |
|
208 */ |
|
209 void AddPaddingAtEnd (uint32_t size); |
|
210 /** |
|
211 * Remove size bytes from the end of the current packet |
|
212 * It is safe to remove more bytes that what is present in |
|
213 * the packet. |
|
214 * |
|
215 * \param size number of bytes from remove |
|
216 */ |
|
217 void RemoveAtEnd (uint32_t size); |
|
218 /** |
|
219 * Remove size bytes from the start of the current packet. |
|
220 * It is safe to remove more bytes that what is present in |
|
221 * the packet. |
|
222 * |
|
223 * \param size number of bytes from remove |
|
224 */ |
|
225 void RemoveAtStart (uint32_t size); |
|
226 |
|
227 /** |
|
228 * If you try to change the content of the buffer |
|
229 * returned by this method, you will die. |
|
230 * |
|
231 * \returns a pointer to the internal buffer of the packet. |
|
232 */ |
|
233 uint8_t const *PeekData (void) const; |
|
234 |
|
235 /** |
|
236 * A packet is allocated a new uid when it is created |
|
237 * empty or with zero-filled payload. |
|
238 * |
|
239 * \returns an integer identifier which uniquely |
|
240 * identifies this packet. |
|
241 */ |
|
242 uint32_t GetUid (void) const; |
|
243 |
|
244 /** |
|
245 * \param os output stream in which the data should be printed. |
|
246 * |
|
247 * Iterate over the headers and trailers present in this packet, |
|
248 * from the first header to the last trailer and invoke, for |
|
249 * each of them, the user-provided method Header::DoPrint or |
|
250 * Trailer::DoPrint methods. |
|
251 */ |
|
252 void Print (std::ostream &os) const; |
|
253 /** |
|
254 * \param os output stream in which the data should be printed. |
|
255 * \param printer the output formatter to use to print |
|
256 * the content of this packet. |
|
257 * |
|
258 * Iterate over the headers and trailers present in this packet, |
|
259 * either in the "forward" (first header to last trailer) or in |
|
260 * the "backward" (last trailer to first header) direction, as |
|
261 * specified by the PacketPrinter::PrintForward or the |
|
262 * PacketPrinter::PrintBackward methods. For each header, trailer, |
|
263 * or fragment of a header or a trailer, invoke the user-specified |
|
264 * print callback stored in the specified PacketPrinter. |
|
265 */ |
|
266 void Print (std::ostream &os, const PacketPrinter &printer) const; |
|
267 |
|
268 /** |
|
269 * By default, packets do not keep around enough metadata to |
|
270 * perform the operations requested by the Print methods. If you |
|
271 * want to be able to invoke any of the two ::Print methods, |
|
272 * you need to invoke this method at least once during the |
|
273 * simulation setup and before any packet is created. |
|
274 * |
|
275 * The packet metadata is also used to perform extensive |
|
276 * sanity checks at runtime when performing operations on a |
|
277 * Packet. For example, this metadata is used to verify that |
|
278 * when you remove a header from a packet, this same header |
|
279 * was actually present at the front of the packet. These |
|
280 * errors will be detected and will abort the program. |
|
281 */ |
|
282 static void EnableMetadata (void); |
|
283 private: |
|
284 Packet (Buffer buffer, Tags tags, PacketMetadata metadata); |
|
285 Buffer m_buffer; |
|
286 Tags m_tags; |
|
287 PacketMetadata m_metadata; |
|
288 static uint32_t m_globalUid; |
|
289 }; |
|
290 |
|
291 /** |
|
292 * \defgroup tags Packet Tags |
|
293 * |
|
294 * A tag is a class which must define: |
|
295 * - a public default constructor |
|
296 * - a public static method named GetUid |
|
297 * - a public method named Print |
|
298 * - a public method named GetSerializedSize |
|
299 * - a public method named Serialize |
|
300 * - a public method named Deserialize |
|
301 * |
|
302 * So, a tag class should look like this: |
|
303 * \code |
|
304 * // note how a tag class does not derive from any other class. |
|
305 * class MyTag |
|
306 * { |
|
307 * public: |
|
308 * // we need a public default constructor |
|
309 * MyTag (); |
|
310 * // we need a public static GetUid |
|
311 * // GetUid must return a string which uniquely |
|
312 * // identifies this tag type |
|
313 * static std::string GetUid (void); |
|
314 * // Print should record in the output stream |
|
315 * // the content of the tag instance. |
|
316 * void Print (std::ostream &os) const; |
|
317 * // GetSerializedSize should return the number of bytes needed |
|
318 * // to store the state of a tag instance |
|
319 * uint32_t GetSerializedSize (void) const; |
|
320 * // Serialize should store its state in the input |
|
321 * // buffer with the help of the iterator. It should |
|
322 * // write exactly size bytes. |
|
323 * void Serialize (Buffer::Iterator i, uint32_t size) const; |
|
324 * // Deserialize should restore the state of a Tag instance |
|
325 * // from a byte buffer with the help of the iterator |
|
326 * uint32_t Deserialize (Buffer::Iterator i); |
|
327 * }; |
|
328 * |
|
329 * std::string MyTag::GetUid (void) |
|
330 * { |
|
331 * // we really want to make sure that this |
|
332 * // string is unique in the universe. |
|
333 * return "MyTag.unique.prefix"; |
|
334 * } |
|
335 * \endcode |
|
336 */ |
|
337 |
|
338 /** |
|
339 * \defgroup packetperf Packet Performance |
75 * The current implementation of the byte buffers and tag list is based |
340 * The current implementation of the byte buffers and tag list is based |
76 * on COW (Copy On Write. An introduction to COW can be found in Scott |
341 * on COW (Copy On Write. An introduction to COW can be found in Scott |
77 * Meyer's "More Effective C++", items 17 and 29). What this means is that |
342 * Meyer's "More Effective C++", items 17 and 29). What this means is that |
78 * copying packets without modifying them is very cheap (in terms of cpu |
343 * copying packets without modifying them is very cheap (in terms of cpu |
79 * and memory usage) and modifying them can be also very cheap. What is |
344 * and memory usage) and modifying them can be also very cheap. What is |
102 * sometimes by several orders of magnitude. However, even the |
367 * sometimes by several orders of magnitude. However, even the |
103 * dirty operations have been optimized for common use-cases which |
368 * dirty operations have been optimized for common use-cases which |
104 * means that most of the time, these operations will not trigger |
369 * means that most of the time, these operations will not trigger |
105 * data copies and will thus be still very fast. |
370 * data copies and will thus be still very fast. |
106 */ |
371 */ |
107 class Packet { |
372 |
108 public: |
373 } // namespace ns3 |
109 /** |
|
110 * Create an empty packet with a new uid (as returned |
|
111 * by getUid). |
|
112 */ |
|
113 Packet (); |
|
114 /** |
|
115 * Create a packet with a zero-filled payload. |
|
116 * The memory necessary for the payload is not allocated: |
|
117 * it will be allocated at any later point if you attempt |
|
118 * to fragment this packet or to access the zero-filled |
|
119 * bytes. The packet is allocated with a new uid (as |
|
120 * returned by getUid). |
|
121 * |
|
122 * \param size the size of the zero-filled payload |
|
123 */ |
|
124 Packet (uint32_t size); |
|
125 /** |
|
126 * Create a packet with payload filled with the content |
|
127 * of this buffer. The input data is copied: the input |
|
128 * buffer is untouched. |
|
129 * |
|
130 * \param buffer the data to store in the packet. |
|
131 * \param size the size of the input buffer. |
|
132 */ |
|
133 Packet (uint8_t const*buffer, uint32_t size); |
|
134 /** |
|
135 * Create a new packet which contains a fragment of the original |
|
136 * packet. The returned packet shares the same uid as this packet. |
|
137 * |
|
138 * \param start offset from start of packet to start of fragment to create |
|
139 * \param length length of fragment to create |
|
140 * \returns a fragment of the original packet |
|
141 */ |
|
142 Packet CreateFragment (uint32_t start, uint32_t length) const; |
|
143 /** |
|
144 * \returns the size in bytes of the packet (including the zero-filled |
|
145 * initial payload) |
|
146 */ |
|
147 uint32_t GetSize (void) const; |
|
148 /** |
|
149 * Add header to this packet. This method invokes the |
|
150 * ns3::Chunk::GetSerializedSize and ns3::Chunk::SerializeTo |
|
151 * methods to reserve space in the buffer and request the |
|
152 * header to serialize itself in the packet buffer. |
|
153 * |
|
154 * \param header a reference to the header to add to this packet. |
|
155 */ |
|
156 template <typename T> |
|
157 void AddHeader (T const &header); |
|
158 /** |
|
159 * Deserialize and remove the header from the internal buffer. |
|
160 * This method invokes ns3::Chunk::DeserializeFrom. |
|
161 * |
|
162 * \param header a reference to the header to remove from the internal buffer. |
|
163 * \returns the number of bytes removed from the packet. |
|
164 */ |
|
165 template <typename T> |
|
166 uint32_t RemoveHeader (T &header); |
|
167 /** |
|
168 * Add trailer to this packet. This method invokes the |
|
169 * ns3::Chunk::GetSerializedSize and ns3::Trailer::serializeTo |
|
170 * methods to reserve space in the buffer and request the trailer |
|
171 * to serialize itself in the packet buffer. |
|
172 * |
|
173 * \param trailer a reference to the trailer to add to this packet. |
|
174 */ |
|
175 template <typename T> |
|
176 void AddTrailer (T const &trailer); |
|
177 /** |
|
178 * Remove a deserialized trailer from the internal buffer. |
|
179 * This method invokes the ns3::Chunk::DeserializeFrom method. |
|
180 * |
|
181 * \param trailer a reference to the trailer to remove from the internal buffer. |
|
182 * \returns the number of bytes removed from the end of the packet. |
|
183 */ |
|
184 template <typename T> |
|
185 uint32_t RemoveTrailer (T &trailer); |
|
186 /** |
|
187 * Attach a tag to this packet. The tag is fully copied |
|
188 * in a packet-specific internal buffer. This operation |
|
189 * is expected to be really fast. |
|
190 * |
|
191 * \param tag a pointer to the tag to attach to this packet. |
|
192 */ |
|
193 template <typename T> |
|
194 void AddTag (T const &tag); |
|
195 /** |
|
196 * Remove a tag from this packet. The data stored internally |
|
197 * for this tag is copied in the input tag if an instance |
|
198 * of this tag type is present in the internal buffer. If this |
|
199 * tag type is not present, the input tag is not modified. |
|
200 * |
|
201 * This operation can be potentially slow and might trigger |
|
202 * unexpectedly large memory allocations. It is thus |
|
203 * usually a better idea to create a copy of this packet, |
|
204 * and invoke removeAllTags on the copy to remove all |
|
205 * tags rather than remove the tags one by one from a packet. |
|
206 * |
|
207 * \param tag a pointer to the tag to remove from this packet |
|
208 * \returns true if an instance of this tag type is stored |
|
209 * in this packet, false otherwise. |
|
210 */ |
|
211 template <typename T> |
|
212 bool RemoveTag (T &tag); |
|
213 /** |
|
214 * Copy a tag stored internally to the input tag. If no instance |
|
215 * of this tag is present internally, the input tag is not modified. |
|
216 * |
|
217 * \param tag a pointer to the tag to read from this packet |
|
218 * \returns true if an instance of this tag type is stored |
|
219 * in this packet, false otherwise. |
|
220 */ |
|
221 template <typename T> |
|
222 bool PeekTag (T &tag) const; |
|
223 /** |
|
224 * Remove all the tags stored in this packet. This operation is |
|
225 * much much faster than invoking removeTag n times. |
|
226 */ |
|
227 void RemoveAllTags (void); |
|
228 /** |
|
229 * Concatenate the input packet at the end of the current |
|
230 * packet. This does not alter the uid of either packet. |
|
231 * |
|
232 * \param packet packet to concatenate |
|
233 */ |
|
234 void AddAtEnd (Packet packet); |
|
235 /** |
|
236 * \param size number of padding bytes to add. |
|
237 */ |
|
238 void AddPaddingAtEnd (uint32_t size); |
|
239 /** |
|
240 * Remove size bytes from the end of the current packet |
|
241 * It is safe to remove more bytes that what is present in |
|
242 * the packet. |
|
243 * |
|
244 * \param size number of bytes from remove |
|
245 */ |
|
246 void RemoveAtEnd (uint32_t size); |
|
247 /** |
|
248 * Remove size bytes from the start of the current packet. |
|
249 * It is safe to remove more bytes that what is present in |
|
250 * the packet. |
|
251 * |
|
252 * \param size number of bytes from remove |
|
253 */ |
|
254 void RemoveAtStart (uint32_t size); |
|
255 |
|
256 /** |
|
257 * If you try to change the content of the buffer |
|
258 * returned by this method, you will die. |
|
259 * |
|
260 * \returns a pointer to the internal buffer of the packet. |
|
261 */ |
|
262 uint8_t const *PeekData (void) const; |
|
263 |
|
264 /** |
|
265 * A packet is allocated a new uid when it is created |
|
266 * empty or with zero-filled payload. |
|
267 * |
|
268 * \returns an integer identifier which uniquely |
|
269 * identifies this packet. |
|
270 */ |
|
271 uint32_t GetUid (void) const; |
|
272 |
|
273 /** |
|
274 * \param os output stream in which the data should be printed. |
|
275 * |
|
276 * Iterate over the headers and trailers present in this packet, |
|
277 * from the first header to the last trailer and invoke, for |
|
278 * each of them, the user-provided method Header::DoPrint or |
|
279 * Trailer::DoPrint methods. |
|
280 */ |
|
281 void Print (std::ostream &os) const; |
|
282 /** |
|
283 * \param os output stream in which the data should be printed. |
|
284 * \param printer the output formatter to use to print |
|
285 * the content of this packet. |
|
286 * |
|
287 * Iterate over the headers and trailers present in this packet, |
|
288 * either in the "forward" (first header to last trailer) or in |
|
289 * the "backward" (last trailer to first header) direction, as |
|
290 * specified by the PacketPrinter::PrintForward or the |
|
291 * PacketPrinter::PrintBackward methods. For each header, trailer, |
|
292 * or fragment of a header or a trailer, invoke the user-specified |
|
293 * print callback stored in the specified PacketPrinter. |
|
294 */ |
|
295 void Print (std::ostream &os, const PacketPrinter &printer) const; |
|
296 |
|
297 /** |
|
298 * By default, packets do not keep around enough metadata to |
|
299 * perform the operations requested by the Print methods. If you |
|
300 * want to be able to invoke any of the two ::Print methods, |
|
301 * you need to invoke this method at least once during the |
|
302 * simulation setup and before any packet is created. |
|
303 * |
|
304 * The packet metadata is also used to perform extensive |
|
305 * sanity checks at runtime when performing operations on a |
|
306 * Packet. For example, this metadata is used to verify that |
|
307 * when you remove a header from a packet, this same header |
|
308 * was actually present at the front of the packet. These |
|
309 * errors will be detected and will abort the program. |
|
310 */ |
|
311 static void EnableMetadata (void); |
|
312 private: |
|
313 Packet (Buffer buffer, Tags tags, PacketMetadata metadata); |
|
314 Buffer m_buffer; |
|
315 Tags m_tags; |
|
316 PacketMetadata m_metadata; |
|
317 static uint32_t m_globalUid; |
|
318 }; |
|
319 |
|
320 }; // namespace ns3 |
|
321 |
374 |
322 |
375 |
323 /************************************************** |
376 /************************************************** |
324 Start of implementation of templates defined |
377 Start of implementation of templates defined |
325 above |
378 above |