summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_fsm.c')
-rw-r--r--bgpd/bgp_fsm.c3000
1 files changed, 1478 insertions, 1522 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 2b8498e51..5e117d767 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1,4 +1,4 @@
-/* BGP-4 Finite State Machine
+/* BGP-4 Finite State Machine
From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
@@ -50,29 +50,28 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_bfd.h"
#include "bgpd/bgp_memory.h"
-DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
-DEFINE_HOOK(peer_established, (struct peer *peer), (peer))
+DEFINE_HOOK(peer_backward_transition, (struct peer * peer), (peer))
+DEFINE_HOOK(peer_established, (struct peer * peer), (peer))
/* Definition of display strings corresponding to FSM events. This should be
* kept consistent with the events defined in bgpd.h
*/
-static const char *bgp_event_str[] =
-{
- NULL,
- "BGP_Start",
- "BGP_Stop",
- "TCP_connection_open",
- "TCP_connection_closed",
- "TCP_connection_open_failed",
- "TCP_fatal_error",
- "ConnectRetry_timer_expired",
- "Hold_Timer_expired",
- "KeepAlive_timer_expired",
- "Receive_OPEN_message",
- "Receive_KEEPALIVE_message",
- "Receive_UPDATE_message",
- "Receive_NOTIFICATION_message",
- "Clearing_Completed",
+static const char *bgp_event_str[] = {
+ NULL,
+ "BGP_Start",
+ "BGP_Stop",
+ "TCP_connection_open",
+ "TCP_connection_closed",
+ "TCP_connection_open_failed",
+ "TCP_fatal_error",
+ "ConnectRetry_timer_expired",
+ "Hold_Timer_expired",
+ "KeepAlive_timer_expired",
+ "Receive_OPEN_message",
+ "Receive_KEEPALIVE_message",
+ "Receive_UPDATE_message",
+ "Receive_NOTIFICATION_message",
+ "Clearing_Completed",
};
/* BGP FSM (finite state machine) has three types of functions. Type
@@ -81,1069 +80,1035 @@ static const char *bgp_event_str[] =
function. */
/* BGP event function. */
-int bgp_event (struct thread *);
+int bgp_event(struct thread *);
/* BGP thread functions. */
-static int bgp_start_timer (struct thread *);
-static int bgp_connect_timer (struct thread *);
-static int bgp_holdtime_timer (struct thread *);
-static int bgp_keepalive_timer (struct thread *);
+static int bgp_start_timer(struct thread *);
+static int bgp_connect_timer(struct thread *);
+static int bgp_holdtime_timer(struct thread *);
+static int bgp_keepalive_timer(struct thread *);
/* BGP FSM functions. */
-static int bgp_start (struct peer *);
+static int bgp_start(struct peer *);
-static void
-peer_xfer_stats (struct peer *peer_dst, struct peer *peer_src)
+static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
{
- /* Copy stats over. These are only the pre-established state stats */
- peer_dst->open_in += peer_src->open_in;
- peer_dst->open_out += peer_src->open_out;
- peer_dst->keepalive_in += peer_src->keepalive_in;
- peer_dst->keepalive_out += peer_src->keepalive_out;
- peer_dst->notify_in += peer_src->notify_in;
- peer_dst->notify_out += peer_src->notify_out;
- peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in;
- peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out;
+ /* Copy stats over. These are only the pre-established state stats */
+ peer_dst->open_in += peer_src->open_in;
+ peer_dst->open_out += peer_src->open_out;
+ peer_dst->keepalive_in += peer_src->keepalive_in;
+ peer_dst->keepalive_out += peer_src->keepalive_out;
+ peer_dst->notify_in += peer_src->notify_in;
+ peer_dst->notify_out += peer_src->notify_out;
+ peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in;
+ peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out;
}
-static struct peer *
-peer_xfer_conn(struct peer *from_peer)
+static struct peer *peer_xfer_conn(struct peer *from_peer)
{
- struct peer *peer;
- afi_t afi;
- safi_t safi;
- int fd;
- int status, pstatus;
- unsigned char last_evt, last_maj_evt;
-
- assert(from_peer != NULL);
-
- peer = from_peer->doppelganger;
-
- if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
- return from_peer;
-
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s: peer transfer %p fd %d -> %p fd %d)", from_peer->host,
- from_peer, from_peer->fd, peer, peer->fd);
-
- BGP_WRITE_OFF(peer->t_write);
- BGP_READ_OFF(peer->t_read);
- BGP_WRITE_OFF(from_peer->t_write);
- BGP_READ_OFF(from_peer->t_read);
-
- BGP_TIMER_OFF(peer->t_routeadv);
- BGP_TIMER_OFF(from_peer->t_routeadv);
-
- fd = peer->fd;
- peer->fd = from_peer->fd;
- from_peer->fd = fd;
- stream_reset(peer->ibuf);
- stream_fifo_clean(peer->obuf);
- stream_fifo_clean(from_peer->obuf);
-
- peer->as = from_peer->as;
- peer->v_holdtime = from_peer->v_holdtime;
- peer->v_keepalive = from_peer->v_keepalive;
- peer->routeadv = from_peer->routeadv;
- peer->v_routeadv = from_peer->v_routeadv;
- peer->v_gr_restart = from_peer->v_gr_restart;
- peer->cap = from_peer->cap;
- status = peer->status;
- pstatus = peer->ostatus;
- last_evt = peer->last_event;
- last_maj_evt = peer->last_major_event;
- peer->status = from_peer->status;
- peer->ostatus = from_peer->ostatus;
- peer->last_event = from_peer->last_event;
- peer->last_major_event = from_peer->last_major_event;
- from_peer->status = status;
- from_peer->ostatus = pstatus;
- from_peer->last_event = last_evt;
- from_peer->last_major_event = last_maj_evt;
- peer->remote_id = from_peer->remote_id;
-
- if (from_peer->hostname != NULL)
- {
- if (peer->hostname)
- {
- XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
- peer->hostname = NULL;
- }
-
- peer->hostname = from_peer->hostname;
- from_peer->hostname = NULL;
- }
-
- if (from_peer->domainname != NULL)
- {
- if (peer->domainname)
- {
- XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
- peer->domainname= NULL;
- }
-
- peer->domainname = from_peer->domainname;
- from_peer->domainname = NULL;
- }
-
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- {
- peer->af_flags[afi][safi] = from_peer->af_flags[afi][safi];
- peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi];
- peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
- peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi];
- peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi];
- peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
- peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
- }
-
- if (bgp_getsockname(peer) < 0)
- {
- zlog_err ("%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
- (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""),
- peer->host, peer->fd, from_peer->fd);
- bgp_stop(peer);
- bgp_stop(from_peer);
- return NULL;
- }
- if (from_peer->status > Active)
- {
- if (bgp_getsockname(from_peer) < 0)
- {
- zlog_err ("%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
- (CHECK_FLAG (from_peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""),
- from_peer->host, from_peer->fd, peer->fd);
- bgp_stop(from_peer);
- from_peer = NULL;
- }
- }
-
- BGP_READ_ON(peer->t_read, bgp_read, peer->fd);
- BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
-
- if (from_peer)
- peer_xfer_stats(peer, from_peer);
-
- return(peer);
+ struct peer *peer;
+ afi_t afi;
+ safi_t safi;
+ int fd;
+ int status, pstatus;
+ unsigned char last_evt, last_maj_evt;
+
+ assert(from_peer != NULL);
+
+ peer = from_peer->doppelganger;
+
+ if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ return from_peer;
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
+ from_peer->host, from_peer, from_peer->fd, peer,
+ peer->fd);
+
+ BGP_WRITE_OFF(peer->t_write);
+ BGP_READ_OFF(peer->t_read);
+ BGP_WRITE_OFF(from_peer->t_write);
+ BGP_READ_OFF(from_peer->t_read);
+
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_OFF(from_peer->t_routeadv);
+
+ fd = peer->fd;
+ peer->fd = from_peer->fd;
+ from_peer->fd = fd;
+ stream_reset(peer->ibuf);
+ stream_fifo_clean(peer->obuf);
+ stream_fifo_clean(from_peer->obuf);
+
+ peer->as = from_peer->as;
+ peer->v_holdtime = from_peer->v_holdtime;
+ peer->v_keepalive = from_peer->v_keepalive;
+ peer->routeadv = from_peer->routeadv;
+ peer->v_routeadv = from_peer->v_routeadv;
+ peer->v_gr_restart = from_peer->v_gr_restart;
+ peer->cap = from_peer->cap;
+ status = peer->status;
+ pstatus = peer->ostatus;
+ last_evt = peer->last_event;
+ last_maj_evt = peer->last_major_event;
+ peer->status = from_peer->status;
+ peer->ostatus = from_peer->ostatus;
+ peer->last_event = from_peer->last_event;
+ peer->last_major_event = from_peer->last_major_event;
+ from_peer->status = status;
+ from_peer->ostatus = pstatus;
+ from_peer->last_event = last_evt;
+ from_peer->last_major_event = last_maj_evt;
+ peer->remote_id = from_peer->remote_id;
+
+ if (from_peer->hostname != NULL) {
+ if (peer->hostname) {
+ XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
+ peer->hostname = NULL;
+ }
+
+ peer->hostname = from_peer->hostname;
+ from_peer->hostname = NULL;
+ }
+
+ if (from_peer->domainname != NULL) {
+ if (peer->domainname) {
+ XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
+ peer->domainname = NULL;
+ }
+
+ peer->domainname = from_peer->domainname;
+ from_peer->domainname = NULL;
+ }
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ peer->af_flags[afi][safi] =
+ from_peer->af_flags[afi][safi];
+ peer->af_sflags[afi][safi] =
+ from_peer->af_sflags[afi][safi];
+ peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
+ peer->afc_nego[afi][safi] =
+ from_peer->afc_nego[afi][safi];
+ peer->afc_adv[afi][safi] =
+ from_peer->afc_adv[afi][safi];
+ peer->afc_recv[afi][safi] =
+ from_peer->afc_recv[afi][safi];
+ peer->orf_plist[afi][safi] =
+ from_peer->orf_plist[afi][safi];
+ }
+
+ if (bgp_getsockname(peer) < 0) {
+ zlog_err(
+ "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
+ (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
+ ? "accept"
+ : ""),
+ peer->host, peer->fd, from_peer->fd);
+ bgp_stop(peer);
+ bgp_stop(from_peer);
+ return NULL;
+ }
+ if (from_peer->status > Active) {
+ if (bgp_getsockname(from_peer) < 0) {
+ zlog_err(
+ "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
+ (CHECK_FLAG(from_peer->sflags,
+ PEER_STATUS_ACCEPT_PEER)
+ ? "accept"
+ : ""),
+ from_peer->host, from_peer->fd, peer->fd);
+ bgp_stop(from_peer);
+ from_peer = NULL;
+ }
+ }
+
+ BGP_READ_ON(peer->t_read, bgp_read, peer->fd);
+ BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
+
+ if (from_peer)
+ peer_xfer_stats(peer, from_peer);
+
+ return (peer);
}
/* Hook function called after bgp event is occered. And vty's
neighbor command invoke this function after making neighbor
structure. */
-void
-bgp_timer_set (struct peer *peer)
+void bgp_timer_set(struct peer *peer)
{
- switch (peer->status)
- {
- case Idle:
- /* First entry point of peer's finite state machine. In Idle
- status start timer is on unless peer is shutdown or peer is
- inactive. All other timer must be turned off */
- if (BGP_PEER_START_SUPPRESSED (peer) || ! peer_active (peer))
- {
- BGP_TIMER_OFF (peer->t_start);
- }
- else
- {
- BGP_TIMER_ON (peer->t_start, bgp_start_timer,
- peer->v_start);
- }
- BGP_TIMER_OFF (peer->t_connect);
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- BGP_TIMER_OFF (peer->t_routeadv);
- break;
-
- case Connect:
- /* After start timer is expired, the peer moves to Connect
- status. Make sure start timer is off and connect timer is
- on. */
- BGP_TIMER_OFF (peer->t_start);
- BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- BGP_TIMER_OFF (peer->t_routeadv);
- break;
-
- case Active:
- /* Active is waiting connection from remote peer. And if
- connect timer is expired, change status to Connect. */
- BGP_TIMER_OFF (peer->t_start);
- /* If peer is passive mode, do not set connect timer. */
- if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)
- || CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
- {
- BGP_TIMER_OFF (peer->t_connect);
+ switch (peer->status) {
+ case Idle:
+ /* First entry point of peer's finite state machine. In Idle
+ status start timer is on unless peer is shutdown or peer is
+ inactive. All other timer must be turned off */
+ if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)) {
+ BGP_TIMER_OFF(peer->t_start);
+ } else {
+ BGP_TIMER_ON(peer->t_start, bgp_start_timer,
+ peer->v_start);
+ }
+ BGP_TIMER_OFF(peer->t_connect);
+ BGP_TIMER_OFF(peer->t_holdtime);
+ BGP_TIMER_OFF(peer->t_keepalive);
+ BGP_TIMER_OFF(peer->t_routeadv);
+ break;
+
+ case Connect:
+ /* After start timer is expired, the peer moves to Connect
+ status. Make sure start timer is off and connect timer is
+ on. */
+ BGP_TIMER_OFF(peer->t_start);
+ BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
+ peer->v_connect);
+ BGP_TIMER_OFF(peer->t_holdtime);
+ BGP_TIMER_OFF(peer->t_keepalive);
+ BGP_TIMER_OFF(peer->t_routeadv);
+ break;
+
+ case Active:
+ /* Active is waiting connection from remote peer. And if
+ connect timer is expired, change status to Connect. */
+ BGP_TIMER_OFF(peer->t_start);
+ /* If peer is passive mode, do not set connect timer. */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)
+ || CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
+ BGP_TIMER_OFF(peer->t_connect);
+ } else {
+ BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
+ peer->v_connect);
+ }
+ BGP_TIMER_OFF(peer->t_holdtime);
+ BGP_TIMER_OFF(peer->t_keepalive);
+ BGP_TIMER_OFF(peer->t_routeadv);
+ break;
+
+ case OpenSent:
+ /* OpenSent status. */
+ BGP_TIMER_OFF(peer->t_start);
+ BGP_TIMER_OFF(peer->t_connect);
+ if (peer->v_holdtime != 0) {
+ BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
+ peer->v_holdtime);
+ } else {
+ BGP_TIMER_OFF(peer->t_holdtime);
+ }
+ BGP_TIMER_OFF(peer->t_keepalive);
+ BGP_TIMER_OFF(peer->t_routeadv);
+ break;
+
+ case OpenConfirm:
+ /* OpenConfirm status. */
+ BGP_TIMER_OFF(peer->t_start);
+ BGP_TIMER_OFF(peer->t_connect);
+
+ /* If the negotiated Hold Time value is zero, then the Hold Time
+ timer and KeepAlive timers are not started. */
+ if (peer->v_holdtime == 0) {
+ BGP_TIMER_OFF(peer->t_holdtime);
+ BGP_TIMER_OFF(peer->t_keepalive);
+ } else {
+ BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
+ peer->v_holdtime);
+ BGP_TIMER_ON(peer->t_keepalive, bgp_keepalive_timer,
+ peer->v_keepalive);
+ }
+ BGP_TIMER_OFF(peer->t_routeadv);
+ break;
+
+ case Established:
+ /* In Established status start and connect timer is turned
+ off. */
+ BGP_TIMER_OFF(peer->t_start);
+ BGP_TIMER_OFF(peer->t_connect);
+
+ /* Same as OpenConfirm, if holdtime is zero then both holdtime
+ and keepalive must be turned off. */
+ if (peer->v_holdtime == 0) {
+ BGP_TIMER_OFF(peer->t_holdtime);
+ BGP_TIMER_OFF(peer->t_keepalive);
+ } else {
+ BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
+ peer->v_holdtime);
+ BGP_TIMER_ON(peer->t_keepalive, bgp_keepalive_timer,
+ peer->v_keepalive);
+ }
+ break;
+ case Deleted:
+ BGP_TIMER_OFF(peer->t_gr_restart);
+ BGP_TIMER_OFF(peer->t_gr_stale);
+ BGP_TIMER_OFF(peer->t_pmax_restart);
+ case Clearing:
+ BGP_TIMER_OFF(peer->t_start);
+ BGP_TIMER_OFF(peer->t_connect);
+ BGP_TIMER_OFF(peer->t_holdtime);
+ BGP_TIMER_OFF(peer->t_keepalive);
+ BGP_TIMER_OFF(peer->t_routeadv);
+ break;
}
- else
- {
- BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
- }
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- BGP_TIMER_OFF (peer->t_routeadv);
- break;
-
- case OpenSent:
- /* OpenSent status. */
- BGP_TIMER_OFF (peer->t_start);
- BGP_TIMER_OFF (peer->t_connect);
- if (peer->v_holdtime != 0)
- {
- BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
- peer->v_holdtime);
- }
- else
- {
- BGP_TIMER_OFF (peer->t_holdtime);
- }
- BGP_TIMER_OFF (peer->t_keepalive);
- BGP_TIMER_OFF (peer->t_routeadv);
- break;
-
- case OpenConfirm:
- /* OpenConfirm status. */
- BGP_TIMER_OFF (peer->t_start);
- BGP_TIMER_OFF (peer->t_connect);
-
- /* If the negotiated Hold Time value is zero, then the Hold Time
- timer and KeepAlive timers are not started. */
- if (peer->v_holdtime == 0)
- {
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- }
- else
- {
- BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
- peer->v_holdtime);
- BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
- peer->v_keepalive);
- }
- BGP_TIMER_OFF (peer->t_routeadv);
- break;
-
- case Established:
- /* In Established status start and connect timer is turned
- off. */
- BGP_TIMER_OFF (peer->t_start);
- BGP_TIMER_OFF (peer->t_connect);
-
- /* Same as OpenConfirm, if holdtime is zero then both holdtime
- and keepalive must be turned off. */
- if (peer->v_holdtime == 0)
- {
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- }
- else
- {
- BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
- peer->v_holdtime);
- BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
- peer->v_keepalive);
- }
- break;
- case Deleted:
- BGP_TIMER_OFF (peer->t_gr_restart);
- BGP_TIMER_OFF (peer->t_gr_stale);
- BGP_TIMER_OFF (peer->t_pmax_restart);
- case Clearing:
- BGP_TIMER_OFF (peer->t_start);
- BGP_TIMER_OFF (peer->t_connect);
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- BGP_TIMER_OFF (peer->t_routeadv);
- break;
- }
}
/* BGP start timer. This function set BGP_Start event to thread value
and process event. */
-static int
-bgp_start_timer (struct thread *thread)
+static int bgp_start_timer(struct thread *thread)
{
- struct peer *peer;
+ struct peer *peer;
- peer = THREAD_ARG (thread);
- peer->t_start = NULL;
+ peer = THREAD_ARG(thread);
+ peer->t_start = NULL;
- if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s [FSM] Timer (start timer expire).", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Timer (start timer expire).", peer->host);
- THREAD_VAL (thread) = BGP_Start;
- bgp_event (thread); /* bgp_event unlocks peer */
+ THREAD_VAL(thread) = BGP_Start;
+ bgp_event(thread); /* bgp_event unlocks peer */
- return 0;
+ return 0;
}
/* BGP connect retry timer. */
-static int
-bgp_connect_timer (struct thread *thread)
+static int bgp_connect_timer(struct thread *thread)
{
- struct peer *peer;
- int ret;
-
- peer = THREAD_ARG (thread);
- peer->t_connect = NULL;
-
- if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
-
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- bgp_stop(peer);
- ret = -1;
- }
- else
- {
- THREAD_VAL (thread) = ConnectRetry_timer_expired;
- bgp_event (thread); /* bgp_event unlocks peer */
- ret = 0;
- }
-
- return ret;
+ struct peer *peer;
+ int ret;
+
+ peer = THREAD_ARG(thread);
+ peer->t_connect = NULL;
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
+
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) {
+ bgp_stop(peer);
+ ret = -1;
+ } else {
+ THREAD_VAL(thread) = ConnectRetry_timer_expired;
+ bgp_event(thread); /* bgp_event unlocks peer */
+ ret = 0;
+ }
+
+ return ret;
}
/* BGP holdtime timer. */
-static int
-bgp_holdtime_timer (struct thread *thread)
+static int bgp_holdtime_timer(struct thread *thread)
{
- struct peer *peer;
+ struct peer *peer;
- peer = THREAD_ARG (thread);
- peer->t_holdtime = NULL;
+ peer = THREAD_ARG(thread);
+ peer->t_holdtime = NULL;
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Timer (holdtime timer expire)", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Timer (holdtime timer expire)",
+ peer->host);
- THREAD_VAL (thread) = Hold_Timer_expired;
- bgp_event (thread); /* bgp_event unlocks peer */
+ THREAD_VAL(thread) = Hold_Timer_expired;
+ bgp_event(thread); /* bgp_event unlocks peer */
- return 0;
+ return 0;
}
/* BGP keepalive fire ! */
-static int
-bgp_keepalive_timer (struct thread *thread)
+static int bgp_keepalive_timer(struct thread *thread)
{
- struct peer *peer;
+ struct peer *peer;
- peer = THREAD_ARG (thread);
- peer->t_keepalive = NULL;
+ peer = THREAD_ARG(thread);
+ peer->t_keepalive = NULL;
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Timer (keepalive timer expire)", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Timer (keepalive timer expire)",
+ peer->host);
- THREAD_VAL (thread) = KeepAlive_timer_expired;
- bgp_event (thread); /* bgp_event unlocks peer */
+ THREAD_VAL(thread) = KeepAlive_timer_expired;
+ bgp_event(thread); /* bgp_event unlocks peer */
- return 0;
+ return 0;
}
-int
-bgp_routeadv_timer (struct thread *thread)
+int bgp_routeadv_timer(struct thread *thread)
{
- struct peer *peer;
+ struct peer *peer;
- peer = THREAD_ARG (thread);
- peer->t_routeadv = NULL;
+ peer = THREAD_ARG(thread);
+ peer->t_routeadv = NULL;
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Timer (routeadv timer expire)", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Timer (routeadv timer expire)",
+ peer->host);
- peer->synctime = bgp_clock ();
+ peer->synctime = bgp_clock();
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
- /* MRAI timer will be started again when FIFO is built, no need to
- * do it here.
- */
- return 0;
+ /* MRAI timer will be started again when FIFO is built, no need to
+ * do it here.
+ */
+ return 0;
}
/* BGP Peer Down Cause */
-const char *peer_down_str[] =
+const char *peer_down_str[] = {"",
+ "Router ID changed",
+ "Remote AS changed",
+ "Local AS change",
+ "Cluster ID changed",
+ "Confederation identifier changed",
+ "Confederation peer changed",
+ "RR client config change",
+ "RS client config change",
+ "Update source change",
+ "Address family activated",
+ "Admin. shutdown",
+ "User reset",
+ "BGP Notification received",
+ "BGP Notification send",
+ "Peer closed the session",
+ "Neighbor deleted",
+ "Peer-group add member",
+ "Peer-group delete member",
+ "Capability changed",
+ "Passive config change",
+ "Multihop config change",
+ "NSF peer closed the session",
+ "Intf peering v6only config change",
+ "BFD down received",
+ "Interface down",
+ "Neighbor address lost"};
+
+static int bgp_graceful_restart_timer_expire(struct thread *thread)
{
- "",
- "Router ID changed",
- "Remote AS changed",
- "Local AS change",
- "Cluster ID changed",
- "Confederation identifier changed",
- "Confederation peer changed",
- "RR client config change",
- "RS client config change",
- "Update source change",
- "Address family activated",
- "Admin. shutdown",
- "User reset",
- "BGP Notification received",
- "BGP Notification send",
- "Peer closed the session",
- "Neighbor deleted",
- "Peer-group add member",
- "Peer-group delete member",
- "Capability changed",
- "Passive config change",
- "Multihop config change",
- "NSF peer closed the session",
- "Intf peering v6only config change",
- "BFD down received",
- "Interface down",
- "Neighbor address lost"
-};
-
-static int
-bgp_graceful_restart_timer_expire (struct thread *thread)
-{
- struct peer *peer;
- afi_t afi;
- safi_t safi;
-
- peer = THREAD_ARG (thread);
- peer->t_gr_restart = NULL;
-
- /* NSF delete stale route */
- for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
- if (peer->nsf[afi][safi])
- bgp_clear_stale_route (peer, afi, safi);
-
- UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
- BGP_TIMER_OFF (peer->t_gr_stale);
-
- if (bgp_debug_neighbor_events(peer))
- {
- zlog_debug ("%s graceful restart timer expired", peer->host);
- zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
- }
+ struct peer *peer;
+ afi_t afi;
+ safi_t safi;
+
+ peer = THREAD_ARG(thread);
+ peer->t_gr_restart = NULL;
+
+ /* NSF delete stale route */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
+ if (peer->nsf[afi][safi])
+ bgp_clear_stale_route(peer, afi, safi);
+
+ UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
+ BGP_TIMER_OFF(peer->t_gr_stale);
+
+ if (bgp_debug_neighbor_events(peer)) {
+ zlog_debug("%s graceful restart timer expired", peer->host);
+ zlog_debug("%s graceful restart stalepath timer stopped",
+ peer->host);
+ }
- bgp_timer_set (peer);
+ bgp_timer_set(peer);
- return 0;
+ return 0;
}
-static int
-bgp_graceful_stale_timer_expire (struct thread *thread)
+static int bgp_graceful_stale_timer_expire(struct thread *thread)
{
- struct peer *peer;
- afi_t afi;
- safi_t safi;
+ struct peer *peer;
+ afi_t afi;
+ safi_t safi;
- peer = THREAD_ARG (thread);
- peer->t_gr_stale = NULL;
+ peer = THREAD_ARG(thread);
+ peer->t_gr_stale = NULL;
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s graceful restart stalepath timer expired", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s graceful restart stalepath timer expired",
+ peer->host);
- /* NSF delete stale route */
- for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
- if (peer->nsf[afi][safi])
- bgp_clear_stale_route (peer, afi, safi);
+ /* NSF delete stale route */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++)
+ if (peer->nsf[afi][safi])
+ bgp_clear_stale_route(peer, afi, safi);
- return 0;
+ return 0;
}
-static int
-bgp_update_delay_applicable (struct bgp *bgp)
+static int bgp_update_delay_applicable(struct bgp *bgp)
{
- /* update_delay_over flag should be reset (set to 0) for any new
- applicability of the update-delay during BGP process lifetime.
- And it should be set after an occurence of the update-delay is over)*/
- if (!bgp->update_delay_over)
- return 1;
-
- return 0;
+ /* update_delay_over flag should be reset (set to 0) for any new
+ applicability of the update-delay during BGP process lifetime.
+ And it should be set after an occurence of the update-delay is
+ over)*/
+ if (!bgp->update_delay_over)
+ return 1;
+
+ return 0;
}
-int
-bgp_update_delay_active (struct bgp *bgp)
+int bgp_update_delay_active(struct bgp *bgp)
{
- if (bgp->t_update_delay)
- return 1;
+ if (bgp->t_update_delay)
+ return 1;
- return 0;
+ return 0;
}
-int
-bgp_update_delay_configured (struct bgp *bgp)
+int bgp_update_delay_configured(struct bgp *bgp)
{
- if (bgp->v_update_delay)
- return 1;
+ if (bgp->v_update_delay)
+ return 1;
- return 0;
+ return 0;
}
/* Do the post-processing needed when bgp comes out of the read-only mode
on ending the update delay. */
-void
-bgp_update_delay_end (struct bgp *bgp)
+void bgp_update_delay_end(struct bgp *bgp)
{
- THREAD_TIMER_OFF (bgp->t_update_delay);
- THREAD_TIMER_OFF (bgp->t_establish_wait);
-
- /* Reset update-delay related state */
- bgp->update_delay_over = 1;
- bgp->established = 0;
- bgp->restarted_peers = 0;
- bgp->implicit_eors = 0;
- bgp->explicit_eors = 0;
-
- quagga_timestamp(3, bgp->update_delay_end_time,
- sizeof(bgp->update_delay_end_time));
-
- /*
- * Add an end-of-initial-update marker to the main process queues so that
- * the route advertisement timer for the peers can be started. Also set
- * the zebra and peer update hold flags. These flags are used to achieve
- * three stages in the update-delay post processing:
- * 1. Finish best-path selection for all the prefixes held on the queues.
- * (routes in BGP are updated, and peers sync queues are populated too)
- * 2. As the eoiu mark is reached in the bgp process routine, ship all the
- * routes to zebra. With that zebra should see updates from BGP close
- * to each other.
- * 3. Unblock the peer update writes. With that peer update packing with
- * the prefixes should be at its maximum.
- */
- bgp_add_eoiu_mark(bgp);
- bgp->main_zebra_update_hold = 1;
- bgp->main_peers_update_hold = 1;
-
- /* Resume the queue processing. This should trigger the event that would take
- care of processing any work that was queued during the read-only mode. */
- work_queue_unplug(bm->process_main_queue);
+ THREAD_TIMER_OFF(bgp->t_update_delay);
+ THREAD_TIMER_OFF(bgp->t_establish_wait);
+
+ /* Reset update-delay related state */
+ bgp->update_delay_over = 1;
+ bgp->established = 0;
+ bgp->restarted_peers = 0;
+ bgp->implicit_eors = 0;
+ bgp->explicit_eors = 0;
+
+ quagga_timestamp(3, bgp->update_delay_end_time,
+ sizeof(bgp->update_delay_end_time));
+
+ /*
+ * Add an end-of-initial-update marker to the main process queues so
+ * that
+ * the route advertisement timer for the peers can be started. Also set
+ * the zebra and peer update hold flags. These flags are used to achieve
+ * three stages in the update-delay post processing:
+ * 1. Finish best-path selection for all the prefixes held on the
+ * queues.
+ * (routes in BGP are updated, and peers sync queues are populated
+ * too)
+ * 2. As the eoiu mark is reached in the bgp process routine, ship all
+ * the
+ * routes to zebra. With that zebra should see updates from BGP
+ * close
+ * to each other.
+ * 3. Unblock the peer update writes. With that peer update packing
+ * with
+ * the prefixes should be at its maximum.
+ */
+ bgp_add_eoiu_mark(bgp);
+ bgp->main_zebra_update_hold = 1;
+ bgp->main_peers_update_hold = 1;
+
+ /* Resume the queue processing. This should trigger the event that would
+ take
+ care of processing any work that was queued during the read-only
+ mode. */
+ work_queue_unplug(bm->process_main_queue);
}
/**
* see bgp_fsm.h
*/
-void
-bgp_start_routeadv (struct bgp *bgp)
+void bgp_start_routeadv(struct bgp *bgp)
{
- struct listnode *node, *nnode;
- struct peer *peer;
+ struct listnode *node, *nnode;
+ struct peer *peer;
- zlog_info("bgp_start_routeadv(), update hold status %d",
- bgp->main_peers_update_hold);
+ zlog_info("bgp_start_routeadv(), update hold status %d",
+ bgp->main_peers_update_hold);
- if (bgp->main_peers_update_hold)
- return;
+ if (bgp->main_peers_update_hold)
+ return;
- quagga_timestamp(3, bgp->update_delay_peers_resume_time,
- sizeof(bgp->update_delay_peers_resume_time));
+ quagga_timestamp(3, bgp->update_delay_peers_resume_time,
+ sizeof(bgp->update_delay_peers_resume_time));
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- {
- if (peer->status != Established)
- continue;
- BGP_TIMER_OFF(peer->t_routeadv);
- BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
- }
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (peer->status != Established)
+ continue;
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
+ }
}
/**
* see bgp_fsm.h
*/
-void
-bgp_adjust_routeadv (struct peer *peer)
+void bgp_adjust_routeadv(struct peer *peer)
{
- time_t nowtime = bgp_clock();
- double diff;
- unsigned long remain;
-
- /* Bypass checks for special case of MRAI being 0 */
- if (peer->v_routeadv == 0)
- {
- /* Stop existing timer, just in case it is running for a different
- * duration and schedule write thread immediately.
- */
- if (peer->t_routeadv)
- BGP_TIMER_OFF(peer->t_routeadv);
-
- peer->synctime = bgp_clock ();
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
- return;
- }
-
-
- /*
- * CASE I:
- * If the last update was written more than MRAI back, expire the timer
- * instantly so that we can send the update out sooner.
- *
- * <------- MRAI --------->
- * |-----------------|-----------------------|
- * <------------- m ------------>
- * ^ ^ ^
- * | | |
- * | | current time
- * | timer start
- * last write
- *
- * m > MRAI
- */
- diff = difftime(nowtime, peer->last_update);
- if (diff > (double) peer->v_routeadv)
- {
- BGP_TIMER_OFF(peer->t_routeadv);
- BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
- return;
- }
-
- /*
- * CASE II:
- * - Find when to expire the MRAI timer.
- * If MRAI timer is not active, assume we can start it now.
- *
- * <------- MRAI --------->
- * |------------|-----------------------|
- * <-------- m ----------><----- r ----->
- * ^ ^ ^
- * | | |
- * | | current time
- * | timer start
- * last write
- *
- * (MRAI - m) < r
- */
- if (peer->t_routeadv)
- remain = thread_timer_remain_second(peer->t_routeadv);
- else
- remain = peer->v_routeadv;
- diff = peer->v_routeadv - diff;
- if (diff <= (double) remain)
- {
- BGP_TIMER_OFF(peer->t_routeadv);
- BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff);
- }
+ time_t nowtime = bgp_clock();
+ double diff;
+ unsigned long remain;
+
+ /* Bypass checks for special case of MRAI being 0 */
+ if (peer->v_routeadv == 0) {
+ /* Stop existing timer, just in case it is running for a
+ * different
+ * duration and schedule write thread immediately.
+ */
+ if (peer->t_routeadv)
+ BGP_TIMER_OFF(peer->t_routeadv);
+
+ peer->synctime = bgp_clock();
+ BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
+ return;
+ }
+
+
+ /*
+ * CASE I:
+ * If the last update was written more than MRAI back, expire the timer
+ * instantly so that we can send the update out sooner.
+ *
+ * <------- MRAI --------->
+ * |-----------------|-----------------------|
+ * <------------- m ------------>
+ * ^ ^ ^
+ * | | |
+ * | | current time
+ * | timer start
+ * last write
+ *
+ * m > MRAI
+ */
+ diff = difftime(nowtime, peer->last_update);
+ if (diff > (double)peer->v_routeadv) {
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
+ return;
+ }
+
+ /*
+ * CASE II:
+ * - Find when to expire the MRAI timer.
+ * If MRAI timer is not active, assume we can start it now.
+ *
+ * <------- MRAI --------->
+ * |------------|-----------------------|
+ * <-------- m ----------><----- r ----->
+ * ^ ^ ^
+ * | | |
+ * | | current time
+ * | timer start
+ * last write
+ *
+ * (MRAI - m) < r
+ */
+ if (peer->t_routeadv)
+ remain = thread_timer_remain_second(peer->t_routeadv);
+ else
+ remain = peer->v_routeadv;
+ diff = peer->v_routeadv - diff;
+ if (diff <= (double)remain) {
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff);
+ }
}
-static int
-bgp_maxmed_onstartup_applicable (struct bgp *bgp)
+static int bgp_maxmed_onstartup_applicable(struct bgp *bgp)
{
- if (!bgp->maxmed_onstartup_over)
- return 1;
+ if (!bgp->maxmed_onstartup_over)
+ return 1;
- return 0;
+ return 0;
}
-int
-bgp_maxmed_onstartup_configured (struct bgp *bgp)
+int bgp_maxmed_onstartup_configured(struct bgp *bgp)
{
- if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
- return 1;
+ if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
+ return 1;
- return 0;
+ return 0;
}
-int
-bgp_maxmed_onstartup_active (struct bgp *bgp)
+int bgp_maxmed_onstartup_active(struct bgp *bgp)
{
- if (bgp->t_maxmed_onstartup)
- return 1;
+ if (bgp->t_maxmed_onstartup)
+ return 1;
- return 0;
+ return 0;
}
-void
-bgp_maxmed_update (struct bgp *bgp)
+void bgp_maxmed_update(struct bgp *bgp)
{
- u_char maxmed_active;
- u_int32_t maxmed_value;
-
- if (bgp->v_maxmed_admin)
- {
- maxmed_active = 1;
- maxmed_value = bgp->maxmed_admin_value;
- }
- else if (bgp->t_maxmed_onstartup)
- {
- maxmed_active = 1;
- maxmed_value = bgp->maxmed_onstartup_value;
- }
- else
- {
- maxmed_active = 0;
- maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
- }
-
- if (bgp->maxmed_active != maxmed_active ||
- bgp->maxmed_value != maxmed_value)
- {
- bgp->maxmed_active = maxmed_active;
- bgp->maxmed_value = maxmed_value;
-
- update_group_announce(bgp);
- }
+ u_char maxmed_active;
+ u_int32_t maxmed_value;
+
+ if (bgp->v_maxmed_admin) {
+ maxmed_active = 1;
+ maxmed_value = bgp->maxmed_admin_value;
+ } else if (bgp->t_maxmed_onstartup) {
+ maxmed_active = 1;
+ maxmed_value = bgp->maxmed_onstartup_value;
+ } else {
+ maxmed_active = 0;
+ maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
+ }
+
+ if (bgp->maxmed_active != maxmed_active
+ || bgp->maxmed_value != maxmed_value) {
+ bgp->maxmed_active = maxmed_active;
+ bgp->maxmed_value = maxmed_value;
+
+ update_group_announce(bgp);
+ }
}
/* The maxmed onstartup timer expiry callback. */
-static int
-bgp_maxmed_onstartup_timer (struct thread *thread)
+static int bgp_maxmed_onstartup_timer(struct thread *thread)
{
- struct bgp *bgp;
+ struct bgp *bgp;
- zlog_info ("Max med on startup ended - timer expired.");
+ zlog_info("Max med on startup ended - timer expired.");
- bgp = THREAD_ARG (thread);
- THREAD_TIMER_OFF (bgp->t_maxmed_onstartup);
- bgp->maxmed_onstartup_over = 1;
+ bgp = THREAD_ARG(thread);
+ THREAD_TIMER_OFF(bgp->t_maxmed_onstartup);
+ bgp->maxmed_onstartup_over = 1;
- bgp_maxmed_update(bgp);
+ bgp_maxmed_update(bgp);
- return 0;
+ return 0;
}
-static void
-bgp_maxmed_onstartup_begin (struct bgp *bgp)
+static void bgp_maxmed_onstartup_begin(struct bgp *bgp)
{
- /* Applicable only once in the process lifetime on the startup */
- if (bgp->maxmed_onstartup_over)
- return;
+ /* Applicable only once in the process lifetime on the startup */
+ if (bgp->maxmed_onstartup_over)
+ return;
- zlog_info ("Begin maxmed onstartup mode - timer %d seconds",
- bgp->v_maxmed_onstartup);
+ zlog_info("Begin maxmed onstartup mode - timer %d seconds",
+ bgp->v_maxmed_onstartup);
- THREAD_TIMER_ON (bm->master, bgp->t_maxmed_onstartup,
- bgp_maxmed_onstartup_timer,
- bgp, bgp->v_maxmed_onstartup);
+ THREAD_TIMER_ON(bm->master, bgp->t_maxmed_onstartup,
+ bgp_maxmed_onstartup_timer, bgp,
+ bgp->v_maxmed_onstartup);
- if (!bgp->v_maxmed_admin)
- {
- bgp->maxmed_active = 1;
- bgp->maxmed_value = bgp->maxmed_onstartup_value;
- }
+ if (!bgp->v_maxmed_admin) {
+ bgp->maxmed_active = 1;
+ bgp->maxmed_value = bgp->maxmed_onstartup_value;
+ }
- /* Route announce to all peers should happen after this in bgp_establish() */
+ /* Route announce to all peers should happen after this in
+ * bgp_establish() */
}
-static void
-bgp_maxmed_onstartup_process_status_change(struct peer *peer)
+static void bgp_maxmed_onstartup_process_status_change(struct peer *peer)
{
- if (peer->status == Established && !peer->bgp->established)
- {
- bgp_maxmed_onstartup_begin(peer->bgp);
- }
+ if (peer->status == Established && !peer->bgp->established) {
+ bgp_maxmed_onstartup_begin(peer->bgp);
+ }
}
/* The update delay timer expiry callback. */
-static int
-bgp_update_delay_timer (struct thread *thread)
+static int bgp_update_delay_timer(struct thread *thread)
{
- struct bgp *bgp;
+ struct bgp *bgp;
- zlog_info ("Update delay ended - timer expired.");
+ zlog_info("Update delay ended - timer expired.");
- bgp = THREAD_ARG (thread);
- THREAD_TIMER_OFF (bgp->t_update_delay);
- bgp_update_delay_end(bgp);
+ bgp = THREAD_ARG(thread);
+ THREAD_TIMER_OFF(bgp->t_update_delay);
+ bgp_update_delay_end(bgp);
- return 0;
+ return 0;
}
/* The establish wait timer expiry callback. */
-static int
-bgp_establish_wait_timer (struct thread *thread)
+static int bgp_establish_wait_timer(struct thread *thread)
{
- struct bgp *bgp;
+ struct bgp *bgp;
- zlog_info ("Establish wait - timer expired.");
+ zlog_info("Establish wait - timer expired.");
- bgp = THREAD_ARG (thread);
- THREAD_TIMER_OFF (bgp->t_establish_wait);
- bgp_check_update_delay(bgp);
+ bgp = THREAD_ARG(thread);
+ THREAD_TIMER_OFF(bgp->t_establish_wait);
+ bgp_check_update_delay(bgp);
- return 0;
+ return 0;
}
/* Steps to begin the update delay:
- initialize queues if needed
- stop the queue processing
- start the timer */
-static void
-bgp_update_delay_begin (struct bgp *bgp)
+static void bgp_update_delay_begin(struct bgp *bgp)
{
- struct listnode *node, *nnode;
- struct peer *peer;
+ struct listnode *node, *nnode;
+ struct peer *peer;
- /* Stop the processing of queued work. Enqueue shall continue */
- work_queue_plug(bm->process_main_queue);
+ /* Stop the processing of queued work. Enqueue shall continue */
+ work_queue_plug(bm->process_main_queue);
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- peer->update_delay_over = 0;
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ peer->update_delay_over = 0;
- /* Start the update-delay timer */
- THREAD_TIMER_ON (bm->master, bgp->t_update_delay, bgp_update_delay_timer,
- bgp, bgp->v_update_delay);
+ /* Start the update-delay timer */
+ THREAD_TIMER_ON(bm->master, bgp->t_update_delay, bgp_update_delay_timer,
+ bgp, bgp->v_update_delay);
- if (bgp->v_establish_wait != bgp->v_update_delay)
- THREAD_TIMER_ON (bm->master, bgp->t_establish_wait, bgp_establish_wait_timer,
- bgp, bgp->v_establish_wait);
+ if (bgp->v_establish_wait != bgp->v_update_delay)
+ THREAD_TIMER_ON(bm->master, bgp->t_establish_wait,
+ bgp_establish_wait_timer, bgp,
+ bgp->v_establish_wait);
- quagga_timestamp(3, bgp->update_delay_begin_time,
- sizeof(bgp->update_delay_begin_time));
+ quagga_timestamp(3, bgp->update_delay_begin_time,
+ sizeof(bgp->update_delay_begin_time));
}
-static void
-bgp_update_delay_process_status_change(struct peer *peer)
+static void bgp_update_delay_process_status_change(struct peer *peer)
{
- if (peer->status == Established)
- {
- if (!peer->bgp->established++)
- {
- bgp_update_delay_begin(peer->bgp);
- zlog_info ("Begin read-only mode - update-delay timer %d seconds",
- peer->bgp->v_update_delay);
- }
- if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV))
- bgp_update_restarted_peers(peer);
- }
- if (peer->ostatus == Established && bgp_update_delay_active(peer->bgp))
- {
- /* Adjust the update-delay state to account for this flap.
- NOTE: Intentionally skipping adjusting implicit_eors or explicit_eors
- counters. Extra sanity check in bgp_check_update_delay() should
- be enough to take care of any additive discrepancy in bgp eor
- counters */
- peer->bgp->established--;
- peer->update_delay_over = 0;
- }
+ if (peer->status == Established) {
+ if (!peer->bgp->established++) {
+ bgp_update_delay_begin(peer->bgp);
+ zlog_info(
+ "Begin read-only mode - update-delay timer %d seconds",
+ peer->bgp->v_update_delay);
+ }
+ if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV))
+ bgp_update_restarted_peers(peer);
+ }
+ if (peer->ostatus == Established
+ && bgp_update_delay_active(peer->bgp)) {
+ /* Adjust the update-delay state to account for this flap.
+ NOTE: Intentionally skipping adjusting implicit_eors or
+ explicit_eors
+ counters. Extra sanity check in bgp_check_update_delay()
+ should
+ be enough to take care of any additive discrepancy in bgp eor
+ counters */
+ peer->bgp->established--;
+ peer->update_delay_over = 0;
+ }
}
/* Called after event occured, this function change status and reset
read/write and timer thread. */
-void
-bgp_fsm_change_status (struct peer *peer, int status)
+void bgp_fsm_change_status(struct peer *peer, int status)
{
- bgp_dump_state (peer, peer->status, status);
-
- /* Transition into Clearing or Deleted must /always/ clear all routes..
- * (and must do so before actually changing into Deleted..
- */
- if (status >= Clearing)
- {
- 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. */
- peer->ostatus = peer->status;
- peer->status = status;
-
- /* Save event that caused status change. */
- peer->last_major_event = peer->cur_event;
-
- if (status == Established)
- UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
-
- /* If max-med processing is applicable, do the necessary. */
- if (status == Established)
- {
- if (bgp_maxmed_onstartup_configured(peer->bgp) &&
- bgp_maxmed_onstartup_applicable(peer->bgp))
- bgp_maxmed_onstartup_process_status_change(peer);
- else
- peer->bgp->maxmed_onstartup_over = 1;
- }
-
- /* If update-delay processing is applicable, do the necessary. */
- if (bgp_update_delay_configured(peer->bgp) &&
- bgp_update_delay_applicable(peer->bgp))
- bgp_update_delay_process_status_change(peer);
-
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s went from %s to %s",
- peer->host,
- lookup_msg(bgp_status_msg, peer->ostatus, NULL),
- lookup_msg(bgp_status_msg, peer->status, NULL));
+ bgp_dump_state(peer, peer->status, status);
+
+ /* Transition into Clearing or Deleted must /always/ clear all routes..
+ * (and must do so before actually changing into Deleted..
+ */
+ if (status >= Clearing) {
+ 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. */
+ peer->ostatus = peer->status;
+ peer->status = status;
+
+ /* Save event that caused status change. */
+ peer->last_major_event = peer->cur_event;
+
+ if (status == Established)
+ UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
+
+ /* If max-med processing is applicable, do the necessary. */
+ if (status == Established) {
+ if (bgp_maxmed_onstartup_configured(peer->bgp)
+ && bgp_maxmed_onstartup_applicable(peer->bgp))
+ bgp_maxmed_onstartup_process_status_change(peer);
+ else
+ peer->bgp->maxmed_onstartup_over = 1;
+ }
+
+ /* If update-delay processing is applicable, do the necessary. */
+ if (bgp_update_delay_configured(peer->bgp)
+ && bgp_update_delay_applicable(peer->bgp))
+ bgp_update_delay_process_status_change(peer);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s went from %s to %s", peer->host,
+ lookup_msg(bgp_status_msg, peer->ostatus, NULL),
+ lookup_msg(bgp_status_msg, peer->status, NULL));
}
/* Flush the event queue and ensure the peer is shut down */
-static int
-bgp_clearing_completed (struct peer *peer)
+static int bgp_clearing_completed(struct peer *peer)
{
- int rc = bgp_stop(peer);
+ int rc = bgp_stop(peer);
- if (rc >= 0)
- BGP_EVENT_FLUSH (peer);
+ if (rc >= 0)
+ BGP_EVENT_FLUSH(peer);
- return rc;
+ return rc;
}
/* Administrative BGP peer stop event. */
/* May be called multiple times for the same peer */
-int
-bgp_stop (struct peer *peer)
+int bgp_stop(struct peer *peer)
{
- afi_t afi;
- safi_t safi;
- char orf_name[BUFSIZ];
- int ret = 0;
-
- if (peer_dynamic_neighbor(peer) &&
- !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE)))
- {
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s (dynamic neighbor) deleted", peer->host);
- peer_delete (peer);
- return -1;
- }
-
- /* Can't do this in Clearing; events are used for state transitions */
- if (peer->status != Clearing)
- {
- /* Delete all existing events of the peer */
- BGP_EVENT_FLUSH (peer);
- }
-
- /* Increment Dropped count. */
- if (peer->status == Established)
- {
- peer->dropped++;
-
- /* bgp log-neighbor-changes of neighbor Down */
- if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
- {
- struct vrf *vrf = vrf_lookup_by_id (peer->bgp->vrf_id);
- zlog_info ("%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s",
- peer->host,
- (peer->hostname) ? peer->hostname : "Unknown",
- vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name : "Default") : "",
- peer_down_str [(int) peer->last_reset]);
+ afi_t afi;
+ safi_t safi;
+ char orf_name[BUFSIZ];
+ int ret = 0;
+
+ if (peer_dynamic_neighbor(peer)
+ && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ peer_delete(peer);
+ return -1;
}
- /* graceful restart */
- if (peer->t_gr_stale)
- {
- BGP_TIMER_OFF (peer->t_gr_stale);
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
+ /* Can't do this in Clearing; events are used for state transitions */
+ if (peer->status != Clearing) {
+ /* Delete all existing events of the peer */
+ BGP_EVENT_FLUSH(peer);
}
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
- {
- if (bgp_debug_neighbor_events(peer))
- {
- zlog_debug ("%s graceful restart timer started for %d sec",
- peer->host, peer->v_gr_restart);
- zlog_debug ("%s graceful restart stalepath timer started for %d sec",
- peer->host, peer->bgp->stalepath_time);
- }
- BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
- peer->v_gr_restart);
- BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
- peer->bgp->stalepath_time);
+
+ /* Increment Dropped count. */
+ if (peer->status == Established) {
+ peer->dropped++;
+
+ /* bgp log-neighbor-changes of neighbor Down */
+ if (bgp_flag_check(peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
+ struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
+ zlog_info(
+ "%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s",
+ peer->host,
+ (peer->hostname) ? peer->hostname : "Unknown",
+ vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
+ : "Default")
+ : "",
+ peer_down_str[(int)peer->last_reset]);
+ }
+
+ /* graceful restart */
+ if (peer->t_gr_stale) {
+ BGP_TIMER_OFF(peer->t_gr_stale);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s graceful restart stalepath timer stopped",
+ peer->host);
+ }
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
+ if (bgp_debug_neighbor_events(peer)) {
+ zlog_debug(
+ "%s graceful restart timer started for %d sec",
+ peer->host, peer->v_gr_restart);
+ zlog_debug(
+ "%s graceful restart stalepath timer started for %d sec",
+ peer->host, peer->bgp->stalepath_time);
+ }
+ BGP_TIMER_ON(peer->t_gr_restart,
+ bgp_graceful_restart_timer_expire,
+ peer->v_gr_restart);
+ BGP_TIMER_ON(peer->t_gr_stale,
+ bgp_graceful_stale_timer_expire,
+ peer->bgp->stalepath_time);
+ } else {
+ UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST;
+ safi < SAFI_RESERVED_4; safi++)
+ peer->nsf[afi][safi] = 0;
+ }
+
+ /* set last reset time */
+ peer->resettime = peer->uptime = bgp_clock();
+
+ if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
+ zlog_debug("%s remove from all update group",
+ peer->host);
+ update_group_remove_peer_afs(peer);
+
+ hook_call(peer_backward_transition, peer);
+
+ /* Reset peer synctime */
+ peer->synctime = 0;
+
+ bgp_bfd_deregister_peer(peer);
}
- else
- {
- UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
- for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
- peer->nsf[afi][safi] = 0;
+ /* Stop read and write threads when exists. */
+ BGP_READ_OFF(peer->t_read);
+ BGP_WRITE_OFF(peer->t_write);
+
+ /* Stop all timers. */
+ BGP_TIMER_OFF(peer->t_start);
+ BGP_TIMER_OFF(peer->t_connect);
+ BGP_TIMER_OFF(peer->t_holdtime);
+ BGP_TIMER_OFF(peer->t_keepalive);
+ BGP_TIMER_OFF(peer->t_routeadv);
+
+ /* Stream reset. */
+ peer->packet_size = 0;
+
+ /* Clear input and output buffer. */
+ if (peer->ibuf)
+ stream_reset(peer->ibuf);
+ if (peer->work)
+ stream_reset(peer->work);
+ if (peer->obuf)
+ stream_fifo_clean(peer->obuf);
+
+ /* Close of file descriptor. */
+ if (peer->fd >= 0) {
+ close(peer->fd);
+ peer->fd = -1;
}
- /* set last reset time */
- peer->resettime = peer->uptime = bgp_clock ();
-
- if (BGP_DEBUG (update_groups, UPDATE_GROUPS))
- zlog_debug ("%s remove from all update group", peer->host);
- update_group_remove_peer_afs(peer);
-
- hook_call(peer_backward_transition, peer);
-
- /* Reset peer synctime */
- peer->synctime = 0;
-
- bgp_bfd_deregister_peer(peer);
- }
-
- /* Stop read and write threads when exists. */
- BGP_READ_OFF (peer->t_read);
- BGP_WRITE_OFF (peer->t_write);
-
- /* Stop all timers. */
- BGP_TIMER_OFF (peer->t_start);
- BGP_TIMER_OFF (peer->t_connect);
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- BGP_TIMER_OFF (peer->t_routeadv);
-
- /* Stream reset. */
- peer->packet_size = 0;
-
- /* Clear input and output buffer. */
- if (peer->ibuf)
- stream_reset (peer->ibuf);
- if (peer->work)
- stream_reset (peer->work);
- if (peer->obuf)
- stream_fifo_clean (peer->obuf);
-
- /* Close of file descriptor. */
- if (peer->fd >= 0)
- {
- close (peer->fd);
- peer->fd = -1;
- }
-
- for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
- {
- /* Reset all negotiated variables */
- peer->afc_nego[afi][safi] = 0;
- peer->afc_adv[afi][safi] = 0;
- peer->afc_recv[afi][safi] = 0;
-
- /* peer address family capability flags*/
- peer->af_cap[afi][safi] = 0;
-
- /* peer address family status flags*/
- peer->af_sflags[afi][safi] = 0;
-
- /* Received ORF prefix-filter */
- peer->orf_plist[afi][safi] = NULL;
-
- if ((peer->status == OpenConfirm) || (peer->status == Established)) {
- /* ORF received prefix-filter pnt */
- sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
- prefix_bgp_orf_remove_all (afi, orf_name);
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ /* Reset all negotiated variables */
+ peer->afc_nego[afi][safi] = 0;
+ peer->afc_adv[afi][safi] = 0;
+ peer->afc_recv[afi][safi] = 0;
+
+ /* peer address family capability flags*/
+ peer->af_cap[afi][safi] = 0;
+
+ /* peer address family status flags*/
+ peer->af_sflags[afi][safi] = 0;
+
+ /* Received ORF prefix-filter */
+ peer->orf_plist[afi][safi] = NULL;
+
+ if ((peer->status == OpenConfirm)
+ || (peer->status == Established)) {
+ /* ORF received prefix-filter pnt */
+ sprintf(orf_name, "%s.%d.%d", peer->host, afi,
+ safi);
+ prefix_bgp_orf_remove_all(afi, orf_name);
+ }
+ }
+
+ /* Reset keepalive and holdtime */
+ if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)) {
+ peer->v_keepalive = peer->keepalive;
+ peer->v_holdtime = peer->holdtime;
+ } else {
+ peer->v_keepalive = peer->bgp->default_keepalive;
+ peer->v_holdtime = peer->bgp->default_holdtime;
}
- }
-
- /* Reset keepalive and holdtime */
- if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
- {
- peer->v_keepalive = peer->keepalive;
- peer->v_holdtime = peer->holdtime;
- }
- else
- {
- peer->v_keepalive = peer->bgp->default_keepalive;
- peer->v_holdtime = peer->bgp->default_holdtime;
- }
-
- peer->update_time = 0;
-
- /* Until we are sure that there is no problem about prefix count
- this should be commented out.*/
+
+ peer->update_time = 0;
+
+/* Until we are sure that there is no problem about prefix count
+ this should be commented out.*/
#if 0
/* Reset prefix count */
peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
@@ -1153,731 +1118,722 @@ bgp_stop (struct peer *peer)
peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
#endif /* 0 */
- if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&
- !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE)))
- {
- peer_delete(peer);
- ret = -1;
- }
- else
- {
- bgp_peer_conf_if_to_su_update(peer);
- }
-
- return ret;
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
+ && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
+ peer_delete(peer);
+ ret = -1;
+ } else {
+ bgp_peer_conf_if_to_su_update(peer);
+ }
+
+ return ret;
}
/* BGP peer is stoped by the error. */
-static int
-bgp_stop_with_error (struct peer *peer)
+static int bgp_stop_with_error(struct peer *peer)
{
- /* Double start timer. */
- peer->v_start *= 2;
-
- /* Overflow check. */
- if (peer->v_start >= (60 * 2))
- peer->v_start = (60 * 2);
-
- if (peer_dynamic_neighbor(peer))
- {
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s (dynamic neighbor) deleted", peer->host);
- peer_delete (peer);
- return -1;
- }
-
- return(bgp_stop (peer));
+ /* Double start timer. */
+ peer->v_start *= 2;
+
+ /* Overflow check. */
+ if (peer->v_start >= (60 * 2))
+ peer->v_start = (60 * 2);
+
+ if (peer_dynamic_neighbor(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ peer_delete(peer);
+ return -1;
+ }
+
+ return (bgp_stop(peer));
}
/* something went wrong, send notify and tear down */
-static int
-bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code)
+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);
-
- if (peer_dynamic_neighbor(peer))
- {
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s (dynamic neighbor) deleted", peer->host);
- peer_delete (peer);
- return -1;
- }
+ /* Send notify to remote peer */
+ bgp_notify_send(peer, code, sub_code);
+
+ if (peer_dynamic_neighbor(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ peer_delete(peer);
+ return -1;
+ }
- /* Clear start timer value to default. */
- peer->v_start = BGP_INIT_START_TIMER;
+ /* Clear start timer value to default. */
+ peer->v_start = BGP_INIT_START_TIMER;
- return(bgp_stop(peer));
+ return (bgp_stop(peer));
}
/* TCP connection open. Next we send open message to remote peer. And
add read thread for reading open message. */
-static int
-bgp_connect_success (struct peer *peer)
+static int bgp_connect_success(struct peer *peer)
{
- if (peer->fd < 0)
- {
- zlog_err ("bgp_connect_success peer's fd is negative value %d",
- peer->fd);
- bgp_stop(peer);
- return -1;
- }
-
- if (bgp_getsockname (peer) < 0)
- {
- zlog_err ("%s: bgp_getsockname(): failed for peer %s, fd %d", __FUNCTION__,
- peer->host, peer->fd);
- bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0); /* internal error */
- return -1;
- }
-
- BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
-
- if (bgp_debug_neighbor_events(peer))
- {
- char buf1[SU_ADDRSTRLEN];
-
- if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- zlog_debug ("%s open active, local address %s", peer->host,
- sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
- else
- zlog_debug ("%s passive open", peer->host);
- }
-
- bgp_open_send (peer);
-
- return 0;
+ if (peer->fd < 0) {
+ zlog_err("bgp_connect_success peer's fd is negative value %d",
+ peer->fd);
+ bgp_stop(peer);
+ return -1;
+ }
+
+ if (bgp_getsockname(peer) < 0) {
+ zlog_err("%s: bgp_getsockname(): failed for peer %s, fd %d",
+ __FUNCTION__, peer->host, peer->fd);
+ bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
+ 0); /* internal error */
+ return -1;
+ }
+
+ BGP_READ_ON(peer->t_read, bgp_read, peer->fd);
+
+ if (bgp_debug_neighbor_events(peer)) {
+ char buf1[SU_ADDRSTRLEN];
+
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ zlog_debug("%s open active, local address %s",
+ peer->host,
+ sockunion2str(peer->su_local, buf1,
+ SU_ADDRSTRLEN));
+ else
+ zlog_debug("%s passive open", peer->host);
+ }
+
+ bgp_open_send(peer);
+
+ return 0;
}
/* TCP connect fail */
-static int
-bgp_connect_fail (struct peer *peer)
+static int bgp_connect_fail(struct peer *peer)
{
- if (peer_dynamic_neighbor(peer))
- {
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s (dynamic neighbor) deleted", peer->host);
- peer_delete (peer);
- return -1;
- }
-
- return (bgp_stop (peer));
+ if (peer_dynamic_neighbor(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ peer_delete(peer);
+ return -1;
+ }
+
+ return (bgp_stop(peer));
}
/* This function is the first starting point of all BGP connection. It
try to connect to remote peer with non-blocking IO. */
-int
-bgp_start (struct peer *peer)
+int bgp_start(struct peer *peer)
{
- int status;
- int connected = 0;
-
- bgp_peer_conf_if_to_su_update(peer);
-
- if (peer->su.sa.sa_family == AF_UNSPEC)
- {
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Unable to get neighbor's IP address, waiting...",
- peer->host);
- return -1;
- }
-
- if (BGP_PEER_START_SUPPRESSED (peer))
- {
- if (bgp_debug_neighbor_events(peer))
- zlog_err ("%s [FSM] Trying to start suppressed peer"
- " - this is never supposed to happen!", peer->host);
- return -1;
- }
-
- /* Scrub some information that might be left over from a previous,
- * session
- */
- /* Connection information. */
- if (peer->su_local)
- {
- sockunion_free (peer->su_local);
- peer->su_local = NULL;
- }
-
- if (peer->su_remote)
- {
- sockunion_free (peer->su_remote);
- peer->su_remote = NULL;
- }
-
- /* Clear remote router-id. */
- peer->remote_id.s_addr = 0;
-
- /* Clear peer capability flag. */
- peer->cap = 0;
-
- /* If the peer is passive mode, force to move to Active mode. */
- if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
- {
- BGP_EVENT_ADD (peer, TCP_connection_open_failed);
- return 0;
- }
-
- /* Register to be notified on peer up */
- if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
- ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
- && ! bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
- connected = 1;
- else
- connected = 0;
-
- if (!bgp_find_or_add_nexthop(peer->bgp, family2afi(peer->su.sa.sa_family),
- NULL, peer, connected))
- {
-#if defined (HAVE_CUMULUS)
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Waiting for NHT", peer->host);
-
- BGP_EVENT_ADD(peer, TCP_connection_open_failed);
- return 0;
+ int status;
+ int connected = 0;
+
+ bgp_peer_conf_if_to_su_update(peer);
+
+ if (peer->su.sa.sa_family == AF_UNSPEC) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s [FSM] Unable to get neighbor's IP address, waiting...",
+ peer->host);
+ return -1;
+ }
+
+ if (BGP_PEER_START_SUPPRESSED(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_err(
+ "%s [FSM] Trying to start suppressed peer"
+ " - this is never supposed to happen!",
+ peer->host);
+ return -1;
+ }
+
+ /* Scrub some information that might be left over from a previous,
+ * session
+ */
+ /* Connection information. */
+ if (peer->su_local) {
+ sockunion_free(peer->su_local);
+ peer->su_local = NULL;
+ }
+
+ if (peer->su_remote) {
+ sockunion_free(peer->su_remote);
+ peer->su_remote = NULL;
+ }
+
+ /* Clear remote router-id. */
+ peer->remote_id.s_addr = 0;
+
+ /* Clear peer capability flag. */
+ peer->cap = 0;
+
+ /* If the peer is passive mode, force to move to Active mode. */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
+ BGP_EVENT_ADD(peer, TCP_connection_open_failed);
+ return 0;
+ }
+
+ /* Register to be notified on peer up */
+ if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
+ && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
+ && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+ connected = 1;
+ else
+ connected = 0;
+
+ if (!bgp_find_or_add_nexthop(peer->bgp,
+ family2afi(peer->su.sa.sa_family), NULL,
+ peer, connected)) {
+#if defined(HAVE_CUMULUS)
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Waiting for NHT", peer->host);
+
+ BGP_EVENT_ADD(peer, TCP_connection_open_failed);
+ return 0;
#endif
- }
-
- status = bgp_connect (peer);
-
- switch (status)
- {
- case connect_error:
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Connect error", peer->host);
- BGP_EVENT_ADD (peer, TCP_connection_open_failed);
- break;
- case connect_success:
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Connect immediately success, fd %d",
- peer->host, peer->fd);
- BGP_EVENT_ADD (peer, TCP_connection_open);
- break;
- case connect_in_progress:
- /* To check nonblocking connect, we wait until socket is
- readable or writable. */
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Non blocking connect waiting result, fd %d",
- peer->host, peer->fd);
- if (peer->fd < 0)
- {
- zlog_err ("bgp_start peer's fd is negative value %d",
- peer->fd);
- return -1;
}
- BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
- break;
- }
- return 0;
+
+ status = bgp_connect(peer);
+
+ switch (status) {
+ case connect_error:
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Connect error", peer->host);
+ BGP_EVENT_ADD(peer, TCP_connection_open_failed);
+ break;
+ case connect_success:
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s [FSM] Connect immediately success, fd %d",
+ peer->host, peer->fd);
+ BGP_EVENT_ADD(peer, TCP_connection_open);
+ break;
+ case connect_in_progress:
+ /* To check nonblocking connect, we wait until socket is
+ readable or writable. */
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s [FSM] Non blocking connect waiting result, fd %d",
+ peer->host, peer->fd);
+ if (peer->fd < 0) {
+ zlog_err("bgp_start peer's fd is negative value %d",
+ peer->fd);
+ return -1;
+ }
+ BGP_READ_ON(peer->t_read, bgp_read, peer->fd);
+ BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
+ break;
+ }
+ return 0;
}
/* Connect retry timer is expired when the peer status is Connect. */
-static int
-bgp_reconnect (struct peer *peer)
+static int bgp_reconnect(struct peer *peer)
{
- if (bgp_stop (peer) < 0)
- return -1;
+ if (bgp_stop(peer) < 0)
+ return -1;
- bgp_start (peer);
- return 0;
+ bgp_start(peer);
+ return 0;
}
-static int
-bgp_fsm_open (struct peer *peer)
+static int bgp_fsm_open(struct peer *peer)
{
- /* Send keepalive and make keepalive timer */
- bgp_keepalive_send (peer);
+ /* Send keepalive and make keepalive timer */
+ bgp_keepalive_send(peer);
- /* Reset holdtimer value. */
- BGP_TIMER_OFF (peer->t_holdtime);
+ /* Reset holdtimer value. */
+ BGP_TIMER_OFF(peer->t_holdtime);
- return 0;
+ return 0;
}
/* Keepalive send to peer. */
-static int
-bgp_fsm_keepalive_expire (struct peer *peer)
+static int bgp_fsm_keepalive_expire(struct peer *peer)
{
- bgp_keepalive_send (peer);
- return 0;
+ bgp_keepalive_send(peer);
+ 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)
+static int bgp_fsm_event_error(struct peer *peer)
{
- zlog_err ("%s [FSM] unexpected packet received in state %s",
- peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
+ zlog_err("%s [FSM] unexpected packet received in state %s", peer->host,
+ lookup_msg(bgp_status_msg, peer->status, NULL));
- return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
+ return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, 0);
}
/* Hold timer expire. This is error of BGP connection. So cut the
peer and change to Idle status. */
-static int
-bgp_fsm_holdtime_expire (struct peer *peer)
+static int bgp_fsm_holdtime_expire(struct peer *peer)
{
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s [FSM] Hold timer expire", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Hold timer expire", peer->host);
- return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
+ return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0);
}
/* Status goes to Established. Send keepalive packet then make first
update information. */
-static int
-bgp_establish (struct peer *peer)
+static int bgp_establish(struct peer *peer)
{
- afi_t afi;
- safi_t safi;
- int nsf_af_count = 0;
- int ret = 0;
- struct peer *other;
-
- other = peer->doppelganger;
- peer = peer_xfer_conn(peer);
- if (!peer)
- {
- zlog_err ("%%Neighbor failed in xfer_conn");
- return -1;
- }
-
- if (other == peer)
- ret = 1; /* bgp_establish specific code when xfer_conn happens. */
-
- /* Reset capability open status flag. */
- if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
- SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
-
- /* Clear start timer value to default. */
- peer->v_start = BGP_INIT_START_TIMER;
-
- /* Increment established count. */
- peer->established++;
- bgp_fsm_change_status (peer, Established);
-
- /* bgp log-neighbor-changes of neighbor Up */
- if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
- {
- struct vrf *vrf = vrf_lookup_by_id (peer->bgp->vrf_id);
- zlog_info ("%%ADJCHANGE: neighbor %s(%s) in vrf %s Up",
- peer->host,
- (peer->hostname) ? peer->hostname : "Unknown",
- vrf ? ((vrf->vrf_id != VRF_DEFAULT ) ? vrf->name : "Default") : "");
- }
- /* assign update-group/subgroup */
- update_group_adjust_peer_afs(peer);
-
- /* graceful restart */
- UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
- for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++)
- {
- if (peer->afc_nego[afi][safi]
- && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
- && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
- {
- if (peer->nsf[afi][safi]
- && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
- bgp_clear_stale_route (peer, afi, safi);
-
- peer->nsf[afi][safi] = 1;
- nsf_af_count++;
- }
- else
- {
- if (peer->nsf[afi][safi])
- bgp_clear_stale_route (peer, afi, safi);
- peer->nsf[afi][safi] = 0;
- }
- }
-
- if (nsf_af_count)
- SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
- else
- {
- UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
- if (peer->t_gr_stale)
- {
- BGP_TIMER_OFF (peer->t_gr_stale);
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
+ afi_t afi;
+ safi_t safi;
+ int nsf_af_count = 0;
+ int ret = 0;
+ struct peer *other;
+
+ other = peer->doppelganger;
+ peer = peer_xfer_conn(peer);
+ if (!peer) {
+ zlog_err("%%Neighbor failed in xfer_conn");
+ return -1;
}
- }
- if (peer->t_gr_restart)
- {
- BGP_TIMER_OFF (peer->t_gr_restart);
- if (bgp_debug_neighbor_events(peer))
- zlog_debug ("%s graceful restart timer stopped", peer->host);
- }
+ if (other == peer)
+ ret =
+ 1; /* bgp_establish specific code when xfer_conn
+ happens. */
+
+ /* Reset capability open status flag. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
+ SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
+
+ /* Clear start timer value to default. */
+ peer->v_start = BGP_INIT_START_TIMER;
+
+ /* Increment established count. */
+ peer->established++;
+ bgp_fsm_change_status(peer, Established);
+
+ /* bgp log-neighbor-changes of neighbor Up */
+ if (bgp_flag_check(peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
+ struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
+ zlog_info("%%ADJCHANGE: neighbor %s(%s) in vrf %s Up",
+ peer->host,
+ (peer->hostname) ? peer->hostname : "Unknown",
+ vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
+ : "Default")
+ : "");
+ }
+ /* assign update-group/subgroup */
+ update_group_adjust_peer_afs(peer);
+
+ /* graceful restart */
+ UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) {
+ if (peer->afc_nego[afi][safi]
+ && CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV)
+ && CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_RCV)) {
+ if (peer->nsf[afi][safi]
+ && !CHECK_FLAG(
+ peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV))
+ bgp_clear_stale_route(peer, afi, safi);
+
+ peer->nsf[afi][safi] = 1;
+ nsf_af_count++;
+ } else {
+ if (peer->nsf[afi][safi])
+ bgp_clear_stale_route(peer, afi, safi);
+ peer->nsf[afi][safi] = 0;
+ }
+ }
+
+ if (nsf_af_count)
+ SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
+ else {
+ UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
+ if (peer->t_gr_stale) {
+ BGP_TIMER_OFF(peer->t_gr_stale);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s graceful restart stalepath timer stopped",
+ peer->host);
+ }
+ }
- hook_call(peer_established, peer);
+ if (peer->t_gr_restart) {
+ BGP_TIMER_OFF(peer->t_gr_restart);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s graceful restart timer stopped",
+ peer->host);
+ }
- /* Reset uptime, send keepalive, send current table. */
- peer->uptime = bgp_clock ();
+ hook_call(peer_established, peer);
+
+ /* Reset uptime, send keepalive, send current table. */
+ peer->uptime = bgp_clock();
+
+ /* Send route-refresh when ORF is enabled */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ if (CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV)) {
+ if (CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_RCV))
+ bgp_route_refresh_send(
+ peer, afi, safi,
+ ORF_TYPE_PREFIX,
+ REFRESH_IMMEDIATE, 0);
+ else if (
+ CHECK_FLAG(
+ peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
+ bgp_route_refresh_send(
+ peer, afi, safi,
+ ORF_TYPE_PREFIX_OLD,
+ REFRESH_IMMEDIATE, 0);
+ }
+
+ /* First update is deferred until ORF or ROUTE-REFRESH is received */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ if (CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV))
+ if (CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV)
+ || CHECK_FLAG(
+ peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
+ SET_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_ORF_WAIT_REFRESH);
+
+ bgp_announce_peer(peer);
+
+ /* Start the route advertisement timer to send updates to the peer - if
+ * BGP
+ * is not in read-only mode. If it is, the timer will be started at the
+ * end
+ * of read-only mode.
+ */
+ if (!bgp_update_delay_active(peer->bgp)) {
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
+ }
- /* Send route-refresh when ORF is enabled */
- for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
- if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
- {
- if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
- bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
- REFRESH_IMMEDIATE, 0);
- else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
- bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
- REFRESH_IMMEDIATE, 0);
+ if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "[Event] Deleting stub connection for peer %s",
+ peer->host);
+
+ if (peer->doppelganger->status > Active)
+ bgp_notify_send(peer->doppelganger, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ else
+ peer_delete(peer->doppelganger);
}
- /* First update is deferred until ORF or ROUTE-REFRESH is received */
- for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
- for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
- if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
- if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
- SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
-
- bgp_announce_peer (peer);
-
- /* Start the route advertisement timer to send updates to the peer - if BGP
- * is not in read-only mode. If it is, the timer will be started at the end
- * of read-only mode.
- */
- if (!bgp_update_delay_active(peer->bgp))
- {
- BGP_TIMER_OFF(peer->t_routeadv);
- BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 0);
- }
-
- if (peer->doppelganger && (peer->doppelganger->status != Deleted))
- {
- if (bgp_debug_neighbor_events(peer))
- zlog_debug("[Event] Deleting stub connection for peer %s", peer->host);
-
- if (peer->doppelganger->status > Active)
- bgp_notify_send (peer->doppelganger, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
- else
- peer_delete(peer->doppelganger);
- }
-
- bgp_bfd_register_peer(peer);
- return ret;
+ bgp_bfd_register_peer(peer);
+ return ret;
}
/* Keepalive packet is received. */
-static int
-bgp_fsm_keepalive (struct peer *peer)
+static int bgp_fsm_keepalive(struct peer *peer)
{
- bgp_update_implicit_eors(peer);
+ bgp_update_implicit_eors(peer);
- /* peer count update */
- peer->keepalive_in++;
+ /* peer count update */
+ peer->keepalive_in++;
- BGP_TIMER_OFF (peer->t_holdtime);
- return 0;
+ BGP_TIMER_OFF(peer->t_holdtime);
+ return 0;
}
/* Update packet is received. */
-static int
-bgp_fsm_update (struct peer *peer)
+static int bgp_fsm_update(struct peer *peer)
{
- BGP_TIMER_OFF (peer->t_holdtime);
- return 0;
+ BGP_TIMER_OFF(peer->t_holdtime);
+ return 0;
}
/* This is empty event. */
-static int
-bgp_ignore (struct peer *peer)
+static int bgp_ignore(struct peer *peer)
{
- zlog_err ("%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
- peer->host, bgp_event_str[peer->cur_event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- bgp_event_str[peer->last_event],
- bgp_event_str[peer->last_major_event], peer->fd);
- return 0;
+ zlog_err(
+ "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
+ peer->host, bgp_event_str[peer->cur_event],
+ lookup_msg(bgp_status_msg, peer->status, NULL),
+ bgp_event_str[peer->last_event],
+ bgp_event_str[peer->last_major_event], peer->fd);
+ return 0;
}
/* This is to handle unexpected events.. */
-static int
-bgp_fsm_exeption (struct peer *peer)
+static int bgp_fsm_exeption(struct peer *peer)
{
- zlog_err ("%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
- peer->host, bgp_event_str[peer->cur_event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- bgp_event_str[peer->last_event],
- bgp_event_str[peer->last_major_event], peer->fd);
- return(bgp_stop (peer));
+ zlog_err(
+ "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
+ peer->host, bgp_event_str[peer->cur_event],
+ lookup_msg(bgp_status_msg, peer->status, NULL),
+ bgp_event_str[peer->last_event],
+ bgp_event_str[peer->last_major_event], peer->fd);
+ return (bgp_stop(peer));
}
-void
-bgp_fsm_nht_update(struct peer *peer, int valid)
+void bgp_fsm_nht_update(struct peer *peer, int valid)
{
- if (!peer)
- return;
-
- switch (peer->status)
- {
- case Idle:
- if (valid)
- BGP_EVENT_ADD(peer, BGP_Start);
- break;
- case Connect:
- if (!valid)
- {
- BGP_TIMER_OFF(peer->t_connect);
- BGP_EVENT_ADD(peer, TCP_fatal_error);
+ if (!peer)
+ return;
+
+ switch (peer->status) {
+ case Idle:
+ if (valid)
+ BGP_EVENT_ADD(peer, BGP_Start);
+ break;
+ case Connect:
+ if (!valid) {
+ BGP_TIMER_OFF(peer->t_connect);
+ BGP_EVENT_ADD(peer, TCP_fatal_error);
+ }
+ break;
+ case Active:
+ if (valid) {
+ BGP_TIMER_OFF(peer->t_connect);
+ BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
+ }
+ break;
+ case OpenSent:
+ case OpenConfirm:
+ case Established:
+ if (!valid && (peer->gtsm_hops == 1))
+ BGP_EVENT_ADD(peer, TCP_fatal_error);
+ case Clearing:
+ case Deleted:
+ default:
+ break;
}
- break;
- case Active:
- if (valid)
- {
- BGP_TIMER_OFF(peer->t_connect);
- BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
- }
- break;
- case OpenSent:
- case OpenConfirm:
- case Established:
- if (!valid && (peer->gtsm_hops == 1))
- BGP_EVENT_ADD(peer, TCP_fatal_error);
- case Clearing:
- case Deleted:
- default:
- break;
- }
}
/* Finite State Machine structure */
static const struct {
- int (*func) (struct peer *);
- int next_state;
-} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
-{
- {
- /* Idle state: In Idle state, all events other than BGP_Start is
- ignored. With BGP_Start event, finite state machine calls
- bgp_start(). */
- {bgp_start, Connect}, /* BGP_Start */
- {bgp_stop, Idle}, /* BGP_Stop */
- {bgp_stop, Idle}, /* TCP_connection_open */
- {bgp_stop, Idle}, /* TCP_connection_closed */
- {bgp_ignore, Idle}, /* TCP_connection_open_failed */
- {bgp_stop, Idle}, /* TCP_fatal_error */
- {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
- {bgp_ignore, Idle}, /* Hold_Timer_expired */
- {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
- {bgp_ignore, Idle}, /* Receive_OPEN_message */
- {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
- {bgp_ignore, Idle}, /* Receive_UPDATE_message */
- {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
- {bgp_ignore, Idle}, /* Clearing_Completed */
- },
- {
- /* Connect */
- {bgp_ignore, Connect}, /* BGP_Start */
- {bgp_stop, Idle}, /* BGP_Stop */
- {bgp_connect_success, OpenSent}, /* TCP_connection_open */
- {bgp_stop, Idle}, /* TCP_connection_closed */
- {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
- {bgp_connect_fail, Idle}, /* TCP_fatal_error */
- {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
- {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
- {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
- {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
- {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
- {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
- {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
- {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
- },
- {
- /* Active, */
- {bgp_ignore, Active}, /* BGP_Start */
- {bgp_stop, Idle}, /* BGP_Stop */
- {bgp_connect_success, OpenSent}, /* TCP_connection_open */
- {bgp_stop, Idle}, /* TCP_connection_closed */
- {bgp_ignore, Active}, /* TCP_connection_open_failed */
- {bgp_fsm_exeption, Idle}, /* TCP_fatal_error */
- {bgp_start, Connect}, /* ConnectRetry_timer_expired */
- {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
- {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
- {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
- {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
- {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
- {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */
- {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
- },
- {
- /* OpenSent, */
- {bgp_ignore, OpenSent}, /* BGP_Start */
- {bgp_stop, Idle}, /* BGP_Stop */
- {bgp_stop, Active}, /* TCP_connection_open */
- {bgp_stop, Active}, /* TCP_connection_closed */
- {bgp_stop, Active}, /* TCP_connection_open_failed */
- {bgp_stop, Active}, /* TCP_fatal_error */
- {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
- {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
- {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
- {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
- {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
- {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
- {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
- {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
- },
- {
- /* OpenConfirm, */
- {bgp_ignore, OpenConfirm}, /* BGP_Start */
- {bgp_stop, Idle}, /* BGP_Stop */
- {bgp_stop, Idle}, /* TCP_connection_open */
- {bgp_stop, Idle}, /* TCP_connection_closed */
- {bgp_stop, Idle}, /* TCP_connection_open_failed */
- {bgp_stop, Idle}, /* TCP_fatal_error */
- {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
- {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
- {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
- {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
- {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
- {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
- {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
- {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
- },
- {
- /* Established, */
- {bgp_ignore, Established}, /* BGP_Start */
- {bgp_stop, Clearing}, /* BGP_Stop */
- {bgp_stop, Clearing}, /* TCP_connection_open */
- {bgp_stop, Clearing}, /* TCP_connection_closed */
- {bgp_stop, Clearing}, /* TCP_connection_open_failed */
- {bgp_stop, Clearing}, /* TCP_fatal_error */
- {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
- {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
- {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
- {bgp_stop, Clearing}, /* Receive_OPEN_message */
- {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
- {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
- {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
- {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
- },
- {
- /* Clearing, */
- {bgp_ignore, Clearing}, /* BGP_Start */
- {bgp_stop, Clearing}, /* BGP_Stop */
- {bgp_stop, Clearing}, /* TCP_connection_open */
- {bgp_stop, Clearing}, /* TCP_connection_closed */
- {bgp_stop, Clearing}, /* TCP_connection_open_failed */
- {bgp_stop, Clearing}, /* TCP_fatal_error */
- {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
- {bgp_stop, Clearing}, /* Hold_Timer_expired */
- {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
- {bgp_stop, Clearing}, /* Receive_OPEN_message */
- {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
- {bgp_stop, Clearing}, /* Receive_UPDATE_message */
- {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
- {bgp_clearing_completed, Idle}, /* Clearing_Completed */
- },
- {
- /* Deleted, */
- {bgp_ignore, Deleted}, /* BGP_Start */
- {bgp_ignore, Deleted}, /* BGP_Stop */
- {bgp_ignore, Deleted}, /* TCP_connection_open */
- {bgp_ignore, Deleted}, /* TCP_connection_closed */
- {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
- {bgp_ignore, Deleted}, /* TCP_fatal_error */
- {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
- {bgp_ignore, Deleted}, /* Hold_Timer_expired */
- {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
- {bgp_ignore, Deleted}, /* Receive_OPEN_message */
- {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
- {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
- {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
- {bgp_ignore, Deleted}, /* Clearing_Completed */
- },
+ int (*func)(struct peer *);
+ int next_state;
+} FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = {
+ {
+ /* Idle state: In Idle state, all events other than BGP_Start is
+ ignored. With BGP_Start event, finite state machine calls
+ bgp_start(). */
+ {bgp_start, Connect}, /* BGP_Start */
+ {bgp_stop, Idle}, /* BGP_Stop */
+ {bgp_stop, Idle}, /* TCP_connection_open */
+ {bgp_stop, Idle}, /* TCP_connection_closed */
+ {bgp_ignore, Idle}, /* TCP_connection_open_failed */
+ {bgp_stop, Idle}, /* TCP_fatal_error */
+ {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
+ {bgp_ignore, Idle}, /* Hold_Timer_expired */
+ {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
+ {bgp_ignore, Idle}, /* Receive_OPEN_message */
+ {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
+ {bgp_ignore, Idle}, /* Receive_UPDATE_message */
+ {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* Connect */
+ {bgp_ignore, Connect}, /* BGP_Start */
+ {bgp_stop, Idle}, /* BGP_Stop */
+ {bgp_connect_success, OpenSent}, /* TCP_connection_open */
+ {bgp_stop, Idle}, /* TCP_connection_closed */
+ {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
+ {bgp_connect_fail, Idle}, /* TCP_fatal_error */
+ {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
+ {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
+ {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
+ {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
+ {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
+ {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
+ {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* Active, */
+ {bgp_ignore, Active}, /* BGP_Start */
+ {bgp_stop, Idle}, /* BGP_Stop */
+ {bgp_connect_success, OpenSent}, /* TCP_connection_open */
+ {bgp_stop, Idle}, /* TCP_connection_closed */
+ {bgp_ignore, Active}, /* TCP_connection_open_failed */
+ {bgp_fsm_exeption, Idle}, /* TCP_fatal_error */
+ {bgp_start, Connect}, /* ConnectRetry_timer_expired */
+ {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
+ {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
+ {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
+ {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
+ {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
+ {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* OpenSent, */
+ {bgp_ignore, OpenSent}, /* BGP_Start */
+ {bgp_stop, Idle}, /* BGP_Stop */
+ {bgp_stop, Active}, /* TCP_connection_open */
+ {bgp_stop, Active}, /* TCP_connection_closed */
+ {bgp_stop, Active}, /* TCP_connection_open_failed */
+ {bgp_stop, Active}, /* TCP_fatal_error */
+ {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
+ {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
+ {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
+ {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
+ {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
+ {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
+ {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* OpenConfirm, */
+ {bgp_ignore, OpenConfirm}, /* BGP_Start */
+ {bgp_stop, Idle}, /* BGP_Stop */
+ {bgp_stop, Idle}, /* TCP_connection_open */
+ {bgp_stop, Idle}, /* TCP_connection_closed */
+ {bgp_stop, Idle}, /* TCP_connection_open_failed */
+ {bgp_stop, Idle}, /* TCP_fatal_error */
+ {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
+ {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
+ {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
+ {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
+ {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
+ {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
+ {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* Established, */
+ {bgp_ignore, Established}, /* BGP_Start */
+ {bgp_stop, Clearing}, /* BGP_Stop */
+ {bgp_stop, Clearing}, /* TCP_connection_open */
+ {bgp_stop, Clearing}, /* TCP_connection_closed */
+ {bgp_stop, Clearing}, /* TCP_connection_open_failed */
+ {bgp_stop, Clearing}, /* TCP_fatal_error */
+ {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
+ {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
+ {bgp_fsm_keepalive_expire,
+ Established}, /* KeepAlive_timer_expired */
+ {bgp_stop, Clearing}, /* Receive_OPEN_message */
+ {bgp_fsm_keepalive,
+ Established}, /* Receive_KEEPALIVE_message */
+ {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
+ {bgp_stop_with_error,
+ Clearing}, /* Receive_NOTIFICATION_message */
+ {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* Clearing, */
+ {bgp_ignore, Clearing}, /* BGP_Start */
+ {bgp_stop, Clearing}, /* BGP_Stop */
+ {bgp_stop, Clearing}, /* TCP_connection_open */
+ {bgp_stop, Clearing}, /* TCP_connection_closed */
+ {bgp_stop, Clearing}, /* TCP_connection_open_failed */
+ {bgp_stop, Clearing}, /* TCP_fatal_error */
+ {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
+ {bgp_stop, Clearing}, /* Hold_Timer_expired */
+ {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
+ {bgp_stop, Clearing}, /* Receive_OPEN_message */
+ {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
+ {bgp_stop, Clearing}, /* Receive_UPDATE_message */
+ {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
+ {bgp_clearing_completed, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* Deleted, */
+ {bgp_ignore, Deleted}, /* BGP_Start */
+ {bgp_ignore, Deleted}, /* BGP_Stop */
+ {bgp_ignore, Deleted}, /* TCP_connection_open */
+ {bgp_ignore, Deleted}, /* TCP_connection_closed */
+ {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
+ {bgp_ignore, Deleted}, /* TCP_fatal_error */
+ {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
+ {bgp_ignore, Deleted}, /* Hold_Timer_expired */
+ {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
+ {bgp_ignore, Deleted}, /* Receive_OPEN_message */
+ {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
+ {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
+ {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Deleted}, /* Clearing_Completed */
+ },
};
/* Execute event process. */
-int
-bgp_event (struct thread *thread)
+int bgp_event(struct thread *thread)
{
- int event;
- struct peer *peer;
- int ret;
+ int event;
+ struct peer *peer;
+ int ret;
- peer = THREAD_ARG (thread);
- event = THREAD_VAL (thread);
+ peer = THREAD_ARG(thread);
+ event = THREAD_VAL(thread);
- ret = bgp_event_update(peer, event);
+ ret = bgp_event_update(peer, event);
- return (ret);
+ return (ret);
}
-int
-bgp_event_update (struct peer *peer, int event)
+int bgp_event_update(struct peer *peer, int event)
{
- int next;
- int ret = 0;
- struct peer *other;
- int passive_conn = 0;
- int dyn_nbr;
-
- other = peer->doppelganger;
- passive_conn = (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0;
- dyn_nbr = peer_dynamic_neighbor(peer);
-
- /* Logging this event. */
- next = FSM [peer->status -1][event - 1].next_state;
-
- if (bgp_debug_neighbor_events(peer) && peer->status != next)
- zlog_debug ("%s [FSM] %s (%s->%s), fd %d", peer->host,
- bgp_event_str[event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- lookup_msg(bgp_status_msg, next, NULL), peer->fd);
-
- peer->last_event = peer->cur_event;
- peer->cur_event = event;
-
- /* Call function. */
- if (FSM [peer->status -1][event - 1].func)
- ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
-
- /* When function do not want proceed next job return -1. */
- if (ret >= 0)
- {
- if (ret == 1 && next == Established)
- {
- /* The case when doppelganger swap accurred in bgp_establish.
- Update the peer pointer accordingly */
- peer = other;
- }
-
- /* If status is changed. */
- if (next != peer->status)
- bgp_fsm_change_status (peer, next);
-
- /* Make sure timer is set. */
- bgp_timer_set (peer);
-
- }
- else if (!dyn_nbr && !passive_conn && peer->bgp)
- {
- /* If we got a return value of -1, that means there was an error, restart
- * the FSM. If the peer structure was deleted
- */
- zlog_err ("%s [FSM] Failure handling event %s in state %s, "
- "prior events %s, %s, fd %d",
- peer->host, bgp_event_str[peer->cur_event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- bgp_event_str[peer->last_event],
- bgp_event_str[peer->last_major_event], peer->fd);
- bgp_stop (peer);
- bgp_fsm_change_status(peer, Idle);
- bgp_timer_set(peer);
- }
- return ret;
+ int next;
+ int ret = 0;
+ struct peer *other;
+ int passive_conn = 0;
+ int dyn_nbr;
+
+ other = peer->doppelganger;
+ passive_conn =
+ (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0;
+ dyn_nbr = peer_dynamic_neighbor(peer);
+
+ /* Logging this event. */
+ next = FSM[peer->status - 1][event - 1].next_state;
+
+ if (bgp_debug_neighbor_events(peer) && peer->status != next)
+ zlog_debug("%s [FSM] %s (%s->%s), fd %d", peer->host,
+ bgp_event_str[event],
+ lookup_msg(bgp_status_msg, peer->status, NULL),
+ lookup_msg(bgp_status_msg, next, NULL), peer->fd);
+
+ peer->last_event = peer->cur_event;
+ peer->cur_event = event;
+
+ /* Call function. */
+ if (FSM[peer->status - 1][event - 1].func)
+ ret = (*(FSM[peer->status - 1][event - 1].func))(peer);
+
+ /* When function do not want proceed next job return -1. */
+ if (ret >= 0) {
+ if (ret == 1 && next == Established) {
+ /* The case when doppelganger swap accurred in
+ bgp_establish.
+ Update the peer pointer accordingly */
+ peer = other;
+ }
+
+ /* If status is changed. */
+ if (next != peer->status)
+ bgp_fsm_change_status(peer, next);
+
+ /* Make sure timer is set. */
+ bgp_timer_set(peer);
+
+ } else if (!dyn_nbr && !passive_conn && peer->bgp) {
+ /* If we got a return value of -1, that means there was an
+ * error, restart
+ * the FSM. If the peer structure was deleted
+ */
+ zlog_err(
+ "%s [FSM] Failure handling event %s in state %s, "
+ "prior events %s, %s, fd %d",
+ peer->host, bgp_event_str[peer->cur_event],
+ lookup_msg(bgp_status_msg, peer->status, NULL),
+ bgp_event_str[peer->last_event],
+ bgp_event_str[peer->last_major_event], peer->fd);
+ bgp_stop(peer);
+ bgp_fsm_change_status(peer, Idle);
+ bgp_timer_set(peer);
+ }
+ return ret;
}