back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_fsm.c (source / functions) Hit Total Coverage
Test: test_bgp_set_aspath_replace.py::BGPSetAspathReplace Lines: 525 1325 39.6 %
Date: 2023-02-24 18:37:49 Functions: 28 70 40.0 %

          Line data    Source code
       1             : /* BGP-4 Finite State Machine
       2             :  * From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
       3             :  * Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "linklist.h"
      25             : #include "prefix.h"
      26             : #include "sockunion.h"
      27             : #include "thread.h"
      28             : #include "log.h"
      29             : #include "stream.h"
      30             : #include "ringbuf.h"
      31             : #include "memory.h"
      32             : #include "plist.h"
      33             : #include "workqueue.h"
      34             : #include "queue.h"
      35             : #include "filter.h"
      36             : #include "command.h"
      37             : #include "lib_errors.h"
      38             : #include "zclient.h"
      39             : #include "lib/json.h"
      40             : #include "bgpd/bgpd.h"
      41             : #include "bgpd/bgp_attr.h"
      42             : #include "bgpd/bgp_debug.h"
      43             : #include "bgpd/bgp_errors.h"
      44             : #include "bgpd/bgp_fsm.h"
      45             : #include "bgpd/bgp_packet.h"
      46             : #include "bgpd/bgp_network.h"
      47             : #include "bgpd/bgp_route.h"
      48             : #include "bgpd/bgp_dump.h"
      49             : #include "bgpd/bgp_open.h"
      50             : #include "bgpd/bgp_advertise.h"
      51             : #include "bgpd/bgp_community.h"
      52             : #include "bgpd/bgp_updgrp.h"
      53             : #include "bgpd/bgp_nht.h"
      54             : #include "bgpd/bgp_bfd.h"
      55             : #include "bgpd/bgp_memory.h"
      56             : #include "bgpd/bgp_keepalives.h"
      57             : #include "bgpd/bgp_io.h"
      58             : #include "bgpd/bgp_zebra.h"
      59             : #include "bgpd/bgp_vty.h"
      60             : 
      61           4 : DEFINE_HOOK(peer_backward_transition, (struct peer * peer), (peer));
      62          82 : DEFINE_HOOK(peer_status_changed, (struct peer * peer), (peer));
      63             : 
      64             : enum bgp_fsm_state_progress {
      65             :         BGP_FSM_FAILURE_AND_DELETE = -2,
      66             :         BGP_FSM_FAILURE = -1,
      67             :         BGP_FSM_SUCCESS = 0,
      68             :         BGP_FSM_SUCCESS_STATE_TRANSFER = 1,
      69             : };
      70             : 
      71             : /* Definition of display strings corresponding to FSM events. This should be
      72             :  * kept consistent with the events defined in bgpd.h
      73             :  */
      74             : static const char *const bgp_event_str[] = {
      75             :         NULL,
      76             :         "BGP_Start",
      77             :         "BGP_Stop",
      78             :         "TCP_connection_open",
      79             :         "TCP_connection_open_w_delay",
      80             :         "TCP_connection_closed",
      81             :         "TCP_connection_open_failed",
      82             :         "TCP_fatal_error",
      83             :         "ConnectRetry_timer_expired",
      84             :         "Hold_Timer_expired",
      85             :         "KeepAlive_timer_expired",
      86             :         "DelayOpen_timer_expired",
      87             :         "Receive_OPEN_message",
      88             :         "Receive_KEEPALIVE_message",
      89             :         "Receive_UPDATE_message",
      90             :         "Receive_NOTIFICATION_message",
      91             :         "Clearing_Completed",
      92             : };
      93             : 
      94             : /* BGP FSM (finite state machine) has three types of functions.  Type
      95             :    one is thread functions.  Type two is event functions.  Type three
      96             :    is FSM functions.  Timer functions are set by bgp_timer_set
      97             :    function. */
      98             : 
      99             : /* BGP event function. */
     100             : void bgp_event(struct thread *);
     101             : 
     102             : /* BGP thread functions. */
     103             : static void bgp_start_timer(struct thread *);
     104             : static void bgp_connect_timer(struct thread *);
     105             : static void bgp_holdtime_timer(struct thread *);
     106             : static void bgp_delayopen_timer(struct thread *);
     107             : 
     108             : /* BGP FSM functions. */
     109             : static enum bgp_fsm_state_progress bgp_start(struct peer *);
     110             : 
     111             : /* Register peer with NHT */
     112          11 : int bgp_peer_reg_with_nht(struct peer *peer)
     113             : {
     114          11 :         int connected = 0;
     115             : 
     116          11 :         if (peer->sort == BGP_PEER_EBGP && peer->ttl == BGP_DEFAULT_TTL
     117          11 :             && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
     118          11 :             && !CHECK_FLAG(peer->bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
     119          11 :                 connected = 1;
     120             : 
     121          11 :         return bgp_find_or_add_nexthop(
     122          11 :                 peer->bgp, peer->bgp, family2afi(peer->su.sa.sa_family),
     123             :                 SAFI_UNICAST, NULL, peer, connected, NULL);
     124             : }
     125             : 
     126           2 : static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
     127             : {
     128             :         /* Copy stats over. These are only the pre-established state stats */
     129           2 :         peer_dst->open_in += peer_src->open_in;
     130           2 :         peer_dst->open_out += peer_src->open_out;
     131           2 :         peer_dst->keepalive_in += peer_src->keepalive_in;
     132           2 :         peer_dst->keepalive_out += peer_src->keepalive_out;
     133           2 :         peer_dst->notify_in += peer_src->notify_in;
     134           2 :         peer_dst->notify_out += peer_src->notify_out;
     135           2 :         peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in;
     136           2 :         peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out;
     137           2 : }
     138             : 
     139           4 : static struct peer *peer_xfer_conn(struct peer *from_peer)
     140             : {
     141           4 :         struct peer *peer;
     142           4 :         afi_t afi;
     143           4 :         safi_t safi;
     144           4 :         int fd;
     145           4 :         enum bgp_fsm_status status, pstatus;
     146           4 :         enum bgp_fsm_events last_evt, last_maj_evt;
     147             : 
     148           4 :         assert(from_peer != NULL);
     149             : 
     150           4 :         peer = from_peer->doppelganger;
     151             : 
     152           4 :         if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
     153             :                 return from_peer;
     154             : 
     155             :         /*
     156             :          * Let's check that we are not going to loose known configuration
     157             :          * state based upon doppelganger rules.
     158             :          */
     159          50 :         FOREACH_AFI_SAFI (afi, safi) {
     160          42 :                 if (from_peer->afc[afi][safi] != peer->afc[afi][safi]) {
     161           0 :                         flog_err(
     162             :                                 EC_BGP_DOPPELGANGER_CONFIG,
     163             :                                 "from_peer->afc[%d][%d] is not the same as what we are overwriting",
     164             :                                 afi, safi);
     165           0 :                         return NULL;
     166             :                 }
     167             :         }
     168             : 
     169           2 :         if (bgp_debug_neighbor_events(peer))
     170           0 :                 zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
     171             :                            from_peer->host, from_peer, from_peer->fd, peer,
     172             :                            peer->fd);
     173             : 
     174           2 :         bgp_writes_off(peer);
     175           2 :         bgp_reads_off(peer);
     176           2 :         bgp_writes_off(from_peer);
     177           2 :         bgp_reads_off(from_peer);
     178             : 
     179             :         /*
     180             :          * Before exchanging FD remove doppelganger from
     181             :          * keepalive peer hash. It could be possible conf peer
     182             :          * fd is set to -1. If blocked on lock then keepalive
     183             :          * thread can access peer pointer with fd -1.
     184             :          */
     185           2 :         bgp_keepalives_off(from_peer);
     186             : 
     187           2 :         THREAD_OFF(peer->t_routeadv);
     188           2 :         THREAD_OFF(peer->t_connect);
     189           2 :         THREAD_OFF(peer->t_delayopen);
     190           2 :         THREAD_OFF(peer->t_connect_check_r);
     191           2 :         THREAD_OFF(peer->t_connect_check_w);
     192           2 :         THREAD_OFF(from_peer->t_routeadv);
     193           2 :         THREAD_OFF(from_peer->t_connect);
     194           2 :         THREAD_OFF(from_peer->t_delayopen);
     195           2 :         THREAD_OFF(from_peer->t_connect_check_r);
     196           2 :         THREAD_OFF(from_peer->t_connect_check_w);
     197           2 :         THREAD_OFF(from_peer->t_process_packet);
     198             : 
     199             :         /*
     200             :          * At this point in time, it is possible that there are packets pending
     201             :          * on various buffers. Those need to be transferred or dropped,
     202             :          * otherwise we'll get spurious failures during session establishment.
     203             :          */
     204           4 :         frr_with_mutex (&peer->io_mtx, &from_peer->io_mtx) {
     205           2 :                 fd = peer->fd;
     206           2 :                 peer->fd = from_peer->fd;
     207           2 :                 from_peer->fd = fd;
     208             : 
     209           2 :                 stream_fifo_clean(peer->ibuf);
     210           2 :                 stream_fifo_clean(peer->obuf);
     211             : 
     212             :                 /*
     213             :                  * this should never happen, since bgp_process_packet() is the
     214             :                  * only task that sets and unsets the current packet and it
     215             :                  * runs in our pthread.
     216             :                  */
     217           2 :                 if (peer->curr) {
     218           0 :                         flog_err(
     219             :                                 EC_BGP_PKT_PROCESS,
     220             :                                 "[%s] Dropping pending packet on connection transfer:",
     221             :                                 peer->host);
     222             :                         /* there used to be a bgp_packet_dump call here, but
     223             :                          * that's extremely confusing since there's no way to
     224             :                          * identify the packet in MRT dumps or BMP as dropped
     225             :                          * due to connection transfer.
     226             :                          */
     227           0 :                         stream_free(peer->curr);
     228           0 :                         peer->curr = NULL;
     229             :                 }
     230             : 
     231             :                 // copy each packet from old peer's output queue to new peer
     232           2 :                 while (from_peer->obuf->head)
     233           0 :                         stream_fifo_push(peer->obuf,
     234             :                                          stream_fifo_pop(from_peer->obuf));
     235             : 
     236             :                 // copy each packet from old peer's input queue to new peer
     237           2 :                 while (from_peer->ibuf->head)
     238           0 :                         stream_fifo_push(peer->ibuf,
     239             :                                          stream_fifo_pop(from_peer->ibuf));
     240             : 
     241           2 :                 ringbuf_wipe(peer->ibuf_work);
     242           2 :                 ringbuf_copy(peer->ibuf_work, from_peer->ibuf_work,
     243             :                              ringbuf_remain(from_peer->ibuf_work));
     244             :         }
     245             : 
     246           2 :         peer->as = from_peer->as;
     247           2 :         peer->v_holdtime = from_peer->v_holdtime;
     248           2 :         peer->v_keepalive = from_peer->v_keepalive;
     249           2 :         peer->v_routeadv = from_peer->v_routeadv;
     250           2 :         peer->v_delayopen = from_peer->v_delayopen;
     251           2 :         peer->v_gr_restart = from_peer->v_gr_restart;
     252           2 :         peer->cap = from_peer->cap;
     253           2 :         peer->remote_role = from_peer->remote_role;
     254           2 :         status = peer->status;
     255           2 :         pstatus = peer->ostatus;
     256           2 :         last_evt = peer->last_event;
     257           2 :         last_maj_evt = peer->last_major_event;
     258           2 :         peer->status = from_peer->status;
     259           2 :         peer->ostatus = from_peer->ostatus;
     260           2 :         peer->last_event = from_peer->last_event;
     261           2 :         peer->last_major_event = from_peer->last_major_event;
     262           2 :         from_peer->status = status;
     263           2 :         from_peer->ostatus = pstatus;
     264           2 :         from_peer->last_event = last_evt;
     265           2 :         from_peer->last_major_event = last_maj_evt;
     266           2 :         peer->remote_id = from_peer->remote_id;
     267           2 :         peer->last_reset = from_peer->last_reset;
     268           2 :         peer->max_packet_size = from_peer->max_packet_size;
     269             : 
     270           9 :         BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
     271             :                                                           peer->bgp->peer);
     272             : 
     273           2 :         if (bgp_peer_gr_mode_get(peer) == PEER_DISABLE) {
     274             : 
     275           0 :                 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
     276             : 
     277           0 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
     278           0 :                         peer_nsf_stop(peer);
     279             :                 }
     280             :         }
     281             : 
     282           2 :         if (peer->hostname) {
     283           0 :                 XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
     284           0 :                 peer->hostname = NULL;
     285             :         }
     286           2 :         if (from_peer->hostname != NULL) {
     287           2 :                 peer->hostname = from_peer->hostname;
     288           2 :                 from_peer->hostname = NULL;
     289             :         }
     290             : 
     291           2 :         if (peer->domainname) {
     292           0 :                 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
     293           0 :                 peer->domainname = NULL;
     294             :         }
     295           2 :         if (from_peer->domainname != NULL) {
     296           0 :                 peer->domainname = from_peer->domainname;
     297           0 :                 from_peer->domainname = NULL;
     298             :         }
     299             : 
     300          50 :         FOREACH_AFI_SAFI (afi, safi) {
     301          42 :                 peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi];
     302          42 :                 peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
     303          42 :                 peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi];
     304          42 :                 peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi];
     305          42 :                 peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
     306          42 :                 peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
     307          42 :                 peer->llgr[afi][safi] = from_peer->llgr[afi][safi];
     308             :         }
     309             : 
     310           2 :         if (bgp_getsockname(peer) < 0) {
     311           0 :                 flog_err(
     312             :                         EC_LIB_SOCKET,
     313             :                         "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
     314             :                         (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
     315             :                                  ? "accept"
     316             :                                  : ""),
     317             :                         peer->host, peer->fd, from_peer->fd);
     318           0 :                 BGP_EVENT_ADD(peer, BGP_Stop);
     319           0 :                 BGP_EVENT_ADD(from_peer, BGP_Stop);
     320           0 :                 return NULL;
     321             :         }
     322           2 :         if (from_peer->status > Active) {
     323           0 :                 if (bgp_getsockname(from_peer) < 0) {
     324           0 :                         flog_err(
     325             :                                 EC_LIB_SOCKET,
     326             :                                 "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
     327             : 
     328             :                                 (CHECK_FLAG(from_peer->sflags,
     329             :                                             PEER_STATUS_ACCEPT_PEER)
     330             :                                          ? "accept"
     331             :                                          : ""),
     332             :                                 from_peer->host, from_peer->fd, peer->fd);
     333           0 :                         bgp_stop(from_peer);
     334           0 :                         from_peer = NULL;
     335             :                 }
     336             :         }
     337             : 
     338             : 
     339             :         // Note: peer_xfer_stats() must be called with I/O turned OFF
     340           0 :         if (from_peer)
     341           2 :                 peer_xfer_stats(peer, from_peer);
     342             : 
     343             :         /* Register peer for NHT. This is to allow RAs to be enabled when
     344             :          * needed, even on a passive connection.
     345             :          */
     346           2 :         bgp_peer_reg_with_nht(peer);
     347           2 :         if (from_peer)
     348           2 :                 bgp_replace_nexthop_by_peer(from_peer, peer);
     349             : 
     350           2 :         bgp_reads_on(peer);
     351           2 :         bgp_writes_on(peer);
     352           2 :         thread_add_event(bm->master, bgp_process_packet, peer, 0,
     353             :                          &peer->t_process_packet);
     354             : 
     355           2 :         return (peer);
     356             : }
     357             : 
     358             : /* Hook function called after bgp event is occered.  And vty's
     359             :    neighbor command invoke this function after making neighbor
     360             :    structure. */
     361          70 : void bgp_timer_set(struct peer *peer)
     362             : {
     363          70 :         afi_t afi;
     364          70 :         safi_t safi;
     365             : 
     366          70 :         switch (peer->status) {
     367          10 :         case Idle:
     368             :                 /* First entry point of peer's finite state machine.  In Idle
     369             :                    status start timer is on unless peer is shutdown or peer is
     370             :                    inactive.  All other timer must be turned off */
     371          10 :                 if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)
     372          10 :                     || peer->bgp->vrf_id == VRF_UNKNOWN) {
     373           0 :                         THREAD_OFF(peer->t_start);
     374             :                 } else {
     375          10 :                         BGP_TIMER_ON(peer->t_start, bgp_start_timer,
     376             :                                      peer->v_start);
     377             :                 }
     378          10 :                 THREAD_OFF(peer->t_connect);
     379          10 :                 THREAD_OFF(peer->t_holdtime);
     380          10 :                 bgp_keepalives_off(peer);
     381          10 :                 THREAD_OFF(peer->t_routeadv);
     382          10 :                 THREAD_OFF(peer->t_delayopen);
     383             :                 break;
     384             : 
     385           6 :         case Connect:
     386             :                 /* After start timer is expired, the peer moves to Connect
     387             :                    status.  Make sure start timer is off and connect timer is
     388             :                    on. */
     389           6 :                 THREAD_OFF(peer->t_start);
     390           6 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
     391           0 :                         BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
     392             :                                      (peer->v_delayopen + peer->v_connect));
     393             :                 else
     394           6 :                         BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
     395             :                                      peer->v_connect);
     396             : 
     397           6 :                 THREAD_OFF(peer->t_holdtime);
     398           6 :                 bgp_keepalives_off(peer);
     399           6 :                 THREAD_OFF(peer->t_routeadv);
     400             :                 break;
     401             : 
     402           3 :         case Active:
     403             :                 /* Active is waiting connection from remote peer.  And if
     404             :                    connect timer is expired, change status to Connect. */
     405           3 :                 THREAD_OFF(peer->t_start);
     406             :                 /* If peer is passive mode, do not set connect timer. */
     407           3 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)
     408           3 :                     || CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
     409           0 :                         THREAD_OFF(peer->t_connect);
     410             :                 } else {
     411           3 :                         if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
     412           0 :                                 BGP_TIMER_ON(
     413             :                                         peer->t_connect, bgp_connect_timer,
     414             :                                         (peer->v_delayopen + peer->v_connect));
     415             :                         else
     416           3 :                                 BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
     417             :                                              peer->v_connect);
     418             :                 }
     419           3 :                 THREAD_OFF(peer->t_holdtime);
     420           3 :                 bgp_keepalives_off(peer);
     421           3 :                 THREAD_OFF(peer->t_routeadv);
     422             :                 break;
     423             : 
     424           6 :         case OpenSent:
     425             :                 /* OpenSent status. */
     426           6 :                 THREAD_OFF(peer->t_start);
     427           6 :                 THREAD_OFF(peer->t_connect);
     428           6 :                 if (peer->v_holdtime != 0) {
     429           6 :                         BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
     430             :                                      peer->v_holdtime);
     431             :                 } else {
     432           0 :                         THREAD_OFF(peer->t_holdtime);
     433             :                 }
     434           6 :                 bgp_keepalives_off(peer);
     435           6 :                 THREAD_OFF(peer->t_routeadv);
     436           6 :                 THREAD_OFF(peer->t_delayopen);
     437             :                 break;
     438             : 
     439           4 :         case OpenConfirm:
     440             :                 /* OpenConfirm status. */
     441           4 :                 THREAD_OFF(peer->t_start);
     442           4 :                 THREAD_OFF(peer->t_connect);
     443             : 
     444             :                 /* If the negotiated Hold Time value is zero, then the Hold Time
     445             :                    timer and KeepAlive timers are not started. */
     446           4 :                 if (peer->v_holdtime == 0) {
     447           0 :                         THREAD_OFF(peer->t_holdtime);
     448           0 :                         bgp_keepalives_off(peer);
     449             :                 } else {
     450           4 :                         BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
     451             :                                      peer->v_holdtime);
     452           4 :                         bgp_keepalives_on(peer);
     453             :                 }
     454           4 :                 THREAD_OFF(peer->t_routeadv);
     455           4 :                 THREAD_OFF(peer->t_delayopen);
     456             :                 break;
     457             : 
     458          20 :         case Established:
     459             :                 /* In Established status start and connect timer is turned
     460             :                    off. */
     461          20 :                 THREAD_OFF(peer->t_start);
     462          20 :                 THREAD_OFF(peer->t_connect);
     463          20 :                 THREAD_OFF(peer->t_delayopen);
     464             : 
     465             :                 /* Same as OpenConfirm, if holdtime is zero then both holdtime
     466             :                    and keepalive must be turned off. */
     467          20 :                 if (peer->v_holdtime == 0) {
     468           0 :                         THREAD_OFF(peer->t_holdtime);
     469           0 :                         bgp_keepalives_off(peer);
     470             :                 } else {
     471          20 :                         BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
     472             :                                      peer->v_holdtime);
     473          20 :                         bgp_keepalives_on(peer);
     474             :                 }
     475             :                 break;
     476          19 :         case Deleted:
     477          19 :                 THREAD_OFF(peer->t_gr_restart);
     478          19 :                 THREAD_OFF(peer->t_gr_stale);
     479             : 
     480         475 :                 FOREACH_AFI_SAFI (afi, safi)
     481         399 :                         THREAD_OFF(peer->t_llgr_stale[afi][safi]);
     482             : 
     483          19 :                 THREAD_OFF(peer->t_pmax_restart);
     484          19 :                 THREAD_OFF(peer->t_refresh_stalepath);
     485             :         /* fallthru */
     486             :         case Clearing:
     487          21 :                 THREAD_OFF(peer->t_start);
     488          21 :                 THREAD_OFF(peer->t_connect);
     489          21 :                 THREAD_OFF(peer->t_holdtime);
     490          21 :                 bgp_keepalives_off(peer);
     491          21 :                 THREAD_OFF(peer->t_routeadv);
     492          21 :                 THREAD_OFF(peer->t_delayopen);
     493             :                 break;
     494           0 :         case BGP_STATUS_MAX:
     495           0 :                 flog_err(EC_LIB_DEVELOPMENT,
     496             :                          "BGP_STATUS_MAX while a legal state is not valid state for the FSM");
     497           0 :                 break;
     498             :         }
     499          70 : }
     500             : 
     501             : /* BGP start timer.  This function set BGP_Start event to thread value
     502             :    and process event. */
     503           3 : static void bgp_start_timer(struct thread *thread)
     504             : {
     505           3 :         struct peer *peer;
     506             : 
     507           3 :         peer = THREAD_ARG(thread);
     508             : 
     509           3 :         if (bgp_debug_neighbor_events(peer))
     510           0 :                 zlog_debug("%s [FSM] Timer (start timer expire).", peer->host);
     511             : 
     512           3 :         THREAD_VAL(thread) = BGP_Start;
     513           3 :         bgp_event(thread); /* bgp_event unlocks peer */
     514           3 : }
     515             : 
     516             : /* BGP connect retry timer. */
     517           0 : static void bgp_connect_timer(struct thread *thread)
     518             : {
     519           0 :         struct peer *peer;
     520             : 
     521           0 :         peer = THREAD_ARG(thread);
     522             : 
     523             :         /* stop the DelayOpenTimer if it is running */
     524           0 :         THREAD_OFF(peer->t_delayopen);
     525             : 
     526           0 :         assert(!peer->t_write);
     527           0 :         assert(!peer->t_read);
     528             : 
     529           0 :         if (bgp_debug_neighbor_events(peer))
     530           0 :                 zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
     531             : 
     532           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
     533           0 :                 bgp_stop(peer);
     534             :         else {
     535           0 :                 THREAD_VAL(thread) = ConnectRetry_timer_expired;
     536           0 :                 bgp_event(thread); /* bgp_event unlocks peer */
     537             :         }
     538           0 : }
     539             : 
     540             : /* BGP holdtime timer. */
     541           0 : static void bgp_holdtime_timer(struct thread *thread)
     542             : {
     543           0 :         atomic_size_t inq_count;
     544           0 :         struct peer *peer;
     545             : 
     546           0 :         peer = THREAD_ARG(thread);
     547             : 
     548           0 :         if (bgp_debug_neighbor_events(peer))
     549           0 :                 zlog_debug("%s [FSM] Timer (holdtime timer expire)",
     550             :                            peer->host);
     551             : 
     552             :         /*
     553             :          * Given that we do not have any expectation of ordering
     554             :          * for handling packets from a peer -vs- handling
     555             :          * the hold timer for a peer as that they are both
     556             :          * events on the peer.  If we have incoming
     557             :          * data on the peers inq, let's give the system a chance
     558             :          * to handle that data.  This can be especially true
     559             :          * for systems where we are heavily loaded for one
     560             :          * reason or another.
     561             :          */
     562           0 :         inq_count = atomic_load_explicit(&peer->ibuf->count,
     563             :                                          memory_order_relaxed);
     564           0 :         if (inq_count)
     565           0 :                 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
     566             :                              peer->v_holdtime);
     567             : 
     568           0 :         THREAD_VAL(thread) = Hold_Timer_expired;
     569           0 :         bgp_event(thread); /* bgp_event unlocks peer */
     570           0 : }
     571             : 
     572           8 : void bgp_routeadv_timer(struct thread *thread)
     573             : {
     574           8 :         struct peer *peer;
     575             : 
     576           8 :         peer = THREAD_ARG(thread);
     577             : 
     578           8 :         if (bgp_debug_neighbor_events(peer))
     579           0 :                 zlog_debug("%s [FSM] Timer (routeadv timer expire)",
     580             :                            peer->host);
     581             : 
     582           8 :         peer->synctime = monotime(NULL);
     583             : 
     584           8 :         thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets, peer, 0,
     585             :                               &peer->t_generate_updgrp_packets);
     586             : 
     587             :         /* MRAI timer will be started again when FIFO is built, no need to
     588             :          * do it here.
     589             :          */
     590           8 : }
     591             : 
     592             : /* RFC 4271 DelayOpenTimer */
     593           0 : void bgp_delayopen_timer(struct thread *thread)
     594             : {
     595           0 :         struct peer *peer;
     596             : 
     597           0 :         peer = THREAD_ARG(thread);
     598             : 
     599           0 :         if (bgp_debug_neighbor_events(peer))
     600           0 :                 zlog_debug("%s [FSM] Timer (DelayOpentimer expire)",
     601             :                            peer->host);
     602             : 
     603           0 :         THREAD_VAL(thread) = DelayOpen_timer_expired;
     604           0 :         bgp_event(thread); /* bgp_event unlocks peer */
     605           0 : }
     606             : 
     607             : /* BGP Peer Down Cause */
     608             : const char *const peer_down_str[] = {"",
     609             :                                      "Router ID changed",
     610             :                                      "Remote AS changed",
     611             :                                      "Local AS change",
     612             :                                      "Cluster ID changed",
     613             :                                      "Confederation identifier changed",
     614             :                                      "Confederation peer changed",
     615             :                                      "RR client config change",
     616             :                                      "RS client config change",
     617             :                                      "Update source change",
     618             :                                      "Address family activated",
     619             :                                      "Admin. shutdown",
     620             :                                      "User reset",
     621             :                                      "BGP Notification received",
     622             :                                      "BGP Notification send",
     623             :                                      "Peer closed the session",
     624             :                                      "Neighbor deleted",
     625             :                                      "Peer-group add member",
     626             :                                      "Peer-group delete member",
     627             :                                      "Capability changed",
     628             :                                      "Passive config change",
     629             :                                      "Multihop config change",
     630             :                                      "NSF peer closed the session",
     631             :                                      "Intf peering v6only config change",
     632             :                                      "BFD down received",
     633             :                                      "Interface down",
     634             :                                      "Neighbor address lost",
     635             :                                      "No path to specified Neighbor",
     636             :                                      "Waiting for Peer IPv6 LLA",
     637             :                                      "Waiting for VRF to be initialized",
     638             :                                      "No AFI/SAFI activated for peer",
     639             :                                      "AS Set config change",
     640             :                                      "Waiting for peer OPEN",
     641             :                                      "Reached received prefix count",
     642             :                                      "Socket Error",
     643             :                                      "Admin. shutdown (RTT)"};
     644             : 
     645           0 : static void bgp_graceful_restart_timer_off(struct peer *peer)
     646             : {
     647           0 :         afi_t afi;
     648           0 :         safi_t safi;
     649             : 
     650           0 :         FOREACH_AFI_SAFI (afi, safi)
     651           0 :                 if (CHECK_FLAG(peer->af_sflags[afi][safi],
     652             :                                PEER_STATUS_LLGR_WAIT))
     653             :                         return;
     654             : 
     655           0 :         UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
     656           0 :         THREAD_OFF(peer->t_gr_stale);
     657             : 
     658           0 :         if (peer_dynamic_neighbor(peer) &&
     659           0 :             !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
     660           0 :                 if (bgp_debug_neighbor_events(peer))
     661           0 :                         zlog_debug("%s (dynamic neighbor) deleted (%s)",
     662             :                                    peer->host, __func__);
     663           0 :                 peer_delete(peer);
     664             :         }
     665             : 
     666           0 :         bgp_timer_set(peer);
     667             : }
     668             : 
     669           0 : static void bgp_llgr_stale_timer_expire(struct thread *thread)
     670             : {
     671           0 :         struct peer_af *paf;
     672           0 :         struct peer *peer;
     673           0 :         afi_t afi;
     674           0 :         safi_t safi;
     675             : 
     676           0 :         paf = THREAD_ARG(thread);
     677             : 
     678           0 :         peer = paf->peer;
     679           0 :         afi = paf->afi;
     680           0 :         safi = paf->safi;
     681             : 
     682             :         /* If the timer for the "Long-lived Stale Time" expires before the
     683             :          * session is re-established, the helper MUST delete all the
     684             :          * stale routes from the neighbor that it is retaining.
     685             :          */
     686           0 :         if (bgp_debug_neighbor_events(peer))
     687           0 :                 zlog_debug("%pBP Long-lived stale timer (%s) expired", peer,
     688             :                            get_afi_safi_str(afi, safi, false));
     689             : 
     690           0 :         UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_LLGR_WAIT);
     691             : 
     692           0 :         bgp_clear_stale_route(peer, afi, safi);
     693             : 
     694           0 :         bgp_graceful_restart_timer_off(peer);
     695           0 : }
     696             : 
     697           0 : static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
     698             : {
     699           0 :         struct bgp_dest *dest;
     700           0 :         struct bgp_path_info *pi;
     701           0 :         struct bgp_table *table;
     702           0 :         struct attr attr;
     703             : 
     704           0 :         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
     705           0 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
     706           0 :                      dest = bgp_route_next(dest)) {
     707           0 :                         struct bgp_dest *rm;
     708             : 
     709           0 :                         table = bgp_dest_get_bgp_table_info(dest);
     710           0 :                         if (!table)
     711           0 :                                 continue;
     712             : 
     713           0 :                         for (rm = bgp_table_top(table); rm;
     714           0 :                              rm = bgp_route_next(rm))
     715           0 :                                 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
     716           0 :                                      pi = pi->next) {
     717           0 :                                         if (pi->peer != peer)
     718           0 :                                                 continue;
     719             : 
     720           0 :                                         if (bgp_attr_get_community(pi->attr) &&
     721           0 :                                             community_include(
     722             :                                                     bgp_attr_get_community(
     723           0 :                                                             pi->attr),
     724             :                                                     COMMUNITY_NO_LLGR))
     725           0 :                                                 continue;
     726             : 
     727           0 :                                         if (bgp_debug_neighbor_events(peer))
     728           0 :                                                 zlog_debug(
     729             :                                                         "%pBP Long-lived set stale community (LLGR_STALE) for: %pFX",
     730             :                                                         peer, &dest->p);
     731             : 
     732           0 :                                         attr = *pi->attr;
     733           0 :                                         bgp_attr_add_llgr_community(&attr);
     734           0 :                                         pi->attr = bgp_attr_intern(&attr);
     735           0 :                                         bgp_recalculate_afi_safi_bestpaths(
     736             :                                                 peer->bgp, afi, safi);
     737             : 
     738           0 :                                         break;
     739             :                                 }
     740             :                 }
     741             :         } else {
     742           0 :                 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
     743           0 :                      dest = bgp_route_next(dest))
     744           0 :                         for (pi = bgp_dest_get_bgp_path_info(dest); pi;
     745           0 :                              pi = pi->next) {
     746           0 :                                 if (pi->peer != peer)
     747           0 :                                         continue;
     748             : 
     749           0 :                                 if (bgp_attr_get_community(pi->attr) &&
     750           0 :                                     community_include(
     751           0 :                                             bgp_attr_get_community(pi->attr),
     752             :                                             COMMUNITY_NO_LLGR))
     753           0 :                                         continue;
     754             : 
     755           0 :                                 if (bgp_debug_neighbor_events(peer))
     756           0 :                                         zlog_debug(
     757             :                                                 "%pBP Long-lived set stale community (LLGR_STALE) for: %pFX",
     758             :                                                 peer, &dest->p);
     759             : 
     760           0 :                                 attr = *pi->attr;
     761           0 :                                 bgp_attr_add_llgr_community(&attr);
     762           0 :                                 pi->attr = bgp_attr_intern(&attr);
     763           0 :                                 bgp_recalculate_afi_safi_bestpaths(peer->bgp,
     764             :                                                                    afi, safi);
     765             : 
     766           0 :                                 break;
     767             :                         }
     768             :         }
     769           0 : }
     770             : 
     771           0 : static void bgp_graceful_restart_timer_expire(struct thread *thread)
     772             : {
     773           0 :         struct peer *peer, *tmp_peer;
     774           0 :         struct listnode *node, *nnode;
     775           0 :         struct peer_af *paf;
     776           0 :         afi_t afi;
     777           0 :         safi_t safi;
     778             : 
     779           0 :         peer = THREAD_ARG(thread);
     780             : 
     781           0 :         if (bgp_debug_neighbor_events(peer)) {
     782           0 :                 zlog_debug("%pBP graceful restart timer expired", peer);
     783           0 :                 zlog_debug("%pBP graceful restart stalepath timer stopped",
     784             :                            peer);
     785             :         }
     786             : 
     787           0 :         FOREACH_AFI_SAFI (afi, safi) {
     788           0 :                 if (!peer->nsf[afi][safi])
     789           0 :                         continue;
     790             : 
     791             :                 /* Once the "Restart Time" period ends, the LLGR period is
     792             :                  * said to have begun and the following procedures MUST be
     793             :                  * performed:
     794             :                  *
     795             :                  * The helper router MUST start a timer for the
     796             :                  * "Long-lived Stale Time".
     797             :                  *
     798             :                  * The helper router MUST attach the LLGR_STALE community
     799             :                  * for the stale routes being retained. Note that this
     800             :                  * requirement implies that the routes would need to be
     801             :                  * readvertised, to disseminate the modified community.
     802             :                  */
     803           0 :                 if (peer->llgr[afi][safi].stale_time) {
     804           0 :                         paf = peer_af_find(peer, afi, safi);
     805           0 :                         if (!paf)
     806           0 :                                 continue;
     807             : 
     808           0 :                         if (bgp_debug_neighbor_events(peer))
     809           0 :                                 zlog_debug(
     810             :                                         "%pBP Long-lived stale timer (%s) started for %d sec",
     811             :                                         peer,
     812             :                                         get_afi_safi_str(afi, safi, false),
     813             :                                         peer->llgr[afi][safi].stale_time);
     814             : 
     815           0 :                         SET_FLAG(peer->af_sflags[afi][safi],
     816             :                                  PEER_STATUS_LLGR_WAIT);
     817             : 
     818           0 :                         bgp_set_llgr_stale(peer, afi, safi);
     819           0 :                         bgp_clear_stale_route(peer, afi, safi);
     820             : 
     821           0 :                         thread_add_timer(bm->master,
     822             :                                          bgp_llgr_stale_timer_expire, paf,
     823             :                                          peer->llgr[afi][safi].stale_time,
     824             :                                          &peer->t_llgr_stale[afi][safi]);
     825             : 
     826           0 :                         for (ALL_LIST_ELEMENTS(peer->bgp->peer, node, nnode,
     827             :                                                tmp_peer))
     828           0 :                                 bgp_announce_route(tmp_peer, afi, safi, false);
     829             :                 } else {
     830           0 :                         bgp_clear_stale_route(peer, afi, safi);
     831             :                 }
     832             :         }
     833             : 
     834           0 :         bgp_graceful_restart_timer_off(peer);
     835           0 : }
     836             : 
     837           0 : static void bgp_graceful_stale_timer_expire(struct thread *thread)
     838             : {
     839           0 :         struct peer *peer;
     840           0 :         afi_t afi;
     841           0 :         safi_t safi;
     842             : 
     843           0 :         peer = THREAD_ARG(thread);
     844             : 
     845           0 :         if (bgp_debug_neighbor_events(peer))
     846           0 :                 zlog_debug("%pBP graceful restart stalepath timer expired",
     847             :                            peer);
     848             : 
     849             :         /* NSF delete stale route */
     850           0 :         FOREACH_AFI_SAFI_NSF (afi, safi)
     851           0 :                 if (peer->nsf[afi][safi])
     852           0 :                         bgp_clear_stale_route(peer, afi, safi);
     853           0 : }
     854             : 
     855             : /* Selection deferral timer processing function */
     856           0 : static void bgp_graceful_deferral_timer_expire(struct thread *thread)
     857             : {
     858           0 :         struct afi_safi_info *info;
     859           0 :         afi_t afi;
     860           0 :         safi_t safi;
     861           0 :         struct bgp *bgp;
     862             : 
     863           0 :         info = THREAD_ARG(thread);
     864           0 :         afi = info->afi;
     865           0 :         safi = info->safi;
     866           0 :         bgp = info->bgp;
     867             : 
     868           0 :         if (BGP_DEBUG(update, UPDATE_OUT))
     869           0 :                 zlog_debug(
     870             :                         "afi %d, safi %d : graceful restart deferral timer expired",
     871             :                         afi, safi);
     872             : 
     873           0 :         bgp->gr_info[afi][safi].eor_required = 0;
     874           0 :         bgp->gr_info[afi][safi].eor_received = 0;
     875           0 :         XFREE(MTYPE_TMP, info);
     876             : 
     877             :         /* Best path selection */
     878           0 :         bgp_best_path_select_defer(bgp, afi, safi);
     879           0 : }
     880             : 
     881           0 : static bool bgp_update_delay_applicable(struct bgp *bgp)
     882             : {
     883             :         /* update_delay_over flag should be reset (set to 0) for any new
     884             :            applicability of the update-delay during BGP process lifetime.
     885             :            And it should be set after an occurence of the update-delay is
     886             :            over)*/
     887           0 :         if (!bgp->update_delay_over)
     888           0 :                 return true;
     889             :         return false;
     890             : }
     891             : 
     892          48 : bool bgp_update_delay_active(struct bgp *bgp)
     893             : {
     894          44 :         if (bgp->t_update_delay)
     895           0 :                 return true;
     896             :         return false;
     897             : }
     898             : 
     899          41 : bool bgp_update_delay_configured(struct bgp *bgp)
     900             : {
     901           0 :         if (bgp->v_update_delay)
     902           0 :                 return true;
     903             :         return false;
     904             : }
     905             : 
     906             : /* Do the post-processing needed when bgp comes out of the read-only mode
     907             :    on ending the update delay. */
     908           0 : void bgp_update_delay_end(struct bgp *bgp)
     909             : {
     910           0 :         THREAD_OFF(bgp->t_update_delay);
     911           0 :         THREAD_OFF(bgp->t_establish_wait);
     912             : 
     913             :         /* Reset update-delay related state */
     914           0 :         bgp->update_delay_over = 1;
     915           0 :         bgp->established = 0;
     916           0 :         bgp->restarted_peers = 0;
     917           0 :         bgp->implicit_eors = 0;
     918           0 :         bgp->explicit_eors = 0;
     919             : 
     920           0 :         frr_timestamp(3, bgp->update_delay_end_time,
     921             :                       sizeof(bgp->update_delay_end_time));
     922             : 
     923             :         /*
     924             :          * Add an end-of-initial-update marker to the main process queues so
     925             :          * that
     926             :          * the route advertisement timer for the peers can be started. Also set
     927             :          * the zebra and peer update hold flags. These flags are used to achieve
     928             :          * three stages in the update-delay post processing:
     929             :          *  1. Finish best-path selection for all the prefixes held on the
     930             :          * queues.
     931             :          *     (routes in BGP are updated, and peers sync queues are populated
     932             :          * too)
     933             :          *  2. As the eoiu mark is reached in the bgp process routine, ship all
     934             :          * the
     935             :          *     routes to zebra. With that zebra should see updates from BGP
     936             :          * close
     937             :          *     to each other.
     938             :          *  3. Unblock the peer update writes. With that peer update packing
     939             :          * with
     940             :          *     the prefixes should be at its maximum.
     941             :          */
     942           0 :         bgp_add_eoiu_mark(bgp);
     943           0 :         bgp->main_zebra_update_hold = 1;
     944           0 :         bgp->main_peers_update_hold = 1;
     945             : 
     946             :         /*
     947             :          * Resume the queue processing. This should trigger the event that would
     948             :          * take care of processing any work that was queued during the read-only
     949             :          * mode.
     950             :          */
     951           0 :         work_queue_unplug(bgp->process_queue);
     952           0 : }
     953             : 
     954             : /**
     955             :  * see bgp_fsm.h
     956             :  */
     957           0 : void bgp_start_routeadv(struct bgp *bgp)
     958             : {
     959           0 :         struct listnode *node, *nnode;
     960           0 :         struct peer *peer;
     961             : 
     962           0 :         zlog_info("%s, update hold status %d", __func__,
     963             :                   bgp->main_peers_update_hold);
     964             : 
     965           0 :         if (bgp->main_peers_update_hold)
     966             :                 return;
     967             : 
     968           0 :         frr_timestamp(3, bgp->update_delay_peers_resume_time,
     969             :                       sizeof(bgp->update_delay_peers_resume_time));
     970             : 
     971           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     972           0 :                 if (!peer_established(peer))
     973           0 :                         continue;
     974           0 :                 THREAD_OFF(peer->t_routeadv);
     975           0 :                 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
     976             :         }
     977             : }
     978             : 
     979             : /**
     980             :  * see bgp_fsm.h
     981             :  */
     982           5 : void bgp_adjust_routeadv(struct peer *peer)
     983             : {
     984           5 :         time_t nowtime = monotime(NULL);
     985           5 :         double diff;
     986           5 :         unsigned long remain;
     987             : 
     988             :         /* Bypass checks for special case of MRAI being 0 */
     989           5 :         if (peer->v_routeadv == 0) {
     990             :                 /* Stop existing timer, just in case it is running for a
     991             :                  * different
     992             :                  * duration and schedule write thread immediately.
     993             :                  */
     994           5 :                 THREAD_OFF(peer->t_routeadv);
     995             : 
     996           5 :                 peer->synctime = monotime(NULL);
     997             :                 /* If suppress fib pending is enabled, route is advertised to
     998             :                  * peers when the status is received from the FIB. The delay
     999             :                  * is added to update group packet generate which will allow
    1000             :                  * more routes to be sent in the update message
    1001             :                  */
    1002           5 :                 BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
    1003             :                                           bgp_generate_updgrp_packets);
    1004           5 :                 return;
    1005             :         }
    1006             : 
    1007             : 
    1008             :         /*
    1009             :          * CASE I:
    1010             :          * If the last update was written more than MRAI back, expire the timer
    1011             :          * instantly so that we can send the update out sooner.
    1012             :          *
    1013             :          *                           <-------  MRAI --------->
    1014             :          *         |-----------------|-----------------------|
    1015             :          *         <------------- m ------------>
    1016             :          *         ^                 ^          ^
    1017             :          *         |                 |          |
    1018             :          *         |                 |     current time
    1019             :          *         |            timer start
    1020             :          *      last write
    1021             :          *
    1022             :          *                     m > MRAI
    1023             :          */
    1024           0 :         diff = difftime(nowtime, peer->last_update);
    1025           0 :         if (diff > (double)peer->v_routeadv) {
    1026           0 :                 THREAD_OFF(peer->t_routeadv);
    1027           0 :                 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
    1028           0 :                 return;
    1029             :         }
    1030             : 
    1031             :         /*
    1032             :          * CASE II:
    1033             :          * - Find when to expire the MRAI timer.
    1034             :          *   If MRAI timer is not active, assume we can start it now.
    1035             :          *
    1036             :          *                      <-------  MRAI --------->
    1037             :          *         |------------|-----------------------|
    1038             :          *         <-------- m ----------><----- r ----->
    1039             :          *         ^            ^        ^
    1040             :          *         |            |        |
    1041             :          *         |            |   current time
    1042             :          *         |       timer start
    1043             :          *      last write
    1044             :          *
    1045             :          *                     (MRAI - m) < r
    1046             :          */
    1047           0 :         if (peer->t_routeadv)
    1048           0 :                 remain = thread_timer_remain_second(peer->t_routeadv);
    1049             :         else
    1050           0 :                 remain = peer->v_routeadv;
    1051           0 :         diff = peer->v_routeadv - diff;
    1052           0 :         if (diff <= (double)remain) {
    1053           0 :                 THREAD_OFF(peer->t_routeadv);
    1054           0 :                 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff);
    1055             :         }
    1056             : }
    1057             : 
    1058           0 : static bool bgp_maxmed_onstartup_applicable(struct bgp *bgp)
    1059             : {
    1060           0 :         if (!bgp->maxmed_onstartup_over)
    1061           0 :                 return true;
    1062             :         return false;
    1063             : }
    1064             : 
    1065           4 : bool bgp_maxmed_onstartup_configured(struct bgp *bgp)
    1066             : {
    1067           0 :         if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
    1068           0 :                 return true;
    1069             :         return false;
    1070             : }
    1071             : 
    1072           0 : bool bgp_maxmed_onstartup_active(struct bgp *bgp)
    1073             : {
    1074           0 :         if (bgp->t_maxmed_onstartup)
    1075           0 :                 return true;
    1076             :         return false;
    1077             : }
    1078             : 
    1079           0 : void bgp_maxmed_update(struct bgp *bgp)
    1080             : {
    1081           0 :         uint8_t maxmed_active;
    1082           0 :         uint32_t maxmed_value;
    1083             : 
    1084           0 :         if (bgp->v_maxmed_admin) {
    1085           0 :                 maxmed_active = 1;
    1086           0 :                 maxmed_value = bgp->maxmed_admin_value;
    1087           0 :         } else if (bgp->t_maxmed_onstartup) {
    1088           0 :                 maxmed_active = 1;
    1089           0 :                 maxmed_value = bgp->maxmed_onstartup_value;
    1090             :         } else {
    1091             :                 maxmed_active = 0;
    1092             :                 maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
    1093             :         }
    1094             : 
    1095           0 :         if (bgp->maxmed_active != maxmed_active
    1096           0 :             || bgp->maxmed_value != maxmed_value) {
    1097           0 :                 bgp->maxmed_active = maxmed_active;
    1098           0 :                 bgp->maxmed_value = maxmed_value;
    1099             : 
    1100           0 :                 update_group_announce(bgp);
    1101             :         }
    1102           0 : }
    1103             : 
    1104           0 : int bgp_fsm_error_subcode(int status)
    1105             : {
    1106           0 :         int fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC;
    1107             : 
    1108           0 :         switch (status) {
    1109             :         case OpenSent:
    1110             :                 fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT;
    1111             :                 break;
    1112             :         case OpenConfirm:
    1113             :                 fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM;
    1114             :                 break;
    1115             :         case Established:
    1116             :                 fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED;
    1117             :                 break;
    1118             :         default:
    1119             :                 break;
    1120             :         }
    1121             : 
    1122           0 :         return fsm_err_subcode;
    1123             : }
    1124             : 
    1125             : /* The maxmed onstartup timer expiry callback. */
    1126           0 : static void bgp_maxmed_onstartup_timer(struct thread *thread)
    1127             : {
    1128           0 :         struct bgp *bgp;
    1129             : 
    1130           0 :         zlog_info("Max med on startup ended - timer expired.");
    1131             : 
    1132           0 :         bgp = THREAD_ARG(thread);
    1133           0 :         THREAD_OFF(bgp->t_maxmed_onstartup);
    1134           0 :         bgp->maxmed_onstartup_over = 1;
    1135             : 
    1136           0 :         bgp_maxmed_update(bgp);
    1137           0 : }
    1138             : 
    1139           0 : static void bgp_maxmed_onstartup_begin(struct bgp *bgp)
    1140             : {
    1141             :         /* Applicable only once in the process lifetime on the startup */
    1142           0 :         if (bgp->maxmed_onstartup_over)
    1143             :                 return;
    1144             : 
    1145           0 :         zlog_info("Begin maxmed onstartup mode - timer %d seconds",
    1146             :                   bgp->v_maxmed_onstartup);
    1147             : 
    1148           0 :         thread_add_timer(bm->master, bgp_maxmed_onstartup_timer, bgp,
    1149             :                          bgp->v_maxmed_onstartup, &bgp->t_maxmed_onstartup);
    1150             : 
    1151           0 :         if (!bgp->v_maxmed_admin) {
    1152           0 :                 bgp->maxmed_active = 1;
    1153           0 :                 bgp->maxmed_value = bgp->maxmed_onstartup_value;
    1154             :         }
    1155             : 
    1156             :         /* Route announce to all peers should happen after this in
    1157             :          * bgp_establish() */
    1158             : }
    1159             : 
    1160           0 : static void bgp_maxmed_onstartup_process_status_change(struct peer *peer)
    1161             : {
    1162           0 :         if (peer_established(peer) && !peer->bgp->established) {
    1163           0 :                 bgp_maxmed_onstartup_begin(peer->bgp);
    1164             :         }
    1165           0 : }
    1166             : 
    1167             : /* The update delay timer expiry callback. */
    1168           0 : static void bgp_update_delay_timer(struct thread *thread)
    1169             : {
    1170           0 :         struct bgp *bgp;
    1171             : 
    1172           0 :         zlog_info("Update delay ended - timer expired.");
    1173             : 
    1174           0 :         bgp = THREAD_ARG(thread);
    1175           0 :         THREAD_OFF(bgp->t_update_delay);
    1176           0 :         bgp_update_delay_end(bgp);
    1177           0 : }
    1178             : 
    1179             : /* The establish wait timer expiry callback. */
    1180           0 : static void bgp_establish_wait_timer(struct thread *thread)
    1181             : {
    1182           0 :         struct bgp *bgp;
    1183             : 
    1184           0 :         zlog_info("Establish wait - timer expired.");
    1185             : 
    1186           0 :         bgp = THREAD_ARG(thread);
    1187           0 :         THREAD_OFF(bgp->t_establish_wait);
    1188           0 :         bgp_check_update_delay(bgp);
    1189           0 : }
    1190             : 
    1191             : /* Steps to begin the update delay:
    1192             :      - initialize queues if needed
    1193             :      - stop the queue processing
    1194             :      - start the timer */
    1195           0 : static void bgp_update_delay_begin(struct bgp *bgp)
    1196             : {
    1197           0 :         struct listnode *node, *nnode;
    1198           0 :         struct peer *peer;
    1199             : 
    1200             :         /* Stop the processing of queued work. Enqueue shall continue */
    1201           0 :         work_queue_plug(bgp->process_queue);
    1202             : 
    1203           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
    1204           0 :                 peer->update_delay_over = 0;
    1205             : 
    1206             :         /* Start the update-delay timer */
    1207           0 :         thread_add_timer(bm->master, bgp_update_delay_timer, bgp,
    1208             :                          bgp->v_update_delay, &bgp->t_update_delay);
    1209             : 
    1210           0 :         if (bgp->v_establish_wait != bgp->v_update_delay)
    1211           0 :                 thread_add_timer(bm->master, bgp_establish_wait_timer, bgp,
    1212             :                                  bgp->v_establish_wait, &bgp->t_establish_wait);
    1213             : 
    1214           0 :         frr_timestamp(3, bgp->update_delay_begin_time,
    1215             :                       sizeof(bgp->update_delay_begin_time));
    1216           0 : }
    1217             : 
    1218           0 : static void bgp_update_delay_process_status_change(struct peer *peer)
    1219             : {
    1220           0 :         if (peer_established(peer)) {
    1221           0 :                 if (!peer->bgp->established++) {
    1222           0 :                         bgp_update_delay_begin(peer->bgp);
    1223           0 :                         zlog_info(
    1224             :                                 "Begin read-only mode - update-delay timer %d seconds",
    1225             :                                 peer->bgp->v_update_delay);
    1226             :                 }
    1227           0 :                 if (CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV))
    1228           0 :                         bgp_update_restarted_peers(peer);
    1229             :         }
    1230           0 :         if (peer->ostatus == Established
    1231           0 :             && bgp_update_delay_active(peer->bgp)) {
    1232             :                 /* Adjust the update-delay state to account for this flap.
    1233             :                    NOTE: Intentionally skipping adjusting implicit_eors or
    1234             :                    explicit_eors
    1235             :                    counters. Extra sanity check in bgp_check_update_delay()
    1236             :                    should
    1237             :                    be enough to take care of any additive discrepancy in bgp eor
    1238             :                    counters */
    1239           0 :                 peer->bgp->established--;
    1240           0 :                 peer->update_delay_over = 0;
    1241             :         }
    1242           0 : }
    1243             : 
    1244             : /* Called after event occurred, this function change status and reset
    1245             :    read/write and timer thread. */
    1246          41 : void bgp_fsm_change_status(struct peer *peer, enum bgp_fsm_status status)
    1247             : {
    1248          41 :         struct bgp *bgp;
    1249          41 :         uint32_t peer_count;
    1250             : 
    1251          41 :         bgp = peer->bgp;
    1252          41 :         peer_count = bgp->established_peers;
    1253             : 
    1254          41 :         if (status == Established)
    1255           4 :                 bgp->established_peers++;
    1256          37 :         else if ((peer_established(peer)) && (status != Established))
    1257           4 :                 bgp->established_peers--;
    1258             : 
    1259          41 :         if (bgp_debug_neighbor_events(peer)) {
    1260           0 :                 struct vrf *vrf = vrf_lookup_by_id(bgp->vrf_id);
    1261             : 
    1262           0 :                 zlog_debug("%s : vrf %s(%u), Status: %s established_peers %u", __func__,
    1263             :                            vrf ? vrf->name : "Unknown", bgp->vrf_id,
    1264             :                            lookup_msg(bgp_status_msg, status, NULL),
    1265             :                            bgp->established_peers);
    1266             :         }
    1267             : 
    1268             :         /* Set to router ID to the value provided by RIB if there are no peers
    1269             :          * in the established state and peer count did not change
    1270             :          */
    1271          41 :         if ((peer_count != bgp->established_peers) &&
    1272             :             (bgp->established_peers == 0))
    1273           3 :                 bgp_router_id_zebra_bump(bgp->vrf_id, NULL);
    1274             : 
    1275             :         /* Transition into Clearing or Deleted must /always/ clear all routes..
    1276             :          * (and must do so before actually changing into Deleted..
    1277             :          */
    1278          41 :         if (status >= Clearing) {
    1279          12 :                 bgp_clear_route_all(peer);
    1280             : 
    1281             :                 /* If no route was queued for the clear-node processing,
    1282             :                  * generate the
    1283             :                  * completion event here. This is needed because if there are no
    1284             :                  * routes
    1285             :                  * to trigger the background clear-node thread, the event won't
    1286             :                  * get
    1287             :                  * generated and the peer would be stuck in Clearing. Note that
    1288             :                  * this
    1289             :                  * event is for the peer and helps the peer transition out of
    1290             :                  * Clearing
    1291             :                  * state; it should not be generated per (AFI,SAFI). The event
    1292             :                  * is
    1293             :                  * directly posted here without calling clear_node_complete() as
    1294             :                  * we
    1295             :                  * shouldn't do an extra unlock. This event will get processed
    1296             :                  * after
    1297             :                  * the state change that happens below, so peer will be in
    1298             :                  * Clearing
    1299             :                  * (or Deleted).
    1300             :                  */
    1301          12 :                 if (!work_queue_is_scheduled(peer->clear_node_queue) &&
    1302             :                     status != Deleted)
    1303           0 :                         BGP_EVENT_ADD(peer, Clearing_Completed);
    1304             :         }
    1305             : 
    1306             :         /* Preserve old status and change into new status. */
    1307          41 :         peer->ostatus = peer->status;
    1308          41 :         peer->status = status;
    1309             : 
    1310             :         /* Reset received keepalives counter on every FSM change */
    1311          41 :         peer->rtt_keepalive_rcv = 0;
    1312             : 
    1313             :         /* Fire backward transition hook if that's the case */
    1314          41 :         if (peer->ostatus == Established && peer->status != Established)
    1315           4 :                 hook_call(peer_backward_transition, peer);
    1316             : 
    1317             :         /* Save event that caused status change. */
    1318          41 :         peer->last_major_event = peer->cur_event;
    1319             : 
    1320             :         /* Operations after status change */
    1321          41 :         hook_call(peer_status_changed, peer);
    1322             : 
    1323          41 :         if (status == Established)
    1324           4 :                 UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
    1325             : 
    1326             :         /* If max-med processing is applicable, do the necessary. */
    1327           4 :         if (status == Established) {
    1328           4 :                 if (bgp_maxmed_onstartup_configured(peer->bgp)
    1329           0 :                     && bgp_maxmed_onstartup_applicable(peer->bgp))
    1330           0 :                         bgp_maxmed_onstartup_process_status_change(peer);
    1331             :                 else
    1332           4 :                         peer->bgp->maxmed_onstartup_over = 1;
    1333             :         }
    1334             : 
    1335             :         /* If update-delay processing is applicable, do the necessary. */
    1336          41 :         if (bgp_update_delay_configured(peer->bgp)
    1337           0 :             && bgp_update_delay_applicable(peer->bgp))
    1338           0 :                 bgp_update_delay_process_status_change(peer);
    1339             : 
    1340          41 :         if (bgp_debug_neighbor_events(peer))
    1341           0 :                 zlog_debug("%s fd %d went from %s to %s", peer->host, peer->fd,
    1342             :                            lookup_msg(bgp_status_msg, peer->ostatus, NULL),
    1343             :                            lookup_msg(bgp_status_msg, peer->status, NULL));
    1344          41 : }
    1345             : 
    1346             : /* Flush the event queue and ensure the peer is shut down */
    1347           2 : static enum bgp_fsm_state_progress bgp_clearing_completed(struct peer *peer)
    1348             : {
    1349           2 :         enum bgp_fsm_state_progress rc = bgp_stop(peer);
    1350             : 
    1351           2 :         if (rc >= BGP_FSM_SUCCESS)
    1352           2 :                 BGP_EVENT_FLUSH(peer);
    1353             : 
    1354           2 :         return rc;
    1355             : }
    1356             : 
    1357             : /* Administrative BGP peer stop event. */
    1358             : /* May be called multiple times for the same peer */
    1359          19 : enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
    1360             : {
    1361          19 :         afi_t afi;
    1362          19 :         safi_t safi;
    1363          19 :         char orf_name[BUFSIZ];
    1364          19 :         enum bgp_fsm_state_progress ret = BGP_FSM_SUCCESS;
    1365          19 :         struct bgp *bgp = peer->bgp;
    1366          19 :         struct graceful_restart_info *gr_info = NULL;
    1367             : 
    1368          19 :         peer->nsf_af_count = 0;
    1369             : 
    1370             :         /* deregister peer */
    1371          19 :         if (peer->bfd_config
    1372           0 :             && peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE)
    1373           0 :                 bfd_sess_uninstall(peer->bfd_config->session);
    1374             : 
    1375          19 :         if (peer_dynamic_neighbor_no_nsf(peer) &&
    1376           0 :             !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
    1377           0 :                 if (bgp_debug_neighbor_events(peer))
    1378           0 :                         zlog_debug("%s (dynamic neighbor) deleted (%s)",
    1379             :                                    peer->host, __func__);
    1380           0 :                 peer_delete(peer);
    1381           0 :                 return BGP_FSM_FAILURE_AND_DELETE;
    1382             :         }
    1383             : 
    1384             :         /* Can't do this in Clearing; events are used for state transitions */
    1385          19 :         if (peer->status != Clearing) {
    1386             :                 /* Delete all existing events of the peer */
    1387          17 :                 BGP_EVENT_FLUSH(peer);
    1388             :         }
    1389             : 
    1390             :         /* Increment Dropped count. */
    1391          19 :         if (peer_established(peer)) {
    1392           4 :                 peer->dropped++;
    1393             : 
    1394             :                 /* Notify BGP conditional advertisement process */
    1395           4 :                 peer->advmap_table_change = true;
    1396             : 
    1397             :                 /* bgp log-neighbor-changes of neighbor Down */
    1398           4 :                 if (CHECK_FLAG(peer->bgp->flags,
    1399             :                                BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
    1400           0 :                         struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
    1401             : 
    1402           0 :                         zlog_info(
    1403             :                                 "%%ADJCHANGE: neighbor %pBP in vrf %s Down %s",
    1404             :                                 peer,
    1405             :                                 vrf ? ((vrf->vrf_id != VRF_DEFAULT)
    1406             :                                                ? vrf->name
    1407             :                                                : VRF_DEFAULT_NAME)
    1408             :                                     : "",
    1409             :                                 peer_down_str[(int)peer->last_reset]);
    1410             :                 }
    1411             : 
    1412             :                 /* graceful restart */
    1413           4 :                 if (peer->t_gr_stale) {
    1414           0 :                         THREAD_OFF(peer->t_gr_stale);
    1415           0 :                         if (bgp_debug_neighbor_events(peer))
    1416           0 :                                 zlog_debug(
    1417             :                                         "%pBP graceful restart stalepath timer stopped",
    1418             :                                         peer);
    1419             :                 }
    1420           4 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
    1421           0 :                         if (bgp_debug_neighbor_events(peer)) {
    1422           0 :                                 zlog_debug(
    1423             :                                         "%pBP graceful restart timer started for %d sec",
    1424             :                                         peer, peer->v_gr_restart);
    1425           0 :                                 zlog_debug(
    1426             :                                         "%pBP graceful restart stalepath timer started for %d sec",
    1427             :                                         peer, peer->bgp->stalepath_time);
    1428             :                         }
    1429           0 :                         BGP_TIMER_ON(peer->t_gr_restart,
    1430             :                                      bgp_graceful_restart_timer_expire,
    1431             :                                      peer->v_gr_restart);
    1432           0 :                         BGP_TIMER_ON(peer->t_gr_stale,
    1433             :                                      bgp_graceful_stale_timer_expire,
    1434             :                                      peer->bgp->stalepath_time);
    1435             :                 } else {
    1436           4 :                         UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
    1437             : 
    1438          52 :                         FOREACH_AFI_SAFI_NSF (afi, safi)
    1439          36 :                                 peer->nsf[afi][safi] = 0;
    1440             :                 }
    1441             : 
    1442             :                 /* Stop route-refresh stalepath timer */
    1443           4 :                 if (peer->t_refresh_stalepath) {
    1444           0 :                         THREAD_OFF(peer->t_refresh_stalepath);
    1445             : 
    1446           0 :                         if (bgp_debug_neighbor_events(peer))
    1447           0 :                                 zlog_debug(
    1448             :                                         "%pBP route-refresh restart stalepath timer stopped",
    1449             :                                         peer);
    1450             :                 }
    1451             : 
    1452             :                 /* If peer reset before receiving EOR, decrement EOR count and
    1453             :                  * cancel the selection deferral timer if there are no
    1454             :                  * pending EOR messages to be received
    1455             :                  */
    1456           4 :                 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
    1457         100 :                         FOREACH_AFI_SAFI (afi, safi) {
    1458          84 :                                 if (!peer->afc_nego[afi][safi]
    1459           4 :                                     || CHECK_FLAG(peer->af_sflags[afi][safi],
    1460             :                                                   PEER_STATUS_EOR_RECEIVED))
    1461          84 :                                         continue;
    1462             : 
    1463           0 :                                 gr_info = &bgp->gr_info[afi][safi];
    1464           0 :                                 if (!gr_info)
    1465           0 :                                         continue;
    1466             : 
    1467           0 :                                 if (gr_info->eor_required)
    1468           0 :                                         gr_info->eor_required--;
    1469             : 
    1470           0 :                                 if (BGP_DEBUG(update, UPDATE_OUT))
    1471           0 :                                         zlog_debug("peer %s, EOR_required %d",
    1472             :                                                    peer->host,
    1473             :                                                    gr_info->eor_required);
    1474             : 
    1475             :                                 /* There is no pending EOR message */
    1476           0 :                                 if (gr_info->eor_required == 0) {
    1477           0 :                                         if (gr_info->t_select_deferral) {
    1478           0 :                                                 void *info = THREAD_ARG(
    1479             :                                                         gr_info->t_select_deferral);
    1480           0 :                                                 XFREE(MTYPE_TMP, info);
    1481             :                                         }
    1482           0 :                                         THREAD_OFF(gr_info->t_select_deferral);
    1483           0 :                                         gr_info->eor_received = 0;
    1484             :                                 }
    1485             :                         }
    1486             :                 }
    1487             : 
    1488             :                 /* set last reset time */
    1489           4 :                 peer->resettime = peer->uptime = monotime(NULL);
    1490             : 
    1491           4 :                 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
    1492           0 :                         zlog_debug("%s remove from all update group",
    1493             :                                    peer->host);
    1494           4 :                 update_group_remove_peer_afs(peer);
    1495             : 
    1496             :                 /* Reset peer synctime */
    1497           4 :                 peer->synctime = 0;
    1498             :         }
    1499             : 
    1500             :         /* stop keepalives */
    1501          19 :         bgp_keepalives_off(peer);
    1502             : 
    1503             :         /* Stop read and write threads. */
    1504          19 :         bgp_writes_off(peer);
    1505          19 :         bgp_reads_off(peer);
    1506             : 
    1507          19 :         THREAD_OFF(peer->t_connect_check_r);
    1508          19 :         THREAD_OFF(peer->t_connect_check_w);
    1509             : 
    1510             :         /* Stop all timers. */
    1511          19 :         THREAD_OFF(peer->t_start);
    1512          19 :         THREAD_OFF(peer->t_connect);
    1513          19 :         THREAD_OFF(peer->t_holdtime);
    1514          19 :         THREAD_OFF(peer->t_routeadv);
    1515          19 :         THREAD_OFF(peer->t_delayopen);
    1516             : 
    1517             :         /* Clear input and output buffer.  */
    1518          38 :         frr_with_mutex (&peer->io_mtx) {
    1519          19 :                 if (peer->ibuf)
    1520          19 :                         stream_fifo_clean(peer->ibuf);
    1521          19 :                 if (peer->obuf)
    1522          19 :                         stream_fifo_clean(peer->obuf);
    1523             : 
    1524          19 :                 if (peer->ibuf_work)
    1525          19 :                         ringbuf_wipe(peer->ibuf_work);
    1526          19 :                 if (peer->obuf_work)
    1527          19 :                         stream_reset(peer->obuf_work);
    1528             : 
    1529          19 :                 if (peer->curr) {
    1530           0 :                         stream_free(peer->curr);
    1531           0 :                         peer->curr = NULL;
    1532             :                 }
    1533             :         }
    1534             : 
    1535             :         /* Close of file descriptor. */
    1536          19 :         if (peer->fd >= 0) {
    1537           6 :                 close(peer->fd);
    1538           6 :                 peer->fd = -1;
    1539             :         }
    1540             : 
    1541             :         /* Reset capabilities. */
    1542          19 :         peer->cap = 0;
    1543             : 
    1544             :         /* Resetting neighbor role to the default value */
    1545          19 :         peer->remote_role = ROLE_UNDEFINED;
    1546             : 
    1547         475 :         FOREACH_AFI_SAFI (afi, safi) {
    1548             :                 /* Reset all negotiated variables */
    1549         399 :                 peer->afc_nego[afi][safi] = 0;
    1550         399 :                 peer->afc_adv[afi][safi] = 0;
    1551         399 :                 peer->afc_recv[afi][safi] = 0;
    1552             : 
    1553             :                 /* peer address family capability flags*/
    1554         399 :                 peer->af_cap[afi][safi] = 0;
    1555             : 
    1556             :                 /* peer address family status flags*/
    1557         399 :                 peer->af_sflags[afi][safi] = 0;
    1558             : 
    1559             :                 /* Received ORF prefix-filter */
    1560         399 :                 peer->orf_plist[afi][safi] = NULL;
    1561             : 
    1562         399 :                 if ((peer->status == OpenConfirm) || (peer_established(peer))) {
    1563             :                         /* ORF received prefix-filter pnt */
    1564          84 :                         snprintf(orf_name, sizeof(orf_name), "%s.%d.%d",
    1565             :                                  peer->host, afi, safi);
    1566          84 :                         prefix_bgp_orf_remove_all(afi, orf_name);
    1567             :                 }
    1568             :         }
    1569             : 
    1570             :         /* Reset keepalive and holdtime */
    1571          19 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) {
    1572          16 :                 peer->v_keepalive = peer->keepalive;
    1573          16 :                 peer->v_holdtime = peer->holdtime;
    1574             :         } else {
    1575           3 :                 peer->v_keepalive = peer->bgp->default_keepalive;
    1576           3 :                 peer->v_holdtime = peer->bgp->default_holdtime;
    1577             :         }
    1578             : 
    1579             :         /* Reset DelayOpenTime */
    1580          19 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
    1581           0 :                 peer->v_delayopen = peer->delayopen;
    1582             :         else
    1583          19 :                 peer->v_delayopen = peer->bgp->default_delayopen;
    1584             : 
    1585          19 :         peer->update_time = 0;
    1586             : 
    1587          19 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
    1588          19 :             && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
    1589           1 :                 peer_delete(peer);
    1590           1 :                 ret = BGP_FSM_FAILURE_AND_DELETE;
    1591             :         } else {
    1592          18 :                 bgp_peer_conf_if_to_su_update(peer);
    1593             :         }
    1594             :         return ret;
    1595             : }
    1596             : 
    1597             : /* BGP peer is stoped by the error. */
    1598           0 : static enum bgp_fsm_state_progress bgp_stop_with_error(struct peer *peer)
    1599             : {
    1600             :         /* Double start timer. */
    1601           0 :         peer->v_start *= 2;
    1602             : 
    1603             :         /* Overflow check. */
    1604           0 :         if (peer->v_start >= (60 * 2))
    1605           0 :                 peer->v_start = (60 * 2);
    1606             : 
    1607           0 :         if (peer_dynamic_neighbor_no_nsf(peer)) {
    1608           0 :                 if (bgp_debug_neighbor_events(peer))
    1609           0 :                         zlog_debug("%s (dynamic neighbor) deleted (%s)",
    1610             :                                    peer->host, __func__);
    1611           0 :                 peer_delete(peer);
    1612           0 :                 return BGP_FSM_FAILURE;
    1613             :         }
    1614             : 
    1615           0 :         return bgp_stop(peer);
    1616             : }
    1617             : 
    1618             : 
    1619             : /* something went wrong, send notify and tear down */
    1620             : static enum bgp_fsm_state_progress
    1621           0 : bgp_stop_with_notify(struct peer *peer, uint8_t code, uint8_t sub_code)
    1622             : {
    1623             :         /* Send notify to remote peer */
    1624           0 :         bgp_notify_send(peer, code, sub_code);
    1625             : 
    1626           0 :         if (peer_dynamic_neighbor_no_nsf(peer)) {
    1627           0 :                 if (bgp_debug_neighbor_events(peer))
    1628           0 :                         zlog_debug("%s (dynamic neighbor) deleted (%s)",
    1629             :                                    peer->host, __func__);
    1630           0 :                 peer_delete(peer);
    1631           0 :                 return BGP_FSM_FAILURE;
    1632             :         }
    1633             : 
    1634             :         /* Clear start timer value to default. */
    1635           0 :         peer->v_start = BGP_INIT_START_TIMER;
    1636             : 
    1637           0 :         return bgp_stop(peer);
    1638             : }
    1639             : 
    1640             : /**
    1641             :  * Determines whether a TCP session has successfully established for a peer and
    1642             :  * events as appropriate.
    1643             :  *
    1644             :  * This function is called when setting up a new session. After connect() is
    1645             :  * called on the peer's socket (in bgp_start()), the fd is passed to poll()
    1646             :  * to wait for connection success or failure. When poll() returns, this
    1647             :  * function is called to evaluate the result.
    1648             :  *
    1649             :  * Due to differences in behavior of poll() on Linux and BSD - specifically,
    1650             :  * the value of .revents in the case of a closed connection - this function is
    1651             :  * scheduled both for a read and a write event. The write event is triggered
    1652             :  * when the connection is established. A read event is triggered when the
    1653             :  * connection is closed. Thus we need to cancel whichever one did not occur.
    1654             :  */
    1655           3 : static void bgp_connect_check(struct thread *thread)
    1656             : {
    1657           3 :         int status;
    1658           3 :         socklen_t slen;
    1659           3 :         int ret;
    1660           3 :         struct peer *peer;
    1661             : 
    1662           3 :         peer = THREAD_ARG(thread);
    1663           3 :         assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
    1664           3 :         assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
    1665           3 :         assert(!peer->t_read);
    1666           3 :         assert(!peer->t_write);
    1667             : 
    1668           3 :         THREAD_OFF(peer->t_connect_check_r);
    1669           3 :         THREAD_OFF(peer->t_connect_check_w);
    1670             : 
    1671             :         /* Check file descriptor. */
    1672           3 :         slen = sizeof(status);
    1673           3 :         ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *)&status,
    1674             :                          &slen);
    1675             : 
    1676             :         /* If getsockopt is fail, this is fatal error. */
    1677           3 :         if (ret < 0) {
    1678           0 :                 zlog_err("can't get sockopt for nonblocking connect: %d(%s)",
    1679             :                           errno, safe_strerror(errno));
    1680           0 :                 BGP_EVENT_ADD(peer, TCP_fatal_error);
    1681           0 :                 return;
    1682             :         }
    1683             : 
    1684             :         /* When status is 0 then TCP connection is established. */
    1685           3 :         if (status == 0) {
    1686           3 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
    1687           0 :                         BGP_EVENT_ADD(peer, TCP_connection_open_w_delay);
    1688             :                 else
    1689           3 :                         BGP_EVENT_ADD(peer, TCP_connection_open);
    1690           3 :                 return;
    1691             :         } else {
    1692           0 :                 if (bgp_debug_neighbor_events(peer))
    1693           0 :                         zlog_debug("%s [Event] Connect failed %d(%s)",
    1694             :                                    peer->host, status, safe_strerror(status));
    1695           0 :                 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
    1696           0 :                 return;
    1697             :         }
    1698             : }
    1699             : 
    1700             : /* TCP connection open.  Next we send open message to remote peer. And
    1701             :    add read thread for reading open message. */
    1702           6 : static enum bgp_fsm_state_progress bgp_connect_success(struct peer *peer)
    1703             : {
    1704           6 :         if (peer->fd < 0) {
    1705           0 :                 flog_err(EC_BGP_CONNECT, "%s peer's fd is negative value %d",
    1706             :                          __func__, peer->fd);
    1707           0 :                 return bgp_stop(peer);
    1708             :         }
    1709             : 
    1710           6 :         if (bgp_getsockname(peer) < 0) {
    1711           0 :                 flog_err_sys(EC_LIB_SOCKET,
    1712             :                              "%s: bgp_getsockname(): failed for peer %s, fd %d",
    1713             :                              __func__, peer->host, peer->fd);
    1714           0 :                 bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
    1715           0 :                                 bgp_fsm_error_subcode(peer->status));
    1716           0 :                 bgp_writes_on(peer);
    1717           0 :                 return BGP_FSM_FAILURE;
    1718             :         }
    1719             : 
    1720             :         /*
    1721             :          * If we are doing nht for a peer that ls v6 LL based
    1722             :          * massage the event system to make things happy
    1723             :          */
    1724           6 :         bgp_nht_interface_events(peer);
    1725             : 
    1726           6 :         bgp_reads_on(peer);
    1727             : 
    1728           6 :         if (bgp_debug_neighbor_events(peer)) {
    1729           0 :                 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
    1730           0 :                         zlog_debug("%s open active, local address %pSU",
    1731             :                                    peer->host, peer->su_local);
    1732             :                 else
    1733           0 :                         zlog_debug("%s passive open", peer->host);
    1734             :         }
    1735             : 
    1736             :         /* Send an open message */
    1737           6 :         bgp_open_send(peer);
    1738             : 
    1739           6 :         return BGP_FSM_SUCCESS;
    1740             : }
    1741             : 
    1742             : /* TCP connection open with RFC 4271 optional session attribute DelayOpen flag
    1743             :  * set.
    1744             :  */
    1745             : static enum bgp_fsm_state_progress
    1746           0 : bgp_connect_success_w_delayopen(struct peer *peer)
    1747             : {
    1748           0 :         if (peer->fd < 0) {
    1749           0 :                 flog_err(EC_BGP_CONNECT, "%s: peer's fd is negative value %d",
    1750             :                          __func__, peer->fd);
    1751           0 :                 return bgp_stop(peer);
    1752             :         }
    1753             : 
    1754           0 :         if (bgp_getsockname(peer) < 0) {
    1755           0 :                 flog_err_sys(EC_LIB_SOCKET,
    1756             :                              "%s: bgp_getsockname(): failed for peer %s, fd %d",
    1757             :                              __func__, peer->host, peer->fd);
    1758           0 :                 bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
    1759           0 :                                 bgp_fsm_error_subcode(peer->status));
    1760           0 :                 bgp_writes_on(peer);
    1761           0 :                 return BGP_FSM_FAILURE;
    1762             :         }
    1763             : 
    1764             :         /*
    1765             :          * If we are doing nht for a peer that ls v6 LL based
    1766             :          * massage the event system to make things happy
    1767             :          */
    1768           0 :         bgp_nht_interface_events(peer);
    1769             : 
    1770           0 :         bgp_reads_on(peer);
    1771             : 
    1772           0 :         if (bgp_debug_neighbor_events(peer)) {
    1773           0 :                 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
    1774           0 :                         zlog_debug("%s open active, local address %pSU",
    1775             :                                    peer->host, peer->su_local);
    1776             :                 else
    1777           0 :                         zlog_debug("%s passive open", peer->host);
    1778             :         }
    1779             : 
    1780             :         /* set the DelayOpenTime to the inital value */
    1781           0 :         peer->v_delayopen = peer->delayopen;
    1782             : 
    1783             :         /* Start the DelayOpenTimer if it is not already running */
    1784           0 :         if (!peer->t_delayopen)
    1785           0 :                 BGP_TIMER_ON(peer->t_delayopen, bgp_delayopen_timer,
    1786             :                              peer->v_delayopen);
    1787             : 
    1788           0 :         if (bgp_debug_neighbor_events(peer))
    1789           0 :                 zlog_debug("%s [FSM] BGP OPEN message delayed for %d seconds",
    1790             :                            peer->host, peer->delayopen);
    1791             : 
    1792             :         return BGP_FSM_SUCCESS;
    1793             : }
    1794             : 
    1795             : /* TCP connect fail */
    1796           3 : static enum bgp_fsm_state_progress bgp_connect_fail(struct peer *peer)
    1797             : {
    1798           3 :         if (peer_dynamic_neighbor_no_nsf(peer)) {
    1799           0 :                 if (bgp_debug_neighbor_events(peer))
    1800           0 :                         zlog_debug("%s (dynamic neighbor) deleted (%s)",
    1801             :                                    peer->host, __func__);
    1802           0 :                 peer_delete(peer);
    1803           0 :                 return BGP_FSM_FAILURE_AND_DELETE;
    1804             :         }
    1805             : 
    1806             :         /*
    1807             :          * If we are doing nht for a peer that ls v6 LL based
    1808             :          * massage the event system to make things happy
    1809             :          */
    1810           3 :         bgp_nht_interface_events(peer);
    1811             : 
    1812           3 :         return bgp_stop(peer);
    1813             : }
    1814             : 
    1815             : /* This function is the first starting point of all BGP connection. It
    1816             :  * try to connect to remote peer with non-blocking IO.
    1817             :  */
    1818           6 : enum bgp_fsm_state_progress bgp_start(struct peer *peer)
    1819             : {
    1820           6 :         int status;
    1821             : 
    1822           6 :         bgp_peer_conf_if_to_su_update(peer);
    1823             : 
    1824           6 :         if (peer->su.sa.sa_family == AF_UNSPEC) {
    1825           0 :                 if (bgp_debug_neighbor_events(peer))
    1826           0 :                         zlog_debug(
    1827             :                                 "%s [FSM] Unable to get neighbor's IP address, waiting...",
    1828             :                                 peer->host);
    1829           0 :                 peer->last_reset = PEER_DOWN_NBR_ADDR;
    1830           0 :                 return BGP_FSM_FAILURE;
    1831             :         }
    1832             : 
    1833           6 :         if (BGP_PEER_START_SUPPRESSED(peer)) {
    1834           0 :                 if (bgp_debug_neighbor_events(peer))
    1835           0 :                         flog_err(EC_BGP_FSM,
    1836             :                                  "%s [FSM] Trying to start suppressed peer - this is never supposed to happen!",
    1837             :                                  peer->host);
    1838           0 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_RTT_SHUTDOWN))
    1839           0 :                         peer->last_reset = PEER_DOWN_RTT_SHUTDOWN;
    1840           0 :                 else if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
    1841           0 :                         peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
    1842           0 :                 else if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN))
    1843           0 :                         peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
    1844           0 :                 else if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
    1845           0 :                         peer->last_reset = PEER_DOWN_PFX_COUNT;
    1846           0 :                 return BGP_FSM_FAILURE;
    1847             :         }
    1848             : 
    1849             :         /* Scrub some information that might be left over from a previous,
    1850             :          * session
    1851             :          */
    1852             :         /* Connection information. */
    1853           6 :         if (peer->su_local) {
    1854           0 :                 sockunion_free(peer->su_local);
    1855           0 :                 peer->su_local = NULL;
    1856             :         }
    1857             : 
    1858           6 :         if (peer->su_remote) {
    1859           0 :                 sockunion_free(peer->su_remote);
    1860           0 :                 peer->su_remote = NULL;
    1861             :         }
    1862             : 
    1863             :         /* Clear remote router-id. */
    1864           6 :         peer->remote_id.s_addr = INADDR_ANY;
    1865             : 
    1866             :         /* Clear peer capability flag. */
    1867           6 :         peer->cap = 0;
    1868             : 
    1869             :         /* If the peer is passive mode, force to move to Active mode. */
    1870           6 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
    1871           0 :                 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
    1872           0 :                 return BGP_FSM_SUCCESS;
    1873             :         }
    1874             : 
    1875           6 :         if (peer->bgp->vrf_id == VRF_UNKNOWN) {
    1876           0 :                 if (bgp_debug_neighbor_events(peer))
    1877           0 :                         flog_err(
    1878             :                                 EC_BGP_FSM,
    1879             :                                 "%s [FSM] In a VRF that is not initialised yet",
    1880             :                                 peer->host);
    1881           0 :                 peer->last_reset = PEER_DOWN_VRF_UNINIT;
    1882           0 :                 return BGP_FSM_FAILURE;
    1883             :         }
    1884             : 
    1885             :         /* Register peer for NHT. If next hop is already resolved, proceed
    1886             :          * with connection setup, else wait.
    1887             :          */
    1888           6 :         if (!bgp_peer_reg_with_nht(peer)) {
    1889           3 :                 if (bgp_zebra_num_connects()) {
    1890           3 :                         if (bgp_debug_neighbor_events(peer))
    1891           0 :                                 zlog_debug(
    1892             :                                         "%s [FSM] Waiting for NHT, no path to neighbor present",
    1893             :                                         peer->host);
    1894           3 :                         peer->last_reset = PEER_DOWN_WAITING_NHT;
    1895           3 :                         BGP_EVENT_ADD(peer, TCP_connection_open_failed);
    1896           3 :                         return BGP_FSM_SUCCESS;
    1897             :                 }
    1898             :         }
    1899             : 
    1900           3 :         assert(!peer->t_write);
    1901           3 :         assert(!peer->t_read);
    1902           3 :         assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
    1903           3 :         assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
    1904           3 :         status = bgp_connect(peer);
    1905             : 
    1906           3 :         switch (status) {
    1907           0 :         case connect_error:
    1908           0 :                 if (bgp_debug_neighbor_events(peer))
    1909           0 :                         zlog_debug("%s [FSM] Connect error", peer->host);
    1910           0 :                 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
    1911             :                 break;
    1912           0 :         case connect_success:
    1913           0 :                 if (bgp_debug_neighbor_events(peer))
    1914           0 :                         zlog_debug(
    1915             :                                 "%s [FSM] Connect immediately success, fd %d",
    1916             :                                 peer->host, peer->fd);
    1917             : 
    1918           0 :                 BGP_EVENT_ADD(peer, TCP_connection_open);
    1919             :                 break;
    1920           3 :         case connect_in_progress:
    1921             :                 /* To check nonblocking connect, we wait until socket is
    1922             :                    readable or writable. */
    1923           3 :                 if (bgp_debug_neighbor_events(peer))
    1924           0 :                         zlog_debug(
    1925             :                                 "%s [FSM] Non blocking connect waiting result, fd %d",
    1926             :                                 peer->host, peer->fd);
    1927           3 :                 if (peer->fd < 0) {
    1928           0 :                         flog_err(EC_BGP_FSM,
    1929             :                                  "%s peer's fd is negative value %d", __func__,
    1930             :                                  peer->fd);
    1931           0 :                         return BGP_FSM_FAILURE;
    1932             :                 }
    1933             :                 /*
    1934             :                  * - when the socket becomes ready, poll() will signify POLLOUT
    1935             :                  * - if it fails to connect, poll() will signify POLLHUP
    1936             :                  * - POLLHUP is handled as a 'read' event by thread.c
    1937             :                  *
    1938             :                  * therefore, we schedule both a read and a write event with
    1939             :                  * bgp_connect_check() as the handler for each and cancel the
    1940             :                  * unused event in that function.
    1941             :                  */
    1942           3 :                 thread_add_read(bm->master, bgp_connect_check, peer, peer->fd,
    1943             :                                 &peer->t_connect_check_r);
    1944           3 :                 thread_add_write(bm->master, bgp_connect_check, peer, peer->fd,
    1945             :                                  &peer->t_connect_check_w);
    1946           3 :                 break;
    1947             :         }
    1948             :         return BGP_FSM_SUCCESS;
    1949             : }
    1950             : 
    1951             : /* Connect retry timer is expired when the peer status is Connect. */
    1952           0 : static enum bgp_fsm_state_progress bgp_reconnect(struct peer *peer)
    1953             : {
    1954           0 :         enum bgp_fsm_state_progress ret;
    1955             : 
    1956           0 :         ret = bgp_stop(peer);
    1957           0 :         if (ret < BGP_FSM_SUCCESS)
    1958             :                 return ret;
    1959             : 
    1960             :         /* Send graceful restart capabilty */
    1961           0 :         BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
    1962             :                                                           peer->bgp->peer);
    1963             : 
    1964           0 :         return bgp_start(peer);
    1965             : }
    1966             : 
    1967           4 : static enum bgp_fsm_state_progress bgp_fsm_open(struct peer *peer)
    1968             : {
    1969             :         /* If DelayOpen is active, we may still need to send an open message */
    1970           4 :         if ((peer->status == Connect) || (peer->status == Active))
    1971           0 :                 bgp_open_send(peer);
    1972             : 
    1973             :         /* Send keepalive and make keepalive timer */
    1974           4 :         bgp_keepalive_send(peer);
    1975             : 
    1976           4 :         return BGP_FSM_SUCCESS;
    1977             : }
    1978             : 
    1979             : /* FSM error, unexpected event.  This is error of BGP connection. So cut the
    1980             :    peer and change to Idle status. */
    1981           0 : static enum bgp_fsm_state_progress bgp_fsm_event_error(struct peer *peer)
    1982             : {
    1983           0 :         flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s",
    1984             :                  peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
    1985             : 
    1986           0 :         return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR,
    1987           0 :                                     bgp_fsm_error_subcode(peer->status));
    1988             : }
    1989             : 
    1990             : /* Hold timer expire.  This is error of BGP connection. So cut the
    1991             :    peer and change to Idle status. */
    1992           0 : static enum bgp_fsm_state_progress bgp_fsm_holdtime_expire(struct peer *peer)
    1993             : {
    1994           0 :         if (bgp_debug_neighbor_events(peer))
    1995           0 :                 zlog_debug("%s [FSM] Hold timer expire", peer->host);
    1996             : 
    1997             :         /* RFC8538 updates RFC 4724 by defining an extension that permits
    1998             :          * the Graceful Restart procedures to be performed when the BGP
    1999             :          * speaker receives a BGP NOTIFICATION message or the Hold Time expires.
    2000             :          */
    2001           0 :         if (peer_established(peer) &&
    2002           0 :             bgp_has_graceful_restart_notification(peer))
    2003           0 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE))
    2004           0 :                         SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
    2005             : 
    2006           0 :         return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0);
    2007             : }
    2008             : 
    2009             : /* RFC 4271 DelayOpenTimer_Expires event */
    2010             : static enum bgp_fsm_state_progress
    2011           0 : bgp_fsm_delayopen_timer_expire(struct peer *peer)
    2012             : {
    2013             :         /* Stop the DelayOpenTimer */
    2014           0 :         THREAD_OFF(peer->t_delayopen);
    2015             : 
    2016             :         /* Send open message to peer */
    2017           0 :         bgp_open_send(peer);
    2018             : 
    2019             :         /* Set the HoldTimer to a large value (4 minutes) */
    2020           0 :         peer->v_holdtime = 245;
    2021             : 
    2022           0 :         return BGP_FSM_SUCCESS;
    2023             : }
    2024             : 
    2025             : /* Start the selection deferral timer thread for the specified AFI, SAFI */
    2026           0 : static int bgp_start_deferral_timer(struct bgp *bgp, afi_t afi, safi_t safi,
    2027             :                                     struct graceful_restart_info *gr_info)
    2028             : {
    2029           0 :         struct afi_safi_info *thread_info;
    2030             : 
    2031             :         /* If the deferral timer is active, then increment eor count */
    2032           0 :         if (gr_info->t_select_deferral) {
    2033           0 :                 gr_info->eor_required++;
    2034           0 :                 return 0;
    2035             :         }
    2036             : 
    2037             :         /* Start the deferral timer when the first peer enabled for the graceful
    2038             :          * restart is established
    2039             :          */
    2040           0 :         if (gr_info->eor_required == 0) {
    2041           0 :                 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
    2042             : 
    2043           0 :                 thread_info->afi = afi;
    2044           0 :                 thread_info->safi = safi;
    2045           0 :                 thread_info->bgp = bgp;
    2046             : 
    2047           0 :                 thread_add_timer(bm->master, bgp_graceful_deferral_timer_expire,
    2048             :                                  thread_info, bgp->select_defer_time,
    2049             :                                  &gr_info->t_select_deferral);
    2050             :         }
    2051           0 :         gr_info->eor_required++;
    2052             :         /* Send message to RIB indicating route update pending */
    2053           0 :         if (gr_info->af_enabled[afi][safi] == false) {
    2054           0 :                 gr_info->af_enabled[afi][safi] = true;
    2055             :                 /* Send message to RIB */
    2056           0 :                 bgp_zebra_update(afi, safi, bgp->vrf_id,
    2057             :                                  ZEBRA_CLIENT_ROUTE_UPDATE_PENDING);
    2058             :         }
    2059           0 :         if (BGP_DEBUG(update, UPDATE_OUT))
    2060           0 :                 zlog_debug("Started the deferral timer for %s eor_required %d",
    2061             :                            get_afi_safi_str(afi, safi, false),
    2062             :                            gr_info->eor_required);
    2063             :         return 0;
    2064             : }
    2065             : 
    2066             : /* Update the graceful restart information for the specified AFI, SAFI */
    2067           4 : static int bgp_update_gr_info(struct peer *peer, afi_t afi, safi_t safi)
    2068             : {
    2069           4 :         struct graceful_restart_info *gr_info;
    2070           4 :         struct bgp *bgp = peer->bgp;
    2071           4 :         int ret = 0;
    2072             : 
    2073           4 :         if ((afi < AFI_IP) || (afi >= AFI_MAX)) {
    2074           0 :                 if (BGP_DEBUG(update, UPDATE_OUT))
    2075           0 :                         zlog_debug("%s : invalid afi %d", __func__, afi);
    2076           0 :                 return -1;
    2077             :         }
    2078             : 
    2079           4 :         if ((safi < SAFI_UNICAST) || (safi > SAFI_MPLS_VPN)) {
    2080           0 :                 if (BGP_DEBUG(update, UPDATE_OUT))
    2081           0 :                         zlog_debug("%s : invalid safi %d", __func__, safi);
    2082           0 :                 return -1;
    2083             :         }
    2084             : 
    2085             :         /* Restarting router */
    2086           4 :         if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
    2087           4 :             && BGP_PEER_RESTARTING_MODE(peer)) {
    2088             :                 /* Check if the forwarding state is preserved */
    2089           0 :                 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD)) {
    2090           0 :                         gr_info = &(bgp->gr_info[afi][safi]);
    2091           0 :                         ret = bgp_start_deferral_timer(bgp, afi, safi, gr_info);
    2092             :                 }
    2093             :         }
    2094             :         return ret;
    2095             : }
    2096             : 
    2097             : /**
    2098             :  * Transition to Established state.
    2099             :  *
    2100             :  * Convert peer from stub to full fledged peer, set some timers, and generate
    2101             :  * initial updates.
    2102             :  */
    2103           4 : static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
    2104             : {
    2105           4 :         afi_t afi;
    2106           4 :         safi_t safi;
    2107           4 :         int nsf_af_count = 0;
    2108           4 :         enum bgp_fsm_state_progress ret = BGP_FSM_SUCCESS;
    2109           4 :         struct peer *other;
    2110           4 :         int status;
    2111             : 
    2112           4 :         other = peer->doppelganger;
    2113           4 :         hash_release(peer->bgp->peerhash, peer);
    2114           4 :         if (other)
    2115           2 :                 hash_release(peer->bgp->peerhash, other);
    2116             : 
    2117           4 :         peer = peer_xfer_conn(peer);
    2118           4 :         if (!peer) {
    2119           0 :                 flog_err(EC_BGP_CONNECT, "%%Neighbor failed in xfer_conn");
    2120           0 :                 return BGP_FSM_FAILURE;
    2121             :         }
    2122             : 
    2123           4 :         if (other == peer)
    2124           2 :                 ret = BGP_FSM_SUCCESS_STATE_TRANSFER;
    2125             : 
    2126             :         /* Reset capability open status flag. */
    2127           4 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
    2128           0 :                 SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
    2129             : 
    2130             :         /* Clear start timer value to default. */
    2131           4 :         peer->v_start = BGP_INIT_START_TIMER;
    2132             : 
    2133             :         /* Increment established count. */
    2134           4 :         peer->established++;
    2135           4 :         bgp_fsm_change_status(peer, Established);
    2136             : 
    2137             :         /* bgp log-neighbor-changes of neighbor Up */
    2138           4 :         if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
    2139           0 :                 struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
    2140           0 :                 zlog_info("%%ADJCHANGE: neighbor %pBP in vrf %s Up", peer,
    2141             :                           vrf ? ((vrf->vrf_id != VRF_DEFAULT)
    2142             :                                          ? vrf->name
    2143             :                                          : VRF_DEFAULT_NAME)
    2144             :                               : "");
    2145             :         }
    2146             :         /* assign update-group/subgroup */
    2147           4 :         update_group_adjust_peer_afs(peer);
    2148             : 
    2149             :         /* graceful restart */
    2150           4 :         UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
    2151           4 :         if (bgp_debug_neighbor_events(peer)) {
    2152           0 :                 if (BGP_PEER_RESTARTING_MODE(peer))
    2153           0 :                         zlog_debug("%pBP BGP_RESTARTING_MODE", peer);
    2154           0 :                 else if (BGP_PEER_HELPER_MODE(peer))
    2155           0 :                         zlog_debug("%pBP BGP_HELPER_MODE", peer);
    2156             :         }
    2157             : 
    2158          52 :         FOREACH_AFI_SAFI_NSF (afi, safi) {
    2159          36 :                 if (peer->afc_nego[afi][safi] &&
    2160           4 :                     CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV) &&
    2161           4 :                     CHECK_FLAG(peer->af_cap[afi][safi],
    2162             :                                PEER_CAP_RESTART_AF_RCV)) {
    2163           0 :                         if (peer->nsf[afi][safi] &&
    2164           0 :                             !CHECK_FLAG(peer->af_cap[afi][safi],
    2165             :                                         PEER_CAP_RESTART_AF_PRESERVE_RCV))
    2166           0 :                                 bgp_clear_stale_route(peer, afi, safi);
    2167             : 
    2168           0 :                         peer->nsf[afi][safi] = 1;
    2169           0 :                         nsf_af_count++;
    2170             :                 } else {
    2171          36 :                         if (peer->nsf[afi][safi])
    2172           0 :                                 bgp_clear_stale_route(peer, afi, safi);
    2173          36 :                         peer->nsf[afi][safi] = 0;
    2174             :                 }
    2175             :                 /* Update the graceful restart information */
    2176          36 :                 if (peer->afc_nego[afi][safi]) {
    2177           4 :                         if (!BGP_SELECT_DEFER_DISABLE(peer->bgp)) {
    2178           4 :                                 status = bgp_update_gr_info(peer, afi, safi);
    2179           4 :                                 if (status < 0)
    2180           0 :                                         zlog_err(
    2181             :                                                 "Error in updating graceful restart for %s",
    2182             :                                                 get_afi_safi_str(afi, safi,
    2183             :                                                                  false));
    2184             :                         } else {
    2185           0 :                                 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer) &&
    2186           0 :                                     BGP_PEER_RESTARTING_MODE(peer) &&
    2187           0 :                                     CHECK_FLAG(peer->bgp->flags,
    2188             :                                                BGP_FLAG_GR_PRESERVE_FWD))
    2189           0 :                                         peer->bgp->gr_info[afi][safi]
    2190           0 :                                                 .eor_required++;
    2191             :                         }
    2192             :                 }
    2193             :         }
    2194             : 
    2195           4 :         if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
    2196           0 :                 if ((bgp_peer_gr_mode_get(peer) == PEER_GR)
    2197           0 :                     || ((bgp_peer_gr_mode_get(peer) == PEER_GLOBAL_INHERIT)
    2198           0 :                         && (bgp_global_gr_mode_get(peer->bgp) == GLOBAL_GR))) {
    2199           0 :                         FOREACH_AFI_SAFI (afi, safi)
    2200             :                                 /* Send route processing complete
    2201             :                                    message to RIB */
    2202           0 :                                 bgp_zebra_update(
    2203           0 :                                         afi, safi, peer->bgp->vrf_id,
    2204             :                                         ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
    2205             :                 }
    2206             :         } else {
    2207             :                 /* Peer sends R-bit. In this case, we need to send
    2208             :                  * ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE to Zebra. */
    2209           4 :                 if (CHECK_FLAG(peer->cap,
    2210             :                                PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)) {
    2211         100 :                         FOREACH_AFI_SAFI (afi, safi)
    2212             :                                 /* Send route processing complete
    2213             :                                    message to RIB */
    2214          84 :                                 bgp_zebra_update(
    2215          84 :                                         afi, safi, peer->bgp->vrf_id,
    2216             :                                         ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
    2217             :                 }
    2218             :         }
    2219             : 
    2220           4 :         peer->nsf_af_count = nsf_af_count;
    2221             : 
    2222           4 :         if (nsf_af_count)
    2223           0 :                 SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
    2224             :         else {
    2225           4 :                 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
    2226           4 :                 if (peer->t_gr_stale) {
    2227           0 :                         THREAD_OFF(peer->t_gr_stale);
    2228           0 :                         if (bgp_debug_neighbor_events(peer))
    2229           0 :                                 zlog_debug(
    2230             :                                         "%pBP graceful restart stalepath timer stopped",
    2231             :                                         peer);
    2232             :                 }
    2233             :         }
    2234             : 
    2235           4 :         if (peer->t_gr_restart) {
    2236           0 :                 THREAD_OFF(peer->t_gr_restart);
    2237           0 :                 if (bgp_debug_neighbor_events(peer))
    2238           0 :                         zlog_debug("%pBP graceful restart timer stopped", peer);
    2239             :         }
    2240             : 
    2241             :         /* Reset uptime, turn on keepalives, send current table. */
    2242           4 :         if (!peer->v_holdtime)
    2243           0 :                 bgp_keepalives_on(peer);
    2244             : 
    2245           4 :         peer->uptime = monotime(NULL);
    2246             : 
    2247             :         /* Send route-refresh when ORF is enabled.
    2248             :          * Stop Long-lived Graceful Restart timers.
    2249             :          */
    2250         100 :         FOREACH_AFI_SAFI (afi, safi) {
    2251          84 :                 if (peer->t_llgr_stale[afi][safi]) {
    2252           0 :                         THREAD_OFF(peer->t_llgr_stale[afi][safi]);
    2253           0 :                         if (bgp_debug_neighbor_events(peer))
    2254           0 :                                 zlog_debug(
    2255             :                                         "%pBP Long-lived stale timer stopped for afi/safi: %d/%d",
    2256             :                                         peer, afi, safi);
    2257             :                 }
    2258             : 
    2259          84 :                 if (CHECK_FLAG(peer->af_cap[afi][safi],
    2260             :                                PEER_CAP_ORF_PREFIX_SM_ADV)) {
    2261           0 :                         if (CHECK_FLAG(peer->af_cap[afi][safi],
    2262             :                                        PEER_CAP_ORF_PREFIX_RM_RCV))
    2263           0 :                                 bgp_route_refresh_send(
    2264             :                                         peer, afi, safi, ORF_TYPE_PREFIX,
    2265             :                                         REFRESH_IMMEDIATE, 0,
    2266             :                                         BGP_ROUTE_REFRESH_NORMAL);
    2267           0 :                         else if (CHECK_FLAG(peer->af_cap[afi][safi],
    2268             :                                             PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
    2269           0 :                                 bgp_route_refresh_send(
    2270             :                                         peer, afi, safi, ORF_TYPE_PREFIX_OLD,
    2271             :                                         REFRESH_IMMEDIATE, 0,
    2272             :                                         BGP_ROUTE_REFRESH_NORMAL);
    2273             :                 }
    2274             :         }
    2275             : 
    2276             :         /* First update is deferred until ORF or ROUTE-REFRESH is received */
    2277         100 :         FOREACH_AFI_SAFI (afi, safi) {
    2278          84 :                 if (CHECK_FLAG(peer->af_cap[afi][safi],
    2279             :                                PEER_CAP_ORF_PREFIX_RM_ADV))
    2280           0 :                         if (CHECK_FLAG(peer->af_cap[afi][safi],
    2281             :                                        PEER_CAP_ORF_PREFIX_SM_RCV)
    2282           0 :                             || CHECK_FLAG(peer->af_cap[afi][safi],
    2283             :                                           PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
    2284           0 :                                 SET_FLAG(peer->af_sflags[afi][safi],
    2285             :                                          PEER_STATUS_ORF_WAIT_REFRESH);
    2286             :         }
    2287             : 
    2288           4 :         bgp_announce_peer(peer);
    2289             : 
    2290             :         /* Start the route advertisement timer to send updates to the peer - if
    2291             :          * BGP
    2292             :          * is not in read-only mode. If it is, the timer will be started at the
    2293             :          * end
    2294             :          * of read-only mode.
    2295             :          */
    2296           4 :         if (!bgp_update_delay_active(peer->bgp)) {
    2297           4 :                 THREAD_OFF(peer->t_routeadv);
    2298           4 :                 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
    2299             :         }
    2300             : 
    2301           4 :         if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
    2302           2 :                 if (bgp_debug_neighbor_events(peer))
    2303           0 :                         zlog_debug(
    2304             :                                 "[Event] Deleting stub connection for peer %s",
    2305             :                                 peer->host);
    2306             : 
    2307           2 :                 if (peer->doppelganger->status > Active)
    2308           0 :                         bgp_notify_send(peer->doppelganger, BGP_NOTIFY_CEASE,
    2309             :                                         BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
    2310             :                 else
    2311           2 :                         peer_delete(peer->doppelganger);
    2312             :         }
    2313             : 
    2314             :         /*
    2315             :          * If we are replacing the old peer for a doppelganger
    2316             :          * then switch it around in the bgp->peerhash
    2317             :          * the doppelgangers su and this peer's su are the same
    2318             :          * so the hash_release is the same for either.
    2319             :          */
    2320           4 :         (void)hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
    2321             : 
    2322             :         /* Start BFD peer if not already running. */
    2323           4 :         if (peer->bfd_config)
    2324           0 :                 bgp_peer_bfd_update_source(peer);
    2325             : 
    2326             :         return ret;
    2327             : }
    2328             : 
    2329             : /* Keepalive packet is received. */
    2330           4 : static enum bgp_fsm_state_progress bgp_fsm_keepalive(struct peer *peer)
    2331             : {
    2332           4 :         THREAD_OFF(peer->t_holdtime);
    2333           4 :         return BGP_FSM_SUCCESS;
    2334             : }
    2335             : 
    2336             : /* Update packet is received. */
    2337          12 : static enum bgp_fsm_state_progress bgp_fsm_update(struct peer *peer)
    2338             : {
    2339          12 :         THREAD_OFF(peer->t_holdtime);
    2340          12 :         return BGP_FSM_SUCCESS;
    2341             : }
    2342             : 
    2343             : /* This is empty event. */
    2344           0 : static enum bgp_fsm_state_progress bgp_ignore(struct peer *peer)
    2345             : {
    2346           0 :         flog_err(
    2347             :                 EC_BGP_FSM,
    2348             :                 "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
    2349             :                 peer->host, bgp_event_str[peer->cur_event],
    2350             :                 lookup_msg(bgp_status_msg, peer->status, NULL),
    2351             :                 bgp_event_str[peer->last_event],
    2352             :                 bgp_event_str[peer->last_major_event], peer->fd);
    2353           0 :         return BGP_FSM_SUCCESS;
    2354             : }
    2355             : 
    2356             : /* This is to handle unexpected events.. */
    2357           0 : static enum bgp_fsm_state_progress bgp_fsm_exception(struct peer *peer)
    2358             : {
    2359           0 :         flog_err(
    2360             :                 EC_BGP_FSM,
    2361             :                 "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
    2362             :                 peer->host, bgp_event_str[peer->cur_event],
    2363             :                 lookup_msg(bgp_status_msg, peer->status, NULL),
    2364             :                 bgp_event_str[peer->last_event],
    2365             :                 bgp_event_str[peer->last_major_event], peer->fd);
    2366           0 :         return bgp_stop(peer);
    2367             : }
    2368             : 
    2369           3 : void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops)
    2370             : {
    2371           3 :         if (!peer)
    2372             :                 return;
    2373             : 
    2374           3 :         switch (peer->status) {
    2375           0 :         case Idle:
    2376           0 :                 if (has_valid_nexthops)
    2377           0 :                         BGP_EVENT_ADD(peer, BGP_Start);
    2378             :                 break;
    2379           0 :         case Connect:
    2380           0 :                 if (!has_valid_nexthops) {
    2381           0 :                         THREAD_OFF(peer->t_connect);
    2382           0 :                         BGP_EVENT_ADD(peer, TCP_fatal_error);
    2383             :                 }
    2384             :                 break;
    2385           3 :         case Active:
    2386           3 :                 if (has_valid_nexthops) {
    2387           3 :                         THREAD_OFF(peer->t_connect);
    2388           3 :                         BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
    2389             :                 }
    2390             :                 break;
    2391           0 :         case OpenSent:
    2392             :         case OpenConfirm:
    2393             :         case Established:
    2394           0 :                 if (!has_valid_nexthops
    2395           0 :                     && (peer->gtsm_hops == BGP_GTSM_HOPS_CONNECTED
    2396           0 :                         || peer->bgp->fast_convergence))
    2397           0 :                         BGP_EVENT_ADD(peer, TCP_fatal_error);
    2398             :         case Clearing:
    2399             :         case Deleted:
    2400             :         case BGP_STATUS_MAX:
    2401             :                 break;
    2402             :         }
    2403             : }
    2404             : 
    2405             : /* Finite State Machine structure */
    2406             : static const struct {
    2407             :         enum bgp_fsm_state_progress (*func)(struct peer *);
    2408             :         enum bgp_fsm_status next_state;
    2409             : } FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = {
    2410             :         {
    2411             :                 /* Idle state: In Idle state, all events other than BGP_Start is
    2412             :                    ignored.  With BGP_Start event, finite state machine calls
    2413             :                    bgp_start(). */
    2414             :                 {bgp_start, Connect}, /* BGP_Start                    */
    2415             :                 {bgp_stop, Idle},     /* BGP_Stop                     */
    2416             :                 {bgp_stop, Idle},     /* TCP_connection_open          */
    2417             :                 {bgp_stop, Idle},     /* TCP_connection_open_w_delay */
    2418             :                 {bgp_stop, Idle},     /* TCP_connection_closed        */
    2419             :                 {bgp_ignore, Idle},   /* TCP_connection_open_failed   */
    2420             :                 {bgp_stop, Idle},     /* TCP_fatal_error              */
    2421             :                 {bgp_ignore, Idle},   /* ConnectRetry_timer_expired   */
    2422             :                 {bgp_ignore, Idle},   /* Hold_Timer_expired           */
    2423             :                 {bgp_ignore, Idle},   /* KeepAlive_timer_expired      */
    2424             :                 {bgp_ignore, Idle},   /* DelayOpen_timer_expired */
    2425             :                 {bgp_ignore, Idle},   /* Receive_OPEN_message         */
    2426             :                 {bgp_ignore, Idle},   /* Receive_KEEPALIVE_message    */
    2427             :                 {bgp_ignore, Idle},   /* Receive_UPDATE_message       */
    2428             :                 {bgp_ignore, Idle},   /* Receive_NOTIFICATION_message */
    2429             :                 {bgp_ignore, Idle},   /* Clearing_Completed           */
    2430             :         },
    2431             :         {
    2432             :                 /* Connect */
    2433             :                 {bgp_ignore, Connect}, /* BGP_Start                    */
    2434             :                 {bgp_stop, Idle},      /* BGP_Stop                     */
    2435             :                 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
    2436             :                 {bgp_connect_success_w_delayopen,
    2437             :                  Connect},                  /* TCP_connection_open_w_delay */
    2438             :                 {bgp_stop, Idle},           /* TCP_connection_closed        */
    2439             :                 {bgp_connect_fail, Active}, /* TCP_connection_open_failed   */
    2440             :                 {bgp_connect_fail, Idle},   /* TCP_fatal_error              */
    2441             :                 {bgp_reconnect, Connect},   /* ConnectRetry_timer_expired   */
    2442             :                 {bgp_fsm_exception, Idle},  /* Hold_Timer_expired           */
    2443             :                 {bgp_fsm_exception, Idle},  /* KeepAlive_timer_expired      */
    2444             :                 {bgp_fsm_delayopen_timer_expire,
    2445             :                  OpenSent},                  /* DelayOpen_timer_expired */
    2446             :                 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message         */
    2447             :                 {bgp_fsm_exception, Idle},   /* Receive_KEEPALIVE_message    */
    2448             :                 {bgp_fsm_exception, Idle},   /* Receive_UPDATE_message       */
    2449             :                 {bgp_stop, Idle},            /* Receive_NOTIFICATION_message */
    2450             :                 {bgp_fsm_exception, Idle},   /* Clearing_Completed           */
    2451             :         },
    2452             :         {
    2453             :                 /* Active, */
    2454             :                 {bgp_ignore, Active}, /* BGP_Start                    */
    2455             :                 {bgp_stop, Idle},     /* BGP_Stop                     */
    2456             :                 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
    2457             :                 {bgp_connect_success_w_delayopen,
    2458             :                  Active},                  /* TCP_connection_open_w_delay */
    2459             :                 {bgp_stop, Idle},          /* TCP_connection_closed        */
    2460             :                 {bgp_ignore, Active},      /* TCP_connection_open_failed   */
    2461             :                 {bgp_fsm_exception, Idle}, /* TCP_fatal_error              */
    2462             :                 {bgp_start, Connect},      /* ConnectRetry_timer_expired   */
    2463             :                 {bgp_fsm_exception, Idle}, /* Hold_Timer_expired           */
    2464             :                 {bgp_fsm_exception, Idle}, /* KeepAlive_timer_expired      */
    2465             :                 {bgp_fsm_delayopen_timer_expire,
    2466             :                  OpenSent},                  /* DelayOpen_timer_expired */
    2467             :                 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message         */
    2468             :                 {bgp_fsm_exception, Idle},   /* Receive_KEEPALIVE_message    */
    2469             :                 {bgp_fsm_exception, Idle},   /* Receive_UPDATE_message       */
    2470             :                 {bgp_fsm_exception, Idle},   /* Receive_NOTIFICATION_message */
    2471             :                 {bgp_fsm_exception, Idle},   /* Clearing_Completed           */
    2472             :         },
    2473             :         {
    2474             :                 /* OpenSent, */
    2475             :                 {bgp_ignore, OpenSent},    /* BGP_Start                    */
    2476             :                 {bgp_stop, Idle},          /* BGP_Stop                     */
    2477             :                 {bgp_stop, Active},        /* TCP_connection_open          */
    2478             :                 {bgp_fsm_exception, Idle}, /* TCP_connection_open_w_delay */
    2479             :                 {bgp_stop, Active},        /* TCP_connection_closed        */
    2480             :                 {bgp_stop, Active},        /* TCP_connection_open_failed   */
    2481             :                 {bgp_stop, Active},        /* TCP_fatal_error              */
    2482             :                 {bgp_fsm_exception, Idle}, /* ConnectRetry_timer_expired   */
    2483             :                 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
    2484             :                 {bgp_fsm_exception, Idle},   /* KeepAlive_timer_expired      */
    2485             :                 {bgp_fsm_exception, Idle},   /* DelayOpen_timer_expired */
    2486             :                 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message         */
    2487             :                 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message    */
    2488             :                 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message       */
    2489             :                 {bgp_fsm_event_error, Idle}, /* Receive_NOTIFICATION_message */
    2490             :                 {bgp_fsm_exception, Idle},   /* Clearing_Completed           */
    2491             :         },
    2492             :         {
    2493             :                 /* OpenConfirm, */
    2494             :                 {bgp_ignore, OpenConfirm}, /* BGP_Start                    */
    2495             :                 {bgp_stop, Idle},          /* BGP_Stop                     */
    2496             :                 {bgp_stop, Idle},          /* TCP_connection_open          */
    2497             :                 {bgp_fsm_exception, Idle}, /* TCP_connection_open_w_delay */
    2498             :                 {bgp_stop, Idle},          /* TCP_connection_closed        */
    2499             :                 {bgp_stop, Idle},          /* TCP_connection_open_failed   */
    2500             :                 {bgp_stop, Idle},          /* TCP_fatal_error              */
    2501             :                 {bgp_fsm_exception, Idle}, /* ConnectRetry_timer_expired   */
    2502             :                 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
    2503             :                 {bgp_ignore, OpenConfirm},    /* KeepAlive_timer_expired      */
    2504             :                 {bgp_fsm_exception, Idle},    /* DelayOpen_timer_expired */
    2505             :                 {bgp_fsm_exception, Idle},    /* Receive_OPEN_message         */
    2506             :                 {bgp_establish, Established}, /* Receive_KEEPALIVE_message    */
    2507             :                 {bgp_fsm_exception, Idle},    /* Receive_UPDATE_message       */
    2508             :                 {bgp_stop_with_error, Idle},  /* Receive_NOTIFICATION_message */
    2509             :                 {bgp_fsm_exception, Idle},    /* Clearing_Completed           */
    2510             :         },
    2511             :         {
    2512             :                 /* Established, */
    2513             :                 {bgp_ignore, Established}, /* BGP_Start                    */
    2514             :                 {bgp_stop, Clearing},      /* BGP_Stop                     */
    2515             :                 {bgp_stop, Clearing},      /* TCP_connection_open          */
    2516             :                 {bgp_fsm_exception, Idle}, /* TCP_connection_open_w_delay */
    2517             :                 {bgp_stop, Clearing},      /* TCP_connection_closed        */
    2518             :                 {bgp_stop, Clearing},      /* TCP_connection_open_failed   */
    2519             :                 {bgp_stop, Clearing},      /* TCP_fatal_error              */
    2520             :                 {bgp_stop, Clearing},      /* ConnectRetry_timer_expired   */
    2521             :                 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
    2522             :                 {bgp_ignore, Established}, /* KeepAlive_timer_expired      */
    2523             :                 {bgp_fsm_exception, Idle}, /* DelayOpen_timer_expired */
    2524             :                 {bgp_stop, Clearing},      /* Receive_OPEN_message         */
    2525             :                 {bgp_fsm_keepalive,
    2526             :                  Established}, /* Receive_KEEPALIVE_message    */
    2527             :                 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
    2528             :                 {bgp_stop_with_error,
    2529             :                  Clearing},                /* Receive_NOTIFICATION_message */
    2530             :                 {bgp_fsm_exception, Idle}, /* Clearing_Completed           */
    2531             :         },
    2532             :         {
    2533             :                 /* Clearing, */
    2534             :                 {bgp_ignore, Clearing}, /* BGP_Start                    */
    2535             :                 {bgp_stop, Clearing},   /* BGP_Stop                     */
    2536             :                 {bgp_stop, Clearing},   /* TCP_connection_open          */
    2537             :                 {bgp_stop, Clearing},   /* TCP_connection_open_w_delay */
    2538             :                 {bgp_stop, Clearing},   /* TCP_connection_closed        */
    2539             :                 {bgp_stop, Clearing},   /* TCP_connection_open_failed   */
    2540             :                 {bgp_stop, Clearing},   /* TCP_fatal_error              */
    2541             :                 {bgp_stop, Clearing},   /* ConnectRetry_timer_expired   */
    2542             :                 {bgp_stop, Clearing},   /* Hold_Timer_expired           */
    2543             :                 {bgp_stop, Clearing},   /* KeepAlive_timer_expired      */
    2544             :                 {bgp_stop, Clearing},   /* DelayOpen_timer_expired */
    2545             :                 {bgp_stop, Clearing},   /* Receive_OPEN_message         */
    2546             :                 {bgp_stop, Clearing},   /* Receive_KEEPALIVE_message    */
    2547             :                 {bgp_stop, Clearing},   /* Receive_UPDATE_message       */
    2548             :                 {bgp_stop, Clearing},   /* Receive_NOTIFICATION_message */
    2549             :                 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
    2550             :         },
    2551             :         {
    2552             :                 /* Deleted, */
    2553             :                 {bgp_ignore, Deleted}, /* BGP_Start                    */
    2554             :                 {bgp_ignore, Deleted}, /* BGP_Stop                     */
    2555             :                 {bgp_ignore, Deleted}, /* TCP_connection_open          */
    2556             :                 {bgp_ignore, Deleted}, /* TCP_connection_open_w_delay */
    2557             :                 {bgp_ignore, Deleted}, /* TCP_connection_closed        */
    2558             :                 {bgp_ignore, Deleted}, /* TCP_connection_open_failed   */
    2559             :                 {bgp_ignore, Deleted}, /* TCP_fatal_error              */
    2560             :                 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired   */
    2561             :                 {bgp_ignore, Deleted}, /* Hold_Timer_expired           */
    2562             :                 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired      */
    2563             :                 {bgp_ignore, Deleted}, /* DelayOpen_timer_expired */
    2564             :                 {bgp_ignore, Deleted}, /* Receive_OPEN_message         */
    2565             :                 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message    */
    2566             :                 {bgp_ignore, Deleted}, /* Receive_UPDATE_message       */
    2567             :                 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
    2568             :                 {bgp_ignore, Deleted}, /* Clearing_Completed           */
    2569             :         },
    2570             : };
    2571             : 
    2572             : /* Execute event process. */
    2573          17 : void bgp_event(struct thread *thread)
    2574             : {
    2575          17 :         enum bgp_fsm_events event;
    2576          17 :         struct peer *peer;
    2577             : 
    2578          17 :         peer = THREAD_ARG(thread);
    2579          17 :         event = THREAD_VAL(thread);
    2580             : 
    2581          17 :         peer_lock(peer);
    2582          17 :         bgp_event_update(peer, event);
    2583          17 :         peer_unlock(peer);
    2584          17 : }
    2585             : 
    2586          45 : int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
    2587             : {
    2588          45 :         enum bgp_fsm_status next;
    2589          45 :         enum bgp_fsm_state_progress ret = 0;
    2590          45 :         struct peer *other;
    2591          45 :         int passive_conn = 0;
    2592          45 :         int dyn_nbr;
    2593             : 
    2594             :         /* default return code */
    2595          45 :         ret = FSM_PEER_NOOP;
    2596             : 
    2597          45 :         other = peer->doppelganger;
    2598          45 :         passive_conn =
    2599          45 :                 (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0;
    2600          45 :         dyn_nbr = peer_dynamic_neighbor(peer);
    2601             : 
    2602             :         /* Logging this event. */
    2603          45 :         next = FSM[peer->status - 1][event - 1].next_state;
    2604             : 
    2605          45 :         if (bgp_debug_neighbor_events(peer) && peer->status != next)
    2606           0 :                 zlog_debug("%s [FSM] %s (%s->%s), fd %d", peer->host,
    2607             :                            bgp_event_str[event],
    2608             :                            lookup_msg(bgp_status_msg, peer->status, NULL),
    2609             :                            lookup_msg(bgp_status_msg, next, NULL), peer->fd);
    2610             : 
    2611          45 :         peer->last_event = peer->cur_event;
    2612          45 :         peer->cur_event = event;
    2613             : 
    2614             :         /* Call function. */
    2615          45 :         if (FSM[peer->status - 1][event - 1].func)
    2616          45 :                 ret = (*(FSM[peer->status - 1][event - 1].func))(peer);
    2617             : 
    2618          45 :         if (ret >= BGP_FSM_SUCCESS) {
    2619          44 :                 if (ret == BGP_FSM_SUCCESS_STATE_TRANSFER &&
    2620          44 :                     next == Established) {
    2621             :                         /* The case when doppelganger swap accurred in
    2622             :                            bgp_establish.
    2623             :                            Update the peer pointer accordingly */
    2624           2 :                         ret = FSM_PEER_TRANSFERRED;
    2625           2 :                         peer = other;
    2626             :                 }
    2627             : 
    2628             :                 /* If status is changed. */
    2629          44 :                 if (next != peer->status) {
    2630          24 :                         bgp_fsm_change_status(peer, next);
    2631             : 
    2632             :                         /*
    2633             :                          * If we're going to ESTABLISHED then we executed a
    2634             :                          * peer transfer. In this case we can either return
    2635             :                          * FSM_PEER_TRANSITIONED or FSM_PEER_TRANSFERRED.
    2636             :                          * Opting for TRANSFERRED since transfer implies
    2637             :                          * session establishment.
    2638             :                          */
    2639          24 :                         if (ret != FSM_PEER_TRANSFERRED)
    2640          24 :                                 ret = FSM_PEER_TRANSITIONED;
    2641             :                 }
    2642             : 
    2643             :                 /* Make sure timer is set. */
    2644          44 :                 bgp_timer_set(peer);
    2645             : 
    2646             :         } else {
    2647             :                 /*
    2648             :                  * If we got a return value of -1, that means there was an
    2649             :                  * error, restart the FSM. Since bgp_stop() was called on the
    2650             :                  * peer. only a few fields are safe to access here. In any case
    2651             :                  * we need to indicate that the peer was stopped in the return
    2652             :                  * code.
    2653             :                  */
    2654           1 :                 if (!dyn_nbr && !passive_conn && peer->bgp &&
    2655             :                     ret != BGP_FSM_FAILURE_AND_DELETE) {
    2656           0 :                         flog_err(
    2657             :                                 EC_BGP_FSM,
    2658             :                                 "%s [FSM] Failure handling event %s in state %s, prior events %s, %s, fd %d",
    2659             :                                 peer->host, bgp_event_str[peer->cur_event],
    2660             :                                 lookup_msg(bgp_status_msg, peer->status, NULL),
    2661             :                                 bgp_event_str[peer->last_event],
    2662             :                                 bgp_event_str[peer->last_major_event],
    2663             :                                 peer->fd);
    2664           0 :                         bgp_stop(peer);
    2665           0 :                         bgp_fsm_change_status(peer, Idle);
    2666           0 :                         bgp_timer_set(peer);
    2667             :                 }
    2668             :                 ret = FSM_PEER_STOPPED;
    2669             :         }
    2670             : 
    2671          45 :         return ret;
    2672             : }
    2673             : /* BGP GR Code */
    2674             : 
    2675           0 : int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp,
    2676             :                                     enum global_mode global_new_state,
    2677             :                                     enum global_mode global_old_state)
    2678             : {
    2679           0 :         struct peer *peer = {0};
    2680           0 :         struct listnode *node = {0};
    2681           0 :         struct listnode *nnode = {0};
    2682           0 :         enum peer_mode peer_old_state = PEER_INVALID;
    2683             : 
    2684           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
    2685             : 
    2686           0 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2687           0 :                         zlog_debug("%s [BGP_GR] Peer: (%s) :", __func__,
    2688             :                                    peer->host);
    2689             : 
    2690           0 :                 peer_old_state = bgp_peer_gr_mode_get(peer);
    2691             : 
    2692           0 :                 if (peer_old_state == PEER_GLOBAL_INHERIT) {
    2693             : 
    2694             :                         /*
    2695             :                          *Reset only these peers and send a
    2696             :                          *new open message with the change capabilities.
    2697             :                          *Considering the mode to be "global_new_state" and
    2698             :                          *do all operation accordingly
    2699             :                          */
    2700             : 
    2701           0 :                         switch (global_new_state) {
    2702           0 :                         case GLOBAL_HELPER:
    2703           0 :                                 BGP_PEER_GR_HELPER_ENABLE(peer);
    2704           0 :                                 break;
    2705           0 :                         case GLOBAL_GR:
    2706           0 :                                 BGP_PEER_GR_ENABLE(peer);
    2707           0 :                                 break;
    2708           0 :                         case GLOBAL_DISABLE:
    2709           0 :                                 BGP_PEER_GR_DISABLE(peer);
    2710           0 :                                 break;
    2711           0 :                         case GLOBAL_INVALID:
    2712           0 :                                 zlog_debug("%s [BGP_GR] GLOBAL_INVALID",
    2713             :                                            __func__);
    2714           0 :                                 return BGP_ERR_GR_OPERATION_FAILED;
    2715             :                         }
    2716             :                 }
    2717             :         }
    2718             : 
    2719           0 :         bgp->global_gr_present_state = global_new_state;
    2720             : 
    2721           0 :         return BGP_GR_SUCCESS;
    2722             : }
    2723             : 
    2724           0 : int bgp_gr_update_all(struct bgp *bgp, int global_gr_cmd)
    2725             : {
    2726           0 :         enum global_mode global_new_state = GLOBAL_INVALID;
    2727           0 :         enum global_mode global_old_state = GLOBAL_INVALID;
    2728             : 
    2729           0 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2730           0 :                 zlog_debug("%s [BGP_GR]START: global_gr_cmd :%s:", __func__,
    2731             :                            print_global_gr_cmd(global_gr_cmd));
    2732             : 
    2733           0 :         global_old_state = bgp_global_gr_mode_get(bgp);
    2734             : 
    2735           0 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2736           0 :                 zlog_debug("[BGP_GR] global_old_gr_state :%s:",
    2737             :                            print_global_gr_mode(global_old_state));
    2738             : 
    2739           0 :         if (global_old_state != GLOBAL_INVALID) {
    2740           0 :                 global_new_state =
    2741             :                         bgp->GLOBAL_GR_FSM[global_old_state][global_gr_cmd];
    2742             : 
    2743           0 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2744           0 :                         zlog_debug("[BGP_GR] global_new_gr_state :%s:",
    2745             :                                    print_global_gr_mode(global_new_state));
    2746             :         } else {
    2747           0 :                 zlog_err("%s [BGP_GR] global_old_state == GLOBAL_INVALID",
    2748             :                          __func__);
    2749           0 :                 return BGP_ERR_GR_OPERATION_FAILED;
    2750             :         }
    2751             : 
    2752           0 :         if (global_new_state == GLOBAL_INVALID) {
    2753           0 :                 zlog_err("%s [BGP_GR] global_new_state == GLOBAL_INVALID",
    2754             :                          __func__);
    2755           0 :                 return BGP_ERR_GR_INVALID_CMD;
    2756             :         }
    2757           0 :         if (global_new_state == global_old_state) {
    2758             :                 /* Trace msg */
    2759           0 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2760           0 :                         zlog_debug(
    2761             :                                 "%s [BGP_GR] global_new_state == global_old_state :%s",
    2762             :                                 __func__,
    2763             :                                 print_global_gr_mode(global_new_state));
    2764           0 :                 return BGP_GR_NO_OPERATION;
    2765             :         }
    2766             : 
    2767           0 :         return bgp_gr_lookup_n_update_all_peer(bgp, global_new_state,
    2768             :                                                global_old_state);
    2769             : }
    2770             : 
    2771           0 : const char *print_peer_gr_mode(enum peer_mode pr_mode)
    2772             : {
    2773           0 :         const char *peer_gr_mode = NULL;
    2774             : 
    2775           0 :         switch (pr_mode) {
    2776           0 :         case PEER_HELPER:
    2777           0 :                 peer_gr_mode = "PEER_HELPER";
    2778           0 :                 break;
    2779           0 :         case PEER_GR:
    2780           0 :                 peer_gr_mode = "PEER_GR";
    2781           0 :                 break;
    2782           0 :         case PEER_DISABLE:
    2783           0 :                 peer_gr_mode = "PEER_DISABLE";
    2784           0 :                 break;
    2785           0 :         case PEER_INVALID:
    2786           0 :                 peer_gr_mode = "PEER_INVALID";
    2787           0 :                 break;
    2788           0 :         case PEER_GLOBAL_INHERIT:
    2789           0 :                 peer_gr_mode = "PEER_GLOBAL_INHERIT";
    2790           0 :                 break;
    2791             :         }
    2792             : 
    2793           0 :         return peer_gr_mode;
    2794             : }
    2795             : 
    2796           0 : const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd)
    2797             : {
    2798           0 :         const char *peer_gr_cmd = NULL;
    2799             : 
    2800           0 :         switch (pr_gr_cmd) {
    2801           0 :         case PEER_GR_CMD:
    2802           0 :                 peer_gr_cmd = "PEER_GR_CMD";
    2803           0 :                 break;
    2804           0 :         case NO_PEER_GR_CMD:
    2805           0 :                 peer_gr_cmd = "NO_PEER_GR_CMD";
    2806           0 :                 break;
    2807           0 :         case PEER_DISABLE_CMD:
    2808           0 :                 peer_gr_cmd = "PEER_DISABLE_GR_CMD";
    2809           0 :                 break;
    2810           0 :         case NO_PEER_DISABLE_CMD:
    2811           0 :                 peer_gr_cmd = "NO_PEER_DISABLE_GR_CMD";
    2812           0 :                 break;
    2813           0 :         case PEER_HELPER_CMD:
    2814           0 :                 peer_gr_cmd = "PEER_HELPER_CMD";
    2815           0 :                 break;
    2816           0 :         case NO_PEER_HELPER_CMD:
    2817           0 :                 peer_gr_cmd = "NO_PEER_HELPER_CMD";
    2818           0 :                 break;
    2819             :         }
    2820             : 
    2821           0 :         return peer_gr_cmd;
    2822             : }
    2823             : 
    2824           0 : const char *print_global_gr_mode(enum global_mode gl_mode)
    2825             : {
    2826           0 :         const char *global_gr_mode = NULL;
    2827             : 
    2828           0 :         switch (gl_mode) {
    2829           0 :         case GLOBAL_HELPER:
    2830           0 :                 global_gr_mode = "GLOBAL_HELPER";
    2831           0 :                 break;
    2832           0 :         case GLOBAL_GR:
    2833           0 :                 global_gr_mode = "GLOBAL_GR";
    2834           0 :                 break;
    2835           0 :         case GLOBAL_DISABLE:
    2836           0 :                 global_gr_mode = "GLOBAL_DISABLE";
    2837           0 :                 break;
    2838           0 :         case GLOBAL_INVALID:
    2839           0 :                 global_gr_mode = "GLOBAL_INVALID";
    2840           0 :                 break;
    2841             :         }
    2842             : 
    2843           0 :         return global_gr_mode;
    2844             : }
    2845             : 
    2846           0 : const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd)
    2847             : {
    2848           0 :         const char *global_gr_cmd = NULL;
    2849             : 
    2850           0 :         switch (gl_gr_cmd) {
    2851           0 :         case GLOBAL_GR_CMD:
    2852           0 :                 global_gr_cmd = "GLOBAL_GR_CMD";
    2853           0 :                 break;
    2854           0 :         case NO_GLOBAL_GR_CMD:
    2855           0 :                 global_gr_cmd = "NO_GLOBAL_GR_CMD";
    2856           0 :                 break;
    2857           0 :         case GLOBAL_DISABLE_CMD:
    2858           0 :                 global_gr_cmd = "GLOBAL_DISABLE_CMD";
    2859           0 :                 break;
    2860           0 :         case NO_GLOBAL_DISABLE_CMD:
    2861           0 :                 global_gr_cmd = "NO_GLOBAL_DISABLE_CMD";
    2862           0 :                 break;
    2863             :         }
    2864             : 
    2865           0 :         return global_gr_cmd;
    2866             : }
    2867             : 
    2868          10 : enum global_mode bgp_global_gr_mode_get(struct bgp *bgp)
    2869             : {
    2870           0 :         return bgp->global_gr_present_state;
    2871             : }
    2872             : 
    2873           5 : enum peer_mode bgp_peer_gr_mode_get(struct peer *peer)
    2874             : {
    2875           2 :         return peer->peer_gr_present_state;
    2876             : }
    2877             : 
    2878           0 : int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd)
    2879             : {
    2880           0 :         enum peer_mode peer_new_state = PEER_INVALID;
    2881           0 :         enum peer_mode peer_old_state = PEER_INVALID;
    2882           0 :         struct bgp_peer_gr peer_state;
    2883           0 :         int result = BGP_GR_FAILURE;
    2884             : 
    2885             :         /*
    2886             :          * fetch peer_old_state from peer structure also
    2887             :          * fetch global_old_state from bgp structure,
    2888             :          * peer had a back pointer to bgpo struct ;
    2889             :          */
    2890             : 
    2891           0 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2892           0 :                 zlog_debug("%s [BGP_GR] START:Peer: (%s) : peer_gr_cmd :%s:",
    2893             :                            __func__, peer->host,
    2894             :                            print_peer_gr_cmd(peer_gr_cmd));
    2895             : 
    2896           0 :         peer_old_state = bgp_peer_gr_mode_get(peer);
    2897             : 
    2898           0 :         if (peer_old_state == PEER_INVALID) {
    2899           0 :                 zlog_debug("[BGP_GR] peer_old_state == Invalid state !");
    2900           0 :                 return BGP_ERR_GR_OPERATION_FAILED;
    2901             :         }
    2902             : 
    2903           0 :         peer_state = peer->PEER_GR_FSM[peer_old_state][peer_gr_cmd];
    2904           0 :         peer_new_state = peer_state.next_state;
    2905             : 
    2906           0 :         if (peer_new_state == PEER_INVALID) {
    2907           0 :                 zlog_debug(
    2908             :                         "[BGP_GR] Invalid bgp graceful restart command used !");
    2909           0 :                 return BGP_ERR_GR_INVALID_CMD;
    2910             :         }
    2911             : 
    2912           0 :         if (peer_new_state != peer_old_state) {
    2913           0 :                 result = peer_state.action_fun(peer, peer_old_state,
    2914             :                                                peer_new_state);
    2915             :         } else {
    2916           0 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2917           0 :                         zlog_debug(
    2918             :                                 "[BGP_GR] peer_old_state == peer_new_state !");
    2919           0 :                 return BGP_GR_NO_OPERATION;
    2920             :         }
    2921             : 
    2922           0 :         if (result == BGP_GR_SUCCESS) {
    2923             : 
    2924             :                 /* Update the mode i.e peer_new_state into the peer structure */
    2925           0 :                 peer->peer_gr_present_state = peer_new_state;
    2926           0 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2927           0 :                         zlog_debug(
    2928             :                                 "[BGP_GR] Successfully change the state of the peer to : %s : !",
    2929             :                                 print_peer_gr_mode(peer_new_state));
    2930             : 
    2931           0 :                 return BGP_GR_SUCCESS;
    2932             :         }
    2933             : 
    2934             :         return result;
    2935             : }
    2936             : 
    2937           0 : unsigned int bgp_peer_gr_action(struct peer *peer, int old_peer_state,
    2938             :                                 int new_peer_state)
    2939             : {
    2940           0 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2941           0 :                 zlog_debug(
    2942             :                         "%s [BGP_GR] Move peer from old_peer_state :%s: to new_peer_state :%s: !!!!",
    2943             :                         __func__, print_peer_gr_mode(old_peer_state),
    2944             :                         print_peer_gr_mode(new_peer_state));
    2945             : 
    2946           0 :         int bgp_gr_global_mode = GLOBAL_INVALID;
    2947           0 :         unsigned int ret = BGP_GR_FAILURE;
    2948             : 
    2949           0 :         if (old_peer_state == new_peer_state) {
    2950             :                 /* Nothing to do over here as the present and old state is the
    2951             :                  * same */
    2952             :                 return BGP_GR_NO_OPERATION;
    2953             :         }
    2954           0 :         if ((old_peer_state == PEER_INVALID)
    2955           0 :             || (new_peer_state == PEER_INVALID)) {
    2956             :                 /* something bad happend , print error message */
    2957             :                 return BGP_ERR_GR_INVALID_CMD;
    2958             :         }
    2959             : 
    2960           0 :         bgp_gr_global_mode = bgp_global_gr_mode_get(peer->bgp);
    2961             : 
    2962           0 :         if ((old_peer_state == PEER_GLOBAL_INHERIT)
    2963           0 :             && (new_peer_state != PEER_GLOBAL_INHERIT)) {
    2964             : 
    2965             :                 /* fetch the Mode running in the Global state machine
    2966             :                  *from the bgp structure into a variable called
    2967             :                  *bgp_gr_global_mode
    2968             :                  */
    2969             : 
    2970             :                 /* Here we are checking if the
    2971             :                  *1. peer_new_state == global_mode == helper_mode
    2972             :                  *2. peer_new_state == global_mode == GR_mode
    2973             :                  *3. peer_new_state == global_mode == disabled_mode
    2974             :                  */
    2975             : 
    2976           0 :                 BGP_PEER_GR_GLOBAL_INHERIT_UNSET(peer);
    2977             : 
    2978           0 :                 if (new_peer_state == bgp_gr_global_mode) {
    2979             :                         /*This is incremental updates i.e no tear down
    2980             :                          *of the existing session
    2981             :                          *as the peer is already working in the same mode.
    2982             :                          */
    2983             :                         ret = BGP_GR_SUCCESS;
    2984             :                 } else {
    2985           0 :                         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    2986           0 :                                 zlog_debug(
    2987             :                                         "[BGP_GR] Peer state changed from :%s ",
    2988             :                                         print_peer_gr_mode(old_peer_state));
    2989             : 
    2990           0 :                         bgp_peer_move_to_gr_mode(peer, new_peer_state);
    2991             : 
    2992           0 :                         ret = BGP_GR_SUCCESS;
    2993             :                 }
    2994             :         }
    2995             :         /* In the case below peer is going into Global inherit mode i.e.
    2996             :          * the peer would work as the mode configured at the global level
    2997             :          */
    2998           0 :         else if ((new_peer_state == PEER_GLOBAL_INHERIT)
    2999           0 :                  && (old_peer_state != PEER_GLOBAL_INHERIT)) {
    3000             :                 /* Here in this case it would be destructive
    3001             :                  * in all the cases except one case when,
    3002             :                  * Global GR is configured Disabled
    3003             :                  * and present_peer_state is not disable
    3004             :                  */
    3005             : 
    3006           0 :                 BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
    3007             : 
    3008           0 :                 if (old_peer_state == bgp_gr_global_mode) {
    3009             : 
    3010             :                         /* This is incremental updates
    3011             :                          *i.e no tear down of the existing session
    3012             :                          *as the peer is already working in the same mode.
    3013             :                          */
    3014             :                         ret = BGP_GR_SUCCESS;
    3015             :                 } else {
    3016             :                         /*  Destructive always */
    3017             :                         /*  Tear down the old session
    3018             :                          *  and send the new capability
    3019             :                          *  as per the bgp_gr_global_mode
    3020             :                          */
    3021             : 
    3022           0 :                         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    3023           0 :                                 zlog_debug(
    3024             :                                         "[BGP_GR] Peer state changed from :%s",
    3025             :                                         print_peer_gr_mode(old_peer_state));
    3026             : 
    3027           0 :                         bgp_peer_move_to_gr_mode(peer, bgp_gr_global_mode);
    3028             : 
    3029           0 :                         ret = BGP_GR_SUCCESS;
    3030             :                 }
    3031             :         } else {
    3032             :                 /*
    3033             :                  *This else case, it include all the cases except -->
    3034             :                  *(new_peer_state != Peer_Global) &&
    3035             :                  *( old_peer_state != Peer_Global )
    3036             :                  */
    3037           0 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    3038           0 :                         zlog_debug("[BGP_GR] Peer state changed from :%s",
    3039             :                                    print_peer_gr_mode(old_peer_state));
    3040             : 
    3041           0 :                 bgp_peer_move_to_gr_mode(peer, new_peer_state);
    3042             : 
    3043           0 :                 ret = BGP_GR_SUCCESS;
    3044             :         }
    3045             : 
    3046             :         return ret;
    3047             : }
    3048             : 
    3049          10 : inline void bgp_peer_move_to_gr_mode(struct peer *peer, int new_state)
    3050             : 
    3051             : {
    3052          10 :         int bgp_global_gr_mode = bgp_global_gr_mode_get(peer->bgp);
    3053             : 
    3054          10 :         switch (new_state) {
    3055           0 :         case PEER_HELPER:
    3056           0 :                 BGP_PEER_GR_HELPER_ENABLE(peer);
    3057           0 :                 break;
    3058           0 :         case PEER_GR:
    3059           0 :                 BGP_PEER_GR_ENABLE(peer);
    3060           0 :                 break;
    3061           0 :         case PEER_DISABLE:
    3062           0 :                 BGP_PEER_GR_DISABLE(peer);
    3063           0 :                 break;
    3064          10 :         case PEER_GLOBAL_INHERIT:
    3065          10 :                 BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
    3066             : 
    3067          10 :                 if (bgp_global_gr_mode == GLOBAL_HELPER) {
    3068          10 :                         BGP_PEER_GR_HELPER_ENABLE(peer);
    3069           0 :                 } else if (bgp_global_gr_mode == GLOBAL_GR) {
    3070           0 :                         BGP_PEER_GR_ENABLE(peer);
    3071           0 :                 } else if (bgp_global_gr_mode == GLOBAL_DISABLE) {
    3072           0 :                         BGP_PEER_GR_DISABLE(peer);
    3073             :                 } else {
    3074           0 :                         zlog_err(
    3075             :                                 "[BGP_GR] Default switch inherit mode ::: SOMETHING IS WRONG !!!");
    3076             :                 }
    3077             :                 break;
    3078           0 :         default:
    3079           0 :                 zlog_err(
    3080             :                         "[BGP_GR] Default switch mode ::: SOMETHING IS WRONG !!!");
    3081           0 :                 break;
    3082             :         }
    3083          10 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    3084           0 :                 zlog_debug("[BGP_GR] Peer state changed  --to-->  : %d : !",
    3085             :                            new_state);
    3086          10 : }
    3087             : 
    3088          14 : void bgp_peer_gr_flags_update(struct peer *peer)
    3089             : {
    3090          14 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    3091           0 :                 zlog_debug("%s [BGP_GR] called !", __func__);
    3092          14 :         if (CHECK_FLAG(peer->peer_gr_new_status_flag,
    3093             :                        PEER_GRACEFUL_RESTART_NEW_STATE_HELPER))
    3094          14 :                 SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
    3095             :         else
    3096           0 :                 UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
    3097          14 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    3098           0 :                 zlog_debug(
    3099             :                         "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_HELPER : %s : !",
    3100             :                         peer->host,
    3101             :                         (CHECK_FLAG(peer->flags,
    3102             :                                     PEER_FLAG_GRACEFUL_RESTART_HELPER)
    3103             :                                  ? "Set"
    3104             :                                  : "UnSet"));
    3105          14 :         if (CHECK_FLAG(peer->peer_gr_new_status_flag,
    3106             :                        PEER_GRACEFUL_RESTART_NEW_STATE_RESTART))
    3107           0 :                 SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
    3108             :         else
    3109          14 :                 UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
    3110          14 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    3111           0 :                 zlog_debug(
    3112             :                         "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART : %s : !",
    3113             :                         peer->host,
    3114             :                         (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
    3115             :                                  ? "Set"
    3116             :                                  : "UnSet"));
    3117          14 :         if (CHECK_FLAG(peer->peer_gr_new_status_flag,
    3118             :                        PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT))
    3119          14 :                 SET_FLAG(peer->flags,
    3120             :                          PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT);
    3121             :         else
    3122           0 :                 UNSET_FLAG(peer->flags,
    3123             :                            PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT);
    3124          14 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    3125           0 :                 zlog_debug(
    3126             :                         "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT : %s : !",
    3127             :                         peer->host,
    3128             :                         (CHECK_FLAG(peer->flags,
    3129             :                                     PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT)
    3130             :                                  ? "Set"
    3131             :                                  : "UnSet"));
    3132             : 
    3133          14 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
    3134          14 :             && !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER)) {
    3135           0 :                 zlog_debug("[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_MODE!",
    3136             :                            peer->host);
    3137             : 
    3138           0 :                 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
    3139             : 
    3140           0 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
    3141             : 
    3142           0 :                         peer_nsf_stop(peer);
    3143           0 :                         zlog_debug(
    3144             :                                 "[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_WAIT!",
    3145             :                                 peer->host);
    3146             :                 }
    3147             :         }
    3148          14 : }

Generated by: LCOV version v1.16-topotato