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_DSDV_ROUTING_H__ 00020 #define __ALGORITHMS_ROUTING_DSDV_ROUTING_H__ 00021 00022 #include "util/base_classes/routing_base.h" 00023 #include "algorithms/routing/dsdv/dsdv_routing_types.h" 00024 #include "algorithms/routing/dsdv/dsdv_routing_message.h" 00025 #include "algorithms/routing/dsdv/dsdv_broadcast_message.h" 00026 #include "config.h" 00027 #include <string.h> 00028 00029 00030 namespace wiselib 00031 { 00032 00043 template<typename OsModel_P, 00044 typename RoutingTable_P, 00045 typename Radio_P = typename OsModel_P::Radio, 00046 typename Timer_P = typename OsModel_P::Timer, 00047 typename Debug_P = typename OsModel_P::Debug> 00048 class DsdvRouting 00049 : public RoutingBase<OsModel_P, Radio_P> 00050 { 00051 public: 00052 typedef OsModel_P OsModel; 00053 typedef Radio_P Radio; 00054 typedef Timer_P Timer; 00055 typedef Debug_P Debug; 00056 00057 typedef RoutingTable_P RoutingTable; 00058 typedef typename RoutingTable::iterator RoutingTableIterator; 00059 typedef typename RoutingTable::value_type RoutingTableValue; 00060 typedef typename RoutingTable::mapped_type RoutingTableEntry; 00061 00062 typedef DsdvRouting<OsModel, RoutingTable, Radio, Timer, Debug> self_type; 00063 typedef self_type* self_pointer_t; 00064 00065 typedef typename Radio::node_id_t node_id_t; 00066 typedef typename Radio::size_t size_t; 00067 typedef typename Radio::block_data_t block_data_t; 00068 typedef typename Radio::message_id_t message_id_t; 00069 00070 typedef typename Timer::millis_t millis_t; 00071 00072 typedef DsdvRoutingMessage<OsModel, Radio> RoutingMessage; 00073 typedef DsdvBroadcastMessage<OsModel, Radio> BroadcastMessage; 00074 // -------------------------------------------------------------------- 00075 enum ErrorCodes 00076 { 00077 SUCCESS = OsModel::SUCCESS, 00078 ERR_UNSPEC = OsModel::ERR_UNSPEC, 00079 ERR_NOTIMPL = OsModel::ERR_NOTIMPL, 00080 ERR_HOSTUNREACH = OsModel::ERR_HOSTUNREACH 00081 }; 00082 // -------------------------------------------------------------------- 00083 enum SpecialNodeIds { 00084 BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 00085 NULL_NODE_ID = Radio_P::NULL_NODE_ID 00086 }; 00087 // -------------------------------------------------------------------- 00088 enum Restrictions { 00089 MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH - RoutingMessage::PAYLOAD_POS 00090 }; 00091 // -------------------------------------------------------------------- 00094 DsdvRouting(); 00095 ~DsdvRouting(); 00097 00098 int init( Radio& radio, Timer& timer, Debug& debug ) 00099 { 00100 radio_ = &radio; 00101 timer_ = &timer; 00102 debug_ = &debug; 00103 return SUCCESS; 00104 } 00105 00106 inline int init(); 00107 inline int destruct(); 00108 00111 int enable_radio( void ); 00112 int disable_radio( void ); 00114 00117 00119 int send( node_id_t receiver, size_t len, block_data_t *data ); 00122 void receive( node_id_t from, size_t len, block_data_t *data ); 00125 typename Radio::node_id_t id() 00126 { return radio_->id(); } 00128 00129 inline void set_startup_time( millis_t t ) 00130 { startup_time_ = t; }; 00131 00132 inline void set_work_period( millis_t t ) 00133 { work_period_ = t; }; 00134 00135 private: 00136 00137 Radio& radio() 00138 { return *radio_; } 00139 00140 Timer& timer() 00141 { return *timer_; } 00142 00143 Debug& debug() 00144 { return *debug_; } 00145 00146 typename Radio::self_pointer_t radio_; 00147 typename Timer::self_pointer_t timer_; 00148 typename Debug::self_pointer_t debug_; 00149 00152 void timer_elapsed( void *userdata ); 00154 00157 void update_routing_table( node_id_t from, BroadcastMessage& message ); 00158 void print_routing_table( RoutingTable& rt ); 00160 00161 millis_t startup_time_; 00162 millis_t work_period_; 00163 00164 RoutingTable routing_table_; 00165 }; 00166 // ----------------------------------------------------------------------- 00167 // ----------------------------------------------------------------------- 00168 // ----------------------------------------------------------------------- 00169 template<typename OsModel_P, 00170 typename RoutingTable_P, 00171 typename Radio_P, 00172 typename Timer_P, 00173 typename Debug_P> 00174 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00175 DsdvRouting() 00176 : radio_ ( 0 ), 00177 timer_ ( 0 ), 00178 debug_ ( 0 ), 00179 startup_time_ ( 2000 ), 00180 work_period_ ( 5000 ) 00181 {} 00182 // ----------------------------------------------------------------------- 00183 template<typename OsModel_P, 00184 typename RoutingTable_P, 00185 typename Radio_P, 00186 typename Timer_P, 00187 typename Debug_P> 00188 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00189 ~DsdvRouting() 00190 { 00191 #ifdef ROUTING_DSDV_DEBUG 00192 debug().debug( "DsdvRouting: Destroyed\n" ); 00193 #endif 00194 } 00195 // ----------------------------------------------------------------------- 00196 template<typename OsModel_P, 00197 typename RoutingTable_P, 00198 typename Radio_P, 00199 typename Timer_P, 00200 typename Debug_P> 00201 int 00202 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00203 init( void ) 00204 { 00205 routing_table_.clear(); 00206 enable_radio(); 00207 00208 return SUCCESS; 00209 } 00210 // ----------------------------------------------------------------------- 00211 template<typename OsModel_P, 00212 typename RoutingTable_P, 00213 typename Radio_P, 00214 typename Timer_P, 00215 typename Debug_P> 00216 int 00217 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00218 destruct( void ) 00219 { 00220 return disable_radio(); 00221 } 00222 // ----------------------------------------------------------------------- 00223 template<typename OsModel_P, 00224 typename RoutingTable_P, 00225 typename Radio_P, 00226 typename Timer_P, 00227 typename Debug_P> 00228 int 00229 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00230 enable_radio( void ) 00231 { 00232 #ifdef ROUTING_DSDV_DEBUG 00233 debug().debug( "DsdvRouting: Boot for %i\n", radio().id() ); 00234 #endif 00235 radio().enable_radio(); 00236 radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00237 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00238 startup_time_, this, 0 ); 00239 00240 return SUCCESS; 00241 } 00242 // ----------------------------------------------------------------------- 00243 template<typename OsModel_P, 00244 typename RoutingTable_P, 00245 typename Radio_P, 00246 typename Timer_P, 00247 typename Debug_P> 00248 int 00249 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00250 disable_radio( void ) 00251 { 00252 #ifdef ROUTING_DSDV_DEBUG 00253 debug().debug( "DsdvRouting: Disable\n" ); 00254 #endif 00255 return ERR_NOTIMPL; 00256 } 00257 // ----------------------------------------------------------------------- 00258 template<typename OsModel_P, 00259 typename RoutingTable_P, 00260 typename Radio_P, 00261 typename Timer_P, 00262 typename Debug_P> 00263 int 00264 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00265 send( node_id_t destination, size_t len, block_data_t *data ) 00266 { 00267 RoutingTableIterator it = routing_table_.find( destination ); 00268 if ( it != routing_table_.end() && 00269 it->second.next_hop != radio().NULL_NODE_ID ) 00270 { 00271 RoutingMessage message; 00272 message.set_msg_id( DsdvRoutingMsgId ); 00273 message.set_source( radio().id() ); 00274 message.set_destination( destination ); 00275 message.set_payload( len, data ); 00276 radio().send( it->second.next_hop, message.buffer_size(), (uint8_t*)&message ); 00277 #ifdef ROUTING_DSDV_DEBUG 00278 // debug().debug( "DsdvRouting: Send to %i over %i.\n", message.destination(), it->second.next_hop ); 00279 #endif 00280 } 00281 else 00282 { 00283 #ifdef ROUTING_DSDV_DEBUG 00284 // debug().debug( "DsdvRouting: Send failed. Route to Destination not known.\n" ); 00285 #endif 00286 return ERR_HOSTUNREACH; 00287 } 00288 00289 return SUCCESS; 00290 } 00291 // ----------------------------------------------------------------------- 00292 template<typename OsModel_P, 00293 typename RoutingTable_P, 00294 typename Radio_P, 00295 typename Timer_P, 00296 typename Debug_P> 00297 void 00298 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00299 timer_elapsed( void* userdata ) 00300 { 00301 #ifdef ROUTING_DSDV_DEBUG 00302 debug().debug( "DsdvRouting: Execute TimerElapsed at %i\n", radio().id() ); 00303 int messages = 0; 00304 #endif 00305 if ( routing_table_.empty() ) 00306 { 00307 BroadcastMessage message; 00308 message.set_msg_id( DsdvBroadcastMsgId ); 00309 message.set_entry_cnt( 0 ); 00310 radio().send( Radio::BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*)&message ); 00311 } 00312 else 00313 { 00314 RoutingTableIterator it = routing_table_.begin(); 00315 while ( it != routing_table_.end() ) 00316 { 00317 BroadcastMessage message; 00318 message.set_msg_id( DsdvBroadcastMsgId ); 00319 int idx = 0; 00320 for ( ; it != routing_table_.end() && idx < BroadcastMessage::MAX_ENTRIES; ++it ) 00321 { 00322 message.set_entry( idx, it->first, it->second ); 00323 idx++; 00324 } 00325 message.set_entry_cnt( idx ); 00326 radio().send( Radio::BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*)&message ); 00327 #ifdef ROUTING_DSDV_DEBUG 00328 messages++; 00329 debug().debug( "DsdvRouting: BC-Message %d with %i entries (%d max)\n", messages, idx, BroadcastMessage::MAX_ENTRIES ); 00330 #endif 00331 } 00332 } 00333 00334 #ifdef ROUTING_DSDV_DEBUG 00335 print_routing_table( routing_table_ ); 00336 #endif 00337 00338 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00339 work_period_, this, 0 ); 00340 } 00341 // ----------------------------------------------------------------------- 00342 template<typename OsModel_P, 00343 typename RoutingTable_P, 00344 typename Radio_P, 00345 typename Timer_P, 00346 typename Debug_P> 00347 void 00348 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00349 receive( node_id_t from, size_t len, block_data_t *data ) 00350 { 00351 if ( from == radio().id() ) 00352 return; 00353 00354 message_id_t msg_id = read<OsModel, block_data_t, message_id_t>( data ); 00355 if ( msg_id == DsdvBroadcastMsgId ) 00356 { 00357 BroadcastMessage *message = (BroadcastMessage *)data; 00358 routing_table_[from] = RoutingTableEntry( from, 1 ); 00359 update_routing_table( from, *message ); 00360 } 00361 else if ( msg_id == DsdvRoutingMsgId ) 00362 { 00363 RoutingMessage *message = reinterpret_cast<RoutingMessage*>(data); 00364 #ifdef ROUTING_DSDV_DEBUG 00365 debug().debug( "DsdvRouting: Rcvd at %i, ID %i, Len %i, From %i -> %i.\n", 00366 radio().id(), 00367 message->msg_id(), message->payload_size(), 00368 message->source(), message->destination() ); 00369 #endif 00370 00371 if ( message->destination() == radio().id() ) 00372 { 00373 notify_receivers( message->source(), message->payload_size(), message->payload() ); 00374 #ifdef ROUTING_DSDV_DEBUG 00375 debug().debug( "DsdvRouting: Received Dsdv-Routing-Message from %i\n", 00376 message->source() ); 00377 #endif 00378 } 00379 else 00380 { 00381 RoutingTableIterator it = routing_table_.find( message->destination() ); 00382 if ( it != routing_table_.end() && 00383 it->second.next_hop != radio().NULL_NODE_ID ) 00384 { 00385 radio().send( it->second.next_hop, len, data ); 00386 } 00387 #ifdef ROUTING_DSDV_DEBUG 00388 else 00389 debug().debug( "DsdvRouting: Forwarding FAILED (src %i). No route to %i known.\n", 00390 message->source(), message->destination() ); 00391 #endif 00392 } 00393 } 00394 } 00395 // ----------------------------------------------------------------------- 00396 template<typename OsModel_P, 00397 typename RoutingTable_P, 00398 typename Radio_P, 00399 typename Timer_P, 00400 typename Debug_P> 00406 void 00407 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00408 update_routing_table( node_id_t from, BroadcastMessage& message ) 00409 { 00410 for ( int i = 0; i < message.entry_cnt(); i++ ) 00411 { 00412 node_id_t id; 00413 RoutingTableEntry entry; 00414 if ( !message.entry( i, id, entry ) ) 00415 continue; 00416 00417 RoutingTableValue value( id, entry ); 00418 if ( value.first != radio().NULL_NODE_ID && 00419 value.first != radio().id() ) 00420 { 00421 RoutingTableIterator cur = routing_table_.find( value.first ); 00422 if ( cur == routing_table_.end() ) 00423 { 00424 #ifdef ROUTING_DSDV_DEBUG 00425 // debug().debug( "DsdvRouting: Add %i because not known\n", value.first ); 00426 #endif 00427 routing_table_[value.first] = RoutingTableEntry( 00428 from, value.second.hops + 1 ); 00429 } 00430 else if ( cur->second.hops > value.second.hops + 1 ) 00431 { 00432 #ifdef ROUTING_DSDV_DEBUG 00433 // debug().debug( "DsdvRouting: Update %i because smaller hopcount (new %i < old %i)\n", 00434 // value.first, value.second.hops, cur->second.hops ); 00435 #endif 00436 routing_table_[value.first] = RoutingTableEntry( 00437 from, value.second.hops + 1 ); 00438 } 00439 } 00440 } 00441 } 00442 // ----------------------------------------------------------------------- 00443 template<typename OsModel_P, 00444 typename RoutingTable_P, 00445 typename Radio_P, 00446 typename Timer_P, 00447 typename Debug_P> 00448 void 00449 DsdvRouting<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Debug_P>:: 00450 print_routing_table( RoutingTable& rt ) 00451 { 00452 #ifdef ROUTING_DSDV_DEBUG 00453 int i = 0; 00454 debug().debug( "DsdvRouting: Routing Table of %i (%d entries):\n", radio().id(), rt.size() ); 00455 for ( RoutingTableIterator it = rt.begin(); it != rt.end(); ++it ) 00456 { 00457 debug().debug( "DsdvRouting: %i: Dest %i SendTo %i Hops %i\n", 00458 i++, 00459 it->first, 00460 it->second.next_hop, 00461 it->second.hops ); 00462 } 00463 #endif 00464 } 00465 00466 } 00467 #endif