xorp

peer.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 
00003 // Copyright (c) 2001-2009 XORP, Inc.
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, Version 2, June
00007 // 1991 as published by the Free Software Foundation. Redistribution
00008 // and/or modification of this program under the terms of any other
00009 // version of the GNU General Public License is not permitted.
00010 // 
00011 // This program is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00014 // see the GNU General Public License, Version 2, a copy of which can be
00015 // found in the XORP LICENSE.gpl file.
00016 // 
00017 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00018 // http://xorp.net
00019 
00020 // $XORP: xorp/bgp/peer.hh,v 1.53 2008/11/08 06:14:37 mjh Exp $
00021 
00022 #ifndef __BGP_PEER_HH__
00023 #define __BGP_PEER_HH__
00024 
00025 #include <sys/types.h>
00026 
00027 #include "socket.hh"
00028 #include "local_data.hh"
00029 #include "peer_data.hh"
00030 
00031 enum FSMState {
00032     STATEIDLE = 1,
00033     STATECONNECT = 2,
00034     STATEACTIVE = 3,
00035     STATEOPENSENT = 4,
00036     STATEOPENCONFIRM = 5,
00037     STATEESTABLISHED = 6,
00038     STATESTOPPED = 7    // This state is not in the protocol specification. 
00039             // After sending a notify it is necessary to
00040             // close the connection. Data transmission/reception 
00041             // is asynchronous, but the close is currently
00042             // synchronous. Thus the stopped state allows
00043             // us to wait for the notify to be sent to TCP,
00044             // before closing the connection.
00045 };
00046 
00047 enum FSMEvent {
00048     EVENTBGPSTART = 1,
00049     EVENTBGPSTOP = 2,
00050     EVENTBGPTRANOPEN = 3,
00051     EVENTBGPTRANCLOSED = 4,
00052     EVENTBGPCONNOPENFAIL = 5,
00053     EVENTBGPTRANFATALERR = 6,
00054     EVENTCONNTIMEEXP = 7,
00055     EVENTHOLDTIMEEXP = 8,
00056     EVENTKEEPALIVEEXP = 9,
00057     EVENTRECOPENMESS = 10,
00058     EVENTRECKEEPALIVEMESS = 11,
00059     EVENTRECUPDATEMESS = 12,
00060     EVENTRECNOTMESS = 13
00061 };
00062 
00063 enum PeerOutputState {
00064     PEER_OUTPUT_OK = 1,
00065     PEER_OUTPUT_BUSY = 2,
00066     PEER_OUTPUT_FAIL = 3
00067 };
00068 
00069 #define OPENMSGOK 0
00070 #define UPDATEMSGOK 0
00071 
00072 const uint32_t RIB_IPC_HANDLER_UNIQUE_ID = 0;
00073 const uint32_t AGGR_HANDLER_UNIQUE_ID = 1;
00074 const uint32_t UNIQUE_ID_START = AGGR_HANDLER_UNIQUE_ID + 1;
00075 
00076 class BGPMain;
00077 class PeerHandler;
00078 class AcceptSession;
00079 
00083 class DampPeerOscillations {
00084  public:
00085     DampPeerOscillations(EventLoop& eventloop, uint32_t restart_threshold,
00086              uint32_t time_period, uint32_t idle_holdtime);
00087 
00091     void restart();
00092 
00096     uint32_t idle_holdtime() const;
00097 
00101     void reset();
00102  private:
00103     EventLoop& _eventloop;      // Reference to the eventloop.
00104     const uint32_t _restart_threshold;  // Number of restart after
00105                     // which the idle holdtime
00106                     // will increase.
00107     const uint32_t _time_period;    // Period in seconds over
00108                     // which to sample errors.
00109     const uint32_t _idle_holdtime;  // Holdtime in seconds to use once the
00110                     // error threshold is passed.
00111 
00112     uint32_t _restart_counter;      // Count number of restarts in
00113                     // last time quantum.
00114 
00115     XorpTimer _zero_restart;        // Zero the restart counter.
00116 
00120     void zero_restart_count();
00121 };
00122 
00123 class BGPPeer {
00124 public:
00125     BGPPeer(LocalData *ld, BGPPeerData *pd, SocketClient *sock, BGPMain *m);
00126     virtual ~BGPPeer();
00127 
00131     uint32_t get_unique_id() const  { return _unique_id; }
00132 
00136     void zero_stats();
00137 
00141     void clear_last_error();
00142 
00147     BGPPeerData *swap_peerdata(BGPPeerData *pd) {
00148     BGPPeerData *tmp = _peerdata;
00149     _peerdata = pd;
00150 
00151     return tmp;
00152     }
00153 
00154     void connected(XorpFd s);
00155     void remove_accept_attempt(AcceptSession *conn);
00156     SocketClient *swap_sockets(SocketClient *new_sock);
00157     XorpFd get_sock();
00158 
00162     void event_start();         // EVENTBGPSTART
00163     void event_stop(bool restart=false, bool automatic = false);// EVENTBGPSTOP
00164     void event_open();          // EVENTBGPTRANOPEN
00165     void event_open(const XorpFd sock); // EVENTBGPTRANOPEN
00166     void event_closed();        // EVENTBGPTRANCLOSED
00167     void event_openfail();      // EVENTBGPCONNOPENFAIL
00168     void event_tranfatal();     // EVENTBGPTRANFATALERR
00169     void event_connexp();       // EVENTCONNTIMEEXP
00170     void event_holdexp();       // EVENTHOLDTIMEEXP
00171     void event_keepexp();       // EVENTKEEPALIVEEXP
00172     void event_delay_open_exp();    // Event 12: DelayOpenTimer_Expires
00173     void event_idle_hold_exp();     // Event 13: IdleHoldTimer_Expires
00174     void event_openmess(const OpenPacket& p);   // EVENTRECOPENMESS
00175     void event_keepmess();          // EVENTRECKEEPALIVEMESS
00176     void event_recvupdate(UpdatePacket& p);     // EVENTRECUPDATEMESS
00177     void event_recvnotify(const NotificationPacket& p); // EVENTRECNOTMESS
00178 
00179     void generate_open_message(OpenPacket& open);
00180     void notify_peer_of_error(const int error,
00181                   const int subcode = UNSPECIFIED,
00182                   const uint8_t*data = 0,
00183                   const size_t len = 0);
00184 
00185     FSMState state()            { return _state; }
00186     static const char *pretty_print_state(FSMState s);
00187 
00192     TimeVal jitter(const TimeVal& t);
00193 
00194     void clear_all_timers();
00195     void start_connect_retry_timer();
00196     void clear_connect_retry_timer();
00197     void restart_connect_retry_timer();
00198 
00199     void start_keepalive_timer();
00200     void clear_keepalive_timer();
00201 
00202     void start_hold_timer();
00203     void clear_hold_timer();
00204     void restart_hold_timer();
00205 
00206     void start_stopped_timer();
00207     void clear_stopped_timer();
00208 
00209     void start_idle_hold_timer();
00210     void clear_idle_hold_timer();
00214     bool running_idle_hold_timer() const;
00215 
00216     void start_delay_open_timer();
00217     void clear_delay_open_timer();
00218 
00219     bool get_message(BGPPacket::Status status, const uint8_t *buf, size_t len,
00220              SocketClient *socket_client);
00221     PeerOutputState send_message(const BGPPacket& p);
00222     void send_message_complete(SocketClient::Event, const uint8_t *buf);
00223 
00224     string str() const          { return _peername; }
00225     bool is_connected() const       { return _SocketClient->is_connected(); }
00226     bool still_reading() const      { return _SocketClient->still_reading(); }
00227     LocalData* localdata()              { return _localdata; }
00228     IPv4 id() const             { return _localdata->get_id(); }
00229     BGPMain* main() const       { return _mainprocess; }
00230     const BGPPeerData* peerdata() const { return _peerdata; }
00231     bool ibgp() const           { return peerdata()->ibgp(); }
00232     bool use_4byte_asnums() const { 
00233     return _peerdata->use_4byte_asnums(); 
00234     }
00235     bool we_use_4byte_asnums() const { 
00236     return _localdata->use_4byte_asnums(); 
00237     }
00238 
00242     bool send_netreachability(const BGPUpdateAttrib &n);
00243     /*
00244     ** Virtual so that it can be subclassed in the plumbing test code.
00245     */
00246     virtual PeerOutputState send_update_message(const UpdatePacket& p);
00247 
00248     uint32_t get_established_transitions() const {
00249     return _established_transitions;
00250     }
00251     uint32_t get_established_time() const;
00252     void get_msg_stats(uint32_t& in_updates, 
00253                uint32_t& out_updates, 
00254                uint32_t& in_msgs, 
00255                uint32_t& out_msgs, 
00256                uint16_t& last_error, 
00257                uint32_t& in_update_elapsed) const;
00258 protected:
00259 private:
00260     LocalData* _localdata;
00261 
00265     static uint32_t _unique_id_allocator;
00266     const uint32_t _unique_id;
00267 
00268     friend class BGPPeerList;
00269 
00270     void connect_to_peer(SocketClient::ConnectCallback cb) {
00271     XLOG_ASSERT(_SocketClient);
00272     _SocketClient->connect(cb);
00273     }
00274     void connect_to_peer_complete(bool success) {
00275     if (success)
00276         event_open();       // Event = EVENTBGPTRANOPEN
00277     else
00278         event_openfail();       // Event = EVENTBGPCONNOPENFAIL
00279     }
00280 
00281     void send_notification(const NotificationPacket& p, bool restart = true,
00282                bool automatic = true);
00283     void send_notification_complete(SocketClient::Event, const uint8_t *buf,
00284                     bool restart, bool automatic);
00285     void flush_transmit_queue()     { _SocketClient->flush_transmit_queue(); }
00286     void stop_reader()          { _SocketClient->stop_reader(); }
00287 
00288     SocketClient *_SocketClient;
00289     bool _output_queue_was_busy;
00290     FSMState _state;
00291 
00292     BGPPeerData* _peerdata;
00293     BGPMain* _mainprocess;
00294     PeerHandler *_handler;
00295     list<AcceptSession *> _accept_attempt;
00296     string _peername;
00297 
00298     XorpTimer _timer_connect_retry;
00299     XorpTimer _timer_hold_time;
00300     XorpTimer _timer_keep_alive;
00301     XorpTimer _idle_hold;
00302     XorpTimer _delay_open;
00303 
00304     // counters needed for the BGP MIB
00305     uint32_t _in_updates;
00306     uint32_t _out_updates;
00307     uint32_t _in_total_messages;
00308     uint32_t _out_total_messages;
00309     uint8_t _last_error[2];
00310     uint32_t _established_transitions;
00311     TimeVal _established_time;
00312     TimeVal _in_update_time;
00313 
00317     XorpTimer _timer_stopped;
00318     void hook_stopped();
00319 
00320     void check_open_packet(const OpenPacket *p) throw (CorruptMessage);
00321     NotificationPacket* check_update_packet(const UpdatePacket *p,
00322                         bool& good_nexthop);
00323 
00327     bool established();
00328 
00329     bool release_resources();
00330 
00341     void set_state(FSMState s, bool restart = true, bool automatic = true);
00342     bool remote_ip_ge_than(const BGPPeer& peer);
00343 
00344     bool _damping_peer_oscillations;    // True if Damp Peer
00345                     // Oscillations is enabled.
00346     DampPeerOscillations _damp_peer_oscillations;
00347     
00352     void automatic_restart();
00353     
00354 private:
00355     friend class BGPMain;
00356 
00357     bool _current_state;
00358     void set_current_peer_state(bool state) {_current_state = state;}
00359     bool get_current_peer_state() {return _current_state;}
00360 
00361     bool _next_state;
00362     void set_next_peer_state(bool state) {_next_state = state;}
00363     bool get_next_peer_state() {return _next_state;}
00364 
00365     bool _activated;
00366     void set_activate_state(bool state) {_activated = state;}
00367     bool get_activate_state() {return _activated;}
00368 };
00369 
00370 /*
00371  * All incoming TCP connection attempts are handled through this class.
00372  * The BGPPeer class handles outgoing connection attempts.
00373  *
00374  * Under normal circumstances only one connection attempt will be
00375  * taking place. When both BGP processes at either end of a session
00376  * attempt to make a connection at the same time there may be a
00377  * connection collision in this case it is necessary to hold two TCP
00378  * connections until an open message is seen by the peer to decide
00379  * which session should be selected. If a connection collision is
00380  * detected this class does *not* send an open message, it waits for
00381  * the peers open message. It should be noted that the BGPPeer class
00382  * is not aware that a connection collision condition exists, hence it
00383  * does not check the IDs. The assumptions are that:
00384  * 1) The IDs will be identical in both open messages so it's only
00385  *    necessary to check one of the two open messages.
00386  * 2) A BGP process will actually send a open message after making a
00387  *    connection. 
00388  *
00389  * This class could be used to get rid of the XORP invented STOPPED
00390  * state in state machine.
00391  */
00392 class AcceptSession {
00393  public:
00394      AcceptSession(BGPPeer& peer, XorpFd sock);
00395 
00396      ~AcceptSession();
00397 
00401      void start();
00402 
00407      void no_open_received();
00408 
00413      void remove();
00414 
00418      void send_notification_accept(const NotificationPacket& np);
00419 
00423      void send_notification_cb(SocketClient::Event ev, const uint8_t* buf);
00424 
00428      void cease();
00429 
00434      void collision();
00435 
00440      void event_openmess_accept(const OpenPacket& p);
00441 
00445      void swap_sockets();
00446 
00451      void swap_sockets(const OpenPacket& p);
00452 
00453 
00454      void notify_peer_of_error_accept(const int error,
00455                       const int subcode = UNSPECIFIED,
00456                       const uint8_t*data = 0,
00457                       const size_t len = 0);
00458 
00459      void event_tranfatal_accept();
00460 
00464      void event_closed_accept();
00465 
00469      void event_keepmess_accept();
00470 
00474      void event_recvupdate_accept(const UpdatePacket& p);
00475 
00479      void event_recvnotify_accept(const NotificationPacket& p);
00480 
00484      bool get_message_accept(BGPPacket::Status status, const uint8_t *buf,
00485                  size_t len, SocketClient *socket_client);
00486 
00487      bool is_connected() { return _socket_client->is_connected(); }
00488 
00489      bool still_reading() { return _socket_client->still_reading(); }
00490 
00491      void ignore_message() { _accept_messages = false; }
00492 
00493      bool accept_message() const { return _accept_messages; }
00494 
00495      string str() {
00496      return _peer.str();
00497      }
00498 
00499  private:
00500      BGPPeer& _peer;
00501      XorpFd _sock;
00502      SocketClient *_socket_client;
00503      bool _accept_messages;
00504 
00505      XorpTimer _open_wait;  // Wait for an open message from the peer.
00506 
00507      BGPMain *main()            { return _peer.main(); }
00508      FSMState state()           { return _peer.state(); }
00509      const BGPPeerData* peerdata() const{ return _peer.peerdata(); }
00510      bool running_idle_hold_timer() const {
00511     return _peer.running_idle_hold_timer();
00512      } 
00513 };
00514 
00515 #endif // __BGP_PEER_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations