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