DESERT 3.5.1
Loading...
Searching...
No Matches
uwvbr-module.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2017 Regents of the SIGNET lab, University of Padova.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions
7// are met:
8// 1. Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution.
13// 3. Neither the name of the University of Padova (SIGNET lab) nor the
14// names of its contributors may be used to endorse or promote products
15// derived from this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29
40#include "uwvbr-module.h"
41
42#include <iostream>
43#include <rng.h>
44
45extern packet_t PT_UWVBR;
46
53static class UwVbrPktClass : public PacketHeaderClass
54{
55public:
57 : PacketHeaderClass("PacketHeader/UWVBR", sizeof(hdr_uwvbr))
58 {
59 this->bind();
60 bind_offset(&hdr_uwvbr::offset_);
61 }
63
67static class UwVbrModuleClass : public TclClass
68{
69public:
71 : TclClass("Module/UW/VBR")
72 {
73 }
74
75 TclObject *
76 create(int, const char *const *)
77 {
78 return (new UwVbrModule());
79 }
81
82void
84{
85 module->transmit();
86}
87
88void
90{
91 module->switchPeriod();
92}
93
94int UwVbrModule::uidcnt_ = 0; // unique id of the packet generated
95
97 : dstPort_(0)
98 , dstAddr_(0)
99 , PoissonTraffic_(0)
100 , debug_(0)
101 , txsn(1)
102 , hrsn(0)
103 , pkts_recv(0)
104 , pkts_ooseq(0)
105 , pkts_lost(0)
106 , pkts_invalid(0)
107 , pkts_last_reset(0)
108 , rftt(-1)
109 , srtt(0)
110 , sftt(0)
111 , lrtime(0)
112 , sthr(0)
113 , drop_out_of_order_(0)
114 , period_identifier_(1)
115 , timer_switch_1_(1000)
116 , timer_switch_2_(500)
117 , sendTmr_(this)
118 , period_switcher_(this)
119 , pktSize_(0)
120 , sumrtt(0)
121 , sumrtt2(0)
122 , rttsamples(0)
123 , sumftt(0)
124 , sumftt2(0)
125 , fttsamples(0)
126 , sumbytes(0)
127 , sumdt(0)
128 , esn(0)
129{ // binding to TCL variables
130 bind("period1_", &period1_);
131 bind("period2_", &period2_);
132 bind("timer_switch_1_", &timer_switch_1_);
133 bind("timer_switch_2_", &timer_switch_2_);
134 bind("destPort_", (int *) &dstPort_);
135 bind("destAddr_", (int *) &dstAddr_);
136 bind("packetSize_", &pktSize_);
137 bind("PoissonTraffic_", &PoissonTraffic_);
138 bind("debug_", &debug_);
139 bind("drop_out_of_order_", &drop_out_of_order_);
140 sn_check = new bool[USHRT_MAX];
141 for (int i = 0; i < USHRT_MAX; i++) {
142 sn_check[i] = false;
143 }
144}
145
149
150// TCL command interpreter
151
152int
153UwVbrModule::command(int argc, const char *const *argv)
154{
155 Tcl &tcl = Tcl::instance();
156 if (argc == 2) {
157 if (strcasecmp(argv[1], "start") == 0) { // TCL command to start the
158 // packet generation and
159 // transmission
160 start();
161 return TCL_OK;
162 } else if (strcasecmp(argv[1], "stop") ==
163 0) { // TCL command to stop the packet generation
164 stop();
165 return TCL_OK;
166 } else if (strcasecmp(argv[1], "getrtt") == 0) {
167 tcl.resultf("%f", GetRTT());
168 return TCL_OK;
169 } else if (strcasecmp(argv[1], "getftt") == 0) {
170 tcl.resultf("%f", GetFTT());
171 return TCL_OK;
172 } else if (strcasecmp(argv[1], "getper") == 0) {
173 tcl.resultf("%f", GetPER());
174 return TCL_OK;
175 } else if (strcasecmp(argv[1], "getthr") == 0) {
176 tcl.resultf("%f", GetTHR());
177 return TCL_OK;
178 } else if (strcasecmp(argv[1], "getvbrheadersize") == 0) {
179 tcl.resultf("%d", this->getVbrHeaderSize());
180 return TCL_OK;
181 } else if (strcasecmp(argv[1], "getrttstd") == 0) {
182 tcl.resultf("%f", GetRTTstd());
183 return TCL_OK;
184 } else if (strcasecmp(argv[1], "getfttstd") == 0) {
185 tcl.resultf("%f", GetFTTstd());
186 return TCL_OK;
187 } else if (strcasecmp(argv[1], "getsentpkts") == 0) {
188 tcl.resultf("%d", txsn - 1);
189 return TCL_OK;
190 } else if (strcasecmp(argv[1], "getrecvpkts") == 0) {
191 tcl.resultf("%d", pkts_recv);
192 return TCL_OK;
193 } else if (strcasecmp(argv[1], "sendPkt") == 0) {
194 sendPkt();
195 return TCL_OK;
196 } else if (strcasecmp(argv[1], "resetStats") == 0) {
197 resetStats();
198 fprintf(stderr,
199 "VbrModule::command() resetStats %s, pkts_last_reset=%d, "
200 "hrsn=%d, txsn=%d\n",
201 tag_,
203 hrsn,
204 txsn);
205 return TCL_OK;
206 }
207 }
208 return Module::command(argc, argv);
209}
210
211int
213{
214 switch (m->type()) {
215 default:
216 return Module::crLayCommand(m);
217 }
218}
219
220void
222{
223 hdr_cmn *ch = hdr_cmn::access(p);
224 ch->uid() = uidcnt_++;
225 ch->ptype() = PT_UWVBR;
226 ch->size() = pktSize_;
227
228 hdr_uwip *uwiph = hdr_uwip::access(p);
229 uwiph->daddr() = dstAddr_;
230
231 hdr_uwudp *uwudp = hdr_uwudp::access(p);
232 uwudp->dport() = dstPort_;
233
234 hdr_uwvbr *uwvbrh = HDR_UWVBR(p);
235 uwvbrh->sn() = txsn++;
236 ch->timestamp() = Scheduler::instance().clock();
237
238 if (rftt >= 0) {
239 uwvbrh->rftt() = rftt;
240 uwvbrh->rftt_valid() = true;
241 } else {
242 uwvbrh->rftt_valid() = false;
243 }
244}
245
246void
252
253void
255{
256 double delay = 0;
257 Packet *p = Packet::alloc();
258 initPkt(p);
259 hdr_cmn *ch = hdr_cmn::access(p);
260 hdr_uwvbr *uwvbrh = HDR_UWVBR(p);
261 if (debug_ > 10)
262 printf("VbrModule(%d)::sendPkt, send a pkt (%d) with sn: %d\n",
263 getId(),
264 ch->uid(),
265 uwvbrh->sn());
266 sendDown(p, delay);
267}
268
269void
271{
272 sendPkt();
273 // Schedule next transmission.
275}
276
277void
279{
280 if (period_identifier_ == 1) {
283 } else {
286 }
287}
288
289void
291{
292 sendTmr_.force_cancel();
293}
294
295void
296UwVbrModule::recv(Packet *p, Handler *h)
297{
298 recv(p);
299}
300
301void
303{
304 hdr_cmn *ch = hdr_cmn::access(p);
305 if (debug_ > 10)
306 printf("VbrModule(%d)::recv(Packet*p,Handler*) pktId %d\n",
307 getId(),
308 ch->uid());
309
310 if (ch->ptype() != PT_UWVBR) {
313 return;
314 }
315
316 hdr_uwvbr *uwvbrh = HDR_UWVBR(p);
317
318 esn = hrsn + 1; // expected sn
319
320 if (!drop_out_of_order_) {
321 if (sn_check[uwvbrh->sn()]) { // Packet already processed: drop it
324 return;
325 }
326 }
327
328 sn_check[uwvbrh->sn()] = true;
329
330 if (drop_out_of_order_) {
331 if (uwvbrh->sn() <
332 esn) { // packet is out of sequence and is to be discarded
333 incrPktOoseq();
334 if (debug_ > 1) {
335 printf("VbrModule::recv() Pkt out of sequence! "
336 "vbrh->sn=%d\thrsn=%d\tesn=%d\n",
337 uwvbrh->sn(),
338 hrsn,
339 esn);
340 }
342 return;
343 }
344 }
345
346 rftt = Scheduler::instance().clock() - ch->timestamp();
347
348 if (uwvbrh->rftt_valid()) {
349 double rtt = rftt + uwvbrh->rftt();
350 updateRTT(rtt);
351 }
352
354
355 /* a new packet has been received */
356 incrPktRecv();
357
358 hrsn = uwvbrh->sn();
359 if (drop_out_of_order_) {
360 if (uwvbrh->sn() > esn) { // packet losses are observed
361 incrPktLost(uwvbrh->sn() - (esn));
362 }
363 }
364
365 double dt = Scheduler::instance().clock() - lrtime;
366 updateThroughput(ch->size(), dt);
367
368 lrtime = Scheduler::instance().clock();
369
370 Packet::free(p);
371
372 if (drop_out_of_order_) {
374 fprintf(stderr,
375 "ERROR VbrModule::recv() pkts_lost=%d pkts_recv=%d "
376 "hrsn=%d\n",
377 pkts_lost,
378 pkts_recv,
379 hrsn);
380 }
381 }
382}
383
384double
386{
387 return (rttsamples > 0) ? sumrtt / rttsamples : 0;
388}
389
390double
392{
393 return (fttsamples > 0) ? sumftt / fttsamples : 0;
394}
395
396double
398{
399 if (rttsamples > 1) {
400 double var =
401 (sumrtt2 - (sumrtt * sumrtt / rttsamples)) / (rttsamples - 1);
402 return (sqrt(var));
403 } else {
404 return 0;
405 }
406}
407
408double
410{
411 if (fttsamples > 1) {
412 double var;
413 var = (sumftt2 - (sumftt * sumftt / fttsamples)) / (fttsamples - 1);
414 if (var > 0) {
415 return (sqrt(var));
416 } else {
417 return 0;
418 }
419 } else {
420 return 0;
421 }
422}
423
424double
426{
427 if (drop_out_of_order_) {
428 if ((pkts_recv + pkts_lost) > 0) {
429 return ((double) pkts_lost / (double) (pkts_recv + pkts_lost));
430 } else {
431 return 0;
432 }
433 } else {
434 if (esn > 1)
435 return (1 - (double) pkts_recv / (double) (esn - 1));
436 else
437 return 0;
438 }
439}
440
441double
443{
444 return ((sumdt != 0) ? sumbytes * 8 / sumdt : 0);
445}
446
447void
448UwVbrModule::updateRTT(const double &rtt)
449{
450 sumrtt += rtt;
451 sumrtt2 += rtt * rtt;
452 rttsamples++;
453}
454
455void
456UwVbrModule::updateFTT(const double &ftt)
457{
458 sumftt += ftt;
459 sumftt2 += ftt * ftt;
460 fttsamples++;
461}
462
463void
464UwVbrModule::updateThroughput(const int &bytes, const double &dt)
465{
466 sumbytes += bytes;
467 sumdt += dt;
468
469 if (debug_ > 1) {
470 cerr << "bytes=" << bytes << " dt=" << dt << endl;
471 }
472}
473
474void
476{
477 pkts_lost += npkts;
478}
479
480void
485
486void
491
492void
497
498void
500{
502 pkts_recv = 0;
503 pkts_ooseq = 0;
504 pkts_lost = 0;
505 srtt = 0;
506 sftt = 0;
507 sthr = 0;
508 rftt = -1;
509 sumrtt = 0;
510 sumrtt2 = 0;
511 rttsamples = 0;
512 sumftt = 0;
513 sumftt2 = 0;
514 fttsamples = 0;
515 sumbytes = 0;
516 sumdt = 0;
517}
518
519double
521{
522 double period_;
523 if (period1_ < 0 || period2_ < 0) {
524 fprintf(stderr, "%s : Error : period <= 0", __PRETTY_FUNCTION__);
525 exit(1);
526 }
527
528 if (period_identifier_ == 1) {
529 period_ = period1_;
530 } else {
531 period_ = period2_;
532 }
533
534 if (PoissonTraffic_) {
535 double u = RNG::defaultrng()->uniform_double();
536 double lambda = 1 / period_;
537 return (-log(u) / lambda);
538 } else {
539 // VBR
540 return period_;
541 }
542}
Adds the module for UwVbrModuleClass in ns2.
TclObject * create(int, const char *const *)
UwVbrModule class is used to manage UWVBR packets, and to collect statistics about them.
int debug_
Flag to enable or disable dirrefent levels of debug.
nsaddr_t dstAddr_
IP of the destination.
double sumftt2
Sum of (FTT^2).
double timer_switch_2_
Period in witch the node tramsmits with a packet every period2_ seconds.
virtual double getTimeBeforeNextPkt()
Returns the amount of time to wait before the next transmission.
double sumbytes
Sum of bytes received.
double rftt
Forward Trip Time seen for last received packet.
int pkts_invalid
Total number of invalid packets received.
double sumdt
Sum of the delays.
int rttsamples
Number of RTT samples.
virtual double GetPER() const
Returns the mean Packet Error Rate.
virtual double GetRTTstd() const
Returns the Round Trip Time Standard Deviation.
int fttsamples
Number of FTT samples.
virtual void start()
Start to send packets.
virtual double GetRTT() const
Returns the mean Round Trip Time.
int PoissonTraffic_
1 if the traffic is generated according to a poissonian distribution.
virtual void initPkt(Packet *p)
Initializes a data packet passed as argument with the default values.
virtual double GetFTTstd() const
Returns the mean Forward Trip Time Standard Deviation.
int pkts_last_reset
for error checking after stats are reset.
double srtt
Smoothed Round Trip Time, calculated as for TCP.
virtual int crLayCommand(ClMessage *m)
bool * sn_check
Used to keep track of the packets already received.
double sumrtt2
Sum of (RTT^2).
virtual double GetTHR() const
Returns the mean Throughput.
int drop_out_of_order_
Flag to enable or disable the check for out of order packets.
UwVbrPeriodSwitcher period_switcher_
Timer which schedules the switch between different sending periods.
double period2_
period between two consecutive packet transmissions (mode 2).
u_int16_t dstPort_
Destination port.
uint32_t esn
Expected serial number.
static int uidcnt_
Unique id of the packet generated.
static const int getVbrHeaderSize()
Returns the size in byte of a hdr_uwvbr packet header.
int pktSize_
Packet size.
virtual void updateThroughput(const int &, const double &)
Updates the Throughput.
double sumftt
Sum of FTT samples.
int pkts_ooseq
Total number of packets received out of sequence.
virtual void stop()
Stop to send packets.
UwVbrSendTimer sendTmr_
Timer which schedules packet transmissions.
double timer_switch_1_
Period in witch the node tramsmits with a packet every period1_ seconds.
virtual void incrPktLost(const int &)
Increases the number of packets lost.
virtual void updateRTT(const double &)
Updates the Round Trip Time.
double sumrtt
Sum of RTT samples.
UwVbrModule()
Constructor of UwVbrModule class.
virtual void incrPktInvalid()
Increases by one the number of invalid packets.
virtual void incrPktOoseq()
Increases by one the number of out of sequence packets received.
int pkts_recv
Total number of received packets.
int period_identifier_
Flag used to identify in which one of the period the vbr module is.
int txsn
Sequence number of next new packet to be transmitted.
virtual void updateFTT(const double &)
Updates the Forward Trip Time.
double period1_
period between two consecutive packet transmissions (mode 1).
virtual void sendPkt()
Allocates, initialize and sends a packet.
virtual void incrPktRecv()
Increases by one the number of received packets.
virtual double GetFTT() const
Returns the mean Forward Trip Time.
double sftt
Smoothed Forward Trip Time, calculated as srtt.
double sthr
Smoothed throughput calculation.
int pkts_lost
Total number of lost packets, including packets received out of sequence.
int hrsn
Highest received sequence number.
virtual int command(int argc, const char *const *argv)
TCL command interpreter.
virtual void recv(Packet *)
Performs the reception of packets from upper and lower layers.
virtual void resetStats()
Resets all the statistics of the UWVBR module.
virtual void transmit()
Creates and transmits a packet and schedules a new transmission.
virtual ~UwVbrModule()
Destructor of UwVbrModule class.
double lrtime
Time of last packet reception.
virtual void switchPeriod()
Switches between the two different states in which UWVBR can operate.
virtual void expire(Event *e)
Adds the header for hdr_uwvbr packets in ns2.
virtual void expire(Event *e)
hdr_uwip describes UWIP packets.
Definition uwip-module.h:70
uint8_t & daddr()
Reference to the daddr_ variable.
static hdr_uwip * access(const Packet *p)
Definition uwip-module.h:86
hdr_uwudp describes UWUDP packets.
static struct hdr_uwudp * access(const Packet *p)
uint8_t & dport()
Reference to the dport_ variable.
hdr_uwvbr describes UWVBR packets.
float & rftt()
Reference to the rftt_ variable.
bool & rftt_valid()
Reference to the rftt_valid_ variable.
u_int16_t & sn()
Reference to the sn_ variable.
static int offset_
Required by the PacketHeaderManager.
UwVbrModuleClass class_module_uwvbr
UwVbrPktClass class_uwvbr_pkt
Provides the UWVBR packets header description and the definition of the class UWVBR.
#define UWVBR_DROP_REASON_OUT_OF_SEQUENCE
Reason for a drop in a UWVBR module.
#define UWVBR_DROP_REASON_DUPLICATED_PACKET
Reason for a drop in a UWVBR module.
#define UWVBR_DROP_REASON_UNKNOWN_TYPE
Reason for a drop in a UWVBR module.
#define HDR_UWVBR(P)