version 1.1.1.3, 2013/07/21 23:54:37
|
version 1.1.1.4, 2016/11/02 10:09:10
|
Line 30 Software Foundation, Inc., 59 Temple Place - Suite 330
|
Line 30 Software Foundation, Inc., 59 Temple Place - Suite 330
|
#include "stream.h" |
#include "stream.h" |
#include "memory.h" |
#include "memory.h" |
#include "plist.h" |
#include "plist.h" |
|
#include "workqueue.h" |
|
#include "filter.h" |
|
|
#include "bgpd/bgpd.h" |
#include "bgpd/bgpd.h" |
#include "bgpd/bgp_attr.h" |
#include "bgpd/bgp_attr.h" |
Line 43 Software Foundation, Inc., 59 Temple Place - Suite 330
|
Line 45 Software Foundation, Inc., 59 Temple Place - Suite 330
|
#ifdef HAVE_SNMP |
#ifdef HAVE_SNMP |
#include "bgpd/bgp_snmp.h" |
#include "bgpd/bgp_snmp.h" |
#endif /* HAVE_SNMP */ |
#endif /* HAVE_SNMP */ |
| |
/* BGP FSM (finite state machine) has three types of functions. Type |
/* BGP FSM (finite state machine) has three types of functions. Type |
one is thread functions. Type two is event functions. Type three |
one is thread functions. Type two is event functions. Type three |
is FSM functions. Timer functions are set by bgp_timer_set |
is FSM functions. Timer functions are set by bgp_timer_set |
Line 65 static int bgp_start (struct peer *);
|
Line 67 static int bgp_start (struct peer *);
|
static int |
static int |
bgp_start_jitter (int time) |
bgp_start_jitter (int time) |
{ |
{ |
return ((rand () % (time + 1)) - (time / 2)); | return ((random () % (time + 1)) - (time / 2)); |
} |
} |
|
|
/* Check if suppress start/restart of sessions to peer. */ |
/* Check if suppress start/restart of sessions to peer. */ |
Line 100 bgp_timer_set (struct peer *peer)
|
Line 102 bgp_timer_set (struct peer *peer)
|
BGP_TIMER_OFF (peer->t_connect); |
BGP_TIMER_OFF (peer->t_connect); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_asorig); |
|
BGP_TIMER_OFF (peer->t_routeadv); |
BGP_TIMER_OFF (peer->t_routeadv); |
break; |
break; |
|
|
Line 112 bgp_timer_set (struct peer *peer)
|
Line 113 bgp_timer_set (struct peer *peer)
|
BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect); |
BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_asorig); |
|
BGP_TIMER_OFF (peer->t_routeadv); |
BGP_TIMER_OFF (peer->t_routeadv); |
break; |
break; |
|
|
Line 132 bgp_timer_set (struct peer *peer)
|
Line 132 bgp_timer_set (struct peer *peer)
|
} |
} |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_asorig); |
|
BGP_TIMER_OFF (peer->t_routeadv); |
BGP_TIMER_OFF (peer->t_routeadv); |
break; |
break; |
|
|
Line 150 bgp_timer_set (struct peer *peer)
|
Line 149 bgp_timer_set (struct peer *peer)
|
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_holdtime); |
} |
} |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_asorig); |
|
BGP_TIMER_OFF (peer->t_routeadv); |
BGP_TIMER_OFF (peer->t_routeadv); |
break; |
break; |
|
|
Line 173 bgp_timer_set (struct peer *peer)
|
Line 171 bgp_timer_set (struct peer *peer)
|
BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, |
BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, |
peer->v_keepalive); |
peer->v_keepalive); |
} |
} |
BGP_TIMER_OFF (peer->t_asorig); |
|
BGP_TIMER_OFF (peer->t_routeadv); |
BGP_TIMER_OFF (peer->t_routeadv); |
break; |
break; |
|
|
Line 197 bgp_timer_set (struct peer *peer)
|
Line 194 bgp_timer_set (struct peer *peer)
|
BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, |
BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, |
peer->v_keepalive); |
peer->v_keepalive); |
} |
} |
BGP_TIMER_OFF (peer->t_asorig); |
|
break; |
break; |
case Deleted: |
case Deleted: |
BGP_TIMER_OFF (peer->t_gr_restart); |
BGP_TIMER_OFF (peer->t_gr_restart); |
Line 208 bgp_timer_set (struct peer *peer)
|
Line 204 bgp_timer_set (struct peer *peer)
|
BGP_TIMER_OFF (peer->t_connect); |
BGP_TIMER_OFF (peer->t_connect); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_asorig); |
|
BGP_TIMER_OFF (peer->t_routeadv); |
BGP_TIMER_OFF (peer->t_routeadv); |
} |
} |
} |
} |
Line 406 bgp_fsm_change_status (struct peer *peer, int status)
|
Line 401 bgp_fsm_change_status (struct peer *peer, int status)
|
* (and must do so before actually changing into Deleted.. |
* (and must do so before actually changing into Deleted.. |
*/ |
*/ |
if (status >= Clearing) |
if (status >= Clearing) |
bgp_clear_route_all (peer); | { |
| bgp_clear_route_all (peer); |
| |
| /* If no route was queued for the clear-node processing, generate the |
| * completion event here. This is needed because if there are no routes |
| * to trigger the background clear-node thread, the event won't get |
| * generated and the peer would be stuck in Clearing. Note that this |
| * event is for the peer and helps the peer transition out of Clearing |
| * state; it should not be generated per (AFI,SAFI). The event is |
| * directly posted here without calling clear_node_complete() as we |
| * shouldn't do an extra unlock. This event will get processed after |
| * the state change that happens below, so peer will be in Clearing |
| * (or Deleted). |
| */ |
| if (!work_queue_is_scheduled (peer->clear_node_queue)) |
| BGP_EVENT_ADD (peer, Clearing_Completed); |
| } |
|
|
/* Preserve old status and change into new status. */ |
/* Preserve old status and change into new status. */ |
peer->ostatus = peer->status; |
peer->ostatus = peer->status; |
Line 505 bgp_stop (struct peer *peer)
|
Line 516 bgp_stop (struct peer *peer)
|
BGP_TIMER_OFF (peer->t_connect); |
BGP_TIMER_OFF (peer->t_connect); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_holdtime); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_keepalive); |
BGP_TIMER_OFF (peer->t_asorig); |
|
BGP_TIMER_OFF (peer->t_routeadv); |
BGP_TIMER_OFF (peer->t_routeadv); |
|
|
/* Stream reset. */ |
/* Stream reset. */ |
Line 545 bgp_stop (struct peer *peer)
|
Line 555 bgp_stop (struct peer *peer)
|
|
|
/* ORF received prefix-filter pnt */ |
/* ORF received prefix-filter pnt */ |
sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); |
sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); |
prefix_bgp_orf_remove_all (orf_name); | prefix_bgp_orf_remove_all (afi, orf_name); |
} |
} |
|
|
/* Reset keepalive and holdtime */ |
/* Reset keepalive and holdtime */ |
Line 592 bgp_stop_with_error (struct peer *peer)
|
Line 602 bgp_stop_with_error (struct peer *peer)
|
return 0; |
return 0; |
} |
} |
|
|
|
|
|
/* something went wrong, send notify and tear down */ |
|
static int |
|
bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code) |
|
{ |
|
/* Send notify to remote peer */ |
|
bgp_notify_send (peer, code, sub_code); |
|
|
|
/* Sweep if it is temporary peer. */ |
|
if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) |
|
{ |
|
zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host); |
|
peer_delete (peer); |
|
return -1; |
|
} |
|
|
|
/* Clear start timer value to default. */ |
|
peer->v_start = BGP_INIT_START_TIMER; |
|
|
|
/* bgp_stop needs to be invoked while in Established state */ |
|
bgp_stop(peer); |
|
|
|
return 0; |
|
} |
|
|
|
|
/* TCP connection open. Next we send open message to remote peer. And |
/* TCP connection open. Next we send open message to remote peer. And |
add read thread for reading open message. */ |
add read thread for reading open message. */ |
static int |
static int |
Line 740 bgp_fsm_keepalive_expire (struct peer *peer)
|
Line 776 bgp_fsm_keepalive_expire (struct peer *peer)
|
return 0; |
return 0; |
} |
} |
|
|
|
/* FSM error, unexpected event. This is error of BGP connection. So cut the |
|
peer and change to Idle status. */ |
|
static int |
|
bgp_fsm_event_error (struct peer *peer) |
|
{ |
|
plog_err (peer->log, "%s [FSM] unexpected packet received in state %s", |
|
peer->host, LOOKUP (bgp_status_msg, peer->status)); |
|
|
|
return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0); |
|
} |
|
|
/* Hold timer expire. This is error of BGP connection. So cut the |
/* Hold timer expire. This is error of BGP connection. So cut the |
peer and change to Idle status. */ |
peer and change to Idle status. */ |
static int |
static int |
bgp_fsm_holdtime_expire (struct peer *peer) |
bgp_fsm_holdtime_expire (struct peer *peer) |
{ |
{ |
if (BGP_DEBUG (fsm, FSM)) |
if (BGP_DEBUG (fsm, FSM)) |
zlog (peer->log, LOG_DEBUG, "%s [FSM] Hold timer expire", peer->host); | plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host); |
|
|
/* Send notify to remote peer. */ | return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0); |
bgp_notify_send (peer, BGP_NOTIFY_HOLD_ERR, 0); | |
| |
/* Sweep if it is temporary peer. */ | |
if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) | |
{ | |
zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host); | |
peer_delete (peer); | |
return -1; | |
} | |
| |
/* bgp_stop needs to be invoked while in Established state */ | |
bgp_stop(peer); | |
| |
return 0; | |
} |
} |
|
|
/* Status goes to Established. Send keepalive packet then make first |
/* Status goes to Established. Send keepalive packet then make first |
Line 905 bgp_ignore (struct peer *peer)
|
Line 938 bgp_ignore (struct peer *peer)
|
zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host); |
zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host); |
return 0; |
return 0; |
} |
} |
| |
/* Finite State Machine structure */ |
/* Finite State Machine structure */ |
static const struct { |
static const struct { |
int (*func) (struct peer *); |
int (*func) (struct peer *); |
Line 977 static const struct {
|
Line 1010 static const struct {
|
{bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ |
{bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ |
{bgp_ignore, Idle}, /* KeepAlive_timer_expired */ |
{bgp_ignore, Idle}, /* KeepAlive_timer_expired */ |
{bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */ |
{bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */ |
{bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */ | {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */ |
{bgp_ignore, Idle}, /* Receive_UPDATE_message */ | {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */ |
{bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */ |
{bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */ |
{bgp_ignore, Idle}, /* Clearing_Completed */ |
{bgp_ignore, Idle}, /* Clearing_Completed */ |
}, |
}, |