DESERT 3.5.1
Loading...
Searching...
No Matches
sun-ipr-node.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 "sun-ipr-node.h"
40
41extern packet_t PT_SUN_PATH_EST;
42extern packet_t PT_SUN_PROBE;
43
50
54static class SunNodeModuleClass : public TclClass
55{
56public:
58 : TclClass("Module/UW/SUNNode")
59 {
60 }
61
62 TclObject *
63 create(int, const char *const *)
64 {
65 return (new SunIPRoutingNode());
66 }
68
69// Timer. It is invoked automatically when the timer on a route expires.
70void
72{
73 module->expTimerHopTable();
74} /* RemoveHopTableTimer::expire */
75
76// Timer. It is invoked automatically when the timer on a sink probe expires.
77void
79{
80 module->lostSink();
81} /* SinkProbeTimer::expire */
82
83// Timer. It is invoked automatically when the search path timer expires.
84void
86{
87 module->searchPathExpire();
88} /* SearchPathTimer::expire */
89
90// Constructor for SunIPRoutingNode class
92 : ipAddr_(0)
93 , metrics_(SNR)
94 , PoissonTraffic_(1)
95 , period_status_(0.1)
96 , period_data_(100)
97 , num_hop_to_sink(0)
98 , quality_link(0)
99 , hop_table_length(0)
100 , sink_associated(0)
101 , printDebug_(0)
102 , probe_min_snr_(10)
103 , search_path_enable_(true)
104 , reset_buffer_if_error_(0)
105 , pointer_packets_(0)
106 , pointer_acks_(0)
107 , list_packets_max_time_(0)
108 , list_acks_max_time_(0)
109 , packets_array_full(false)
110 , acks_array_full(false)
111 , alpha_(1.0 / 3.0)
112 , max_ack_error_(4)
113 , ack_warnings_counter_(0)
114 , ack_error_state(false)
115 , buffer_max_size_(1)
116 , safe_timer_buffer_(0)
117 , timer_route_validity_(5)
118 , timer_sink_probe_validity_(200)
119 , timer_buffer_(15)
120 , timer_search_path_(60)
121 , rmhopTableTmr_(this)
122 , sinkProbeTimer_(this)
123 , bufferTmr_(this)
124 , searchPathTmr_(this)
125 , paths_selected()
126 , n_paths_established(0)
127 , max_retx_(1)
128{
129 if (STACK_TRACE)
130 std::cout << "> SunIPRoutingNode()" << std::endl;
131 bind("ipAddr_", &ipAddr_);
132 bind("metrics_", &metrics_);
133 bind("PoissonTraffic_", &PoissonTraffic_);
134 bind("period_status_", &period_status_);
135 bind("period_data_", &period_data_);
136 bind("max_ack_error_", &max_ack_error_);
137 bind("timer_route_validity_", &timer_route_validity_);
138 bind("timer_sink_probe_validity_", &timer_sink_probe_validity_);
139 bind("timer_buffer_", &timer_buffer_);
140 bind("timer_search_path_", &timer_search_path_);
141 bind("alpha_", &alpha_);
142 bind("printDebug_", &printDebug_);
143 bind("probe_min_snr_", &probe_min_snr_);
144 bind("buffer_max_size_", &buffer_max_size_);
145 bind("safe_timer_buffer_", &safe_timer_buffer_);
146 bind("disable_path_error_", &disable_path_error_);
147 bind("reset_buffer_if_error_", &reset_buffer_if_error_);
148 bind("max_retx_", &max_retx_);
150 bufferTmr_.resched(timer_buffer_);
151 for (int i = 0; i < MAX_HOP_NUMBER; i++)
152 data_and_hops[i] = 0;
153 clearHops();
154 trace_separator_ = '\t';
155 // cout.precision(5);
156 // cout.setf(ios::floatfield, ios::fixed);
157} /* SunIPRoutingNode::SunIPRoutingNode */
158
159// Destructor for SunIPRoutingNode class
161{
162 if (STACK_TRACE)
163 std::cout << "> ~SunIPRoutingNode()" << std::endl;
164 if (printDebug_ > 5) {
165 std::cout << "[" << NOW << "]::Node[IP:" << this->printIP(ipAddr_)
166 << "||hops:" << this->getNumberOfHopToSink()
167 << "]::NODE_DELETED"
168 << std::endl;
169 }
170 delete[] hop_table;
171 delete[] trace_file_name_;
172} /* SunIPRoutingNode::~SunIPRoutingNode */
173
174int
176{
177 if (STACK_TRACE)
178 std::cout << "> recvSyncClMsg()" << std::endl;
179 return Module::recvSyncClMsg(m);
180} /* SunIPRoutingNode::recvSyncClMsg */
181
182int
184{
185 if (STACK_TRACE)
186 std::cout << "> recvAsyncClMsg()" << std::endl;
187 if (m->type() == UWIP_CLMSG_SEND_ADDR) {
189 ipAddr_ = m_->getAddr();
190 }
191 return Module::recvAsyncClMsg(m);
192} /* SunIPRoutingNode::recvAsyncClMsg */
193
194// Usually when this function is invoked you have to rest also the info about
195// the number of hops to the sink (@see setNumberOfHopToSink)
196void
198{
199 if (STACK_TRACE)
200 std::cout << "> clearHops()" << std::endl;
201 if (printDebug_ > 5) {
202 std::cout << "[" << NOW << "]::Node[IP:" << this->printIP(ipAddr_)
203 << "||hops:" << this->getNumberOfHopToSink()
204 << "]::CLEARING_HOPS::";
205 for (int i = 0; i < hop_table_length; i++) {
206 std::cout << printIP(hop_table[i])<< "|";
207 }
208 std::cout << std::endl;
209 }
210 for (int i = 0; i < MAX_HOP_NUMBER; i++) {
211 hop_table[i] = 0;
212 }
214 quality_link = 0;
216} /* SunIPRoutingNode::clearHops */
217
218/* This function is used to initialize the node. It sends to the lower
219 * layers a Sync message asking for the IP.
220 * In the tcl file it is important to add a line to call the command that will
221 * invoke
222 * this function.
223 * Example:
224 * ...
225 * set ipr($id) [new Module/UW/SUNNode]
226 * set ipif($id) [new Module/UW/IP]
227 * ...
228 * $node($id) addModule 5 $ipr($id) 0 "IPR"
229 * $node($id) addModule 4 $ipif($id) 0 "IPF"
230 * ...
231 * $ipif($id) addr "1.0.0.${tmp_}"
232 * ...
233 * $ipr($id) initialize
234 */
235void
237{
238 if (STACK_TRACE)
239 std::cout << "> initialize()" << std::endl;
240 // Asking for the IP of the current Node.
241 if (ipAddr_ == 0) {
242 UWIPClMsgReqAddr *m = new UWIPClMsgReqAddr(getId());
243 m->setDest(CLBROADCASTADDR);
245 }
246} /* SunIPRoutingNode::initialize */
247
248// This function prints in the stdout the routing table of the current node.
249void
251{
252 if (STACK_TRACE)
253 std::cout << "> printHopTable()" << std::endl;
254
255 std::cout << "HOPS_LIST:" << "\n";
256 for (int i = 0; i < hop_table_length; i++) {
257 std::cout << ">" << this->printIP(hop_table[i]) << "\n";
258 }
259 std::cout << std::endl;
260} /* SunIPRoutingNode::printHopTable */
261
262void
264{
265 auto it = paths_selected.begin();
266 std::cout << "END_NODES_MAP:" << "\n";
267 while (it != paths_selected.end()) {
268 std::cout << "NODE::" << printIP(it->first) << "::SELECTED::" << (uint)it->second << "::TIMES\n";
269 it++;
270 }
271 std::cout << std::endl;
272}
273
274/* This function convert an IP from a nsaddr_t to a string in the
275 * classical form: x.x.x.x. It returns a string, it doesn't print
276 * the value in the stdout.
277 */
278string
279SunIPRoutingNode::printIP(const nsaddr_t &ip_)
280{
281 if (STACK_TRACE)
282 std::cout << "> printIP()" << std::endl;
284 out << ((ip_ & 0xff000000) >> 24);
285 out << ".";
286 out << ((ip_ & 0x00ff0000) >> 16);
287 out << ".";
288 out << ((ip_ & 0x0000ff00) >> 8);
289 out << ".";
290 out << ((ip_ & 0x000000ff));
291 return out.str();
292} /* SunIPRoutingNode::printIP */
293
294/* This function convert an IP from a ns_addr_t to a string in the
295 * classical form: x.x.x.x
296 */
297string
298SunIPRoutingNode::printIP(const ns_addr_t &ipt_)
299{
300 return SunIPRoutingNode::printIP(ipt_.addr_);
301} /* SunIPRoutingNode::printIP */
302
303nsaddr_t
305{
306 if (STACK_TRACE)
307 std::cout << "> str2addr()" << std::endl;
308 int level[4] = {0, 0, 0, 0};
309 char tmp[20];
310 strncpy(tmp, str, 19);
311 tmp[19] = '\0';
312 char *p = strtok(tmp, ".");
313 for (int i = 0; p && i < 4; p = strtok(NULL, "."), i++) {
314 level[i] = atoi(p);
315 if (level[i] > 255)
316 level[i] = 255;
317 else if (level[i] < 0)
318 level[i] = 0;
319 }
320 nsaddr_t addr = 0;
321 for (int i = 0; i < 4; i++) {
322 addr += (level[i] << 8 * (3 - i));
323 }
324 return addr;
325} /* SunIPRoutingNode::str2addr */
326
327// Command implementation from nsmiracle. */
328int
329SunIPRoutingNode::command(int argc, const char *const *argv)
330{
331 if (STACK_TRACE)
332 std::cout << "> command()" << std::endl;
333 Tcl &tcl = Tcl::instance();
334
335 if (argc == 2) {
336 if (strcasecmp(argv[1], "initialize") == 0) {
337 this->initialize();
338 return TCL_OK;
339 } else if (strcasecmp(argv[1], "clearhops") == 0) {
340 this->clearHops();
341 return TCL_OK;
342 } else if (strcasecmp(argv[1], "printhopcount") == 0) {
343 if (num_hop_to_sink <= 0)
344 std::cout << "N: " << this->printIP(ipAddr_)
345 << " not connected to the sink." << std::endl;
346 else
347 std::cout << "N: " << this->printIP(ipAddr_)
348 << " # hops to sink = " << num_hop_to_sink << std::endl;
349 return TCL_OK;
350 } else if (strcasecmp(argv[1], "printhops") == 0) {
351 this->printHopTable();
352 return TCL_OK;
353 } else if (strcasecmp(argv[1], "printselectedroutes") == 0) {
355 return TCL_OK;
356 } else if (strcasecmp(argv[1], "getackcount") == 0) {
357 tcl.resultf("%lu", this->getAckCount());
358 return TCL_OK;
359 } else if (strcasecmp(argv[1], "getdatapktcount") == 0) {
360 tcl.resultf("%lu", this->getDataCount());
361 return TCL_OK;
362 } else if (strcasecmp(argv[1], "getforwardedcount") == 0) {
363 tcl.resultf("%lu", this->getForwardedCount());
364 return TCL_OK;
365 } else if (strcasecmp(argv[1], "getdatapktdroppedbuffer") == 0) {
366 tcl.resultf("%lu", this->getDataDropsCountBuffer());
367 return TCL_OK;
368 } else if (strcasecmp(argv[1], "getdatapktdroppedmaxretx") == 0) {
369 tcl.resultf("%lu", this->getDataDropsCountMaxRetx());
370 return TCL_OK;
371 } else if (strcasecmp(argv[1], "getpathestablishmentpktcount") == 0) {
372 tcl.resultf("%lu", this->getPathEstablishmentCount());
373 return TCL_OK;
374 } else if (strcasecmp(argv[1], "getackheadersize") == 0) {
375 tcl.resultf("%d", this->getAckHeaderSize());
376 return TCL_OK;
377 } else if (strcasecmp(argv[1], "getdatapktheadersize") == 0) {
378 tcl.resultf("%d", this->getDataPktHeaderSize());
379 return TCL_OK;
380 } else if (strcasecmp(argv[1], "getpathestheadersize") == 0) {
381 tcl.resultf("%d", this->getPathEstHeaderSize());
382 return TCL_OK;
383 } else if (strcasecmp(argv[1], "getNpathsestablished") == 0) {
384 tcl.resultf("%d", getNPathsEstablished());
385 return TCL_OK;
386 } else if (strcasecmp(argv[1], "getbufferstatus") == 0) {
387 tcl.resultf("%d", buffer_data.size());
388 return TCL_OK;
389 } else if (strcasecmp(argv[1], "getmeanretx") == 0) {
390 // double num = double(pkt_tx_) - double(pkt_stored_ -
391 // buffer_data.size());
392 // double den = double(pkt_stored_ - buffer_data.size());
393 // cout << ":ip:" << printIP(ipAddr_);
394 // cout << ":pkt_tx_:" << pkt_tx_;
395 // cout << ":pkt_stored_:" << pkt_stored_;
396 // cout << ":pkts_still_in_buffer:" <<
397 // buffer_data.size();
398 // cout << ":meanretx:" << (double(num)/double(den)) <<
399 // endl;
400 if (pkt_stored_ == 0 ||
401 static_cast<ulong>(pkt_stored_) == buffer_data.size()) {
402 tcl.resultf("%d", 0);
403 } else {
404 double num = double(pkt_tx_) -
406 double den = double(pkt_stored_ - buffer_data.size());
407 double retx = std::max(double(num) / double(den), double(0));
408 tcl.resultf("%f", retx);
409 }
410 return TCL_OK;
411 } else if (strcasecmp(argv[1], "gettransmittedpackets") == 0) {
412 tcl.resultf("%d", pkt_tx_);
413 return TCL_OK;
414 }
415 } else if (argc == 3) {
416 if (strcasecmp(argv[1], "getstats") == 0) {
417 if ((atoi(argv[2]) >= 0) && (atoi(argv[2]) < MAX_HOP_NUMBER)) {
418 tcl.resultf("%d", data_and_hops[atoi(argv[2])]);
419 return TCL_OK;
420 } else {
421 tcl.resultf(0);
422 return TCL_OK;
423 }
424 } else if (strcasecmp(argv[1], "addr") == 0) {
425 ipAddr_ = str2addr((char *) argv[2]);
426 if (ipAddr_ == 0) {
427 fprintf(stderr, "0.0.0.0 is not a valid IP address");
428 return TCL_ERROR;
429 }
430 return TCL_OK;
431 } else if (strcasecmp(argv[1], "trace") == 0) {
432 string tmp_ = ((char *) argv[2]);
433 trace_file_name_ = new char[tmp_.length() + 1];
434 strcpy(trace_file_name_, tmp_.c_str());
435 if (trace_file_name_ == NULL) {
436 fprintf(stderr, "Empty string for the trace file name");
437 return TCL_ERROR;
438 }
439 trace_ = true;
442 trace_file_.close();
443 return TCL_OK;
444 }
445 }
446 return Module::command(argc, argv);
447} /* SunIPRoutingNode::command */
448
449void
451{
452 if (STACK_TRACE)
453 std::cout << "> recv()" << std::endl;
454 hdr_uwip *iph = HDR_UWIP(p);
455 hdr_cmn *ch = HDR_CMN(p);
459
460 if (!ch->error()) { // Process the packet only if it is free from errors.
461 if (trace_)
462 this->tracePacket(p, "RECV_PKT");
463 if (ch->direction() == hdr_cmn::UP) {
464 if ((ch->next_hop() == UWIP_BROADCAST) ||
465 (ch->next_hop() == ipAddr_) ||
466 (iph->daddr() == UWIP_BROADCAST) ||
467 (iph->daddr() == ipAddr_)) { // Redundant check already made
468 // in UWIP (just in case).
469 if (ch->ptype() == PT_SUN_PATH_EST) { // Path Establishment Packet.
470
471 if (hpest->ptype() == PATH_SEARCH) { // Path Search.
472 if (iph->saddr() == ipAddr_) { // Garbage: the node
473 // received a request
474 // from itself.
475 Packet::free(p);
476 return;
477 } else {
478 if (printDebug_ > 5) {
479 std::cout << "[" << NOW << "]::Node[IP:" << this->printIP(ipAddr_)
480 << "||hops:" << this->getNumberOfHopToSink()
481 << "]::RECEIVED_PATH_EST::REQUEST_FROM:"
482 << printIP(iph->saddr())
483 << "::UID:" << ch->uid()
484 << "::SENDING_REPLYPATHESTABLISHMENT"
485 << std::endl;
486 }
487 if (trace_)
488 this->tracePacket(p, "RECV_SRC");
489 this->replyPathEstSearch(p->copy());
490 Packet::free(p);
491 return;
492 }
493 } else if (hpest->ptype() == PATH_ANSWER) { // Path Answer.
494 if (iph->saddr() == ipAddr_) { // Garbage: the node
495 // received an answer
496 // from itself.
497 Packet::free(p);
498 return;
499 } else {
500 if (iph->daddr() == ipAddr_) { // The packet is
501 // arrived to the
502 // destination.
503 if (printDebug_ > 5) {
504 std::cout << "[" << NOW
505 << "]::Node[IP:" << this->printIP(ipAddr_)
506 << "||hops:" << this->getNumberOfHopToSink()
507 << "]::RECEIVED_PATH_EST::PATH_ANSWER_FROM:"
508 << printIP(iph->saddr())
509 << "::EVALUATE_PATH"
510 << "::UID:" << ch->uid()
511 << std::endl;
512 }
513 if (trace_)
514 this->tracePacket(p, "RECV_PTH");
515 this->evaluatePath(p);
516 Packet::free(p);
517 return;
518 } else {
519 if (printDebug_ > 5) {
520 std::cout << "[" << NOW
521 << "]::Node[IP:" << this->printIP(ipAddr_)
522 << "||hops:" << this->getNumberOfHopToSink()
523 << "]::RECEIVED_PATH_EST::PATH_ANSWER_FROM:"
524 << printIP(iph->saddr())
525 << "::SEND_ROUTE_BACK"
526 << std::endl;
527 }
528 this->sendRouteBack(p->copy());
529 Packet::free(p);
530 return;
531 }
532 }
533 } else if (hpest->ptype() == PATH_ERROR) {
534 if (iph->saddr() == ipAddr_) { // Garbage: the node
535 // received an error from
536 // itself.
537 Packet::free(p);
538 return;
539 } else { // Path error: reset the route information and
540 // send back the route error packet.
541 if (printDebug_ > 5) {
542 if (printDebug_ > 5) {
543 std::cout << "[" << NOW
544 << "]::Node[IP:" << this->printIP(ipAddr_)
545 << "||hops:" << this->getNumberOfHopToSink()
546 << "]::PATH_EST:PATH_ERROR_FROM:"
547 << printIP(iph->saddr())
548 << "::UID:"
549 << ch->uid()
550 << std::endl;
551 }
552 }
553 if (trace_)
554 this->tracePacket(p, "RECV_ERR");
555 this->clearHops();
556 this->setNumberOfHopToSink(0);
557 if (iph->daddr() != ipAddr_) {
558 this->sendRouteErrorBack(p->copy());
560 while (!buffer_data.empty()) {
561 Packet::free(
562 ((buffer_element) buffer_data.front()).p_);
563 buffer_data.erase(buffer_data.begin());
564 Packet::free(p);
565 return;
566 }
567 }
568 }
569 Packet::free(p);
570 return;
571 }
572 } else {
573 Packet::free(p);
574 return;
575 }
576 } else if (ch->ptype() == PT_SUN_ACK) { // Ack Packet.
577 if (iph->saddr() == ipAddr_) { // Garbage: the node received
578 // an ack from itself.
579 Packet::free(p);
580 return;
581 } else {
582 if (printDebug_ > 5) {
583 std::cout << "[" << NOW
584 << "]::Node[IP:" << this->printIP(ipAddr_)
585 << "||hops:" << this->getNumberOfHopToSink()
586 << "]::RECEIVED_ACK_FROM:"
587 << printIP(iph->saddr())
588 << "::UID:" << hack->uid()
589 << std::endl;
590 }
591 if (trace_)
592 this->tracePacket(p, "RECV_ACK");
593 this->updateAcksCount();
595 if (hack->uid() == _tmp.id_pkt_) { // Ack for the first
596 // packet in the
597 // buffer.
599 ack_error_state = false;
600 if (buffer_data.size() > 0) { // There is at least
601 // one packet in the
602 // buffer.
603 if (safe_timer_buffer_) {
605 (Scheduler::instance().clock() -
606 ch->timestamp()) *
607 2 * (1 - 0.99);
608 if (timer_buffer_ <
609 (Scheduler::instance().clock() -
610 ch->timestamp()) *
611 2) {
613 (Scheduler::instance().clock() -
614 ch->timestamp()) *
615 2;
616 }
617 }
618 if (printDebug_ > 5) {
619 std::cout << "[" << NOW
620 << "]::Node[IP:" << this->printIP(ipAddr_)
621 << "||hops:" << this->getNumberOfHopToSink()
622 << "]::BUFFER_SIZE:" << buffer_data.size()
623 << "::PACKET_REMOVED:" << ch->uid()
624 << std::endl;
625 }
626 Packet::free(
627 ((buffer_element) buffer_data.front())
628 .p_);
629 buffer_data.erase(
630 buffer_data.begin()); // Remove the
631 // first packet.
632 }
633 } else {
634 ;
635 }
636 Packet::free(p);
637 }
638 } else if (ch->ptype() == PT_SUN_PROBE) { // Probe Packet.
639 if (printDebug_ > 5) {
640 std::cout << "[" << NOW
641 << "]::Node[IP:" << this->printIP(ipAddr_)
642 << "||hops:" << this->getNumberOfHopToSink()
643 << "]::RECEIVED_PROBE_FROM:"
644 << printIP(iph->saddr())
645 << std::endl;
646 }
647 if (trace_)
648 this->tracePacket(p, "RECV_PRB");
649 this->receiveProbe(p);
650 Packet::free(p);
651 return;
652 } else { // ch->ptype_ == Data packet.+
654 if (trace_)
655 this->tracePacket(p, "RECV_DTA");
656 this->updatePacketsCount();
657
658 if (printDebug_ > 5) {
659 std::cout << "[" << NOW
660 << "]::Node[IP:" << this->printIP(ipAddr_)
661 << "||hops:" << this->getNumberOfHopToSink()
662 << "]::RECEIVED_DATA_FROM:"
663 << printIP(iph->saddr())
664 << "::PREV_HOP:" << printIP(ch->prev_hop_)
665 << "::UID:" << ch->uid()
666 << std::endl;
667 }
668
669 if (iph->daddr() == ipAddr_) { // The packet is arrived at
670 // destination: send it up.
671 // Send back an ack
672 this->sendBackAck(p);
673
674 ch->size() -= sizeof(hdr_sun_data);
675 sendUp(p->copy());
676 Packet::free(p);
677 return;
678 } else if ((ch->next_hop() == ipAddr_) &&
679 (iph->daddr() != ipAddr_)) { // The node is a relay,
680 // forward the Data
681 // packet.
682 // Send back an ack
683 this->sendBackAck(p); // Send back an ack.
684
685 if (buffer_data.size() < buffer_max_size_) {
686 if (printDebug_ > 5) {
687 std::cout << "[" << NOW
688 << "]::Node[IP:" << this->printIP(ipAddr_)
689 << "||hops:" << this->getNumberOfHopToSink()
690 << "]::DATA_PACKET_TO_FORWARD"
691 << "::SRC:" << printIP(iph->saddr())
692 << "::DST:" << printIP(iph->daddr())
693 << "::NHOP:"<< printIP(ch->next_hop())
694 << "::PHOP:"<< printIP(ch->prev_hop_)
695 << "::UID:" << ch->uid()
696 << "::SN:" << uwcbrh->sn()
697 << "::PATH:";
698 for (int i = 0; i < hdata->list_of_hops_length(); i++) {
699 std::cout << printIP(hdata->list_of_hops()[i]) << ";";
700 }
701 std::cout << std::endl;
702 }
703 // if (buffer_data.size()
704 // == 0) { //TODO: enable
705 // this?
706 // this->searchPath();
707 // // Node not
708 // connected with any
709 // sink: send a path
710 // establishment
711 // request.
712 // search_path_enable_
713 // = false;
714 // searchPathTmr_.resched(timer_search_path_);
715 // }
716 pkt_stored_++;
717 buffer_data.push_back(buffer_element(p->copy(),
718 uwcbrh->sn(),
719 Scheduler::instance().clock()));
720 Packet::free(p);
721 } else {
722 if (printDebug_ > 5) {
723 std::cout << "[" << NOW
724 << "]::Node[IP:" << this->printIP(ipAddr_)
725 << "||hops:" << this->getNumberOfHopToSink()
726 << "]::BUFFER_FULL:DROPPING_PACKET"
727 << "::UID:" << ch->uid()
728 << std::endl;
729 }
732 }
733 return;
734 }
735 }
736 } else { // Wrong destination.
737 if (printDebug_ > 5)
738 std::cout << "[" << NOW
739 << "]::Node[IP:" << this->printIP(ipAddr_)
740 << "||hops:" << this->getNumberOfHopToSink()
741 << "]::DROPPING_PACKET::WRONG_IP"
742 << std::endl;
744 return;
745 }
746 } else if (ch->direction() ==
747 hdr_cmn::DOWN) { // The packet is arrived from the upper layers.
748 this->updatePacketsCount();
749 if (this->getNumberOfHopToSink() ==
750 1) { // The node is connected directly with the sink.
751 iph->saddr() = ipAddr_;
752 iph->daddr() =
753 0; // Used to set that the packet is not initialized.
754 if (buffer_data.size() < buffer_max_size_) { // There is space
755 // to buffer the
756 // packet.
757 if (printDebug_ > 5)
758 std::cout << "[" << NOW
759 << "]::Node[IP:" << this->printIP(ipAddr_)
760 << "||hops:" << this->getNumberOfHopToSink()
761 << "]::TO_SEND::PACKET_BUFFERED"
762 << "::UID:" << ch->uid()
763 << "::SN::" << uwcbrh->sn()
764 << std::endl;
765 pkt_stored_++;
766 buffer_data.push_back(buffer_element(p->copy(),
767 uwcbrh->sn(),
768 Scheduler::instance().clock()));
769 Packet::free(p);
770 } else {
771 if (printDebug_ > 5)
772 std::cout << "[" << NOW
773 << "]::Node[IP:" << this->printIP(ipAddr_)
774 << "||hops:" << this->getNumberOfHopToSink()
775 << "]::TO_SEND::DROPPING::BUFFER_FULL"
776 << std::endl;
779 }
780 return;
781 } else { // The current node is not directly connected with the
782 // sink.
783 iph->saddr() = ipAddr_;
784 iph->daddr() = 0; // Used to set that the packet is not initialized.
785 if (buffer_data.size() < buffer_max_size_) {
786 if (printDebug_ > 5)
787 std::cout << "[" << NOW
788 << "]::Node[IP:" << this->printIP(ipAddr_)
789 << "||hops:" << this->getNumberOfHopToSink()
790 << "]::TO_SEND::PACKET_BUFFERED"
791 << "::UID:" << ch->uid()
792 << "::SN::" << uwcbrh->sn()
793 << std::endl;
794 pkt_stored_++;
795 buffer_data.push_back(buffer_element(p->copy(),
796 uwcbrh->sn(),
797 Scheduler::instance().clock()));
798 Packet::free(p);
799 } else {
800 if (printDebug_ > 5)
801 std::cout << "[" << NOW
802 << "]::Node[IP:" << this->printIP(ipAddr_)
803 << "||hops:" << this->getNumberOfHopToSink()
804 << "]::TO_SEND::DROPPING::BUFFER_FULL"
805 << std::endl;
808 }
809 if (this->getNumberOfHopToSink() == 0) {
810 if (printDebug_ > 5)
811 std::cout << "[" << NOW
812 << "]::Node[IP:" << this->printIP(ipAddr_)
813 << "||hops:" << this->getNumberOfHopToSink()
814 << "]::BEGIN_SEARCH_PATH"
815 << std::endl;
817 this->searchPath(); // Node not connected with any sink:
818 // send a path establishment
819 // request.
820 search_path_enable_ = false;
822 }
823 }
824 return;
825 }
826 } else {
827 if (printDebug_ > 5)
828 std::cout << "[" << NOW
829 << "]::Node[IP:" << this->printIP(ipAddr_)
830 << "||hops:" << this->getNumberOfHopToSink()
831 << "]::DOWN:DATA:DROP:NO_DIRECTION"
832 << std::endl;
834 return;
835 }
836 }
837} /* SunIPRoutingNode::recv */
838
839/* This function sets the number of hops that the current node needs to reach
840 * the sink.
841 * It accepts only values >= 0.
842 * If the input value is accepted the function returns the input value,
843 * otherwise it returns 0 and doesn't change the current hop_count.
844 */
845const int &
847{
848 if (STACK_TRACE)
849 std::cout << "> setNumberOfHopToSink()" << std::endl;
850 if (hop < 0) {
851 num_hop_to_sink = 0;
852 return this->getNumberOfHopToSink();
853 } else { // (hop >= 0)
855 snr_to_sink_ = double(-9999.9);
856 return this->getNumberOfHopToSink();
857 }
858} /* SunIPRoutingNode::setNumberOfHopToSink */
859
860/* If = 1: directly connected;
861 * If = 0: not connected;
862 * If > 1: # of hops;
863 */
864const int &
866{
867 if (STACK_TRACE)
868 std::cout << "> getNumberOfHopToSink()" << std::endl;
869 return num_hop_to_sink;
870} /* SunIPRoutingNode::getNumberOfHopToSink */
871
872void
874{
875 if (STACK_TRACE)
876 std::cout << "> receiveProbe()" << std::endl;
877 hdr_MPhy *ph = HDR_MPHY(p);
878 hdr_uwip *iph = HDR_UWIP(p);
879 if (this->isZero(ph->Pn)) { // If the power of noise value is not
880 // initialized accept the probe anyway.
881 this->clearHops();
882 this->setNumberOfHopToSink(1);
883 sink_associated = iph->saddr();
885 if (printDebug_ > 5) {
886 std::cout << "[" << NOW
887 << "]::Node[IP:" << this->printIP(ipAddr_)
888 << "||hops:" << this->getNumberOfHopToSink()
889 << "]::BECAME_END_NODE"
890 << "::" << (uint)iph->saddr()
891 << std::endl;
892 }
893 } else if (10 * log10(ph->Pr / (ph->Pi + ph->Pn)) >
894 probe_min_snr_) { // Accept the probe only if its snr is greater
895 // than a minimum value.
896 // cout << "sinr probe: " << 10*log10(ph->Pr/(ph->Pi + ph->Pn))
897 // << endl;
898 // cout << "snr probe: " << 10*log10(ph->Pr/(ph->Pn)) << endl;
899 this->clearHops();
900 this->setNumberOfHopToSink(1);
901 sink_associated = iph->saddr();
902 snr_to_sink_ = 10 * log10(ph->Pr / (ph->Pn));
904 if (printDebug_ > 5) {
905 std::cout << "[" << NOW
906 << "]::Node[IP:" << this->printIP(ipAddr_)
907 << "||hops:" << this->getNumberOfHopToSink()
908 << "]::BECAME_END_NODE"
909 << "::" << (uint)iph->saddr()
910 << std::endl;
911 }
912 }
913} /* SunIPRoutingNode::receiveProbe */
914
915/* This function send a message to inform the other nodes involved in a path
916 * that the current node lost its link with the sink. And resets the information
917 * about the sink.
918 */
919void
921{
922 if (STACK_TRACE)
923 std::cout << "> lostSink()" << std::endl;
924 if (this->getNumberOfHopToSink() ==
925 1) { // Only a node with hc 1 can lost the sink.
926 this->clearHops();
927 this->setNumberOfHopToSink(0);
929 }
930} /* SunIPRoutingNode::lostSink */
931
932void
934{
935 if (STACK_TRACE)
936 std::cout << "> searchPathExpire()" << std::endl;
937 search_path_enable_ = true;
938 return;
939} /* SunIPRoutingNode::searchPathExpire */
940
941/* This function is called by the timer. It resets all the routing
942 * information.
943 */
944void
946{
947 if (STACK_TRACE)
948 std::cout << "> expTimerHopTable()" << std::endl;
949 if (printDebug_ > 5)
950 std::cout << "[" << NOW
951 << "]::Node[IP:" << this->printIP(ipAddr_)
952 << "||hops:" << this->getNumberOfHopToSink()
953 << "]::ROUTING_TABLE_EXPIRED"
954 << std::endl;
955 this->clearHops();
956 this->setNumberOfHopToSink(0);
957} /* SunIPRoutingNode::expTimerHopTable */
958
959void
960SunIPRoutingNode::tracePacket(const Packet *const p, const string &position)
961{
962 if (STACK_TRACE)
963 std::cout << "> tracePacket()" << std::endl;
964 hdr_MPhy *ph = HDR_MPHY(p);
965 hdr_uwip *iph = HDR_UWIP(p);
966 hdr_cmn *ch = HDR_CMN(p);
969 if (trace_) {
970 double snr_ = 0;
971 if (ph->Pn == 0) { // TODO: trick for CMRE logs
972 snr_ = -999;
973 } else {
974 snr_ = 10 * log10(ph->Pr / ph->Pn);
975 }
976 if (ch->ptype() == PT_SUN_ACK) {
977 this->writeInTrace(this->createTraceString(position,
978 Scheduler::instance().clock(),
979 ipAddr_,
980 ch->uid(),
981 hack->uid(),
982 ch->prev_hop_,
983 ch->next_hop(),
984 iph->saddr(),
985 iph->daddr(),
986 snr_,
987 ch->direction(),
988 ch->ptype()));
989 } else {
990 this->writeInTrace(this->createTraceString(position,
991 Scheduler::instance().clock(),
992 ipAddr_,
993 ch->uid(),
994 uwcbrh->sn(),
995 ch->prev_hop_,
996 ch->next_hop(),
997 iph->saddr(),
998 iph->daddr(),
999 snr_,
1000 ch->direction(),
1001 ch->ptype()));
1002 }
1003 }
1004} /* SunIPRoutingNode::tracePacket */
1005
1006string
1007SunIPRoutingNode::createTraceString(const string &info_string,
1008 const double &simulation_time_, const int &node_id_, const int &pkt_id_,
1009 const int &pkt_sn_, const int &pkt_from_, const int &pkt_next_hop,
1010 const int &pkt_source_, const int &pkt_destination_, const double &snr_,
1011 const int &direction_, const int &pkt_type)
1012{
1013 if (STACK_TRACE)
1014 std::cout << "> createTraceString()" << std::endl;
1015 osstream_.clear();
1016 osstream_.str("");
1017 osstream_ << info_string << this->trace_separator_ << simulation_time_
1018 << this->trace_separator_ << (node_id_ & 0x000000ff)
1019 << this->trace_separator_ << (pkt_id_ & 0x000000ff)
1020 << this->trace_separator_ << (pkt_sn_ & 0x000000ff)
1021 << this->trace_separator_ << (pkt_from_ & 0x000000ff)
1022 << this->trace_separator_ << (pkt_next_hop & 0x000000ff)
1023 << this->trace_separator_ << (pkt_source_ & 0x000000ff)
1024 << this->trace_separator_ << (pkt_destination_ & 0x000000ff)
1025 << this->trace_separator_ << snr_ << this->trace_separator_
1026 << direction_ << this->trace_separator_ << pkt_type;
1027 return osstream_.str();
1028} /* SunIPRoutingNode::createTraceString */
1029
1030void
1031SunIPRoutingNode::writeInTrace(const string &string_to_write_)
1032{
1033 if (STACK_TRACE)
1034 std::cout << "> writeInTrace()" << std::endl;
1035 trace_file_.open(trace_file_name_, fstream::app);
1037 trace_file_.close();
1038} /* SunIPRoutingNode::writeInTrace */
SunIPRoutingNode *virtual void expire(Event *e)
< Pointer to an objet of type SunIPRoutingNode.
SunIPRoutingNode *virtual void expire(Event *e)
< Pointer to an objet of type SunIPRoutingNode.
virtual void expire(Event *e)
Method invoked when the SinkProbeTimer timer expires.
SunIPRoutingNode class is used to represent the routing layer of a node.
virtual void replyPathEstSearch(Packet *)
Replies to Path Establishment Search packets.
static string printIP(const nsaddr_t &)
Returns a string with an IP in the classic form "x.x.x.x" converting an ns2 nsaddr_t address.
double timer_route_validity_
Maximum validity time for a route entry.
uint max_retx_
Maximum Number of transmissions performed: real retransmissions counter the counter is increased only...
const long & getPathEstablishmentCount() const
Returns the number of Path Establishment packets processed by the entire network.
virtual void writeInTrace(const string &)
Opens the trace file, writes the string passed as input and closes the file.
vector< buffer_element > buffer_data
Buffer used to store data packets.
virtual void printSelectedRoutes() const
Print the nodes that were chosen as relay nodes to rach the sink and how many times each node was cho...
double timer_sink_probe_validity_
Maximum validity time for a sink probe.
ostringstream osstream_
Used to convert to string.
const long & getNPathsEstablished()
Print how many times the node was established as relay node for other nodes of the netwok.
char trace_separator_
Used as separator among elements in an entr of the tracefile.
bool search_path_enable_
Flag to enable or disable the possibility to send search_path packets.
static long number_of_datapkt_
Comulative number of Data packets processed by SunIPRoutingNode objects.
virtual int command(int, const char *const *)
TCL command interpreter.
const long & getForwardedCount() const
Returns the number of Data packets forwarded by the entire network.
virtual void clearHops()
Clears all the route information of the current node.
double probe_min_snr_
Value below which if a node receives a probe it discards it.
static const int getDataPktHeaderSize()
Returns the size in byte of a hdr_sun_data packet header.
nsaddr_t * hop_table
List of IPs to reach the sink.
int disable_path_error_
Flag to enable or disable the possibility to send Path Error packets.
std::map< uint8_t, uint > paths_selected
Map containing the nodes selected as relay to the sink and the number of times each node was selected...
bool trace_
Flag used to enable or disable the trace file for nodes,.
static long number_of_ackpkt_
Comulative number of Ack packets processed by SunIPRoutingNode objects.
virtual const int & getNumberOfHopToSink() const
Returns the number of hops that separate the node to the sink.
static nsaddr_t str2addr(const char *)
Returns a nsaddr_t address from an IP written as a string in the form "x.x.x.x".
virtual void updatePacketsCount()
Updates the number of packets processed by the current node.
virtual const int & evaluatePath(const Packet *)
Evaluates the route information contained in a Path Establishment packet, and according to different ...
const long & getDataDropsCountBuffer() const
Returns the number of packets dropped by the entire network for the reason: buffer is full.
int hop_table_length
Current length of the hop_table.
SinkProbeTimer sinkProbeTimer_
SinkProbeTimer object.
virtual void expTimerHopTable()
This function is invoked when the timer of the routing table expires.
int data_and_hops[MAX_HOP_NUMBER]
Structure that contains the number of data packets sent by the current node to the sink,...
virtual void sendRouteBack(Packet *)
Forwards a Path Establishment Answer Packet.
ofstream trace_file_
Ofstream used to write the trace file in the disk.
char * trace_file_name_
Name of the trace file writter for the current node.
virtual string createTraceString(const string &, const double &, const int &, const int &, const int &, const int &, const int &, const int &, const int &, const double &, const int &, const int &)
Function that accepts a list of string and create an entry for the trace file.
int reset_buffer_if_error_
If == 1 when a node identify a broken link it will automatically free its buffer.
static long number_of_pathestablishment_
Comulative number of Path Establishment packets processed by SunIPRoutingNode objects.
double snr_to_sink_
SNR between the sink and the current node.
static long number_of_pkt_forwarded_
Comulative number of Data packets forwarded by the network.
double period_status_
Period of the Poisson traffic for status and ack packets.
BufferTimer bufferTmr_
BufferTimer object.
nsaddr_t sink_associated
IP of the sink associated to the node.
virtual void updateAcksCount()
Updates the number of acks received by the current node.
static const int getPathEstHeaderSize()
Returns the size in byte of a hdr_sun_path_est packet header.
double timer_buffer_
Timer for buffer management.
virtual void receiveProbe(const Packet *)
Invoked when the node receives a probe packet from a sink.
virtual const int & setNumberOfHopToSink(const int &)
Sets the number of hops that the current node needs to reach the sink.
double period_data_
Period of the Poisson traffic for data packets in the buffer.
virtual void sendBackAck(const Packet *)
Creates an ack packet and sends it to the previous hop using the information contained in the header ...
double alpha_
Parameters used by Load metric.
SearchPathTimer searchPathTmr_
SearchPathTimer object.
SunIPRoutingNode()
Constructor of SunIPRoutingNode class.
bool ack_error_state
true if the node is not in an error state (that means that it discovered a broken link),...
const long & getDataCount() const
Returns the number of Data packets processed by the entire network.
int PoissonTraffic_
Enable (1) or disable (0) the Poisson traffic for SUN packets.
static const int getAckHeaderSize()
Returns the size in byte of a hdr_sun_ack packet header.
const long & getAckCount() const
Returns the number of Ack packets processed by the entire network.
double quality_link
Quality of the link from the node to the sink.
virtual void lostSink()
This function removes all the information about routing information and sink association.
virtual void searchPath()
Sends a Path Establishment Packet with the option field sets to Search.
const long & getDataDropsCountMaxRetx() const
Returns the number of packets dropped by the entire network for the reason: maximum number of retrans...
uint32_t buffer_max_size_
Maximum length of the data buffer.
virtual void printHopTable() const
Prints in the stdout the routing table of the current node.
virtual int recvSyncClMsg(ClMessage *)
Cross-Layer messages synchronous interpreter.
int ack_warnings_counter_
Number of acks lost since the last reset.
int max_ack_error_
Maximum number of Ack errors tollerated by the node.
virtual void searchPathExpire()
This function enable the possibility to send a new Seath Path packet.
int printDebug_
Flag to enable or disable dirrefent levels of debug.
virtual void sendRouteErrorBack(Packet *)
Send back an error packet to the previous hop.
virtual ~SunIPRoutingNode()
Destructor of SunIPRoutingNode class.
long pkt_stored_
Keep track of the total number of packet transmitted.
virtual void initialize()
Initializes a SunIPRoutingNode node.
static long number_of_drops_buffer_full_
Comulative number of packets dropped by SunIPRoutingNode objects, reason: the buffer is full.
virtual void tracePacket(const Packet *const, const string &position="UNDEF___")
Traces a packet.
nsaddr_t ipAddr_
IP of the current node.
int metrics_
Metric used by the current node.
virtual int recvAsyncClMsg(ClMessage *)
Cross-Layer messages asynchronous interpreter.
long pkt_tx_
Keep track of the total number of packet retransmitted.
double timer_search_path_
Timer for the search path mechanism.
virtual void recv(Packet *)
Performs the reception of packets from upper and lower layers.
static long number_of_drops_maxretx_
Comulative number of packets dropped by SunIPRoutingNode objects, reason: max number of retransmissio...
const bool isZero(const double &value) const
Evaluates is the number passed as input is equal to zero.
int num_hop_to_sink
Number of hops needed to reach the sink using tha path saved tn the routing table.
int safe_timer_buffer_
Enables a mechanism used to modify the timer_buffer_ in case of the sending time is shorter than the ...
Adds the module for SunIPRoutingNode in ns2.
TclObject * create(int, const char *const *)
Class that manages cross layer messages that require the IP of the node.
Definition uwip-clmsg.h:57
Class used to answer to UWIPClMsgReqAddr cross layer messages.
Definition uwip-clmsg.h:68
nsaddr_t getAddr()
buffer_element describes an entry in the buffer used by SUN.
hdr_sun_ack describes acks packets used by UWSUN.
Definition sun-hdr-ack.h:52
hdr_sun_data describes data packets used by UWSUN
hdr_sun_path_est describes path establishment packets used by UWSUN
hdr_uwcbr describes UWCBR packets.
hdr_uwip describes UWIP packets.
Definition uwip-module.h:70
uint8_t & daddr()
Reference to the daddr_ variable.
uint8_t & saddr()
Reference to the saddr_ variable.
Definition uwip-module.h:95
#define HDR_SUN_ACK(p)
Definition sun-hdr-ack.h:45
#define HDR_SUN_DATA(p)
#define PATH_SEARCH
#define PATH_ERROR
#define PATH_ANSWER
#define HDR_SUN_PATH_EST(p)
#define DROP_BUFFER_IS_FULL
Reason for a drop in a UWSUN module.
#define DROP_PACKET_NOT_FOR_ME
Reason for a drop in a UWSUN module.
#define STACK_TRACE
Used to keep track of methods call.
#define DROP_PACKET_WITHOUT_DIRECTION
Reason for a drop in a UWSUN module.
SunNodeModuleClass class_module_sun_node
Dinamic source routing protocol, this file contains Nodes specifications.
#define HDR_UWCBR(p)
static const int MAX_HOP_NUMBER
Maximum number of hops contained in a SUN Path Establishment packet.
static const uint8_t UWIP_BROADCAST
Variable used to represent a broadcast UWIP.
Definition uwip-module.h:62
#define HDR_UWIP(P)
Definition uwip-module.h:58