1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2007 University of Washington
4 * Copyright (c) 2013 ResiliNets, ITTC, University of Kansas
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 *
20 * This file incorporates work covered by the following copyright and
21 * permission notice:
22 *
23 * Copyright (c) 1997 Regents of the University of California.
24 * All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. Neither the name of the University nor of the Laboratory may be used
35 * to endorse or promote products derived from this software without
36 * specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 * Contributed by the Daedalus Research Group, UC Berkeley
51 * (http://daedalus.cs.berkeley.edu)
52 *
53 * This code has been ported from ns-2 (queue/errmodel.{cc,h}
54 */
55
56 /* BurstErrorModel additions
57 *
58 * Author: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
59 * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
60 * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
61 */
62
63 #include <cmath>
64
65 #include "error-model.h"
66
67 #include "ns3/packet.h"
68 #include "ns3/assert.h"
69 #include "ns3/log.h"
70 #include "ns3/boolean.h"
71 #include "ns3/enum.h"
72 #include "ns3/double.h"
73 #include "ns3/string.h"
74 #include "ns3/pointer.h"
75
76 namespace ns3 {
77
78 NS_LOG_COMPONENT_DEFINE ("ErrorModel");
79
80 NS_OBJECT_ENSURE_REGISTERED (ErrorModel);
81
GetTypeId(void)82 TypeId ErrorModel::GetTypeId (void)
83 {
84 static TypeId tid = TypeId ("ns3::ErrorModel")
85 .SetParent<Object> ()
86 .SetGroupName("Network")
87 .AddAttribute ("IsEnabled", "Whether this ErrorModel is enabled or not.",
88 BooleanValue (true),
89 MakeBooleanAccessor (&ErrorModel::m_enable),
90 MakeBooleanChecker ())
91 ;
92 return tid;
93 }
94
ErrorModel()95 ErrorModel::ErrorModel () :
96 m_enable (true)
97 {
98 NS_LOG_FUNCTION (this);
99 }
100
~ErrorModel()101 ErrorModel::~ErrorModel ()
102 {
103 NS_LOG_FUNCTION (this);
104 }
105
106 bool
IsCorrupt(Ptr<Packet> p)107 ErrorModel::IsCorrupt (Ptr<Packet> p)
108 {
109 NS_LOG_FUNCTION (this << p);
110 bool result;
111 // Insert any pre-conditions here
112 result = DoCorrupt (p);
113 // Insert any post-conditions here
114 return result;
115 }
116
117 void
Reset(void)118 ErrorModel::Reset (void)
119 {
120 NS_LOG_FUNCTION (this);
121 DoReset ();
122 }
123
124 void
Enable(void)125 ErrorModel::Enable (void)
126 {
127 NS_LOG_FUNCTION (this);
128 m_enable = true;
129 }
130
131 void
Disable(void)132 ErrorModel::Disable (void)
133 {
134 NS_LOG_FUNCTION (this);
135 m_enable = false;
136 }
137
138 bool
IsEnabled(void) const139 ErrorModel::IsEnabled (void) const
140 {
141 NS_LOG_FUNCTION (this);
142 return m_enable;
143 }
144
145 //
146 // RateErrorModel
147 //
148
149 NS_OBJECT_ENSURE_REGISTERED (RateErrorModel);
150
GetTypeId(void)151 TypeId RateErrorModel::GetTypeId (void)
152 {
153 static TypeId tid = TypeId ("ns3::RateErrorModel")
154 .SetParent<ErrorModel> ()
155 .SetGroupName("Network")
156 .AddConstructor<RateErrorModel> ()
157 .AddAttribute ("ErrorUnit", "The error unit",
158 EnumValue (ERROR_UNIT_BYTE),
159 MakeEnumAccessor (&RateErrorModel::m_unit),
160 MakeEnumChecker (ERROR_UNIT_BIT, "ERROR_UNIT_BIT",
161 ERROR_UNIT_BYTE, "ERROR_UNIT_BYTE",
162 ERROR_UNIT_PACKET, "ERROR_UNIT_PACKET"))
163 .AddAttribute ("ErrorRate", "The error rate.",
164 DoubleValue (0.0),
165 MakeDoubleAccessor (&RateErrorModel::m_rate),
166 MakeDoubleChecker<double> ())
167 .AddAttribute ("RanVar", "The decision variable attached to this error model.",
168 StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1.0]"),
169 MakePointerAccessor (&RateErrorModel::m_ranvar),
170 MakePointerChecker<RandomVariableStream> ())
171 ;
172 return tid;
173 }
174
175
RateErrorModel()176 RateErrorModel::RateErrorModel ()
177 {
178 NS_LOG_FUNCTION (this);
179 }
180
~RateErrorModel()181 RateErrorModel::~RateErrorModel ()
182 {
183 NS_LOG_FUNCTION (this);
184 }
185
186 RateErrorModel::ErrorUnit
GetUnit(void) const187 RateErrorModel::GetUnit (void) const
188 {
189 NS_LOG_FUNCTION (this);
190 return m_unit;
191 }
192
193 void
SetUnit(enum ErrorUnit error_unit)194 RateErrorModel::SetUnit (enum ErrorUnit error_unit)
195 {
196 NS_LOG_FUNCTION (this << error_unit);
197 m_unit = error_unit;
198 }
199
200 double
GetRate(void) const201 RateErrorModel::GetRate (void) const
202 {
203 NS_LOG_FUNCTION (this);
204 return m_rate;
205 }
206
207 void
SetRate(double rate)208 RateErrorModel::SetRate (double rate)
209 {
210 NS_LOG_FUNCTION (this << rate);
211 m_rate = rate;
212 }
213
214 void
SetRandomVariable(Ptr<RandomVariableStream> ranvar)215 RateErrorModel::SetRandomVariable (Ptr<RandomVariableStream> ranvar)
216 {
217 NS_LOG_FUNCTION (this << ranvar);
218 m_ranvar = ranvar;
219 }
220
221 int64_t
AssignStreams(int64_t stream)222 RateErrorModel::AssignStreams (int64_t stream)
223 {
224 NS_LOG_FUNCTION (this << stream);
225 m_ranvar->SetStream (stream);
226 return 1;
227 }
228
229 bool
DoCorrupt(Ptr<Packet> p)230 RateErrorModel::DoCorrupt (Ptr<Packet> p)
231 {
232 NS_LOG_FUNCTION (this << p);
233 if (!IsEnabled ())
234 {
235 return false;
236 }
237 switch (m_unit)
238 {
239 case ERROR_UNIT_PACKET:
240 return DoCorruptPkt (p);
241 case ERROR_UNIT_BYTE:
242 return DoCorruptByte (p);
243 case ERROR_UNIT_BIT:
244 return DoCorruptBit (p);
245 default:
246 NS_ASSERT_MSG (false, "m_unit not supported yet");
247 break;
248 }
249 return false;
250 }
251
252 bool
DoCorruptPkt(Ptr<Packet> p)253 RateErrorModel::DoCorruptPkt (Ptr<Packet> p)
254 {
255 NS_LOG_FUNCTION (this << p);
256 return (m_ranvar->GetValue () < m_rate);
257 }
258
259 bool
DoCorruptByte(Ptr<Packet> p)260 RateErrorModel::DoCorruptByte (Ptr<Packet> p)
261 {
262 NS_LOG_FUNCTION (this << p);
263 // compute pkt error rate, assume uniformly distributed byte error
264 double per = 1 - std::pow (1.0 - m_rate, static_cast<double> (p->GetSize ()));
265 return (m_ranvar->GetValue () < per);
266 }
267
268 bool
DoCorruptBit(Ptr<Packet> p)269 RateErrorModel::DoCorruptBit (Ptr<Packet> p)
270 {
271 NS_LOG_FUNCTION (this << p);
272 // compute pkt error rate, assume uniformly distributed bit error
273 double per = 1 - std::pow (1.0 - m_rate, static_cast<double> (8 * p->GetSize ()) );
274 return (m_ranvar->GetValue () < per);
275 }
276
277 void
DoReset(void)278 RateErrorModel::DoReset (void)
279 {
280 NS_LOG_FUNCTION (this);
281 /* re-initialize any state; no-op for now */
282 }
283
284
285 //
286 // BurstErrorModel
287 //
288
289 NS_OBJECT_ENSURE_REGISTERED (BurstErrorModel);
290
GetTypeId(void)291 TypeId BurstErrorModel::GetTypeId (void)
292 {
293 static TypeId tid = TypeId ("ns3::BurstErrorModel")
294 .SetParent<ErrorModel> ()
295 .SetGroupName("Network")
296 .AddConstructor<BurstErrorModel> ()
297 .AddAttribute ("ErrorRate", "The burst error event.",
298 DoubleValue (0.0),
299 MakeDoubleAccessor (&BurstErrorModel::m_burstRate),
300 MakeDoubleChecker<double> ())
301 .AddAttribute ("BurstStart", "The decision variable attached to this error model.",
302 StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1.0]"),
303 MakePointerAccessor (&BurstErrorModel::m_burstStart),
304 MakePointerChecker<RandomVariableStream> ())
305 .AddAttribute ("BurstSize", "The number of packets being corrupted at one drop.",
306 StringValue ("ns3::UniformRandomVariable[Min=1|Max=4]"),
307 MakePointerAccessor (&BurstErrorModel::m_burstSize),
308 MakePointerChecker<RandomVariableStream> ())
309 ;
310 return tid;
311 }
312
313
BurstErrorModel()314 BurstErrorModel::BurstErrorModel () : m_counter (0), m_currentBurstSz (0)
315 {
316
317 }
318
~BurstErrorModel()319 BurstErrorModel::~BurstErrorModel ()
320 {
321 NS_LOG_FUNCTION (this);
322 }
323
324 double
GetBurstRate(void) const325 BurstErrorModel::GetBurstRate (void) const
326 {
327 NS_LOG_FUNCTION (this);
328 return m_burstRate;
329 }
330
331 void
SetBurstRate(double rate)332 BurstErrorModel::SetBurstRate (double rate)
333 {
334 NS_LOG_FUNCTION (this << rate);
335 m_burstRate = rate;
336 }
337
338 void
SetRandomVariable(Ptr<RandomVariableStream> ranVar)339 BurstErrorModel::SetRandomVariable (Ptr<RandomVariableStream> ranVar)
340 {
341 NS_LOG_FUNCTION (this << ranVar);
342 m_burstStart = ranVar;
343 }
344
345 void
SetRandomBurstSize(Ptr<RandomVariableStream> burstSz)346 BurstErrorModel::SetRandomBurstSize(Ptr<RandomVariableStream> burstSz)
347 {
348 NS_LOG_FUNCTION (this << burstSz);
349 m_burstSize = burstSz;
350 }
351
352 int64_t
AssignStreams(int64_t stream)353 BurstErrorModel::AssignStreams (int64_t stream)
354 {
355 NS_LOG_FUNCTION (this << stream);
356 m_burstStart->SetStream (stream);
357 m_burstSize->SetStream(stream);
358 return 2;
359 }
360
361 bool
DoCorrupt(Ptr<Packet> p)362 BurstErrorModel::DoCorrupt (Ptr<Packet> p)
363 {
364 NS_LOG_FUNCTION (this);
365 if (!IsEnabled ())
366 {
367 return false;
368 }
369 double ranVar = m_burstStart ->GetValue();
370
371 if (ranVar < m_burstRate)
372 {
373 // get a new burst size for the new error event
374 m_currentBurstSz = m_burstSize->GetInteger();
375 NS_LOG_DEBUG ("new burst size selected: " << m_currentBurstSz);
376 if (m_currentBurstSz == 0)
377 {
378 NS_LOG_WARN ("Burst size == 0; shouldn't happen");
379 return false;
380 }
381 m_counter = 1; // start counting dropped packets
382 return true; // drop this packet
383 }
384 else
385 {
386 // not a burst error event
387 if (m_counter < m_currentBurstSz)
388 {
389 // check to see if all the packets (determined by the last
390 // generated m_currentBurstSz) have been dropped.
391 // If not, drop 1 more packet
392 m_counter++;
393 return true;
394 }
395 else
396 {
397 // all packets in the last error event have been dropped
398 // and there is no new error event, so do not drop the packet
399 return false; // no error event
400 }
401 }
402 }
403
404 void
DoReset(void)405 BurstErrorModel::DoReset (void)
406 {
407 NS_LOG_FUNCTION (this);
408 m_counter = 0;
409 m_currentBurstSz = 0;
410
411 }
412
413
414 //
415 // ListErrorModel
416 //
417
418 NS_OBJECT_ENSURE_REGISTERED (ListErrorModel);
419
GetTypeId(void)420 TypeId ListErrorModel::GetTypeId (void)
421 {
422 static TypeId tid = TypeId ("ns3::ListErrorModel")
423 .SetParent<ErrorModel> ()
424 .SetGroupName("Network")
425 .AddConstructor<ListErrorModel> ()
426 ;
427 return tid;
428 }
429
ListErrorModel()430 ListErrorModel::ListErrorModel ()
431 {
432 NS_LOG_FUNCTION (this);
433 }
434
~ListErrorModel()435 ListErrorModel::~ListErrorModel ()
436 {
437 NS_LOG_FUNCTION (this);
438 }
439
440 std::list<uint32_t>
GetList(void) const441 ListErrorModel::GetList (void) const
442 {
443 NS_LOG_FUNCTION (this);
444 return m_packetList;
445 }
446
447 void
SetList(const std::list<uint32_t> & packetlist)448 ListErrorModel::SetList (const std::list<uint32_t> &packetlist)
449 {
450 NS_LOG_FUNCTION (this << &packetlist);
451 m_packetList = packetlist;
452 }
453
454 // When performance becomes a concern, the list provided could be
455 // converted to a dynamically-sized array of uint32_t to avoid
456 // list iteration below.
457 bool
DoCorrupt(Ptr<Packet> p)458 ListErrorModel::DoCorrupt (Ptr<Packet> p)
459 {
460 NS_LOG_FUNCTION (this << p);
461 if (!IsEnabled ())
462 {
463 return false;
464 }
465 uint32_t uid = p->GetUid ();
466 for (PacketListCI i = m_packetList.begin ();
467 i != m_packetList.end (); i++)
468 {
469 if (uid == *i)
470 {
471 return true;
472 }
473 }
474 return false;
475 }
476
477 void
DoReset(void)478 ListErrorModel::DoReset (void)
479 {
480 NS_LOG_FUNCTION (this);
481 m_packetList.clear ();
482 }
483
484 //
485 // ReceiveListErrorModel
486 //
487
488 NS_OBJECT_ENSURE_REGISTERED (ReceiveListErrorModel);
489
GetTypeId(void)490 TypeId ReceiveListErrorModel::GetTypeId (void)
491 {
492 static TypeId tid = TypeId ("ns3::ReceiveListErrorModel")
493 .SetParent<ErrorModel> ()
494 .SetGroupName("Network")
495 .AddConstructor<ReceiveListErrorModel> ()
496 ;
497 return tid;
498 }
499
500
ReceiveListErrorModel()501 ReceiveListErrorModel::ReceiveListErrorModel () :
502 m_timesInvoked (0)
503 {
504 NS_LOG_FUNCTION (this);
505 }
506
~ReceiveListErrorModel()507 ReceiveListErrorModel::~ReceiveListErrorModel ()
508 {
509 NS_LOG_FUNCTION (this);
510 }
511
512 std::list<uint32_t>
GetList(void) const513 ReceiveListErrorModel::GetList (void) const
514 {
515 NS_LOG_FUNCTION (this);
516 return m_packetList;
517 }
518
519 void
SetList(const std::list<uint32_t> & packetlist)520 ReceiveListErrorModel::SetList (const std::list<uint32_t> &packetlist)
521 {
522 NS_LOG_FUNCTION (this << &packetlist);
523 m_packetList = packetlist;
524 }
525
526 bool
DoCorrupt(Ptr<Packet> p)527 ReceiveListErrorModel::DoCorrupt (Ptr<Packet> p)
528 {
529 NS_LOG_FUNCTION (this << p);
530 if (!IsEnabled ())
531 {
532 return false;
533 }
534 m_timesInvoked += 1;
535 for (PacketListCI i = m_packetList.begin ();
536 i != m_packetList.end (); i++)
537 {
538 if (m_timesInvoked - 1 == *i)
539 {
540 return true;
541 }
542 }
543 return false;
544 }
545
546 void
DoReset(void)547 ReceiveListErrorModel::DoReset (void)
548 {
549 NS_LOG_FUNCTION (this);
550 m_packetList.clear ();
551 }
552
553
554 NS_OBJECT_ENSURE_REGISTERED (BinaryErrorModel);
555
GetTypeId(void)556 TypeId BinaryErrorModel::GetTypeId (void)
557 {
558 static TypeId tid = TypeId ("ns3::BinaryErrorModel")
559 .SetParent<ErrorModel> ()
560 .AddConstructor<BinaryErrorModel> ()
561 ;
562 return tid;
563 }
564
BinaryErrorModel()565 BinaryErrorModel::BinaryErrorModel ()
566 {
567 NS_LOG_FUNCTION (this);
568 m_counter = 0;
569 }
570
~BinaryErrorModel()571 BinaryErrorModel::~BinaryErrorModel ()
572 {
573 NS_LOG_FUNCTION (this);
574 }
575
576 bool
DoCorrupt(Ptr<Packet> p)577 BinaryErrorModel::DoCorrupt (Ptr<Packet> p)
578 {
579 NS_LOG_FUNCTION (this);
580 if (!IsEnabled ())
581 {
582 return false;
583 }
584 bool ret = m_counter%2;
585 m_counter++;
586 return ret;
587 }
588
589 void
DoReset(void)590 BinaryErrorModel::DoReset (void)
591 {
592 NS_LOG_FUNCTION (this);
593 m_counter = 0;
594 }
595
596
597
598
599 } // namespace ns3
600
601