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