Wiselib
wiselib.testing/algorithms/routing/dymo/dymo_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_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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines