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

📄 test_update_queue.cc

📁 RIP 协议实现
💻 CC
字号:
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-// 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_update_queue.cc,v 1.24 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 "update_queue.hh"#include "test_utils.hh"#ifdef HAVE_GETOPT_H#include <getopt.h>#endif/////////////////////////////////////////////////////////////////////////////////// Constants//static const char *program_name         = "test_updates";static const char *program_description  = "Test RIP update queue";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();    }};static const IfMgrIfTree ift_dummy = IfMgrIfTree();template <typename A>class UpdateQueueTester{public:    UpdateQueueTester(EventLoop& e)	: _e(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);    }    ~UpdateQueueTester()    {	RouteDB<A>& rdb = _rip_system.route_db();	rdb.flush_routes();	UpdateQueue<A>& uq = rdb.update_queue();	uq.flush();    }    int run_test()    {	string ifname, vifname;		// XXX: not set, because not needed	const uint32_t n_routes = 20000;	verbose_log("Running test for IPv%u\n",		    XORP_UINT_CAST(A::ip_version()));	RouteDB<A>& rdb = _rip_system.route_db();	UpdateQueue<A>& uq = _rip_system.route_db().update_queue();	_fast_reader = uq.create_reader();	_slow_reader = uq.create_reader();	if (uq.updates_queued() != 0) {	    verbose_log("Have updates when none expected\n");	    return 1;	}	verbose_log("Generating nets\n");	set<IPNet<A> > nets;	make_nets(nets, n_routes);	verbose_log("Creating routes for nets\n");	for_each(nets.begin(), nets.end(),		 RouteInjector<A>(rdb, A::ZERO(), ifname, vifname, 5,				  _pm.the_peer()));	if (uq.updates_queued() != n_routes) {	    verbose_log("%u updates queued, expected %u\n",			XORP_UINT_CAST(uq.updates_queued()),			XORP_UINT_CAST(n_routes));	    return 1;	}	uint32_t n = 0;	for (n = 0; n < n_routes; n++) {	    if (uq.get(_fast_reader) == 0) {		verbose_log("Ran out of updates at %u.\n", XORP_UINT_CAST(n));		return 1;	    }	    uq.next(_fast_reader);	}	if (uq.get(_fast_reader) != 0) {	    verbose_log("Got an extra update.\n");	    return 1;	}	bool expire = false;	XorpTimer t = _e.set_flag_after_ms(6000, &expire);	while (t.scheduled()) {	    _e.run();	}	verbose_log("%u updates queued, expected %u\n",		    XORP_UINT_CAST(uq.updates_queued()),		    XORP_UINT_CAST(n_routes));	for (n = 0; n < n_routes; n++) {	    if (uq.get(_fast_reader) == 0) {		verbose_log("Ran out of updates at %u.\n", XORP_UINT_CAST(n));		return 1;	    }	    uq.next(_fast_reader);	}	for (n = 0; n < 2 * n_routes; n++) {	    if (uq.get(_slow_reader) == 0) {		verbose_log("Ran out of updates at %u.\n", XORP_UINT_CAST(n));		return 1;	    }	    uq.next(_slow_reader);	}	if (uq.get(_slow_reader) != 0) {	    verbose_log("Got an extra update.\n");	    return 1;	}	uq.destroy_reader(_fast_reader);	uq.destroy_reader(_slow_reader);	if (uq.updates_queued() != 0) {	    verbose_log("Updates queued (%u) when no readers present\n",			XORP_UINT_CAST(uq.updates_queued()));	    return 1;	}	_slow_reader = uq.create_reader();	_fast_reader = uq.create_reader();	verbose_log("Creating routes for nets (again)\n");	for (typename set<IPNet<A> >::const_iterator n = nets.begin();	     n != nets.end(); ++n) {	    if (rdb.update_route(*n, A::ZERO(), ifname, vifname, 5, 0,				 _pm.the_peer(), PolicyTags(),				 false) == false) {		verbose_log("Failed to add route for %s\n",			    n->str().c_str());		return 1;	    }	}	verbose_log("flushing and waiting for route updates\n");	uq.ffwd(_fast_reader);	uq.flush();	if (uq.updates_queued() != 0) {	    verbose_log("Flushed and route count != 0\n");	    return 1;	}	if (uq.get(_fast_reader) != 0) {	    verbose_log("Got an extra update.\n"); 	    return 1;	}	if (uq.get(_slow_reader) != 0) {	    verbose_log("Got an extra update.\n");	    return 1;	}	expire = false;	t = _e.set_flag_after_ms(6000, &expire);	while (t.scheduled()) {	    _e.run();	}	for (n = 0; n < n_routes; n++) {	    if (uq.get(_slow_reader) == 0) {		verbose_log("Ran out of updates at %u.\n", XORP_UINT_CAST(n));		return 1;	    }	    uq.next(_slow_reader);	    if (uq.get(_fast_reader) == 0) {		verbose_log("Ran out of updates at %u.\n", XORP_UINT_CAST(n));		return 1;	    }	    uq.next(_fast_reader);	}	if (uq.get(_fast_reader) != 0) {	    verbose_log("Got an extra update.\n");	    return 1;	}	if (uq.get(_slow_reader) != 0) {	    verbose_log("Got an extra update.\n");	    return 1;	}		verbose_log("Success\n");	return 0;    }protected:    EventLoop&		_e;    System<A>		_rip_system;    SpoofPortManager<A> _pm;    typename UpdateQueue<A>::ReadIterator _fast_reader;    typename UpdateQueue<A>::ReadIterator _slow_reader;};/** * 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 {	EventLoop e;	UpdateQueueTester<IPv4> uqt4(e);	rval |= uqt4.run_test();	UpdateQueueTester<IPv6> uqt6(e);	rval |= uqt6.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 + -