xorp

debug_io.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2009 XORP, Inc.
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License, Version 2, June
00008 // 1991 as published by the Free Software Foundation. Redistribution
00009 // and/or modification of this program under the terms of any other
00010 // version of the GNU General Public License is not permitted.
00011 // 
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00015 // see the GNU General Public License, Version 2, a copy of which can be
00016 // found in the XORP LICENSE.gpl file.
00017 // 
00018 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00019 // http://xorp.net
00020 
00021 // $XORP: xorp/ospf/debug_io.hh,v 1.30 2008/11/14 12:44:19 bms Exp $
00022 
00023 #ifndef __OSPF_DEBUG_IO_HH__
00024 #define __OSPF_DEBUG_IO_HH__
00025 
00029 template <typename A>
00030 class DebugIO : public IO<A> {
00031  public:
00032     DebugIO(TestInfo& info, OspfTypes::Version version, EventLoop& eventloop)
00033     : _info(info), _eventloop(eventloop), _packets(0),
00034       _lsa_decoder(version), _next_interface_id(1)
00035     {
00036     initialise_lsa_decoder(version, _lsa_decoder);
00037     initialise_packet_decoder(version, _dec, _lsa_decoder);
00038     }
00039 
00043     void pp(const string& which, int level, const string& interface, 
00044         const string& vif, A dst, A src,
00045         uint8_t* data, uint32_t len) {
00046 
00047     TimeVal now;
00048     _eventloop.current_time(now);
00049     DOUT_LEVEL(_info, level) << now.pretty_print() << endl;
00050     DOUT_LEVEL(_info, level) << which << "(" << interface << "," << vif
00051             << "," << dst.str() << "," << src.str()
00052             <<  "...)" << endl;
00053 
00054     try {
00055         // Decode the packet in order to pretty print it.
00056         Packet *packet = _dec.decode(data, len);
00057         DOUT_LEVEL(_info, level) << packet->str() << endl;
00058         delete packet;
00059     } catch(InvalidPacket& e) {
00060         DOUT_LEVEL(_info, level) << "Probably no decoder provided: " <<
00061         e.str() <<
00062         endl;
00063     }
00064 
00065     }
00066 
00067     int startup() {
00068     ServiceBase::set_status(SERVICE_READY);
00069     return (XORP_OK);
00070     }
00071     
00072     int shutdown() {
00073     ServiceBase::set_status(SERVICE_SHUTDOWN);
00074     return (XORP_OK);
00075     }
00076 
00080     bool send(const string& interface, const string& vif, 
00081           A dst, A src,
00082           int ttl, uint8_t* data, uint32_t len)
00083     {
00084     pp("SEND", 0, interface, vif, dst, src, data, len);
00085 
00086     _packets++;
00087     DOUT(_info) << "packets sent " << _packets << endl;
00088 
00089     if (!_forward_cb.is_empty())
00090         _forward_cb->dispatch(interface, vif, dst, src, data, len);
00091     return true;
00092     UNUSED(ttl);
00093     }
00094 
00098     bool register_forward(typename IO<A>::ReceiveCallback cb)
00099     {
00100     _forward_cb = cb;
00101 
00102     return true;
00103     }
00104 
00108     void receive(const string& interface, const string& vif, 
00109          A dst, A src,
00110          uint8_t* data, uint32_t len)
00111     {
00112     pp("RECEIVE", 1, interface, vif, dst, src, data, len);
00113 
00114     if (! IO<A>::_receive_cb.is_empty())
00115         IO<A>::_receive_cb->dispatch(interface, vif, dst, src, data, len);
00116     }
00117 
00121     bool enable_interface_vif(const string& interface, const string& vif)
00122     {
00123     DOUT(_info) << "enable_interface_vif(" << interface << "," << vif <<
00124         "...)" << endl;
00125 
00126     return true;
00127     }
00128 
00132     bool disable_interface_vif(const string& interface, const string& vif)
00133     {
00134     DOUT(_info) << "disable_interface_vif(" << interface << "," << vif <<
00135         "...)" << endl;
00136 
00137     return true;
00138     }
00139 
00145     bool is_interface_enabled(const string& interface) const
00146     {
00147     DOUT(_info) << "enabled(" << interface << ")\n";
00148 
00149     return true;
00150     }
00151 
00157     bool is_vif_enabled(const string& interface, const string& vif) const
00158     {
00159     DOUT(_info) << "enabled(" << interface << "," << vif << ")\n";
00160 
00161     return true;
00162     }
00163 
00169     bool is_address_enabled(const string& interface, const string& vif,
00170                     const A& address) const
00171     {
00172     DOUT(_info) << "enabled(" << interface << "," << vif << ","
00173             << cstring(address) << ")\n";
00174 
00175     return true;
00176     }
00177 
00178     bool get_addresses(const string& interface, const string& vif,
00179                list<A>& /*addresses*/) const
00180     {
00181     DOUT(_info) << "get_addresses(" << interface << "," << vif << ","
00182             << ")\n";
00183 
00184     return true;
00185     }
00186 
00187     // It should be safe to return the same address for each interface
00188     // as it is link local.
00189 
00190     bool get_link_local_address(const string& interface, const string& vif,
00191                 IPv4& address) {
00192 
00193     DOUT(_info) << "link_local(" << interface << "," << vif << ")\n";
00194 
00195     // RFC 3330
00196     address = IPv4("169.254.0.1");
00197     
00198     return true;
00199     }
00200 
00201     bool get_link_local_address(const string& interface, const string& vif,
00202                 IPv6& address) {
00203 
00204     DOUT(_info) << "link_local(" << interface << "," << vif << ")\n";
00205     
00206     // XXX
00207     // Nasty hack to generate a different link local address for
00208     // each vif. Assumes that the last character of the vif name
00209     // is a number, solves a problem with test_peering. Should
00210     // really hash the whole interface and vid and use the name
00211     // from the info structure.
00212     string addr = "fe80::";
00213     addr.push_back(vif[vif.size() -1]);
00214     DOUT(_info) << "address = " << addr << ")\n";
00215 
00216     address = IPv6(addr.c_str());
00217 
00218     return true;
00219     }
00220 
00221     bool get_interface_id(const string& interface, uint32_t& interface_id)
00222     {
00223     DOUT(_info) << "get_interface_id(" << interface << ")\n";
00224 
00225     if (0 == _interface_ids.count(interface)) {
00226         interface_id = _next_interface_id++;
00227         _interface_ids[interface] = interface_id;
00228     } else {
00229         interface_id = _interface_ids[interface];
00230     }
00231 
00232     return true;
00233     }
00234 
00235     uint32_t get_prefix_length(const string& interface, const string& vif,
00236                    A address)
00237     {
00238     DOUT(_info) << "get_prefix_length(" << interface << "," << vif << ","
00239             << cstring(address) << ")\n";
00240 
00241     return 16;
00242     }
00243 
00244     uint32_t get_mtu(const string& interface)
00245     {
00246     DOUT(_info) << "get_mtu(" << interface << ")\n";
00247 
00248     return 1500;
00249     }
00250 
00254     bool join_multicast_group(const string& interface, const string& vif,
00255                   A mcast)
00256     {
00257     DOUT(_info) << "join_multicast_group(" << interface << "," << vif <<
00258         "," << mcast.str() << ")" << endl;
00259 
00260     return true;
00261     }
00262 
00266     bool leave_multicast_group(const string& interface, const string& vif,
00267                   A mcast)
00268     {
00269     DOUT(_info) << "leave_multicast_group(" << interface << "," << vif <<
00270         "," << mcast.str() << ")" << endl;
00271 
00272     return true;
00273     }
00274 
00278     bool add_route(IPNet<A> net, A nexthop, uint32_t nexthop_id, 
00279            uint32_t metric, bool equal, bool discard,
00280            const PolicyTags& policytags)
00281     {
00282     DOUT(_info) << "Net: " << net.str() <<
00283         " nexthop: " << nexthop.str() <<
00284         " nexthop_id: " << nexthop_id <<
00285         " metric: " << metric <<
00286         " equal: " << bool_c_str(equal) <<
00287         " discard: " << bool_c_str(discard) << 
00288         " policy: " << policytags.str() << endl;
00289 
00290     XLOG_ASSERT(0 == _routing_table.count(net));
00291     DebugRouteEntry dre;
00292     dre._nexthop = nexthop;
00293     dre._metric = metric;
00294     dre._equal = equal;
00295     dre._discard = discard;
00296     dre._policytags = policytags;
00297 
00298     _routing_table[net] = dre;
00299 
00300     return true;
00301     }
00302 
00306     bool replace_route(IPNet<A> net, A nexthop, uint32_t nexthop_id,
00307                uint32_t metric, bool equal, bool discard,
00308                const PolicyTags& policytags)
00309     {
00310     DOUT(_info) << "Net: " << net.str() <<
00311         " nexthop: " << nexthop.str() <<
00312         " nexthop_id: " << nexthop_id <<
00313         " metric: " << metric <<
00314         " equal: " << bool_c_str(equal) <<
00315         " discard: " << bool_c_str(discard) <<
00316         " policy: " << policytags.str() << endl;
00317 
00318     if (!delete_route(net))
00319         return false;
00320 
00321     return add_route(net, nexthop, nexthop_id, metric, equal, discard,
00322              policytags);
00323     }
00324 
00328     bool delete_route(IPNet<A> net)
00329     {
00330     DOUT(_info) << "Net: " << net.str() << endl;
00331 
00332     XLOG_ASSERT(1 == _routing_table.count(net));
00333     _routing_table.erase(_routing_table.find(net));
00334     
00335     return true;
00336     }
00337 
00342     void routing_table_empty() {
00343     _routing_table.clear();
00344     }
00345 
00346     uint32_t routing_table_size() {
00347     return _routing_table.size();
00348     }
00349 
00353     bool routing_table_verify(IPNet<A> net, A nexthop, uint32_t metric,
00354                   bool equal, bool discard) {
00355     DOUT(_info) << "Net: " << net.str() <<
00356         " nexthop: " << nexthop.str() <<
00357         " metric: " << metric <<
00358         " equal: " << bool_c_str(equal) <<
00359         " discard: " << bool_c_str(discard) << endl;
00360 
00361     if (0 == _routing_table.count(net)) {
00362         DOUT(_info) << "Net: " << net.str() << " not in table\n";
00363         return false;
00364     }
00365 
00366     DebugRouteEntry dre = _routing_table[net];
00367     if (dre._nexthop != nexthop) {
00368         DOUT(_info) << "Nexthop mismatch: " << nexthop.str() << " " <<
00369         dre._nexthop.str() << endl;
00370         return false;
00371     }
00372     if (dre._metric != metric) {
00373         DOUT(_info) << "Metric mismatch: " << metric << " " <<
00374         dre._metric << endl;
00375         return false;
00376     }
00377     if (dre._equal != equal) {
00378         DOUT(_info) << "Equal mismatch: " << bool_c_str(equal) << " " <<
00379         bool_c_str(dre._equal) << endl;
00380         return false;
00381     }
00382     if (dre._discard != discard) {
00383         DOUT(_info) << "Discard mismatch: " << bool_c_str(discard) << " " <<
00384         bool_c_str(dre._discard) << endl;
00385         return false;
00386     }
00387 
00388     return true;
00389     }
00390 
00394     int packets()
00395     {
00396     return _packets;
00397     }
00398  private:
00399     TestInfo& _info;
00400     EventLoop& _eventloop;
00401     PacketDecoder _dec;
00402     int _packets;
00403     LsaDecoder _lsa_decoder;
00404 
00405     typename IO<A>::ReceiveCallback _forward_cb;
00406 
00407     uint32_t _next_interface_id;
00408     map<string, uint32_t> _interface_ids;
00409 
00410     struct DebugRouteEntry {
00411     A _nexthop;
00412     uint32_t _metric;
00413     bool _equal;
00414     bool _discard;
00415     PolicyTags _policytags;
00416     };
00417 
00418     map<IPNet<A>, DebugRouteEntry> _routing_table;
00419 };
00420 #endif // __OSPF_DEBUG_IO_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations