// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// vim:set sts=4 ts=8:
// Copyright (c) 2001-2009 XORP, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, Version 2, June
// 1991 as published by the Free Software Foundation. Redistribution
// and/or modification of this program under the terms of any other
// version of the GNU General Public License is not permitted.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
// see the GNU General Public License, Version 2, a copy of which can be
// found in the XORP LICENSE.gpl file.
//
// XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
// http://xorp.net
// $XORP: xorp/rib/rib.hh,v 1.45 2009/01/05 18:31:07 jtc Exp $
#ifndef __RIB_RIB_HH__
#define __RIB_RIB_HH__
#include <string>
#include "libxorp/xorp.h"
#include "libxorp/ipv4.hh"
#include "libxorp/ipv6.hh"
#include "libxorp/ipnet.hh"
#include "libxorp/nexthop.hh"
#include "libxorp/vif.hh"
#include "route.hh"
#include "rt_tab_base.hh"
#include "rt_tab_origin.hh"
#include "rt_tab_merged.hh"
#include "rt_tab_extint.hh"
#include "rt_tab_redist.hh"
#include "rt_tab_pol_redist.hh"
#include "rt_tab_register.hh"
#include "rt_tab_pol_conn.hh"
#include "policy/backend/policytags.hh"
#include "policy/backend/policy_redist_map.hh"
class RegisterServer;
class RibManager;
class RibVif;
enum RibTransportType {
UNICAST = 1,
MULTICAST = 2
};
enum RibVerifyType {
MISS = 0, // No route to destination
DISCARD = 1, // Discard route for destination
UNREACHABLE = 2, // Unreachable route for destination
IP = 3 // Protocol route to destination
};
/**
* @short Master class for a RIB.
*
* RIB is the master class for a Routing Information Base. It holds
* the RibVif table, routing tables for each protocol, etc. Typically we
* would have one RIB for IPv4 unicast, one for IPv4 multicast
* topology, one for IPv6 unicast and one for IPv6 multicast.
*
* Note that the XRL commands assume some level of filtering has already
* taken place to route to command to the right RIB.
*/
template<class A>
class RIB {
public:
/**
* RIB Constructor.
*
* @param rib_type indicates whether this RIB holds UNICAST or
* MULTICAST routing information. In the case of multicast, this
* is the topology information, not the forwarding information.
* @param rib_manager the main RIB manager process holding stuff
* that's common to all the individual RIBs.
* @param eventloop the main event loop.
*/
RIB(RibTransportType rib_type, RibManager& rib_manager,
EventLoop& eventloop);
/**
* RIB Destructor.
*/
virtual ~RIB();
/**
* Set test-mode: abort on some errors that we'd normally mask.
*/
void set_errors_are_fatal() { _errors_are_fatal = true; }
/**
* Get the list with the registered protocol names.
*
* @return the list with the registered protocol names.
*/
list<string> registered_protocol_names() const;
/**
* Initialize the RIB.
* Note that it is an error to initialize the table twice.
*
* @param register_server the @ref RegisterServer to initialize
* the Rib with.
*/
void initialize(RegisterServer& register_server);
/**
* Initialize the RIB's RedistTable at the end so that the
* winning routes are exported to the RIB clients (e.g., the FEA).
* Note that it is an error to initialize the table twice.
*
* @see RedistTable
* @param all a keyword string which can be used by RIB clients
* to register with the RIB to receive the winning routes from
* the RedistTable.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int initialize_redist_all(const string& all);
/**
* Initialize the RIB's PolicyRedistTable. The PolicyRedistTable enables
* route redistribution according to policy configuration. Based on the
* policy tags of routes passing through this table, a redistribution
* request is sent to the relevant protocols. If routes are being deleted,
* protocols are informed to stop advertising the route.
*
*/
int initialize_policy_redist();
/**
* Initialize the RIB's RegisterTable. The RegisterTable allows
* routing protocols such as BGP to register interest in routing
* information that affects specfic addresses.
* Note that it is an error to initialize the table twice.
*
* @param register_server the @ref RegisterServer to initialize
* the Rib with.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int initialize_register(RegisterServer& register_server);
/**
* Add a new OriginTable. Use is deprecated, except in test suites.
*
* @see OriginTable
* @param tablename human-readable name for this table to help in
* debugging.
* @param target_class the XRL target class of the routing
* protocol that will supply routes to this OriginTable.
* @param target_instance the XRL target instance of the routing
* protocol that will supply routes to this OriginTable.
* @param admin_distance default administrative distance to be
* applied to routes that enter the RIB through this OriginTable.
* @param protocol_type the routing protocol type (@ref ProtocolType).
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int new_origin_table(const string& tablename,
const string& target_class,
const string& target_instance,
uint32_t admin_distance,
ProtocolType protocol_type);
/**
* Inform the RIB about the existence of a Virtual Interface.
* Note that it is an error to add twice a vif with the same vifname.
*
* @see Vif
* @param vifname the name of the VIF, as understood by the FEA.
* @param vif Vif class instance giving the information about this vif.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int new_vif(const string& vifname, const Vif& vif);
/**
* Inform the RIB that a VIF no longer exists.
*
* @param vifname the name of the VIF, as previously indicated by new_vif.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int delete_vif(const string& vifname);
/**
* Destroy a VIF container for a VIF that no longer exists.
*
* @param rib_vif the VIF container that will be destroyed.
*/
virtual void destroy_deleted_vif(RibVif* rib_vif);
/**
* Set the vif flags of a configured vif.
*
* @param vifname the name of the vif.
* @param is_pim_register true if the vif is a PIM Register interface.
* @param is_p2p true if the vif is point-to-point interface.
* @param is_loopback true if the vif is a loopback interface.
* @param is_multicast true if the vif is multicast capable.
* @param is_broadcast true if the vif is broadcast capable.
* @param is_up true if the underlying vif is UP.
* @param mtu the MTU of the vif.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int set_vif_flags(const string& vifname,
bool is_p2p,
bool is_loopback,
bool is_multicast,
bool is_broadcast,
bool is_up,
uint32_t mtu);
/**
* Add an address and subnet to a existing VIF. Each VIF may have
* multiple addresses and associated subnets.
*
* @param vifname the name of the VIF the address will be added to.
* @param addr the address to be added. This must be one of the
* addresses of this router.
* @param subnet the subnet that is connected to this VIF
* corresponding to the address addr.
* @param broadcast the broadcast address to add. In case of IPv6
* this address is ignored.
* @param peer the peer address to add.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int add_vif_address(const string& vifname,
const A& addr,
const IPNet<A>& subnet,
const A& broadcast_addr,
const A& peer_addr);
/**
* Remove an address and the associated subnet from an existing VIF.
* @param vifname the name of the VIF the address will be removed from.
* @param addr the address to be removed. This must be an address
* previously added by add_vif_address.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int delete_vif_address(const string& vifname, const A& addr);
/**
* Add a route to the "connected" OriginTable.
*
* @param vif the vif with the connected route.
* @param net the subnet (address and prefix length) of the route.
* @param nexthop_addr the nexthop address of the route to add.
* @param peer_addr the peer address for the route to add
* (if a point-to-point interface).
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int add_connected_route(const RibVif& vif,
const IPNet<A>& net,
const A& nexthop_addr,
const A& peer_addr);
/**
* Delete a route from the "connected" OriginTable.
*
* @param vif the vif with the connected route.
* @param net the subnet (address and prefix length) of the route.
* @param peer_addr the peer address for the route to delete
* (if a point-to-point interface).
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int delete_connected_route(const RibVif& vif,
const IPNet<A>& net,
const A& peer_addr);
/**
* Add a route via the OriginTable called tablename.
*
* @param tablename the name of the OriginTable into which the
* route should be inserted.
* @param net the subnet (address and prefix length) of the route.
* @param nexthop_addr the nexthop that packets destined for net should be
* forwarded to.
* @param ifname the name of the physical interface toward the
* destination. If an empty string the interface will be chosen by RIB.
* @param vifname the name of the virtual interface toward the
* destination. If an empty string the interface will be chosen by RIB.
* @param metric the routing protocol metric associated with this route.
* @param policytags the policy-tags for this route.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int add_route(const string& tablename,
const IPNet<A>& net,
const A& nexthop_addr,
const string& ifname,
const string& vifname,
uint32_t metric,
const PolicyTags& policytags);
/**
* Replace an existing route via the OriginTable called tablename.
*
* @param tablename the name of the OriginTable in which the
* route should be replaced.
* @param net the subnet (address and prefix length) of the route.
* @param nexthop_addr the new nexthop that packets destined for @ref net
* should be forwarded to.
* @param ifname the name of the physical interface toward the
* destination. If an empty string the interface will be chosen by RIB.
* @param vifname the name of the virtual interface toward the
* destination. If an empty string the interface will be chosen by RIB.
* @param metric the new routing protocol metric associated with this
* @param policytags the policy-tags for this route.
* route.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int replace_route(const string& tablename,
const IPNet<A>& net,
const A& nexthop_addr,
const string& ifname,
const string& vifname,
uint32_t metric,
const PolicyTags& policytags);
/**
* Verify the result of a route lookup in the RIB matches the
* parameters we expect. Intended for testing purposes only.
*
* @param lookupaddr the destination to be verified.
* @param nexthop_addr the expected next hop address.
* @param ifname the expected interface.
* @param metric the expected routing protocol metric.
* @param type the expected type of match.
*
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int verify_route(const A& lookupaddr,
const string& ifname,
const A& nexthop_addr,
uint32_t metric,
RibVerifyType matchtype);
/**
* Delete an existing route via the OriginTable called tablename.
*
* @param tablename the name of the OriginTable in which the
* route should be deleted.
* @param subnet the subnet (address and prefix length) of the
* route to be deleted.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int delete_route(const string& tablename,
const IPNet<A>& subnet);
/**
* Lookup an address in the RIB to determine the nexthop router to
* which packets for this address will be forwarded.
*
* @param lookupaddr the address to be looked up.
* @return pointer to address of next hop for @ref lookupaddr if
* available, otherwise A::ZERO().
*/
virtual const A& lookup_route(const A& lookupaddr);
/**
* Used for debugging only
*/
virtual RouteRange<A>* route_range_lookup(const A& lookupaddr);
/**
* Register interest in being notified about all changes to
* routing information that would affect traffic destined for a
* particular address.
*
* @param lookupaddr the address to register interest in.
* @param module the XRL module name to which notifications of
* changes should be sent.
*/
virtual RouteRegister<A>* route_register(const A& lookupaddr,
const string& module);
/**
* De-register interest in being notified about all changes to
* routing information for a particular address.
*
* @see RIB<A>::route_register
*
* @param lookupaddr the address to de-register interest in.
* @param module the XRL module name to which notifications of
* changes should no longer be sent.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int route_deregister(const IPNet<A>& subnet, const string& module);
/**
* Find a routing protocol, given its protocol name.
*
* @param protocol the name of the protocol to search for.
* @return pointer to protocol if exists, NULL otherwise.
*/
Protocol* find_protocol(const string& protocol);
/**
* Get route redistribution table for specified routing protocol.
*/
RedistTable<A>* protocol_redist_table(const string& protocol);
/**
* Create the OriginTable for an IGP protocol and plumb it into
* the RIB. Typically this will be called when a new instance of
* an IGP routing protocol such as OSPF starts up.
*
* @param tablename the routing protocol name. This should be one
* of the list of names the RIB knows about, or the incorrect
* default administrative distance will be applied.
* @param target_class the XRL target class of the routing
* protocol that will supply routes to this OriginTable.
* @param target_instance the XRL target instance of the routing
* protocol that will supply routes to this OriginTable.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int add_igp_table(const string& tablename,
const string& target_class,
const string& target_instance);
/**
* Delete the OriginTable for an IGP protocol and unplumb it from
* the RIB. Typically this will be called when an instance of
* an IGP routing protocol such as OSPF exits.
*
* @param tablename the routing protocol name, previously
* registered using @ref add_igp_table.
* @param target_class the XRL target class of the routing
* protocol that supplied routes to this OriginTable.
* @param target_instance the XRL target instance of the routing
* protocol that supplied routes to this OriginTable.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int delete_igp_table(const string& tablename,
const string& target_class,
const string& target_instance);
/**
* Create the OriginTable for an EGP protocol and plumb it into
* the RIB. Typically this will be called when a new instance of
* an EGP routing protocol such as EBGP or IBGP starts up. Note
* that EBGP and IBGP should register separately.
*
* @param tablename the routing protocol name. This should be one
* of the list of names the RIB knows about, or the incorrect
* default administrative distance will be applied.
* @param target_class the XRL target class of the routing
* protocol that will supply routes to this OriginTable.
* @param target_instance the XRL target instance of the routing
* protocol that will supply routes to this OriginTable.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int add_egp_table(const string& tablename,
const string& target_class,
const string& target_instance);
/**
* Delete the OriginTable for an EGP protocol and unplumb it from
* the RIB. Typically this will be called when an instance of
* an EGP routing protocol such as BGP exits.
*
* @param tablename the routing protocol name, previously
* registered using @ref add_igp_table.
* @param target_class the XRL target class of the routing
* protocol that supplied routes to this OriginTable.
* @param target_instance the XRL target instance of the routing
* protocol that supplied routes to this OriginTable.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
virtual int delete_egp_table(const string& tablename,
const string& target_class,
const string& target_instance);
/**
* An XRL Target died. We need to check if it's a routing
* protocol, and if it was, clean up after it.
*
* @param target_class the XRL Class of the target that died.
* @param target_instance the XRL Class Instance of the target that died.
*/
void target_death(const string& target_class,
const string& target_instance);
/**
* Print the RIB structure for debugging
*/
void print_rib() const;
/**
* Get RIB name.
*/
string name() const;
/**
* Push routes through policy filters for re-filtering.
*/
void push_routes();
/**
* Set the admin distance associated with a routing protocol.
*
* @param protocol_name the canonical name of a routing protocol,
* in lower case. Eg "ospf", "ibgp", etc.
* @param admin_distance the admin distance to set.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int set_protocol_admin_distance(const string& protocol_name,
const uint32_t& admin_distance);
/**
* Get the map of all registered admin distances.
*
* @return a reference to the _admin_distance map.
*/
map<string, uint32_t>& get_protocol_admin_distances() {
return _admin_distances;
}
/**
* Get the admin distance associated with a routing protocol.
*
* @param protocol_name the canonical name of a routing protocol,
* in lower case. Eg "ospf", "ibgp", etc.
* @return the admin distance; UNKNOWN_ADMIN_DISTANCE if unknown.
*/
uint32_t get_protocol_admin_distance(const string& protocol_name);
private:
/**
* Used to implement @ref add_igp_table and @ref add_egp_table.
*
* @param tablename the routing protocol name.
* @param target_class the XRL target class of the routing
* protocol that will supply routes to this OriginTable.
* @param target_instance the XRL target instance of the routing
* protocol that will supply routes to this OriginTable.
* @param protocol_type the routing protocol type (@ref ProtocolType).
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int add_origin_table(const string& tablename,
const string& target_class,
const string& target_instance,
ProtocolType protocol_type);
/**
* Used to implement @ref delete_igp_table and @ref delete_egp_table.
*
* @param tablename the routing protocol name.
* @param target_class the XRL target class of the routing
* protocol that will supply routes to this OriginTable.
* @param target_instance the XRL target instance of the routing
* protocol that supplied routes to this OriginTable.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int delete_origin_table(const string& tablename,
const string& target_class,
const string& target_instance);
/**
* Add a table for policy filtering of connected routes.
*
* This is used to enable route redistribution of connected routes.
*
* @param origin_tablename The name of the origin table.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int add_policy_connected_table(const string& origin_tablename);
/**
* Add a RedistTable behind OriginTable. This allows routes
* associated with the OriginTable to be redistributed in future.
*
* @param origin_tablename Name of OriginTable.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int add_redist_table(const string& origin_tablename);
/**
* track_back trough the RouteTables' parent pointers to find the
* last (i.e, nearest the OriginTable) table that matches the mask
* in @ref typemask. If the table given by @ref rt doesn't match
* the mask, return it anyway. If a table has more than one
* parent, then this is an error.
*
* @param rt the routing table to start with.
* @param typemask the bitwise-or of the routing table types that
* we may track back through.
* @return the last matching table, or @ref rt if rt itself doesn't match.
*/
RouteTable<A>* track_back(RouteTable<A>* rt, int typemask) const;
/**
* track_forward trough the RouteTables' child pointers to find
* the last able that matches the mask in @ref typemask.
* Unlike track_back, if @ref rt doesn't match, but the next does,
* the track forward anyway.
*
* @param rt the routing table to start with.
* @param typemask the bitwise-or of the routing table types that
* we may track forward through.
* @return the last matching table.
*/
RouteTable<A>* track_forward(RouteTable<A>* rt, int typemask) const;
/**
* Find a routing table, given its table name
*
* @param tablename the name of the table to search for.
* @return pointer to table if exists, NULL otherwise.
*/
RouteTable<A>* find_table(const string& tablename);
/**
* Find a routing table, given its protocol name and XRL target
* instance name.
*
* @param tablename the name of the protocol to search for.
* @param target_class the name of the target class to search for.
* @param target_instance the name of the target instance to search for.
* @return pointer to table if exists, NULL otherwise.
*/
OriginTable<A>* find_table_by_instance(const string& tablename,
const string& target_class,
const string& target_instance);
/**
* Add table to RIB, but don't do any plumbing.
*
* It is an error to add the same table twice or multiple tables
* with the same name.
*
* @param table the table to be added.
*
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int add_table(RouteTable<A>* table);
/**
* Remove table from RIB, but don't do any unplumbing.
* The table is not deleted by this.
*
* @param tablename the name of the table to be removed.
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int remove_table(const string& tablename);
/**
* Find the virtual interface associated with one of this router's
* addresses.
*
* @param addr the IP address to lookup.
* @return pointer to RibVif on success, NULL otherwise.
*/
RibVif* find_vif(const A& addr);
/**
* Find the IP External Nexthop class instance associated with an IP
* address.
*
* @param addr the IP address of the nexthop router.
* @return pointer to external next hop if it exists, NULL otherwise.
*/
IPExternalNextHop<A>* find_external_nexthop(const A& addr);
/**
* Find the IP Peer Nexthop class instance associated with an IP
* address.
*
* @param addr the IP address of the nexthop router.
* @return pointer to peer next hop if it exists, NULL otherwise.
*/
IPPeerNextHop<A>* find_peer_nexthop(const A& addr);
/**
* Find or create the IP External Nexthop class instance
* associated with an IP address.
*
* @param addr the IP address of the nexthop router.
* @return the IPExternalNextHop class instance for @ref addr
*/
IPExternalNextHop<A>* find_or_create_external_nexthop(const A& addr);
/**
* Find or create the IP Peer Nexthop class instance
* associated with an IP address.
*
* @param addr the IP address of the nexthop router.
* @return the IPPeerNextHop class instance for @ref addr.
*/
IPPeerNextHop<A>* find_or_create_peer_nexthop(const A& addr);
/**
* not implemented - force use of default copy constuctor to fail.
*/
RIB(const RIB& );
/**
* not implemented - force use of default assignment operator to fail.
*/
RIB& operator=(const RIB& );
/**
* Flush out routing table changes to other processes.
*/
void flush();
protected:
RibManager& _rib_manager;
EventLoop& _eventloop;
RouteTable<A>* _final_table;
RegisterTable<A>* _register_table;
bool _multicast;
bool _errors_are_fatal;
PolicyRedistTable<A>* _policy_redist_table;
list<RouteTable<A>* > _tables;
map<string, Protocol* > _protocols;
map<string, OriginTable<A>* > _routing_protocol_instances;
map<string, RibVif*> _vifs;
map<string, RibVif*> _deleted_vifs;
map<string, uint32_t> _admin_distances;
map<A, IPExternalNextHop<A> > _external_nexthops;
map<A, IPPeerNextHop<A> > _peer_nexthops;
};
typedef RIB<IPv4> IPv4RIB;
typedef RIB<IPv6> IPv6RIB;
class RibVif : public Vif {
public:
RibVif(RIB<IPv4>* rib, const Vif& vif)
: Vif(vif), _rib4(rib), _rib6(NULL), _usage_counter(0),
_is_deleted(false)
{}
RibVif(RIB<IPv6>* rib, const Vif& vif)
: Vif(vif), _rib4(NULL), _rib6(rib), _usage_counter(0),
_is_deleted(false)
{}
~RibVif() {}
size_t copy_in(const Vif& from_vif) {
Vif* to_vif = this;
*to_vif = from_vif;
return (sizeof(from_vif));
}
void set_deleted(bool v) { _is_deleted = v; }
uint32_t usage_counter() const { return (_usage_counter); }
void incr_usage_counter() { _usage_counter++; }
void decr_usage_counter() {
_usage_counter--;
if (_is_deleted && (_usage_counter == 0)) {
if (_rib4 != NULL) {
_rib4->destroy_deleted_vif(this);
return;
}
if (_rib6 != NULL) {
_rib6->destroy_deleted_vif(this);
return;
}
}
}
private:
//
// XXX: This is a hack that we have two RIB pointers, when one should
// be sufficient. It is to avoid templatization of this class, otherwise
// the generic RouteEntry also needs to become a template.
//
RIB<IPv4>* _rib4;
RIB<IPv6>* _rib6;
uint32_t _usage_counter;
bool _is_deleted;
};
#endif // __RIB_RIB_HH__
Generated by: pavlin on kobe.xorp.net on Wed Jan 7 19:11:09 2009, using kdoc 2.0a54+XORP.