xorp

bgp.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License, Version 2, June
00008 // 1991 as published by the Free Software Foundation. Redistribution
00009 // and/or modification of this program under the terms of any other
00010 // version of the GNU General Public License is not permitted.
00011 // 
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00015 // see the GNU General Public License, Version 2, a copy of which can be
00016 // found in the XORP LICENSE.gpl file.
00017 // 
00018 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00019 // http://xorp.net
00020 
00021 
00022 #ifndef __BGP_MAIN_HH__
00023 #define __BGP_MAIN_HH__
00024 
00025 #include "libxorp/status_codes.h"
00026 #include "libxipc/xrl_std_router.hh"
00027 #include "libxorp/profile.hh"
00028 
00029 #include "socket.hh"
00030 #include "packet.hh"
00031 
00032 #include "peer.hh"
00033 #include "peer_list.hh"
00034 #include "plumbing.hh"
00035 #include "iptuple.hh"
00036 #include "path_attribute.hh"
00037 #include "peer_handler.hh"
00038 #include "process_watch.hh"
00039 
00040 #include "libfeaclient/ifmgr_xrl_mirror.hh"
00041 #include "policy/backend/version_filters.hh"
00042 
00043 class EventLoop;
00044 class XrlBgpTarget;
00045 
00046 class BGPMain : public ServiceBase,
00047         public IfMgrHintObserver,
00048         public ServiceChangeObserverBase {
00049 public:
00050     BGPMain(EventLoop& eventloop);
00051     ~BGPMain();
00052 
00056     ProcessStatus status(string& reason);
00057 
00063     int startup();
00064 
00070     int shutdown();
00071 
00077     void component_up(const string& component_name);
00078 
00084     void component_down(const string& component_name);
00085 
00092     bool is_interface_enabled(const string& interface) const;
00093 
00101     bool is_vif_enabled(const string& interface, const string& vif) const;
00102 
00111     bool is_address_enabled(const string& interface, const string& vif,
00112                 const IPv4& address) const;
00113 
00114     typedef XorpCallback2<void, const string&,
00115               bool>::RefPtr InterfaceStatusCb;
00116     typedef XorpCallback3<void, const string&, const string&,
00117               bool>::RefPtr VifStatusCb;
00118     typedef XorpCallback5<void, const string&, const string&, const IPv4&,
00119               uint32_t, bool>::RefPtr AddressStatus4Cb;
00120 
00129     void register_interface_status(InterfaceStatusCb cb) {
00130     _interface_status_cb = cb;
00131     }
00132 
00141     void register_vif_status(VifStatusCb cb) {
00142     _vif_status_cb = cb;
00143     }
00144 
00154     void register_address_status(AddressStatus4Cb cb) {
00155     _address_status4_cb = cb;
00156     }
00157 
00166     uint32_t get_prefix_length(const string& interface, const string& vif,
00167                    const IPv4& address);
00168 
00175     uint32_t get_mtu(const string& interface);
00176 
00180     bool interface_address4(const IPv4& address) const;
00181 
00190     bool interface_address_prefix_len4(const IPv4& address,
00191                        uint32_t& prefix_len) const;
00192 
00203     void local_config(const uint32_t& as, const IPv4& id, 
00204               bool use_4byte_asnums);
00205 
00209     void set_confederation_identifier(const uint32_t& as, bool disable);
00210 
00214     void set_cluster_id(const IPv4& cluster_id, bool disable);
00215 
00219     void set_damping(uint32_t half_life,uint32_t max_suppress,uint32_t reuse,
00220              uint32_t suppress, bool disable);
00221 
00227     void attach_peer(BGPPeer *p);
00228 
00234     void detach_peer(BGPPeer *p);
00235 
00241     void attach_deleted_peer(BGPPeer *p);
00242 
00248     void detach_deleted_peer(BGPPeer *p);
00249 
00258     BGPPeer *find_peer(const Iptuple& search, list<BGPPeer *>& peers);
00259 
00267     BGPPeer *find_peer(const Iptuple& search);
00268 
00276     BGPPeer *find_deleted_peer(const Iptuple& search);
00277 
00285     bool create_peer(BGPPeerData *pd);
00286 
00296     bool delete_peer(const Iptuple& iptuple);
00297 
00305     bool enable_peer(const Iptuple& iptuple);
00306 
00314     bool disable_peer(const Iptuple& iptuple);
00315 
00324     bool bounce_peer(const Iptuple& iptuple);
00325 
00336     void local_ip_changed(string local_address);
00337 
00346     bool change_tuple(const Iptuple& iptuple, const Iptuple& nptuple);
00347 
00358     bool find_tuple_179(string peer_addr, Iptuple& otuple);
00359 
00369     bool change_local_ip(const Iptuple& iptuple, const string& local_ip, const string& local_dev);
00370 
00379     bool change_local_port(const Iptuple& iptuple, uint32_t local_port);
00380 
00389     bool change_peer_port(const Iptuple& iptuple, uint32_t peer_port);
00390 
00399     bool set_peer_as(const Iptuple& iptuple, uint32_t peer_as);
00400 
00409     bool set_holdtime(const Iptuple& iptuple, uint32_t holdtime);
00410 
00419     bool set_delay_open_time(const Iptuple& iptuple, uint32_t delay_open_time);
00420 
00429     bool set_route_reflector_client(const Iptuple& iptuple, bool rr);
00430 
00439     bool set_confederation_member(const Iptuple& iptuple, bool conf);
00440 
00449     bool set_prefix_limit(const Iptuple& iptuple, 
00450               uint32_t maximum, bool state);
00451 
00460     bool set_nexthop4(const Iptuple& iptuple, const IPv4& next_hop);
00461 
00470     bool set_peer_state(const Iptuple& iptuple, bool state);
00471 
00481     bool activate(const Iptuple& iptuple);
00482 
00488     bool activate_all_peers();
00489 
00499     bool set_peer_md5_password(const Iptuple& iptuple, const string& password);
00500 
00501     /*
00502      * Set next hop rewrite filter.
00503      *
00504      * @param iptuple iptuple.
00505      * @param next_hop next hop value zero to clear filter.
00506      *
00507      * @return true on success
00508      */
00509     bool next_hop_rewrite_filter(const Iptuple& iptuple, const IPv4& next_hop);
00510 
00511     bool get_peer_list_start(uint32_t& token);
00512 
00513     bool get_peer_list_next(const uint32_t& token, 
00514                 string& local_ip, 
00515                 uint32_t& local_port, 
00516                 string& peer_ip, 
00517                 uint32_t& peer_port);
00518 
00519     bool get_peer_id(const Iptuple& iptuple, IPv4& peer_id);
00520     bool get_peer_status(const Iptuple& iptuple,  uint32_t& peer_state, 
00521              uint32_t& admin_status);
00522     bool get_peer_negotiated_version(const Iptuple& iptuple, 
00523                      int32_t& neg_version);
00524     bool get_peer_as(const Iptuple& iptuple,   uint32_t& peer_as);
00525     bool get_peer_msg_stats(const Iptuple& iptuple, 
00526                 uint32_t& in_updates, 
00527                 uint32_t& out_updates, 
00528                 uint32_t& in_msgs, 
00529                 uint32_t& out_msgs, 
00530                 uint16_t& last_error, 
00531                 uint32_t& in_update_elapsed);
00532     bool get_peer_established_stats(const Iptuple& iptuple,  
00533                     uint32_t& transitions, 
00534                     uint32_t& established_time);
00535     bool get_peer_timer_config(const Iptuple& iptuple,
00536                    uint32_t& retry_interval, 
00537                    uint32_t& hold_time, 
00538                    uint32_t& keep_alive, 
00539                    uint32_t& hold_time_configured, 
00540                    uint32_t& keep_alive_configured, 
00541                    uint32_t& min_as_origination_interval,
00542                    uint32_t& min_route_adv_interval);
00543 
00544     bool register_ribname(const string& name);
00545 
00546     void main_loop();
00547 
00548     void terminate() { xorp_do_run = 0; }
00549 
00550     XorpFd create_listener(const Iptuple& iptuple);
00551     LocalData *get_local_data();
00552     void start_server(const Iptuple& iptuple);
00553     void stop_server(const Iptuple& iptuple);
00557     void stop_all_servers();
00558 
00570     bool originate_route(const IPv4Net& nlri,
00571              const IPv4& next_hop,
00572              const bool& unicast,
00573              const bool& multicast,
00574              const PolicyTags& policytags);
00575 
00585     bool withdraw_route(const IPv4Net&  nlri,
00586             const bool& unicast,
00587             const bool& multicast) const;
00588 
00589     template <typename A>
00590     bool get_route_list_start(uint32_t& token,
00591                   const IPNet<A>& prefix,
00592                   const bool& unicast,
00593                   const bool& multicast);
00594 
00595     template <typename A>
00596     bool get_route_list_next(
00597                   // Input values, 
00598                   const uint32_t&   token, 
00599                   // Output values, 
00600                   IPv4&  peer_id, 
00601                   IPNet<A>& net, 
00602                   uint32_t& origin, 
00603                   vector<uint8_t>& aspath, 
00604                   A& nexthop, 
00605                   int32_t& med, 
00606                   int32_t& localpref, 
00607                   int32_t& atomic_agg, 
00608                   vector<uint8_t>& aggregator, 
00609                   int32_t& calc_localpref, 
00610                   vector<uint8_t>& attr_unknown,
00611                   bool& best,
00612                   bool& unicast,
00613                   bool& multicast);
00614 
00615     bool rib_client_route_info_changed4(
00616                     // Input values,
00617                     const IPv4& addr,
00618                     const uint32_t& prefix_len,
00619                     const IPv4& nexthop,
00620                     const uint32_t& metric);
00621 
00622     bool rib_client_route_info_invalid4(
00623                     // Input values,
00624                     const IPv4& addr,
00625                     const uint32_t& prefix_len);
00626 
00637     bool set_parameter(
00638                 // Input values,
00639                const Iptuple& iptuple,
00640                const string& parameter,
00641                const bool toggle);
00642 
00647     BGPPlumbing *plumbing_unicast() const { return _plumbing_unicast; }
00648     BGPPlumbing *plumbing_multicast() const { return _plumbing_multicast; }
00649 
00650     XrlStdRouter *get_router() { return _xrl_router; }
00651     EventLoop& eventloop() { return _eventloop; }
00652     XrlBgpTarget *get_xrl_target() { return _xrl_target; }
00653 
00661     void notify_birth(const string& target_class,
00662               const string& target_instance) {
00663     _process_watch->birth(target_class, target_instance);
00664     }
00665 
00673     void notify_death(const string& target_class,
00674               const string& target_instance) {
00675     _process_watch->death(target_class, target_instance);
00676     }
00677 
00682     bool processes_ready() {
00683     return _process_watch->ready();
00684     }
00685 
00689     string bgp_mib_name() const {
00690     return "bgp4_mib";
00691     }
00692 
00696     bool do_snmp_trap() const {
00697     return _process_watch->target_exists(bgp_mib_name());
00698     }
00699 
00703     void finder_death(const char *file, const int lineno) {
00704     _process_watch->finder_death(file, lineno);
00705     }
00706 
00713     void configure_filter(const uint32_t& filter, const string& conf);
00714 
00720     void reset_filter(const uint32_t& filter);
00721 
00725     void push_routes();
00726 
00728 #ifdef HAVE_IPV6
00729 
00738     bool is_address_enabled(const string& interface, const string& vif,
00739                 const IPv6& address) const;
00740 
00741     typedef XorpCallback5<void, const string&, const string&, const IPv6&,
00742               uint32_t, bool>::RefPtr AddressStatus6Cb;
00743 
00753     void register_address_status(AddressStatus6Cb cb) {
00754     _address_status6_cb = cb;
00755     }
00756 
00765     uint32_t get_prefix_length(const string& interface, const string& vif,
00766                    const IPv6& address);
00767 
00771     bool interface_address6(const IPv6& address) const;
00772 
00781     bool interface_address_prefix_len6(const IPv6& address,
00782                        uint32_t& prefix_len) const;
00783 
00792     bool set_nexthop6(const Iptuple& iptuple, const IPv6& next_hop);
00793 
00802     bool get_nexthop6(const Iptuple& iptuple, IPv6& next_hop);
00803 
00815     bool originate_route(const IPv6Net& nlri,
00816              const IPv6& next_hop,
00817              const bool& unicast,
00818              const bool& multicast,
00819              const PolicyTags& policytags);
00820 
00826     bool withdraw_route(const IPv6Net&  nlri,
00827             const bool& unicast,
00828             const bool& multicast) const;
00829 
00830     bool rib_client_route_info_changed6(
00831                     // Input values,
00832                     const IPv6& addr,
00833                     const uint32_t& prefix_len,
00834                     const IPv6& nexthop,
00835                     const uint32_t& metric);
00836 
00837     bool rib_client_route_info_invalid6(
00838                     // Input values,
00839                     const IPv6& addr,
00840                     const uint32_t& prefix_len);
00841 
00842 #endif //ipv6
00843     
00844 #ifndef XORP_DISABLE_PROFILE
00845 
00848     Profile& profile() {return _profile;}
00849 #endif
00850 
00851 protected:
00852 private:
00860     void status_change(ServiceBase* service,
00861                ServiceStatus    old_status,
00862                ServiceStatus    new_status);
00863 
00869     const ServiceBase* ifmgr_mirror_service_base() const {
00870     return dynamic_cast<const ServiceBase*>(_ifmgr);
00871     }
00872 
00878     const IfMgrIfTree& ifmgr_iftree() const { return _ifmgr->iftree(); }
00879 
00884     void tree_complete();
00885 
00890     void updates_made();
00891 
00895     void address_status_change4(const string& interface, const string& vif,
00896                 const IPv4& source, uint32_t prefix_len,
00897                 bool state);
00898 
00902     struct Server {
00903     Server(XorpFd fd, const Iptuple& iptuple) : _serverfd(fd) {
00904         _tuples.push_back(iptuple);
00905     }
00906     Server(const Server& rhs) {
00907         _serverfd = rhs._serverfd;
00908         _tuples = rhs._tuples;
00909     }
00910     Server& operator=(const Server& rhs) {
00911         if (&rhs == this)
00912         return *this;
00913 
00914         _serverfd = rhs._serverfd;
00915         _tuples = rhs._tuples;
00916 
00917         return *this;
00918     }
00919     string str() {
00920         return c_format("fd(%s)", _serverfd.str().c_str());
00921 
00922     }
00923     XorpFd _serverfd;
00924     list <Iptuple> _tuples;
00925     };
00926 
00927     list<Server> _serverfds;
00928 
00932     void connect_attempt(XorpFd fd, IoEventType type, string laddr, uint16_t lport);
00933 
00934     template <typename A>
00935     void extract_attributes(// Input values, 
00936                 PAListRef<A> attributes, 
00937                 // Output values, 
00938                 uint32_t& origin, 
00939                 vector<uint8_t>& aspath, 
00940                 A& nexthop,
00941                 int32_t& med, 
00942                 int32_t& localpref, 
00943                 int32_t& atomic_agg, 
00944                 vector<uint8_t>& aggregator, 
00945                 int32_t& calc_localpref, 
00946                 vector<uint8_t>& attr_unknown);
00947 
00948 
00949     EventLoop& _eventloop;
00950     bool _exit_loop;
00951     BGPPeerList *_peerlist;     // List of current BGP peers.
00952     BGPPeerList *_deleted_peerlist; // List of deleted BGP peers.
00953 
00957     BGPPlumbing *_plumbing_unicast;
00958     NextHopResolver<IPv4> *_next_hop_resolver_ipv4;
00959 
00963     BGPPlumbing *_plumbing_multicast;
00964 
00968     template <typename A>
00969     class RoutingTableToken {
00970     public:
00971     RoutingTableToken() : _last(0)
00972     {}
00973 
00974     uint32_t create(uint32_t& internal_token, const IPNet<A>& prefix,
00975             const bool& unicast, const bool& multicast) {
00976 
00977         while(_tokens.find(_last) != _tokens.end())
00978         _last++;
00979         
00980         _tokens.insert(make_pair(_last, WhichTable(internal_token, prefix,
00981                                unicast, multicast)));
00982 
00983         return _last;
00984     }
00985     
00986     bool lookup(uint32_t& token, IPNet<A>& prefix,
00987             bool& unicast, bool& multicast) {
00988         typename map <uint32_t, WhichTable>::iterator i;
00989 
00990         i = _tokens.find(token);
00991         if (i == _tokens.end())
00992         return false;
00993 
00994         WhichTable t = i->second;
00995 
00996         token = t._token;
00997         prefix = t._prefix;
00998         unicast = t._unicast;
00999         multicast = t._multicast;
01000 
01001         return true;
01002     }
01003 
01004     void erase(uint32_t& token) {
01005         _tokens.erase(token);
01006     }
01007 
01008     private:
01009     struct WhichTable {
01010         WhichTable() {}
01011         WhichTable(uint32_t token, IPNet<A> prefix,
01012                bool unicast, bool multicast)
01013         : _token(token), _prefix(prefix),
01014           _unicast(unicast), _multicast(multicast)
01015                                    {}
01016         uint32_t _token;
01017         IPNet<A> _prefix;
01018         bool _unicast;
01019         bool _multicast;
01020     };
01021 
01022     map <uint32_t, WhichTable> _tokens;
01023     uint32_t _last;
01024     };
01025 
01026     template <typename A> RoutingTableToken<A>& get_token_table();
01027 
01028     RoutingTableToken<IPv4> _table_ipv4;
01029 
01030     XrlBgpTarget *_xrl_target;
01031     RibIpcHandler *_rib_ipc_handler;
01032     AggregationHandler *_aggregation_handler;
01033     LocalData *_local_data;
01034     XrlStdRouter *_xrl_router;
01035     ProcessWatch *_process_watch;
01036     VersionFilters _policy_filters;
01037 #ifndef XORP_DISABLE_PROFILE
01038     Profile _profile;
01039 #endif
01040 
01041     size_t      _component_count;
01042     IfMgrXrlMirror* _ifmgr;
01043     bool        _is_ifmgr_ready;
01044     IfMgrIfTree     _iftree;    // The interface state information
01045 
01046     InterfaceStatusCb   _interface_status_cb;
01047     VifStatusCb     _vif_status_cb;
01048     AddressStatus4Cb    _address_status4_cb;
01049 
01050     map<IPv4, uint32_t> _interfaces_ipv4;   // IPv4 interface addresses
01051 
01052     bool _first_policy_push;            // Don't form peerings until the
01053                     // first policy push is seen.
01054 
01055 #ifdef HAVE_IPV6
01056 
01060     void address_status_change6(const string& interface, const string& vif,
01061                 const IPv6& source, uint32_t prefix_len,
01062                 bool state);
01063     NextHopResolver<IPv6> *_next_hop_resolver_ipv6;
01064     RoutingTableToken<IPv6> _table_ipv6;
01065     AddressStatus6Cb    _address_status6_cb;
01066     map<IPv6, uint32_t> _interfaces_ipv6;   // IPv6 interface addresses
01067 
01068 #endif //ipv6
01069 };
01070 
01071 template <typename A>
01072 bool
01073 BGPMain::get_route_list_start(uint32_t& token,
01074                   const IPNet<A>& prefix,
01075                   const bool& unicast,
01076                   const bool& multicast)
01077 {
01078     if (unicast) {
01079     token = _plumbing_unicast->create_route_table_reader(prefix);
01080     } else if (multicast) {
01081     token = _plumbing_multicast->create_route_table_reader(prefix);
01082     } else {
01083     XLOG_ERROR("Must specify at least one of unicast or multicast");
01084     return false;
01085     }
01086 
01087     token = get_token_table<A>().create(token, prefix, unicast, multicast);
01088 
01089     return true;
01090 }
01091 
01092 template <typename A>
01093 void
01094 BGPMain::extract_attributes(// Input values,
01095                 PAListRef<A> attributes,
01096                 // Output values,
01097                 uint32_t& origin,
01098                 vector<uint8_t>& aspath,
01099                 A& nexthop,
01100                 int32_t& med,
01101                 int32_t& localpref,
01102                 int32_t& atomic_agg,
01103                 vector<uint8_t>& aggregator,
01104                 int32_t& calc_localpref,
01105                 vector<uint8_t>& attr_unknown)
01106 {
01107     FastPathAttributeList<A> fpa_list(attributes);
01108     origin = fpa_list.origin();
01109     fpa_list.aspath().encode_for_mib(aspath);
01110     nexthop = fpa_list.nexthop();
01111 
01112     const MEDAttribute* med_att = fpa_list.med_att();
01113     if (med_att) {
01114     med = (int32_t)med_att->med();
01115     if (med < 0) {
01116         med = 0x7ffffff;
01117         XLOG_WARNING("MED truncated in MIB from %u to %u\n",
01118              XORP_UINT_CAST(med_att->med()),
01119              XORP_UINT_CAST(med));
01120     }
01121     } else {
01122     med = -1;
01123     }
01124 
01125     const LocalPrefAttribute* local_pref_att
01126     = fpa_list.local_pref_att();
01127     if (local_pref_att) {
01128     localpref = (int32_t)local_pref_att->localpref();
01129     if (localpref < 0) {
01130         localpref = 0x7ffffff;
01131         XLOG_WARNING("LOCAL_PREF truncated in MIB from %u to %u\n",
01132              XORP_UINT_CAST(local_pref_att->localpref()),
01133              XORP_UINT_CAST(localpref));
01134     }
01135     } else {
01136     localpref = -1;
01137     }
01138 
01139     if (fpa_list.atomic_aggregate_att())
01140     atomic_agg = 2;
01141     else
01142     atomic_agg = 1;
01143 
01144     const AggregatorAttribute* agg_att
01145     = fpa_list.aggregator_att();
01146     if (agg_att) {
01147     aggregator.resize(6);
01148     agg_att->route_aggregator().copy_out(&aggregator[0]);
01149     agg_att->aggregator_as().copy_out(&aggregator[4]);
01150     } else {
01151     assert(aggregator.size()==0);
01152     }
01153 
01154     calc_localpref = 0;
01155     attr_unknown.resize(0);
01156 }
01157 
01158 template <typename A>
01159 bool
01160 BGPMain::get_route_list_next(
01161                   // Input values,
01162                   const uint32_t& token,
01163                   // Output values,
01164                   IPv4& peer_id,
01165                   IPNet<A>& net,
01166                   uint32_t& origin,
01167                   vector<uint8_t>& aspath,
01168                   A& nexthop,
01169                   int32_t& med,
01170                   int32_t& localpref,
01171                   int32_t& atomic_agg,
01172                   vector<uint8_t>& aggregator,
01173                   int32_t& calc_localpref,
01174                   vector<uint8_t>& attr_unknown,
01175                   bool& best,
01176                   bool& unicast_global,
01177                   bool& multicast_global)
01178 {
01179     IPNet<A> prefix;
01180     bool unicast = false, multicast = false;
01181     uint32_t internal_token, global_token;
01182     internal_token = global_token = token;
01183 
01184     if (!get_token_table<A>().lookup(internal_token, prefix,
01185                      unicast, multicast))
01186     return false;
01187 
01188     const SubnetRoute<A>* route;
01189     if (unicast) {
01190     if (_plumbing_unicast->read_next_route(internal_token, route,
01191                            peer_id)) {
01192         net = route->net();
01193         extract_attributes(route->attributes(),
01194                    origin, aspath, nexthop, med, localpref,
01195                    atomic_agg, aggregator, calc_localpref,
01196                    attr_unknown);
01197         best = route->is_winner();
01198         unicast_global = true;
01199         multicast_global = false;
01200         return true;
01201     }
01202 
01203     // We may have been asked for the unicast and multicast
01204     // routing tables. In which case once we have completed the
01205     // unicast routing table move onto providing the multicast
01206     // table.
01207     get_token_table<A>().erase(global_token);
01208     if (multicast) {
01209         internal_token =
01210         _plumbing_multicast->create_route_table_reader(prefix);
01211         global_token = get_token_table<A>().
01212         create(internal_token, prefix, false, true);
01213     }
01214     }
01215     if (multicast) {
01216     if (_plumbing_multicast->read_next_route(internal_token, route,
01217                          peer_id)) {
01218         net = route->net();
01219         extract_attributes(route->attributes(),
01220                    origin, aspath, nexthop, med, localpref,
01221                    atomic_agg, aggregator, calc_localpref,
01222                    attr_unknown);
01223         best = route->is_winner();
01224         unicast_global = false;
01225         multicast_global = true;
01226         return true;
01227     }
01228     get_token_table<A>().erase(global_token);
01229     }
01230     return false;
01231 }
01232 
01233 // template <typename A>
01234 // struct NameOf {
01235 //     static const char* get() { return "Unknown"; }
01236 // };
01237 // template <> const char* NameOf<IPv4>::get() { return "IPv4"; }
01238 // template <> const char* NameOf<IPv6>::get() { return "IPv6"; }
01239 
01240 #endif // __BGP_MAIN_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations