|
xorp
|
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__