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

📄 test_trie.cc

📁 xorp源码hg
💻 CC
字号:
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-// Copyright (c) 2001-2007 International Computer Science Institute//// 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/bgp/harness/test_trie.cc,v 1.24 2007/02/16 22:45:26 pavlin Exp $"// #define DEBUG_LOGGING// #define DEBUG_PRINT_FUNCTION_NAME#include "bgp/bgp_module.h"#include "libxorp/xorp.h"#include "libxorp/debug.h"#include "libxorp/xlog.h"#include "libxorp/test_main.hh"#include <map>#include <vector>#include "trie.hh"template <class A>struct ltstr {    bool operator()(IPNet<A> s1, IPNet<A> s2) const {// 	printf("ltstr: %s %s %d\n",// 	       s1.str().c_str(), s2.str().c_str(), s1 < s2);	return s1 < s2;    }};template <class A>class Nmap {public://     typedef map<IPNet<A>, A> nmap;    typedef map<IPNet<A>, A, ltstr<A> > nmap;};typedef vector<const UpdatePacket *> Ulist;/*** Walk the trie and verify that all the networks in the trie are the expected.**** XXX - We should also check that the nexthops are good. They are in** the map after all.*/template <class A>voidtree_walker(const UpdatePacket *p, const IPNet<A>& net, const TimeVal&,	    TestInfo info, typename Nmap<A>::nmap nlri){    DOUT(info) << info.test_name() << endl <<	p->str() <<	"net: " << net.str() << "" << endl;    typename Nmap<A>::nmap::const_iterator i;    for(i = nlri.begin(); i != nlri.end(); i++) {	DOUT(info) << info.test_name() << " " << (*i).first.str() << endl;	if(net == (*i).first)	    return;    }    XLOG_FATAL("Net: %s not found in map", net.str().c_str());}/*** Used to verify that a trie is empty. If this function is called** something is amiss.*/template <class A>voidtree_walker_empty(const UpdatePacket *p, const IPNet<A>& net, const TimeVal&,		  TestInfo info, A dummy_addr){    DOUT(info) << info.test_name() << endl <<	p->str() <<	"net: " << net.str() << "" << endl;    XLOG_FATAL("There should be no entries in this trie\n %s:%s",	       p->str().c_str(), net.str().c_str());    //    // XXX: Dummy address needed to fix template-related deduction problem    // exposed by the Intel C++ compiler.    //    UNUSED(dummy_addr);}template <class A>voidreplay_walker(const UpdatePacket *p, const TimeVal&, TestInfo info,	      size_t *pos, Ulist ulist, A dummy_addr){    DOUT(info) << info.test_name() << " " << (*pos) << endl << p->str();    if(ulist.size() <= *pos)	XLOG_FATAL("vector limit exceeded: %u %u",		   XORP_UINT_CAST(ulist.size()),		   XORP_UINT_CAST(*pos));    if(*p != *ulist[*pos])	XLOG_FATAL("%s NOT EQUAL TO %s", p->str().c_str(),		   ulist[*pos]->str().c_str());    (*pos)++;    //    // XXX: Dummy address needed to fix template-related deduction problem    // exposed by the Intel C++ compiler.    //    UNUSED(dummy_addr);}template <class A> void add_nlri(UpdatePacket *p, IPNet<A> net);template <class A> void withdraw_nlri(UpdatePacket *p, IPNet<A> net);template <class A> void add_nexthop(UpdatePacket *p, A nexthop);template <>voidadd_nlri<IPv4>(UpdatePacket *p, IPNet<IPv4> net){    BGPUpdateAttrib upa(net);    p->add_nlri(upa);}template <>voidwithdraw_nlri<IPv4>(UpdatePacket *p, IPNet<IPv4> net){    BGPUpdateAttrib upa(net);    p->add_withdrawn(upa);}template <>voidadd_nexthop<IPv4>(UpdatePacket *p, IPv4 nexthop){    IPv4NextHopAttribute nha(nexthop);    p->add_pathatt(nha);}template <>voidadd_nlri<IPv6>(UpdatePacket *p, IPNet<IPv6> net){    debug_msg("%s <%s>\n", p->str().c_str(), net.str().c_str());        /*    ** Look for a multiprotocol path attribute, if there is one    ** present just add the net. Otherwise add a multiprotocol path    ** attribute and then add the net. Note: if we add the path    ** attribute we need operate on a pointer hence the goto.    */ top:    MPReachNLRIAttribute<IPv6> *mpreach = 0;    list <PathAttribute*>::const_iterator pai;    for (pai = p->pa_list().begin(); pai != p->pa_list().end(); pai++) {	const PathAttribute* pa;	pa = *pai;		if (dynamic_cast<MPReachNLRIAttribute<IPv6>*>(*pai)) { 	    mpreach = dynamic_cast<MPReachNLRIAttribute<IPv6>*>(*pai);	    mpreach->add_nlri(net);	    mpreach->encode();	    debug_msg("%s\n", p->str().c_str());	    return;	}    }    if(0 == mpreach) {	MPReachNLRIAttribute<IPv6> mp(SAFI_UNICAST);	p->add_pathatt(mp);	goto top;    }}template <>voidwithdraw_nlri<IPv6>(UpdatePacket *p, IPNet<IPv6> net){    debug_msg("%s <%s>\n", p->str().c_str(), net.str().c_str());    /*    ** Look for a multiprotocol path attribute, if there is one    ** present just add the net. Otherwise add a multiprotocol path    ** attribute and then add the net. Note: if we add the path    ** attribute we need operate on a pointer hence the goto.    */ top:    MPUNReachNLRIAttribute<IPv6> *mpunreach = 0;    list <PathAttribute*>::const_iterator pai;    for (pai = p->pa_list().begin(); pai != p->pa_list().end(); pai++) {	const PathAttribute* pa;	pa = *pai;		if (dynamic_cast<MPUNReachNLRIAttribute<IPv6>*>(*pai)) { 	    mpunreach = dynamic_cast<MPUNReachNLRIAttribute<IPv6>*>(*pai);	    mpunreach->add_withdrawn(net);	    mpunreach->encode();	    debug_msg("%s\n", p->str().c_str());	    return;	}    }    if(0 == mpunreach) {	MPUNReachNLRIAttribute<IPv6> mp(SAFI_UNICAST);	p->add_pathatt(mp);	goto top;    }}template <>voidadd_nexthop<IPv6>(UpdatePacket *p, IPv6 nexthop){    /*    ** Look for a multiprotocol path attribute, if there is one    ** present just add the net. Otherwise add a multiprotocol path    ** attribute and then add the nexthop. Note: if we add the path    ** attribute we need operate on a pointer hence the goto.    */ top:    MPReachNLRIAttribute<IPv6> *mpreach = 0;    list <PathAttribute*>::const_iterator pai;    for (pai = p->pa_list().begin(); pai != p->pa_list().end(); pai++) {	const PathAttribute* pa;	pa = *pai;		if (dynamic_cast<MPReachNLRIAttribute<IPv6>*>(*pai)) { 	    mpreach = dynamic_cast<MPReachNLRIAttribute<IPv6>*>(*pai);	    mpreach->set_nexthop(nexthop);	    mpreach->encode();	    debug_msg("%s\n", p->str().c_str());	    return;	}    }    if(0 == mpreach) {	MPReachNLRIAttribute<IPv6> mp(SAFI_UNICAST);	p->add_pathatt(mp);	goto top;    }}template <class A>booltest_single_update(TestInfo& info, A nexthop, IPNet<A> net){    DOUT(info) << info.test_name() << endl;    Trie trie;    /*    ** Verify that the trie is empty.    */    trie.tree_walk_table(callback(tree_walker_empty<A>, info, A::ZERO()));    /*    ** The trie should be empty make sure that a lookup fails.    */    const UpdatePacket *p = trie.lookup(net.str());    if(0 != p) {	DOUT(info) << "lookup suceeded in empty trie!!!\n" << p->str() << endl;	return false;    }    /*    ** Create an update packet with a single NLRI.    */    UpdatePacket *bgpupdate;    bgpupdate = new UpdatePacket();    add_nlri<A>(bgpupdate, net);    /*    ** Add an origin, aspath and next hop to keep it legal.    */    OriginAttribute oa(IGP);    bgpupdate->add_pathatt(oa);    ASPathAttribute aspa(AsPath("1,2,3"));    bgpupdate->add_pathatt(aspa);    add_nexthop<A>(bgpupdate, nexthop);    /*    ** Pass to the trie.    */    TimeVal tv;    size_t len;    const uint8_t *data = bgpupdate->encode(len);    trie.process_update_packet(tv, data, len);    /*    ** Verify that this net is in the trie.    */    p = trie.lookup(net.str());    if(0 == p) {	DOUT(info) << "lookup of " << net.str() << " failed\n";	return false;    }    if(*bgpupdate != *p) {	DOUT(info) << endl << bgpupdate->str() << 	    "NOT EQUAL TO\n" << p->str() << endl;	return false;    }    /*    ** Walk the trie and check that the net is there.    */    typename Nmap<A>::nmap nlri;    nlri[net] = nexthop;    trie.tree_walk_table(callback(tree_walker<A>, info, nlri));    /*    ** Generate a withdraw to remove the entry from the trie.    */    delete [] data;    delete bgpupdate;    bgpupdate = new UpdatePacket();    withdraw_nlri<A>(bgpupdate, net);    data = bgpupdate->encode(len);    trie.process_update_packet(tv, data, len);    /*    ** Check that the net has been removed from the trie.    */    p = trie.lookup(net.str());    if(0 != p) {	DOUT(info) << "lookup suceeded in empty trie!!!\n" << p->str() << endl;	return false;    }    delete [] data;    delete bgpupdate;	// Free up the packet.        /*    ** Verify that the trie is empty.    */    trie.tree_walk_table(callback(tree_walker_empty<A>, info, A::ZERO()));    return true;}template <class A>booltest_replay(TestInfo& info, A nexthop, IPNet<A> net){    DOUT(info) << info.test_name() << endl;    Trie trie;    /*    ** Verify that the trie is empty.    */    trie.tree_walk_table(callback(tree_walker_empty<A>, info, A::ZERO()));    /*    ** The trie should be empty make sure that a lookup fails.    */    const UpdatePacket *p = trie.lookup(net.str());    if(0 != p) {	DOUT(info) << "lookup suceeded in empty trie!!!\n" << p->str() << endl;	return false;    }    UpdatePacket *packet_nlri, *packet_w1, *packet_w2;    const uint8_t *data_nlri, *data_w1, *data_w2;    size_t len_nlri, len_w1, len_w2;    /*    ** Create an update packet with two NLRIs.    */    packet_nlri = new UpdatePacket();    add_nlri<A>(packet_nlri, net);    IPNet<A> net2 = ++net;--net;    add_nlri<A>(packet_nlri, net2);    /*    ** Add an origin, aspath and next hop to keep it legal.    */    OriginAttribute oa(IGP);    packet_nlri->add_pathatt(oa);    ASPathAttribute aspa(AsPath("1,2,3"));    packet_nlri->add_pathatt(aspa);    add_nexthop<A>(packet_nlri, nexthop);    /*    ** Pass to the trie.    */    TimeVal tv;    data_nlri = packet_nlri->encode(len_nlri);    trie.process_update_packet(tv, data_nlri, len_nlri);    /*    ** Verify that net is in the trie.    */    p = trie.lookup(net.str());    if(0 == p) {	DOUT(info) << "lookup of " << net.str() << " failed\n";	return false;    }    if(*packet_nlri != *p) {	DOUT(info) << endl << packet_nlri->str() << 	    "NOT EQUAL TO\n" << p->str() << endl;	return false;    }    /*    ** Verify that net2 is in the trie.    */    p = trie.lookup(net2.str());    if(0 == p) {	DOUT(info) << "lookup of " << net2.str() << " failed\n";	return false;    }    if(*packet_nlri != *p) {	DOUT(info) << endl << packet_nlri->str() << 	    "NOT EQUAL TO\n" << p->str() << endl;	return false;    }    /*    ** Walk the trie and check that both nets are there.    */    typename Nmap<A>::nmap nlri;    nlri[net] = nexthop;    nlri[net2] = nexthop;    trie.tree_walk_table(callback(tree_walker<A>, info, nlri));    /*    ** Generate a withdraw to remove one entry from the trie.    */    packet_w1 = new UpdatePacket();    withdraw_nlri<A>(packet_w1, net);    data_w1 = packet_w1->encode(len_w1);    trie.process_update_packet(tv, data_w1, len_w1);    /*    ** Check that net is no longer in the trie.    */    p = trie.lookup(net.str());    if(0 != p) {	DOUT(info) << "lookup suceeded in empty trie!!!\n" << p->str() << endl;	return false;    }    /*    ** Now check the replay code.    */    size_t pos = 0;    Ulist ulist;    ulist.push_back(packet_nlri);    ulist.push_back(packet_w1);    DOUT(info) << "0\t" << ulist[0]->str() << endl;    DOUT(info) << "1\t" << ulist[1]->str() << endl;    trie.replay_walk(callback(replay_walker<A>, info, &pos, ulist, A::ZERO()));    /*    ** Build another withdraw to remove the net2. This should empty    ** the trie.    */    packet_w2 = new UpdatePacket();    withdraw_nlri<A>(packet_w2, net2);    data_w2 = packet_w2->encode(len_w2);    trie.process_update_packet(tv, data_w2, len_w2);    /*     ** The replay list should be empty.    */    pos = 0;    ulist.clear();    trie.replay_walk(callback(replay_walker<A>, info, &pos, ulist, A::ZERO()));    /*    ** Push the update packet with the two nlris back in.    */    trie.process_update_packet(tv, data_nlri, len_nlri);    /*    ** Check the replay code. It should now only contain the most    ** recent  update.    */    pos = 0;    ulist.clear();    ulist.push_back(packet_nlri);    DOUT(info) << "0\t" << ulist[0]->str() << endl;    trie.replay_walk(callback(replay_walker<A>, info, &pos, ulist, A::ZERO()));    /*    ** Empty out the trie.    */    trie.process_update_packet(tv, data_w1, len_w1);    trie.process_update_packet(tv, data_w2, len_w2);    /*    ** The replay list should be empty.    */    pos = 0;    ulist.clear();    trie.replay_walk(callback(replay_walker<A>, info, &pos, ulist, A::ZERO()));    /*    ** Verify that the trie is empty.    */    trie.tree_walk_table(callback(tree_walker_empty<A>, info, A::ZERO()));    delete [] data_nlri;    delete packet_nlri;    delete [] data_w1;    delete packet_w1;    delete [] data_w2;    delete packet_w2;    return true;}intmain(int argc, char** argv){    XorpUnexpectedHandler x(xorp_unexpected_handler);    xlog_init(argv[0], NULL);    xlog_set_verbose(XLOG_VERBOSE_HIGH);    xlog_add_default_output();    xlog_start();    TestMain t(argc, argv);    string test_name =	t.get_optional_args("-t", "--test", "run only the specified test");    t.complete_args_parsing();         IPNet<IPv4> net1_ipv4("10.10.0.0/16");    IPv4 nexthop1_ipv4("20.20.20.20");    IPNet<IPv6> net1_ipv6("2000::/3");    IPv6 nexthop1_ipv6("20:20:20:20:20:20:20:20");    try {	uint8_t edata[2];	edata[0]=1;	edata[1]=2;	struct test {	    string test_name;	    XorpCallback1<bool, TestInfo&>::RefPtr cb;	} tests[] = {	    {"single_ipv4", callback(test_single_update<IPv4>,				     nexthop1_ipv4, net1_ipv4)},  	    {"single_ipv6", callback(test_single_update<IPv6>,				     nexthop1_ipv6, net1_ipv6)},	    {"replay_ipv4", callback(test_replay<IPv4>,				     nexthop1_ipv4, net1_ipv4)},	    {"replay_ipv6", callback(test_replay<IPv6>,				     nexthop1_ipv6, net1_ipv6)},	};	if("" == test_name) {	    for(unsigned int i = 0; i < sizeof(tests) / sizeof(struct test); 		i++)		t.run(tests[i].test_name, tests[i].cb);	} else {	    for(unsigned int i = 0; i < sizeof(tests) / sizeof(struct test); 		i++)		if(test_name == tests[i].test_name) {		    t.run(tests[i].test_name, tests[i].cb);		    return t.exit();		}	    t.failed("No test with name " + test_name + " found\n");	}    } catch(...) {	xorp_catch_standard_exceptions();    }    xlog_stop();    xlog_exit();    return t.exit();}

⌨️ 快捷键说明

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