Source: ../../bgp/bgp.hh


 
LOGO
 Annotated List  Files  Globals  Hierarchy  Index  Top
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-

// Copyright (c) 2001-2004 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.

// $XORP: xorp/bgp/bgp.hh,v 1.27 2004/06/10 22:40:28 hodson Exp $

#ifndef __BGP_MAIN_HH__
#define __BGP_MAIN_HH__

#include "libxorp/eventloop.hh"
#include "libxorp/status_codes.h"
#include "libxipc/xrl_std_router.hh"

#include "socket.hh"
#include "packet.hh"

#include "peer.hh"
#include "peer_list.hh"
#include "plumbing.hh"
#include "iptuple.hh"
#include "path_attribute.hh"
#include "peer_handler.hh"
#include "process_watch.hh"

class XrlBgpTarget;

class BGPMain {
public:
    BGPMain();
    ~BGPMain();

    /**
     * Get the process status
     */
    ProcessStatus status(string& reason);

    /**
     * Set the local configuration.
     *
     * @param as as number.
     *
     * @param id router id.
     */
    void local_config(const uint32_t& as, const IPv4& id);

    /**
     * attach peer to peerlist
     *
     * @param p BGP peer.
     */
    void attach_peer(BGPPeer *p);

    /**
     * detach peer from the peerlist.
     *
     * @param p BGP peer.
     */
    void detach_peer(BGPPeer *p);

    /**
     * Find peer with this iptuple
     *
     * @param search iptuple.
     *
     * @return A pointer to a peer if one is found NULL otherwise.
     */
    BGPPeer *find_peer(const Iptuple& search);

    /**
     * create a new peer and attach it to the peerlist.
     *
     * @param pd BGP peer data.
     *
     * @return true on success
     */
    bool create_peer(BGPPeerData *pd);

    /**
     * delete peer tear down connection and remove for peerlist.

	XrlBgpTarget xbt(bgp.get_router(), bgp);
     *
     * @param iptuple iptuple.
     *
     * @return true on success
     */
    bool delete_peer(const Iptuple& iptuple);

    /**
     * enable peer
     *
     * @param iptuple iptuple.
     *
     * @return true on success
     */
    bool enable_peer(const Iptuple& iptuple);

    /**
     * disable peer
     *
     * @param iptuple iptuple.
     *
     * @return true on success
     */
    bool disable_peer(const Iptuple& iptuple);

    /**
     * Set peer state.
     *
     * @param iptuple iptuple.
     * @param state should the peering be enable or disabled.
     *
     * @ return true on success.
     */
    bool set_peer_state(const Iptuple& iptuple, bool state);

    /**
     * Activate peer.
     *
     * Enable the peering based on the peer state.
     *
     * @param iptuple iptuple.
     *
     * @ return true on success.
     */
    bool activate(const Iptuple& iptuple);

    /*
     * Set next hop rewrite filter.
     *
     * @param iptuple iptuple.
     * @param next_hop next hop value zero to clear filter.
     *
     * @return true on success
     */
    bool next_hop_rewrite_filter(const Iptuple& iptuple, const IPv4& next_hop);

    bool get_peer_list_start(uint32_t& token);

    bool get_peer_list_next(const uint32_t& token, 
			    IPv4& local_ip, 
			    uint32_t& local_port, 
			    IPv4& peer_ip, 
			    uint32_t& peer_port);

    bool get_peer_id(const Iptuple& iptuple, IPv4& peer_id);
    bool get_peer_status(const Iptuple& iptuple,  uint32_t& peer_state, 
			 uint32_t& admin_status);
    bool get_peer_negotiated_version(const Iptuple& iptuple, 
				     int32_t& neg_version);
    bool get_peer_as(const Iptuple& iptuple,   uint32_t& peer_as);
    bool get_peer_msg_stats(const Iptuple& iptuple, 
			    uint32_t& in_updates, 
			    uint32_t& out_updates, 
			    uint32_t& in_msgs, 
			    uint32_t& out_msgs, 
			    uint16_t& last_error, 
			    uint32_t& in_update_elapsed);
    bool get_peer_established_stats(const Iptuple& iptuple,  
				    uint32_t& transitions, 
				    uint32_t& established_time);
    bool get_peer_timer_config(const Iptuple& iptuple,
			       uint32_t& retry_interval, 
			       uint32_t& hold_time, 
			       uint32_t& keep_alive, 
			       uint32_t& hold_time_configured, 
			       uint32_t& keep_alive_configured, 
			       uint32_t& min_as_origination_interval,
			       uint32_t& min_route_adv_interval);

    bool register_ribname(const string& name);

    void main_loop();

    /**
     * shutdown BGP cleanly
     */
    void terminate() { _exit_loop = true; }
    bool run() {return !_exit_loop;}

    int create_listener(const Iptuple& iptuple);
    LocalData *get_local_data();
    void start_server(const Iptuple& iptuple);
    void stop_server(const Iptuple& iptuple);
    /**
     * Stop listening for incoming connections.
     */
    void stop_all_servers();

    /**
     * Originate an IPv4 route
     *
     * @param nlri subnet to announce
     * @param next_hop to forward to
     * @param unicast if true install in unicast routing table
     * @param multicast if true install in multicast routing table
     *
     * @return true on success
     */
    bool originate_route(const IPv4Net& nlri,
			 const IPv4& next_hop,
			 const bool& unicast,
			 const bool& multicast);

    /**
     * Originate an IPv6 route
     *
     * @param nlri subnet to announce
     * @param next_hop to forward to
     * @param unicast if true install in unicast routing table
     * @param multicast if true install in multicast routing table
     *
     * @return true on success
     */
    bool originate_route(const IPv6Net& nlri,
			 const IPv6& next_hop,
			 const bool& unicast,
			 const bool& multicast);

    /**
     * Withdraw an IPv4 route
     *
     * @param nlri subnet to withdraw
     * @param unicast if true withdraw from unicast routing table
     * @param multicast if true withdraw from multicast routing table
     *
     * @return true on success
     */
    bool withdraw_route(const IPv4Net&	nlri,
			const bool& unicast,
			const bool& multicast) const;

    /**
     * Withdraw an IPv6 route
     *
     * @return true on success
     */
    bool withdraw_route(const IPv6Net&	nlri,
			const bool& unicast,
			const bool& multicast) const;

    template <typename A>
    bool get_route_list_start(uint32_t& token,
			       const bool& unicast,
			       const bool& multicast);

    template <typename A>
    bool get_route_list_next(
			      // Input values, 
			      const uint32_t&	token, 
			      // Output values, 
			      IPv4&  peer_id, 
			      IPNet<A>& net, 
			      uint32_t& origin, 
			      vector<uint8_t>& aspath, 
			      A& nexthop, 
			      int32_t& med, 
			      int32_t& localpref, 
			      int32_t& atomic_agg, 
			      vector<uint8_t>& aggregator, 
			      int32_t& calc_localpref, 
			      vector<uint8_t>& attr_unknown,
			      bool& best,
			      bool& unicast,
			      bool& multicast);

    bool rib_client_route_info_changed4(
					// Input values,
					const IPv4&	addr,
					const uint32_t&	prefix_len,
					const IPv4&	nexthop,
					const uint32_t&	metric);

    bool rib_client_route_info_changed6(
					// Input values,
					const IPv6&	addr,
					const uint32_t&	prefix_len,
					const IPv6&	nexthop,
					const uint32_t&	metric);

    bool rib_client_route_info_invalid4(
					// Input values,
					const IPv4&	addr,
					const uint32_t&	prefix_len);

    bool rib_client_route_info_invalid6(
					// Input values,
					const IPv6&	addr,
					const uint32_t&	prefix_len);

    /**
     * set parameter
     *
     * Typically called via XRL's to set which parameters we support
     * per peer.
     *
     * @param iptuple iptuple
     * @param parameter we are setting for this peer.
     */
    bool set_parameter(
				// Input values,
		       const Iptuple& iptuple,
		       const string& parameter);

    /**
     * Originally inserted for testing. However, now used by all the
     * "rib_client_route_info_*" methods.
     */
    BGPPlumbing *plumbing_unicast() const { return _plumbing_unicast; }
    BGPPlumbing *plumbing_multicast() const { return _plumbing_multicast; }

    XrlStdRouter *get_router() { return _xrl_router; }
    EventLoop& eventloop() { return _eventloop; }
    XrlBgpTarget *get_xrl_target() { return _xrl_target; }

    /**
     * Call via XrlBgpTarget when the finder reports that a process
     * has started.
     * 
     * @param target_class Class of process that has started.
     * @param target_instance Instance name of process that has started.
     */
    void notify_birth(const string& target_class,
		      const string& target_instance) {
	_process_watch->birth(target_class, target_instance);
    }

    /**
     * Call via XrlBgpTarget when the finder reports that a process
     * has terminated.
     * 
     * @param target_class Class of process that has terminated.
     * @param target_instance Instance name of process that has terminated.
     */
    void notify_death(const string& target_class,
		      const string& target_instance) {
	_process_watch->death(target_class, target_instance);
    }

    /**
     * @return Return true when all the processes that BGP is
     * dependent on are ready.
     */
    bool processes_ready() {
	return _process_watch->ready();
    }

    /**
     * @return Return the bgp mib name.
     */
    string bgp_mib_name() const {
	return "bgp4_mib";
    }

    /**
     * Check to see if the bgp snmp entity is running.
     */
    bool do_snmp_trap() const {
	return _process_watch->target_exists(bgp_mib_name());
    }

    /**
     * To be called when the finder dies.
     */
    void finder_death(const char *file, const int lineno) {
	_process_watch->finder_death(file, lineno);
    }
protected:
private:
    /**
     * Store the socket descriptor and iptuple together.
     */
    struct Server {
	Server(int fd, Iptuple iptuple) : _serverfd(fd) {
	    _tuples.push_back(iptuple);
	}
	Server(const Server& rhs) {
	    _serverfd = rhs._serverfd;
	    _tuples = rhs._tuples;
	}
	Server operator=(const Server& rhs) {
	    if (&rhs == this)
		return *this;

	    _serverfd = rhs._serverfd;
	    _tuples = rhs._tuples;

	    return *this;
	}
	int _serverfd;
	list <Iptuple> _tuples;
    };

    list<Server> _serverfds;

    /**
     * Callback method called when a connection attempt is made.
     */
    void connect_attempt(int fd, SelectorMask m,
			 struct in_addr laddr, uint16_t lport);

    template <typename A>
    void extract_attributes(// Input values, 
			    const PathAttributeList<A>& attributes, 
			    // Output values, 
			    uint32_t& origin, 
			    vector<uint8_t>& aspath, 
			    A& nexthop,
			    int32_t& med, 
			    int32_t& localpref, 
			    int32_t& atomic_agg, 
			    vector<uint8_t>& aggregator, 
			    int32_t& calc_localpref, 
			    vector<uint8_t>& attr_unknown);


    bool _exit_loop;
    BGPPeerList *_peerlist;

    /**
    * Unicast Routing Table. SAFI = 1.
    */
    BGPPlumbing *_plumbing_unicast;
    NextHopResolver<IPv4> *_next_hop_resolver_ipv4;

    /**
    * Multicast Routing Table. SAFI = 2.
    */
    BGPPlumbing *_plumbing_multicast;
    NextHopResolver<IPv6> *_next_hop_resolver_ipv6;

    /**
     * Token generator to map between unicast and multicast.
     *
     */
    struct RoutingTableToken {
	RoutingTableToken() : _last(0)
	{}

	uint32_t create(uint32_t& internal_token, const bool& unicast,
			const bool& multicast) {

	    while(_tokens.find(_last) != _tokens.end())
		_last++;
		
	    _tokens[_last] = WhichTable(internal_token, unicast, multicast);

	    return _last;
	}
	
	bool lookup(uint32_t& token, bool& unicast, bool& multicast) {
	    map <uint32_t, WhichTable>::iterator i;

	    i = _tokens.find(token);
	    if (i == _tokens.end())
		return false;

	    WhichTable t = i->second;

	    token = t._token;
	    unicast = t._unicast;
	    multicast = t._multicast;

	    return true;
	}

	void erase(uint32_t& token) {
	    _tokens.erase(token);
	}
    private:
	struct WhichTable {
	    WhichTable() {}
	    WhichTable(uint32_t token, bool unicast, bool multicast)
		: _token(token), _unicast(unicast), _multicast(multicast)
							       {}
	    uint32_t _token;
	    bool _unicast;
	    bool _multicast;
	};

	map <uint32_t, WhichTable> _tokens;
	uint32_t _last;
    };

    template <typename A> RoutingTableToken& get_token_table();

    RoutingTableToken _table_ipv4;
    RoutingTableToken _table_ipv6;

    XrlBgpTarget *_xrl_target;
    RibIpcHandler *_rib_ipc_handler;
    LocalData _local_data;
    XrlStdRouter *_xrl_router;
    static EventLoop _eventloop;
    ProcessWatch *_process_watch;
};

template <typename A>
bool
BGPMain::get_route_list_start(uint32_t& token,
				 const bool& unicast,
				 const bool& multicast)
{
    A dummy;

    if (unicast) {
	token = _plumbing_unicast->create_route_table_reader(dummy);
    } else if (multicast) {
	token = _plumbing_multicast->create_route_table_reader(dummy);
    } else {
	XLOG_ERROR("Must specify at least one of unicast or multicast");
	return false;
    }

    token = get_token_table<A>().create(token, unicast, multicast);

    return true;
}

template <typename A>
void
BGPMain::extract_attributes(// Input values,
			    const PathAttributeList<A>& attributes,
			    // Output values,
			    uint32_t& origin,
			    vector<uint8_t>& aspath,
			    A& nexthop,
			    int32_t& med,
			    int32_t& localpref,
			    int32_t& atomic_agg,
			    vector<uint8_t>& aggregator,
			    int32_t& calc_localpref,
			    vector<uint8_t>& attr_unknown)
{
    origin = attributes.origin();
    attributes.aspath().encode_for_mib(aspath);
    nexthop = attributes.nexthop();

    const MEDAttribute* med_att = attributes.med_att();
    if (med_att) {
	med = (int32_t)med_att->med();
	if (med < 0) {
	    med = 0x7ffffff;
	    XLOG_WARNING("MED truncated in MIB from %u to %u\n",
			 med_att->med(), med);
	}
    } else {
	med = -1;
    }

    const LocalPrefAttribute* local_pref_att
	= attributes.local_pref_att();
    if (local_pref_att) {
	localpref = (int32_t)local_pref_att->localpref();
	if (localpref < 0) {
	    localpref = 0x7ffffff;
	    XLOG_WARNING("LOCAL_PREF truncated in MIB from %u to %u\n",
			 local_pref_att->localpref(), localpref);
	}
    } else {
	localpref = -1;
    }

    if (attributes.atomic_aggregate_att())
	atomic_agg = 2;
    else
	atomic_agg = 1;

    const AggregatorAttribute* agg_att
	= attributes.aggregator_att();
    if (agg_att) {
	aggregator.resize(6);
	agg_att->route_aggregator().copy_out(&aggregator[0]);
	agg_att->aggregator_as().copy_out(&aggregator[4]);
    } else {
	assert(aggregator.size()==0);
    }

    calc_localpref = 0;
    attr_unknown.resize(0);
}

template <typename A>
bool
BGPMain::get_route_list_next(
			      // Input values,
			      const uint32_t& token,
			      // Output values,
			      IPv4& peer_id,
			      IPNet<A>& net,
			      uint32_t& origin,
			      vector<uint8_t>& aspath,
			      A& nexthop,
			      int32_t& med,
			      int32_t& localpref,
			      int32_t& atomic_agg,
			      vector<uint8_t>& aggregator,
			      int32_t& calc_localpref,
			      vector<uint8_t>& attr_unknown,
			      bool& best,
			      bool& unicast_global,
			      bool& multicast_global)
{
    bool unicast, multicast;
    uint32_t internal_token, global_token;
    internal_token = global_token = token;

    A dummy;

    if (!get_token_table<A>().lookup(internal_token, unicast, multicast))
	return false;

    const SubnetRoute<A>* route;
    if (unicast) {
	if (_plumbing_unicast->read_next_route(internal_token, route,
					       peer_id)) {
	    net = route->net();
	    extract_attributes(*route->attributes(),
			       origin, aspath, nexthop, med, localpref,
			       atomic_agg, aggregator, calc_localpref,
			       attr_unknown);
	    best = route->is_winner();
	    unicast_global = true;
	    multicast_global = false;
	    return true;
	}

	// We may have been asked for the unicast and multicast
	// routing tables. In which case once we have completed the
	// unicast routing table move onto providing the multicast
	// table.
	get_token_table<A>().erase(global_token);
	if (multicast) {
	    internal_token =
		_plumbing_multicast->create_route_table_reader(dummy);
	    global_token = get_token_table<A>().
		create(internal_token, false, true);
	}
    }
    if (multicast) {
	if (_plumbing_multicast->read_next_route(internal_token, route,
						 peer_id)) {
	    net = route->net();
	    extract_attributes(*route->attributes(),
			       origin, aspath, nexthop, med, localpref,
			       atomic_agg, aggregator, calc_localpref,
			       attr_unknown);
	    best = route->is_winner();
	    unicast_global = false;
	    multicast_global = true;
	    return true;
	}
	get_token_table<A>().erase(global_token);
    }
    return false;
}

// template <typename A>
// struct NameOf {
//     static const char* get() { return "Unknown"; }
// };
// template <> const char* NameOf<IPv4>::get() { return "IPv4"; }
// template <> const char* NameOf<IPv6>::get() { return "IPv6"; }

#endif // __BGP_MAIN_HH__

Generated by: pavlin on possum.icir.org on Thu Jul 8 23:48:33 2004, using kdoc $.