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 __FLOODING_ALGORITHM_H__ 00020 #define __FLOODING_ALGORITHM_H__ 00021 00022 #include "util/base_classes/routing_base.h" 00023 #include "flooding_message.h" 00024 #include <string.h> 00025 00026 namespace wiselib 00027 { 00028 00036 template<typename OsModel_P, 00037 typename NodeidIntMap_P, 00038 typename Radio_P = typename OsModel_P::Radio, 00039 typename Debug_P = typename OsModel_P::Debug> 00040 class FloodingAlgorithm 00041 : public RoutingBase<OsModel_P, Radio_P> 00042 { 00043 public: 00044 typedef OsModel_P OsModel; 00045 typedef Radio_P Radio; 00046 typedef Debug_P Debug; 00047 00048 typedef NodeidIntMap_P MapType; 00049 typedef typename MapType::iterator MapTypeIterator; 00050 00051 typedef FloodingAlgorithm<OsModel, MapType, Radio, Debug> self_type; 00052 typedef self_type* self_pointer_t; 00053 00054 typedef typename Radio::node_id_t node_id_t; 00055 typedef typename Radio::size_t size_t; 00056 typedef typename Radio::block_data_t block_data_t; 00057 typedef typename Radio::message_id_t message_id_t; 00058 00059 typedef FloodingMessage<OsModel, Radio> Message; 00060 // -------------------------------------------------------------------- 00061 enum ErrorCodes 00062 { 00063 SUCCESS = OsModel::SUCCESS, 00064 ERR_UNSPEC = OsModel::ERR_UNSPEC, 00065 ERR_NETDOWN = OsModel::ERR_NETDOWN 00066 }; 00067 // -------------------------------------------------------------------- 00068 enum SpecialNodeIds 00069 { 00070 BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 00071 NULL_NODE_ID = Radio_P::NULL_NODE_ID 00072 }; 00073 // -------------------------------------------------------------------- 00074 enum Restrictions 00075 { 00076 MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH - Message::PAYLOAD_POS 00077 }; 00078 // -------------------------------------------------------------------- 00081 FloodingAlgorithm(); 00082 ~FloodingAlgorithm(); 00084 00087 int enable_radio( void ); 00088 int disable_radio( void ); 00090 00093 00095 int send( node_id_t receiver, size_t len, block_data_t *data ); 00098 void receive( node_id_t from, size_t len, block_data_t *data ); 00101 typename Radio::node_id_t id() 00102 { return radio_->id(); }; 00104 00105 int init( Radio& radio, Debug& debug ) 00106 { 00107 radio_ = &radio; 00108 debug_ = &debug; 00109 return SUCCESS; 00110 } 00111 00112 int init() 00113 { 00114 seq_nr_ = FLOODING_INIT_SEQ_NR; 00115 return enable_radio(); 00116 } 00117 00118 int destruct() 00119 { 00120 return disable_radio(); 00121 } 00122 00123 private: 00124 Radio& radio() 00125 { return *radio_; } 00126 00127 Debug& debug() 00128 { return *debug_; } 00129 00130 typename Radio::self_pointer_t radio_; 00131 typename Debug::self_pointer_t debug_; 00132 00133 enum MessageIds 00134 { 00135 FLOODING_MESSAGE_ID = 112 00136 }; 00137 00138 enum SequenceNumbers 00139 { 00140 FLOODING_INIT_SEQ_NR = 0 00141 }; 00142 00143 int callback_id_; 00144 uint16_t seq_nr_; 00145 00146 MapType seq_map_; 00147 }; 00148 // ----------------------------------------------------------------------- 00149 // ----------------------------------------------------------------------- 00150 // ----------------------------------------------------------------------- 00151 template<typename OsModel_P, 00152 typename RoutingTable_P, 00153 typename Radio_P, 00154 typename Debug_P> 00155 FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00156 FloodingAlgorithm() 00157 : callback_id_ ( 0 ), 00158 seq_nr_ ( FLOODING_INIT_SEQ_NR ) 00159 {} 00160 // ----------------------------------------------------------------------- 00161 template<typename OsModel_P, 00162 typename RoutingTable_P, 00163 typename Radio_P, 00164 typename Debug_P> 00165 FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00166 ~FloodingAlgorithm() 00167 { 00168 #ifdef ROUTING_FLOODING_DEBUG 00169 debug().debug( "FloodingAlgorithm:dtor\n" ); 00170 #endif 00171 } 00172 // ----------------------------------------------------------------------- 00173 template<typename OsModel_P, 00174 typename RoutingTable_P, 00175 typename Radio_P, 00176 typename Debug_P> 00177 int 00178 FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00179 enable_radio( void ) 00180 { 00181 #ifdef ROUTING_FLOODING_DEBUG 00182 debug().debug( "FloodingAlgorithm: Boot for %i\n", radio().id() ); 00183 #endif 00184 00185 radio().enable_radio(); 00186 callback_id_ = radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00187 return SUCCESS; 00188 } 00189 // ----------------------------------------------------------------------- 00190 template<typename OsModel_P, 00191 typename RoutingTable_P, 00192 typename Radio_P, 00193 typename Debug_P> 00194 int 00195 FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00196 disable_radio( void ) 00197 { 00198 #ifdef ROUTING_FLOODING_DEBUG 00199 debug().debug( "FloodingAlgorithm: Disable\n" ); 00200 #endif 00201 radio().unreg_recv_callback( callback_id_ ); 00202 radio().disable(); 00203 return SUCCESS; 00204 } 00205 // ----------------------------------------------------------------------- 00206 template<typename OsModel_P, 00207 typename RoutingTable_P, 00208 typename Radio_P, 00209 typename Debug_P> 00210 int 00211 FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00212 send( node_id_t destination, size_t len, block_data_t *data ) 00213 { 00214 #ifdef ROUTING_FLOODING_DEBUG 00215 debug().debug( "FloodingAlgorithm: Send at %d\n", radio_->id() ); 00216 #endif 00217 00218 Message message; 00219 message.set_msg_id( FLOODING_MESSAGE_ID ); 00220 message.set_node_id( radio().id() ); 00221 message.set_seq_nr( seq_nr_ ); 00222 message.set_payload( len, data ); 00223 00224 radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message ); 00225 00226 seq_nr_++; 00227 return SUCCESS; 00228 } 00229 // ----------------------------------------------------------------------- 00230 template<typename OsModel_P, 00231 typename RoutingTable_P, 00232 typename Radio_P, 00233 typename Debug_P> 00234 void 00235 FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>:: 00236 receive( node_id_t from, size_t len, block_data_t *data ) 00237 { 00238 00239 if ( from == radio().id() ) 00240 { 00241 #ifdef ROUTING_FLOODING_DEBUG 00242 debug().debug( "FloodingAlgorithm ERROR: received radio message from myself at %u\n", radio_->id() ); 00243 #endif 00244 return; 00245 } 00246 00247 00248 message_id_t msg_id = read<OsModel, block_data_t, message_id_t>( data ); 00249 00250 if ( msg_id == FLOODING_MESSAGE_ID ) 00251 { 00252 Message *message = (Message *)data; 00253 if ( message->node_id() == radio().id() ) 00254 { 00255 #ifdef ROUTING_FLOODING_DEBUG 00256 debug().debug( "FloodingAlgorithm ERROR: received flooding message from myself at %u (msg id is %u)\n", radio_->id(), message->node_id() ); 00257 #endif 00258 return; 00259 } 00260 00261 // Has message already been received? If so, return. 00262 // Of course, there is a simplification with the check for seq_nr 00263 // just to be greater than the known one---but this can be done for 00264 // simplicity reasons (code-space!!) 00265 MapTypeIterator it = seq_map_.find( message->node_id() ); 00266 if ( it == seq_map_.end() || 00267 ( it != seq_map_.end() && 00268 ( message->seq_nr() > it->second || 00269 ( message->seq_nr() == FLOODING_INIT_SEQ_NR && it->second >= 2))) ) 00270 { 00271 // Update sequence number, and forward the message to neighbors. 00272 seq_map_[message->node_id()] = message->seq_nr(); 00273 radio().send( radio().BROADCAST_ADDRESS, len, data ); 00274 00275 #ifdef ROUTING_FLOODING_DEBUG 00276 debug().debug( "FloodingAlgorithm: receive at %d from %d with seqnr %d (here is %d)\n", 00277 radio_->id(), message->node_id(), message->seq_nr(), seq_map_[message->node_id()] ); 00278 #endif 00279 00280 // Pass message to each registered receiver. 00281 notify_receivers( message->node_id(), message->payload_size(), message->payload() ); 00282 } 00283 else 00284 { 00285 #ifdef ROUTING_FLOODING_DEBUG 00286 debug().debug( "FloodingAlgorithm ERROR: sequence number already known at %d (%d <= %d)\n", 00287 radio_->id(), message->seq_nr(), seq_map_[message->node_id()] ); 00288 #endif 00289 } 00290 } 00291 else 00292 { 00293 #ifdef ROUTING_FLOODING_DEBUG 00294 debug().debug( "FloodingAlgorithm INFO: unknown message at %d (%d != %d)\n", radio_->id(), msg_id, FLOODING_MESSAGE_ID ); 00295 #endif 00296 } 00297 } 00298 00299 } 00300 #endif