DESERT 3.5.1
Loading...
Searching...
No Matches
uw-csma-aloha.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
39#include "uw-csma-aloha.h"
40#include <mac.h>
41#include <cmath>
42#include <climits>
43#include <iomanip>
44#include <rng.h>
45#include <stdio.h>
46#include <stdlib.h>
47
52static class CSMAModuleClass : public TclClass
53{
54public:
59 : TclClass("Module/UW/CSMA_ALOHA")
60 {
61 }
66 TclObject *
67 create(int, const char *const *)
68 {
69 return (new CsmaAloha());
70 }
72
73void
75{
77 if (module->curr_state == CSMA_STATE_WAIT_ACK) {
78
79 if (module->debug_)
80 cout << NOW << " CsmaAloha(" << module->addr
81 << ") timer expire() current state = "
82 << module->status_info[module->curr_state]
83 << "; ACK not received, next state = "
84 << module->status_info[CSMA_STATE_BACKOFF] << endl;
85
86 module->refreshReason(CSMA_REASON_ACK_TIMEOUT);
87 module->stateBackoff();
88 } else {
89 if (module->debug_)
90 cout << NOW << " CsmaAloha(" << module->addr
91 << ")::AckTimer::expired() " << endl;
92 }
93}
94
95void
96CsmaAloha::BackOffTimer::expire(Event *e)
97{
98 timer_status = CSMA_EXPIRED;
99 if (module->curr_state == CSMA_STATE_BACKOFF) {
100
101 if (module->debug_)
102 cout << NOW << " CsmaAloha(" << module->addr
103 << ") timer expire() current state = "
104 << module->status_info[module->curr_state]
105 << "; backoff expired, next state = "
106 << module->status_info[CSMA_STATE_IDLE] << endl;
107
109 module->exitBackoff();
110 module->stateIdle();
111 } else {
112 if (module->debug_)
113 cout << NOW << " CsmaAloha(" << module->addr
114 << ")::BackoffTimer::expired() " << endl;
115 }
116}
117
118void
120{
122
123 if (module->curr_state == CSMA_STATE_LISTEN) {
124
125 if (module->debug_)
126 cout << NOW << " CsmaAloha(" << module->addr
127 << ") timer expire() current state = "
128 << module->status_info[module->curr_state]
129 << "; listening period expired, next state = "
130 << module->status_info[CSMA_STATE_TX_DATA] << endl;
131
132 module->refreshReason(CSMA_REASON_LISTEN_TIMEOUT);
133 module->stateTxData();
134 } else {
135 if (module->debug_)
136 cout << NOW << " CsmaAloha(" << module->addr
137 << ")::ListenTimer::expired() " << endl;
138 }
139}
140
141const double CsmaAloha::prop_speed = 1500.0;
142int CsmaAloha::u_pkt_id;
143bool CsmaAloha::initialized = false;
144
145map<CsmaAloha::CSMA_STATUS, string> CsmaAloha::status_info;
146map<CsmaAloha::CSMA_REASON_STATUS, string> CsmaAloha::reason_info;
147map<CsmaAloha::CSMA_PKT_TYPE, string> CsmaAloha::pkt_type_info;
148
149CsmaAloha::CsmaAloha()
150 : ack_timer(this)
151 , listen_timer(this)
152 , backoff_timer(this)
153 , u_data_id(0)
154 , last_sent_data_id(-1)
155 , session_distance(SESSION_DISTANCE_NOT_SET)
156 , curr_data_pkt(0)
157 , last_data_id_rx(NOT_SET)
158 , curr_tx_rounds(0)
159 , TxActive(false)
160 , RxActive(false)
161 , session_active(false)
162 , print_transitions(false)
163 , has_buffer_queue(false)
164 , curr_state(CSMA_STATE_IDLE)
165 , prev_state(CSMA_STATE_IDLE)
166 , prev_prev_state(CSMA_STATE_IDLE)
167 , ack_mode(CSMA_ACK_MODE)
168 , last_reason(CSMA_REASON_NOT_SET)
169 , start_tx_time(0)
170 , srtt(0)
171 , sumrtt(0)
172 , sumrtt2(0)
173 , rttsamples(0)
174{
175 u_pkt_id = 0;
176 mac2phy_delay_ = 1e-19;
177
178 bind("HDR_size_", (int *) &HDR_size);
179 bind("ACK_size_", (int *) &ACK_size);
180 bind("max_tx_tries_", (int *) &max_tx_tries);
181 bind("wait_costant_", (double *) &wait_costant);
182 bind("debug_", (double *) &debug_);
183 bind("max_payload_", (int *) &max_payload);
184 bind("ACK_timeout_", (double *) &ACK_timeout);
185 bind("alpha_", (double *) &alpha_);
186 bind("backoff_tuner_", (double *) &backoff_tuner);
187 bind("buffer_pkts_", (int *) &buffer_pkts);
188 bind("max_backoff_counter_", (int *) &max_backoff_counter);
189 bind("listen_time_", &listen_time);
190
191 if (max_tx_tries <= 0)
192 max_tx_tries = INT_MAX;
193 if (buffer_pkts > 0)
194 has_buffer_queue = true;
195 if (listen_time <= 0.0)
196 listen_time = 1e-19;
197}
198
199CsmaAloha::~CsmaAloha()
200{
201}
202
203// TCL command interpreter
204int
205CsmaAloha::command(int argc, const char *const *argv)
206{
207 Tcl &tcl = Tcl::instance();
208 if (argc == 2) {
209 if (strcasecmp(argv[1], "setAckMode") == 0) {
210 ack_mode = CSMA_ACK_MODE;
211 return TCL_OK;
212 } else if (strcasecmp(argv[1], "setNoAckMode") == 0) {
213 ack_mode = CSMA_NO_ACK_MODE;
214 return TCL_OK;
215 } else if (strcasecmp(argv[1], "initialize") == 0) {
216 if (initialized == false)
217 initInfo();
218 if (print_transitions)
219 fout.open("/tmp/CSMAstateTransitions.txt", ios_base::app);
220 return TCL_OK;
221 } else if (strcasecmp(argv[1], "printTransitions") == 0) {
222 print_transitions = true;
223 return TCL_OK;
224 } else if (strcasecmp(argv[1], "getQueueSize") == 0) {
225 tcl.resultf("%d", Q.size());
226 return TCL_OK;
227 } else if (strcasecmp(argv[1], "getUpLayersDataRx") == 0) {
228 tcl.resultf("%d", getUpLayersDataPktsRx());
229 return TCL_OK;
230 }
231 } else if (argc == 3) {
232 if (strcasecmp(argv[1], "setMacAddr") == 0) {
233 addr = atoi(argv[2]);
234 if (debug_)
235 cout << "Csma_Aloha MAC address of current node is " << addr
236 << endl;
237 return TCL_OK;
238 }
239 }
240 return MMac::command(argc, argv);
241}
242
243int
244CsmaAloha::crLayCommand(ClMessage *m)
245{
246 switch (m->type()) {
247
248 default:
249 return Module::crLayCommand(m);
250 }
251}
252
253void
254CsmaAloha::initInfo()
255{
256
257 initialized = true;
258
259 if ((print_transitions) && (system(NULL))) {
260 system("rm -f /tmp/CSMAstateTransitions.txt");
261 system("touch /tmp/CSMAstateTransitions.txt");
262 }
263
264 status_info[CSMA_STATE_IDLE] = "Idle state";
265 status_info[CSMA_STATE_BACKOFF] = "Backoff state";
266 status_info[CSMA_STATE_TX_DATA] = "Transmit DATA state";
267 status_info[CSMA_STATE_TX_ACK] = "Transmit ACK state";
268 status_info[CSMA_STATE_WAIT_ACK] = "Wait for ACK state";
269 status_info[CSMA_STATE_DATA_RX] = "DATA received state";
270 status_info[CSMA_STATE_ACK_RX] = "ACK received state";
271 status_info[CSMA_STATE_LISTEN] = "Listening channel state";
272 status_info[CSMA_STATE_RX_IDLE] = "Start rx Idle state";
273 status_info[CSMA_STATE_RX_BACKOFF] = "Start rx Backoff state";
274 status_info[CSMA_STATE_RX_LISTEN] = "Start rx Listen state";
275 status_info[CSMA_STATE_RX_WAIT_ACK] = "Start rx Wait ACK state";
276 status_info[CSMA_STATE_CHK_LISTEN_TIMEOUT] = "Check Listen timeout state";
277 status_info[CSMA_STATE_CHK_BACKOFF_TIMEOUT] = "Check Backoff timeout state";
278 status_info[CSMA_STATE_CHK_ACK_TIMEOUT] = "Check Wait ACK timeout state";
279 status_info[CSMA_STATE_WRONG_PKT_RX] = "Wrong Pkt Rx state";
280
281 reason_info[CSMA_REASON_DATA_PENDING] = "DATA pending from upper layers";
282 reason_info[CSMA_REASON_DATA_RX] = "DATA received";
283 reason_info[CSMA_REASON_DATA_TX] = "DATA transmitted";
284 reason_info[CSMA_REASON_ACK_TX] = "ACK tranmsitted";
285 reason_info[CSMA_REASON_ACK_RX] = "ACK received";
286 reason_info[CSMA_REASON_BACKOFF_TIMEOUT] = "Backoff expired";
287 reason_info[CSMA_REASON_ACK_TIMEOUT] = "ACK timeout";
288 reason_info[CSMA_REASON_DATA_EMPTY] = "DATA queue empty";
289 reason_info[CSMA_REASON_MAX_TX_TRIES] = "DATA dropped due to max tx rounds";
290 reason_info[CSMA_REASON_LISTEN] = "DATA pending, listening to channel";
291 reason_info[CSMA_REASON_LISTEN_TIMEOUT] =
292 "DATA pending, end of listening period";
293 reason_info[CSMA_REASON_START_RX] = "Start rx pkt";
294 reason_info[CSMA_REASON_PKT_NOT_FOR_ME] = "Received an erroneous pkt";
295 reason_info[CSMA_REASON_BACKOFF_PENDING] = "Backoff timer pending";
296 reason_info[CSMA_REASON_WAIT_ACK_PENDING] = "Wait for ACK timer pending";
297 reason_info[CSMA_REASON_LISTEN_PENDING] = "Listen to channel pending";
298 reason_info[CSMA_REASON_PKT_ERROR] = "Erroneous pkt";
299
300 pkt_type_info[CSMA_ACK_PKT] = "ACK pkt";
301 pkt_type_info[CSMA_DATA_PKT] = "DATA pkt";
302 pkt_type_info[CSMA_DATAMAX_PKT] = "MAX payload DATA pkt";
303}
304
305void
306CsmaAloha::resetSession()
307{
308 session_distance = SESSION_DISTANCE_NOT_SET;
309}
310
311void
312CsmaAloha::updateRTT(double curr_rtt)
313{
314 srtt = alpha_ * srtt + (1 - alpha_) * curr_rtt;
315 sumrtt += curr_rtt;
316 sumrtt2 += curr_rtt * curr_rtt;
317 rttsamples++;
318 ACK_timeout = srtt;
319}
320
321void
322CsmaAloha::updateAckTimeout(double rtt)
323{
324 updateRTT(rtt);
325
326 if (debug_)
327 cout << NOW << " CsmaAloha(" << addr
328 << ")::updateAckTimeout() curr ACK_timeout = " << ACK_timeout
329 << endl;
330}
331
332bool
333CsmaAloha::keepDataPkt(int serial_number)
334{
335 bool keep_packet;
336 if (serial_number > last_data_id_rx) {
337 keep_packet = true;
338 last_data_id_rx = serial_number;
339 } else
340 keep_packet = false;
341 return keep_packet;
342}
343
344double
345CsmaAloha::computeTxTime(CSMA_PKT_TYPE type)
346{
347 double duration;
348 Packet *temp_data_pkt;
349
350 if (type == CSMA_DATA_PKT) {
351 if (!Q.empty()) {
352 temp_data_pkt = (Q.front())->copy();
353 hdr_cmn *ch = HDR_CMN(temp_data_pkt);
354 ch->size() = HDR_size + ch->size();
355 } else {
356 temp_data_pkt = Packet::alloc();
357 hdr_cmn *ch = HDR_CMN(temp_data_pkt);
358 ch->size() = HDR_size + max_payload;
359 }
360 } else if (type == CSMA_ACK_PKT) {
361 temp_data_pkt = Packet::alloc();
362 hdr_cmn *ch = HDR_CMN(temp_data_pkt);
363 ch->size() = ACK_size;
364 }
365 duration = Mac2PhyTxDuration(temp_data_pkt);
366 Packet::free(temp_data_pkt);
367 return (duration);
368}
369
370void
371CsmaAloha::exitBackoff()
372{
373 backoff_timer.stop();
374}
375
376double
377CsmaAloha::getBackoffTime()
378{
379 incrTotalBackoffTimes();
380 double random = RNG::defaultrng()->uniform_double();
381
382 backoff_timer.incrCounter();
383 int counter = backoff_timer.getCounter();
384 if (counter > max_backoff_counter)
385 counter = max_backoff_counter;
386
387 double backoff_duration =
388 backoff_tuner * random * 2.0 * ACK_timeout * pow(2.0, counter);
389 backoffSumDuration(backoff_duration);
390
391 if (debug_) {
392 cout << NOW << " CsmaAloha(" << addr
393 << ")::getBackoffTime() backoff time = " << backoff_duration
394 << " s" << endl;
395 }
396 return backoff_duration;
397}
398
399void
400CsmaAloha::recvFromUpperLayers(Packet *p)
401{
402 if (((has_buffer_queue == true) && (Q.size() < buffer_pkts)) ||
403 (has_buffer_queue == false)) {
404 initPkt(p, CSMA_DATA_PKT);
405 Q.push(p);
406 incrUpperDataRx();
407 waitStartTime();
408
409 if (curr_state == CSMA_STATE_IDLE) {
410 refreshReason(CSMA_REASON_DATA_PENDING);
411 stateListen();
412 }
413 } else {
414 incrDiscardedPktsTx();
415 drop(p, 1, CSMA_DROP_REASON_BUFFER_FULL);
416 }
417}
418
419void
420CsmaAloha::initPkt(Packet *p, CSMA_PKT_TYPE type, int dest_addr)
421{
422 hdr_cmn *ch = hdr_cmn::access(p);
423 hdr_mac *mach = HDR_MAC(p);
424
425 int curr_size = ch->size();
426
427 switch (type) {
428
429 case (CSMA_DATA_PKT): {
430 ch->size() = curr_size + HDR_size;
431 data_sn_queue.push(u_data_id);
432 u_data_id++;
433 } break;
434
435 case (CSMA_ACK_PKT): {
436 ch->ptype() = PT_MMAC_ACK;
437 ch->size() = ACK_size;
438 ch->uid() = u_pkt_id++;
439 mach->set(MF_CONTROL, addr, dest_addr);
440 mach->macSA() = addr;
441 mach->macDA() = dest_addr;
442 } break;
443 }
444}
445
446void
447CsmaAloha::Mac2PhyStartTx(Packet *p)
448{
449 if (debug_)
450 cout << NOW << " CsmaAloha(" << addr
451 << ")::Mac2PhyStartTx() start tx packet" << endl;
452
453 MMac::Mac2PhyStartTx(p);
454}
455
456void
457CsmaAloha::Phy2MacEndTx(const Packet *p)
458{
459
460 if (debug_)
461 cout << NOW << " CsmaAloha(" << addr
462 << ")::Phy2MacEndTx() end tx packet" << endl;
463
464 switch (curr_state) {
465
466 case (CSMA_STATE_TX_DATA): {
467 refreshReason(CSMA_REASON_DATA_TX);
468 if (ack_mode == CSMA_ACK_MODE) {
469
470 if (debug_)
471 cout << NOW << " CsmaAloha(" << addr
472 << ")::Phy2MacEndTx() DATA sent,from "
473 << status_info[curr_state] << " to "
474 << status_info[CSMA_STATE_WAIT_ACK] << endl;
475
476 stateWaitAck();
477 } else {
478
479 if (debug_)
480 cout << NOW << " CsmaAloha(" << addr
481 << ")::Phy2MacEndTx() DATA sent, from "
482 << status_info[curr_state] << " to "
483 << status_info[CSMA_STATE_IDLE] << endl;
484
485 stateIdle();
486 }
487 } break;
488
489 case (CSMA_STATE_TX_ACK): {
490 refreshReason(CSMA_REASON_ACK_TX);
491
492 if (prev_prev_state == CSMA_STATE_RX_BACKOFF) {
493 if (debug_)
494 cout << NOW << " CsmaAloha(" << addr
495 << ")::Phy2MacEndTx() ack sent, from "
496 << status_info[curr_state] << " to "
497 << status_info[CSMA_STATE_CHK_BACKOFF_TIMEOUT] << endl;
498
499 stateCheckBackoffExpired();
500 } else if (prev_prev_state == CSMA_STATE_RX_LISTEN) {
501 if (debug_)
502 cout << NOW << " CsmaAloha(" << addr
503 << ")::Phy2MacEndTx() ack sent, from "
504 << status_info[curr_state] << " to "
505 << status_info[CSMA_STATE_CHK_LISTEN_TIMEOUT] << endl;
506
507 stateCheckListenExpired();
508 } else if (prev_prev_state == CSMA_STATE_RX_IDLE) {
509
510 if (debug_)
511 cout << NOW << " CsmaAloha(" << addr
512 << ")::Phy2MacEndTx() ack sent, from "
513 << status_info[curr_state] << " to "
514 << status_info[CSMA_STATE_IDLE] << endl;
515
516 stateIdle();
517 } else if (prev_prev_state == CSMA_STATE_RX_WAIT_ACK) {
518 if (debug_)
519 cout << NOW << " CsmaAloha(" << addr
520 << ")::Phy2MacEndTx() ack sent, from "
521 << status_info[curr_state] << " to "
522 << status_info[CSMA_STATE_IDLE] << endl;
523 stateCheckAckExpired();
524 } else {
525
526 cout << NOW << " CsmaAloha(" << addr
527 << ")::Phy2MacEndTx() logical error in timers, current "
528 "state = "
529 << status_info[curr_state] << endl;
530 stateIdle();
531 }
532 } break;
533
534 default: {
535 cout << NOW << " CsmaAloha(" << addr
536 << ")::Phy2MacEndTx() logical error, current state = "
537 << status_info[curr_state] << endl;
538 stateIdle();
539 } break;
540 }
541}
542
543void
544CsmaAloha::Phy2MacStartRx(const Packet *p)
545{
546 if (debug_)
547 cout << NOW << " CsmaAloha(" << addr
548 << ")::Phy2MacStartRx() rx Packet " << endl;
549
550 refreshReason(CSMA_REASON_START_RX);
551
552 switch (curr_state) {
553
554 case (CSMA_STATE_IDLE):
555 stateRxIdle();
556 break;
557
558 case (CSMA_STATE_LISTEN):
559 stateRxListen();
560 break;
561
562 case (CSMA_STATE_BACKOFF):
563 stateRxBackoff();
564 break;
565
566 case (CSMA_STATE_WAIT_ACK):
567 stateRxWaitAck();
568 break;
569
570 default: {
571 cerr << NOW << " CsmaAloha(" << addr
572 << ")::Phy2MacStartRx() logical warning, current state = "
573 << status_info[curr_state] << endl;
574 stateIdle();
575 }
576 }
577}
578
579void
580CsmaAloha::Phy2MacEndRx(Packet *p)
581{
582
583 hdr_cmn *ch = HDR_CMN(p);
584 packet_t rx_pkt_type = ch->ptype();
585 hdr_mac *mach = HDR_MAC(p);
586 hdr_MPhy *ph = HDR_MPHY(p);
587
588 int source_mac = mach->macSA();
589 int dest_mac = mach->macDA();
590
591 double gen_time = ph->txtime;
592 double received_time = ph->rxtime;
593 double diff_time = received_time - gen_time;
594
595 double distance = diff_time * prop_speed;
596
597 if (debug_)
598 cout << NOW << " CsmaAloha(" << addr << ")::Phy2MacEndRx() "
599 << status_info[curr_state]
600 << ", received a pkt type = " << ch->ptype()
601 << ", src addr = " << mach->macSA()
602 << " dest addr = " << mach->macDA()
603 << ", estimated distance between nodes = " << distance << " m "
604 << endl;
605
606 if (ch->error()) {
607
608 if (debug_)
609 cout << NOW << " CsmaAloha(" << addr
610 << ")::Phy2MacEndRx() dropping corrupted pkt " << endl;
611 incrErrorPktsRx();
612
613 refreshReason(CSMA_REASON_PKT_ERROR);
614 drop(p, 1, CSMA_DROP_REASON_ERROR);
615 stateRxPacketNotForMe(NULL);
616 } else {
617 if (dest_mac == addr || dest_mac == MAC_BROADCAST) {
618 if (rx_pkt_type == PT_MMAC_ACK) {
619 refreshReason(CSMA_REASON_ACK_RX);
620 stateRxAck(p);
621 } else if (curr_state != CSMA_STATE_RX_WAIT_ACK) {
622 refreshReason(CSMA_REASON_DATA_RX);
623 stateRxData(p);
624 } else {
625 refreshReason(CSMA_REASON_PKT_NOT_FOR_ME);
626 stateRxPacketNotForMe(p);
627 }
628 } else {
629 refreshReason(CSMA_REASON_PKT_NOT_FOR_ME);
630 stateRxPacketNotForMe(p);
631 }
632 }
633}
634
635void
636CsmaAloha::txData()
637{
638 Packet *data_pkt = curr_data_pkt->copy();
639
640 if ((ack_mode == CSMA_NO_ACK_MODE)) {
641 queuePop();
642 }
643
644 incrDataPktsTx();
645 incrCurrTxRounds();
646 Mac2PhyStartTx(data_pkt);
647}
648
649void
650CsmaAloha::txAck(int dest_addr)
651{
652 Packet *ack_pkt = Packet::alloc();
653 initPkt(ack_pkt, CSMA_ACK_PKT, dest_addr);
654
655 incrAckPktsTx();
656 Mac2PhyStartTx(ack_pkt);
657}
658
659void
660CsmaAloha::stateRxPacketNotForMe(Packet *p)
661{
662 if (debug_)
663 cout << NOW << " CsmaAloha(" << addr
664 << ")::stateRxPacketNotForMe() pkt for another address. Dropping "
665 "pkt"
666 << endl;
667 if (p != NULL)
668 Packet::free(p);
669
670 refreshState(CSMA_STATE_WRONG_PKT_RX);
671
672 switch (prev_state) {
673
674 case CSMA_STATE_RX_IDLE:
675 stateIdle();
676 break;
677
678 case CSMA_STATE_RX_LISTEN:
679 stateCheckListenExpired();
680 break;
681
682 case CSMA_STATE_RX_BACKOFF:
683 stateCheckBackoffExpired();
684 break;
685
686 case CSMA_STATE_RX_WAIT_ACK:
687 stateCheckAckExpired();
688 break;
689
690 default:
691 cerr << NOW << " CsmaAloha(" << addr
692 << ")::stateRxPacketNotForMe() logical error, current state = "
693 << status_info[curr_state] << endl;
694 stateIdle();
695 }
696}
697
698void
699CsmaAloha::stateCheckListenExpired()
700{
701 refreshState(CSMA_STATE_CHK_LISTEN_TIMEOUT);
702
703 if (debug_)
704 cout << NOW << " CsmaAloha(" << addr << ")::stateCheckListenExpired()"
705 << endl;
706 if (print_transitions)
707 printStateInfo();
708 if (listen_timer.isActive()) {
709 refreshReason(CSMA_REASON_LISTEN_PENDING);
710 refreshState(CSMA_STATE_LISTEN);
711 } else if (listen_timer.isExpired()) {
712 refreshReason(CSMA_REASON_LISTEN_TIMEOUT);
713 if (!(prev_state == CSMA_STATE_TX_ACK ||
714 prev_state == CSMA_STATE_WRONG_PKT_RX ||
715 prev_state == CSMA_STATE_ACK_RX ||
716 prev_state == CSMA_STATE_DATA_RX))
717 stateTxData();
718 else
719 stateListen();
720 } else {
721 cerr << NOW << " CsmaAloha(" << addr
722 << ")::stateCheckListenExpired() listen_timer logical error, "
723 "current timer state = "
724 << status_info[curr_state] << endl;
725 stateIdle();
726 }
727}
728
729void
730CsmaAloha::stateCheckAckExpired()
731{
732 refreshState(CSMA_STATE_CHK_ACK_TIMEOUT);
733
734 if (debug_)
735 cout << NOW << " CsmaAloha(" << addr << ")::stateCheckAckExpired()"
736 << endl;
737 if (print_transitions)
738 printStateInfo();
739 if (ack_timer.isActive()) {
740 refreshReason(CSMA_REASON_WAIT_ACK_PENDING);
741 refreshState(CSMA_STATE_WAIT_ACK);
742 } else if (ack_timer.isExpired()) {
743 refreshReason(CSMA_REASON_ACK_TIMEOUT);
744 stateBackoff();
745 } else {
746 cerr << NOW << " CsmaAloha(" << addr
747 << ")::stateCheckAckExpired() ack_timer logical error, current "
748 "timer state = "
749 << status_info[curr_state] << endl;
750 stateIdle();
751 }
752}
753
754void
755CsmaAloha::stateCheckBackoffExpired()
756{
757 refreshState(CSMA_STATE_CHK_BACKOFF_TIMEOUT);
758
759 if (debug_)
760 cout << NOW << " CsmaAloha(" << addr << ")::stateCheckBackoffExpired()"
761 << endl;
762 if (print_transitions)
763 printStateInfo();
764 if (backoff_timer.isActive()) {
765 refreshReason(CSMA_REASON_BACKOFF_PENDING);
766 stateBackoff();
767 } else if (backoff_timer.isExpired()) {
768 refreshReason(CSMA_REASON_BACKOFF_TIMEOUT);
769 exitBackoff();
770 stateIdle();
771 } else {
772 cerr << NOW << " CsmaAloha(" << addr
773 << ")::stateCheckBackoffExpired() backoff_timer logical error, "
774 "current timer state = "
775 << status_info[curr_state] << endl;
776 stateIdle();
777 }
778}
779
780void
781CsmaAloha::stateIdle()
782{
783 ack_timer.stop();
784 backoff_timer.stop();
785 listen_timer.stop();
786 resetSession();
787
788 refreshState(CSMA_STATE_IDLE);
789
790 if (print_transitions)
791 printStateInfo();
792
793 if (debug_)
794 cout << NOW << " CsmaAloha(" << addr
795 << ")::stateIdle() queue size = " << Q.size() << endl;
796
797 if (!Q.empty()) {
798 refreshReason(CSMA_REASON_LISTEN);
799 stateListen();
800 }
801}
802
803void
804CsmaAloha::stateRxIdle()
805{
806 refreshState(CSMA_STATE_RX_IDLE);
807
808 if (print_transitions)
809 printStateInfo();
810}
811
812void
813CsmaAloha::stateListen()
814{
815 listen_timer.stop();
816 refreshState(CSMA_STATE_LISTEN);
817
818 listen_timer.incrCounter();
819
820 double time =
821 listen_time * RNG::defaultrng()->uniform_double() + wait_costant;
822
823 if (debug_)
824 cout << NOW << " CsmaAloha(" << addr
825 << ")::stateListen() listen time = " << time << endl;
826
827 if (print_transitions)
828 printStateInfo();
829
830 listen_timer.schedule(time);
831}
832
833void
834CsmaAloha::stateRxListen()
835{
836 refreshState(CSMA_STATE_RX_LISTEN);
837
838 if (print_transitions)
839 printStateInfo();
840}
841
842void
843CsmaAloha::stateBackoff()
844{
845 refreshState(CSMA_STATE_BACKOFF);
846
847 if (backoff_timer.isFrozen())
848 backoff_timer.unFreeze();
849 else
850 backoff_timer.schedule(getBackoffTime());
851
852 if (debug_)
853 cout << NOW << " CsmaAloha(" << addr << ")::stateBackoff() " << endl;
854 if (print_transitions)
855 printStateInfo(backoff_timer.getDuration());
856}
857
858void
859CsmaAloha::stateRxBackoff()
860{
861 backoff_timer.freeze();
862 refreshState(CSMA_STATE_RX_BACKOFF);
863
864 if (print_transitions)
865 printStateInfo();
866}
867
868void
869CsmaAloha::stateTxData()
870{
871 refreshState(CSMA_STATE_TX_DATA);
872
873 if (debug_)
874 cout << NOW << " CsmaAloha(" << addr << ")::stateTxData() " << endl;
875 if (print_transitions)
876 printStateInfo();
877
878 curr_data_pkt = Q.front();
879
880 if (data_sn_queue.front() != last_sent_data_id) {
881 resetCurrTxRounds();
882 ack_timer.resetCounter();
883 listen_timer.resetCounter();
884 backoff_timer.resetCounter();
885 }
886 if (curr_tx_rounds < max_tx_tries) {
887 hdr_mac *mach = HDR_MAC(curr_data_pkt);
888
889 mach->macSA() = addr;
890 start_tx_time = NOW;
891 last_sent_data_id = data_sn_queue.front();
892 txData();
893 } else {
894 queuePop(false);
895 incrDroppedPktsTx();
896
897 refreshReason(CSMA_REASON_MAX_TX_TRIES);
898
899 if (debug_)
900 cout << NOW << " CsmaAloha(" << addr
901 << ")::stateTxData() curr_tx_rounds " << curr_tx_rounds
902 << " > max_tx_tries = " << max_tx_tries << endl;
903
904 stateIdle();
905 }
906}
907
908void
909CsmaAloha::stateWaitAck()
910{
911 ack_timer.stop();
912 refreshState(CSMA_STATE_WAIT_ACK);
913
914 if (debug_)
915 cout << NOW << " CsmaAloha(" << addr << ")::stateWaitAck() " << endl;
916 if (print_transitions)
917 printStateInfo();
918
919 ack_timer.incrCounter();
920 ack_timer.schedule(ACK_timeout + 2 * wait_costant);
921}
922
923void
924CsmaAloha::stateRxWaitAck()
925{
926 refreshState(CSMA_STATE_RX_WAIT_ACK);
927
928 if (print_transitions)
929 printStateInfo();
930}
931
932void
933CsmaAloha::stateTxAck(int dest_addr)
934{
935 refreshState(CSMA_STATE_TX_ACK);
936
937 if (debug_)
938 cout << NOW << " CsmaAloha(" << addr << ")::stateTxAck() dest addr "
939 << dest_addr << endl;
940 if (print_transitions)
941 printStateInfo();
942
943 txAck(dest_addr);
944}
945
946void
947CsmaAloha::stateRxData(Packet *data_pkt)
948{
949 refreshState(CSMA_STATE_DATA_RX);
950
951 if (debug_)
952 cout << NOW << " CsmaAloha(" << addr << ")::stateRxData() in state "
953 << status_info[curr_state] << endl;
954 refreshReason(CSMA_REASON_DATA_RX);
955
956 hdr_mac *mach = HDR_MAC(data_pkt);
957 int dst_addr = mach->macSA();
958
959 switch (prev_state) {
960
961 case CSMA_STATE_RX_IDLE: {
962 hdr_cmn *ch = hdr_cmn::access(data_pkt);
963 ch->size() = ch->size() - HDR_size;
964 incrDataPktsRx();
965 sendUp(data_pkt);
966
967 if (ack_mode == CSMA_ACK_MODE)
968 stateTxAck(dst_addr);
969 else
970 stateIdle();
971 } break;
972
973 case CSMA_STATE_RX_LISTEN: {
974 hdr_cmn *ch = hdr_cmn::access(data_pkt);
975 ch->size() = ch->size() - HDR_size;
976 incrDataPktsRx();
977 sendUp(data_pkt);
978
979 if (ack_mode == CSMA_ACK_MODE)
980 stateTxAck(dst_addr);
981 else
982 stateCheckListenExpired();
983 } break;
984
985 case CSMA_STATE_RX_BACKOFF: {
986 hdr_cmn *ch = hdr_cmn::access(data_pkt);
987 ch->size() = ch->size() - HDR_size;
988 incrDataPktsRx();
989 sendUp(data_pkt);
990 if (ack_mode == CSMA_ACK_MODE)
991 stateTxAck(dst_addr);
992 else
993 stateCheckBackoffExpired();
994 } break;
995
996 case CSMA_STATE_RX_WAIT_ACK: {
997 hdr_cmn *ch = hdr_cmn::access(data_pkt);
998 ch->size() = ch->size() - HDR_size;
999 incrDataPktsRx();
1000 sendUp(data_pkt);
1001 if (ack_mode == CSMA_ACK_MODE)
1002 stateTxAck(dst_addr);
1003 else
1004 stateCheckAckExpired();
1005 } break;
1006
1007 default:
1008
1009 cerr << NOW << " CsmaAloha(" << addr
1010 << ")::stateRxData() logical error, prev state = "
1011 << status_info[prev_state] << endl;
1012 }
1013}
1014
1015void
1016CsmaAloha::stateRxAck(Packet *p)
1017{
1018 ack_timer.stop();
1019 refreshState(CSMA_STATE_ACK_RX);
1020 if (debug_)
1021 cout << NOW << " CsmaAloha(" << addr << ")::stateRxAck() " << endl;
1022
1023 Packet::free(p);
1024
1025 refreshReason(CSMA_REASON_ACK_RX);
1026
1027 switch (prev_state) {
1028
1029 case CSMA_STATE_RX_IDLE:
1030 stateIdle();
1031 break;
1032
1033 case CSMA_STATE_RX_LISTEN:
1034 stateCheckListenExpired();
1035 break;
1036
1037 case CSMA_STATE_RX_BACKOFF:
1038 stateCheckBackoffExpired();
1039 break;
1040
1041 case CSMA_STATE_RX_WAIT_ACK:
1042 queuePop();
1043 updateAckTimeout(NOW - start_tx_time);
1044 incrAckPktsRx();
1045 stateIdle();
1046 break;
1047
1048 default:
1049
1050 cerr << NOW << " CsmaAloha(" << addr
1051 << ")::stateRxAck() logical error, prev state = "
1052 << status_info[prev_state] << endl;
1053 }
1054}
1055
1056void
1057CsmaAloha::printStateInfo(double delay)
1058{
1059 if (debug_)
1060 cout << NOW << " CsmaAloha(" << addr << ")::printStateInfo() "
1061 << "from " << status_info[prev_state] << " to "
1062 << status_info[curr_state]
1063 << ". Reason: " << reason_info[last_reason] << endl;
1064
1065 if (curr_state == CSMA_STATE_BACKOFF) {
1066 fout << left << setw(10) << NOW << " CsmaAloha(" << addr
1067 << ")::printStateInfo() "
1068 << "from " << status_info[prev_state] << " to "
1069 << status_info[curr_state]
1070 << ". Reason: " << reason_info[last_reason]
1071 << ". Backoff duration = " << delay << endl;
1072 } else {
1073 fout << left << setw(10) << NOW << " CsmaAloha(" << addr
1074 << ")::printStateInfo() "
1075 << "from " << status_info[prev_state] << " to "
1076 << status_info[curr_state]
1077 << ". Reason: " << reason_info[last_reason] << endl;
1078 }
1079}
1080
1081void
1082CsmaAloha::waitForUser()
1083{
1084 std::string response;
1085 std::cout << "Press Enter to continue";
1086 std::getline(std::cin, response);
1087}
Class that represents the binding with the tcl configuration script.
CSMAModuleClass()
Constructor of the class.
TclObject * create(int, const char *const *)
Creates the TCL object needed for the tcl language interpretation.
virtual void expire(Event *e)
Method called when the timer expire.
CsmaAloha *CSMA_TIMER_STATUS timer_status
< Pointer to an object of type CsmaAloha
virtual void expire(Event *e)
Method called when the timer expire.
Class that describes a CsmaAloha module.
double ACK_timeout
Duration of the ACK waiting time.
virtual void stateIdle()
IDLE state.
virtual void stateTxData()
State in which the protocol allows the node to transmit a data packet.
virtual void stateCheckAckExpired()
Checks if the ACK reception timer is expired.
virtual void updateAckTimeout(double rtt)
Updates the AckTimeout calling getRTT, where the ACK timeout is computed as srtt/rttsamples using the...
virtual void stateRxAck(Packet *p)
state in which an ACK packet is received
double alpha_
smooth factor in the calculation of the RTT
@ CSMA_REASON_BACKOFF_TIMEOUT
virtual void stateWaitAck()
State in which a DATA packet is sent.
virtual void stateRxData(Packet *p)
State in which a DATA packet is received.
virtual void stateCheckListenExpired()
Checks if the Listen period is expired.
virtual void refreshReason(CSMA_REASON_STATUS reason)
Refresh the reason for the change of state.
virtual void stateRxPacketNotForMe(Packet *p)
state in which a wrong Packet is received
virtual void Phy2MacEndRx(Packet *p)
Method called when the Phy Layer finish to receive a Packet.
CsmaAloha()
Constructor of the CsmaAloha class.
BackOffTimer backoff_timer
Object that represents the backoff timer.
virtual double getBackoffTime()
compute the BackOff time as backoff = backoff_tuner*random*2*ACK_timeout*2^(counter) where counter is...
virtual void printStateInfo(double delay=0)
Prints in a file the textual information of the current state and the transitions reasons.
virtual void Phy2MacEndTx(const Packet *p)
Method called when the PHY layer finish to transmit the packet.
AckTimer ack_timer
Object that represents the ack timer.
virtual void stateBackoff()
BackOff STATE.
virtual void exitBackoff()
Method called when the Backoff timer is expired.
virtual void Phy2MacStartRx(const Packet *p)
Method called when the Phy Layer start to receive a Packet.
ListenTimer listen_timer
Object that represents the listen timer.
virtual void stateListen()
State in which the node is listening the channel.
static map< CSMA_STATUS, string > status_info
Textual description of the protocol states.
int curr_tx_rounds
Number of current transmission of the same packet.
virtual void Mac2PhyStartTx(Packet *p)
Pass the packet to the PHY layer.
CSMA_STATUS curr_state
Current state of the protocol.
int max_tx_tries
Maximum number of transmissions for one packet.
virtual void stateCheckBackoffExpired()
Checks if the Backoff period is expired.
virtual void stateTxAck(int dest_addr)
State in which the protocol set-up the ACK packet to transmit.
@ NOT_SET
@ SESSION_DISTANCE_NOT_SET
CSMAModuleClass class_module_csma
Provides the description of CsmaAloha Class.
@ DATA