⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test_route_walk.cc

📁 RIP 协议实现
💻 CC
字号:
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-// vim:set sts=4 ts=8:// Copyright (c) 2001-2008 XORP, Inc.//// 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.#ident "$XORP: xorp/rip/test_route_walk.cc,v 1.22 2008/07/23 05:11:37 pavlin Exp $"#include <set>#include "rip_module.h"#include "libxorp/xlog.h"#include "libxorp/c_format.hh"#include "libxorp/eventloop.hh"#include "libxorp/ipv4.hh"#include "libxorp/ipv4net.hh"#include "port.hh"#include "peer.hh"#include "route_db.hh"#include "system.hh"#include "test_utils.hh"#ifdef HAVE_GETOPT_H#include <getopt.h>#endif/////////////////////////////////////////////////////////////////////////////////// Constants//static const char *program_name         = "test_route_walk";static const char *program_description  = "Test RIP route walking";static const char *program_version_id   = "0.1";static const char *program_date         = "July, 2003";static const char *program_copyright    = "See file LICENSE";static const char *program_return_value = "0 on success, 1 if test error, 2 if internal error";// ----------------------------------------------------------------------------// Spoof Port that supports just a single Peer//template <typename A>class SpoofPort : public Port<A> {public:    SpoofPort(PortManagerBase<A>& pm, A addr) : Port<A>(pm)    {	this->_peers.push_back(new Peer<A>(*this, addr));	verbose_log("Constructing SpoofPort instance\n");    }    ~SpoofPort()    {	verbose_log("Destructing SpoofPort instance\n");	while (this->_peers.empty() == false) {	    delete this->_peers.front();	    this->_peers.pop_front();	}    }};// ----------------------------------------------------------------------------// Type specific helperstemplate <typename A>struct DefaultPeer {    static A get();};template <>IPv4 DefaultPeer<IPv4>::get() { return IPv4("10.0.0.1"); }template <>IPv6 DefaultPeer<IPv6>::get() { return IPv6("10::1"); }// ----------------------------------------------------------------------------// Spoof Port Manager instance support a single Spoof Port which in turn// contains a single Peer.//template <typename A>class SpoofPortManager : public PortManagerBase<A> {public:    SpoofPortManager(System<A>& s, const IfMgrIfTree& iftree)	: PortManagerBase<A>(s, iftree)    {	this->_ports.push_back(new SpoofPort<A>(*this, DefaultPeer<A>::get()));    }    ~SpoofPortManager()    {	while (!this->_ports.empty()) {	    delete this->_ports.front();	    this->_ports.pop_front();	}    }    Port<A>* the_port()    {	XLOG_ASSERT(this->_ports.size() == 1);	return this->_ports.front();    }    Peer<A>* the_peer()    {	XLOG_ASSERT(this->_ports.size() == 1);	XLOG_ASSERT(this->_ports.front()->peers().size() == 1);	return this->_ports.front()->peers().front();    }};/////////////////////////////////////////////////////////////////////////////////// Walk tester class//static const IfMgrIfTree ift_dummy = IfMgrIfTree();template <typename A>class RouteWalkTester{public:    RouteWalkTester()	: _e(), _rip_system(_e), _pm(_rip_system, ift_dummy)    {	_pm.the_port()->constants().set_expiry_secs(3);	_pm.the_port()->constants().set_deletion_secs(2);    }    ~RouteWalkTester()    {	RouteDB<A>& rdb = _rip_system.route_db();	rdb.flush_routes();    }    bool    walk_routes(RouteWalker<A>* rw,		bool wait_on_expiring,		uint32_t* done,		uint32_t todo)    {	TimeVal now;	_e.current_time(now);	TimeVal ten_ms(0, 10000);	verbose_log("walked routes = %u\n", XORP_UINT_CAST(*done));	rw->resume();	while (todo != 0) {	    if (rw->current_route() == 0) {		verbose_log("Halting with %u routes done.\n",			    XORP_UINT_CAST(*done));		return false;	    }	    if (wait_on_expiring) {		TimeVal delta = rw->current_route()->timer().expiry() - now;		if (delta < ten_ms) {		    verbose_log("Pausing on route about to be expired "				"or deleted (expiry in %d.%06d secs).\n",				XORP_INT_CAST(delta.sec()),				XORP_INT_CAST(delta.usec()));		    break;		}	    }	    rw->next_route();	    *done = *done + 1;	    todo--;	}	rw->pause(1);	return true;    }    int    run_test()    {	string ifname, vifname;		// XXX: not set, because not needed	const uint32_t n_routes = 20000;	verbose_log("Creating routes for nets\n");	RouteDB<A>& rdb = _rip_system.route_db();	set<IPNet<A> > nets;	make_nets(nets, n_routes);	TimeVal tv_add_start;	_e.current_time(tv_add_start);	for_each(nets.begin(), nets.end(),		 RouteInjector<A>(rdb, A::ZERO(), ifname, vifname, 5,				  _pm.the_peer()));	TimeVal tv_add_end;	_e.current_time(tv_add_end);	tv_add_end -= tv_add_start;	verbose_log("Adding routes took %d.%06d secs\n",		    XORP_INT_CAST(tv_add_end.sec()),		    XORP_INT_CAST(tv_add_end.usec()));	// Walk routes on 1ms timer	// We make 2 passes over routes with 97 routes read per 1ms	// Total time taken 2 * 20000 / 97 * 0.001 = 407ms	uint32_t routes_done = 0;	RouteWalker<A> rw(rdb);	XorpTimer t;	for (int i = 0; i < 2; i++) {	    verbose_log("Starting full route walk %d\n", i);	    t = _e.new_periodic_ms(1,				   callback(this,					    &RouteWalkTester<A>::walk_routes,					    &rw, false,					    &routes_done,					    static_cast<uint32_t>(97u)));	    while (t.scheduled()) {		_e.run();		if (routes_done > n_routes) {		    verbose_log("Walked more routes than exist!\n");		    return 1;		}	    }	    if (routes_done != n_routes) {		verbose_log("Read %u routes, expected to read %u\n",			    XORP_UINT_CAST(routes_done),			    XORP_UINT_CAST(n_routes));		return 1;	    }	    routes_done = 0;	    rw.reset();	}	// Routes start being deleted after 5 seconds so if we walk	// slowly we have a reasonable chance of standing on a route as	// it gets deleted.	//	// Read 10 routes every 30ms.	// 20000 routes -> 20000 / 10 * 0.030 = 60 seconds	//	// Except it doesn't run that long as the routes are collapsing	//	verbose_log("Starting walk as routes are deleted.\n");	rw.reset();	routes_done = 0;	t = _e.new_periodic_ms(30,			       callback(this,					&RouteWalkTester<A>::walk_routes,					&rw, true,					&routes_done,					static_cast<uint32_t>(10u)));	while (t.scheduled()) {	    _e.run();	    if (routes_done > n_routes) {		verbose_log("Walked more routes than exist!\n");		return 1;	    }	}	verbose_log("Read %u routes, %u available at end.\n",		    XORP_UINT_CAST(routes_done),		    XORP_UINT_CAST(rdb.route_count()));	rdb.flush_routes();	if (rdb.route_count() != 0) {	    verbose_log("Had routes left when none expected.\n");	    return 1;	}	return 0;    }protected:    EventLoop		_e;    System<A>		_rip_system;    SpoofPortManager<A> _pm;};/** * Print program info to output stream. * * @param stream the output stream the print the program info to. */static voidprint_program_info(FILE *stream){    fprintf(stream, "Name:          %s\n", program_name);    fprintf(stream, "Description:   %s\n", program_description);    fprintf(stream, "Version:       %s\n", program_version_id);    fprintf(stream, "Date:          %s\n", program_date);    fprintf(stream, "Copyright:     %s\n", program_copyright);    fprintf(stream, "Return:        %s\n", program_return_value);}/* * Print program usage information to the stderr. * * @param progname the name of the program. */static voidusage(const char* progname){    print_program_info(stderr);    fprintf(stderr, "usage: %s [-v] [-h]\n", progname);    fprintf(stderr, "       -h          : usage (this message)\n");    fprintf(stderr, "       -v          : verbose output\n");}intmain(int argc, char* const argv[]){    //    // 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();    int ch;    while ((ch = getopt(argc, argv, "hv")) != -1) {        switch (ch) {        case 'v':            set_verbose(true);            break;        case 'h':        case '?':        default:            usage(argv[0]);            xlog_stop();            xlog_exit();            if (ch == 'h')                return (0);            else                return (1);        }    }    argc -= optind;    argv += optind;    int rval = 0;    XorpUnexpectedHandler x(xorp_unexpected_handler);    try {	{	    RouteWalkTester<IPv4> rwt4;	    rval = rwt4.run_test();	}	{	    RouteWalkTester<IPv6> rwt6;	    rval |= rwt6.run_test();	}    } catch (...) {        // Internal error        xorp_print_standard_exceptions();        rval = 2;    }    //    // Gracefully stop and exit xlog    //    xlog_stop();    xlog_exit();    return rval;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -