Source: ../../ospf/debug_io.hh


 
LOGO
 Annotated List  Files  Globals  Hierarchy  Index  Top
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// vim:set sts=4 ts=8:

// Copyright (c) 2001-2006 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.

// $XORP: xorp/ospf/debug_io.hh,v 1.16 2006/03/28 03:06:53 atanu Exp $

#ifndef __OSPF_DEBUG_IO_HH__
#define __OSPF_DEBUG_IO_HH__

/**
 * Debugging implementation of IO for use by test programs.
 */
template <typename A>
class DebugIO : public IO<A> {
 public:
    DebugIO(TestInfo& info, OspfTypes::Version version, EventLoop& eventloop)
	: _info(info), _eventloop(eventloop), _packets(0),
	  _lsa_decoder(version)
    {
	initialise_lsa_decoder(version, _lsa_decoder);
	initialise_packet_decoder(version, _dec, _lsa_decoder);
    }

    /**
     * Pretty print frames. Specific to DebugIO.
     */
    void pp(const string& which, int level, const string& interface, 
	    const string& vif, A dst, A src,
	    uint8_t* data, uint32_t len) {

	TimeVal now;
	_eventloop.current_time(now);
	DOUT_LEVEL(_info, level) << now.pretty_print() << endl;
	DOUT_LEVEL(_info, level) << which << "(" << interface << "," << vif
		    << "," << dst.str() << "," << src.str()
		    <<  "...)" << endl;

	try {
	    // Decode the packet in order to pretty print it.
	    Packet *packet = _dec.decode(data, len);
	    DOUT_LEVEL(_info, level) << packet->str() << endl;
	    delete packet;
	} catch(BadPacket& e) {
	    DOUT_LEVEL(_info, level) << "Probably no decoder provided: " <<
		e.str() <<
		endl;
	}

    }

    bool startup() {
	ServiceBase::set_status(SERVICE_READY);
	return true;
    }
    
    bool shutdown() {
	ServiceBase::set_status(SERVICE_SHUTDOWN);
	return true;
    }

    /**
     * Send Raw frames.
     */
    bool send(const string& interface, const string& vif, 
	      A dst, A src,
	      uint8_t* data, uint32_t len)
    {
	pp("SEND", 0, interface, vif, dst, src, data, len);

	_packets++;
	DOUT(_info) << "packets sent " << _packets << endl;

	if (!_forward_cb.is_empty())
	    _forward_cb->dispatch(interface, vif, dst, src, data, len);
	return true;
    }

    /**
     * Register where frames should be forwarded. Specific to DebugIO.
     */
    bool register_forward(typename IO<A>::ReceiveCallback cb)
    {
	_forward_cb = cb;

	return true;
    }

    /**
     * Receive frames. Specific to DebugIO.
     */
    void receive(const string& interface, const string& vif, 
		 A dst, A src,
		 uint8_t* data, uint32_t len)
    {
	pp("RECEIVE", 1, interface, vif, dst, src, data, len);

	if (! IO<A>::_receive_cb.is_empty())
	    IO<A>::_receive_cb->dispatch(interface, vif, dst, src, data, len);
    }

    /**
     * Enable the interface/vif to receive frames.
     */
    bool enable_interface_vif(const string& interface, const string& vif)
    {
	DOUT(_info) << "enable_interface_vif(" << interface << "," << vif <<
	    "...)" << endl;

	return true;
    }

    /**
     * Disable this interface/vif from receiving frames.
     */
    bool disable_interface_vif(const string& interface, const string& vif)
    {
	DOUT(_info) << "disable_interface_vif(" << interface << "," << vif <<
	    "...)" << endl;

	return true;
    }

    /**
     * Test whether this interface is enabled.
     *
     * @return true if it exists and is enabled, otherwise false.
     */
    bool is_interface_enabled(const string& interface) const
    {
	DOUT(_info) << "enabled(" << interface << ")\n";

	return true;
    }

    /**
     * Test whether this interface/vif is enabled.
     *
     * @return true if it exists and is enabled, otherwise false.
     */
    bool is_vif_enabled(const string& interface, const string& vif) const
    {
	DOUT(_info) << "enabled(" << interface << "," << vif << ")\n";

	return true;
    }

    /**
     * Test whether this interface/vif/address is enabled.
     *
     * @return true if it exists and is enabled, otherwise false.
     */
    bool is_address_enabled(const string& interface, const string& vif,
				    const A& address) const
    {
	DOUT(_info) << "enabled(" << interface << "," << vif << ","
		    << cstring(address) << ")\n";

	return true;
    }

    uint32_t get_prefix_length(const string& interface, const string& vif,
			       A address)
    {
	DOUT(_info) << "get_prefix_length(" << interface << "," << vif << ","
		    << cstring(address) << ")\n";

	return 16;
    }

    uint32_t get_mtu(const string& interface)
    {
	DOUT(_info) << "get_mtu(" << interface << ")\n";

	return 1500;
    }

    /**
     * On the interface/vif join this multicast group.
     */
    bool join_multicast_group(const string& interface, const string& vif,
			      A mcast)
    {
	DOUT(_info) << "join_multicast_group(" << interface << "," << vif <<
	    "," << mcast.str() << ")" << endl;

	return true;
    }

    /**
     * On the interface/vif leave this multicast group.
     */
    bool leave_multicast_group(const string& interface, const string& vif,
			      A mcast)
    {
	DOUT(_info) << "leave_multicast_group(" << interface << "," << vif <<
	    "," << mcast.str() << ")" << endl;

	return true;
    }

    /**
     * Add route to RIB.
     */
    bool add_route(IPNet<A> net, A nexthop, uint32_t metric, bool equal,
		   bool discard, const PolicyTags& policytags)
    {
	DOUT(_info) << "Net: " << net.str() <<
	    " nexthop: " << nexthop.str() <<
	    " metric: " << metric <<
	    " equal: " << pb(equal) <<
	    " discard: " << pb(discard) << 
	    " policy: " << policytags.str() << endl;

	XLOG_ASSERT(0 == _routing_table.count(net));
	DebugRouteEntry dre;
	dre._nexthop = nexthop;
	dre._metric = metric;
	dre._equal = equal;
	dre._discard = discard;
	dre._policytags = policytags;

	_routing_table[net] = dre;

	return true;
    }

    /**
     * Replace route in RIB.
     */
    bool replace_route(IPNet<A> net, A nexthop, uint32_t metric, bool equal,
		       bool discard, const PolicyTags& policytags)
    {
	DOUT(_info) << "Net: " << net.str() <<
	    " nexthop: " << nexthop.str() <<
	    " metric: " << metric <<
	    " equal: " << pb(equal) <<
	    " discard: " << pb(discard) <<
	    " policy: " << policytags.str() << endl;

	if (!delete_route(net))
	    return false;

	return add_route(net, nexthop, metric, equal, discard, policytags);
    }

    /**
     * Delete route from RIB
     */
    bool delete_route(IPNet<A> net)
    {
	DOUT(_info) << "Net: " << net.str() << endl;

	XLOG_ASSERT(1 == _routing_table.count(net));
	_routing_table.erase(_routing_table.find(net));
	
	return true;
    }

    /**
     * A debugging entry point.
     * Empty the routing table.
     */
    void routing_table_empty() {
	_routing_table.clear();
    }

    uint32_t routing_table_size() {
	return _routing_table.size();
    }

    /**
     * Verify that this route is in the routing table.
     */
    bool routing_table_verify(IPNet<A> net, A nexthop, uint32_t metric,
			      bool equal, bool discard) {
	DOUT(_info) << "Net: " << net.str() <<
	    " nexthop: " << nexthop.str() <<
	    " metric: " << metric <<
	    " equal: " << pb(equal) <<
	    " discard: " << pb(discard) << endl;

	if (0 == _routing_table.count(net)) {
	    DOUT(_info) << "Net: " << net.str() << " not in table\n";
	    return false;
	}

	DebugRouteEntry dre = _routing_table[net];
	if (dre._nexthop != nexthop) {
	    DOUT(_info) << "Nexthop mismatch: " << nexthop.str() << " " <<
		dre._nexthop.str() << endl;
	    return false;
	}
	if (dre._metric != metric) {
	    DOUT(_info) << "Metric mismatch: " << metric << " " <<
		dre._metric << endl;
	    return false;
	}
	if (dre._equal != equal) {
	    DOUT(_info) << "Equal mismatch: " << pb(equal) << " " <<
		pb(dre._equal) << endl;
	    return false;
	}
	if (dre._discard != discard) {
	    DOUT(_info) << "Discard mismatch: " << pb(discard) << " " <<
		pb(dre._discard) << endl;
	    return false;
	}

	return true;
    }

    /**
     * Return the number of packets that have seen so far.
     */
    int packets()
    {
	return _packets;
    }
 private:
    TestInfo& _info;
    EventLoop& _eventloop;
    PacketDecoder _dec;
    int _packets;
    LsaDecoder _lsa_decoder;

    typename IO<A>::ReceiveCallback _forward_cb;

    struct DebugRouteEntry {
	A _nexthop;
	uint32_t _metric;
	bool _equal;
	bool _discard;
	PolicyTags _policytags;
    };

    map<IPNet<A>, DebugRouteEntry> _routing_table;
};
#endif // __OSPF_DEBUG_IO_HH__

Generated by: pavlin on possum.icir.org on Wed Aug 2 15:36:38 2006, using kdoc $.