📄 test_outputs.cc
字号:
: 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->_opn.find(n) == this->_opn.end()) { verbose_log("Saw own or alien route with split horizon\n"); // ==> 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() != 0) { verbose_log("Test peer routes seen (%u) does not match expected " "(%u)\n", XORP_UINT_CAST(this->test_peer_routes_seen()), XORP_UINT_CAST(0)); 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->total_routes_seen() == (uint32_t)this->_opn.size(); }};template <typename A>class PoisonReverseValidator : public HorizonValidatorBase<A> {public: PoisonReverseValidator(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() && cost == RIP_INFINITY) { 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(); }};// ----------------------------------------------------------------------------// OutputTester//// This is a bit nasty, the OutputClass is either OutputUpdates or OutputTable// class. These classes have the same methods and so it seems a waste to// write this code out twice. OutputClass is only referenced in one location// so it's not rocket science to comprehend this.//static const IfMgrIfTree ift_dummy = IfMgrIfTree();template <typename A, typename OutputClass>class OutputTester{public: OutputTester(const set<IPNet<A> >& test_peer_nets, const set<IPNet<A> >& other_peer_nets) : _e(), _rip_system(_e), _pm(_rip_system, ift_dummy), _tpn(test_peer_nets), _opn(other_peer_nets) { _pm.test_port()->constants().set_expiry_secs(10); _pm.test_port()->constants().set_deletion_secs(5); _pm.test_port()->set_advertise_default_route(false); _pm.other_port()->constants().set_expiry_secs(10); _pm.other_port()->constants().set_deletion_secs(5); _pm.test_port()->set_io_handler(new BlockedPortIO<A>(*_pm.test_port()), true); _pm.other_port()->set_io_handler( new BlockedPortIO<A>(*_pm.other_port()), true); } ~OutputTester() { RouteDB<A>& rdb = _rip_system.route_db(); rdb.flush_routes(); } int run_test(RipHorizon horizon, HorizonValidatorBase<A>& validator) { string ifname, vifname; // XXX: not set, because not needed _pm.test_port()->set_horizon(horizon); RouteDB<A>& rdb = _rip_system.route_db(); PacketQueue<A> op_out; // Output pkt qu. OutputClass ou(_e, *_pm.test_port(), op_out, rdb); // Output pkt gen ou.start(); verbose_log("Injecting routes from test peer.\n"); for (typename set<IPNet<A> >::const_iterator n = _tpn.begin(); n != _tpn.end(); n++) { RouteEntryOrigin<A>* reo = _pm.test_peer(); if (rdb.update_route(*n, A::ZERO(), ifname, vifname, 5u, 0u, reo, PolicyTags(), false) == false) { verbose_log("Failed to add route for %s\n", n->str().c_str()); return 1; } } verbose_log("Injecting routes from other peer.\n"); for (typename set<IPNet<A> >::const_iterator n = this->_opn.begin(); n != this->_opn.end(); n++) { RouteEntryOrigin<A>* reo = _pm.other_peer(); if (rdb.update_route(*n, A::ZERO(), ifname, vifname, 5u, 0u, reo, PolicyTags(), false) == false) { verbose_log("Failed to add route for %s\n", n->str().c_str()); return 1; } } bool timeout = false; XorpTimer tot = _e.set_flag_after_ms(10000, &timeout); ou.start(); while (ou.running() && timeout == false) { _e.run(); } verbose_log("%u bytes buffered in packet queue.\n", XORP_UINT_CAST(op_out.buffered_bytes())); if (timeout) { verbose_log("Timed out!\n"); return 1; } uint32_t cnt = 0; while (op_out.empty() == false) { if (validator.valid_response(op_out.head()) == false) { verbose_log("Failed on packet validation.\n"); return 1; } op_out.pop_head(); cnt++; } if (validator.valid_in_sum() == false) { verbose_log("Not valid in sum.\n"); return 1; } return 0; }protected: EventLoop _e; System<A> _rip_system; SpoofPortManager<A> _pm; const set<IPNet<A> >& _tpn; const set<IPNet<A> >& _opn;};/** * 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");}// ----------------------------------------------------------------------------// Injected Network statetemplate <typename A>intrun_all_test_cases(){ int rval = 0; static const uint32_t n_routes = 577; // Make one large collection of unique nets set<IPNet<A> > all_nets; make_nets<A>(all_nets, 2 * n_routes); set<IPNet<A> > tpn; // networks associated with peer under test set<IPNet<A> > opn; // networks associated with other peer. // Split large collection into nets for tpn and opn for_each(all_nets.begin(), all_nets.end(), SplitNets<A>(tpn, opn)); // // OutputUpdates class tests // { verbose_log("=== IPv%u No Horizon updates test ===\n", XORP_UINT_CAST(A::ip_version())); OutputTester<A, OutputUpdates<A> > tester(tpn, opn); NoHorizonValidator<A> nohv(tpn, opn); rval |= tester.run_test(NONE, nohv); if (rval) return rval; } { verbose_log("=== IPv%u Split Horizon updates test ===\n", XORP_UINT_CAST(A::ip_version())); OutputTester<A, OutputUpdates<A> > tester(tpn, opn); SplitHorizonValidator<A> shv(tpn, opn); rval |= tester.run_test(SPLIT, shv); if (rval) return rval; } { verbose_log("=== IPv%u Split Horizon Poison Reverse test ===\n", XORP_UINT_CAST(A::ip_version())); OutputTester<A, OutputUpdates<A> > tester(tpn, opn); PoisonReverseValidator<A> prv(tpn, opn); rval |= tester.run_test(SPLIT_POISON_REVERSE, prv); if (rval) return rval; } // // OutputTable class tests // { verbose_log("=== IPv%u No Horizon table test ===\n", XORP_UINT_CAST(A::ip_version())); OutputTester<A, OutputTable<A> > tester(tpn, opn); NoHorizonValidator<A> nohv(tpn, opn); rval |= tester.run_test(NONE, nohv); if (rval) return rval; } { verbose_log("=== IPv%u Split Horizon table test ===\n", XORP_UINT_CAST(A::ip_version())); OutputTester<A, OutputTable<A> > tester(tpn, opn); SplitHorizonValidator<A> shv(tpn, opn); rval |= tester.run_test(SPLIT, shv); if (rval) return rval; } { verbose_log("=== IPv%u Split Horizon Poison Reverse table test ===\n", XORP_UINT_CAST(A::ip_version())); OutputTester<A, OutputTable<A> > tester(tpn, opn); PoisonReverseValidator<A> prv(tpn, opn); rval |= tester.run_test(SPLIT_POISON_REVERSE, prv); } return rval;}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 { rval |= run_all_test_cases<IPv4>(); rval |= run_all_test_cases<IPv6>(); } 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 + -