xorp

pim_bsr.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 
00003 // Copyright (c) 2001-2011 XORP, Inc and Others
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, Version 2, June
00007 // 1991 as published by the Free Software Foundation. Redistribution
00008 // and/or modification of this program under the terms of any other
00009 // version of the GNU General Public License is not permitted.
00010 // 
00011 // This program is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00014 // see the GNU General Public License, Version 2, a copy of which can be
00015 // found in the XORP LICENSE.gpl file.
00016 // 
00017 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00018 // http://xorp.net
00019 
00020 
00021 #ifndef __PIM_PIM_BSR_HH__
00022 #define __PIM_PIM_BSR_HH__
00023 
00024 
00025 //
00026 // PIM Bootstrap Router (BSR) mechanism definitions
00027 //
00028 
00029 
00030 
00031 
00032 #include "libxorp/ipvx.hh"
00033 #include "libxorp/ipvxnet.hh"
00034 #include "libxorp/timer.hh"
00035 #include "libproto/proto_unit.hh"
00036 #include "pim_scope_zone_table.hh"
00037 
00038 
00039 //
00040 // Constants definitions
00041 //
00042 
00043 
00044 //
00045 // Structures/classes, typedefs and macros
00046 //
00047 
00048 class PimNode;
00049 class PimVif;
00050 class BsrGroupPrefix;
00051 class BsrZone;
00052 class BsrRp;
00053 
00054 // The PIM BSR class
00055 class PimBsr : public ProtoUnit {
00056 public:
00057     PimBsr(PimNode& pim_node);
00058     virtual ~PimBsr();
00059     
00063     void    clear();
00064 
00070     int     start();
00071 
00077     int     stop();
00078 
00084     void    enable();
00085     
00092     void    disable();
00093 
00100     int     apply_bsr_changes(string& error_msg);
00101 
00102     PimNode&    pim_node()  const   { return (_pim_node); }
00103     
00104     int     unicast_pim_bootstrap(PimVif *pim_vif,
00105                       const IPvX& nbr_addr) const;
00106     
00107     list<BsrZone *>& config_bsr_zone_list() { return (_config_bsr_zone_list); }
00108     list<BsrZone *>& active_bsr_zone_list() { return (_active_bsr_zone_list); }
00109     list<BsrZone *>& expire_bsr_zone_list() { return (_expire_bsr_zone_list); }
00110     
00111     BsrZone *add_config_bsr_zone(const BsrZone& bsr_zone,
00112                      string& error_msg);
00113     BsrZone *add_active_bsr_zone(const BsrZone& bsr_zone,
00114                        string& error_msg);
00115     BsrZone *add_expire_bsr_zone(const BsrZone& bsr_zone);
00116     void    delete_config_bsr_zone(BsrZone *old_bsr_zone);
00117     void    delete_active_bsr_zone(BsrZone *old_bsr_zone);
00118     void    delete_expire_bsr_zone(BsrZone *old_bsr_zone);
00119     void    delete_all_expire_bsr_zone_by_zone_id(const PimScopeZoneId& zone_id);
00120     void    delete_expire_bsr_zone_prefix(const IPvXNet& group_prefix,
00121                           bool is_scope_zone);
00122     
00123     BsrZone *find_config_bsr_zone(const PimScopeZoneId& zone_id) const;    
00124     BsrZone *find_active_bsr_zone(const PimScopeZoneId& zone_id) const;
00125     BsrZone *find_config_bsr_zone_by_prefix(const IPvXNet& group_prefix,
00126                         bool is_scope_zone) const;
00127     BsrZone *find_active_bsr_zone_by_prefix(const IPvXNet& group_prefix,
00128                         bool is_scope_zone) const;
00129     BsrRp   *find_rp(const IPvXNet& group_prefix, bool is_scope_zone,
00130              const IPvX& rp_addr) const;
00131     void    add_rps_to_rp_table();
00132     void    schedule_rp_table_apply_rp_changes();
00133     void    clean_expire_bsr_zones();
00134     void    schedule_clean_expire_bsr_zones();
00135 
00136     void    add_vif_addr(uint32_t vif_index, const IPvX& vif_addr);
00137     void    delete_vif_addr(uint32_t vif_index, const IPvX& vif_addr);
00138 
00139     //
00140     // Test-related methods
00141     //
00142     BsrZone *add_test_bsr_zone(const PimScopeZoneId& zone_id,
00143                    const IPvX& bsr_addr,
00144                    uint8_t bsr_priority,
00145                    uint8_t hash_mask_len,
00146                    uint16_t fragment_tag);
00147     BsrZone *find_test_bsr_zone(const PimScopeZoneId& zone_id) const;
00148     BsrGroupPrefix *add_test_bsr_group_prefix(const PimScopeZoneId& zone_id,
00149                           const IPvXNet& group_prefix,
00150                           bool is_scope_zone,
00151                           uint8_t expected_rp_count);
00152     BsrRp   *add_test_bsr_rp(const PimScopeZoneId& zone_id,
00153                  const IPvXNet& group_prefix,
00154                  const IPvX& rp_addr,
00155                  uint8_t rp_priority,
00156                  uint16_t rp_holdtime);
00157     int     send_test_bootstrap(const string& vif_name, string& error_msg);
00158     int     send_test_bootstrap_by_dest(const string& vif_name,
00159                         const IPvX& dest_addr,
00160                         string& error_msg);
00161     int     send_test_cand_rp_adv();
00162     
00163 private:
00164     void    rp_table_apply_rp_changes_timer_timeout();
00165     void    clean_expire_bsr_zones_timer_timeout();
00166     
00167     BsrZone *find_bsr_zone_by_prefix_from_list(
00168     const list<BsrZone *>& zone_list, const IPvXNet& group_prefix,
00169     bool is_scope_zone) const;
00170     bool    can_add_config_bsr_zone(const BsrZone& bsr_zone,
00171                     string& error_msg) const;
00172     bool    can_add_active_bsr_zone(const BsrZone& bsr_zone,
00173                     string& error_msg) const;
00174     PimNode&    _pim_node;          // The associated PIM node
00175     list<BsrZone *> _config_bsr_zone_list;  // List of configured Cand-BSR
00176                         // zones and/or Cand-RP info
00177     list<BsrZone *> _active_bsr_zone_list;  // List of active BSR zones
00178     list<BsrZone *> _expire_bsr_zone_list;  // List of expiring BSR zones
00179     list<BsrZone *> _test_bsr_zone_list;    // List of test BSR zones
00180     XorpTimer   _rp_table_apply_rp_changes_timer; // Timer to apply RP changes
00181                           // to the RpTable
00182     XorpTimer   _clean_expire_bsr_zones_timer;  // Timer to cleanup expiring
00183                         // BSR zones
00184 };
00185 
00186 class BsrZone : public BugCatcher {
00187 public:
00188     BsrZone(PimBsr& pim_bsr, const BsrZone& bsr_zone);
00189     BsrZone(PimBsr& pim_bsr, const PimScopeZoneId& zone_id);
00190     BsrZone(PimBsr& pim_bsr, const IPvX& bsr_addr, uint8_t bsr_priority,
00191         uint8_t hash_mask_len, uint16_t fragment_tag);
00192     ~BsrZone();
00193     
00194     PimBsr& pim_bsr()       { return (_pim_bsr);        }
00195     
00196     //
00197     // BsrZone type
00198     //
00199     bool    is_config_bsr_zone() const { return (_is_config_bsr_zone); }
00200     bool    is_active_bsr_zone() const { return (_is_active_bsr_zone); }
00201     bool    is_expire_bsr_zone() const { return (_is_expire_bsr_zone); }
00202     bool    is_test_bsr_zone() const { return (_is_test_bsr_zone); }
00203     void    set_config_bsr_zone(bool v);
00204     void    set_active_bsr_zone(bool v);
00205     void    set_expire_bsr_zone(bool v);
00206     void    set_test_bsr_zone(bool v);
00207     
00208     const IPvX& bsr_addr() const    { return (_bsr_addr);       }
00209     void    set_bsr_addr(const IPvX& v) { _bsr_addr = v; }
00210     uint8_t bsr_priority() const    { return (_bsr_priority);   }
00211     void    set_bsr_priority(uint8_t v) { _bsr_priority = v;    }
00212     uint8_t hash_mask_len() const   { return (_hash_mask_len);  }
00213     uint16_t    fragment_tag() const    { return (_fragment_tag);   }
00214     uint16_t    new_fragment_tag()  { return (++_fragment_tag); }
00215     bool    is_accepted_message() const { return (_is_accepted_message); }
00216     void    set_is_accepted_message(bool v) { _is_accepted_message = v; }
00217     bool    is_unicast_message() const { return (_is_unicast_message); }
00218     const IPvX& unicast_message_src() const { return (_unicast_message_src); }
00219     void    set_is_unicast_message(bool v, const IPvX& src) {
00220     _is_unicast_message = v;
00221     _unicast_message_src = src;
00222     }
00223     bool    is_cancel() const   { return (_is_cancel);      }
00224     void    set_is_cancel(bool v)   { _is_cancel = v;       }
00225     const PimScopeZoneId& zone_id() const { return (_zone_id);      }
00226     void    set_zone_id(const PimScopeZoneId& zone_id) { _zone_id = zone_id; }
00227     
00228     // The states used per scope zone
00229     enum bsr_zone_state_t {
00230     STATE_INIT,         // The state after initialization
00231     // States if I am a Candidate BSR
00232     STATE_CANDIDATE_BSR,
00233     STATE_PENDING_BSR,
00234     STATE_ELECTED_BSR,
00235     // States if I am not a Candidate BSR
00236     STATE_NO_INFO,
00237     STATE_ACCEPT_ANY,
00238     STATE_ACCEPT_PREFERRED
00239     };
00240     bsr_zone_state_t bsr_zone_state() const { return (_bsr_zone_state); }
00241     void set_bsr_zone_state(bsr_zone_state_t v) { _bsr_zone_state = v;  }
00242 
00250     int update_config_bsr_zone(const BsrZone& new_bsr_zone, string& error_msg);
00251 
00252     bool    is_consistent(string& error_msg) const;
00253     bool    can_merge_rp_set(const BsrZone& bsr_zone,
00254                  string& error_msg) const;
00255     void    merge_rp_set(const BsrZone& bsr_zone);
00256     void    store_rp_set(const BsrZone& bsr_zone);
00257     
00258     XorpTimer&  bsr_timer()         { return (_bsr_timer);  }
00259     const XorpTimer& const_bsr_timer() const    { return (_bsr_timer);  }
00260     void    expire_bsr_timer();
00261     XorpTimer&  scope_zone_expiry_timer() {
00262     return (_scope_zone_expiry_timer);
00263     }
00264     const XorpTimer& const_scope_zone_expiry_timer() const {
00265     return (_scope_zone_expiry_timer);
00266     }
00267     
00268     const list<BsrGroupPrefix *>& bsr_group_prefix_list() const {
00269     return (_bsr_group_prefix_list);
00270     }
00271     list<BsrGroupPrefix *>& bsr_group_prefix_list() {
00272     return (_bsr_group_prefix_list);
00273     }
00274     BsrGroupPrefix *add_bsr_group_prefix(const IPvXNet& group_prefix_init,
00275                      bool is_scope_zone_init,
00276                      uint8_t expected_rp_count);
00277     void    delete_bsr_group_prefix(BsrGroupPrefix *bsr_group_prefix);
00278     BsrGroupPrefix *find_bsr_group_prefix(const IPvXNet& group_prefix) const;
00279     
00280     bool    process_candidate_bsr(const BsrZone& cand_bsr_zone);
00281     bool    i_am_bsr() const;
00282     bool    is_new_bsr_preferred(const BsrZone& bsr_zone) const;
00283     bool    is_new_bsr_same_priority(const BsrZone& bsr_zone) const;
00284     TimeVal randomized_override_interval(const IPvX& my_addr,
00285                      uint8_t my_priority) const;
00286     
00287     bool    is_bsm_forward() const { return (_is_bsm_forward); }
00288     void    set_bsm_forward(bool v) { _is_bsm_forward = v; }
00289     bool    is_bsm_originate() const { return (_is_bsm_originate); }
00290     void    set_bsm_originate(bool v) { _is_bsm_originate = v; }
00291     bool    i_am_candidate_bsr() const { return (_i_am_candidate_bsr); }
00292     void    set_i_am_candidate_bsr(bool i_am_candidate_bsr,
00293                        uint32_t my_vif_index,
00294                        const IPvX& my_bsr_addr,
00295                        uint8_t my_bsr_priority);
00296     
00297     uint32_t    my_vif_index() const    { return (_my_vif_index);   }
00298     const IPvX& my_bsr_addr() const { return (_my_bsr_addr);    }
00299     uint8_t my_bsr_priority() const { return (_my_bsr_priority);    }
00300     bool    is_my_bsr_addr_explicit() const { return (_is_my_bsr_addr_explicit); }
00301     void    set_is_my_bsr_addr_explicit(bool v) { _is_my_bsr_addr_explicit = v; }
00302     
00303     //
00304     // Cand-RP related methods
00305     //
00306     BsrRp   *find_rp(const IPvXNet& group_prefix,
00307              const IPvX& rp_addr) const;
00308     BsrRp   *add_rp(const IPvXNet& group_prefix,
00309             bool is_scope_zone_init,
00310             const IPvX& rp_addr,
00311             uint8_t rp_priority,
00312             uint16_t rp_holdtime,
00313             string& error_msg);
00314     XorpTimer&  candidate_rp_advertise_timer() {
00315     return (_candidate_rp_advertise_timer);
00316     }
00317     const XorpTimer& const_candidate_rp_advertise_timer() const {
00318     return (_candidate_rp_advertise_timer);
00319     }
00320     void    start_candidate_rp_advertise_timer();
00321     void    expire_candidate_rp_advertise_timer();
00322     
00323 private:
00324     void    bsr_timer_timeout();
00325     void    scope_zone_expiry_timer_timeout();
00326     void    candidate_rp_advertise_timer_timeout();
00327     
00328     PimBsr& _pim_bsr;       // The PimBsr for this BsrZone
00329     
00330     // BsrZone type
00331     bool    _is_config_bsr_zone;    // True if config BSR zone
00332     bool    _is_active_bsr_zone;    // True if active BSR zone
00333     bool    _is_expire_bsr_zone;    // True if expire BSR zone
00334     bool    _is_test_bsr_zone;  // True if test BSR zone
00335     
00336     // State at all routers
00337     IPvX    _bsr_addr;      // The address of the Bootstrap router
00338     uint8_t _bsr_priority;      // The BSR priority (larger is better)
00339     uint8_t _hash_mask_len;     // The hash mask length
00340     uint16_t    _fragment_tag;      // The fragment tag
00341     bool    _is_accepted_message;   // True if info accepted already
00342     bool    _is_unicast_message;    // True if info received by unicast
00343     IPvX    _unicast_message_src;   // The source address of the info
00344                     // (if received by unicast)
00345     
00346     PimScopeZoneId _zone_id;        // The (prefix-based) scope zone ID.
00347                     // If non-scoped zone, the ID is
00348                     // IPvXNet:ip_multicast_base_prefix()
00349     
00350     XorpTimer   _bsr_timer;     // The Bootstrap Timer
00351     list<BsrGroupPrefix *> _bsr_group_prefix_list; // The list of group
00352                     // prefixes for this zone.
00353                     // XXX: if a scope zone, and if there
00354                     // is a group-RP prefix for the whole
00355                     // zone, this prefix must be in front.
00356     bsr_zone_state_t _bsr_zone_state;   // Scope zone state
00357     XorpTimer   _scope_zone_expiry_timer; // The Scope-Zone Expiry Timer
00358     
00359     // State at a Candidate BSR
00360     bool    _i_am_candidate_bsr;    // True if I am Cand-BSR for this zone
00361     uint32_t    _my_vif_index;      // The vif index with my address
00362                     // if a Cand-BSR
00363     IPvX    _my_bsr_addr;       // My address if a Cand-BSR
00364     uint8_t _my_bsr_priority;   // My BSR priority if a Cand-BSR
00365     bool    _is_my_bsr_addr_explicit; // True if my Cand-BSR address was
00366                     // set explicitly
00367     
00368     // State at a Candidate RP
00369     XorpTimer   _candidate_rp_advertise_timer; // The C-RP Adv. Timer
00370     
00371     // Misc. state
00372     bool    _is_bsm_forward;    // Temp. state: if true, forward BSM
00373     bool    _is_bsm_originate;  // Temp. state: if true, originate BSM
00374     bool    _is_cancel;     // True if we are canceling this zone
00375 };
00376 
00377 class BsrGroupPrefix {
00378 public:
00379     BsrGroupPrefix(BsrZone& bsr_zone, const IPvXNet& group_prefix,
00380            bool is_scope_zone, uint8_t expected_rp_count);
00381     BsrGroupPrefix(BsrZone& bsr_zone, const BsrGroupPrefix& bsr_group_prefix);
00382     ~BsrGroupPrefix();
00383     
00384     BsrZone&    bsr_zone()      { return (_bsr_zone);       }
00385     bool    is_scope_zone() const { return (_is_scope_zone); }
00386     const IPvXNet& group_prefix() const { return (_group_prefix);   }
00387     uint8_t expected_rp_count() const { return (_expected_rp_count); }
00388     uint8_t received_rp_count() const { return (_received_rp_count); }
00389     void    set_received_rp_count(uint8_t v) { _received_rp_count = v; }
00390     void    set_expected_rp_count(uint8_t v) { _expected_rp_count = v; }
00391     const list<BsrRp *>& rp_list()  const   { return (_rp_list);    }
00392     list<BsrRp *>& rp_list()            { return (_rp_list);    }
00393     BsrRp   *add_rp(const IPvX& rp_addr, uint8_t rp_priority,
00394             uint16_t rp_holdtime);
00395     void    delete_rp(BsrRp *bsr_rp);
00396     BsrRp   *find_rp(const IPvX& rp_addr) const;
00397     bool is_completed() const { return (_expected_rp_count == _received_rp_count); }
00398     
00399     // Removal related methods
00400     void    schedule_bsr_group_prefix_remove();
00401     const XorpTimer& const_remove_timer() const {
00402     return (_remove_timer);
00403     }
00404     
00405     
00406 private:
00407     void    remove_timer_timeout();
00408     
00409     BsrZone&    _bsr_zone;      // The BSR zone I belong to
00410     
00411     // Group prefix state
00412     IPvXNet _group_prefix;      // The group address prefix
00413     bool    _is_scope_zone;     // True if prefix for admin. scope zone
00414     uint8_t _expected_rp_count; // Expected number of RPs
00415     uint8_t _received_rp_count; // Received number of RPs so far
00416     list<BsrRp *> _rp_list;     // The list of received RPs
00417     
00418     // Misc. state
00419     XorpTimer   _remove_timer;      // Timer to remove empty prefix
00420 };
00421 
00422 class BsrRp {
00423 public:
00424     BsrRp(BsrGroupPrefix& bsr_group_prefix, const IPvX& rp_addr,
00425       uint8_t rp_priority, uint16_t rp_holdtime);
00426     BsrRp(BsrGroupPrefix& bsr_group_prefix, const BsrRp& bsr_rp);
00427     
00428     BsrGroupPrefix& bsr_group_prefix() { return (_bsr_group_prefix); }
00429     const IPvX& rp_addr() const { return (_rp_addr);            }
00430     void    set_rp_addr(const IPvX& v) { _rp_addr = v;      }
00431     uint8_t rp_priority() const { return (_rp_priority);        }
00432     uint16_t    rp_holdtime() const { return (_rp_holdtime);        }
00433     void    set_rp_priority(uint8_t v)  { _rp_priority = v;     }
00434     void    set_rp_holdtime(uint16_t v) { _rp_holdtime = v;     }
00435     const XorpTimer& const_candidate_rp_expiry_timer() const {
00436     return (_candidate_rp_expiry_timer);
00437     }
00438     void    start_candidate_rp_expiry_timer();
00439 
00440     uint32_t    my_vif_index() const    { return (_my_vif_index);   }
00441     void    set_my_vif_index(uint32_t v) { _my_vif_index = v; }
00442     bool    is_my_rp_addr_explicit() const { return (_is_my_rp_addr_explicit); }
00443     void    set_is_my_rp_addr_explicit(bool v) { _is_my_rp_addr_explicit = v; }
00444     
00445 private:
00446     void    candidate_rp_expiry_timer_timeout();
00447     
00448     BsrGroupPrefix& _bsr_group_prefix;  // The BSR prefix I belong to
00449     
00450     // RP state
00451     IPvX    _rp_addr;       // The address of the RP
00452     uint8_t _rp_priority;       // RP priority (smaller is better)
00453     uint16_t    _rp_holdtime;       // RP holdtime (in seconds)
00454     XorpTimer   _candidate_rp_expiry_timer; // The C-RP Expiry Timer
00455     uint32_t    _my_vif_index;      // The vif index with my address
00456                     // if a Cand-RP
00457     bool    _is_my_rp_addr_explicit; // True if my Cand-RP address was
00458                     // set explicitly
00459 };
00460 
00461 //
00462 // Global variables
00463 //
00464 
00465 
00466 //
00467 // Global functions prototypes
00468 //
00469 
00470 #endif // __PIM_PIM_BSR_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations