Source: ../../ospf/xrl_io.hh
|
|
|
|
// -*- 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/ospf/xrl_io.hh,v 1.36 2009/01/05 18:31:01 jtc Exp $
#ifndef __OSPF_XRL_IO_HH__
#define __OSPF_XRL_IO_HH__
#include "libxipc/xrl_router.hh"
#include "libfeaclient/ifmgr_xrl_mirror.hh"
#include "policy/backend/policytags.hh"
#include "io.hh"
class EventLoop;
template <typename A> class XrlIO;
/**
* XXX - This should be moved to its own file.
*
* Queue route adds and deletes to the RIB.
*/
template <class A>
class XrlQueue {
public:
XrlQueue(EventLoop& eventloop, XrlRouter& xrl_router);
void set_io(XrlIO<A> *io) {
_io = io;
}
void queue_add_route(string ribname, const IPNet<A>& net,
const A& nexthop, uint32_t nexthop_id,
uint32_t metric, const PolicyTags& policytags);
void queue_delete_route(string ribname, const IPNet<A>& net);
bool busy();
private:
static const size_t WINDOW = 100; // Maximum number of XRLs
// allowed in flight.
XrlIO<A> *_io;
EventLoop& _eventloop;
XrlRouter& _xrl_router;
struct Queued {
bool add;
string ribname;
IPNet<A> net;
A nexthop;
uint32_t nexthop_id;
uint32_t metric;
string comment;
PolicyTags policytags;
};
deque <Queued> _xrl_queue;
size_t _flying; //XRLs currently in flight
/**
* Maximum number in flight
*/
bool maximum_number_inflight() const { return _flying >= WINDOW; }
/**
* Start the transmission of XRLs to tbe RIB.
*/
void start();
/**
* The specialised method called by sendit to deal with IPv4/IPv6.
*
* @param q the queued command.
* @param protocol "ospf"
* @return True if the add/delete was queued.
*/
bool sendit_spec(Queued& q, const char *protocol);
EventLoop& eventloop() const;
void route_command_done(const XrlError& error, const string comment);
};
/**
* Concrete implementation of IO using XRLs.
*/
template <typename A>
class XrlIO : public IO<A>,
public IfMgrHintObserver,
public ServiceChangeObserverBase {
public:
XrlIO(EventLoop& eventloop, XrlRouter& xrl_router, const string& feaname,
const string& ribname)
: _eventloop(eventloop),
_xrl_router(xrl_router),
_feaname(feaname),
_ribname(ribname),
_component_count(0),
_ifmgr(eventloop, feaname.c_str(), _xrl_router.finder_address(),
_xrl_router.finder_port()),
_rib_queue(eventloop, xrl_router)
{
_ifmgr.set_observer(this);
_ifmgr.attach_hint_observer(this);
_rib_queue.set_io(this);
//
// TODO: for now startup inside the constructor. Ideally, we want
// to startup after the FEA birth event.
//
// startup();
}
~XrlIO() {
//
// TODO: for now shutdown inside the destructor. Ideally, we want
// to shutdown gracefully before we call the destructor.
//
// shutdown();
_ifmgr.detach_hint_observer(this);
_ifmgr.unset_observer(this);
}
/**
* Startup operation.
*
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int startup() {
//
// XXX: when the startup is completed,
// IfMgrHintObserver::tree_complete() will be called.
//
if (_ifmgr.startup() != XORP_OK) {
ServiceBase::set_status(SERVICE_FAILED);
return (XORP_ERROR);
}
register_rib();
component_up("startup");
return (XORP_OK);
}
/**
* Shutdown operation.
*
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int shutdown() {
//
// XXX: when the shutdown is completed, XrlIO::status_change()
// will be called.
//
unregister_rib();
component_down("shutdown");
return (_ifmgr.shutdown());
}
/**
* Called when internal subsystem comes up.
*/
void component_up(string /*name*/) {
// fprintf(stderr, "Component: %s count %d\n", name.c_str(),
// _component_count + 1);
_component_count++;
// XXX - Should really get every component to register at
// initialisation time and track the individual
// status. Simpler to uncomment the printfs and track the count.
if (4 == _component_count)
ServiceBase::set_status(SERVICE_RUNNING);
}
/**
* Called when internal subsystem goes down.
*/
void component_down(string /*name*/) {
// fprintf(stderr, "Component: %s count %d\n", name.c_str(),
// _component_count - 1);
_component_count--;
if (0 == _component_count)
ServiceBase::set_status(SERVICE_SHUTDOWN);
else
ServiceBase::set_status(SERVICE_SHUTTING_DOWN);
}
/**
* Receiver Raw frames.
*/
void recv(const string& interface,
const string& vif,
A src,
A dst,
uint8_t ip_protocol,
int32_t ip_ttl,
int32_t ip_tos,
bool ip_router_alert,
bool ip_internet_control,
const vector<uint8_t>& payload);
/**
* Send Raw frames.
*/
bool send(const string& interface, const string& vif,
A dst, A src,
int ttl, uint8_t* data, uint32_t len);
/**
* Enable the interface/vif to receive frames.
*/
bool enable_interface_vif(const string& interface, const string& vif);
/**
* Disable this interface/vif from receiving frames.
*/
bool disable_interface_vif(const string& interface, const string& vif);
/**
* Test whether an interface is enabled.
*
* @param interface the name of the interface to test.
* @return true if it exists and is enabled, otherwise false.
*/
bool is_interface_enabled(const string& interface) const;
/**
* Test whether an interface/vif is enabled.
*
* @param interface the name of the interface to test.
* @param vif the name of the vif to test.
* @return true if it exists and is enabled, otherwise false.
*/
bool is_vif_enabled(const string& interface, const string& vif) const;
/**
* Test whether an interface/vif/address is enabled.
*
* @param interface the name of the interface to test.
* @param vif the name of the vif to test.
* @param address the address to test.
* @return true if it exists and is enabled, otherwise false.
*/
bool is_address_enabled(const string& interface, const string& vif,
const A& address) const;
/**
* Get all addresses associated with this interface/vif.
*
* @param interface the name of the interface
* @param vif the name of the vif
* @param addresses (out argument) list of associated addresses
*
* @return true if there are no errors.
*/
bool get_addresses(const string& interface, const string& vif,
list<A>& addresses) const;
/**
* Get a link local address for this interface/vif if available.
*
* @param interface the name of the interface
* @param vif the name of the vif
* @param address (out argument) set if address is found.
*
* @return true if a link local address is available.
*/
bool get_link_local_address(const string& interface, const string& vif,
A& address);
/**
* Get the interface ID.
*
* @param interface the name of the interface.
* @param interface_id the value if found..
* @return true if the interface ID has been found..
*/
bool get_interface_id(const string& interface, uint32_t& interface_id);
/**
* Obtain the subnet prefix length for an interface/vif/address.
*
* @param interface the name of the interface.
* @param vif the name of the vif.
* @param address the address.
* @return the subnet prefix length for the address.
*/
uint32_t get_prefix_length(const string& interface, const string& vif,
A address);
/**
* Obtain the MTU for an interface.
*
* @param the name of the interface.
* @return the mtu for the interface.
*/
uint32_t get_mtu(const string& interface);
/**
* On the interface/vif join this multicast group.
*/
bool join_multicast_group(const string& interface, const string& vif,
A mcast);
/**
* On the interface/vif leave this multicast group.
*/
bool leave_multicast_group(const string& interface, const string& vif,
A mcast);
/**
* Register with the RIB.
*/
void register_rib();
/**
* Remove registration from the RIB.
*/
void unregister_rib();
void rib_command_done(const XrlError& error, bool up, const char *comment);
/**
* Add route to RIB.
*
* @param net network
* @param nexthop
* @param nexthop_id interface ID towards the nexthop
* @param metric to network
* @param equal true if this in another route to the same destination.
* @param discard true if this is a discard route.
* @param policytags policy info to the RIB.
*/
bool add_route(IPNet<A> net,
A nexthop,
uint32_t nexthop_id,
uint32_t metric,
bool equal,
bool discard,
const PolicyTags& policytags);
/**
* Replace route in RIB.
*
* @param net network
* @param nexthop
* @param nexthop_id interface ID towards the nexthop
* @param metric to network
* @param equal true if this in another route to the same destination.
* @param discard true if this is a discard route.
* @param policytags policy info to the RIB.
*/
bool replace_route(IPNet<A> net,
A nexthop,
uint32_t nexthop_id,
uint32_t metric,
bool equal,
bool discard,
const PolicyTags& policytags);
/**
* Delete route from RIB.
*/
bool delete_route(IPNet<A> net);
private:
/**
* A method invoked when the status of a service changes.
*
* @param service the service whose status has changed.
* @param old_status the old status.
* @param new_status the new status.
*/
void status_change(ServiceBase* service,
ServiceStatus old_status,
ServiceStatus new_status) {
if (old_status == new_status)
return;
if (SERVICE_RUNNING == new_status)
component_up(service->service_name());
if (SERVICE_SHUTDOWN == new_status)
component_down(service->service_name());
}
/**
* Obtain a pointer to the interface manager service base.
*
* @return a pointer to the interface manager service base.
*/
const ServiceBase* ifmgr_mirror_service_base() const {
return dynamic_cast<const ServiceBase*>(&_ifmgr);
}
/**
* Obtain a reference to the interface manager's interface tree.
*
* @return a reference to the interface manager's interface tree.
*/
const IfMgrIfTree& ifmgr_iftree() const { return _ifmgr.iftree(); }
/**
* An IfMgrHintObserver method invoked when the initial interface tree
* information has been received.
*/
void tree_complete();
/**
* An IfMgrHintObserver method invoked whenever the interface tree
* information has been changed.
*/
void updates_made();
//
// XRL callbacks
//
void send_cb(const XrlError& xrl_error, string interface, string vif);
void enable_interface_vif_cb(const XrlError& xrl_error, string interface,
string vif);
void disable_interface_vif_cb(const XrlError& xrl_error, string interface,
string vif);
void join_multicast_group_cb(const XrlError& xrl_error, string interface,
string vif);
void leave_multicast_group_cb(const XrlError& xrl_error, string interface,
string vif);
EventLoop& _eventloop;
XrlRouter& _xrl_router;
string _feaname;
string _ribname;
uint32_t _component_count;
IfMgrXrlMirror _ifmgr;
XrlQueue<A> _rib_queue;
//
// A local copy with the interface state information
//
IfMgrIfTree _iftree;
};
#endif // __OSPF_XRL_IO_HH__
Generated by: pavlin on kobe.xorp.net on Wed Jan 7 19:11:07 2009, using kdoc 2.0a54+XORP.