Wiselib
wiselib.stable/algorithms/routing/dsdv/dsdv_routing.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines