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

📄 test_outputs.cc

📁 RIP 协议实现
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- 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_outputs.cc,v 1.34 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/ipv6.hh"#include "libxorp/ipnet.hh"#include "auth.hh"#include "output_table.hh"#include "output_updates.hh"#include "port.hh"#include "peer.hh"#include "packet_queue.hh"#include "route_db.hh"#include "system.hh"#include "update_queue.hh"#include "test_utils.hh"#ifdef HAVE_GETOPT_H#include <getopt.h>#endif/////////////////////////////////////////////////////////////////////////////////// This test comprises of a RIP system with 2 ports injecting routes.  One of// the ports has an associated Output class instance that generates packets// containing the routes.  We test both the update packets and the unsolicted// response packets.////			   +---	System ----+//	       		TestPort	OtherPort// 	 Routes ------> TestPeer	OtherPeer <------ Routes//			   |//			   V//		    response packets (inspected)//// We look at the routes in the response packets and compare them against// what we'd expect to see against differing horizon policies.///////////////////////////////////////////////////////////////////////////////////// Generic Constants//static const char *program_name         = "test_output_update";static const char *program_description  = "Test RIP Port processing";static const char *program_version_id   = "0.1";static const char *program_date         = "August, 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";// ----------------------------------------------------------------------------// Type specific helperstemplate <typename A>struct DefaultPeer {    static A get();};template <typename A>struct OtherPeer {    static A get();};template <>IPv4 DefaultPeer<IPv4>::get() { return IPv4("10.0.0.1"); }template <>IPv4 OtherPeer<IPv4>::get() { return IPv4("192.168.0.1"); }template <>IPv6 DefaultPeer<IPv6>::get() { return IPv6("10::1"); }template <>IPv6 OtherPeer<IPv6>::get() { return IPv6("1920:1680::1"); }// ----------------------------------------------------------------------------// 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();	}    }};// ----------------------------------------------------------------------------// BlockedPortIO//// This is a port IO class that reports it's always pending so packets// build up in the packet queue and never leave...template <typename A>class BlockedPortIO : public PortIOBase<A>{public:    typedef A			Addr;    typedef PortIOUserBase<A>	PortIOUser;public:    BlockedPortIO(PortIOUserBase<A>& user)	: PortIOBase<A>(user, "if0", "vif0", A(DefaultPeer<A>::get()))    {    }    /**     * Called by RIP Port instance.     */    bool send(const Addr&,	      uint16_t,	      const vector<uint8_t>&)    {	XLOG_FATAL("Called send inappropriately");	return true;    }    bool pending() const    {	return true;    }private:};// ----------------------------------------------------------------------------// 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()));	this->_ports.push_back(new SpoofPort<A>(*this, OtherPeer<A>::get()));    }    ~SpoofPortManager()    {	while (!this->_ports.empty()) {	    delete this->_ports.front();	    this->_ports.pop_front();	}    }    Port<A>* test_port()    {	return this->_ports.front();    }    const Port<A>* test_port() const    {	return this->_ports.front();    }    Port<A>* other_port()    {	return this->_ports.back();    }    const Port<A>* other_port() const    {	return this->_ports.back();    }    Peer<A>* test_peer()    {	return test_port()->peers().front();    }    const Peer<A>* test_peer() const    {	return test_port()->peers().front();    }    Peer<A>* other_peer()    {	return other_port()->peers().front();    }    const Peer<A>* other_peer() const    {	return other_port()->peers().front();    }};// ----------------------------------------------------------------------------// Response Reader - Really needed for IPv6, but IPv4 is trivialtemplate <typename A>struct ResponseReader {    ResponseReader(const RipPacket<A>* rp) : _rp(rp), _pe(0)    {	RipPacketHeader rph(_rp->header_ptr());	if (rph.command() != RipPacketHeader::RESPONSE) {	    verbose_log("Bad packet!\n");	    _pe = ~0U;	}    }    bool get(IPNet<A>& n, A& nh, uint32_t& cost, uint32_t& tag);    uint32_t packet_entry() const		{ return _pe; }protected:    const RipPacket<A>* _rp;    uint32_t		_pe; 	// Current packet entry    A			_nh6;	// IPv6 only next hop};template <>boolResponseReader<IPv4>::get(IPNet<IPv4>& 	n,			  IPv4& 	nh,			  uint32_t& 	cost,			  uint32_t& 	tag){    const uint8_t* pre_ptr = _rp->route_entry_ptr(_pe);    if (pre_ptr == NULL)	return false;    const PacketRouteEntry<IPv4> pre(pre_ptr);    n 	 = pre.net();    nh 	 = pre.nexthop();    cost = pre.metric();    tag  = pre.tag();    _pe++;    return true;}template <>boolResponseReader<IPv6>::get(IPNet<IPv6>& 	n,			  IPv6& 	nh,			  uint32_t& 	cost,			  uint32_t& 	tag){    for (;;) {	const uint8_t* pre_ptr = _rp->route_entry_ptr(_pe);	if (pre_ptr == NULL)	    return false;	const PacketRouteEntry<IPv6> pre(pre_ptr);	if (pre.is_nexthop()) {	    _nh6 = pre.nexthop();	    _pe++;	    continue;	}	nh   = _nh6;	n    = pre.net();	cost = pre.metric();	tag  = pre.tag();	_pe++;	return true;    }}//-----------------------------------------------------------------------------// Horizon checkerstemplate <typename A>class HorizonValidatorBase{public:    HorizonValidatorBase(const set<IPNet<A> >& tpn, const set<IPNet<A> >& opn)	: _total_routes_seen(0), _test_peer_routes_seen(0),	  _tpn(tpn), _opn(opn)    {}    virtual ~HorizonValidatorBase() {}    /* Check an individual response packet is valid */    virtual bool valid_response(const RipPacket<A>* p) = 0;    /* Final check responses valid */    virtual bool valid_in_sum() const = 0;    uint32_t total_routes_seen() const { return _total_routes_seen; }    uint32_t test_peer_routes_seen() const { return _test_peer_routes_seen; }protected:    uint32_t _total_routes_seen;    uint32_t _test_peer_routes_seen;    const set<IPNet<A> >& _tpn;    const set<IPNet<A> >& _opn;};template <typename A>class NoHorizonValidator : public HorizonValidatorBase<A> {public:    NoHorizonValidator(const set<IPNet<A> >& tpn, const set<IPNet<A> >& opn)	: HorizonValidatorBase<A>(tpn, opn)    {}    bool valid_response(const RipPacket<A>* p)    {	IPNet<A> n;	A	 nh;	uint32_t cost;	uint32_t tag;	ResponseReader<A> rr(p);	while (rr.get(n, nh, cost, tag) == true) {	    this->_total_routes_seen++;	    if (this->_tpn.find(n) != this->_tpn.end()) {		this->_test_peer_routes_seen++;	    } else if (this->_opn.find(n) != this->_opn.end()) {		// No-op	    } else {		// Not a test peer net and not an other peer net		// ==> it's bogus		verbose_log("Failed Processing entry %u / %u %s cost %u\n",			    XORP_UINT_CAST(rr.packet_entry()),			    XORP_UINT_CAST(p->max_entries()),			    n.str().c_str(),			    XORP_UINT_CAST(cost));		return false;	    }	}	return true;    }    bool valid_in_sum() const    {	if (this->test_peer_routes_seen() != this->_tpn.size()) {	    verbose_log("Test routes seen (%u) does not match expected (%u)\n",			XORP_UINT_CAST(this->test_peer_routes_seen()),			XORP_UINT_CAST(this->_tpn.size()));	    return false;	}	verbose_log("total routes seen %u, test peer routes seen = %u\n",		    XORP_UINT_CAST(this->total_routes_seen()),		    XORP_UINT_CAST(this->test_peer_routes_seen()));	return this->test_peer_routes_seen() * 2 == this->total_routes_seen();    }};template <typename A>class SplitHorizonValidator : public HorizonValidatorBase<A> {public:    SplitHorizonValidator(const set<IPNet<A> >& tpn, const set<IPNet<A> >& opn)

⌨️ 快捷键说明

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