Wiselib
wiselib.stable/algorithms/routing/dsr/dsr_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_DSR_ROUTING_H__
00020 #define __ALGORITHMS_ROUTING_DSR_ROUTING_H__
00021 
00022 #include "algorithms/routing/dsr/dsr_routing_types.h"
00023 #include "algorithms/routing/dsr/dsr_route_discovery_msg.h"
00024 #include "algorithms/routing/dsr/dsr_routing_msg.h"
00025 #include "util/base_classes/routing_base.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 DsrRouting
00049       : public RoutingBase<OsModel_P, Radio_P>
00050    {
00051    public:
00052       typedef OsModel_P OsModel;
00053       typedef Radio_P Radio;
00054       typedef typename OsModel::Timer Timer;
00055       typedef typename OsModel::Debug Debug;
00056 
00057       typedef RoutingTable_P RoutingTable;
00058       typedef typename RoutingTable::iterator RoutingTableIterator;
00059       typedef typename RoutingTable::mapped_type RoutingTableValue;
00060       typedef typename RoutingTable::value_type RoutingTableEntry;
00061 
00062       typedef typename RoutingTableValue::Path Path;
00063       typedef typename Path::iterator PathIterator;
00064 
00065       typedef DsrRouting<OsModel, RoutingTable, Radio> self_type;
00066       typedef self_type* self_pointer_t;
00067 
00068       typedef typename Radio::node_id_t node_id_t;
00069       typedef typename Radio::size_t size_t;
00070       typedef typename Radio::block_data_t block_data_t;
00071       typedef typename Radio::message_id_t message_id_t;
00072 
00073       typedef typename Timer::millis_t millis_t;
00074 
00075       typedef DsrRouteDiscoveryMessage<OsModel, Radio, Path> RouteDiscoveryMessage;
00076       typedef DsrRoutingMessage<OsModel, Radio, Path> RoutingMessage;
00077       // --------------------------------------------------------------------
00078       enum ErrorCodes
00079       {
00080          SUCCESS = OsModel::SUCCESS,
00081          ERR_UNSPEC = OsModel::ERR_UNSPEC,
00082          ERR_NOTIMPL = OsModel::ERR_NOTIMPL,
00083          ERR_BUSY = OsModel::ERR_BUSY
00084       };
00085       // --------------------------------------------------------------------
00086       enum SpecialNodeIds {
00087          BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 
00088          NULL_NODE_ID      = Radio_P::NULL_NODE_ID      
00089       };
00090       // --------------------------------------------------------------------
00091       enum Restrictions {
00092          MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH   
00093       };
00094       // --------------------------------------------------------------------
00097       DsrRouting();
00098       ~DsrRouting();
00100 
00101       int init( Radio& radio, Timer& timer, Debug& debug )
00102       {
00103          radio_ = &radio;
00104          timer_ = &timer;
00105          debug_ = &debug;
00106          return SUCCESS;
00107       }
00108 
00109       inline int init();
00110       inline int destruct();
00111 
00114       int enable_radio( void );
00115       int disable_radio( void );
00117 
00120       void timer_elapsed( void *userdata );
00122 
00125 
00127       int send( node_id_t receiver, size_t len, block_data_t *data );
00130       void receive( node_id_t from, size_t len, block_data_t *data );
00133       typename Radio::node_id_t id()
00134       { return radio_->id(); }
00136 
00137    private:
00138 
00139       Radio& radio()
00140       { return *radio_; }
00141 
00142       Timer& timer()
00143       { return *timer_; }
00144 
00145       Debug& debug()
00146       { return *debug_; }
00147 
00148       typename Radio::self_pointer_t radio_;
00149       typename Timer::self_pointer_t timer_;
00150       typename Debug::self_pointer_t debug_;
00151 
00152       uint16_t seq_nr_;
00153 
00154       bool send_in_progress_;
00155 
00156       RoutingTable routing_table_;
00157       RoutingMessage routing_message_;
00158 
00159       void handle_route_request( node_id_t from, RouteDiscoveryMessage& message );
00160       void handle_route_reply( node_id_t from, RouteDiscoveryMessage& message );
00161       void handle_routing_message( node_id_t from, size_t len, RoutingMessage& message );
00162 
00163       void update_seq_nr( node_id_t node, uint16_t seq_nr );
00164       uint16_t get_seq_nr( node_id_t node );
00165 
00166       void print_path( Path& path );
00167    };
00168    // -----------------------------------------------------------------------
00169    // -----------------------------------------------------------------------
00170    // -----------------------------------------------------------------------
00171    template<typename OsModel_P,
00172             typename RoutingTable_P,
00173             typename Radio_P>
00174    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00175    DsrRouting()
00176       : seq_nr_            ( 1 ),
00177          send_in_progress_ ( false )
00178    {}
00179    // -----------------------------------------------------------------------
00180    template<typename OsModel_P,
00181             typename RoutingTable_P,
00182             typename Radio_P>
00183    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00184    ~DsrRouting()
00185    {
00186 #ifdef ROUTING_DSR_DEBUG
00187       debug().debug( "DsrRouting: Destroyed\n" );
00188 #endif
00189    }
00190    // -----------------------------------------------------------------------
00191    template<typename OsModel_P,
00192             typename RoutingTable_P,
00193             typename Radio_P>
00194    int
00195    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00196    init( void )
00197    {
00198       routing_table_.clear();
00199       routing_message_ = RoutingMessage();
00200       seq_nr_ = 1;
00201       send_in_progress_ = false;
00202 
00203       enable_radio();
00204 
00205       return SUCCESS;
00206    }
00207    // -----------------------------------------------------------------------
00208    template<typename OsModel_P,
00209             typename RoutingTable_P,
00210             typename Radio_P>
00211    int
00212    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00213    destruct( void )
00214    {
00215       return disable_radio();
00216    }
00217    // -----------------------------------------------------------------------
00218    template<typename OsModel_P,
00219             typename RoutingTable_P,
00220             typename Radio_P>
00221    int
00222    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00223    enable_radio( void )
00224    {
00225 #ifdef ROUTING_DSR_DEBUG
00226       debug().debug( "DsrRouting: Boot for %d\n", radio().id() );
00227 #endif
00228 
00229       radio().enable_radio();
00230       radio().template reg_recv_callback<self_type, &self_type::receive>( this );
00231 
00232       timer().template set_timer<self_type, &self_type::timer_elapsed>(
00233                                  15000, this, 0 );
00234 
00235       return SUCCESS;
00236    }
00237    // -----------------------------------------------------------------------
00238    template<typename OsModel_P,
00239             typename RoutingTable_P,
00240             typename Radio_P>
00241    int
00242    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00243    disable_radio( void )
00244    {
00245 #ifdef ROUTING_DSR_DEBUG
00246       debug().debug( "DsrRouting: Disable\n" );
00247 #endif
00248       return ERR_NOTIMPL;
00249    }
00250    // -----------------------------------------------------------------------
00251    template<typename OsModel_P,
00252             typename RoutingTable_P,
00253             typename Radio_P>
00254    void
00255    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00256    timer_elapsed( void *userdata )
00257    {
00258       timer().template set_timer<self_type, &self_type::timer_elapsed>(
00259                                  15000, this, 0 );
00260    }
00261    // -----------------------------------------------------------------------
00262    template<typename OsModel_P,
00263             typename RoutingTable_P,
00264             typename Radio_P>
00265    int
00266    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00267    send( node_id_t destination, size_t len, block_data_t *data )
00268    {
00269       // waiting for route reply - cannot store another routing message
00270       if ( send_in_progress_ )
00271          return ERR_BUSY;
00272 
00273       routing_message_ = RoutingMessage( DsrRoutingMsgId, radio().id(), destination, 1, len, data );
00274 
00275       RoutingTableIterator it = routing_table_.find( destination );
00276       if ( it != routing_table_.end() )
00277       {
00278          routing_message_.set_path( it->second.path );
00279          radio().send( it->second.path[1], routing_message_.buffer_size(), (uint8_t*)&routing_message_ );
00280 #ifdef ROUTING_DSR_DEBUG
00281          debug().debug( "DsrRouting: Existing path in Cache with size %d hops %d idx %d\n",
00282             it->second.path.size(), it->second.hops, routing_message_.path_idx() );
00283          print_path( it->second.path );
00284 #endif
00285       }
00286       else
00287       {
00288          send_in_progress_ = true;
00289          RouteDiscoveryMessage message( DsrRouteRequestMsgId,
00290                                         0, // hops
00291                                         seq_nr_++,
00292                                         radio().id(),
00293                                         destination,
00294                                         0 ); // path idx - not needed when sending request
00295          Path path;
00296          path.push_back( radio().id() );
00297          message.set_path( path );
00298 
00299          radio().send( Radio::BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*)&message );
00300 #ifdef ROUTING_DSR_DEBUG
00301          debug().debug( "DsrRouting: Start Route Request from %d to %d.\n", message.source(), message.destination() );
00302 #endif
00303       }
00304 
00305       return SUCCESS;
00306    }
00307    // -----------------------------------------------------------------------
00308    template<typename OsModel_P,
00309             typename RoutingTable_P,
00310             typename Radio_P>
00311    void
00312    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00313    receive( node_id_t from, size_t len, block_data_t *data )
00314    {
00315       message_id_t msg_id = read<OsModel, block_data_t, message_id_t>( data );
00316       if ( msg_id == DsrRouteRequestMsgId )
00317       {
00318          RouteDiscoveryMessage *message = reinterpret_cast<RouteDiscoveryMessage*>(data);
00319          handle_route_request( from, *message );
00320       }
00321       else if ( msg_id == DsrRouteReplyMsgId )
00322       {
00323          RouteDiscoveryMessage *message = reinterpret_cast<RouteDiscoveryMessage*>(data);
00324          handle_route_reply( from, *message );
00325       }
00326       else if ( msg_id == DsrRoutingMsgId )
00327       {
00328          RoutingMessage *message = reinterpret_cast<RoutingMessage*>(data);
00329          handle_routing_message( from, len, *message );
00330       }
00331    }
00332    // -----------------------------------------------------------------------
00333    template<typename OsModel_P,
00334             typename RoutingTable_P,
00335             typename Radio_P>
00336    void
00337    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00338    handle_route_request( node_id_t from, RouteDiscoveryMessage& message )
00339    {
00340       if ( get_seq_nr(message.source()) >= message.sequence_nr() )
00341       {
00342 #ifdef ROUTING_DSR_DEBUG
00343 //          debug().debug( "DsrRouting: Seq nr %d in RReq at %d from %d (to %d) is known.\n",
00344 //                        message.sequence_nr(), radio().id(),
00345 //                        message.source(), message.destination() );
00346 #endif
00347          return;
00348       }
00349       update_seq_nr( message.source(), message.sequence_nr() );
00350 
00351       if ( message.destination() == radio().id() )
00352       {
00353          RouteDiscoveryMessage msg(message);
00354          msg.set_msg_id( DsrRouteReplyMsgId );
00355          msg.set_hops( msg.hops() + 1 );
00356 
00357          Path path;
00358          msg.path( path );
00359          path.push_back( radio().id() );
00360          msg.set_path( path );
00361 
00362          radio().send( path[msg.path_idx()], msg.buffer_size(), (uint8_t*)&msg );
00363 #ifdef ROUTING_DSR_DEBUG
00364          debug().debug( "DsrRouting: Reply to RREQ with size %d, hops %d; idx %d\n", path.size(), msg.hops(), msg.path_idx() );
00365          print_path(path);
00366          debug().debug( "DsrRouting: Route Request from %d at destination %d, send back route reply over %d\n",
00367                            msg.source(),
00368                            msg.destination(),
00369                            path[msg.path_idx()] );
00370 #endif
00371       }
00372       else
00373       {
00374          RouteDiscoveryMessage msg(message);
00375          Path path;
00376          msg.path( path );
00377          path.push_back( radio().id() );
00378          msg.inc_path_idx();
00379          msg.set_hops( msg.hops() + 1 );
00380          msg.set_path( path );
00381          radio().send( Radio::BROADCAST_ADDRESS, msg.buffer_size(), (uint8_t*)&msg );
00382 #ifdef ROUTING_DSR_DEBUG
00383 //          debug().debug( "DsrRouting: Forward RREQ at %d (from %d to %d) with idx %d (size %d).\n",
00384 //             radio().id(), message.source(), message.destination(), message.path_idx(), path.size() );
00385 //          print_path( path );
00386 #endif
00387       }
00388    }
00389    // -----------------------------------------------------------------------
00390    template<typename OsModel_P,
00391             typename RoutingTable_P,
00392             typename Radio_P>
00393    void
00394    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00395    handle_route_reply( node_id_t from, RouteDiscoveryMessage& message )
00396    {
00397       if ( message.source() == radio().id() )
00398       {
00399 #ifdef ROUTING_DSR_DEBUG
00400          debug().debug( "DsrRouting: RREP -> HOME at %d from %d\n",
00401                         message.source(), message.destination() );
00402 #endif
00403          routing_message_.set_path_idx( 1 );
00404          Path path;
00405          message.path( path );
00406          routing_message_.set_path( path );
00407 
00408          RoutingTableValue value;
00409          value.path = path;
00410          value.hops = message.hops();
00411          value.seq_nr = message.sequence_nr();
00412          routing_table_[message.destination()] = value;
00413 
00414          radio().send( path[routing_message_.path_idx()],
00415                       routing_message_.buffer_size(),
00416                       (uint8_t*)&routing_message_ );
00417          send_in_progress_ = false;
00418 #ifdef ROUTING_DSR_DEBUG
00419          debug().debug( "DsrRouting: Routing message with size %d hops %d idx %d (next hop %d)\n",
00420             path.size(), message.hops(), routing_message_.path_idx(), path[routing_message_.path_idx()] );
00421          print_path(path);
00422 #endif
00423       }
00424       else
00425       {
00426          message.dec_path_idx();
00427          Path path;
00428          message.path( path );
00429          radio().send( path[message.path_idx()], message.buffer_size(), (uint8_t*)(&message) );
00430 #ifdef ROUTING_DSR_DEBUG
00431          debug().debug( "DsrRouting: Forward RREP at %d to %d (from %d to %d).\n",
00432             radio().id(),
00433             path[message.path_idx()],
00434             message.source(),
00435             message.destination() );
00436          print_path(path);
00437 #endif
00438       }
00439    }
00440    // -----------------------------------------------------------------------
00441    template<typename OsModel_P,
00442             typename RoutingTable_P,
00443             typename Radio_P>
00444    void
00445    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00446    handle_routing_message( node_id_t from, size_t len, RoutingMessage& message )
00447    {
00448       if ( message.destination() == radio().id() )
00449       {
00450 #ifdef ROUTING_DSR_DEBUG
00451          debug().debug( "DsrRouting: DELIVERED Dsr-Routing-Message at %d from %d\n",
00452                            radio().id(), message.source() );
00453 #endif
00454          notify_receivers( message.source(), message.payload_size(), message.payload() );
00455       }
00456       else
00457       {
00458          RoutingMessage msg( message );
00459          Path path;
00460          message.path( path );
00461          msg.inc_path_idx();
00462 
00463          radio().send( path[msg.path_idx()], len, (uint8_t*)&msg );
00464 #ifdef ROUTING_DSR_DEBUG
00465          debug().debug( "DsrRouting: Forward RoutingMsg at %d to %d with path idx %d (from %d to %d).\n",
00466                        radio().id(),
00467                        path[msg.path_idx()], msg.path_idx(),
00468                        msg.source(), msg.destination() );
00469 #endif
00470       }
00471    }
00472    // -----------------------------------------------------------------------
00473    template<typename OsModel_P,
00474             typename RoutingTable_P,
00475             typename Radio_P>
00476    void
00477    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00478    update_seq_nr( node_id_t node, uint16_t seq_nr )
00479    {
00480       RoutingTableIterator it = routing_table_.find( node );
00481       if ( it != routing_table_.end() )
00482       {
00483          it->second.seq_nr = seq_nr;
00484       }
00485       else
00486       {
00487          RoutingTableValue entry;
00488          entry.hops = 0;
00489          entry.seq_nr = seq_nr;
00490          routing_table_[node] = entry;
00491       }
00492    }
00493    // -----------------------------------------------------------------------
00494    template<typename OsModel_P,
00495             typename RoutingTable_P,
00496             typename Radio_P>
00497    uint16_t
00498    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00499    get_seq_nr( node_id_t node )
00500    {
00501       RoutingTableIterator it = routing_table_.find( node );
00502       if ( it != routing_table_.end() )
00503          return it->second.seq_nr;
00504 
00505       return 0;
00506    }
00507    // -----------------------------------------------------------------------
00508    template<typename OsModel_P,
00509             typename RoutingTable_P,
00510             typename Radio_P>
00511    void
00512    DsrRouting<OsModel_P, RoutingTable_P, Radio_P>::
00513    print_path( Path& path )
00514    {
00515 #ifdef ROUTING_DSR_DEBUG
00516       debug().debug( "  Path" );
00517       for ( PathIterator it = path.begin(); it != path.end(); ++it )
00518       {
00519          debug().debug( " -> %d", *it );
00520       }
00521       debug().debug( "\n" );
00522 #endif
00523    }
00524 
00525 }
00526 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines