Source: ../../ospf/debug_io.hh
|
|
|
|
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// vim:set sts=4 ts=8:
// Copyright (c) 2001-2004 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.15 2005/12/28 18:57:17 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 Thu Mar 9 04:43:44 2006, using kdoc $.