Wiselib
|
00001 /*************************************************************************** 00002 ** This file is part of the generic algorithm library Wiselib. ** 00003 ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project. ** 00004 ** ** 00005 ** The Wiselib is free software: you can redistribute it and/or modify ** 00006 ** it under the terms of the GNU Lesser General Public License as ** 00007 ** published by the Free Software Foundation, either version 3 of the ** 00008 ** License, or (at your option) any later version. ** 00009 ** ** 00010 ** The Wiselib is distributed in the hope that it will be useful, ** 00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 00013 ** GNU Lesser General Public License for more details. ** 00014 ** ** 00015 ** You should have received a copy of the GNU Lesser General Public ** 00016 ** License along with the Wiselib. ** 00017 ** If not, see <http://www.gnu.org/licenses/>. ** 00018 ***************************************************************************/ 00019 #ifndef __ALGORITHMS_ROUTING_DYMO_ROUTING_H__ 00020 #define __ALGORITHMS_ROUTING_DYMO_ROUTING_H__ 00021 00022 #include "/home/zhongliang/project/WISEBED/wiselib/trunk/wiselib.incubation/routing/dymo/dymo_routing_types.h" 00023 #include "/home/zhongliang/project/WISEBED/wiselib/trunk/wiselib.incubation/routing/dymo/dymo_route_discovery_msg.h" 00024 #include "/home/zhongliang/project/WISEBED/wiselib/trunk/wiselib.incubation/routing/dymo/dymo_routing_msg.h" 00025 #include "util/base_classes/routing_base.h" 00026 #include <string.h> 00027 #include "util/pstl/list_static.h" 00028 #include "util/pstl/list_dynamic.h" 00029 #include "util/pstl/map_list.h" 00030 #include "util/pstl/map_static_vector.h" 00031 00032 #undef DEBUG 00033 //#define DEBUG 00034 00035 #define NET_DIAM 10 00036 #define ROUTE_TIMEOUT 2 *NET_DIAM 00037 00038 #define ECHO_INTERVAL 2 00039 #define ALLOWED_LOSS ECHO_INTERVAL * 2 00040 00041 00042 #define RETRY_INTERVAL NET_DIAM * 2 00043 #define MAX_RETRIES 1 00044 using namespace std; 00045 namespace wiselib { 00046 00055 template<typename OsModel_P, 00056 typename RoutingTable_P, 00057 typename Radio_P = typename OsModel_P::Radio, 00058 typename Debug_P = typename OsModel_P::Debug> 00059 class DYMORouting 00060 : public RoutingBase<OsModel_P, Radio_P> { 00061 public: 00062 typedef OsModel_P OsModel; 00063 typedef Radio_P Radio; 00064 typedef Debug_P Debug; 00065 00066 typedef typename OsModel_P::Timer Timer; 00067 00068 typedef RoutingTable_P RoutingTable; 00069 typedef typename RoutingTable::iterator RoutingTableIterator; 00070 typedef typename RoutingTable::mapped_type RoutingTableValue; 00071 typedef typename RoutingTable::value_type RoutingTableEntry; 00072 typedef typename RoutingTableValue::Path Path; 00073 00074 enum { 00075 MAX_PATH_LENGTH = RoutingTableValue::MAX_PATH_LENGTH 00076 }; 00077 00078 typedef DYMORouting<OsModel, RoutingTable, Radio, Debug> self_type; 00079 00080 typedef typename Radio::node_id_t node_id_t; 00081 typedef typename Radio::size_t size_t; 00082 typedef typename Radio::block_data_t block_data_t; 00083 00084 typedef typename Timer::millis_t millis_t; 00085 00086 typedef DYMORouteDiscoveryMessage<OsModel, Radio, Path> RouteDiscoveryMessage; 00087 //typedef map<uint8_t, RouteDiscoveryMessage> pending_msgs_t; 00088 typedef wiselib::MapStaticVector<OsModel,uint8_t, RouteDiscoveryMessage, 10> pending_msgs_t; 00089 00090 //typedef DYMORouting 00091 // -------------------------------------------------------------------- 00092 enum SpecialNodeIds { 00093 BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 00094 NULL_NODE_ID = Radio_P::NULL_NODE_ID 00095 }; 00096 // -------------------------------------------------------------------- 00097 enum Restrictions { 00098 MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH - RouteDiscoveryMessage::PAYLOAD_POS 00099 }; 00100 // -------------------------------------------------------------------- 00103 DYMORouting(); 00104 ~DYMORouting(); 00106 00109 void enable_radio(void); 00110 void disable_radio(void); 00112 00115 void timer_elapsed(void *userdata); 00117 00120 00122 void send( node_id_t receiver, size_t len, block_data_t *data ); 00125 void receive( node_id_t from, size_t len, block_data_t *data ); 00128 typename Radio::node_id_t id() 00129 { 00130 return radio_->id(); 00131 }; 00133 00134 void proc_rreq(node_id_t from, RouteDiscoveryMessage& message); 00135 void proc_rrep(node_id_t from, RouteDiscoveryMessage& message); 00136 void proc_err(node_id_t from, RouteDiscoveryMessage& message); 00137 void proc_data(node_id_t from, RouteDiscoveryMessage& message); 00138 bool route_exists(node_id_t destination); 00139 void check_pending_messages(uint16_t destination); 00140 void table_cleanup(); 00141 void init_path_disc(); 00142 void resend_rreq(uint16_t dest); 00143 00144 00145 void pend_dest_cleanup(); 00146 00147 void neighbors_cleanup(); 00148 00149 void init( Radio& radio, Timer& timer, Debug& debug ) { 00150 radio_ = &radio; 00151 timer_ = &timer; 00152 debug_ = &debug; 00153 } 00154 00155 void destruct() { 00156 } 00157 00158 private: 00159 Radio& radio() 00160 { return *radio_; } 00161 00162 Timer& timer() 00163 { return *timer_; } 00164 00165 Debug& debug() 00166 { return *debug_; } 00167 00168 Radio * radio_; 00169 Timer * timer_; 00170 Debug * debug_; 00171 00172 uint16_t my_seq_nr_; 00173 uint16_t my_bcast_id_; 00174 //map<uint16_t, uint16_t> seq_numbers_; 00175 typename wiselib::MapStaticVector<OsModel,uint16_t, uint16_t, 10> seq_numbers_; 00176 00177 pending_msgs_t pending_msgs_; 00178 00179 struct rreq_info { 00180 uint8_t source; 00181 uint8_t bcast_id; 00182 }; 00183 00184 bool route_found; 00185 00186 //list<struct rreq_info> received_rreq_; //define a list called "received_rreq_" 00187 typename wiselib::list_static<OsModel,struct rreq_info, 10> received_rreq_; 00188 //typename list<struct rreq_info>::iterator rreq_iter_; //define an iterator of list consisting of "struct rreq_info" 00189 typedef typename wiselib::list_static<OsModel,struct rreq_info, 10>::iterator rreq_iter_; 00190 rreq_iter_ rreq_iter; 00191 00192 00193 typename pending_msgs_t::iterator pend_iter_; 00194 00195 //map<uint16_t, uint8_t> neighbors_; 00196 typename wiselib::MapStaticVector<OsModel,uint16_t, uint8_t, 10> neighbors_; 00197 //typedef typename map<uint16_t, uint8_t>::iterator neighbors_iter_; 00198 typedef typename wiselib::MapStaticVector<OsModel,uint16_t, uint8_t, 10>::iterator neighbors_iter_; 00199 00200 struct retry_info { 00201 uint8_t retries; 00202 uint8_t time; 00203 00204 }; 00205 00206 //map<uint16_t, struct retry_info> pend_dests_; 00207 typename wiselib::MapStaticVector<OsModel,uint16_t, struct retry_info, 10> pend_dests_; 00208 //typedef typename map<uint16_t, struct retry_info>::iterator pend_dests_iter_; 00209 typedef typename wiselib::MapStaticVector<OsModel,uint16_t, struct retry_info, 10>::iterator pend_dests_iter_; 00210 00211 00212 short seconds; 00213 int rounds; 00214 00215 RoutingTable routing_table_; 00216 }; 00217 // ----------------------------------------------------------------------- 00218 // ----------------------------------------------------------------------- 00219 // ----------------------------------------------------------------------- 00220 // ----------------------------------------------------------------------- 00221 // ----------------------------------------------------------------------- 00222 00223 00224 00225 template<typename OsModel_P, 00226 typename RoutingTable_P, 00227 typename Radio_P, 00228 typename Debug_P> 00229 void 00230 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00231 neighbors_cleanup(){ 00232 00233 //debug().debug(" %i is cleaning up tables\n",radio().id() ); 00234 neighbors_iter_ n_it; 00235 //neighbors_iter_ n_it; 00236 n_it = neighbors_.begin(); 00237 //it =routing_table_.end(); 00238 //entries = 0; 00239 while(n_it != neighbors_.end()){ 00240 //entries++; 00241 // decrease entry's lifetime and check if is stale 00242 00243 00244 if(n_it->second == 0)//debug().debug(" %i no longer neighbor with %i \n",radio().id(), n_it->first); 00245 { 00246 00247 neighbors_.erase( n_it - neighbors_.begin() ); 00248 //neighbors_.erase(n_it); 00249 if (n_it != neighbors_.end()) 00250 { 00251 break; 00252 } 00253 00254 00255 } 00256 else{ 00257 n_it->second -= 1; 00258 00259 } 00260 n_it++; 00261 } 00262 //debug().debug(" %i has %i entries \n",radio().id(),entries); 00263 00264 } 00265 00266 00267 00268 00269 template<typename OsModel_P, 00270 typename RoutingTable_P, 00271 typename Radio_P, 00272 typename Debug_P> 00273 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00274 DYMORouting() 00275 : my_seq_nr_(0), 00276 my_bcast_id_(0) 00277 {}; 00278 00279 00280 00281 // ----------------------------------------------------------------------- 00282 00283 template<typename OsModel_P, 00284 typename RoutingTable_P, 00285 typename Radio_P, 00286 typename Debug_P> 00287 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00288 ~DYMORouting() { 00289 #ifdef DEBUG 00290 debug().debug("DYMORouting Destroyed\n"); 00291 #endif 00292 }; 00293 // ----------------------------------------------------------------------- 00294 00295 template<typename OsModel_P, 00296 typename RoutingTable_P, 00297 typename Radio_P, 00298 typename Debug_P> 00299 void 00300 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00301 enable_radio(void) { 00302 #ifdef DEBUG 00303 debug().debug("DYMORouting Boots for %i\n", radio().id()); 00304 #endif 00305 my_seq_nr_ = 0; 00306 my_bcast_id_ = 0; 00307 seconds = 0; 00308 00309 rounds = 0; 00310 00311 radio().enable_radio(); 00312 radio().template reg_recv_callback<self_type, &self_type::receive > (this); 00313 00314 timer().template set_timer<self_type, &self_type::timer_elapsed > ( 00315 1000, this, 0); 00316 } 00317 00318 00319 // ----------------------------------------------------------------------- 00320 00321 template<typename OsModel_P, 00322 typename RoutingTable_P, 00323 typename Radio_P, 00324 typename Debug_P> 00325 void 00326 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00327 disable_radio(void) { 00328 #ifdef DEBUG 00329 debug().debug("Called DYMORouting::disable\n"); 00330 #endif 00331 } 00332 00333 00334 // ----------------------------------------------------------------------- 00335 00336 template<typename OsModel_P, 00337 typename RoutingTable_P, 00338 typename Radio_P, 00339 typename Debug_P> 00340 void 00341 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00342 timer_elapsed(void *userdata) { 00343 00344 // debug().debug(" %i setting\n ",radio().id()); 00345 seconds++; 00346 // debug().debug(" %i resetting 1\n %i",radio().id(), seconds); 00347 if( seconds == ECHO_INTERVAL ){ 00348 // debug().debug(" %i resetting2\n ",radio().id()); 00349 // debug().debug(" %iresetting3\n ",radio().id()); 00350 seconds = 0; 00351 // debug().debug(" %i resetting4\n ",radio().id()); 00352 } 00353 // clean up routing table 00354 // debug().debug(" %i table clean up ",radio().id()); 00355 table_cleanup(); 00356 // debug().debug(" done\n "); 00357 // clean up neighbors 00358 // debug().debug("%i neighbors ",radio().id()); 00359 neighbors_cleanup(); 00360 // debug().debug(" done\n "); 00361 // clean up pending destinations 00362 // debug().debug(" %i dest clean up ",radio().id()); 00363 pend_dest_cleanup(); 00364 // debug().debug(" done\n "); 00365 00366 //re-setting timer 00367 timer().template set_timer<self_type, &self_type::timer_elapsed > ( 00368 1000, this, 0); 00369 // debug().debug(" resetting\n "); 00370 } 00371 00372 00373 // ----------------------------------------------------------------------- 00374 00375 template<typename OsModel_P, 00376 typename RoutingTable_P, 00377 typename Radio_P, 00378 typename Debug_P> 00379 bool 00380 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00381 route_exists(node_id_t destination) { 00382 RoutingTableIterator it = routing_table_.find(destination); 00383 if (it != routing_table_.end()) { 00384 return true; 00385 } else 00386 return false; 00387 00388 }; 00389 00390 00391 // ----------------------------------------------------------------------- 00392 00393 template<typename OsModel_P, 00394 typename RoutingTable_P, 00395 typename Radio_P, 00396 typename Debug_P> 00397 void 00398 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00399 check_pending_messages(uint16_t destination) { 00400 pend_iter_ = pending_msgs_.find(destination); 00401 if (pend_iter_ != pending_msgs_.end()) { 00402 // debug().debug("%i has pending msg for %i \n", radio().id(), destination); 00403 00404 uint16_t next_hop = routing_table_[destination].next_hop; 00405 radio().send(next_hop, pend_iter_->second.buffer_size(), (uint8_t*) & pend_iter_->second); 00406 00407 // debug().debug("%i sent stored msg to %i.next hop[%i] \n", radio().id(), destination, next_hop); 00408 routing_table_[destination].lifetime = ROUTE_TIMEOUT; 00409 00410 00411 //remove saved msg 00412 } else { 00413 // debug().debug("%i no msg for %i \n", radio().id(), destination); 00414 00415 } 00416 00417 } 00418 00419 template<typename OsModel_P, 00420 typename RoutingTable_P, 00421 typename Radio_P, 00422 typename Debug_P> 00423 void 00424 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00425 resend_rreq(uint16_t dest){ 00426 if(pend_dests_[dest].retries > MAX_RETRIES){ 00427 debug().debug(" %i was unable to find route for %i \n",radio().id(), dest ); 00428 // TODO delete f 00429 00430 pend_dests_.erase(dest); 00431 00432 pending_msgs_.erase(dest); 00433 00434 00435 } 00436 else{ 00437 pend_dests_[dest].retries+=1; 00438 pend_dests_[dest].time = RETRY_INTERVAL; 00439 00440 00441 00442 RouteDiscoveryMessage message( 00443 DYMO_RREQ, /*msg type*/ 00444 ++my_bcast_id_, /*bcast id*/ 00445 0, /*hop count*/ 00446 ++my_seq_nr_, /*source seq*/ 00447 seq_numbers_[dest]/*destination seq*/, 00448 radio().id(), /*source*/ 00449 dest, /*destination*/ 00450 0/*next hop*/); 00451 00452 00453 radio().send(radio().BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*) & message); 00454 00455 // add my own rreq to received rreq's 00456 struct rreq_info own_rreq; 00457 own_rreq.source = radio().id(); 00458 own_rreq.bcast_id = my_bcast_id_; 00459 received_rreq_.push_back(own_rreq); 00460 00461 debug().debug("%i Resent DYMO_RREQ for %i \n", radio().id(), dest); 00462 00463 } 00464 00465 00466 } 00467 00468 00469 template<typename OsModel_P, 00470 typename RoutingTable_P, 00471 typename Radio_P, 00472 typename Debug_P> 00473 void 00474 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00475 pend_dest_cleanup(){ 00476 00477 //debug().debug(" %i is cleaning up tables\n",radio().id() ); 00478 pend_dests_iter_ p_it; 00479 //neighbors_iter_ n_it; 00480 p_it = pend_dests_.begin(); 00481 //it =routing_table_.end(); 00482 int entries = 0; 00483 while(p_it != pend_dests_.end()){ 00484 00485 if( p_it->second.time > 0){ 00486 p_it->second.time -= 1; 00487 } 00488 00489 //if(p_it->second.time == 0 && p_it->second.retries > 3) 00490 else if (p_it->second.time == 0) { 00491 00492 pend_dests_.erase( p_it - pend_dests_.begin() ); 00493 //pend_dests_.erase(*(p_it)); 00494 00495 pending_msgs_.erase(p_it->first); 00496 00497 if(p_it == pend_dests_.end()){ 00498 break; 00499 } 00500 00501 // resend_rreq(p_it->first); 00502 //debug().debug(" %i found no route for %i \n",radio().id(), p_it->first ); 00503 // TODO also remove from pending messages 00504 } 00505 00506 00507 else if(p_it->second.time == 0 && p_it->second.retries <= MAX_RETRIES){ 00508 resend_rreq(p_it->first); 00509 00510 } 00511 00512 // debug().debug(" %i : %i,%i \n",radio().id(), p_it->second.time ,p_it->second.retries ); 00513 00514 p_it++; 00515 } 00516 00517 00518 00519 00520 00521 } 00522 00523 00524 00525 // ----------------------------------------------------------------------- 00526 template<typename OsModel_P, 00527 typename RoutingTable_P, 00528 typename Radio_P, 00529 typename Debug_P> 00530 void 00531 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00532 table_cleanup(){ 00533 int entries=0; 00534 //debug().debug(" %i is cleaning up tables\n",radio().id() ); 00535 RoutingTableIterator it; 00536 it = routing_table_.begin(); 00537 //it =routing_table_.end(); 00538 entries = 0; 00539 while(it != routing_table_.end()){ 00540 entries++; 00541 // decrease entry's lifetime and check if is stale 00542 00543 00544 if(it->second.lifetime == 0){ 00545 //debug().debug(" %i delete's entry for %i lifetime:%i \n",radio().id(), it->second.destination,it->second.lifetime ); 00546 routing_table_.erase(it); 00547 if (it != routing_table_.end()){ 00548 break; 00549 } 00550 } 00551 else{ 00552 it->second.lifetime -= 1; 00553 00554 } 00555 it++; 00556 } 00557 //debug().debug(" %i has %i entries \n",radio().id(),entries); 00558 } 00559 00560 00561 // ----------------------------------------------------------------------- 00562 00563 template<typename OsModel_P, 00564 typename RoutingTable_P, 00565 typename Radio_P, 00566 typename Debug_P> 00567 void 00568 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00569 send(node_id_t destination, size_t len, block_data_t *data) { 00570 // check for path 00571 if (route_exists(destination)) { 00572 00573 // update ttl 00574 routing_table_[destination].lifetime = ROUTE_TIMEOUT; 00575 00576 // get next hop 00577 uint8_t next_hop = routing_table_[destination].next_hop; 00578 debug().debug("%i found route for %i. next hop:[%i] %i hops away\n", radio().id(), destination, next_hop,routing_table_[destination].hop_cnt); 00579 00580 RouteDiscoveryMessage encap_message( 00581 DYMO_DATA, /*msg type*/ 00582 0, /*bcast id*/ 00583 0, /*hop count*/ 00584 0, /*source seq*/ 00585 seq_numbers_[destination]/*destination seq*/, 00586 radio().id(), /*source*/ 00587 destination, /*destination*/ 00588 0/*next hop*/); 00589 // TODO do actual encapsulation :) 00590 00591 // forward data msg to next hop 00592 radio().send(next_hop, encap_message.buffer_size(), (uint8_t*) & encap_message); 00593 //update lifetime 00594 routing_table_[destination].lifetime = ROUTE_TIMEOUT; 00595 return; 00596 } else if (false/*destination is neighbor*/) { 00597 00598 RouteDiscoveryMessage encap_message( 00599 DYMO_DATA, /*msg type*/ 00600 0, /*bcast id*/ 00601 0, /*hop count*/ 00602 0, /*source seq*/ 00603 seq_numbers_[destination]/*destination seq*/, 00604 radio().id(), /*source*/ 00605 destination, /*destination*/ 00606 0/*next hop*/); 00607 // TODO do actual encapsulation :) 00608 00609 // forward data msg to next hop 00610 radio().send(destination, encap_message.buffer_size(), (uint8_t*) & encap_message); 00611 ; 00612 }// init path disc 00613 else { 00614 debug().debug("%i Starting path discovery \n", radio().id()); 00615 //block_data_t tmp[len]; 00616 //memcpy(tmp, data, len); 00617 00618 RouteDiscoveryMessage stored_message( 00619 DYMO_DATA, /*msg type*/ 00620 0, /*bcast id*/ 00621 0, /*hop count*/ 00622 0, /*source seq*/ 00623 seq_numbers_[destination]/*destination seq*/, 00624 radio().id(), /*source*/ 00625 destination, /*destination*/ 00626 0/*next hop*/); 00627 //TODO add actual data and timeout to this message 00628 00629 pending_msgs_[destination] = stored_message; 00630 // debug().debug("%i stored message %i to buffer \n", radio().id(), stored_message.msg_type()); 00631 00632 //TODO add new entry to pending_dest 00633 struct retry_info retry_entry; 00634 retry_entry.retries = 1; 00635 retry_entry.time = RETRY_INTERVAL; 00636 pend_dests_[destination] = retry_entry; 00637 00638 00639 RouteDiscoveryMessage message( 00640 DYMO_RREQ, /*msg type*/ 00641 ++my_bcast_id_, /*bcast id*/ 00642 0, /*hop count*/ 00643 ++my_seq_nr_, /*source seq*/ 00644 seq_numbers_[destination]/*destination seq*/, 00645 radio().id(), /*source*/ 00646 destination, /*destination*/ 00647 0/*next hop*/); 00648 00649 00650 radio().send(radio().BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*) & message); 00651 00652 // add my own rreq to received rreq's 00653 struct rreq_info own_rreq; 00654 own_rreq.source = radio().id(); 00655 own_rreq.bcast_id = my_bcast_id_; 00656 received_rreq_.push_back(own_rreq); 00657 00658 debug().debug("%i sent DYMO_RREQ for %i \n", radio().id(), destination); 00659 00660 } 00661 } 00662 00663 //--------------------------------------------------------------------- 00664 00665 template<typename OsModel_P, 00666 typename RoutingTable_P, 00667 typename Radio_P, 00668 typename Debug_P> 00669 void 00670 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00671 proc_data(node_id_t from, RouteDiscoveryMessage& message) { 00672 debug().debug("%i received DYMO_DATA message from %i \n", radio().id(), message.source()); 00673 // msg for me 00674 if (message.destination() == radio().id()) { 00675 debug().debug("%i got his DYMO_DATA message msg from %i \n", radio().id(), message.source()); 00676 00677 } // destination is my neighbor 00678 else if (false) { 00679 ; 00680 00681 } // i have route to destination 00682 else if (route_exists(message.destination())) { 00683 debug().debug("%i forwards DYMO_DATA message for %i. next hop [%i] %i hops away \n", radio().id(), message.destination(), routing_table_[message.destination()].next_hop, routing_table_[message.destination()].hop_cnt); 00684 //TODO update lifetime 00685 00686 00687 //forward message to next hop 00688 radio().send(routing_table_[message.destination()].next_hop, message.buffer_size(), (uint8_t*) & message); 00689 routing_table_[message.destination()].lifetime = ROUTE_TIMEOUT; 00690 } else { 00691 debug().debug("%i DYMO_ERROR: no route for \n", radio().id(), message.destination()); 00692 00693 } 00694 00695 } 00696 00697 00698 // ----------------------------------------------------------------------- 00699 00700 template<typename OsModel_P, 00701 typename RoutingTable_P, 00702 typename Radio_P, 00703 typename Debug_P> 00704 void 00705 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00706 proc_rreq(node_id_t from, RouteDiscoveryMessage& message) { 00707 //debug().debug("%i received DYMO_RREQ from: %i. src:%i dst:%i bcast:%i hops:%i\n", radio().id(), from, message.source(), message.destination(), message.bcast_id(),message.hop_cnt()); 00708 00709 // drop any reduntant messages 00710 for (rreq_iter = received_rreq_.begin(); rreq_iter != received_rreq_.end(); ++rreq_iter) { 00711 if ((*rreq_iter).source == message.source() 00712 && (*rreq_iter).bcast_id == message.bcast_id()) { 00713 //cout << "\t\t\tDROPPED\n"; 00714 return; 00715 } 00716 } 00717 00718 // Continue with rreq processing 00719 // Record highest seq num for destination 00720 if (message.source_sequence_nr() - seq_numbers_[message.source()] > 0) { 00721 seq_numbers_[message.source()] = message.source_sequence_nr(); 00722 } 00723 00724 // add rreq to received rreq's 00725 struct rreq_info tmp_info; 00726 tmp_info.source = message.source(); 00727 tmp_info.bcast_id = message.bcast_id(); 00728 //tmp_info.lifetime = INT_MAX; 00729 received_rreq_.push_back(tmp_info); 00730 00731 00732 // add REVERSE path entry 00733 RoutingTableValue value; 00734 00735 value.destination = message.source(); 00736 value.next_hop = from; 00737 value.hop_cnt = message.hop_cnt() + 1; 00738 value.dest_seq = message.destination_sequence_nr(); 00739 value.lifetime = ROUTE_TIMEOUT; 00740 routing_table_[message.source()] = value; 00741 00742 /* debug().debug("%i added route entry %i:%i:%i:%i \n", radio().id(), 00743 routing_table_[message.source()].destination, 00744 routing_table_[message.source()].next_hop, 00745 routing_table_[message.source()].hop_cnt, 00746 routing_table_[message.source()].lifetime);*/ 00747 00748 // check if there are any pending messages for newly added entry 00749 check_pending_messages(message.source()); 00750 00751 //check if i have route for this destination 00752 RoutingTableIterator it = routing_table_.find(message.destination()); 00753 if (it != routing_table_.end()) { 00754 debug().debug("%i found route for %i via %i, %i hops away\n", radio().id(), message.destination(), it->second.next_hop, it->second.hop_cnt); 00755 //debug().debug("%i route found.\n replying with DYMO_RREP to %i \n", radio().id(), message.source()); 00756 //send a route reply 00757 RouteDiscoveryMessage rrep_message( 00758 DYMO_RREP, /*msg type*/ 00759 0, /*bcast id*/ 00760 it->second.hop_cnt, /*hop cnt*/ 00761 seq_numbers_[message.source()], /* source seq nr*/ 00762 0/* dest seq nr*/, 00763 radio().id(), /*source */ 00764 message.source(), /*destination*/ 00765 from/*next hop*/); 00766 radio().send(from, rrep_message.buffer_size(), (uint8_t*) & rrep_message); 00767 00768 return; 00769 } 00770 00771 // i am the destination 00772 if (message.destination() == radio().id()) { 00773 //debug().debug("%i replying with DYMO_RREP to %i \n", radio().id(), message.source()); 00774 // create a rrep message 00775 RouteDiscoveryMessage rrep_message( 00776 DYMO_RREP, /*msg type*/ 00777 0, /*bcast id*/ 00778 0, /*hop cnt*/ 00779 //TODO increase? 00780 ++my_seq_nr_, /* source seq nr*/ 00781 seq_numbers_[message.source()]/* dest seq nr*/, 00782 radio().id(), /*source */ 00783 message.source(), /*destination*/ 00784 from/*next hop*/); 00785 00786 // send rrep 00787 radio().send(from, rrep_message.buffer_size(), (uint8_t*) & rrep_message); 00788 00789 } // no route. re-broadcast 00790 else { 00791 debug().debug("%i forwarding DYMO_RREQ from %i\n", radio().id(), message.source()); 00792 RouteDiscoveryMessage rreq_message( 00793 DYMO_RREQ, /*msg type*/ 00794 message.bcast_id(), /*bcast id*/ 00795 message.hop_cnt() + 1, /*hop cnt*/ 00796 my_seq_nr_, /* source seq nr*/ 00797 seq_numbers_[message.source()]/* dest seq nr*/, 00798 message.source(), /*source */ 00799 message.destination(), /*destination*/ 00800 0/*bcast*/); 00801 radio().send(radio().BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*) & rreq_message); 00802 00803 } 00804 return; 00805 } 00806 00807 00808 // ----------------------------------------------------------------------- 00809 00810 template<typename OsModel_P, 00811 typename RoutingTable_P, 00812 typename Radio_P, 00813 typename Debug_P> 00814 void 00815 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00816 proc_rrep(node_id_t from, RouteDiscoveryMessage& message) { 00817 debug().debug("%i received DYMO_RREP from %i via %i\n", radio().id(), message.source(), from, message.hop_cnt()); 00818 00819 // Record highest seq number 00820 if (message.source_sequence_nr() - seq_numbers_[message.source()] > 0) { 00821 seq_numbers_[message.source()] = message.source_sequence_nr(); 00822 } 00823 00824 // add to route entry only if this is the first entry OR rrep proposes a better path 00825 // or rrep is fresher 00826 if (!route_exists(message.source()) 00827 || routing_table_[message.destination()].dest_seq < message.destination_sequence_nr() 00828 || (routing_table_[message.destination()].hop_cnt > message.hop_cnt() 00829 && routing_table_[message.destination()].dest_seq < message.destination_sequence_nr())) { 00830 00831 RoutingTableValue value; 00832 00833 value.destination = message.source(); 00834 value.next_hop = from; 00835 value.hop_cnt = message.hop_cnt() + 1; 00836 value.dest_seq = seq_numbers_[message.destination()]; 00837 value.lifetime = ROUTE_TIMEOUT; 00838 routing_table_[message.source()] = value; 00839 /* debug().debug("%i added route entry %i:%i:%i:%i \n", radio().id(), 00840 routing_table_[message.source()].destination, 00841 routing_table_[message.source()].next_hop, 00842 routing_table_[message.source()].hop_cnt, 00843 routing_table_[message.source()].lifetime);*/ 00844 00845 00846 // check if there are any pending messages for this target 00847 check_pending_messages(message.source()); 00848 00849 } 00850 // this rrep is not for me 00851 if (message.destination() != radio().id()) { 00852 // unicast using reverse path 00853 RouteDiscoveryMessage rrep_message( 00854 DYMO_RREP, /*msg type*/ 00855 message.bcast_id(), /*bcast id*/ 00856 message.hop_cnt() + 1, /*hop cnt*/ 00857 my_seq_nr_, /* source seq nr*/ 00858 seq_numbers_[message.source()]/* dest seq nr*/, 00859 message.source(), /*source */ 00860 message.destination(), /*destination*/ 00861 0/*bcast*/); 00862 00863 radio().send(routing_table_[message.destination()].next_hop, rrep_message.buffer_size(), (uint8_t*) & rrep_message); 00864 } 00865 00866 return; 00867 } 00868 00869 00870 // ----------------------------------------------------------------------- 00871 00872 template<typename OsModel_P, 00873 typename RoutingTable_P, 00874 typename Radio_P, 00875 typename Debug_P> 00876 void 00877 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00878 proc_err(node_id_t from, RouteDiscoveryMessage& message) { 00879 debug().debug("%i received DYMO_ERROR from %i\n", radio().id(), from); 00880 return; 00881 } 00882 00883 00884 // ----------------------------------------------------------------------- 00885 00886 template<typename OsModel_P, 00887 typename RoutingTable_P, 00888 typename Radio_P, 00889 typename Debug_P> 00890 void 00891 DYMORouting<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00892 receive(node_id_t from, size_t len, block_data_t *data) { 00893 if (from != radio().id()) { 00894 uint8_t msg_type = *data; 00895 //debug().debug("%i received msg %i \n", radio().id(), msg_type); 00896 switch (msg_type) { 00897 00898 case DYMO_RREQ: 00899 { 00900 RouteDiscoveryMessage *message = reinterpret_cast<RouteDiscoveryMessage*> (data); 00901 proc_rreq(from, *message); 00902 break; 00903 } 00904 case DYMO_RREP: 00905 { 00906 RouteDiscoveryMessage *message = reinterpret_cast<RouteDiscoveryMessage*> (data); 00907 proc_rrep(from, *message); 00908 break; 00909 } 00910 case DYMO_ERR: 00911 { 00912 //proc_err(from, *data); 00913 break; 00914 } 00915 case DYMO_DATA: 00916 { 00917 RouteDiscoveryMessage *message = reinterpret_cast<RouteDiscoveryMessage*> (data); 00918 proc_data(from, *message); 00919 break; 00920 } 00921 default: 00922 { 00923 debug().debug("%i received UNRECOGNIZED message type [%i]\n", radio().id(), msg_type); 00924 00925 } 00926 00927 00928 } 00929 00930 } 00931 00932 } 00933 00934 00935 } 00936 #endif