📄 peer.cc
字号:
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-// Copyright (c) 2001-2003 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.50 2003/10/23 04:10:24 atanu Exp $"// #define DEBUG_LOGGING#define DEBUG_PRINT_FUNCTION_NAME#include <string>#include <stdlib.h>#include "config.h"#include "bgp/bgp_module.h"#include "libxorp/debug.h"#include "libxorp/xlog.h"#include "libxorp/eventloop.hh"#include "libxorp/ipv4net.hh"#include "bgp/local_data.hh"#include "bgp/packet.hh"#include "libxipc/xrl_std_router.hh"#include "xrl/interfaces/test_peer_xif.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), _session(false), _passive(false), _keepalive(false), _established(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::PeerPeer::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(), 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("%d", _trie_sent.update_count()) + " "; status += "received: " + c_format("%d", _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, "connect"))) XLOG_FATAL("send_connect failed");}void Peer::disconnect(const string& /*line*/, const vector<string>& /*words*/) throw(InvalidString){ /* Connect the test peer to 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())); }}/*** At the moment the form of the command is:** peer1 send packet update \** origin 0 \** aspath 1/2/3 \** nexthop 10.10.10.10 \** nlri 1.2.3/24***/voidPeer::send_packet(const string& line, const vector<string>& words) throw(InvalidString){ /* XXX ** For the time being only handle sending update packets. ** Make sending updates a separate routine when we support sending ** other types of packets. */ const char update[] = "update"; if(update != words[3]) xorp_throw(InvalidString, c_format("Third argument should be %s not <%s>\n[%s]", update, words[3].c_str(), line.c_str())); /* ** Parse the command line. ** The arguments for this command come in pairs: ** name value */ size_t size = words.size(); if(0 != (size % 2)) xorp_throw(InvalidString, c_format("Incorrect number of arguments:\n[%s]", line.c_str())); const BGPPacket *pkt = Peer::packet(line, words, 3); size_t len; const uint8_t *buf = pkt->encode(len); delete pkt; /* ** Save the update message in the sent trie. */ TimeVal tv; _eventloop->current_time(tv); _trie_sent.process_update_packet(tv, buf, len); _busy++; send_message(buf, len, callback(this, &Peer::xrl_callback, "update"));}struct mrt_header { uint32_t time; uint16_t type; uint16_t subtype; uint32_t length;};struct mrt_update { uint16_t source_as; uint16_t dest_as; uint16_t ifindex; uint16_t af; uint32_t source_ip; uint32_t dest_ip;};inlineconstuint8_t *mrtd_traffic_file_read(FILE *fp, size_t& len){ mrt_header header; if(fread(&header, sizeof(header), 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } len = ntohl(header.length) - sizeof(mrt_update); mrt_update update; if(fread(&update, sizeof(update), 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } uint8_t *buf = new uint8_t[len]; if(fread(buf, len, 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } return buf;}/*** peer send dump mrtd update fname <count>** 0 1 2 3 4 5 6*/voidPeer::send_dump(const string& line, const vector<string>& words) throw(InvalidString){ if(6 != words.size() && 7 != words.size()) xorp_throw(InvalidString, c_format("Incorrect number of arguments:\n[%s]", line.c_str())); const char MRTD[] = "mrtd"; if(MRTD != words[3]) xorp_throw(InvalidString, c_format("Third argument should be %s not <%s>\n[%s]", MRTD, words[3].c_str(), line.c_str())); const char UPDATE[] = "update"; if(UPDATE != words[4]) xorp_throw(InvalidString, c_format("Fourth argument should be %s not <%s>\n[%s]", UPDATE, words[4].c_str(), line.c_str())); string fname = words[5]; FILE *fp = fopen(fname.c_str(), "r"); if(0 == fp) xorp_throw(InvalidString, c_format("fopen of %s failed: %s\n[%s]", fname.c_str(), strerror(errno), line.c_str())); size_t packets_to_send = 0; if(7 == words.size()) packets_to_send = atoi(words[6].c_str()); // XXX - We don't check for this to be an integer, we assume // failure returns zero. In which case the whole file is sent. /* ** It could take quite a while to send a large file so we need to ** set up the transfer and then return. */ send_dump_callback(XrlError::OKAY(), fp, 0, packets_to_send, "mrtd_traffic_send");}voidPeer::send_dump_callback(const XrlError& error, FILE *fp, const size_t packet_number, const size_t packets_to_send, const char *comment){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -