A Discrete-Event Network Simulator
API
bench-packets.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2006 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20
21// This program can be used to benchmark packet serialization/deserialization
22// operations using Headers and Tags, for various numbers of packets 'n'
23// Sample usage: ./ns3 run 'bench-packets --n=10000'
24
25#include "ns3/command-line.h"
26#include "ns3/system-wall-clock-ms.h"
27#include "ns3/packet.h"
28#include "ns3/packet-metadata.h"
29#include <iostream>
30#include <sstream>
31#include <string>
32#include <stdlib.h> // for exit ()
33#include <limits>
34#include <algorithm>
35
36using namespace ns3;
37
39template <int N>
40class BenchHeader : public Header
41{
42public:
43 BenchHeader ();
51 bool IsOk (void) const;
52
57 static TypeId GetTypeId (void);
58 virtual TypeId GetInstanceTypeId (void) const;
59 virtual void Print (std::ostream &os) const;
60 virtual uint32_t GetSerializedSize (void) const;
61 virtual void Serialize (Buffer::Iterator start) const;
63private:
68 static std::string GetTypeName (void);
69 bool m_ok;
70};
71
72template <int N>
74 : m_ok (false)
75{}
76
77template <int N>
78bool
80{
81 return m_ok;
82}
83
84template <int N>
85std::string
87{
88 std::ostringstream oss;
89 oss << "ns3::BenchHeader<" << N << ">";
90 return oss.str ();
91}
92
93template <int N>
96{
97 static TypeId tid = TypeId (GetTypeName ())
98 .SetParent<Header> ()
99 .SetGroupName ("Utils")
100 .HideFromDocumentation ()
101 .AddConstructor<BenchHeader <N> > ()
102 ;
103 return tid;
104}
105template <int N>
106TypeId
108{
109 return GetTypeId ();
110}
111
112template <int N>
113void
114BenchHeader<N>::Print (std::ostream &os) const
115{
116 NS_ASSERT (false);
117}
118template <int N>
121{
122 return N;
123}
124template <int N>
125void
127{
128 start.WriteU8 (N, N);
129}
130template <int N>
133{
134 m_ok = true;
135 for (int i = 0; i < N; i++)
136 {
137 if (start.ReadU8 () != N)
138 {
139 m_ok = false;
140 }
141 }
142 return N;
143}
144
146template <int N>
147class BenchTag : public Tag
148{
149public:
154 static std::string GetName (void) {
155 std::ostringstream oss;
156 oss << "anon::BenchTag<" << N << ">";
157 return oss.str ();
158 }
163 static TypeId GetTypeId (void) {
164 static TypeId tid = TypeId (GetName ())
165 .SetParent<Tag> ()
166 .SetGroupName ("Utils")
167 .HideFromDocumentation ()
168 .AddConstructor<BenchTag<N> > ()
169 ;
170 return tid;
171 }
172 virtual TypeId GetInstanceTypeId (void) const {
173 return GetTypeId ();
174 }
175 virtual uint32_t GetSerializedSize (void) const {
176 return N;
177 }
178 virtual void Serialize (TagBuffer buf) const {
179 for (uint32_t i = 0; i < N; ++i)
180 {
181 buf.WriteU8 (N);
182 }
183 }
184 virtual void Deserialize (TagBuffer buf) {
185 for (uint32_t i = 0; i < N; ++i)
186 {
187 buf.ReadU8 ();
188 }
189 }
190 virtual void Print (std::ostream &os) const {
191 os << "N=" << N;
192 }
194 : Tag () {}
195};
196
197
198static void
200{
201 BenchHeader<25> ipv4;
202 BenchHeader<8> udp;
203 BenchTag<16> tag1;
204 BenchTag<17> tag2;
205
206 for (uint32_t i = 0; i < n; i++) {
207 Ptr<Packet> p = Create<Packet> (2000);
208 p->AddPacketTag (tag1);
209 p->AddHeader (udp);
210 p->RemovePacketTag (tag1);
211 p->AddPacketTag (tag2);
212 p->AddHeader (ipv4);
213 Ptr<Packet> o = p->Copy ();
214 o->RemoveHeader (ipv4);
215 p->RemovePacketTag (tag2);
216 o->RemoveHeader (udp);
217 }
218}
219
220
221
222static void
224{
225 BenchHeader<25> ipv4;
226 BenchHeader<8> udp;
227
228 // The original version of this program did not use BenchHeader::IsOK ()
229 // Below are two asserts that suggest how it can be used.
230 NS_ASSERT_MSG (ipv4.IsOk () == false, "IsOk() should be false before deserialization");
231 for (uint32_t i = 0; i < n; i++) {
232 Ptr<Packet> p = Create<Packet> (2000);
233 p->AddHeader (udp);
234 p->AddHeader (ipv4);
235 Ptr<Packet> o = p->Copy ();
236 o->RemoveHeader (ipv4);
237 o->RemoveHeader (udp);
238 }
239 NS_ASSERT_MSG (ipv4.IsOk () == true, "IsOk() should be true after deserialization");
240}
241
242static void
244{
245 BenchHeader<25> ipv4;
246 BenchHeader<8> udp;
247
248 for (uint32_t i = 0; i < n; i++) {
249 Ptr<Packet> p = Create<Packet> (2000);
250 p->AddHeader (udp);
251 p->AddHeader (ipv4);
252 }
253}
254
255static void
257{
258 BenchHeader<8> udp;
259
260 p->RemoveHeader (udp);
261}
262
263static void
265{
266 BenchHeader<25> ipv4;
267 p->RemoveHeader (ipv4);
268 C2 (p);
269}
270
271static void
273{
274 BenchHeader<25> ipv4;
275 BenchHeader<8> udp;
276
277 for (uint32_t i = 0; i < n; i++) {
278 Ptr<Packet> p = Create<Packet> (2000);
279 p->AddHeader (udp);
280 p->AddHeader (ipv4);
281 C1 (p);
282 }
283}
284
285static void
287{
288 BenchHeader<25> ipv4;
289 BenchHeader<8> udp;
290
291 for (uint32_t i= 0; i < n; i++) {
292 Ptr<Packet> p = Create<Packet> (2000);
293 p->AddHeader (udp);
294 p->AddHeader (ipv4);
295
296 Ptr<Packet> frag0 = p->CreateFragment (0, 250);
297 Ptr<Packet> frag1 = p->CreateFragment (250, 250);
298 Ptr<Packet> frag2 = p->CreateFragment (500, 500);
299 Ptr<Packet> frag3 = p->CreateFragment (1000, 500);
300 Ptr<Packet> frag4 = p->CreateFragment (1500, 500);
301
302 /* Mix fragments in different order */
303 frag2->AddAtEnd (frag3);
304 frag4->AddAtEnd (frag1);
305 frag2->AddAtEnd (frag4);
306 frag0->AddAtEnd (frag2);
307
308 frag0->RemoveHeader (ipv4);
309 frag0->RemoveHeader (udp);
310 }
311}
312
313static void
315{
316 for (uint32_t i = 0; i < n; i++)
317 {
318 Ptr<Packet> p = Create<Packet> (2000);
319 for (uint32_t j = 0; j < 100; j++)
320 {
321 BenchTag<0> tag;
322 p->AddByteTag (tag);
323 }
324 Ptr<Packet> q = Create<Packet> (1000);
325
326 // This should trigger adjustment of all byte tags
327 q->AddAtEnd (p);
328 }
329}
330
331static uint64_t
333{
335 time.Start ();
336 (*bench) (n);
337 uint64_t deltaMs = time.End ();
338 return deltaMs;
339}
340
341
342static void
343runBench (void (*bench) (uint32_t), uint32_t n, uint32_t minIterations, char const *name)
344{
345 uint64_t minDelay = std::numeric_limits<uint64_t>::max();
346 for (uint32_t i = 0; i < minIterations; i++)
347 {
348 uint64_t delay = runBenchOneIteration(bench, n);
349 minDelay = std::min(minDelay, delay);
350 }
351 double ps = n;
352 ps *= 1000;
353 ps /= minDelay;
354 std::cout << ps << " packets/s"
355 << " (" << minDelay << " ms elapsed)\t"
356 << name
357 << std::endl;
358}
359
360int main (int argc, char *argv[])
361{
362 uint32_t n = 0;
363 uint32_t minIterations = 1;
364 bool enablePrinting = false;
365
366 CommandLine cmd (__FILE__);
367 cmd.Usage ("Benchmark Packet class");
368 cmd.AddValue ("n", "number of iterations", n);
369 cmd.AddValue ("min-iterations", "number of subiterations to minimize iteration time over", minIterations);
370 cmd.AddValue ("enable-printing", "enable packet printing", enablePrinting);
371 cmd.Parse (argc, argv);
372
373 if (n == 0)
374 {
375 std::cerr << "Error-- number of packets must be specified " <<
376 "by command-line argument --n=(number of packets)" << std::endl;
377 exit (1);
378 }
379 std::cout << "Running bench-packets with n=" << n << std::endl;
380 std::cout << "All tests begin by adding UDP and IPv4 headers." << std::endl;
381
382 runBench (&benchA, n, minIterations, "Copy packet, remove headers");
383 runBench (&benchB, n, minIterations, "Just add headers");
384 runBench (&benchC, n, minIterations, "Remove by func call");
385 runBench (&benchD, n, minIterations, "Intermixed add/remove headers and tags");
386 runBench (&benchFragment, n, minIterations, "Fragmentation and concatenation");
387 runBench (&benchByteTags, n, minIterations, "Benchmark byte tags");
388
389 return 0;
390}
#define min(a, b)
Definition: 80211b.c:42
#define max(a, b)
Definition: 80211b.c:43
static void benchB(uint32_t n)
static uint64_t runBenchOneIteration(void(*bench)(uint32_t), uint32_t n)
static void benchC(uint32_t n)
static void benchD(uint32_t n)
static void benchFragment(uint32_t n)
static void benchByteTags(uint32_t n)
static void benchA(uint32_t n)
static void runBench(void(*bench)(uint32_t), uint32_t n, uint32_t minIterations, char const *name)
static void C1(Ptr< Packet > p)
static void C2(Ptr< Packet > p)
BenchHeader class used for benchmarking packet serialization/deserialization.
static std::string GetTypeName(void)
Get type name function.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
bool m_ok
variable to track whether deserialization succeeded
virtual void Print(std::ostream &os) const
virtual void Serialize(Buffer::Iterator start) const
virtual uint32_t Deserialize(Buffer::Iterator start)
bool IsOk(void) const
Returns true if the header has been deserialized and the deserialization was correct.
virtual uint32_t GetSerializedSize(void) const
static TypeId GetTypeId(void)
Register this type.
BenchTag class used for benchmarking packet serialization/deserialization.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual void Print(std::ostream &os) const
virtual uint32_t GetSerializedSize(void) const
static std::string GetName(void)
Get the bench tag name.
static TypeId GetTypeId(void)
Register this type.
virtual void Deserialize(TagBuffer buf)
virtual void Serialize(TagBuffer buf) const
iterator in a Buffer instance
Definition: buffer.h:99
Parse command-line arguments.
Definition: command-line.h:229
Protocol header serialization and deserialization.
Definition: header.h:43
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:912
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
Measure elapsed wall clock time in milliseconds.
void Start(void)
Start a measure.
int64_t End(void)
Stop measuring the time since Start() was called.
read and write tag data
Definition: tag-buffer.h:52
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
TAG_BUFFER_INLINE uint8_t ReadU8(void)
Definition: tag-buffer.h:195
tag a set of bytes in a packet
Definition: tag.h:37
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:43
def start()
Definition: core.py:1852