"Fossies" - the Fresh Open Source Software archive 
Member "xorp/rib/add_route.cc" of archive xorp-1.8.5-src.tar.gz:
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2011 XORP, Inc and Others
//
// 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
// Add routes to the RIB.
// #define DEBUG_LOGGING
// #define DEBUG_PRINT_FUNCTION_NAME
#include "rib_module.h"
#include "libxorp/xorp.h"
#include "libxorp/xlog.h"
#include "libxorp/debug.h"
#include "libxorp/callback.hh"
#include "libxorp/ipv4.hh"
#include "libxorp/timeval.hh"
#include "libxorp/timer.hh"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include "libxipc/xrl_std_router.hh"
#include "xrl/interfaces/rib_xif.hh"
template <typename A>
class Route {
public:
bool add;
IPNet<A> net;
A nexthop;
};
template <typename A>
class Fire {
public:
typedef vector<Route<A> > Routes;
Fire(XrlStdRouter& xrl_router, Routes &r,
string ribname, string tablename, bool max_inflight)
: _xrl_router(xrl_router), _r(r), _ribname(ribname),
_tablename(tablename),
_flying(0),
_max_inflight(max_inflight)
{}
void start() {
_next = _r.begin();
send();
}
bool busy() {
return 0 != _flying;
}
private:
bool send();
void done(const XrlError& error, string comment);
private:
XrlStdRouter &_xrl_router;
Routes &_r;
string _ribname;
string _tablename;
int _flying; // Number of XRLs in flight.
bool _max_inflight; // Try and get the maximum
// number of XRLs in flight.
typename Routes::iterator _next; // Next route to send.
};
template<> bool Fire<IPv4>::send();
void
done(const XrlError& error, const char *comment)
{
debug_msg("callback %s %s\n", comment, error.str().c_str());
if(XrlError::OKAY() != error) {
XLOG_WARNING("callback: %s %s", comment, error.str().c_str());
}
}
int
read_routes(const string& route_file, Fire<IPv4>::Routes& v)
{
//
// Read in the file of routes to send
//
// The file contains:
// Subnet followed by nexthop
std::ifstream routein(route_file.c_str());
if (!routein) {
XLOG_ERROR("Failed to open file: %s %s", route_file.c_str(),
strerror(errno));
return -1;
}
while (routein) {
Route<IPv4> r;
string which;
routein >> which;
if ("add" == which) {
r.add = true;
} else if ("delete" == which) {
r.add = false;
} else if ("#" == which) {
char buf[1024];
routein.getline(buf, sizeof(buf));
continue;
} else if ("" == which) {
break;
} else {
XLOG_ERROR("Allowed command are \"add\" or \"delete\""
" not <%s>", which.c_str());
return -1;
}
string word;
routein >> word;
r.net = IPNet<IPv4>(word.c_str());
routein >> word;
r.nexthop = IPv4(word.c_str());
v.push_back(r);
}
routein.close();
return 0;
}
int
usage(const char *myname)
{
fprintf(stderr, "usage: %s -r routes [-t tablename] [-R][-u][-s][-d]\n",
myname);
return -1;
}
int
main(int argc, char **argv)
{
XorpUnexpectedHandler x(xorp_unexpected_handler);
//
// Initialize and start xlog
//
xlog_init(argv[0], NULL);
xlog_set_verbose(XLOG_VERBOSE_LOW); // Least verbose messages
// XXX: verbosity of the error messages temporary increased
xlog_level_set_verbose(XLOG_LEVEL_ERROR, XLOG_VERBOSE_HIGH);
xlog_add_default_output();
xlog_start();
string route_file;
string ribname = "rib";
string tablename = "ebgp";
bool repeat = false;
bool max_inflight = false;
bool silent = false;
bool dont_add_table = false;
int c;
while ((c = getopt(argc, argv, "r:t:Rusd")) != -1) {
switch (c) {
case 'r':
route_file = optarg;
break;
case 't':
tablename = optarg;
break;
case 'R':
repeat = true;
break;
case 'u':
max_inflight = true;
break;
case 's':
silent = true;
break;
case 'd':
dont_add_table = true;
break;
default:
return usage(argv[0]);
}
}
if (route_file == "")
return usage(argv[0]);
try {
//
// Init stuff
//
EventLoop eventloop;
XrlStdRouter xrl_router(eventloop, "add_route");
debug_msg("Waiting for router");
xrl_router.finalize();
wait_until_xrl_router_is_ready(eventloop, xrl_router);
debug_msg("\n");
// Create table.
if (!dont_add_table) {
XrlRibV0p1Client rib(&xrl_router);
rib.send_add_egp_table4(ribname.c_str(),
tablename,
xrl_router.class_name(),
xrl_router.instance_name(), true, true,
callback(done, "add_table"));
}
Fire<IPv4>::Routes v;
int ret = read_routes(route_file, v);
if (0 != ret)
return ret;
Fire<IPv4> f(xrl_router, v, ribname, tablename, max_inflight);
//
// Main loop
//
do {
TimeVal start, end, delta;
TimerList::system_gettimeofday(&start);
f.start();
while (f.busy()) {
eventloop.run();
}
TimerList::system_gettimeofday(&end);
delta = end - start;
if (!silent)
printf("%s seconds taken to add/delete %u routes\n",
delta.str().c_str(), XORP_UINT_CAST(v.size()));
} while (repeat);
} catch (...) {
xorp_catch_standard_exceptions();
}
//
//
// Gracefully stop and exit xlog
//
xlog_stop();
xlog_exit();
return 0;
}
template<>
bool
Fire<IPv4>::send()
{
if (_next == _r.end())
return false;
XrlRibV0p1Client rib(&_xrl_router);
bool sent;
if (_next->add) {
sent = rib.send_add_route4(_ribname.c_str(),
_tablename,
true /*unicast*/,
false /*multicast*/,
_next->net,
_next->nexthop,
0/*metric*/,
XrlAtomList(),
callback(this,
&Fire::done,
c_format("add net: %s nexthop: %s",
_next->net.str().c_str(),
_next->nexthop.str().
c_str())));
} else {
sent = rib.send_delete_route4(_ribname.c_str(),
_tablename,
true /*unicast*/,
false /*multicast*/,
_next->net,
callback(this,
&Fire::done,
c_format("delete net: %s",
_next->net.str().c_str()
)));
}
if (sent) {
_next++;
_flying++;
}
return sent;
}
template<typename A>
void
Fire<A>::done(const XrlError& error, string comment)
{
_flying--;
debug_msg("callback %s\n %s\n", comment.c_str(), error.str().c_str());
switch (error.error_code()) {
case OKAY:
break;
case REPLY_TIMED_OUT:
case RESOLVE_FAILED:
case SEND_FAILED:
case SEND_FAILED_TRANSIENT:
case NO_SUCH_METHOD:
case NO_FINDER:
case BAD_ARGS:
case COMMAND_FAILED:
case INTERNAL_ERROR:
XLOG_ERROR("callback: %s\n%s",
comment.c_str(), error.str().c_str());
break;
}
if (_max_inflight) {
if (0 == _flying) {
while(send())
;
printf("Flying %d\n", _flying);
}
} else {
send();
}
}