DESERT 3.6.0
Loading...
Searching...
No Matches
uwcbr-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 "uwcbr-module.h"
41
42#include <iostream>
43#include <rng.h>
44#include <stdint.h>
45#include <string>
46
47extern packet_t PT_UWCBR;
48
55static class UwCbrPktClass : public PacketHeaderClass
56{
57public:
59 : PacketHeaderClass("PacketHeader/UWCBR", sizeof(hdr_uwcbr))
60 {
61 this->bind();
62 bind_offset(&hdr_uwcbr::offset_);
63 }
65
69static class UwCbrModuleClass : public TclClass
70{
71public:
73 : TclClass("Module/UW/CBR")
74 {
75 }
76
77 TclObject *
78 create(int, const char *const *)
79 {
80 return (new UwCbrModule());
81 }
83
84void
86{
87 module->transmit();
88}
89
91
93 : dstPort_(0)
94 , log_suffix("")
95 , dstAddr_(0)
96 , priority_(0)
97 , PoissonTraffic_(0)
98 , debug_(0)
99 , drop_out_of_order_(0)
100 , traffic_type_(0)
101 , sendTmr_(this)
102 , txsn(1)
103 , hrsn(0)
104 , pkts_recv(0)
105 , pkts_ooseq(0)
106 , pkts_lost(0)
107 , pkts_invalid(0)
108 , pkts_last_reset(0)
109 , cnt(0)
110 , rftt(-1)
111 , srtt(0)
112 , sftt(0)
113 , lrtime(0)
114 , sthr(0)
115 , period_(0)
116 , pktSize_(0)
117 , sumrtt(0)
118 , sumrtt2(0)
119 , rttsamples(0)
120 , sumftt(0)
121 , sumftt2(0)
122 , fttsamples(0)
123 , sumbytes(0)
124 , sumdt(0)
125 , esn(0)
126 , tracefile_enabler_(0)
127{ // binding to TCL variables
128 bind("period_", &period_);
129 bind("destPort_", (int *) &dstPort_);
130 bind("destAddr_", (int *) &dstAddr_);
131 bind("packetSize_", &pktSize_);
132 bind("PoissonTraffic_", &PoissonTraffic_);
133 bind("debug_", &debug_);
134 bind("drop_out_of_order_", &drop_out_of_order_);
135 bind("traffic_type_", (uint *) &traffic_type_);
136 bind("tracefile_enabler_", (int *) &tracefile_enabler_);
137 sn_check = new bool[USHRT_MAX];
138 for (int i = 0; i < USHRT_MAX; i++) {
139 sn_check[i] = false;
140 }
141}
142
143int
144UwCbrModule::command(int argc, const char *const *argv)
145{
146 Tcl &tcl = Tcl::instance();
147 if (argc == 2) {
148 if (strcasecmp(argv[1], "start") == 0) {
149 start();
150 return TCL_OK;
151 } else if (strcasecmp(argv[1], "stop") == 0) {
152 stop();
153 return TCL_OK;
154 } else if (strcasecmp(argv[1], "getrtt") == 0) {
155 tcl.resultf("%f", GetRTT());
156 return TCL_OK;
157 } else if (strcasecmp(argv[1], "getftt") == 0) {
158 tcl.resultf("%f", GetFTT());
159 return TCL_OK;
160 } else if (strcasecmp(argv[1], "gettxtime") == 0) {
161 tcl.resultf("%f", GetTxTime());
162 return TCL_OK;
163 } else if (strcasecmp(argv[1], "getper") == 0) {
164 tcl.resultf("%f", GetPER());
165 return TCL_OK;
166 } else if (strcasecmp(argv[1], "getthr") == 0) {
167 tcl.resultf("%f", GetTHR());
168 return TCL_OK;
169 } else if (strcasecmp(argv[1], "getcbrheadersize") == 0) {
170 tcl.resultf("%d", this->getCbrHeaderSize());
171 return TCL_OK;
172 } else if (strcasecmp(argv[1], "getrttstd") == 0) {
173 tcl.resultf("%f", GetRTTstd());
174 return TCL_OK;
175 } else if (strcasecmp(argv[1], "getfttstd") == 0) {
176 tcl.resultf("%f", GetFTTstd());
177 return TCL_OK;
178 } else if (strcasecmp(argv[1], "getsentpkts") == 0) {
179 tcl.resultf("%d", txsn - 1);
180 return TCL_OK;
181 } else if (strcasecmp(argv[1], "getrecvpkts") == 0) {
182 tcl.resultf("%d", pkts_recv);
183 return TCL_OK;
184 } else if (strcasecmp(argv[1], "setprioritylow") == 0) {
185 priority_ = 0;
186 return TCL_OK;
187 } else if (strcasecmp(argv[1], "setpriorityhigh") == 0) {
188 priority_ = 1;
189 return TCL_OK;
190 } else if (strcasecmp(argv[1], "sendPkt") == 0) {
191 this->sendPkt();
192 return TCL_OK;
193 } else if (strcasecmp(argv[1], "sendPktLowPriority") == 0) {
194 this->sendPktLowPriority();
195 return TCL_OK;
196 } else if (strcasecmp(argv[1], "sendPktHighPriority") == 0) {
197 this->sendPktHighPriority();
198 return TCL_OK;
199 } else if (strcasecmp(argv[1], "resetStats") == 0) {
200 resetStats();
201 tcl.resultf(
202 "CbrModule::command() resetStats %s, pkts_last_reset=%d, "
203 "hrsn=%d, txsn=%d\n",
204 tag_,
206 hrsn,
207 txsn);
208 return TCL_OK;
209 } else if (strcasecmp(argv[1], "printidspkts") == 0) {
210 this->printIdsPkts();
211 return TCL_OK;
212 }
213 } else if (argc == 3) {
214 if (strcasecmp(argv[1], "setLogSuffix") == 0) {
215 string tmp_ = (char *) argv[2];
216 log_suffix = std::string(tmp_);
217 tracefilename = "tracefile" + log_suffix + ".txt";
218 if (tracefile_enabler_) {
219 tracefile.open(tracefilename.c_str(),
220 std::ios_base::out | std::ios_base::app);
221 }
222 return TCL_OK;
223 }
224 } else if (argc == 4) {
225 if (strcasecmp(argv[1], "setLogSuffix") == 0) {
226 string tmp_ = (char *) argv[2];
227 int precision = std::atoi(argv[3]);
228 log_suffix = std::string(tmp_);
229 tracefilename = "tracefile" + log_suffix + ".txt";
230 if (tracefile_enabler_) {
231 tracefile.open(tracefilename.c_str(),
232 std::ios_base::out | std::ios_base::app);
233 tracefile.precision(precision);
234 }
235
236 return TCL_OK;
237 }
238 }
239
240 return Module::command(argc, argv);
241}
242
243void
245{
246 hdr_cmn *ch = hdr_cmn::access(p);
247 ch->uid() = uidcnt_++;
248 ch->ptype() = PT_UWCBR;
249 ch->size() = pktSize_;
250
251 hdr_uwip *uwiph = hdr_uwip::access(p);
252 uwiph->daddr() = dstAddr_;
253
254 hdr_uwudp *uwudp = hdr_uwudp::access(p);
255 uwudp->dport() = dstPort_;
256
257 hdr_uwcbr *uwcbrh = HDR_UWCBR(p);
258 uwcbrh->sn() = txsn++;
259 uwcbrh->priority() = priority_;
260 uwcbrh->traffic_type() = traffic_type_;
261 ch->timestamp() = Scheduler::instance().clock();
262
263 if (rftt >= 0) {
264 uwcbrh->rftt() = rftt;
265 uwcbrh->rftt_valid() = true;
266 } else {
267 uwcbrh->rftt_valid() = false;
268 }
269}
270
271void
276
277void
279{
280 double delay = 0;
281 Packet *p = Packet::alloc();
282 this->initPkt(p);
283 hdr_cmn *ch = hdr_cmn::access(p);
284 hdr_uwcbr *uwcbrh = HDR_UWCBR(p);
285
286 printOnLog(Logger::LogLevel::DEBUG,
287 "UWCBR",
288 "sendPkt()::send a packet (" + to_string(ch->uid()) +
289 ") with sn: " + to_string(uwcbrh->sn()));
290
291 sendDown(p, delay);
292}
293
294void
296{
297 double delay = 0;
298 Packet *p = Packet::alloc();
299 this->initPkt(p);
300 hdr_cmn *ch = hdr_cmn::access(p);
301 hdr_uwcbr *uwcbrh = HDR_UWCBR(p);
302 uwcbrh->priority() = 0;
303
304 printOnLog(Logger::LogLevel::DEBUG,
305 "UWCBR",
306 "sendPktLowPriority()::send a packet (" + to_string(ch->uid()) +
307 ") with sn: " + to_string(uwcbrh->sn()));
308
309 sendDown(p, delay);
310}
311
312void
314{
315 double delay = 0;
316 Packet *p = Packet::alloc();
317 this->initPkt(p);
318 hdr_cmn *ch = hdr_cmn::access(p);
319 hdr_uwcbr *uwcbrh = HDR_UWCBR(p);
320 uwcbrh->priority() = 1;
321
322 printOnLog(Logger::LogLevel::DEBUG,
323 "UWCBR",
324 "sendPktHighPriority()::send a packet (" + to_string(ch->uid()) +
325 ") with sn: " + to_string(uwcbrh->sn()));
326
327 sendDown(p, delay);
328}
329
330void
332{
333 sendPkt();
334 sendTmr_.resched(getTimeBeforeNextPkt()); // schedule next transmission
335}
336
337void
339{
340 sendTmr_.force_cancel();
341}
342
343void
344UwCbrModule::recv(Packet *p, Handler *h)
345{
346 recv(p);
347}
348
349void
351{
352 hdr_cmn *ch = hdr_cmn::access(p);
353
354 printOnLog(Logger::LogLevel::DEBUG,
355 "UWCBR",
356 "recv(Packet *)::received packet with id " + to_string(ch->uid()));
357
358 if (ch->ptype() != PT_UWCBR) {
361 return;
362 }
363
364 hdr_uwcbr *uwcbrh = HDR_UWCBR(p);
365 esn = hrsn + 1; // expected sn
366
367 if (!drop_out_of_order_) {
368 if (sn_check[uwcbrh->sn() & 0x00ffffff]) {
369 // Packet already processed: drop it
372 return;
373 }
374 }
375
376 sn_check[uwcbrh->sn() & 0x00ffffff] = true;
377
378 if (drop_out_of_order_) {
379 if (uwcbrh->sn() < esn) {
380 // packet is out of sequence and is to be discarded
381 incrPktOoseq();
382
383 printOnLog(Logger::LogLevel::ERROR,
384 "UWCBR",
385 "recv(Packet *)::packet out of sequence sn = " +
386 to_string(uwcbrh->sn()) + " hrsn = " +
387 to_string(hrsn) + " esn = " + to_string(esn));
388
390 return;
391 }
392 }
393
394 rftt = NOW - ch->timestamp();
395
396 if (uwcbrh->rftt_valid()) {
397 double rtt = rftt + uwcbrh->rftt();
398 updateRTT(rtt);
399 }
400
401 if (tracefile_enabler_) {
403 }
404
406
407 incrPktRecv();
408
409 hrsn = uwcbrh->sn();
410 if (drop_out_of_order_) {
411 if (uwcbrh->sn() > esn) {
412 incrPktLost(uwcbrh->sn() - (esn));
413 }
414 }
415
416 double dt = NOW - lrtime;
417 updateThroughput(ch->size(), dt);
418
419 lrtime = NOW;
420
421 Packet::free(p);
422
423 if (drop_out_of_order_) {
425
426 printOnLog(Logger::LogLevel::ERROR,
427 "UWCBR",
428 "recv(Packet *)::pkts_lost = " + to_string(pkts_lost) +
429 " pkts_recv = " + to_string(pkts_recv) +
430 " hrsn = " + to_string(hrsn));
431 }
432 }
433}
434
435double
437{
438 return (rttsamples > 0) ? sumrtt / rttsamples : 0;
439}
440
441double
443{
444 return (fttsamples > 0) ? sumftt / fttsamples : 0;
445}
446
447double
449{
450 return (fttsamples > 0) ? sumtxtimes / fttsamples : 0;
451}
452
453double
455{
456 if (rttsamples > 1) {
457 double var =
458 (sumrtt2 - (sumrtt * sumrtt / rttsamples)) / (rttsamples - 1);
459 return (sqrt(var));
460 }
461
462 return 0;
463}
464
465double
467{
468 if (fttsamples > 1) {
469 double var = 0;
470 var = (sumftt2 - (sumftt * sumftt / fttsamples)) / (fttsamples - 1);
471 if (var > 0)
472 return (sqrt(var));
473 }
474
475 return 0;
476}
477
478double
480{
481 if (drop_out_of_order_) {
482 if ((pkts_recv + pkts_lost) > 0)
483 return ((double) pkts_lost / (double) (pkts_recv + pkts_lost));
484 } else {
485 if (esn > 0)
486 return (1 - (double) pkts_recv / (double) esn);
487 }
488
489 return 0;
490}
491
492double
494{
495 return ((sumdt != 0) ? sumbytes * 8 / sumdt : 0);
496}
497
498void
499UwCbrModule::updateRTT(const double &rtt)
500{
501 sumrtt += rtt;
502 sumrtt2 += rtt * rtt;
503 rttsamples++;
504}
505
506void
507UwCbrModule::updateFTT(const double &ftt)
508{
509 sumftt += ftt;
510 sumftt2 += ftt * ftt;
511 fttsamples++;
512}
513
514void
515UwCbrModule::updateThroughput(const int &bytes, const double &dt)
516{
517 sumbytes += bytes;
518 sumdt += dt;
519}
520
521void
523{
524 pkts_lost += npkts;
525}
526
527void
532
533void
538
539void
544
545void
547{
549 pkts_recv = 0;
550 pkts_ooseq = 0;
551 pkts_lost = 0;
552 srtt = 0;
553 sftt = 0;
554 sthr = 0;
555 rftt = -1;
556 sumrtt = 0;
557 sumrtt2 = 0;
558 rttsamples = 0;
559 sumftt = 0;
560 sumftt2 = 0;
561 fttsamples = 0;
562 sumbytes = 0;
563 sumdt = 0;
564}
565
566double
568{
569 if (period_ < 0) {
570 fprintf(stderr, "%s : Error : period <= 0", __PRETTY_FUNCTION__);
571 exit(1);
572 }
573
574 if (PoissonTraffic_) {
575 double u = RNG::defaultrng()->uniform_double();
576 double lambda = 1 / period_;
577 return (-log(u) / lambda);
578 }
579
580 return period_;
581}
582
583void
585{
586 hdr_uwcbr *uwcbrh = HDR_UWCBR(p);
587 hdr_cmn *ch = hdr_cmn::access(p);
588 hdr_uwip *uwiph = hdr_uwip::access(p);
589 if (tracefile_enabler_) {
590 tracefile << NOW << " " << ch->timestamp() << " " << uwcbrh->sn() << " "
591 << (int) uwiph->saddr() << " " << (int) uwiph->daddr() << " "
592 << ch->size() << "\n";
593 tracefile.flush();
594 }
595}
Adds the module for UwCbrModuleClass in ns2.
TclObject * create(int, const char *const *)
UwCbrModule class is used to manage UWCBR packets and to collect statistics about them.
double sumdt
Sum of the delays.
UwCbrModule()
Constructor of UwCbrModule class.
virtual void incrPktRecv()
Increases by one the number of received packets.
virtual void initPkt(Packet *p)
Initializes a data packet passed as argument with the default values.
static int getCbrHeaderSize()
Returns the size in byte of a hdr_uwcbr packet header.
std::string tracefilename
static int uidcnt_
Unique id of the packet generated.
virtual int command(int argc, const char *const *argv) override
TCL command interpreter.
virtual void sendPktLowPriority()
Allocates, initialize and sends a packet with the default priority flag set from tcl.
virtual double getTimeBeforeNextPkt()
Returns the amount of time to wait before the next transmission.
double rftt
Forward Trip Time seen for last received packet.
double sumbytes
Sum of bytes received.
int txsn
Sequence number of the next packet to be transmitted.
int pkts_lost
Total number of lost packets, including packets received out of sequence.
virtual double GetRTTstd() const
Returns the Round Trip Time Standard Deviation.
virtual void stop()
Stop to send packets.
virtual void incrPktInvalid()
Increases by one the number of invalid packets.
uint32_t esn
Expected serial number.
double sumftt2
Sum of (FTT^2).
double sthr
Smoothed throughput calculation.
virtual void incrPktLost(const int &)
Increases the number of packets lost.
uint16_t dstPort_
Destination port.
int pkts_ooseq
Total number of packets received out of sequence.
virtual double GetTHR() const
Returns the mean Throughput.
std::string log_suffix
Possibility to insert a log suffix.
int debug_
Flag to enable several levels of debug.
bool * sn_check
Used to keep track of the packets already received.
double sumftt
Sum of FTT samples.
double srtt
Smoothed Round Trip Time, calculated as for TCP.
uint traffic_type_
Traffic type of the packets.
virtual void printReceivedPacket(Packet *p)
Print to tracefile details about a received packet.
void printIdsPkts() const
Prints the IDs of the packet's headers defined by UWCBR.
char priority_
Priority of the data packets.
virtual double GetTxTime() const
Returns the mean transmission time.
int drop_out_of_order_
Flag to enable or disable the check for out of order packets.
double sftt
Smoothed Forward Trip Time, calculated as srtt.
virtual double GetFTTstd() const
Returns the mean Forward Trip Time Standard Deviation.
virtual void incrPktOoseq()
Increases by one the number of out of sequence packets received.
virtual void updateThroughput(const int &, const double &)
Updates the Throughput.
virtual void updateRTT(const double &)
Updates the Round Trip Time.
int tracefile_enabler_
True if enable tracefile of received packets, default disabled.
nsaddr_t dstAddr_
IP of the destination.
virtual void recv(Packet *) override
Performs the reception of packets from upper and lower layers.
int pkts_recv
Total number of received packets.
UwSendTimer sendTmr_
Timer which schedules packet transmissions.
virtual void start()
Start to send packets.
double lrtime
Time of last packet reception.
virtual void sendPktHighPriority()
Allocates, initialize and sends a packet with the default priority flag set from tcl.
double sumrtt
Sum of RTT samples.
virtual double GetFTT() const
Returns the mean Forward Trip Time.
virtual double GetPER() const
Returns the mean Packet Error Rate.
virtual void transmit()
Creates and transmits a packet and schedules a new transmission.
int pktSize_
UWCBR packets payload size.
int hrsn
Highest received sequence number.
int pkts_invalid
Total number of invalid packets received.
double sumtxtimes
Sum of transmission times
double sumrtt2
Sum of (RTT^2).
int fttsamples
Number of FTT samples.
std::ofstream tracefile
virtual double GetRTT() const
Returns the mean Round Trip Time.
virtual void updateFTT(const double &)
Updates the Forward Trip Time.
int pkts_last_reset
Used for error checking after stats are reset.
virtual void resetStats()
Resets all the statistics of the UWCBR module.
double period_
Period between two consecutive packet transmissions.
virtual void sendPkt()
Allocates, initialize and sends a packet with the default priority flag set from tcl.
int PoissonTraffic_
1 if the traffic is generated according to a poissonian distribution, 0 otherwise.
int rttsamples
Number of RTT samples.
Adds the header for hdr_uwcbr packets in ns2.
virtual void expire(Event *e)
hdr_uwcbr describes UWCBR packets.
float & rftt()
Reference to the rftt_ variable.
char & priority()
Reference to the priority_ variable.
uint16_t & traffic_type()
Reference to the rftt_ variable.
bool & rftt_valid()
Reference to the rftt_valid_ variable.
uint16_t & sn()
Reference to the sn_ variable.
static int offset_
Required by the PacketHeaderManager.
hdr_uwip describes UWIP packets.
Definition uwip-module.h:67
uint8_t & daddr()
Reference to the daddr_ variable.
uint8_t & saddr()
Reference to the saddr_ variable.
Definition uwip-module.h:92
static hdr_uwip * access(const Packet *p)
Definition uwip-module.h:83
hdr_uwudp describes UWUDP packets.
static struct hdr_uwudp * access(const Packet *p)
uint8_t & dport()
Reference to the dport_ variable.
UwCbrModuleClass class_module_uwcbr
UwCbrPktClass class_uwcbr_pkt
Provides the UWCBR packets header description and the definition of the class UWCBR.
#define UWCBR_DROP_REASON_DUPLICATED_PACKET
Reason for a drop in a UWCBR module.
#define UWCBR_DROP_REASON_OUT_OF_SEQUENCE
Reason for a drop in a UWCBR module.
#define HDR_UWCBR(p)
#define UWCBR_DROP_REASON_UNKNOWN_TYPE
Reason for a drop in a UWCBR module.