📄 peer.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/peer.cc,v 1.80 2007/02/16 22:45:25 pavlin Exp $"// #define DEBUG_LOGGING// #define DEBUG_PRINT_FUNCTION_NAME#include "bgp/bgp_module.h"#include "libxorp/debug.h"#include "libxorp/xlog.h"#include "libxorp/eventloop.hh"#include "libxorp/ipv4net.hh"#include "libxorp/utils.hh"#include "libproto/packet.hh"#include "libxipc/xrl_std_router.hh"#include "xrl/interfaces/test_peer_xif.hh"#include "bgp/local_data.hh"#include "bgp/packet.hh"#include "peer.hh"#include "bgppp.hh"Peer::~Peer(){ debug_msg("XXX Deleting peer %p\n", this);}Peer::Peer(EventLoop *eventloop, XrlStdRouter *xrlrouter, const string& peername, const uint32_t genid, const string& target_hostname, const string& target_port) : _eventloop(eventloop), _xrlrouter(xrlrouter), _peername(peername), _genid(genid), _target_hostname(target_hostname), _target_port(target_port), _up(true), _busy(0), _connected(false), _session(false), _passive(false), _established(false), _keepalive(false), _as(AsNum::AS_INVALID), // XXX _holdtime(0), _ipv6(false){ debug_msg("XXX Creating peer %p\n", this);}Peer::Peer(const Peer& rhs) : _as(AsNum::AS_INVALID) // XXX{ debug_msg("Copy constructor\n"); copy(rhs);}Peer::Peer&Peer::operator=(const Peer& rhs){ debug_msg("= operator\n"); if(&rhs == this) return *this; copy(rhs); return *this;}voidPeer::copy(const Peer& rhs){ debug_msg("peername: %s\n", rhs._peername.c_str()); _eventloop = rhs._eventloop; _xrlrouter = rhs._xrlrouter; _peername = rhs._peername; _genid = rhs._genid; _target_hostname = rhs._target_hostname; _target_port = rhs._target_port; _up = rhs._up; _busy = rhs._busy; _session = rhs._session; _passive = rhs._passive; _keepalive = rhs._keepalive; _established = rhs._established; _as = rhs._as; _holdtime = rhs._holdtime; _ipv6 = rhs._ipv6; _id = rhs._id;}Peer::PeerStatePeer::is_this_you(const string& peer_name) const{ debug_msg("is this you: %s %s\n", _peername.c_str(), peer_name.c_str()); if(_up && peer_name == _peername) { debug_msg("Its me\n"); return Peer::YES_ITS_ME; } /* ** If this peer has been down for ten minutes its a candidate to ** be deleted. There should be no more activity on this peer. */ if(!_up) { TimeVal now; _eventloop->current_time(now); if(now - _shutdown_time > TimeVal(60 * 10, 0)) return Peer::PLEASE_DELETE_ME; } return Peer::NO_ITS_NOT_ME;}Peer::PeerStatePeer::is_this_you(const string& peer_name, const uint32_t genid) const{ debug_msg("is this you: %s %s %u\n", _peername.c_str(), peer_name.c_str(), XORP_UINT_CAST(genid)); if(_up && peer_name == _peername && genid == _genid) return Peer::YES_ITS_ME; if(!_up) return is_this_you(""); return Peer::NO_ITS_NOT_ME;}voidPeer::shutdown(){ XLOG_ASSERT(_up); // We should only ever be shutdown once. _up = false; _eventloop->current_time(_shutdown_time); /* ** The corresponding test peer may have a tcp connection with a ** bgp process. Attempt a disconnect. */ _busy++; XrlTestPeerV0p1Client test_peer(_xrlrouter); if(!test_peer.send_reset(_peername.c_str(), callback(this, &Peer::xrl_callback, "reset"))) XLOG_FATAL("reset failed");}boolPeer::up() const{ return _up;}voidPeer::status(string& status){ status = _peername + " "; status += _established ? "established" : ""; status += " "; status += "sent: " + c_format("%u", XORP_UINT_CAST(_trie_sent.update_count())) + " "; status += "received: " + c_format("%u", XORP_UINT_CAST(_trie_recv.update_count())) + " ";}boolPeer::pending(){ debug_msg("pending? : %s\n", (_session && !_established && !_passive) ? "true" : "false");// if(_xrlrouter->pending())// return true; if(_busy > 0) return true;// printf("%s: session: %d established: %d passive %d\n", // _peername.c_str(), _session, _established, _passive); if(_session && !_established && !_passive) return true; return false;}void Peer::listen(const string& /*line*/, const vector<string>& /*words*/) throw(InvalidString){ /* Connect the test peer to the target BGP */ debug_msg("About to listen on: %s\n", _peername.c_str()); _busy += 3; XrlTestPeerV0p1Client test_peer(_xrlrouter); if(!test_peer.send_register(_peername.c_str(), _xrlrouter->name(), _genid, callback(this, &Peer::xrl_callback, "register"))) XLOG_FATAL("send_register failed"); if(!test_peer.send_packetisation(_peername.c_str(), "bgp", callback(this, &Peer::xrl_callback, "packetisation"))) XLOG_FATAL("send_packetisation"); if(!test_peer.send_listen(_peername.c_str(), _target_hostname, atoi(_target_port.c_str()), callback(this, &Peer::xrl_callback, "listen"))) XLOG_FATAL("send_listen failed");}void Peer::connect(const string& /*line*/, const vector<string>& /*words*/) throw(InvalidString){ /* Connect the test peer to the target BGP */ debug_msg("About to connect to: %s\n", _peername.c_str()); _busy += 3; XrlTestPeerV0p1Client test_peer(_xrlrouter); if(!test_peer.send_register(_peername.c_str(), _xrlrouter->name(), _genid, callback(this, &Peer::xrl_callback, "register"))) XLOG_FATAL("send_register failed"); if(!test_peer.send_packetisation(_peername.c_str(), "bgp", callback(this, &Peer::xrl_callback, "packetisation"))) XLOG_FATAL("send_packetisation failed"); if(!test_peer.send_connect(_peername.c_str(), _target_hostname, atoi(_target_port.c_str()), callback(this, &Peer::xrl_callback_connected, "connected"))) XLOG_FATAL("send_connect failed");}void Peer::disconnect(const string& /*line*/, const vector<string>& /*words*/) throw(InvalidString){ /* Disconnect the test peer from the target BGP */ debug_msg("About to disconnect from: %s\n", _peername.c_str()); _busy++; XrlTestPeerV0p1Client test_peer(_xrlrouter); _session = false; _established = false; if(!test_peer.send_disconnect(_peername.c_str(), callback(this, &Peer::xrl_callback, "disconnect"))) XLOG_FATAL("send_disconnect failed");}/*** Form of command:** peer1 establish active <true/false> AS <asnum>***/voidPeer::establish(const string& line, const vector<string>& words) throw(InvalidString){ debug_msg("About to establish a connection %s\n", _peername.c_str()); bool active = true; _session = true; /* ** Parse the command line. ** The arguments for this command come in pairs: ** name value */ uint16_t as = 0; size_t size = words.size(); if(0 != (size % 2)) xorp_throw(InvalidString, c_format("Incorrect number of arguments:\n[%s]", line.c_str())); for(size_t i = 2; i < words.size(); i += 2) { debug_msg("name: %s value: %s\n", words[i].c_str(), words[i + 1].c_str()); if("active" == words[i]) { string aarg = words[i+1]; if("true" == aarg) active = true; else if("false" == aarg) active = false; else xorp_throw(InvalidString, c_format("Illegal argument to active: <%s>\n[%s]", aarg.c_str(), line.c_str())); } else if("AS" == words[i]) { as = atoi(words[i + 1].c_str()); } else if("keepalive" == words[i]) { string kaarg = words[i+1]; if("true" == kaarg) _keepalive = true; else if("false" == kaarg) _keepalive = false; else xorp_throw(InvalidString, c_format("Illegal argument to keepalive: <%s>\n[%s]", kaarg.c_str(), line.c_str())); } else if("holdtime" == words[i]) { _holdtime = atoi(words[i + 1].c_str()); } else if("id" == words[i]) { _id = IPv4(words[i + 1].c_str()); } else if("ipv6" == words[i]) { string ipv6arg = words[i+1]; if("true" == ipv6arg) _ipv6 = true; else if("false" == ipv6arg) _ipv6 = false; else xorp_throw(InvalidString, c_format("Illegal argument to ipv6: <%s>\n[%s]", ipv6arg.c_str(), line.c_str())); } else xorp_throw(InvalidString, c_format("Illegal argument to establish: <%s>\n[%s]", words[i].c_str(), line.c_str())); } if(0 == as) xorp_throw(InvalidString, c_format("No AS number specified:\n[%s]", line.c_str())); _as = AsNum(static_cast<uint16_t>(as)); if(!active) { _passive = true; listen(line, words); return; } connect(line, words); send_open();}voidPeer::send(const string& line, const vector<string>& words) throw(InvalidString){ size_t size = words.size(); if(size < 3) xorp_throw(InvalidString, c_format("Insufficient number of arguments:\n[%s]", line.c_str())); const char PACKET[] = "packet"; const char DUMP[] = "dump"; if(PACKET == words[2]) { send_packet(line, words); } else if(DUMP == words[2]) { send_dump(line, words); } else { xorp_throw(InvalidString, c_format( "Second argument should be %s or %s not <%s>\n[%s]", PACKET, DUMP, words[2].c_str(), line.c_str())); }}/** * A corruption entry. * * The offset at which to corrupt a packet and the value with which to corrupt. */class Corrupt { public: Corrupt(uint32_t offset, uint8_t val) : _offset(offset), _val(val) {} uint32_t offset() const { return _offset; } uint32_t val() const { return _val; } private: uint32_t _offset; uint8_t _val;};/*** Form of command:** peer1 send packet update ...** peer1 send packet notify ...** peer1 send packet open ...** peer1 send packet keepalive** peer1 send packet corrupt offset byte offset byte ... update** notify** open** keepalive**** See the packet method for the rest of the commands*/voidPeer::send_packet(const string& line, const vector<string>& words) throw(InvalidString){ size_t size = words.size(); uint32_t word = 3; list<Corrupt> _corrupt; if ("corrupt" == words[3]) { word += 1; // Pairs of offset byte should be in the stream until we reach // packet. while (word + 2 < size) { if (!xorp_isdigit(words[word][0])) { xorp_throw(InvalidString, c_format("Should be an offset not %s\n[%s]", words[word].c_str(), line.c_str())); } if (!xorp_isdigit(words[word + 1][0])) { xorp_throw(InvalidString, c_format("Should be a value not %s\n[%s]", words[word + 1].c_str(), line.c_str())); } _corrupt.push_back(Corrupt(atoi(words[word].c_str()), atoi(words[word+1].c_str()))); word += 2; if (!xorp_isdigit(words[word][0])) break; } } const BGPPacket *pkt = Peer::packet(line, words, word); size_t len; uint8_t *buf = const_cast<uint8_t *>(pkt->encode(len)); delete pkt; if (!_corrupt.empty()) { list<Corrupt>::const_iterator i; for (i = _corrupt.begin(); i != _corrupt.end(); i++) { if (i->offset() >= len) xorp_throw(InvalidString, c_format("Offset %u larger than packet %u\n[%s]", i->offset(), XORP_UINT_CAST(len), line.c_str())); buf[i->offset()] = i->val(); } } /* ** If this is an update message, save it in the sent trie. */ const char update[] = "update"; if(update == words[3]) { TimeVal tv; _eventloop->current_time(tv); try { _trie_sent.process_update_packet(tv, buf, len); } catch(CorruptMessage& c) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -