Wiselib
wiselib.testing/algorithms/routing/olsr/olsr_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_OLSR_ROUTING_H__
00020 #define __ALGORITHMS_ROUTING_OLSR_ROUTING_H__
00021 
00022 #include "routing_base.h"
00023 #include "olsr_routing_types.h"
00024 #include "olsr_routing_msg.h"
00025 #include "olsr_broadcast_hello_msg.h"
00026 #include "olsr_broadcast_tc_msg.h"
00027 #include <string.h>
00028 #include <time.h>
00029 #include <cstdlib>
00030 #include <math.h>
00031 #include <vector>
00032 #include <map>
00033 #include <set>
00034 #include <iterator>
00035 
00036 //#define DEBUG_OLSRROUTING
00037 
00038 /**********************************************************************************/
00039 //                          Useful Macros                                          /
00040 /**********************************************************************************/
00041 
00042 #ifndef NULL
00043 #define NULL 0
00044 #endif
00045 
00046 #ifndef MIN
00047 #define  MIN(a, b) (((a) < (b)) ? (a) : (b))
00048 #endif
00049 
00050 #ifndef MAX
00051 #define  MAX(a, b) (((a) > (b)) ? (a) : (b))
00052 #endif
00053 
00054 /********** Intervals **********/
00055 #define OLSR_HELLO_INTERVAL      2
00056 #define OLSR_TC_INTERVAL      5
00057 #define OLSR_REFRESH_INTERVAL 2
00058 #define OLSR_NEIGHB_HOLD_TIME 3*OLSR_REFRESH_INTERVAL
00059 #define OLSR_TOP_HOLD_TIME    3*OLSR_TC_INTERVAL
00060 #define OLSR_DUP_HOLD_TIME    30
00061 
00062 #define OLSR_UNSPEC_LINK   0
00063 #define OLSR_ASYM_LINK     1
00064 #define OLSR_SYM_LINK      2
00065 #define OLSR_LOST_LINK     3
00066 
00067 #define OLSR_NOT_NEIGH     0
00068 #define OLSR_SYM_NEIGH     1
00069 #define OLSR_MPR_NEIGH     2
00070 
00071 #define OLSR_WILL_NEVER    0
00072 #define OLSR_WILL_LOW      1
00073 #define OLSR_WILL_DEFAULT  3
00074 #define OLSR_WILL_HIGH     6
00075 #define OLSR_WILL_ALWAYS   7
00076 
00077 #define OLSR_MAX_HELLOS       12                   // Maximum number of hello_msg per Hello message (4 link types * 3 neighbor types)
00078 #define OLSR_MAX_ADDRS        64                   // Maximum number of Neighbor_Addr per hello_msg
00079 
00080 #define OLSR_MSG_HDR_SIZE     12                   // Size (in bytes) of message header
00081 #define OLSR_HELLO_HDR_SIZE      1                    // Size (in bytes) of hello header
00082 #define OLSR_HELLO_MSG_HDR_SIZE  3                    // Size (in bytes) of hello_msg header
00083 #define OLSR_TC_HDR_SIZE      2                    // Size (in bytes) of tc header
00084 
00085 #define OLSR_MAX_SEQ_NUM   65535
00086 #define OLSR_STATUS_NOT_SYM   0                       // Used to set status of an OLSR_nb_tuple as "not symmetric".
00087 #define OLSR_STATUS_SYM    1                       // Used to set status of an OLSR_nb_tuple as "symmetric".
00088 
00089 #define OLSR_C 0.0625                              // Scaling factor used in RFC 3626.
00090 
00091 /****************************************************************************************/
00092 /****************************************************************************************/
00093 
00094 namespace wiselib
00095 {
00096 
00105    template<typename OsModel_P,
00106             typename RoutingTable_P,
00107             typename Clock_P,
00108             typename Radio_P = typename OsModel_P::Radio,
00109             typename Debug_P = typename OsModel_P::Debug>
00110    class OlsrRouting
00111       : public RoutingBase<OsModel_P, Radio_P>
00112    {
00113    public:
00114       typedef OsModel_P OsModel;
00115      typedef RoutingTable_P RoutingTable;
00116       typedef Radio_P Radio;
00117       typedef Debug_P Debug;
00118       typedef Clock_P Clock;
00119 
00120       typedef typename OsModel_P::Timer Timer;
00121 
00122       typedef typename RoutingTable::iterator RoutingTableIterator;
00123       typedef typename RoutingTable::value_type RoutingTableValue;
00124       typedef typename RoutingTable::mapped_type RoutingTableEntry;
00125 
00126       typedef OlsrRouting<OsModel, RoutingTable, Clock, Radio, Debug> self_type;
00127 
00128       typedef typename OsModel::Os Os;
00129 
00130       typedef typename Radio::node_id_t node_id_t;
00131       typedef typename Radio::size_t size_t;
00132       typedef typename Radio::block_data_t block_data_t;
00133       typedef typename Clock::time_t time_t;
00134 
00135       typedef typename Timer::millis_t millis_t;
00136 
00137       typedef OlsrRoutingMessage<OsModel, Radio> RoutingMessage;
00138       typedef OlsrBroadcastHelloMessage<OsModel, Radio, RoutingTableValue>    BroadcastHelloMessage;
00139       typedef OlsrBroadcastTcMessage<OsModel, Radio, RoutingTableValue> BroadcastTcMessage;
00140 
00141       OlsrRouting();
00142       ~OlsrRouting();
00143 
00144       //@name Routing Control
00145       void enable( void );
00146       void disable( void );
00147 
00148       //@name Routing Functionality
00149       void send( node_id_t receiver, size_t len, block_data_t *data );
00150 
00151       inline void set_os( Os* os )
00152       { os_ = os; };
00153 
00154       inline Os* os()
00155       { return os_; };
00156 
00157       /****************************************************************************************/
00158      //                          Data Structure in OLSR                                       /
00159       /****************************************************************************************/
00160 
00161        typedef struct OLSR_rt_entry {              // A Routing table entry
00162 
00163             node_id_t         dest_addr_;       // Address of the destination node.
00164             node_id_t         next_addr_;       // Address of the next hop.
00165             uint32_t       dist_;            // Distance in hops to the destination.
00166 
00167             inline node_id_t& dest_addr()       { return dest_addr_; }
00168             inline node_id_t& next_addr()       { return next_addr_; }
00169             inline uint32_t&  dist()            { return dist_; }
00170 
00171         } OLSR_rt_entry;
00172 
00173 
00174        typedef struct OLSR_link_tuple {               // A Link Tuple.
00175 
00176                node_id_t         local_node_addr_; // Address of the local node.
00177                node_id_t         nb_node_addr_;    // Address of the neighbor node.
00178                double            sym_time_;        // The link is considered bidirectional until this time.
00179                double            asym_time_;       // The link is considered unidirectional until this time.
00180                double            lost_time_;       // The link is considered lost until this time (used for link layer notification).
00181                double            time_;            // Time at which this tuple expires and must be removed.
00182 
00183                inline node_id_t& local_node_addr() { return local_node_addr_; }
00184                inline node_id_t& nb_node_addr()    { return nb_node_addr_; }
00185                inline double&    sym_time()        { return sym_time_; }
00186                inline double&    asym_time()       { return asym_time_; }
00187                inline double&    lost_time()       { return lost_time_; }
00188                inline double&    time()            { return time_; }
00189 
00190             } OLSR_link_tuple;
00191 
00192 
00193         typedef struct OLSR_nb_tuple {             // A Neighbor Tuple.
00194 
00195                node_id_t         nb_node_addr_;    // Address of the neighbor node.
00196                uint8_t        status_;       // Neighbor Type and Link Type at the four less significant digits.
00197                uint8_t        willingness_;     // A value between 0 and 7 specifying the node's willingness to carry traffic on behalf of other nodes.
00198 
00199                inline node_id_t& nb_node_addr()    { return nb_node_addr_; }
00200                inline uint8_t&      status()       { return status_; }
00201                inline uint8_t&      willingness()     { return willingness_; }
00202 
00203             } OLSR_nb_tuple;
00204 
00205 
00206         typedef struct OLSR_nb2hop_tuple {            // A 2-hop Tuple.
00207 
00208                node_id_t         nb_node_addr_;    // Address of the neighbor node.
00209                node_id_t         nb2hop_addr_;     // Address of a 2-hop neighbor with a symmetric link to nb_node_addr.
00210                double            time_;            // Time at which this tuple expires and must be removed.
00211 
00212                inline node_id_t& nb_node_addr()    { return nb_node_addr_; }
00213                inline node_id_t& nb2hop_addr()     { return nb2hop_addr_; }
00214                inline double&    time()            { return time_; }
00215 
00216          } OLSR_nb2hop_tuple;
00217 
00218 
00219         typedef struct OLSR_mprsel_tuple {            // An MPR-Selector Tuple.
00220 
00221                node_id_t         node_addr_;       // Address of a node which have selected this node as a MPR.
00222                double            time_;            // Time at which this tuple expires and must be removed.
00223 
00224                inline node_id_t& node_addr()       { return node_addr_; }
00225                inline double&    time()            { return time_; }
00226 
00227          } OLSR_mprsel_tuple;
00228 
00229 
00230         typedef struct OLSR_dup_tuple {               // A Duplicate Tuple.
00231 
00232                node_id_t         addr_;            // Originator address of the message.
00233                uint16_t       seq_num_;         // Message sequence number.
00234                bool           retransmitted_;      // Indicates whether the message has been retransmitted or not.
00235                double            time_;            // Time at which this tuple expires and must be removed.
00236 
00237                inline node_id_t& addr()            { return addr_; }
00238                inline uint16_t&  seq_num()         { return seq_num_; }
00239                inline bool&      retransmitted()      { return retransmitted_; }
00240                inline double&    time()            { return time_; }
00241 
00242          } OLSR_dup_tuple;
00243 
00244 
00245          typedef struct OLSR_topology_tuple {         // A Topology Tuple.
00246 
00247                node_id_t         dest_addr_;       // Address of the destination.
00248                node_id_t         last_addr_;       // Address of a node which is a neighbor of the destination.
00249                uint16_t       seq_;          // Sequence number.
00250                double            time_;            // Time at which this tuple expires and must be removed.
00251 
00252                inline node_id_t& dest_addr()       { return dest_addr_; }
00253                inline node_id_t& last_addr()       { return last_addr_; }
00254                inline uint16_t&  seq()          { return seq_; }
00255                inline double&    time()            { return time_; }
00256 
00257           } OLSR_topology_tuple;
00258 
00259           typedef std::vector<OLSR_link_tuple*>       linkset_t;
00260           typedef std::vector<OLSR_nb_tuple*>         nbset_t;
00261           typedef std::vector<OLSR_nb2hop_tuple*>     nb2hopset_t;
00262           typedef std::set<node_id_t>              mprset_t;
00263           typedef std::vector<OLSR_mprsel_tuple*>     mprselset_t;
00264           typedef std::vector<OLSR_topology_tuple*>      topologyset_t;
00265           typedef std::vector<OLSR_dup_tuple*>        dupset_t;
00266 
00267           linkset_t     linkset_;
00268           nbset_t    nbset_;
00269           nb2hopset_t   nb2hopset_;
00270           mprset_t      mprset_;
00271           mprselset_t   mprselset_;
00272           topologyset_t topologyset_;
00273           dupset_t      dupset_;
00274 
00275 
00276             /**********************************************************************/
00277             //                        Messages in OLSR                             /
00278             /**********************************************************************/
00279           typedef struct OLSR_hello_msg {                   // OLSR_hello_msg (inside OLSR_hello).
00280 
00281             uint8_t           link_code_;
00282             uint16_t       link_msg_size_;
00283             node_id_t         nb_addrs_[OLSR_MAX_ADDRS];
00284             int               nb_addrs_count_;
00285 
00286             inline uint8_t&      link_code()                { return link_code_; }
00287             inline uint16_t&  link_msg_size()               { return link_msg_size_; }
00288             inline node_id_t& neighbor_addr_list(int i)     { return nb_addrs_[i]; }
00289             inline int        neighbor_addr_count()         { return nb_addrs_count_;}
00290 
00291             inline uint32_t   size()                     // size of each OLSR_hello_msg
00292             {
00293                return OLSR_HELLO_MSG_HDR_SIZE + nb_addrs_count_ * 4;
00294             }
00295 
00296             inline uint32_t size_pnt()
00297          {
00298                uint32_t a = OLSR_HELLO_MSG_HDR_SIZE+nb_addrs_count_*4;
00299 
00300                return a;
00301           }
00302 
00303           } OLSR_hello_msg;
00304 
00305 
00306           typedef struct OLSR_hello {                             // OLSR_hello
00307          uint8_t           htime_;
00308          uint8_t              willingness_;
00309          OLSR_hello_msg       hello_body_[OLSR_MAX_HELLOS];
00310          int                  hello_msg_count_;
00311 
00312          inline uint8_t&         htime()                 { return htime_;       }
00313          inline uint8_t&         willingness()           { return willingness_; }
00314          inline OLSR_hello_msg&  hello_msg(int i)        { return hello_body_[i]; }
00315          inline int           hello_msg_count()       { return hello_msg_count_;}
00316 
00317          inline uint32_t size()                                // size of OLSR_hello ( including all OLSR_hello_msg )
00318          {
00319             uint32_t sz = OLSR_HELLO_HDR_SIZE;
00320 
00321             for (int i = 0; i < hello_msg_count_; i++)
00322                sz += hello_msg(i).size();
00323 
00324             return sz;
00325          }
00326 
00327           } OLSR_hello;
00328 
00329 
00330 
00331             typedef struct OLSR_tc {                           // OLSR_tc
00332 
00333              uint16_t         ansn_;
00334              node_id_t        adv_nb_addrs_[OLSR_MAX_ADDRS];
00335              int              adv_nb_addrs_count_;
00336 
00337              inline  uint16_t&   ansn()                     { return ansn_; }
00338              inline  node_id_t&  adv_neighbor_addr_list(int i) { return adv_nb_addrs_[i]; }
00339              inline int       adv_neighbor_addrs_count()    { return adv_nb_addrs_count_;}
00340 
00341              inline  uint32_t    size()                        // size of OLSR_tc
00342             {
00343                return OLSR_TC_HDR_SIZE + adv_nb_addrs_count_*4;
00344             }
00345 
00346              } OLSR_tc;
00347 
00348 
00349             typedef struct OLSR_msg {                       // OLSR_msg
00350 
00351                uint8_t           msg_id_;                // Message type.
00352                uint8_t           vtime_;                    // Validity time.
00353                uint16_t       msg_size_;                 // Message size (in bytes).
00354                node_id_t         orig_addr_;                // Address of the node which generated this message.
00355                uint8_t           ttl_;                   // Time to live (in hops).
00356                uint8_t           hop_count_;                // Number of hops which the message has taken.
00357                uint16_t       msg_seq_num_;              // Message sequence number.
00358 
00359                union {  OLSR_hello  hello_;
00360                   OLSR_tc     tc_;
00361                   } msg_body_;                           // Message body.
00362 
00363                inline   uint8_t& msg_id()                { return msg_id_; }
00364                inline   uint8_t& vtime()                    { return vtime_; }
00365                inline   uint16_t&   msg_size()                 { return msg_size_; }
00366                inline   node_id_t&  originator_addr()          { return orig_addr_; }
00367                inline   uint8_t& ttl()                   { return ttl_; }
00368                inline   uint8_t& hop_count()                { return hop_count_; }
00369                inline   uint16_t&   msg_seq_num()              { return msg_seq_num_; }
00370 
00371                inline   OLSR_hello& hello()                    { return msg_body_.hello_; }
00372                inline   OLSR_tc& tc()                    { return msg_body_.tc_; }
00373 
00374                inline  uint32_t size()                      // size of OLSR_msg
00375                {
00376                   uint32_t sz = OLSR_MSG_HDR_SIZE;
00377                   if (msg_id() == HELLO)
00378                      sz += hello().size();
00379                   else if (msg_id() == TC)
00380                      sz += tc().size();
00381                   return sz;
00382                }
00383 
00384             } OLSR_msg;
00385 
00386 
00387             /**********************************************************************/
00388             //                OLSR function & Node states' manipulation            /
00389             /**********************************************************************/
00390            inline linkset_t&        linkset()      { return linkset_; }
00391            inline nbset_t&       nbset()        { return nbset_; }
00392            inline nb2hopset_t&      nb2hopset()    { return nb2hopset_; }
00393            inline mprset_t&         mprset()    { return mprset_; }
00394            inline mprselset_t&      mprselset()    { return mprselset_; }
00395            inline topologyset_t&    topologyset()  { return topologyset_; }
00396            inline dupset_t&         dupset()    { return dupset_; }
00397 
00398            void                  nb_loss(OLSR_link_tuple* tuple);                // Case of Neighbor loss
00399 
00400             void                 routing_table_computation();                       // Compute the Routing Table
00401          int                  degree(OLSR_nb_tuple*);                         // This function is used for calculating the MPR Set
00402          bool                 route_exists(node_id_t destination);               // Check whether there is an entry in the local routing table for the destination in the received message
00403 
00404             void                 mpr_computation();                              // Neighbor Detection & Calculation of the MPR nodes
00405            bool                  find_mpr_addr(node_id_t);                       // based on the 1-hop & 2-hop neighbor information
00406            void                  insert_mpr_addr(node_id_t);
00407            void                  clear_mprset();
00408 
00409             void                 process_hello(BroadcastHelloMessage&, node_id_t);     // HELLO processing
00410             void                 process_tc(BroadcastTcMessage&, node_id_t);           // TC processing
00411             void                 process_data(RoutingMessage&, node_id_t);             // DATA processing
00412             void                 forward_hello(node_id_t, BroadcastHelloMessage&, OLSR_dup_tuple*); // HELLO forwarding
00413             void                 forward_tc(node_id_t, BroadcastTcMessage&, OLSR_dup_tuple*);      // TC forwarding
00414 
00415          void                 broadcast_hello();                              // Hello generation & broadcast
00416          void                 broadcast_tc();                                 // TC generation & broadcast
00417 
00418             void                 link_sensing(BroadcastHelloMessage&, node_id_t);
00419             void                 populate_nbset(BroadcastHelloMessage&);               // Updates the Neighbor Set according to the information contained in a new received HELLO message
00420             void                 populate_nb2hopset(BroadcastHelloMessage&);           // Neighbor Detection & Updating of the 2-hop_Neighbor_Tuple based on the update of the Link_Tuple
00421             void                 populate_mprselset(BroadcastHelloMessage&);           // Neighbor Detection & Calculation of the MPR Selector set for the MPR nodes based on the 1-hop & 2-hop neighbor information
00422 
00423             void                 add_dup_tuple(OLSR_dup_tuple*);
00424             void                 rm_dup_tuple(OLSR_dup_tuple*);
00425          OLSR_dup_tuple*         find_dup_tuple(node_id_t, uint16_t);
00426          void                 erase_dup_tuple(OLSR_dup_tuple*);
00427          void                 insert_dup_tuple(OLSR_dup_tuple*);
00428 
00429             void                 add_link_tuple(OLSR_link_tuple*, uint8_t);            // Link Set manipulation
00430             void                 rm_link_tuple(OLSR_link_tuple*);
00431             void                 updated_link_tuple(OLSR_link_tuple*);              // Update a Link_Tuple, also update the corresponding neighbor tuple if it is needed
00432            OLSR_link_tuple*         find_link_tuple(node_id_t);
00433            OLSR_link_tuple*         find_sym_link_tuple(node_id_t, double);
00434            void                  erase_link_tuple(OLSR_link_tuple*);
00435            void                  insert_link_tuple(OLSR_link_tuple*);
00436 
00437             void                 add_nb_tuple(OLSR_nb_tuple*);
00438             void                 rm_nb_tuple(OLSR_nb_tuple*);
00439            OLSR_nb_tuple*           find_nb_tuple(node_id_t);
00440            OLSR_nb_tuple*           find_nb_tuple(node_id_t, uint8_t);
00441            OLSR_nb_tuple*           find_sym_nb_tuple(node_id_t);
00442            void                  erase_nb_tuple(OLSR_nb_tuple*);
00443            void                  insert_nb_tuple(OLSR_nb_tuple*);
00444 
00445             void                 add_nb2hop_tuple(OLSR_nb2hop_tuple*);
00446             void                 rm_nb2hop_tuple(OLSR_nb2hop_tuple*);
00447            OLSR_nb2hop_tuple*       find_nb2hop_tuple(node_id_t, node_id_t);
00448            void                  erase_nb2hop_tuple(OLSR_nb2hop_tuple*);
00449            void                  erase_nb2hop_tuples(node_id_t);
00450            void                  erase_nb2hop_tuples(node_id_t, node_id_t);
00451            void                  insert_nb2hop_tuple(OLSR_nb2hop_tuple*);
00452 
00453             void                 add_mprsel_tuple(OLSR_mprsel_tuple*);
00454             void                 rm_mprsel_tuple(OLSR_mprsel_tuple*);
00455            OLSR_mprsel_tuple*       find_mprsel_tuple(node_id_t);
00456            void                  erase_mprsel_tuple(OLSR_mprsel_tuple*);               // Called by rm_mprsel_tuple()
00457            void                  erase_mprsel_tuples(node_id_t);
00458            void                  insert_mprsel_tuple(OLSR_mprsel_tuple*);           // Called by add_mprsel_tuple()
00459 
00460             void                 add_topology_tuple(OLSR_topology_tuple*);
00461             void                 rm_topology_tuple(OLSR_topology_tuple*);
00462            OLSR_topology_tuple*     find_topology_tuple(node_id_t, node_id_t);
00463            OLSR_topology_tuple*     find_newer_topology_tuple(node_id_t, uint16_t);
00464            void                  erase_topology_tuple(OLSR_topology_tuple*);           // Called by rm_topology_tuple()
00465            void                  erase_older_topology_tuples(node_id_t, uint16_t);
00466            void                  insert_topology_tuple(OLSR_topology_tuple*);       // Called by add_topology_tuple()
00467 
00468            static double            emf_to_seconds(uint8_t);
00469            static uint8_t           seconds_to_emf(double);
00470 
00471          inline uint16_t            msg_seq()                                    // Increments message sequence number and returns the new value.
00472                               {
00473                                  msg_seq_ = (msg_seq_ + 1)%(OLSR_MAX_SEQ_NUM + 1);
00474                                  return msg_seq_;
00475                               }
00476 
00477          inline int              willingness()
00478                               {
00479                                  return OLSR_WILL_DEFAULT;
00480                               }
00481 
00482 
00483    private:
00484          //int random_limit=1;
00485          //double random(random_limit);
00486            void timer_elapsed( void *userdata );                                          // Methods called by Timer
00487 
00488            void timer_expire_link_tuple( OLSR_link_tuple* );                              // Link_tuple     expiration
00489            void timer_expire_nb2hop_tuple( OLSR_nb2hop_tuple* );                          // Nb2hop_tuple   expiration
00490            void timer_expire_topology_tuple( OLSR_topology_tuple* );                      // Topology_tuple expiration
00491            void timer_expire_mprsel_tuple( OLSR_mprsel_tuple* );                          // Mprsel_tuple   expiration
00492            void timer_expire_dup_tuple( OLSR_dup_tuple* );                                // Dup_tuple      expiration
00493 
00494            void receive( node_id_t from, size_t len, block_data_t *data );                   //@name Methods called by RadioModel
00495            void print_routing_table( RoutingTable rt );
00496 
00497            millis_t startup_time_;
00498            millis_t work_period_;
00499            millis_t delay_;                                                      // delay for the retransmission of a message
00500 
00501            //millis_t link_tuple_expire_;                                           // expiration of link_tuple
00502            //millis_t nb_tuple_expire_;                                             // expiration of nb_tuple
00503            //millis_t nb2hop_tuple_expire_;                                         // expiration of nb2hop_tuple
00504            //millis_t topology_tuple_expire_;                                          // expiration of link_tuple
00505            //millis_t mprsel_tuple_expire_;                                         // expiration of mprsel_tuple
00506            //millis_t dup_tuple_expire_;                                            // expiration of dup_tuple
00507 
00508             int nb_addrs_count_before[OLSR_MAX_HELLOS];
00509 
00510            short seconds_hello;
00511            short seconds_tc;
00512 
00513            Os *os_;
00514 
00515            RoutingTable routing_table_;                                                // Routing table
00516 
00517 
00518            uint16_t msg_seq_;
00519            uint16_t ansn_;
00520    };
00521 
00522    // -----------------------------------------------------------------------
00523    // -----------------------------------------------------------------------
00524    // -----------------------------------------------------------------------
00525    template<typename OsModel_P,
00526             typename RoutingTable_P,
00527             typename Clock_P,
00528             typename Radio_P,
00529             typename Debug_P>
00530    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00531    OlsrRouting()
00532       :  startup_time_        ( 2000 ),
00533          work_period_         ( 5000 ),
00534          delay_               ( rand()%50 ),
00535          os_( 0 )
00536    {
00537 
00538 
00539 
00540        msg_seq_      = OLSR_MAX_SEQ_NUM;                 // Message sequence number counter
00541        ansn_      = OLSR_MAX_SEQ_NUM;                 // Advertised Neighbor Set sequence number.
00542    };
00543    // -----------------------------------------------------------------------
00544    template<typename OsModel_P,
00545             typename RoutingTable_P,
00546             typename Clock_P,
00547             typename Radio_P,
00548             typename Debug_P>
00549    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00550    ~OlsrRouting()
00551    {
00552 #ifdef DEBUG_OLSRROUTING
00553       Debug::debug( os(), "OlsrRouting: Destroyed\n" );
00554 #endif
00555    };
00556    // -----------------------------------------------------------------------
00557    template<typename OsModel_P,
00558             typename RoutingTable_P,
00559             typename Clock_P,
00560             typename Radio_P,
00561             typename Debug_P>
00562    void
00563    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00564    enable( void )
00565    {
00566 #ifdef DEBUG_OLSRROUTING
00567       Debug::debug( os(), "OlsrRouting: Boot for %i\n", Radio::id( os() ) );
00568 #endif
00569 
00570       seconds_tc = 0;
00571       seconds_hello = 0;
00572 
00573       Radio::enable( os() );
00574       Radio::template reg_recv_callback<self_type, &self_type::receive>( os(), this );
00575       Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), startup_time_, this, 0 );
00576    }
00577    // -----------------------------------------------------------------------
00578    template<typename OsModel_P,
00579             typename RoutingTable_P,
00580             typename Clock_P,
00581             typename Radio_P,
00582             typename Debug_P>
00583    void
00584    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00585    disable( void )
00586    {
00587 #ifdef DEBUG_OLSRROUTING
00588       Debug::debug( os(), "OlsrRouting: Disable\n" );
00589 #endif
00590    }
00591    // -----------------------------------------------------------------------
00592    template<typename OsModel_P,
00593             typename RoutingTable_P,
00594             typename Clock_P,
00595             typename Radio_P,
00596             typename Debug_P>
00597    void
00598    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P,Radio_P, Debug_P>::
00599    send( node_id_t destination, size_t len, block_data_t *data )        // Send the DATA message according to the routing table entry
00600    {
00601      Debug::debug( os(), "OlsrRouting: START TO SEND DATA.\n" );
00602       RoutingTableIterator it = routing_table_.find( destination );
00603       if ( it != routing_table_.end() && it->second.next_addr != Radio::NULL_NODE_ID )
00604       {
00605        RoutingMessage message;
00606          message.set_msg_id( DATA );
00607          message.set_source( Radio::id(os()) );
00608          message.set_destination( destination );
00609          message.set_payload( len, data );
00610          Radio::send( os(), it->second.next_addr, message.buffer_size(), (uint8_t*)&message );
00611 
00612 #ifdef DEBUG_OLSRROUTING
00613          Debug::debug( os(), "OlsrRouting: Send DATA to %i over %i.\n", message.destination(), it->second.next_addr );
00614 #endif
00615       }
00616 #ifdef DEBUG_OLSRROUTING
00617       else
00618          Debug::debug( os(), "OlsrRouting: Send failed. Route to Destination not known.\n" );
00619 #endif
00620    }
00621 
00622    // ----------------------------------------------------------------------
00623    template<typename OsModel_P,
00624           typename RoutingTable_P,
00625           typename Clock_P,
00626           typename Radio_P,
00627           typename Debug_P>
00628    void
00629    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00630 	broadcast_hello()
00631    {
00632       OLSR_msg msg;
00633       BroadcastHelloMessage hellomessage;
00634 
00635       time_t now = Clock::time( os() );
00636 
00637       hellomessage.set_msg_id( HELLO );
00638       hellomessage.set_vtime( seconds_to_emf(OLSR_NEIGHB_HOLD_TIME) );
00639       hellomessage.set_originator_addr( Radio::id(os()) );
00640       hellomessage.set_ttl(1);
00641       hellomessage.set_hop_count(0);
00642       hellomessage.set_msg_seq_num( msg_seq() );
00643       hellomessage.set_htime( seconds_to_emf(OLSR_HELLO_INTERVAL) );
00644       hellomessage.set_willingness( willingness() );
00645 
00646       msg.hello().hello_msg_count_ = 0;
00647       msg.msg_id() = HELLO;
00648 
00649       std::map< uint8_t, int> linkcodes_count;                             // <link_code, link_code_cnt>
00650 
00651        if (!linkset().size())
00652        {
00653          Debug::debug( os(), "Empty HELLO!!!!!! \n");
00654        }
00655 
00656       for (typename linkset_t::iterator it = linkset().begin(); it != linkset().end(); it++)
00657       {
00658             OLSR_link_tuple* link_tuple = *it;
00659 
00660             if (link_tuple->local_node_addr() == Radio::id(os()) && link_tuple->time() >= now )// for each tuple in the LINK_SET, produce a LINK_CODE and
00661                                                                         // generate a hello_msg corresponding to this LINK_CODE
00662             {
00663                uint8_t link_type, nb_type, link_code;
00664 
00665                // Establishes LINK_TYPE for this entry
00666                if (link_tuple->lost_time() >= now)
00667                   link_type = OLSR_LOST_LINK;                                       // LINK_TYPE = LOST_LINK
00668                else if (link_tuple->sym_time() >= now)
00669                   link_type = OLSR_SYM_LINK;                                     // LINK_TYPE = SYM_LINK
00670                else if (link_tuple->asym_time() >= now)
00671                   link_type = OLSR_ASYM_LINK;                                       // LINK_TYPE = ASYM_LINK
00672                else
00673                   link_type = OLSR_LOST_LINK;                                       // LINK_TYPE = LOST_LINK
00674 
00675                // Establishes NEIGHBOR_TYPE for this entry
00676                if (find_mpr_addr(link_tuple->nb_node_addr()))
00677                   nb_type = OLSR_MPR_NEIGH;                                      // NB_TYPE = MPR_NEIGH
00678                else {
00679                   bool ok = false;
00680                   for (typename nbset_t::iterator nb_it = nbset().begin(); nb_it != nbset().end(); nb_it++)
00681                   {
00682                      OLSR_nb_tuple* nb_tuple = *nb_it;
00683                      if (nb_tuple->nb_node_addr() == link_tuple->nb_node_addr())
00684                      {
00685                         if (nb_tuple->status() == OLSR_STATUS_SYM)
00686                            nb_type = OLSR_SYM_NEIGH;                          // NB_TYPE = SYM_NEIGH
00687                         else if (nb_tuple->status() == OLSR_STATUS_NOT_SYM)
00688                            nb_type = OLSR_NOT_NEIGH;                          // NB_TYPE = NOT_NEIGH
00689                         else
00690                            {
00691                               fprintf(stderr, "There is a neighbor tuple with an unknown status!\n");
00692                               exit(1);
00693                            }
00694                         ok = true;
00695                         break;
00696                      }
00697                   }
00698 
00699                   if (!ok)
00700                   {
00701                      fprintf(stderr, "Link tuple has no corresponding Neighbor tuple\n");
00702                      exit(1);
00703                   }
00704                }
00705 
00706                link_code = (link_type & 0x03) | ((nb_type << 2) & 0x0f);                  // LINK_CODE = LINK_TYPE + NB_TYPE, for this link_tuple entry
00707 
00708 
00709                // For each LINK_CODE, generate a hello_msg
00710                int count = msg.hello().hello_msg_count_;                            // count = #_hello_msg in OLSR_hello = hello_msg_count_, initially 0
00711                for ( int p = 0; p < count; p++ )
00712                {
00713                   nb_addrs_count_before[count] += msg.hello().hello_msg(p).neighbor_addr_count();
00714                }
00715 
00716                typename std::map<uint8_t, int>::iterator pos = linkcodes_count.find(link_code);
00717 
00718             if (pos == linkcodes_count.end())                                    // No such LINK_CODE
00719             {
00720                linkcodes_count[link_code] = count;                               // linkcodes_count[link_code, link_code_cnt]
00721                assert(count >= 0 && count < OLSR_MAX_HELLOS);
00722 
00723                msg.hello().hello_msg(count).nb_addrs_count_ = 0;
00724                hellomessage.set_link_code(count, nb_addrs_count_before[count], link_code);                      // Set the link_code of hello_msg[count]
00725                msg.hello().hello_msg_count_++;
00726             }
00727             else                 // there is already existing item in the linkcodes_count with certain link_code
00728                count = (*pos).second;  // count is set with number of OLSR_hello_msg with the given link_code
00729 
00730             int i = msg.hello().hello_msg(count).nb_addrs_count_;
00731             msg.hello().hello_msg(count).nb_addrs_count_++;
00732 
00733             assert(count >= 0 && count < OLSR_MAX_HELLOS);
00734             assert(i >= 0 && i < OLSR_MAX_ADDRS);
00735 
00736             uint32_t pnt = NULL;
00737             pnt= msg.hello().hello_msg(count).size_pnt();
00738 
00739             node_id_t* pnt2 = NULL;
00740             pnt2 = &(link_tuple->nb_node_addr());
00741 
00742             hellomessage.set_neighbor_addr_list(count, nb_addrs_count_before[count], i, pnt2);                    // Set the neighbor_addr_list[i] of hello_msg[count]
00743             hellomessage.set_link_msg_size(count, nb_addrs_count_before[count], &pnt ); // Set the link_msg_size of hello_msg[count]
00744             hellomessage.set_neighbor_addr_count(count, nb_addrs_count_before[count], msg.hello().hello_msg(count).nb_addrs_count_);         // Set the neighbor_addr_count of hello[count]
00745 
00746             }
00747        }
00748 
00749        hellomessage.set_msg_size( msg.size() );
00750        hellomessage.set_hello_msgs_count( msg.hello().hello_msg_count_ );
00751 
00752        Radio::send( os(), Radio::BROADCAST_ADDRESS, hellomessage.buffer_size(), (uint8_t*)&hellomessage);
00753        Debug::debug( os(), "%i send HELLO with %i hello_msg! \n", Radio::id(os()), msg.hello().hello_msg_count_ );
00754    }
00755    // ----------------------------------------------------------------------
00756    template<typename OsModel_P,
00757           typename RoutingTable_P,
00758           typename Clock_P,
00759           typename Radio_P,
00760           typename Debug_P>
00761    void
00762    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00763 	broadcast_tc()
00764    {
00765        OLSR_msg msg;
00766        BroadcastTcMessage tcmessage;
00767 
00768        msg.msg_id() = TC;
00769        msg.vtime() = seconds_to_emf(OLSR_TOP_HOLD_TIME);
00770        msg.originator_addr() = Radio::id(os());
00771        msg.ttl() = 255;
00772        msg.hop_count() = 0;
00773        msg.msg_seq_num() = msg_seq();
00774        msg.tc().ansn() = ansn_;
00775        msg.tc().adv_nb_addrs_count_ = 0;
00776 
00777        tcmessage.set_msg_id( TC );
00778        tcmessage.set_vtime( seconds_to_emf(OLSR_TOP_HOLD_TIME) );
00779        tcmessage.set_originator_addr( Radio::id(os()) );
00780        tcmessage.set_ttl( 255 );
00781        tcmessage.set_hop_count( 0 );
00782        tcmessage.set_msg_seq_num( msg_seq() );
00783        tcmessage.set_ansn( ansn_ );
00784 
00785        if (!mprselset().size())
00786        {
00787          Debug::debug( os(), "Empty TC!!!!!! \n");
00788        }
00789 
00790        for (typename mprselset_t::iterator it = mprselset().begin(); it != mprselset().end(); it++)      // TC message contains the MPR Selector nodes of this MPR node
00791        {
00792          OLSR_mprsel_tuple* mprsel_tuple = *it;
00793             int count = msg.tc().adv_nb_addrs_count_;
00794 
00795             assert(count >= 0 && count < OLSR_MAX_ADDRS);
00796             msg.tc().adv_neighbor_addr_list(count) = mprsel_tuple->node_addr();           // each MPR selector nodes' address will be included in the TC message
00797             msg.tc().adv_nb_addrs_count_++;
00798 
00799          Debug::debug( os(), "Put node %i into TC message \n", &(mprsel_tuple->node_addr()) );
00800             tcmessage.set_adv_neighbor_addr_list( count,  &(mprsel_tuple->node_addr()) );
00801        }
00802 
00803        tcmessage.set_msg_size( msg.size() );
00804 
00805       Radio::send( os(), Radio::BROADCAST_ADDRESS, msg.size(), (uint8_t*)&tcmessage );
00806 
00807       Debug::debug( os(), "%i send TC with %i NB address! \n", Radio::id(os()), msg.tc().adv_nb_addrs_count_ );
00808    }
00809    // -----------------------------------------------------------------------
00810    template<typename OsModel_P,
00811             typename RoutingTable_P,
00812             typename Clock_P,
00813             typename Radio_P,
00814             typename Debug_P>
00815    void
00816    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00817    timer_elapsed( void* userdata )
00818    {
00819       seconds_hello++;
00820       seconds_tc++;
00821 
00822      if ( seconds_hello == OLSR_HELLO_INTERVAL)
00823      {
00824         broadcast_hello();
00825         seconds_hello = 0;
00826      }
00827 
00828      if ( seconds_tc == OLSR_TC_INTERVAL)
00829      {
00830         broadcast_tc();
00831         seconds_tc = 0;
00832      }
00833 
00834       print_routing_table( routing_table_ );
00835 
00836       Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), work_period_, this, 0 );
00837    }
00838 
00839    // -----------------------------------------------------------------------
00840    template<typename OsModel_P,
00841             typename RoutingTable_P,
00842             typename Clock_P,
00843             typename Radio_P,
00844             typename Debug_P>
00845    void
00846    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00847    timer_expire_link_tuple( OLSR_link_tuple* tuple )// Removes link_tuple if expired.
00848                                        // Else if symmetric time has expired then it is assumed a neighbor loss, the timer is rescheduled to expire at tuple_->time().
00849                                        // Otherwise the timer is rescheduled to expire at the minimum between tuple_->time() and tuple_->sym_time().
00850    {
00851       time_t now = Clock::time( os() );
00852 
00853       if (tuple->time() < now)
00854       {
00855          rm_link_tuple(tuple);
00856          delete tuple;
00857          delete this;
00858       }
00859       else if (tuple->sym_time() < now)
00860       {
00861          nb_loss(tuple);
00862          Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), ( (tuple->time()) - now ), this, 0 );
00863       }
00864       else
00865           Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), ( MIN( tuple->time(), tuple->sym_time()) - now ), this, 0 );
00866 
00867    }
00868 
00869    // -----------------------------------------------------------------------
00870    /*template<typename OsModel_P,
00871             typename RoutingTable_P,
00872             typename Clock_P,
00873             typename Radio_P,
00874             typename Debug_P>
00875    void
00876    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00877    timer_expire_nb_tuple( OLSR_nb_tuple* tuple )
00878    {
00879       time_t now = Clock::time( os() );
00880 
00881       if (tuple.time() < now)
00882       {
00883          rm_nb_tuple(tuple);
00884          delete tuple;
00885          delete this;
00886       }
00887 
00888       Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), nb_tuple_expire_, this, 0 );
00889    }
00890    */
00891    // -----------------------------------------------------------------------
00892    template<typename OsModel_P,
00893             typename RoutingTable_P,
00894             typename Clock_P,
00895             typename Radio_P,
00896             typename Debug_P>
00897    void
00898    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00899    timer_expire_nb2hop_tuple( OLSR_nb2hop_tuple* tuple )
00900    {
00901       time_t now = Clock::time( os() );
00902 
00903       if (tuple->time() < now)
00904       {
00905          rm_nb2hop_tuple(tuple);
00906          delete tuple;
00907          delete this;
00908       }
00909       else
00910       {
00911          Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), ( (tuple->time()) - now ), this, 0 );
00912       }
00913 
00914 
00915    }
00916 
00917    // -----------------------------------------------------------------------
00918    template<typename OsModel_P,
00919             typename RoutingTable_P,
00920             typename Clock_P,
00921             typename Radio_P,
00922             typename Debug_P>
00923    void
00924    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00925    timer_expire_topology_tuple( OLSR_topology_tuple* tuple )
00926    {
00927       time_t now = Clock::time( os() );
00928 
00929       if (tuple->time() < now)
00930       {
00931          rm_topology_tuple(tuple);
00932          delete tuple;
00933          delete this;
00934       }
00935       else
00936          {
00937             Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), ( (tuple->time()) - now ), this, 0 );
00938          }
00939    }
00940 
00941    // -----------------------------------------------------------------------
00942    template<typename OsModel_P,
00943             typename RoutingTable_P,
00944             typename Clock_P,
00945             typename Radio_P,
00946             typename Debug_P>
00947    void
00948    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00949    timer_expire_mprsel_tuple( OLSR_mprsel_tuple* tuple )
00950    {
00951       //time_t now = Clock::time( os() );
00952       double  now = Clock::time( os() );
00953 
00954       if (tuple->time() < now)
00955       {
00956          rm_mprsel_tuple(tuple);
00957          delete tuple;
00958          delete this;
00959       }
00960       else
00961          {
00962             Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), ( (tuple->time()) - now ), this, 0 );
00963          }
00964    }
00965 
00966    // -----------------------------------------------------------------------
00967    template<typename OsModel_P,
00968             typename RoutingTable_P,
00969             typename Clock_P,
00970             typename Radio_P,
00971             typename Debug_P>
00972    void
00973    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00974    timer_expire_dup_tuple( OLSR_dup_tuple* tuple )
00975    {
00976       time_t now = Clock::time( os() );
00977 
00978       if (tuple->time() < now)
00979       {
00980          rm_dup_tuple(tuple);
00981          delete tuple;
00982          delete this;
00983       }
00984       else
00985          {
00986             Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), ( (tuple->time()) - now ), this, 0 );
00987          }
00988    }
00989    // -----------------------------------------------------------------------
00990    template<typename OsModel_P,
00991             typename RoutingTable_P,
00992             typename Clock_P,
00993             typename Radio_P,
00994             typename Debug_P>
00995    void
00996    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
00997    receive( node_id_t from, size_t len, block_data_t *data )
00998    {
00999       if ( from == Radio::id(os()) )                                 // Coming back to myself, Radio::id(os()) is the id of this receiving node
01000          return;
01001 
01002       uint8_t msg_id = *data;
01003 
01004       switch (msg_id)
01005       {
01006              case HELLO:                                          // HELLO
01007              {
01008                BroadcastHelloMessage *message = (BroadcastHelloMessage*)data;
01009                OLSR_dup_tuple *duplicated = find_dup_tuple( message->originator_addr(), message->msg_seq_num() );
01010 
01011                if (duplicated == NULL)
01012                {
01013                   process_hello(*message, from);
01014                }
01015                else
01016                {
01017                   forward_hello(from, *message, duplicated);
01018                }
01019 
01020                break;
01021              }
01022              case TC:                                             // TC
01023              {
01024                BroadcastTcMessage *message = (BroadcastTcMessage*) data;
01025                OLSR_dup_tuple *duplicated = find_dup_tuple( message->originator_addr(), message->msg_seq_num() );
01026 
01027                if (duplicated == NULL)
01028                {
01029                   process_tc(*message, from);
01030                }
01031                else
01032                {
01033                   forward_tc(from, *message, duplicated);
01034                }
01035 
01036                 break;
01037              }
01038              case DATA:                                           // DATA
01039              {
01040                 RoutingMessage *message = (RoutingMessage*) data;
01041                 process_data(*message, from);
01042 
01043                 break;
01044              }
01045              default:
01046              {
01047                  Debug::debug(os(), "%i received UNRECOGNIZED message type [%i]\n", Radio::id(os()), msg_id);
01048              }
01049          }
01050 
01051          routing_table_computation();                                // After processing all OLSR messages, recompute routing table
01052 
01053    }
01054 
01055    // -----------------------------------------------------------------------
01056    // brief Processes a HELLO message following RFC 3626 specification.
01057    // Link sensing & population of the Neighbor Set & population of 2-hop Neighbor Set & population of MPR Selector Set
01058 
01059    // param msg      the OLSR hello message
01060    // param sender      the address of the node where the message was sent
01061 
01062    template<typename OsModel_P,
01063             typename RoutingTable_P,
01064             typename Clock_P,
01065             typename Radio_P,
01066             typename Debug_P>
01067    void
01068    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01069    process_hello(BroadcastHelloMessage& message, node_id_t sender)
01070    {
01071     Debug::debug(os(), "%i received HELLO FROM %i of SIZE %i with %i HELLO_MSG \n", Radio::id(os()), message.originator_addr(), message.msg_size(), message.hello_msgs_count() );
01072 
01073     link_sensing(message, sender);
01074       populate_nbset(message);
01075       populate_nb2hopset(message);
01076       mpr_computation();
01077       populate_mprselset(message);
01078    }
01079 
01080    // -----------------------------------------------------------------------
01081    // brief Updates Link Set according to a new received HELLO message (following RFC 3626 specification). Neighbor Set is also updated if needed
01082 
01083    // param msg      the OLSR message which contains the HELLO message
01084    // param sender      the address of the node where the message was sent
01085 
01086    template<typename OsModel_P,
01087             typename RoutingTable_P,
01088             typename Clock_P,
01089             typename Radio_P,
01090             typename Debug_P>
01091    void
01092    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01093    link_sensing(BroadcastHelloMessage& message, node_id_t sender)
01094    {
01095 
01096 #ifdef DEBUG_OLSRROUTING
01097       Debug::debug(os(), "Link Sensing receiving Hello with %i hello_msgn inside!!!\n", message.hello_msgs_count() );
01098 #endif
01099 
01100    time_t now        = Clock::time( os() );
01101 
01102    // Construct OLSR_hello from BroadcastHelloMessage& message
01103    OLSR_hello hello;
01104    hello.htime_         = message.htime();
01105    hello.willingness_      = message.willingness();
01106    hello.hello_msg_count_  = message.hello_msgs_count();
01107    for (int i = 0; i < hello.hello_msg_count_; i++ )
01108    {
01109       hello.hello_body_[i].link_code_     = message.link_code(i, nb_addrs_count_before[i]);
01110       hello.hello_body_[i].link_msg_size_    = message.link_msg_size(i, nb_addrs_count_before[i]);
01111       hello.hello_body_[i].nb_addrs_count_   = message.neighbor_addr_count(i, nb_addrs_count_before[i]);
01112       for ( int j = 1; j < message.neighbor_addr_count(i, nb_addrs_count_before[i]); j++ )
01113       {
01114          hello.hello_body_[i].nb_addrs_[j] = message.neighbor_addr_list(i, j, nb_addrs_count_before[i]);
01115       }
01116 
01117    }
01118 
01119       bool updated      = false;
01120       bool created      = false;
01121 
01122       OLSR_link_tuple* link_tuple = find_link_tuple(sender);
01123       if (link_tuple == NULL) {                    // Create a new tuple
01124 
01125          link_tuple                 = new OLSR_link_tuple;
01126          link_tuple->nb_node_addr()    = sender;
01127          link_tuple->local_node_addr() = Radio::id(os());
01128          link_tuple->sym_time()        = now - 1;
01129          link_tuple->lost_time()       = 0.0;
01130          link_tuple->time()            = now + emf_to_seconds(message.vtime());
01131 #ifdef DEBUG_OLSRROUTING
01132          Debug::debug(os(), "Adding new link_tuple!!! \n");
01133 #endif
01134          add_link_tuple(link_tuple, hello.willingness());
01135          created = true;
01136       }
01137       else                                   // Update an existing tuple
01138       {
01139 #ifdef DEBUG_OLSRROUTING
01140    Debug::debug(os(), "Update an existing tuple!!! \n");
01141 #endif
01142          updated = true;
01143       }
01144 
01145     link_tuple->asym_time() = now + emf_to_seconds(message.vtime());
01146 
01147       assert(hello.hello_msg_count_ >= 0 && hello.hello_msg_count_ <= OLSR_MAX_HELLOS);
01148       for (int i = 0; i < hello.hello_msg_count_; i++)            // for each the OLSR_hello_msg inside OLSR_hello
01149       {
01150          OLSR_hello_msg& hello_msg = hello.hello_msg(i);
01151          int lt = hello_msg.link_code() & 0x03;
01152          int nt = hello_msg.link_code() >> 2;
01153                                           // We must not process invalid advertised links
01154          if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) || (nt != OLSR_SYM_NEIGH && nt != OLSR_MPR_NEIGH && nt != OLSR_NOT_NEIGH))
01155             continue;
01156 
01157          assert(hello_msg.nb_addrs_count_ >= 0 && hello_msg.nb_addrs_count_ <= OLSR_MAX_ADDRS);
01158          for (int j = 0; j < hello_msg.nb_addrs_count_; j++)      // for each the Neighbor_Interface_Address inside a OLSR_hello_msg
01159          {
01160             if (hello_msg.neighbor_addr_list(j) == Radio::id(os()))
01161             {
01162                if (lt == OLSR_LOST_LINK)
01163                {
01164                   link_tuple->sym_time() = now - 1;
01165                   updated = true;
01166                }
01167                else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK)
01168                {
01169                   link_tuple->sym_time()  = now + emf_to_seconds(message.vtime());
01170                   link_tuple->time()      = link_tuple->sym_time() + OLSR_NEIGHB_HOLD_TIME;
01171                   link_tuple->lost_time() = 0.0;
01172                   updated = true;
01173                }
01174                break;
01175             }
01176          }
01177       }
01178 
01179       link_tuple->time() = MAX(link_tuple->time(), link_tuple->asym_time());
01180 
01181       if (updated)                              // whenever the link tuple is updated, the corresponding neighbor tuple also needs update
01182          updated_link_tuple(link_tuple);
01183 
01184       // Schedules link tuple deletion
01185       timer_expire_link_tuple(link_tuple);
01186 
01187    }
01188 
01189    // -----------------------------------------------------------------------
01190    // brief Updates the Neighbor Set according to the information contained in a new received HELLO message (following RFC 3626).
01191    //    basically the "nb_tuple->status" will be updated
01192 
01193    // param  msg the %OLSR message which contains the HELLO message.
01194 
01195    template<typename OsModel_P,
01196             typename RoutingTable_P,
01197             typename Clock_P,
01198             typename Radio_P,
01199             typename Debug_P>
01200    void
01201    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01202    populate_nbset(BroadcastHelloMessage& message)
01203    {
01204       OLSR_nb_tuple* nb_tuple = find_nb_tuple(message.originator_addr());
01205       if (nb_tuple != NULL)
01206          nb_tuple->willingness() = message.willingness();
01207    }
01208 
01209    // -----------------------------------------------------------------------
01210    // brief Updates the 2-hop Neighbor Set according to the information contained in a new received HELLO message (following RFC 3626).
01211 
01212    // param  msg the %OLSR message which contains the HELLO message.
01213 
01214    template<typename OsModel_P,
01215             typename RoutingTable_P,
01216             typename Clock_P,
01217             typename Radio_P,
01218             typename Debug_P>
01219    void
01220    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01221    populate_nb2hopset(BroadcastHelloMessage& message)
01222    {
01223    time_t now = Clock::time( os() );
01224 
01225    // Construct OLSR_hello from BroadcastHelloMessage& message
01226    OLSR_hello hello;
01227    hello.htime_         = message.htime();
01228    hello.willingness_      = message.willingness();
01229    hello.hello_msg_count_  = message.hello_msgs_count();
01230 
01231    for (int i = 0; i < hello.hello_msg_count_; i++ )
01232    {
01233       hello.hello_body_[i].link_code_     = message.link_code(i, nb_addrs_count_before[i]);
01234       hello.hello_body_[i].link_msg_size_    = message.link_msg_size(i, nb_addrs_count_before[i]);
01235       hello.hello_body_[i].nb_addrs_count_   = message.neighbor_addr_count(i, nb_addrs_count_before[i]);
01236       for ( int j = 1; j < message.neighbor_addr_count(i, nb_addrs_count_before[i]); j++ )
01237       {
01238          hello.hello_body_[i].nb_addrs_[j] = message.neighbor_addr_list(i, j, nb_addrs_count_before[i]);
01239       }
01240 
01241    }
01242 
01243 
01244 
01245       for (typename linkset_t::iterator it_lt = linkset().begin(); it_lt != linkset().end(); it_lt++)
01246       {
01247          OLSR_link_tuple* link_tuple = *it_lt;
01248 
01249          if (link_tuple->nb_node_addr() == message.originator_addr())
01250          {
01251             if (link_tuple->sym_time() >= now)
01252             {
01253                assert(hello.hello_msg_count_ >= 0 && hello.hello_msg_count_ <= OLSR_MAX_HELLOS);
01254                for (int i = 0; i < hello.hello_msg_count_; i++)         // hello_msg_count_ is the number of the "hello_msg" included inside each "hello"
01255                {
01256                   OLSR_hello_msg& hello_msg = hello.hello_msg(i);
01257 
01258                   int nt = hello_msg.link_code() >> 2;      // nt = node_type
01259 
01260                   assert(hello_msg.nb_addrs_count_ >= 0 && hello_msg.nb_addrs_count_ <= OLSR_MAX_ADDRS);
01261                   for (int j = 0; j < hello_msg.nb_addrs_count_; j++)   // hello_msg.count is the number of the "Neighbor_Interface_Address" inside each "hello_msg"
01262                                                 // the "Neighbor_Interface_Address" is actually the 2-hop neighbor address
01263                   {
01264                      node_id_t nb2hop_addr = hello_msg.neighbor_addr_list(j);
01265                      if (nt == OLSR_SYM_NEIGH || nt == OLSR_MPR_NEIGH)
01266                      {
01267                         // if the main address of the 2-hop neighbor address = main address of the receiving node: silently discard the 2-hop neighbor address
01268                         if (nb2hop_addr != Radio::id(os()))
01269                         {
01270                            // Otherwise, a 2-hop tuple is created
01271                            OLSR_nb2hop_tuple* nb2hop_tuple = find_nb2hop_tuple(message.originator_addr(), nb2hop_addr);
01272                            if (nb2hop_tuple == NULL)
01273                            {
01274                               nb2hop_tuple = new OLSR_nb2hop_tuple;
01275                               nb2hop_tuple->nb_node_addr() = message.originator_addr();
01276                               nb2hop_tuple->nb2hop_addr() = nb2hop_addr;
01277                               add_nb2hop_tuple(nb2hop_tuple);
01278                               nb2hop_tuple->time() = now + emf_to_seconds(message.vtime());
01279 
01280                               // Schedules nb2hop tuple deletion
01281                               timer_expire_nb2hop_tuple(nb2hop_tuple);
01282 
01283                            }
01284                            else
01285                            {
01286                               nb2hop_tuple->time() = now + emf_to_seconds(message.vtime());
01287                            }
01288 
01289                         }
01290                      }
01291                      else if (nt == OLSR_NOT_NEIGH)
01292                      {
01293                         // For each 2-hop node listed in the HELLO message with Neighbor Type equal to NOT_NEIGH all 2-hop tuples where: N_neighbor_node_addr == Originator
01294                         // Address AND N_2hop_addr  == main address of the 2-hop neighbor are deleted.
01295                         erase_nb2hop_tuples(message.originator_addr(), nb2hop_addr);
01296                      }
01297                   }
01298                }
01299             }
01300          }
01301       }
01302    }
01303 
01304    // -----------------------------------------------------------------------
01305    // brief Compute MPR set of a node following RFC 3626 hints.
01306 
01307    template<typename OsModel_P,
01308             typename RoutingTable_P,
01309             typename Clock_P,
01310             typename Radio_P,
01311             typename Debug_P>
01312    void
01313    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01314    mpr_computation()
01315    {
01316    time_t now = Clock::time( os() );
01317 
01318    clear_mprset();
01319       nbset_t N;
01320       nb2hopset_t N2;
01321 
01322       // N is the subset of neighbors of the node, which are neighbor "of the interface I"
01323       for (typename nbset_t::iterator it = nbset().begin(); it != nbset().end(); it++)
01324          if ((*it)->status() == OLSR_STATUS_SYM) // I think that we need this check
01325             N.push_back(*it);
01326 
01327       // N2 is the set of 2-hop neighbors reachable from "the interface I", excluding:
01328 
01329       // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
01330       // (ii)  the node performing the computation
01331       // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric link to this node on some interface.
01332 
01333       for (typename nb2hopset_t::iterator it = nb2hopset().begin(); it != nb2hopset().end(); it++) {
01334          OLSR_nb2hop_tuple* nb2hop_tuple = *it;
01335          bool ok = true;
01336          OLSR_nb_tuple* nb_tuple = find_sym_nb_tuple(nb2hop_tuple->nb_node_addr());
01337          if (nb_tuple == NULL)
01338             ok = false;
01339          else {
01340             nb_tuple = find_nb_tuple(nb2hop_tuple->nb_node_addr(), OLSR_WILL_NEVER);
01341             if (nb_tuple != NULL)
01342                ok = false;
01343             else {
01344                nb_tuple = find_sym_nb_tuple(nb2hop_tuple->nb2hop_addr());
01345                if (nb_tuple != NULL)
01346                   ok = false;
01347             }
01348          }
01349 
01350          if (ok)
01351             N2.push_back(nb2hop_tuple);
01352       }
01353 
01354       // 1. Start with an MPR set made of all members of N with N_willingness equal to WILL_ALWAYS
01355       for (typename nbset_t::iterator it = N.begin(); it != N.end(); it++) {
01356          OLSR_nb_tuple* nb_tuple = *it;
01357          if (nb_tuple->willingness() == OLSR_WILL_ALWAYS)
01358             insert_mpr_addr(nb_tuple->nb_node_addr());
01359       }
01360 
01361       // 2. Calculate D(y), where y is a member of N, for all nodes in N.
01362       // We will do this later.
01363 
01364       // 3. Add to the MPR set those nodes in N, which are the *only* nodes to provide reachability to a node in N2.
01365       // Remove the nodes from N2 which are now covered by a node in the MPR set.
01366       mprset_t foundset;
01367       std::set<node_id_t> deleted_addrs;
01368       for (typename nb2hopset_t::iterator it = N2.begin(); it != N2.end(); it++)
01369       {
01370          OLSR_nb2hop_tuple* nb2hop_tuple1 = *it;
01371 
01372          typename mprset_t::iterator pos = foundset.find(nb2hop_tuple1->nb2hop_addr());
01373          if (pos != foundset.end())
01374             continue;
01375 
01376          bool found = false;
01377          for (typename nbset_t::iterator it2 = N.begin();it2 != N.end();it2++) {
01378             if ((*it2)->nb_node_addr() == nb2hop_tuple1->nb_node_addr()) {
01379                found = true;
01380                break;
01381             }
01382          }
01383          if (!found)
01384             continue;
01385 
01386          found = false;
01387          for (typename nb2hopset_t::iterator it2 = it + 1; it2 != N2.end(); it2++) {
01388             OLSR_nb2hop_tuple* nb2hop_tuple2 = *it2;
01389             if (nb2hop_tuple1->nb2hop_addr() == nb2hop_tuple2->nb2hop_addr()) {
01390                foundset.insert(nb2hop_tuple1->nb2hop_addr());
01391                found = true;
01392                break;
01393             }
01394          }
01395          if (!found) {
01396             insert_mpr_addr(nb2hop_tuple1->nb_node_addr());
01397 
01398             for (typename nb2hopset_t::iterator it2 = it + 1; it2 != N2.end(); it2++) {
01399                OLSR_nb2hop_tuple* nb2hop_tuple2 = *it2;
01400                if (nb2hop_tuple1->nb_node_addr() == nb2hop_tuple2->nb_node_addr()) {
01401                   deleted_addrs.insert(nb2hop_tuple2->nb2hop_addr());
01402                   it2 = N2.erase(it2);
01403                   it2--;
01404                }
01405             }
01406             it = N2.erase(it);
01407             it--;
01408          }
01409 
01410          for (typename std::set<node_id_t>::iterator it2 = deleted_addrs.begin(); it2 != deleted_addrs.end(); it2++)
01411          {
01412             for (typename nb2hopset_t::iterator it3 = N2.begin();
01413                it3 != N2.end();
01414                it3++) {
01415                if ((*it3)->nb2hop_addr() == *it2) {
01416                   it3 = N2.erase(it3);
01417                   it3--;
01418                   // I have to reset the external iterator because it
01419                   // may have been invalidated by the latter deletion
01420                   it = N2.begin();
01421                   it--;
01422                }
01423             }
01424          }
01425          deleted_addrs.clear();
01426       }
01427 
01428       // 4. While there exist nodes in N2 which are not covered by at
01429       // least one node in the MPR set:
01430       while (N2.begin() != N2.end()) {
01431          // 4.1. For each node in N, calculate the reachability, i.e., the
01432          // number of nodes in N2 which are not yet covered by at
01433          // least one node in the MPR set, and which are reachable
01434          // through this 1-hop neighbor
01435          std::map<int, std::vector<OLSR_nb_tuple*> > reachability;
01436          std::set<int> rs;
01437          for (typename nbset_t::iterator it = N.begin(); it != N.end(); it++) {
01438             OLSR_nb_tuple* nb_tuple = *it;
01439             int r = 0;
01440             for (typename nb2hopset_t::iterator it2 = N2.begin(); it2 != N2.end(); it2++) {
01441                OLSR_nb2hop_tuple* nb2hop_tuple = *it2;
01442                if (nb_tuple->nb_node_addr() == nb2hop_tuple->nb_node_addr())
01443                   r++;
01444             }
01445             rs.insert(r);
01446             reachability[r].push_back(nb_tuple);
01447          }
01448 
01449          // 4.2. Select as a MPR the node with highest N_willingness among
01450          // the nodes in N with non-zero reachability. In case of
01451          // multiple choice select the node which provides
01452          // reachability to the maximum number of nodes in N2. In
01453          // case of multiple nodes providing the same amount of
01454          // reachability, select the node as MPR whose D(y) is
01455          // greater. Remove the nodes from N2 which are now covered
01456          // by a node in the MPR set.
01457          OLSR_nb_tuple* max = NULL;
01458          int max_r = 0;
01459          for (std::set<int>::iterator it = rs.begin(); it != rs.end(); it++) {
01460             int r = *it;
01461             if (r > 0) {
01462                for (typename std::vector<OLSR_nb_tuple*>::iterator it2 = reachability[r].begin();
01463                   it2 != reachability[r].end();
01464                   it2++) {
01465                   OLSR_nb_tuple* nb_tuple = *it2;
01466                   if (max == NULL || nb_tuple->willingness() > max->willingness()) {
01467                      max = nb_tuple;
01468                      max_r = r;
01469                   }
01470                   else if (nb_tuple->willingness() == max->willingness()) {
01471                      if (r > max_r) {
01472                         max = nb_tuple;
01473                         max_r = r;
01474                      }
01475                      else if (r == max_r) {
01476                         if (degree(nb_tuple) > degree(max)) {
01477                            max = nb_tuple;
01478                            max_r = r;
01479                         }
01480                      }
01481                   }
01482                }
01483             }
01484          }
01485          if (max != NULL) {
01486             insert_mpr_addr(max->nb_node_addr());
01487             std::set<node_id_t> nb2hop_addrs;
01488             for (typename nb2hopset_t::iterator it = N2.begin(); it != N2.end(); it++) {
01489                OLSR_nb2hop_tuple* nb2hop_tuple = *it;
01490                if (nb2hop_tuple->nb_node_addr() == max->nb_node_addr()) {
01491                   nb2hop_addrs.insert(nb2hop_tuple->nb2hop_addr());
01492                   it = N2.erase(it);
01493                   it--;
01494                }
01495             }
01496             for (typename nb2hopset_t::iterator it = N2.begin(); it != N2.end(); it++) {
01497                OLSR_nb2hop_tuple* nb2hop_tuple = *it;
01498                typename std::set<node_id_t>::iterator it2 = nb2hop_addrs.find(nb2hop_tuple->nb2hop_addr());
01499                if (it2 != nb2hop_addrs.end()) {
01500                   it = N2.erase(it);
01501                   it--;
01502                }
01503             }
01504          }
01505       }
01506    }
01507 
01508    // -----------------------------------------------------------------------
01509    template<typename OsModel_P,
01510             typename RoutingTable_P,
01511             typename Clock_P,
01512             typename Radio_P,
01513             typename Debug_P>
01514    bool
01515    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01516    find_mpr_addr(node_id_t addr)
01517    {
01518    typename mprset_t::iterator it = mprset_.find(addr);
01519       return (it != mprset_.end());
01520    }
01521    // -----------------------------------------------------------------------
01522    template<typename OsModel_P,
01523             typename RoutingTable_P,
01524             typename Clock_P,
01525             typename Radio_P,
01526             typename Debug_P>
01527    void
01528    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01529    insert_mpr_addr(node_id_t addr)
01530    {
01531       mprset_.insert(addr);
01532    }
01533    // -----------------------------------------------------------------------
01534    template<typename OsModel_P,
01535             typename RoutingTable_P,
01536             typename Clock_P,
01537             typename Radio_P,
01538             typename Debug_P>
01539    void
01540    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01541    clear_mprset()
01542    {
01543       mprset_.clear();
01544    }
01545    // -----------------------------------------------------------------------
01546 
01547 
01548    // brief Updates the MPR Selector Set according to the information contained in a new received HELLO message (following RFC 3626).
01549 
01550    // param  msg the %OLSR message which contains the HELLO message.
01551 
01552    template<typename OsModel_P,
01553             typename RoutingTable_P,
01554             typename Clock_P,
01555             typename Radio_P,
01556             typename Debug_P>
01557    void
01558    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01559    populate_mprselset(BroadcastHelloMessage& message)
01560    {
01561    time_t now        = Clock::time( os() );
01562 
01563    Debug::debug(os(), "Receive Hello message from %i with %i hello_msg, inside populate_mprselset \n", message.originator_addr(), message.hello_msgs_count() );
01564 
01565    // Construct OLSR_hello from BroadcastHelloMessage& message
01566    OLSR_hello hello;
01567    hello.htime_         = message.htime();
01568    hello.willingness_      = message.willingness();
01569    hello.hello_msg_count_  = message.hello_msgs_count();
01570 
01571    for (int i = 0; i < hello.hello_msg_count_; i++ )
01572    {
01573       hello.hello_body_[i].link_code_     = message.link_code(i, nb_addrs_count_before[i]);
01574       hello.hello_body_[i].link_msg_size_    = message.link_msg_size(i, nb_addrs_count_before[i]);
01575       hello.hello_body_[i].nb_addrs_count_   = message.neighbor_addr_count(i, nb_addrs_count_before[i]);
01576       for ( int j = 1; j < message.neighbor_addr_count(i, nb_addrs_count_before[i]); j++ )
01577       {
01578          hello.hello_body_[i].nb_addrs_[j] = message.neighbor_addr_list(i, j, nb_addrs_count_before[i]);
01579       }
01580 
01581    }
01582 
01583 
01584       assert(hello.hello_msg_count_ >= 0 && hello.hello_msg_count_ <= OLSR_MAX_HELLOS);
01585       for (int i = 0; i < hello.hello_msg_count_; i++)
01586       {
01587          OLSR_hello_msg& hello_msg = hello.hello_msg(i);
01588          int nt = hello_msg.link_code() >> 2;
01589          if (nt == OLSR_MPR_NEIGH)
01590          {
01591             assert(hello_msg.nb_addrs_count_ >= 0 && hello_msg.nb_addrs_count_ <= OLSR_MAX_ADDRS);
01592             for (int j = 0; j < hello_msg.nb_addrs_count_; j++)
01593             {
01594                if (hello_msg.neighbor_addr_list(j) == Radio::id(os()))
01595                {
01596                   // Create a new entry into the mpr selector set
01597                   OLSR_mprsel_tuple* mprsel_tuple = find_mprsel_tuple(message.originator_addr());
01598                   if (mprsel_tuple == NULL)
01599                   {
01600                      mprsel_tuple = new OLSR_mprsel_tuple;
01601                      mprsel_tuple->node_addr() = message.originator_addr();
01602                      mprsel_tuple->time() = now + emf_to_seconds(message.vtime());
01603                      add_mprsel_tuple(mprsel_tuple);
01604 
01605                      // Schedules mpr selector tuple deletion
01606                      timer_expire_mprsel_tuple(mprsel_tuple);
01607 
01608                   }
01609                   else
01610                      mprsel_tuple->time() = now + emf_to_seconds(message.vtime());
01611                }
01612             }
01613          }
01614       }
01615    }
01616 
01617    // -----------------------------------------------------------------------
01618 
01619    // brief OLSR's default forwarding algorithm.
01620 
01621    //param msg          the OLSR message which must be forwarded.
01622    //param dup_tuple    NULL if the message has never been considered for forwarding, or a duplicate tuple in other case.
01623 
01624    template<typename OsModel_P,
01625             typename RoutingTable_P,
01626             typename Clock_P,
01627             typename Radio_P,
01628             typename Debug_P>
01629    void
01630    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01631    forward_hello(node_id_t from, BroadcastHelloMessage& message, OLSR_dup_tuple* dup_tuple)
01632    {
01633    time_t now = Clock::time( os() );
01634 
01635       OLSR_link_tuple* link_tuple = find_sym_link_tuple(from, now);     // If the sender address is not in the symmetric 1-hop neighborhood the message must not be forwarded
01636       if (link_tuple == NULL)
01637          return;
01638 
01639       if (dup_tuple != NULL && dup_tuple->retransmitted())              // If the message has already been considered for forwarding, it must not be retransmitted again
01640       {
01641 #ifdef DEBUG_OLSRROUTING
01642          Debug::debug(os(), "%f: Node %d does not forward a message received from %d because it is duplicated\n", Clock::time( os() ), Radio::id( os() ), dup_tuple->addr() );
01643 #endif
01644 
01645          return;
01646       }
01647 
01648       bool retransmitted = false;                                 // If sender_address is an address of a MPR selector of this node and ttl > 1, the message must be retransmitted
01649       if (message.ttl() > 1)
01650       {
01651          OLSR_mprsel_tuple* mprsel_tuple = find_mprsel_tuple(from);
01652          if (mprsel_tuple != NULL)                             // the sender address is an address of a MPR selector of this local node
01653          {
01654             message.set_ttl( message.ttl() - 1 );
01655             message.set_hop_count( message.hop_count() + 1 );
01656 
01657             Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), delay_, this, 0 ); // introduce a random delay before retransmit the message
01658             Radio::send( os(), Radio::BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*)&message);
01659             retransmitted = true;
01660          }
01661       }
01662 
01663       if (dup_tuple != NULL)                                   // Update duplicate tuple
01664       {
01665          dup_tuple->time()    = now + OLSR_DUP_HOLD_TIME;
01666          dup_tuple->retransmitted() = retransmitted;
01667       }
01668       else                                                  // or create a new one
01669       {
01670          OLSR_dup_tuple* new_dup    = new OLSR_dup_tuple;
01671          new_dup->addr()            = message.originator_addr();
01672          new_dup->seq_num()         = message.msg_seq_num();
01673          new_dup->time()            = now + OLSR_DUP_HOLD_TIME;
01674          new_dup->retransmitted()   = retransmitted;
01675          add_dup_tuple(new_dup);
01676 
01677          // Schedules dup tuple deletion
01678          timer_expire_dup_tuple(new_dup);
01679       }
01680    }
01681    // -----------------------------------------------------------------------
01682 
01683    // brief OLSR's default forwarding algorithm.
01684 
01685    //param msg          the OLSR message which must be forwarded.
01686    //param dup_tuple    NULL if the message has never been considered for forwarding, or a duplicate tuple in other case.
01687 
01688    template<typename OsModel_P,
01689             typename RoutingTable_P,
01690             typename Clock_P,
01691             typename Radio_P,
01692             typename Debug_P>
01693    void
01694    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01695    forward_tc(node_id_t from, BroadcastTcMessage& message, OLSR_dup_tuple* dup_tuple)
01696    {
01697    time_t now = Clock::time( os() );
01698 
01699       OLSR_link_tuple* link_tuple = find_sym_link_tuple(from, now);     // If the sender address is not in the symmetric 1-hop neighborhood the message must not be forwarded
01700       if (link_tuple == NULL)
01701          return;
01702 
01703       if (dup_tuple != NULL && dup_tuple->retransmitted())              // If the message has already been considered for forwarding, it must not be retransmitted again
01704       {
01705 #ifdef DEBUG_OLSRROUTING
01706          Debug::debug(os(), "%f: Node %d does not forward a message received from %d because it is duplicated\n", Clock::time( os() ), Radio::id( os() ), dup_tuple->addr() );
01707 #endif
01708 
01709          return;
01710       }
01711 
01712       bool retransmitted = false;                                 // If sender_address is an address of a MPR selector of this node and ttl > 1, the message must be retransmitted
01713       if (message.ttl() > 1)
01714       {
01715          OLSR_mprsel_tuple* mprsel_tuple = find_mprsel_tuple(from);
01716          if (mprsel_tuple != NULL)                             // the sender address is an address of a MPR selector of this local node
01717          {
01718             message.set_ttl( message.ttl() - 1 );
01719             message.set_hop_count( message.hop_count() + 1 );
01720 
01721             Timer::template set_timer<self_type, &self_type::timer_elapsed>( os(), delay_, this, 0 ); // introduce a random delay before retransmit the message
01722             Radio::send( os(), Radio::BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*)&message);
01723             retransmitted = true;
01724          }
01725       }
01726 
01727       if (dup_tuple != NULL)                                   // Update duplicate tuple
01728       {
01729          dup_tuple->time()    = now + OLSR_DUP_HOLD_TIME;
01730          dup_tuple->retransmitted() = retransmitted;
01731       }
01732       else                                                  // or create a new one
01733       {
01734          OLSR_dup_tuple* new_dup    = new OLSR_dup_tuple;
01735          new_dup->addr()            = message.originator_addr();
01736          new_dup->seq_num()         = message.msg_seq_num();
01737          new_dup->time()            = now + OLSR_DUP_HOLD_TIME;
01738          new_dup->retransmitted()   = retransmitted;
01739          add_dup_tuple(new_dup);
01740 
01741          // Schedules dup tuple deletion
01742          timer_expire_dup_tuple(new_dup);
01743       }
01744    }
01745 
01746    // -----------------------------------------------------------------------
01747    // brief Processes a TC message following RFC 3626 specification, The Topology Set is updated (if needed) with the information of the received TC message.
01748 
01749    // param msg   the OLSR message which contains the TC message.
01750    // param sender   the address of the node where the message was sent from.
01751 
01752    template<typename OsModel_P,
01753              typename RoutingTable_P,
01754              typename Clock_P,
01755              typename Radio_P,
01756              typename Debug_P>
01757     void
01758     OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01759     process_tc(BroadcastTcMessage& message, node_id_t sender)
01760     {
01761    Debug::debug(os(), "%i received TC from %i of size %i  \n", Radio::id(os()), message.originator_addr(), message.msg_size() );
01762    //Debug::debug(os(), "%i received TC from %i \n", Radio::id(os()), message.originator_addr());
01763 
01764     time_t now = Clock::time( os() );
01765 
01766    // Construct OLSR_tc from BroadcastTcMessage& message
01767    OLSR_tc tc;
01768    tc.ansn_                = message.ansn();
01769    tc.adv_nb_addrs_count_     = message.adv_neighbor_addr_list_size();
01770    for ( int i = 1; i < message.adv_neighbor_addr_list_size(); i++ )
01771    {
01772       tc.adv_nb_addrs_[i] = message.adv_neighbor_addr_list(i);
01773    }
01774 
01775 
01776       // 1. If the sender of this message is not in the symmetric 1-hop neighborhood of this node, the message MUST be discarded.
01777       OLSR_link_tuple* link_tuple = find_sym_link_tuple(sender, now);
01778       if (link_tuple == NULL)
01779          return;
01780 
01781       // 2. If there exist some tuple in the topology set where:
01782       //      T_last_addr == originator address AND T_seq > ANSN, then further processing of this TC message MUST NOT be performed.
01783       OLSR_topology_tuple* topology_tuple = find_newer_topology_tuple(message.originator_addr(), tc.ansn());
01784       if (topology_tuple != NULL)
01785          return;
01786 
01787       // 3. All tuples in the topology set where:
01788       //   T_last_addr == originator address AND T_seq < ANSN, MUST be removed from the topology set.
01789       erase_older_topology_tuples(message.originator_addr(), tc.ansn());
01790 
01791       // 4. For each of the advertised neighbor main address received in the TC message:
01792       for (int i = 0; i < tc.adv_nb_addrs_count_; i++)
01793       {
01794          assert(i >= 0 && i < OLSR_MAX_ADDRS);
01795          node_id_t addr = tc.adv_neighbor_addr_list(i);
01796 
01797          // 4.1. If there exist some tuple in the topology set where:
01798          //    T_dest_addr == advertised neighbor main address, AND T_last_addr == originator address,
01799          //  then the holding time of that tuple MUST be set to:  T_time = current time + validity time.
01800 
01801          OLSR_topology_tuple* topology_tuple = find_topology_tuple(addr, message.originator_addr());
01802          if (topology_tuple != NULL)
01803             topology_tuple->time() = now + emf_to_seconds(message.vtime());
01804 
01805          // 4.2. Otherwise, a new tuple MUST be recorded in the topology set where:
01806          //    T_dest_addr = advertised neighbor main address,
01807          //    T_last_addr = originator address,
01808          //    T_seq       = ANSN,
01809          //    T_time      = current time + validity time.
01810          else
01811          {
01812             OLSR_topology_tuple* topology_tuple = new OLSR_topology_tuple;
01813             topology_tuple->dest_addr()   = addr;
01814             topology_tuple->last_addr()   = message.originator_addr();
01815             topology_tuple->seq()      = tc.ansn();
01816             topology_tuple->time()     = now + emf_to_seconds(message.vtime());
01817             add_topology_tuple(topology_tuple);
01818 
01819             // Schedules topology tuple deletion
01820             timer_expire_topology_tuple(topology_tuple);
01821          }
01822       }
01823    }
01824 
01825    // -----------------------------------------------------------------------
01826    // param msg   the OLSR message which contains the TC message.
01827    // param sender   the address of the node where the message was sent from.
01828 
01829    template<typename OsModel_P,
01830             typename RoutingTable_P,
01831             typename Clock_P,
01832             typename Radio_P,
01833             typename Debug_P>
01834     void
01835     OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01836     process_data(RoutingMessage& msg, node_id_t sender)
01837     {
01838        Debug::debug(os(), "%i received DATA from %i \n", Radio::id(os()), msg.source());
01839 
01840        if (msg.destination() == Radio::id(os()))                                                // Got the destination
01841       {
01842            Debug::debug(os(), "%i got his DATA from %i \n", Radio::id(os()), msg.source());
01843       }
01844        else if (route_exists(msg.destination()))                                                // Check any route to destination in the local routing table
01845       {
01846            Debug::debug(os(), "%i forwards DATA for %i. next hop [%i] %i hops away \n",
01847                         Radio::id(os()), msg.destination(), routing_table_[msg.destination()].next_addr, routing_table_[msg.destination()].hops);
01848 
01849            Radio::send(os(), routing_table_[msg.destination()].next_addr, msg.buffer_size(), (uint8_t*) & msg);   //Forward message to next hop in the routing table entry
01850            //routing_table_[msg.destination()].lifetime = ROUTE_TIMEOUT;
01851       }
01852        else
01853         {
01854            Debug::debug(os(), "%i ERROR: no route for \n", Radio::id(os()), msg.destination());
01855 
01856         }
01857     }
01858 
01859    // -----------------------------------------------------------------------
01860    // brief Creates the routing table of the node following RFC 3626 hints.
01861 
01862    // The routing table is updated in case of:
01863    // -- neighbor appearance or loss
01864    // -- 2-hop tuple is created or removed
01865    // -- topology tuple is created or removed
01866    // -- multiple interface association information changes
01867 
01868    template<typename OsModel_P,
01869             typename RoutingTable_P,
01870             typename Clock_P,
01871             typename Radio_P,
01872             typename Debug_P>
01873     void
01874     OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01875     routing_table_computation()
01876     {
01877        routing_table_.clear();                                             // 1. All the entries from the routing table are removed.
01878 
01879        for (typename nbset_t::iterator it = nbset().begin(); it != nbset().end(); it++)   // 2. New routing entries are added starting with the symmetric neighbors (h=1) as the destination nodes.
01880        {
01881           OLSR_nb_tuple* nb_tuple = *it;
01882 
01883           if (nb_tuple->status() == OLSR_STATUS_SYM)
01884           {
01885              bool nb_node_addr = false;
01886              OLSR_link_tuple* lt = NULL;
01887 
01888              for (typename linkset_t::iterator it2 = linkset().begin(); it2 != linkset().end(); it2++)
01889              {
01890                 OLSR_link_tuple* link_tuple = *it2;
01891                 if (link_tuple->nb_node_addr() == nb_tuple->nb_node_addr() && link_tuple->time() >= Clock::time( os() ))
01892                 {
01893                    lt = link_tuple;
01894 
01895 #ifdef DEBUG_OLSRROUTING
01896                    Debug::debug( os(), "OlsrRouting: Add %i because not known\n", link_tuple->nb_node_addr() );
01897 #endif
01898                    routing_table_[link_tuple->nb_node_addr()] = RoutingTableEntry(link_tuple->nb_node_addr(), link_tuple->nb_node_addr(), 1); //insert
01899 
01900                    if (link_tuple->nb_node_addr() == nb_tuple->nb_node_addr())
01901                       nb_node_addr = true;
01902                 }
01903              }
01904 
01905              if (!nb_node_addr && lt != NULL)
01906              {
01907 #ifdef DEBUG_OLSRROUTING
01908              Debug::debug( os(), "OlsrRouting: Add %i because not known\n", nb_tuple->nb_node_addr() );
01909 #endif
01910              routing_table_[nb_tuple->nb_node_addr()] = RoutingTableEntry(nb_tuple->nb_node_addr(), lt->nb_node_addr(), 1);  //insert
01911              }
01912           }
01913        }
01914 
01915       // N2 is the set of 2-hop neighbors reachable from this node, excluding:
01916 
01917       // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
01918       // (ii)  the node performing the computation
01919       // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric link to this node on some interface.
01920        for (typename nb2hopset_t::iterator it = nb2hopset().begin(); it != nb2hopset().end(); it++)
01921        {
01922           OLSR_nb2hop_tuple* nb2hop_tuple = *it;
01923           bool ok = true;
01924           OLSR_nb_tuple* nb_tuple = find_sym_nb_tuple(nb2hop_tuple->nb_node_addr());
01925           if (nb_tuple == NULL)
01926              ok = false;
01927           else
01928           {
01929              nb_tuple = find_nb_tuple(nb2hop_tuple->nb_node_addr(), OLSR_WILL_NEVER);
01930              if (nb_tuple != NULL)
01931                 ok = false;
01932              else
01933              {
01934                 nb_tuple = find_sym_nb_tuple(nb2hop_tuple->nb2hop_addr());
01935                 if (nb_tuple != NULL)
01936                    ok = false;
01937              }
01938           }
01939 
01940          // Successfully find an entry in Nb_Tuple with willingness != NEVER
01941          // 3. For each node in N2 create a new entry in the routing table
01942           if (ok) {
01943              RoutingTableIterator it = routing_table_.find(nb2hop_tuple->nb_node_addr());
01944              assert(it != NULL);
01945 
01946 #ifdef DEBUG_OLSRROUTING
01947              Debug::debug( os(), "OlsrRouting: Add %i because not known\n", nb2hop_tuple->nb2hop_addr() );
01948 #endif
01949              routing_table_[nb2hop_tuple->nb2hop_addr()] = RoutingTableEntry(nb2hop_tuple->nb2hop_addr(), it->second.next_addr, 2);  //insert
01950           }
01951        }
01952 
01953        for (uint32_t h = 2; ; h++)
01954        {
01955           bool added = false;
01956 
01957          // 4.1. For each topology entry in the topology table, if its T_dest_addr does not correspond to R_dest_addr of any
01958          // route entry in the routing table AND its T_last_addr corresponds to R_dest_addr of a route entry whose R_dist
01959          // is equal to h, then a new route entry MUST be recorded in the routing table (if it does not already exist)
01960           for (typename topologyset_t::iterator it = topologyset().begin(); it != topologyset().end(); it++)
01961           {
01962             OLSR_topology_tuple* topology_tuple = *it;
01963             RoutingTableIterator it1 = routing_table_.find(topology_tuple->dest_addr());
01964             RoutingTableIterator it2 = routing_table_.find(topology_tuple->last_addr());
01965              if (it1 == routing_table_.end() && it2 != routing_table_.end() && it2->second.dest_addr == h)
01966              {
01967 #ifdef DEBUG_OLSRROUTING
01968              Debug::debug( os(), "OlsrRouting: Add %i because not known\n", topology_tuple->dest_addr() );
01969 #endif
01970              routing_table_[topology_tuple->dest_addr()] = RoutingTableEntry(topology_tuple->dest_addr(), it2->second.next_addr, h+1);  //insert
01971 
01972                 added = true;
01973              }
01974           }
01975 
01976           if (!added)
01977              break;
01978        }
01979    }
01980 
01981    // -----------------------------------------------------------------------
01982 
01983    template<typename OsModel_P,
01984             typename RoutingTable_P,
01985             typename Clock_P,
01986             typename Radio_P,
01987             typename Debug_P>
01988    void
01989    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
01990    add_dup_tuple(OLSR_dup_tuple* tuple)
01991    {
01992       insert_dup_tuple(tuple);
01993    }
01994    // -----------------------------------------------------------------------
01995    template<typename OsModel_P,
01996             typename RoutingTable_P,
01997             typename Clock_P,
01998             typename Radio_P,
01999             typename Debug_P>
02000    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_dup_tuple*
02001    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02002    find_dup_tuple(node_id_t addr, uint16_t seq_num)
02003    {
02004       for (typename dupset_t::iterator it = dupset_.begin(); it != dupset_.end(); it++)
02005       {
02006          OLSR_dup_tuple* tuple = *it;
02007          if (tuple->addr() == addr && tuple->seq_num() == seq_num)
02008             return tuple;
02009       }
02010 
02011       return NULL;
02012    }
02013 
02014    // -----------------------------------------------------------------------
02015    template<typename OsModel_P,
02016             typename RoutingTable_P,
02017             typename Clock_P,
02018             typename Radio_P,
02019             typename Debug_P>
02020    void
02021    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02022    rm_dup_tuple(OLSR_dup_tuple* tuple)
02023    {
02024       erase_dup_tuple(tuple);
02025    }
02026    // -----------------------------------------------------------------------
02027 
02028    template<typename OsModel_P,
02029             typename RoutingTable_P,
02030             typename Clock_P,
02031             typename Radio_P,
02032             typename Debug_P>
02033    void
02034    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02035    erase_dup_tuple(OLSR_dup_tuple* tuple)
02036    {
02037       for (typename dupset_t::iterator it = dupset_.begin(); it != dupset_.end(); it++)
02038       {
02039          if (*it == tuple)
02040          {
02041             dupset_.erase(it);
02042             break;
02043          }
02044       }
02045    }
02046 
02047    // -----------------------------------------------------------------------
02048 
02049    template<typename OsModel_P,
02050             typename RoutingTable_P,
02051             typename Clock_P,
02052             typename Radio_P,
02053             typename Debug_P>
02054    void
02055    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02056    insert_dup_tuple(OLSR_dup_tuple* tuple)
02057    {
02058       dupset_.push_back(tuple);
02059    }
02060 
02061    // -----------------------------------------------------------------------
02062    // brief Adds a link tuple to the Link Set (and an associated neighbor tuple to the Neighbor Set).
02063    // param tuple the link tuple to be added.
02064    // param willingness willingness of the node which is going to be inserted in the Neighbor Set.
02065 
02066    template<typename OsModel_P,
02067             typename RoutingTable_P,
02068             typename Clock_P,
02069             typename Radio_P,
02070             typename Debug_P>
02071    void
02072    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02073    add_link_tuple(OLSR_link_tuple* tuple, uint8_t  willingness)
02074    {
02075    time_t now = Clock::time( os() );
02076 
02077 #ifdef DEBUG_OLSRROUTING
02078    Debug::debug(os(), "%f: Node %d adds link tuple: nb_addr = %d\n", now, Radio::id(os()), tuple->nb_node_addr());
02079 #endif
02080 
02081       insert_link_tuple(tuple);
02082       // Creates associated neighbor tuple
02083       OLSR_nb_tuple* nb_tuple    = new OLSR_nb_tuple;
02084       nb_tuple->nb_node_addr()   = tuple->nb_node_addr();
02085       nb_tuple->willingness()    = willingness;
02086       if (tuple->sym_time() >= now)
02087          nb_tuple->status() = OLSR_STATUS_SYM;
02088       else
02089          nb_tuple->status() = OLSR_STATUS_NOT_SYM;
02090       add_nb_tuple(nb_tuple);
02091    }
02092    // -----------------------------------------------------------------------
02093    // brief Removes a link tuple from the Link Set.
02094    // param tuple the link tuple to be removed.
02095 
02096    template<typename OsModel_P,
02097             typename RoutingTable_P,
02098             typename Clock_P,
02099             typename Radio_P,
02100             typename Debug_P>
02101    void
02102    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02103    rm_link_tuple(OLSR_link_tuple* tuple)
02104    {
02105       node_id_t nb_addr = tuple->nb_node_addr();
02106     time_t now = Clock::time( os() );
02107 
02108 #ifdef DEBUG_OLSRROUTING
02109     Debug::debug(os(), "%f: Node %d removes neighbor tuple: nb_addr = %d\n", now, Radio::id(os()), nb_addr);
02110 #endif
02111 
02112       erase_link_tuple(tuple);
02113 
02114       OLSR_nb_tuple* nb_tuple = find_nb_tuple(nb_addr);
02115       erase_nb_tuple(nb_tuple);
02116       delete nb_tuple;
02117    }
02118    // -----------------------------------------------------------------------
02119    // brief This function is invoked when a link tuple is updated. Its aim is to also update the corresponding neighbor tuple if it is needed.
02120    // param tuple the link tuple which has been updated.
02121 
02122    template<typename OsModel_P,
02123             typename RoutingTable_P,
02124             typename Clock_P,
02125             typename Radio_P,
02126             typename Debug_P>
02127    void
02128    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02129    updated_link_tuple(OLSR_link_tuple* tuple)
02130    {
02131    time_t now = Clock::time( os() );
02132 
02133       // Each time a link tuple changes, the associated neighbor tuple must be recomputed, basically the "nb_tuple->status" should be updated
02134       OLSR_nb_tuple* nb_tuple = find_nb_tuple(tuple->nb_node_addr());
02135       if (nb_tuple != NULL) {
02136          if (tuple->lost_time() >= now)
02137             nb_tuple->status() = OLSR_STATUS_NOT_SYM;
02138          else if (tuple->sym_time() >= now)
02139             nb_tuple->status() = OLSR_STATUS_SYM;
02140          else
02141             nb_tuple->status() = OLSR_STATUS_NOT_SYM;
02142       }
02143 
02144 #ifdef DEBUG_OLSRROUTING
02145       Debug::debug(os(), "%f: Node %d has updated link tuple: nb_addr = %d status = %s\n", now, Radio::id(os()), tuple->nb_node_addr(),
02146          ((nb_tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
02147 #endif
02148    }
02149    // -----------------------------------------------------------------------
02150 
02151    template<typename OsModel_P,
02152             typename RoutingTable_P,
02153             typename Clock_P,
02154             typename Radio_P,
02155             typename Debug_P>
02156    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_link_tuple *
02157    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02158    find_link_tuple(node_id_t node_addr)
02159    {
02160       for (typename linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++)
02161       {
02162          OLSR_link_tuple* tuple = *it;
02163          if (tuple->nb_node_addr() == node_addr)
02164          {
02165 #ifdef DEBUG_OLSRROUTING
02166             Debug::debug(os(), "Find existing tuple!!!\n");
02167 #endif
02168             return tuple;
02169          }
02170          else
02171          {
02172 #ifdef DEBUG_OLSRROUTING
02173             Debug::debug(os(), "NO existing tuple!!!\n");
02174 #endif
02175             return NULL;
02176          }
02177       }
02178    }
02179 
02180    // -----------------------------------------------------------------------
02181 
02182    template<typename OsModel_P,
02183             typename RoutingTable_P,
02184             typename Clock_P,
02185             typename Radio_P,
02186             typename Debug_P>
02187    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_link_tuple *
02188    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02189    find_sym_link_tuple(node_id_t node_addr, double now)
02190    {
02191 
02192       for (typename linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++)
02193       {
02194          OLSR_link_tuple* tuple = *it;
02195          if (tuple->nb_node_addr() == node_addr)
02196          {
02197             if (tuple->sym_time() > now)
02198                return tuple;
02199             else
02200                break;
02201          }
02202       }
02203       return NULL;
02204    }
02205 
02206    // -----------------------------------------------------------------------
02207 
02208    template<typename OsModel_P,
02209             typename RoutingTable_P,
02210             typename Clock_P,
02211             typename Radio_P,
02212             typename Debug_P>
02213    void
02214    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02215    erase_link_tuple(OLSR_link_tuple* tuple)
02216    {
02217       for (typename linkset_t::iterator it = linkset_.begin(); it != linkset_.end(); it++)
02218       {
02219          if (*it == tuple)
02220          {
02221             linkset_.erase(it);
02222             break;
02223          }
02224       }
02225    }
02226 
02227    // -----------------------------------------------------------------------
02228 
02229    template<typename OsModel_P,
02230             typename RoutingTable_P,
02231             typename Clock_P,
02232             typename Radio_P,
02233             typename Debug_P>
02234    void
02235    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02236    insert_link_tuple(OLSR_link_tuple* tuple)
02237    {
02238       linkset_.push_back(tuple);
02239    }
02240    // -----------------------------------------------------------------------
02241 
02242 
02243    // brief Adds a neighbor tuple to the Neighbor Set.
02244    // param tuple the neighbor tuple to be added.
02245 
02246    template<typename OsModel_P,
02247             typename RoutingTable_P,
02248             typename Clock_P,
02249             typename Radio_P,
02250             typename Debug_P>
02251    void
02252    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02253    add_nb_tuple(OLSR_nb_tuple* tuple)
02254    {
02255 #ifdef DEBUG_OLSRROUTING
02256       Debug::debug(os(), "%f: Node %d adds neighbor tuple: nb_addr = %d status = %s\n", Clock::time( os() ), Radio::id(os()), tuple->nb_node_addr(),
02257          ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
02258 #endif
02259 
02260       insert_nb_tuple(tuple);
02261    }
02262    // -----------------------------------------------------------------------
02263    // brief Removes a neighbor tuple from the Neighbor Set.
02264    // param tuple the neighbor tuple to be removed.
02265 
02266    template<typename OsModel_P,
02267             typename RoutingTable_P,
02268             typename Clock_P,
02269             typename Radio_P,
02270             typename Debug_P>
02271    void
02272    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02273    rm_nb_tuple(OLSR_nb_tuple* tuple)
02274    {
02275 #ifdef DEBUG_OLSRROUTING
02276       Debug::debug( "%f: Node %d removes neighbor tuple: nb_addr = %d status = %s\n", Clock::time( os() ),
02277                                                           Radio::id(os()),
02278                                                           tuple->nb_node_addr(),
02279                                                           ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym")  );
02280 #endif
02281 
02282       erase_nb_tuple(tuple);
02283    }
02284    // -----------------------------------------------------------------------
02285    template<typename OsModel_P,
02286             typename RoutingTable_P,
02287             typename Clock_P,
02288             typename Radio_P,
02289             typename Debug_P>
02290    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_nb_tuple *
02291    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02292    find_nb_tuple(node_id_t node_addr)                 // find a neighbor with NO SPECIFIC requirement
02293    {
02294       for (typename nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++)
02295    {
02296       OLSR_nb_tuple* tuple = *it;
02297       if (tuple->nb_node_addr() == node_addr)
02298          return tuple;
02299    }
02300       return NULL;
02301    }
02302 
02303    // -----------------------------------------------------------------------
02304    template<typename OsModel_P,
02305             typename RoutingTable_P,
02306             typename Clock_P,
02307             typename Radio_P,
02308             typename Debug_P>
02309    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_nb_tuple*
02310    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02311    find_nb_tuple(node_id_t node_addr, uint8_t willingness) // find a neighbor with certain WILLNESS requirement
02312    {
02313       for (typename nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++)
02314       {
02315          OLSR_nb_tuple* tuple = *it;
02316          if (tuple->nb_node_addr() == node_addr && tuple->willingness() == willingness)
02317             return tuple;
02318       }
02319       return NULL;
02320    }
02321 
02322    // -----------------------------------------------------------------------
02323    template<typename OsModel_P,
02324             typename RoutingTable_P,
02325             typename Clock_P,
02326             typename Radio_P,
02327             typename Debug_P>
02328    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_nb_tuple*
02329    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02330    find_sym_nb_tuple(node_id_t node_addr)                // find a neighbor with certain SYMMETRIC requirement
02331    {
02332       for (typename nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++)
02333       {
02334          OLSR_nb_tuple* tuple = *it;
02335          if (tuple->nb_node_addr() == node_addr && tuple->status() == OLSR_STATUS_SYM)
02336             return tuple;
02337       }
02338       return NULL;
02339    }
02340 
02341    // -----------------------------------------------------------------------
02342    template<typename OsModel_P,
02343             typename RoutingTable_P,
02344             typename Clock_P,
02345             typename Radio_P,
02346             typename Debug_P>
02347    void
02348    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02349    erase_nb_tuple(OLSR_nb_tuple* tuple)
02350    {
02351       for (typename nbset_t::iterator it = nbset_.begin(); it != nbset_.end(); it++)
02352       {
02353          if (*it == tuple) {
02354             nbset_.erase(it);
02355             break;
02356          }
02357       }
02358    }
02359 
02360    // -----------------------------------------------------------------------
02361    template<typename OsModel_P,
02362             typename RoutingTable_P,
02363             typename Clock_P,
02364             typename Radio_P,
02365             typename Debug_P>
02366    void
02367    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02368    insert_nb_tuple(OLSR_nb_tuple* tuple)
02369    {
02370       nbset_.push_back(tuple);
02371    }
02372 
02373    // -----------------------------------------------------------------------
02374 
02375    // brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
02376    // param tuple the 2-hop neighbor tuple to be added.
02377 
02378    template<typename OsModel_P,
02379             typename RoutingTable_P,
02380             typename Clock_P,
02381             typename Radio_P,
02382             typename Debug_P>
02383    void
02384    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02385    add_nb2hop_tuple(OLSR_nb2hop_tuple* tuple)
02386    {
02387 #ifdef DEBUG_OLSRROUTING
02388       Debug::debug(os(), "%f: Node %d adds 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n", Clock::time( os() ), Radio::id(os()),
02389       tuple->nb_node_addr(), tuple->nb2hop_addr());
02390 #endif
02391 
02392       insert_nb2hop_tuple(tuple);
02393    }
02394    // -----------------------------------------------------------------------
02395    // brief Removes a 2-hop neighbor tuple from the 2-hop Neighbor Set.
02396    // param tuple the 2-hop neighbor tuple to be removed.
02397 
02398    template<typename OsModel_P,
02399             typename RoutingTable_P,
02400             typename Clock_P,
02401             typename Radio_P,
02402             typename Debug_P>
02403    void
02404    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02405    rm_nb2hop_tuple(OLSR_nb2hop_tuple* tuple) {
02406 #ifdef DEBUG_OLSRROUTING
02407       Debug::debug(os(), "%f: Node %d removes 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n", Clock::time( os() ), Radio::id(os()),
02408          tuple->nb_node_addr(), tuple->nb2hop_addr());
02409 #endif
02410 
02411       erase_nb2hop_tuple(tuple);
02412    }
02413    // -----------------------------------------------------------------------
02414 
02415    template<typename OsModel_P,
02416             typename RoutingTable_P,
02417             typename Clock_P,
02418             typename Radio_P,
02419             typename Debug_P>
02420    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_nb2hop_tuple *
02421    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02422    find_nb2hop_tuple(node_id_t nb_node_addr, node_id_t nb2hop_addr)
02423    {
02424       for (typename nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++)
02425       {
02426          OLSR_nb2hop_tuple* tuple = *it;
02427          if (tuple->nb_node_addr() == nb_node_addr && tuple->nb2hop_addr() == nb2hop_addr)
02428             return tuple;
02429       }
02430       return NULL;
02431    }
02432 
02433    // -----------------------------------------------------------------------
02434 
02435    template<typename OsModel_P,
02436             typename RoutingTable_P,
02437             typename Clock_P,
02438             typename Radio_P,
02439             typename Debug_P>
02440    void
02441    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02442    erase_nb2hop_tuple(OLSR_nb2hop_tuple* tuple)
02443    {
02444       for (typename nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++)
02445       {
02446          if (*it == tuple)
02447          {
02448             nb2hopset_.erase(it);
02449             break;
02450          }
02451       }
02452    }
02453    // -----------------------------------------------------------------------
02454 
02455    template<typename OsModel_P,
02456             typename RoutingTable_P,
02457             typename Clock_P,
02458             typename Radio_P,
02459             typename Debug_P>
02460    void
02461    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02462    erase_nb2hop_tuples(node_id_t nb_node_addr)
02463    {
02464    for (typename nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++)
02465       {
02466          OLSR_nb2hop_tuple* tuple = *it;
02467          if (tuple->nb_node_addr() == nb_node_addr)
02468          {
02469             it = nb2hopset_.erase(it);
02470             it--;
02471          }
02472       }
02473    }
02474    // -----------------------------------------------------------------------
02475 
02476    template<typename OsModel_P,
02477             typename RoutingTable_P,
02478             typename Clock_P,
02479             typename Radio_P,
02480             typename Debug_P>
02481    void
02482    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02483    erase_nb2hop_tuples(node_id_t nb_node_addr, node_id_t nb2hop_addr)
02484    {
02485       for (typename nb2hopset_t::iterator it = nb2hopset_.begin(); it != nb2hopset_.end(); it++)
02486       {
02487          OLSR_nb2hop_tuple* tuple = *it;
02488          if (tuple->nb_node_addr() == nb_node_addr && tuple->nb2hop_addr() == nb2hop_addr)
02489          {
02490             it = nb2hopset_.erase(it);
02491             it--;
02492          }
02493       }
02494    }
02495    // -----------------------------------------------------------------------
02496 
02497    template<typename OsModel_P,
02498             typename RoutingTable_P,
02499             typename Clock_P,
02500             typename Radio_P,
02501             typename Debug_P>
02502    void
02503    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02504    insert_nb2hop_tuple(OLSR_nb2hop_tuple* tuple)
02505    {
02506       nb2hopset_.push_back(tuple);
02507    }
02508 
02509    // -----------------------------------------------------------------------
02510    // brief Adds an MPR selector tuple to the MPR Selector Set, Advertised Neighbor Sequence Number (ANSN) is also updated.
02511    // param tuple the MPR selector tuple to be added.
02512 
02513    template<typename OsModel_P,
02514             typename RoutingTable_P,
02515             typename Clock_P,
02516             typename Radio_P,
02517             typename Debug_P>
02518    void
02519    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02520    add_mprsel_tuple(OLSR_mprsel_tuple* tuple) {
02521 #ifdef DEBUG_OLSRROUTING
02522       Debug::debug(os(), "%f: Node %d adds MPR selector tuple: nb_addr = %d\n", Clock::time( os() ), Radio::id(os()), tuple->node_addr() );
02523 #endif
02524 
02525       insert_mprsel_tuple(tuple);
02526       ansn_ = (ansn_ + 1)%(OLSR_MAX_SEQ_NUM + 1);
02527    }
02528    // -----------------------------------------------------------------------
02529    // brief Removes an MPR selector tuple from the MPR Selector Set, Advertised Neighbor Sequence Number (ANSN) is also updated.
02530    // param tuple the MPR selector tuple to be removed.
02531 
02532    template<typename OsModel_P,
02533             typename RoutingTable_P,
02534             typename Clock_P,
02535             typename Radio_P,
02536             typename Debug_P>
02537    void
02538    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02539    rm_mprsel_tuple(OLSR_mprsel_tuple* tuple) {
02540 #ifdef DEBUG_OLSRROUTING
02541       Debug::debug(os(), "%f: Node %d removes MPR selector tuple: nb_addr = %d\n", Clock::time( os() ), Radio::id(os()), tuple->node_addr() );
02542 #endif
02543 
02544       erase_mprsel_tuple(tuple);
02545       ansn_ = (ansn_ + 1)%(OLSR_MAX_SEQ_NUM + 1);
02546    }
02547    // -----------------------------------------------------------------------
02548 
02549    template<typename OsModel_P,
02550             typename RoutingTable_P,
02551             typename Clock_P,
02552             typename Radio_P,
02553             typename Debug_P>
02554    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_mprsel_tuple *
02555    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02556    find_mprsel_tuple(node_id_t node_addr) {
02557       for (typename mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++)
02558       {
02559          OLSR_mprsel_tuple* tuple = *it;
02560          if (tuple->node_addr() == node_addr)
02561             return tuple;
02562       }
02563       return NULL;
02564    }
02565    // -----------------------------------------------------------------------
02566    template<typename OsModel_P,
02567             typename RoutingTable_P,
02568             typename Clock_P,
02569             typename Radio_P,
02570             typename Debug_P>
02571    void
02572    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02573    erase_mprsel_tuple(OLSR_mprsel_tuple* tuple)
02574    {
02575       for (typename mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++)
02576       {
02577          if (*it == tuple)
02578          {
02579             mprselset_.erase(it);
02580             break;
02581          }
02582       }
02583    }
02584    // -----------------------------------------------------------------------
02585    template<typename OsModel_P,
02586             typename RoutingTable_P,
02587             typename Clock_P,
02588             typename Radio_P,
02589             typename Debug_P>
02590    void
02591    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02592    erase_mprsel_tuples(node_id_t node_addr)
02593    {
02594       for (typename mprselset_t::iterator it = mprselset_.begin(); it != mprselset_.end(); it++)
02595       {
02596          OLSR_mprsel_tuple* tuple = *it;
02597          if (tuple->node_addr() == node_addr) {
02598             it = mprselset_.erase(it);
02599             it--;
02600          }
02601       }
02602    }
02603    // -----------------------------------------------------------------------
02604    template<typename OsModel_P,
02605             typename RoutingTable_P,
02606             typename Clock_P,
02607             typename Radio_P,
02608             typename Debug_P>
02609    void
02610    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02611    insert_mprsel_tuple(OLSR_mprsel_tuple* tuple)
02612    {
02613       mprselset_.push_back(tuple);
02614    }
02615 
02616    // -----------------------------------------------------------------------
02617    // brief Adds a topology tuple to the Topology Set.
02618 
02619    // param tuple the topology tuple to be added.
02620 
02621    template<typename OsModel_P,
02622             typename RoutingTable_P,
02623             typename Clock_P,
02624             typename Radio_P,
02625             typename Debug_P>
02626    void
02627    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02628    add_topology_tuple(OLSR_topology_tuple* tuple)
02629    {
02630 #ifdef DEBUG_OLSRROUTING
02631       Debug::debug(os(), "%f: Node %d adds topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
02632            Clock::time( os() ),
02633            Radio::id(os()),
02634            tuple->dest_addr(),
02635            tuple->last_addr(),
02636            tuple->seq() );
02637 #endif
02638 
02639       insert_topology_tuple(tuple);
02640    }
02641    // -----------------------------------------------------------------------
02642    // brief Removes a topology tuple from the Topology Set.
02643 
02644    // param tuple the topology tuple to be removed.
02645 
02646    template<typename OsModel_P,
02647             typename RoutingTable_P,
02648             typename Clock_P,
02649             typename Radio_P,
02650             typename Debug_P>
02651    void
02652    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02653    rm_topology_tuple(OLSR_topology_tuple* tuple)
02654    {
02655 #ifdef DEBUG_OLSRROUTING
02656       Debug::debug(os(), "%f: Node %d removes topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
02657            Clock::time( os() ),
02658            Radio::id(os()),
02659            tuple->dest_addr(),
02660            tuple->last_addr(),
02661            tuple->seq() );
02662 #endif
02663 
02664       erase_topology_tuple(tuple);
02665    }
02666    // -----------------------------------------------------------------------
02667 
02668    template<typename OsModel_P,
02669             typename RoutingTable_P,
02670             typename Clock_P,
02671             typename Radio_P,
02672             typename Debug_P>
02673    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_topology_tuple *
02674    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02675    find_topology_tuple(node_id_t dest_addr, node_id_t last_addr)
02676    {
02677       for (typename topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++)
02678       {
02679          OLSR_topology_tuple* tuple = *it;
02680          if (tuple->dest_addr() == dest_addr && tuple->last_addr() == last_addr)
02681             return tuple;
02682       }
02683       return NULL;
02684    }
02685    // -----------------------------------------------------------------------
02686 
02687    template<typename OsModel_P,
02688             typename RoutingTable_P,
02689             typename Clock_P,
02690             typename Radio_P,
02691             typename Debug_P>
02692    class OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::OLSR_topology_tuple *
02693    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02694    find_newer_topology_tuple(node_id_t last_addr, u_int16_t ansn)
02695    {
02696       for (typename topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++)
02697       {
02698          OLSR_topology_tuple* tuple = *it;
02699          if (tuple->last_addr() == last_addr && tuple->seq() > ansn)
02700             return tuple;
02701       }
02702       return NULL;
02703    }
02704    // -----------------------------------------------------------------------
02705    template<typename OsModel_P,
02706             typename RoutingTable_P,
02707             typename Clock_P,
02708             typename Radio_P,
02709             typename Debug_P>
02710    void
02711    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02712    erase_topology_tuple(OLSR_topology_tuple* tuple)
02713    {
02714       for (typename topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++)
02715       {
02716          if (*it == tuple)
02717          {
02718             topologyset_.erase(it);
02719             break;
02720          }
02721       }
02722    }
02723    // -----------------------------------------------------------------------
02724    template<typename OsModel_P,
02725             typename RoutingTable_P,
02726             typename Clock_P,
02727             typename Radio_P,
02728             typename Debug_P>
02729    void
02730    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02731    erase_older_topology_tuples(node_id_t last_addr, uint16_t ansn)
02732    {
02733       for (typename topologyset_t::iterator it = topologyset_.begin(); it != topologyset_.end(); it++)
02734       {
02735          OLSR_topology_tuple* tuple = *it;
02736          if (tuple->last_addr() == last_addr && tuple->seq() < ansn)
02737          {
02738             it = topologyset_.erase(it);
02739             it--;
02740          }
02741       }
02742    }
02743    // -----------------------------------------------------------------------
02744    template<typename OsModel_P,
02745             typename RoutingTable_P,
02746             typename Clock_P,
02747             typename Radio_P,
02748             typename Debug_P>
02749    void
02750    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02751    insert_topology_tuple(OLSR_topology_tuple* tuple)
02752    {
02753       topologyset_.push_back(tuple);
02754    }
02755    // -----------------------------------------------------------------------
02756    template<typename OsModel_P,
02757          typename RoutingTable_P,
02758          typename Clock_P,
02759          typename Radio_P,
02760          typename Debug_P>
02761    bool
02762    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02763    route_exists(node_id_t destination)
02764    {
02765       RoutingTableIterator it = routing_table_.find(destination);
02766        if (it != routing_table_.end())
02767        {
02768            return true;
02769        }
02770        else
02771            return false;
02772    }
02773 
02774    // -----------------------------------------------------------------------
02775    template<typename OsModel_P,
02776             typename RoutingTable_P,
02777             typename Clock_P,
02778             typename Radio_P,
02779             typename Debug_P>
02780    void
02781    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02782    print_routing_table( RoutingTable rt )
02783    {
02784 #ifdef DEBUG_OLSRROUTING
02785       int i = 0;
02786       Debug::debug( os(), "OlsrRouting: Routing Table:\n" );
02787       Debug::debug( os(), "+++++++++++++++++++++++++++++++++++++++++++++++++\n" );
02788 
02789       if (!rt.size())
02790         {
02791            Debug::debug( os(), "|          Routing Table is empty!!!            |\n" );
02792         }
02793       else
02794         {
02795               for ( RoutingTableIterator it = rt.begin(); it != rt.end(); ++it )
02796                {
02797                   Debug::debug( os(), "| RoutingTable[%i]: Dest %i SendTo %i Hops %i |\n", i++, it->first, it->second.next_addr, it->second.hops );
02798                }
02799         }
02800 
02801       Debug::debug( os(), "+++++++++++++++++++++++++++++++++++++++++++++++++\n" );
02802 #endif
02803    }
02804 
02805    // -----------------------------------------------------------------------
02806    template<typename OsModel_P,
02807             typename RoutingTable_P,
02808             typename Clock_P,
02809             typename Radio_P,
02810             typename Debug_P>
02811    int
02812    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02813    degree(OLSR_nb_tuple* tuple)
02814    {
02815       int degree = 0;
02816       for (typename nb2hopset_t::iterator it = nb2hopset().begin(); it != nb2hopset().end(); it++)
02817       {
02818          OLSR_nb2hop_tuple* nb2hop_tuple = *it;
02819          if (nb2hop_tuple->nb_node_addr() == tuple->nb_node_addr())
02820          {
02821             OLSR_nb_tuple* nb_tuple = find_nb_tuple(nb2hop_tuple->nb_node_addr());
02822             if (nb_tuple == NULL)
02823                degree++;
02824          }
02825       }
02826 
02827       return degree;
02828    }
02829 
02830    // -----------------------------------------------------------------------
02831    template<typename OsModel_P,
02832             typename RoutingTable_P,
02833             typename Clock_P,
02834             typename Radio_P,
02835             typename Debug_P>
02836    double
02837    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02838    emf_to_seconds(uint8_t olsr_format)
02839    {
02840       // This implementation has been taken from unik-olsrd-0.4.5 (mantissa.c), licensed under the GNU Public License (GPL)
02841       int a = olsr_format >> 4;
02842       int b = olsr_format - a*16;
02843       return (double)(OLSR_C*(1+(double)a/16)*(double)pow(2,b));
02844    }
02845 
02846    // -----------------------------------------------------------------------
02847    template<typename OsModel_P,
02848             typename RoutingTable_P,
02849             typename Clock_P,
02850             typename Radio_P,
02851             typename Debug_P>
02852    uint8_t
02853    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02854    seconds_to_emf(double seconds)
02855    {
02856       // This implementation has been taken from unik-olsrd-0.4.5 (mantissa.c), licensed under the GNU Public License (GPL)
02857       int a, b = 0;
02858       while (seconds/OLSR_C >= pow((double)2, (double)b))
02859          b++;
02860       b--;
02861 
02862       if (b < 0) {
02863          a = 1;
02864          b = 0;
02865       }
02866       else if (b > 15) {
02867          a = 15;
02868          b = 15;
02869       }
02870       else {
02871          a = (int)(16*((double)seconds/(OLSR_C*(double)pow(2, b))-1));
02872          while (a >= 16) {
02873             a -= 16;
02874             b++;
02875          }
02876       }
02877 
02878       return (uint8_t)(a*16+b);
02879    }
02880 
02881    // -----------------------------------------------------------------------
02882    template<typename OsModel_P,
02883             typename RoutingTable_P,
02884             typename Clock_P,
02885             typename Radio_P,
02886             typename Debug_P>
02887    void
02888    OlsrRouting<OsModel_P, RoutingTable_P, Clock_P, Radio_P, Debug_P>::
02889    nb_loss(OLSR_link_tuple* tuple)
02890    {
02891 #ifdef DEBUG_OLSRROUTING
02892       Debug::debug(os(), "%f: Node %d detects neighbor %d loss\n", Clock::time( os() ), Radio::id(os()), tuple->nb_node_addr());
02893 #endif
02894 
02895       updated_link_tuple(tuple);
02896       erase_nb2hop_tuples(tuple->nb_node_addr());
02897       erase_mprsel_tuples(tuple->nb_node_addr());
02898 
02899       mpr_computation();
02900     routing_table_computation();
02901    }
02902 
02903    // -----------------------------------------------------------------------
02904 
02905 
02906 }
02907 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines