DESERT 3.5.1
Loading...
Searching...
No Matches
uwmulti-multiphy-controller.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2014 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
39#include "uwmulti-cmn-hdr.h"
40#include <mphy_pktheader.h>
41#include "mac.h"
42#include "ip.h"
43#include <mmac-clmsg.h>
44#include <uwip-clmsg.h>
45#include <algorithm>
46#include <clmsg-discovery.h>
47
48extern packet_t PT_UWCBR;
49
51{
52 this->debug_ = 0;
53}
54
56{
57 this->debug_ = debug_;
58}
59
61{
62 this->customPriorities[c] = priority;
63}
64
65void PriorityMap::setDefaultPriority(int macID, int priority)
66{
67 this->defaultPriorities[macID] = priority;
68}
69
71{
72 // if connection is specified in custom settings
73 if ( this->customPriorities.find(c) != this->customPriorities.end() ) {
74 return this->customPriorities[c];
75 }
76 // if connection is in default priorities
77 if ( this->defaultPriorities.find(c.localMacID) != this->defaultPriorities.end() ) {
78 return this->defaultPriorities[c.localMacID];
79 }
80
81 // if no priority is available, return the "NULL" priority
82 return -1;
83}
84
85ostream& operator<< (ostream& os, const PriorityMap& obj) {
86 os << "<PriorityMap(debug_=" << obj.debug_ << ", ";
87
88 os << "defaultPriorities={";
89 for (std::map<int, int>::const_iterator it = obj.defaultPriorities.begin();
90 it != obj.defaultPriorities.end();
91 it++)
92 {
93 os << it->first << ": " << it->second << ", ";
94 }
95 os << "}, ";
96
97 os << "customPriorities={";
98 for (std::map<LocalConnection, int>::const_iterator it = obj.customPriorities.begin();
99 it != obj.customPriorities.end();
100 it++)
101 {
102 os << it->first << ": " << it->second << ", ";
103 }
104 os << "})>";
105 return os;
106}
107
111static class UwMultiPhyControlClass : public TclClass
112{
113public:
117 UwMultiPhyControlClass() : TclClass("Module/UW/MULTIPHY_CONTROLLER") {}
122 TclObject* create(int, const char*const*)
123 {
124 return (new UwMultiPhyControl);
125 }
127
129 :
130 Module(),
131 debug_(0)
132{
133 bind("debug_", &debug_);
135}
136
137int UwMultiPhyControl::command(int argc, const char*const* argv)
138{
139 Tcl& tcl = Tcl::instance();
140
141 if (argc == 2) {
142
143 if(strcasecmp(argv[1], "initialize") == 0) {
144 this->initialize();
145 return TCL_OK;
146 }
147
148 } else if (argc == 4) {
149
150 if(strcasecmp(argv[1], "setResilienceTimeout") == 0) {
151 // retrieve mac ID given Tcl name
152 int tclId = atoi(argv[2]);
153 int macID = this->macTclIdLayerId[tclId];
154
155 double timeout = atof(argv[3]);
156
157 this->resilienceTimeouts[macID] = timeout;
158 return TCL_OK;
159 }
160
161 if(strcasecmp(argv[1], "setProbeTimeout") == 0) {
162 // retrieve mac ID given Tcl name
163 int tclId = atoi(argv[2]);
164 int macID = this->macTclIdLayerId[tclId];
165
166 double timeout = atof(argv[3]);
167
168 this->probeTimeouts[macID] = timeout;
169 return TCL_OK;
170 }
171
172 if(strcasecmp(argv[1], "setMacResilience") == 0)
173 {
174 // retrieve mac ID given Tcl name
175 int tclId = atoi(argv[2]);
176 int macID = this->macTclIdLayerId[tclId];
177
178 int score = atoi(argv[3]);
179
180 this->macResilience[macID] = score;
181 return TCL_OK;
182 }
183
184 if(strcasecmp(argv[1], "setDefaultPriority") == 0) {
185 // retrieve mac ID given Tcl name
186 int tclId = atoi(argv[2]);
187 int macID = this->macTclIdLayerId[tclId];
188
189 int priority = atoi(argv[3]);
190
191 this->priorityMap.setDefaultPriority(macID, priority);
192 return TCL_OK;
193 }
194
195 if(strcasecmp(argv[1], "getBestMac") == 0) {
196 int remoteIP = atoi(argv[2]);
197 int trafficType = atoi(argv[3]);
198 int bestMacID = this->getBestMacID(trafficType, remoteIP);
199
200 tcl.resultf("%d", bestMacID);
201
202 return TCL_OK;
203 }
204 } else if (argc == 5) {
205
206 if(strcasecmp(argv[1], "addCustomPriority") == 0) {
207 // retrieve mac ID given Tcl name
208 int tclId = atoi(argv[2]);
209
211 c.localMacID = this->macTclIdLayerId[tclId];
212 c.trafficType = atoi(argv[3]);
213
214 int priority = atoi(argv[4]);
215
216 this->priorityMap.addCustomPriority(c, priority);
217 return TCL_OK;
218 }
219 }
220
221 return Module::command(argc, argv);
222}
223
225{
226 // send discovery ctrl message down
227 ClMsgDiscovery m;
228 m.addSenderData((const PlugIn*) this, getLayer(), getId(), getStackId(), name() , getTag());
229 this->sendSyncClMsgDown(&m);
230 DiscoveryStorage a = m.copyStorage();
231
232 if (debug_ >= 2) {
233 m.printReplyData();
234 }
235
236 for (DBIt it=a.begin(); it!=a.end(); it++) {
237 int id = it->first;
238 int layerId = it->second.getId();
239
240 // unwanted layer (current one probably)
241 if (id == 0) continue;
242
243 // save retrieved information
244 this->macIDs.push_back(layerId);
245
246 // TODO check the one used in recv
247 this->macTclIdLayerId[id] = layerId;
248
249 if (debug_) {
250 std::cout << "UwMultiPhyControl::initialize::tclId(" << id << ")"
251 << "::layerId(" << layerId << ")" << std::endl;
252 }
253 }
254
255 // retrieve and store local IP address
257 this->sendSyncClMsg(&msg);
258 this->localIP = msg.getAddr();
259 if (debug_) {
260 std::cout << "UwMultiPhyControl::initialize::localIP(" << this->localIP << ")" << std::endl;
261 }
262}
263
265{
266 std::cerr << "UwMultiPhyControl: a Packet is received without source module ID" << std::endl;
267 Packet::free(p);
268}
269
270void UwMultiPhyControl::recv(Packet* p, int idSrc)
271{
272 hdr_cmn *ch = HDR_CMN(p);
273
274 if (ch->direction() == hdr_cmn::DOWN) {
275 // create a timer in preparation for the first packet retransmission
276 this->recvFromUpperLayers(p);
277 }
278 else {
279 this->recvFromLowerLayers(p, idSrc);
280 }
281}
282
284{
285 hdr_uwip* uwip = HDR_UWIP(p);
286 hdr_cmn* cmn = HDR_CMN(p);
287
288 int dst_ip = uwip->daddr();
289
291 c.remoteIP = uwip->saddr();
292 c.localMacID = macID;
293
294 if (debug_) {
295 std::cout << NOW
296 << "::UwMultiPhyControl::recvFromLowerLayers"
297 << "::localIP(" << this->localIP << ")"
298 << "::localMAC(" << macID << ")"
299 << "::remoteIP(" << c.remoteIP << ")"
300 << "::destIP(" << dst_ip << ")"
301 << "::pktType(" << printType(cmn->ptype()) << ")"
302 // << "::trafficType(" << cbr->trafficType() << ")"
303 << std::endl;
304 }
305
306 // update availability and trigger its timeout
307 // always, even for packets not for this node
308 this->updateAvailability(c, LINK_OK);
309
310 // send up only if data
311 if (cmn->ptype() == PT_UWMULTIPHY_DATA) {
312 // UWIP layer will
313 // 1) reject packets sent for others
314 // 2) route packets to right application
315
316 // reset proper UWCBR type
317 cmn->ptype() = PT_UWCBR;
318 this->sendUp(p);
319 }
320
321 // link is alive: send corresponding packets in queue, if any
322 bool packet_sent = false;
323 unsigned int n_stored_packets = this->packet_queue.size();
324 for (unsigned int i = 0; i < n_stored_packets; i++) {
325 Packet* stored_p = this->packet_queue.front();
326 this->packet_queue.pop();
327 hdr_uwip* stored_uwip = HDR_UWIP(stored_p);
328
329 if (stored_uwip->daddr() == c.remoteIP) {
330 // process them as if they were a new packet
331 this->recvFromUpperLayers(stored_p);
332 packet_sent = true;
333 }
334 else {
335 // put it again in queue
336 this->packet_queue.push(stored_p);
337 }
338 }
339
340 // answer with PONG only if it is for us and no DATA were sent in previous
341 // queue scan
342 if (!packet_sent &&
343 cmn->ptype() == PT_UWMULTIPHY_PING &&
344 uwip->daddr() == this->localIP) {
345
346 Packet* pongPacket = Packet::alloc();
347
348 // set PONG packet type
349 hdr_cmn* pongCmn = HDR_CMN(pongPacket);
350 pongCmn->ptype() = PT_UWMULTIPHY_PONG;
351 pongCmn->size() = 2;
352
353 // set destination and source address (current node one)
354 hdr_uwip* pongIp = HDR_UWIP(pongPacket);
355
356 pongIp->saddr() = this->localIP;
357 pongIp->daddr() = c.remoteIP;
358
359 Packet::free(p);
360
361 // this triggers errors: lower layer IDs are not the right ones
362 this->sendDown(c.localMacID, pongPacket);
363
364 if (debug_) {
365 std::cout << NOW
366 << "::UwMultiPhyControl::sendPong"
367 << "::localIP(" << this->localIP << ")"
368 << "::localMAC(" << c.localMacID << ")"
369 << "::remoteIP(" << c.remoteIP << ")"
370 << "::pktType(" << printType(pongCmn->ptype()) << ")"
371 << std::endl;
372 }
373 }
374}
375
377{
378 hdr_uwip* uwip = HDR_UWIP(p);
379 hdr_cmn* cmn = HDR_CMN(p);
380 hdr_uwcbr* uwcbr = HDR_UWCBR(p);
381
382 // set packet as data
383 cmn->ptype() = PT_UWMULTIPHY_DATA;
384
385 // find connection to send packet into
386 int trafficType = uwcbr->traffic_type();
387 int remoteIP = uwip->daddr();
388
389 if (debug_) {
390 std::cout << NOW
391 << "::UwMultiPhyControl::recvFromUpperLayers"
392 << "::pktID(" << HDR_CMN(p)->uid_ << ")"
393 << "::localIP(" << this->localIP << ")"
394 << "::remoteIP(" << remoteIP << ")"
395 << "::pktType(" << printType(cmn->ptype()) << ")"
396 << "::trafficType(" << trafficType << ")"
397 << std::endl;
398 }
399
400 int bestMacID = this->getBestMacID(trafficType, remoteIP);
401
402 // if valid mac was found, proceed
403 if (bestMacID != -1) {
404 this->sendDown(bestMacID, p);
405
406 if (debug_) {
407 std::cout << NOW
408 << "::UwMultiPhyControl::sendDown"
409 << "::localIP(" << this->localIP << ")"
410 << "::localMAC(" << bestMacID << ")"
411 << "::remoteIP(" << remoteIP << ")"
412 << "::pktType(" << printType(cmn->ptype()) << ")"
413 << std::endl;
414 }
415
416 } else {
417 // send PINGs trying to reach remote node
418 for (uint i=0; i < this->macIDs.size(); i++) {
420 c.localMacID = this->macIDs[i];
421 c.remoteIP = remoteIP;
422
423 if (this->linkStatuses[c] == LINK_UNKNOWN) {
424 this->sendPing(c);
425 }
426 }
427
428 // put packet in queue, waiting for a PONG
429 this->packet_queue.push(p);
430 }
431}
432
434 // this should not be called unless link condition is UNKNOWN
435 if (this->linkStatuses[c] != LINK_UNKNOWN) {
436 std::cerr << NOW
437 << "::UwMultiPhyControl::sendPing"
438 << "::localIP(" << this->localIP << ")"
439 << "::remoteIP(" << c.remoteIP << ")"
440 << "::localMAC(" << c.localMacID << ")"
441 << "::(ping to be sent while in " << this->linkStatuses[c] << ")"
442 << std::endl;
443 return;
444 }
445
446 this->linkStatuses[c] = LINK_PROBING;
447
448 // send ping packet
449 Packet* pingPacket = Packet::alloc();
450
451 hdr_cmn* ch = HDR_CMN(pingPacket);
452 ch->ptype() = PT_UWMULTIPHY_PING;
453 // check good value: this one comes from module TCL defaults
454 ch->size() = 2;
455
456 // set destination and source address (current node one)
457 hdr_uwip* pingIPHeader = HDR_UWIP(pingPacket);
458
459 pingIPHeader->saddr() = this->localIP;
460 pingIPHeader->daddr() = c.remoteIP;
461
462 if (debug_) {
463 std::cout << NOW
464 << "::UwMultiPhyControl::sendPing"
465 << "::localIP(" << this->localIP << ")"
466 << "::localMAC(" << c.localMacID << ")"
467 << "::remoteIP(" << c.remoteIP << ")"
468 << "::pktType(" << printType(ch->ptype()) << ")"
469 << std::endl;
470 }
471
472 this->sendDown(c.localMacID, pingPacket);
473
474 // ensure the requested timer exists
475 if ( this->probeTimers.find(c) == this->probeTimers.end() ) {
476 this->probeTimers[c] = ProbeTimer(this, c);
477 }
478
479 double probeTimeout = this->probeTimeouts[c.localMacID];
480 this->probeTimers[c].resched(probeTimeout);
481}
482
484{
485 if (debug_) {
486 std::cout << NOW << "::"
487 <<"UwMultiPhyControl::updateAvailability"
488 << "::localIP(" << this->localIP << ")"
489 << "::localMAC(" << c.localMacID << ")"
490 << "::remoteIP(" << c.remoteIP << ")"
491 << "::new status " << status << std::endl;
492 }
493
494 if (status == LINK_OK) {
495 //Reset PROBE timers if a packet is received from that connection
496 if (this->linkStatuses[c] == LINK_PROBING) {
497 if (this->probeTimers.find(c) != this->probeTimers.end()) {
498 this->probeTimers[c].force_cancel();
499 if (debug_) {
500 std::cout << NOW << "::"
501 << "UwMultiPhyControl::updateAvailability"
502 << "::localIP(" << this->localIP << ")"
503 << "::localMAC(" << c.localMacID << ")"
504 << "::remoteIP(" << c.remoteIP << ")"
505 << "::Reset probe timer" << std::endl;
506 }
507 }
508 }
509
510 this->linkStatuses[c] = LINK_OK;
511
512 if ( this->resilienceTimers.find(c) == this->resilienceTimers.end() ) {
513 this->resilienceTimers[c] = ResilienceTimer(this, c);
514 }
515
516 double timeout = resilienceTimeouts[c.localMacID];
517 this->resilienceTimers[c].resched(timeout);
518 }
519 else {
520 this->linkStatuses[c] = status;
521 }
522}
523
524int UwMultiPhyControl::getBestMacID(int trafficType, int remoteIP)
525{
526 int bestMAC = -1;
527 int bestPriority = -1;
528
529 for (uint i=0; i < this->macIDs.size(); i++) {
530 int macID = macIDs[i];
531
532 // build the two connections
533 LocalConnection localConn;
534 localConn.localMacID = macID;
535 localConn.trafficType = trafficType;
536
537 RemoteConnection remoteConn;
538 remoteConn.localMacID = macID;
539 remoteConn.remoteIP = remoteIP;
540
541 // pick the most prioritary MAC that can reach the destination
542 if (this->linkStatuses[remoteConn] == LINK_OK) {
543 int currentPriority = this->priorityMap.getPriority(localConn);
544 if (currentPriority > bestPriority) {
545 bestMAC = macID;
546 bestPriority = currentPriority;
547 }
548 }
549 }
550
551 return bestMAC;
552}
553
555{
556 if (this->module == NULL) {
557 return;
558 }
559
560 if (this->module->debug_) {
561 std::cout << NOW
562 << "::UwMultiPhyControl::ResilienceTimer::Expire"
563 << "::localIP(" << this->module->localIP << ")"
564 << "::localMAC(" << this->conn.localMacID << ")"
565 << "::remoteIP(" << this->conn.remoteIP << ")"
566 << std::endl;
567 }
568 this->module->updateAvailability(this->conn, LINK_UNKNOWN);
569}
570
572{
573 if (this->module == NULL) {
574 return;
575 }
576
577 if (this->module->debug_) {
578 std::cout << NOW
579 << "::UwMultiPhyControl::ProbeTimer::Expire"
580 << "::localIP(" << this->module->localIP << ")"
581 << "::localMAC(" << this->conn.localMacID << ")"
582 << "::remoteIP(" << this->conn.remoteIP << ")"
583 << std::endl;
584 }
585
586 this->module->linkStatuses[this->conn] = LINK_UNKNOWN;
587 this->module->sendPing(this->conn);
588}
std::map< int, int > defaultPriorities
void addCustomPriority(LocalConnection c, int priority)
Set MAC priority for packets coming from a specific traffic type.
int getPriority(LocalConnection c)
Get priority of a certain MAC for packets of given traffic type (using default priority if a custom o...
std::map< LocalConnection, int > customPriorities
void setDefaultPriority(int macID, int priority)
Set MAC default priority regardless of origin traffic type.
Class used to answer to UWIPClMsgReqAddr cross layer messages.
Definition uwip-clmsg.h:68
nsaddr_t getAddr()
Class that represents the binding with the tcl configuration script.
TclObject * create(int, const char *const *)
Creates the TCL object needed for the tcl language interpretation.
UwMultiPhyControlClass()
Constructor of the class.
virtual void expire(Event *e)
Timer expire procedure: handles the PROBE timeout.
virtual void expire(Event *e)
Timer expire procedure: handles the PROBE timeout.
Class used to represents the UwMultiPhyControl layer of a node.
std::map< RemoteConnection, ResilienceTimer > resilienceTimers
UwMultiPhyControl()
Constructor of UwMultiPhy class.
std::map< RemoteConnection, int > linkStatuses
std::map< int, double > resilienceTimeouts
std::queue< Packet * > packet_queue
std::map< int, int > macTclIdLayerId
int getBestMacID(int trafficType, int remoteIP)
void updateAvailability(RemoteConnection c, LinkStatus status)
std::map< RemoteConnection, ProbeTimer > probeTimers
void sendPing(RemoteConnection c)
virtual int command(int, const char *const *)
void recvFromLowerLayers(Packet *p, int macID)
std::map< int, double > probeTimeouts
std::map< int, int > macResilience
<macID, resilience> where resilience score enstablish an order across local MAC layers: if a less rob...
hdr_uwcbr describes UWCBR packets.
uint16_t & traffic_type()
Reference to the rftt_ variable.
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_UWCBR(p)
Cross layer messages definition for the UWIP Module.
#define HDR_UWIP(P)
Definition uwip-module.h:58
ostream & operator<<(ostream &os, const PriorityMap &obj)
UwMultiPhyControlClass class_stack_controller
Definition of UwMultiPhyControl class.
std::string printType(packet_t ptype)