LCOV - code coverage report
Current view: top level - bgpd - bgp_fsm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 375 0.0 %
Date: 2015-11-19 Functions: 0 27 0.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
      18             : along with GNU Zebra; see the file COPYING.  If not, write to the Free
      19             : Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             : 02111-1307, USA.  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "linklist.h"
      25             : #include "prefix.h"
      26             : #include "vty.h"
      27             : #include "sockunion.h"
      28             : #include "thread.h"
      29             : #include "log.h"
      30             : #include "stream.h"
      31             : #include "memory.h"
      32             : #include "plist.h"
      33             : 
      34             : #include "bgpd/bgpd.h"
      35             : #include "bgpd/bgp_attr.h"
      36             : #include "bgpd/bgp_debug.h"
      37             : #include "bgpd/bgp_fsm.h"
      38             : #include "bgpd/bgp_packet.h"
      39             : #include "bgpd/bgp_network.h"
      40             : #include "bgpd/bgp_route.h"
      41             : #include "bgpd/bgp_dump.h"
      42             : #include "bgpd/bgp_open.h"
      43             : #ifdef HAVE_SNMP
      44             : #include "bgpd/bgp_snmp.h"
      45             : #endif /* HAVE_SNMP */
      46             : 
      47             : /* BGP FSM (finite state machine) has three types of functions.  Type
      48             :    one is thread functions.  Type two is event functions.  Type three
      49             :    is FSM functions.  Timer functions are set by bgp_timer_set
      50             :    function. */
      51             : 
      52             : /* BGP event function. */
      53             : int bgp_event (struct thread *);
      54             : 
      55             : /* BGP thread functions. */
      56             : static int bgp_start_timer (struct thread *);
      57             : static int bgp_connect_timer (struct thread *);
      58             : static int bgp_holdtime_timer (struct thread *);
      59             : static int bgp_keepalive_timer (struct thread *);
      60             : 
      61             : /* BGP FSM functions. */
      62             : static int bgp_start (struct peer *);
      63             : 
      64             : /* BGP start timer jitter. */
      65             : static int
      66           0 : bgp_start_jitter (int time)
      67             : {
      68           0 :   return ((rand () % (time + 1)) - (time / 2));
      69             : }
      70             : 
      71             : /* Check if suppress start/restart of sessions to peer. */
      72             : #define BGP_PEER_START_SUPPRESSED(P) \
      73             :   (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \
      74             :    || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW))
      75             : 
      76             : /* Hook function called after bgp event is occered.  And vty's
      77             :    neighbor command invoke this function after making neighbor
      78             :    structure. */
      79             : void
      80           0 : bgp_timer_set (struct peer *peer)
      81             : {
      82           0 :   int jitter = 0;
      83             : 
      84           0 :   switch (peer->status)
      85             :     {
      86             :     case Idle:
      87             :       /* First entry point of peer's finite state machine.  In Idle
      88             :          status start timer is on unless peer is shutdown or peer is
      89             :          inactive.  All other timer must be turned off */
      90           0 :       if (BGP_PEER_START_SUPPRESSED (peer) || ! peer_active (peer))
      91             :         {
      92           0 :           BGP_TIMER_OFF (peer->t_start);
      93             :         }
      94             :       else
      95             :         {
      96           0 :           jitter = bgp_start_jitter (peer->v_start);
      97           0 :           BGP_TIMER_ON (peer->t_start, bgp_start_timer,
      98             :                         peer->v_start + jitter);
      99             :         }
     100           0 :       BGP_TIMER_OFF (peer->t_connect);
     101           0 :       BGP_TIMER_OFF (peer->t_holdtime);
     102           0 :       BGP_TIMER_OFF (peer->t_keepalive);
     103           0 :       BGP_TIMER_OFF (peer->t_asorig);
     104           0 :       BGP_TIMER_OFF (peer->t_routeadv);
     105           0 :       break;
     106             : 
     107             :     case Connect:
     108             :       /* After start timer is expired, the peer moves to Connnect
     109             :          status.  Make sure start timer is off and connect timer is
     110             :          on. */
     111           0 :       BGP_TIMER_OFF (peer->t_start);
     112           0 :       BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
     113           0 :       BGP_TIMER_OFF (peer->t_holdtime);
     114           0 :       BGP_TIMER_OFF (peer->t_keepalive);
     115           0 :       BGP_TIMER_OFF (peer->t_asorig);
     116           0 :       BGP_TIMER_OFF (peer->t_routeadv);
     117           0 :       break;
     118             : 
     119             :     case Active:
     120             :       /* Active is waiting connection from remote peer.  And if
     121             :          connect timer is expired, change status to Connect. */
     122           0 :       BGP_TIMER_OFF (peer->t_start);
     123             :       /* If peer is passive mode, do not set connect timer. */
     124           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)
     125           0 :           || CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
     126             :         {
     127           0 :           BGP_TIMER_OFF (peer->t_connect);
     128             :         }
     129             :       else
     130             :         {
     131           0 :           BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
     132             :         }
     133           0 :       BGP_TIMER_OFF (peer->t_holdtime);
     134           0 :       BGP_TIMER_OFF (peer->t_keepalive);
     135           0 :       BGP_TIMER_OFF (peer->t_asorig);
     136           0 :       BGP_TIMER_OFF (peer->t_routeadv);
     137           0 :       break;
     138             : 
     139             :     case OpenSent:
     140             :       /* OpenSent status. */
     141           0 :       BGP_TIMER_OFF (peer->t_start);
     142           0 :       BGP_TIMER_OFF (peer->t_connect);
     143           0 :       if (peer->v_holdtime != 0)
     144             :         {
     145           0 :           BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer, 
     146             :                         peer->v_holdtime);
     147             :         }
     148             :       else
     149             :         {
     150           0 :           BGP_TIMER_OFF (peer->t_holdtime);
     151             :         }
     152           0 :       BGP_TIMER_OFF (peer->t_keepalive);
     153           0 :       BGP_TIMER_OFF (peer->t_asorig);
     154           0 :       BGP_TIMER_OFF (peer->t_routeadv);
     155           0 :       break;
     156             : 
     157             :     case OpenConfirm:
     158             :       /* OpenConfirm status. */
     159           0 :       BGP_TIMER_OFF (peer->t_start);
     160           0 :       BGP_TIMER_OFF (peer->t_connect);
     161             : 
     162             :       /* If the negotiated Hold Time value is zero, then the Hold Time
     163             :          timer and KeepAlive timers are not started. */
     164           0 :       if (peer->v_holdtime == 0)
     165             :         {
     166           0 :           BGP_TIMER_OFF (peer->t_holdtime);
     167           0 :           BGP_TIMER_OFF (peer->t_keepalive);
     168             :         }
     169             :       else
     170             :         {
     171           0 :           BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
     172             :                         peer->v_holdtime);
     173           0 :           BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, 
     174             :                         peer->v_keepalive);
     175             :         }
     176           0 :       BGP_TIMER_OFF (peer->t_asorig);
     177           0 :       BGP_TIMER_OFF (peer->t_routeadv);
     178           0 :       break;
     179             : 
     180             :     case Established:
     181             :       /* In Established status start and connect timer is turned
     182             :          off. */
     183           0 :       BGP_TIMER_OFF (peer->t_start);
     184           0 :       BGP_TIMER_OFF (peer->t_connect);
     185             : 
     186             :       /* Same as OpenConfirm, if holdtime is zero then both holdtime
     187             :          and keepalive must be turned off. */
     188           0 :       if (peer->v_holdtime == 0)
     189             :         {
     190           0 :           BGP_TIMER_OFF (peer->t_holdtime);
     191           0 :           BGP_TIMER_OFF (peer->t_keepalive);
     192             :         }
     193             :       else
     194             :         {
     195           0 :           BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
     196             :                         peer->v_holdtime);
     197           0 :           BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
     198             :                         peer->v_keepalive);
     199             :         }
     200           0 :       BGP_TIMER_OFF (peer->t_asorig);
     201           0 :       break;
     202             :     case Deleted:
     203           0 :       BGP_TIMER_OFF (peer->t_gr_restart);
     204           0 :       BGP_TIMER_OFF (peer->t_gr_stale);
     205           0 :       BGP_TIMER_OFF (peer->t_pmax_restart);
     206             :     case Clearing:
     207           0 :       BGP_TIMER_OFF (peer->t_start);
     208           0 :       BGP_TIMER_OFF (peer->t_connect);
     209           0 :       BGP_TIMER_OFF (peer->t_holdtime);
     210           0 :       BGP_TIMER_OFF (peer->t_keepalive);
     211           0 :       BGP_TIMER_OFF (peer->t_asorig);
     212           0 :       BGP_TIMER_OFF (peer->t_routeadv);
     213             :     }
     214           0 : }
     215             : 
     216             : /* BGP start timer.  This function set BGP_Start event to thread value
     217             :    and process event. */
     218             : static int
     219           0 : bgp_start_timer (struct thread *thread)
     220             : {
     221             :   struct peer *peer;
     222             : 
     223           0 :   peer = THREAD_ARG (thread);
     224           0 :   peer->t_start = NULL;
     225             : 
     226           0 :   if (BGP_DEBUG (fsm, FSM))
     227           0 :     zlog (peer->log, LOG_DEBUG,
     228             :           "%s [FSM] Timer (start timer expire).", peer->host);
     229             : 
     230           0 :   THREAD_VAL (thread) = BGP_Start;
     231           0 :   bgp_event (thread);  /* bgp_event unlocks peer */
     232             : 
     233           0 :   return 0;
     234             : }
     235             : 
     236             : /* BGP connect retry timer. */
     237             : static int
     238           0 : bgp_connect_timer (struct thread *thread)
     239             : {
     240             :   struct peer *peer;
     241             : 
     242           0 :   peer = THREAD_ARG (thread);
     243           0 :   peer->t_connect = NULL;
     244             : 
     245           0 :   if (BGP_DEBUG (fsm, FSM))
     246           0 :     zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)",
     247             :           peer->host);
     248             : 
     249           0 :   THREAD_VAL (thread) = ConnectRetry_timer_expired;
     250           0 :   bgp_event (thread); /* bgp_event unlocks peer */
     251             : 
     252           0 :   return 0;
     253             : }
     254             : 
     255             : /* BGP holdtime timer. */
     256             : static int
     257           0 : bgp_holdtime_timer (struct thread *thread)
     258             : {
     259             :   struct peer *peer;
     260             : 
     261           0 :   peer = THREAD_ARG (thread);
     262           0 :   peer->t_holdtime = NULL;
     263             : 
     264           0 :   if (BGP_DEBUG (fsm, FSM))
     265           0 :     zlog (peer->log, LOG_DEBUG,
     266             :           "%s [FSM] Timer (holdtime timer expire)",
     267             :           peer->host);
     268             : 
     269           0 :   THREAD_VAL (thread) = Hold_Timer_expired;
     270           0 :   bgp_event (thread); /* bgp_event unlocks peer */
     271             : 
     272           0 :   return 0;
     273             : }
     274             : 
     275             : /* BGP keepalive fire ! */
     276             : static int
     277           0 : bgp_keepalive_timer (struct thread *thread)
     278             : {
     279             :   struct peer *peer;
     280             : 
     281           0 :   peer = THREAD_ARG (thread);
     282           0 :   peer->t_keepalive = NULL;
     283             : 
     284           0 :   if (BGP_DEBUG (fsm, FSM))
     285           0 :     zlog (peer->log, LOG_DEBUG,
     286             :           "%s [FSM] Timer (keepalive timer expire)",
     287             :           peer->host);
     288             : 
     289           0 :   THREAD_VAL (thread) = KeepAlive_timer_expired;
     290           0 :   bgp_event (thread); /* bgp_event unlocks peer */
     291             : 
     292           0 :   return 0;
     293             : }
     294             : 
     295             : static int
     296           0 : bgp_routeadv_timer (struct thread *thread)
     297             : {
     298             :   struct peer *peer;
     299             : 
     300           0 :   peer = THREAD_ARG (thread);
     301           0 :   peer->t_routeadv = NULL;
     302             : 
     303           0 :   if (BGP_DEBUG (fsm, FSM))
     304           0 :     zlog (peer->log, LOG_DEBUG,
     305             :           "%s [FSM] Timer (routeadv timer expire)",
     306             :           peer->host);
     307             : 
     308           0 :   peer->synctime = bgp_clock ();
     309             : 
     310           0 :   BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     311             : 
     312           0 :   BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
     313             :                 peer->v_routeadv);
     314             : 
     315           0 :   return 0;
     316             : }
     317             : 
     318             : /* BGP Peer Down Cause */
     319             : const char *peer_down_str[] =
     320             : {
     321             :   "",
     322             :   "Router ID changed",
     323             :   "Remote AS changed",
     324             :   "Local AS change",
     325             :   "Cluster ID changed",
     326             :   "Confederation identifier changed",
     327             :   "Confederation peer changed",
     328             :   "RR client config change",
     329             :   "RS client config change",
     330             :   "Update source change",
     331             :   "Address family activated",
     332             :   "Admin. shutdown",
     333             :   "User reset",
     334             :   "BGP Notification received",
     335             :   "BGP Notification send",
     336             :   "Peer closed the session",
     337             :   "Neighbor deleted",
     338             :   "Peer-group add member",
     339             :   "Peer-group delete member",
     340             :   "Capability changed",
     341             :   "Passive config change",
     342             :   "Multihop config change",
     343             :   "NSF peer closed the session"
     344             : };
     345             : 
     346             : static int
     347           0 : bgp_graceful_restart_timer_expire (struct thread *thread)
     348             : {
     349             :   struct peer *peer;
     350             :   afi_t afi;
     351             :   safi_t safi;
     352             : 
     353           0 :   peer = THREAD_ARG (thread);
     354           0 :   peer->t_gr_restart = NULL;
     355             : 
     356             :   /* NSF delete stale route */
     357           0 :   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     358           0 :     for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
     359           0 :       if (peer->nsf[afi][safi])
     360           0 :         bgp_clear_stale_route (peer, afi, safi);
     361             : 
     362           0 :   UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
     363           0 :   BGP_TIMER_OFF (peer->t_gr_stale);
     364             : 
     365           0 :   if (BGP_DEBUG (events, EVENTS))
     366             :     {
     367           0 :       zlog_debug ("%s graceful restart timer expired", peer->host);
     368           0 :       zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
     369             :     }
     370             : 
     371           0 :   bgp_timer_set (peer);
     372             : 
     373           0 :   return 0;
     374             : }
     375             : 
     376             : static int
     377           0 : bgp_graceful_stale_timer_expire (struct thread *thread)
     378             : {
     379             :   struct peer *peer;
     380             :   afi_t afi;
     381             :   safi_t safi;
     382             : 
     383           0 :   peer = THREAD_ARG (thread);
     384           0 :   peer->t_gr_stale = NULL;
     385             : 
     386           0 :   if (BGP_DEBUG (events, EVENTS))
     387           0 :     zlog_debug ("%s graceful restart stalepath timer expired", peer->host);
     388             : 
     389             :   /* NSF delete stale route */
     390           0 :   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     391           0 :     for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
     392           0 :       if (peer->nsf[afi][safi])
     393           0 :         bgp_clear_stale_route (peer, afi, safi);
     394             : 
     395           0 :   return 0;
     396             : }
     397             : 
     398             : /* Called after event occured, this function change status and reset
     399             :    read/write and timer thread. */
     400             : void
     401           0 : bgp_fsm_change_status (struct peer *peer, int status)
     402             : {
     403           0 :   bgp_dump_state (peer, peer->status, status);
     404             : 
     405             :   /* Transition into Clearing or Deleted must /always/ clear all routes.. 
     406             :    * (and must do so before actually changing into Deleted..
     407             :    */
     408           0 :   if (status >= Clearing)
     409           0 :     bgp_clear_route_all (peer);
     410             :   
     411             :   /* Preserve old status and change into new status. */
     412           0 :   peer->ostatus = peer->status;
     413           0 :   peer->status = status;
     414             :   
     415           0 :   if (BGP_DEBUG (normal, NORMAL))
     416           0 :     zlog_debug ("%s went from %s to %s",
     417             :                 peer->host,
     418             :                 LOOKUP (bgp_status_msg, peer->ostatus),
     419             :                 LOOKUP (bgp_status_msg, peer->status));
     420           0 : }
     421             : 
     422             : /* Flush the event queue and ensure the peer is shut down */
     423             : static int
     424           0 : bgp_clearing_completed (struct peer *peer)
     425             : {
     426           0 :   int rc = bgp_stop(peer);
     427           0 :   BGP_EVENT_FLUSH (peer);
     428             : 
     429           0 :   return rc;
     430             : }
     431             : 
     432             : /* Administrative BGP peer stop event. */
     433             : /* May be called multiple times for the same peer */
     434             : int
     435           0 : bgp_stop (struct peer *peer)
     436             : {
     437             :   afi_t afi;
     438             :   safi_t safi;
     439             :   char orf_name[BUFSIZ];
     440             : 
     441             :   /* Can't do this in Clearing; events are used for state transitions */
     442           0 :   if (peer->status != Clearing)
     443             :     {
     444             :       /* Delete all existing events of the peer */
     445           0 :       BGP_EVENT_FLUSH (peer);
     446             :     }
     447             : 
     448             :   /* Increment Dropped count. */
     449           0 :   if (peer->status == Established)
     450             :     {
     451           0 :       peer->dropped++;
     452             : 
     453             :       /* bgp log-neighbor-changes of neighbor Down */
     454           0 :       if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
     455           0 :         zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
     456           0 :                    peer_down_str [(int) peer->last_reset]);
     457             : 
     458             :       /* graceful restart */
     459           0 :       if (peer->t_gr_stale)
     460             :         {
     461           0 :           BGP_TIMER_OFF (peer->t_gr_stale);
     462           0 :           if (BGP_DEBUG (events, EVENTS))
     463           0 :             zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
     464             :         }
     465           0 :       if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
     466             :         {
     467           0 :           if (BGP_DEBUG (events, EVENTS))
     468             :             {
     469           0 :               zlog_debug ("%s graceful restart timer started for %d sec",
     470             :                           peer->host, peer->v_gr_restart);
     471           0 :               zlog_debug ("%s graceful restart stalepath timer started for %d sec",
     472           0 :                           peer->host, peer->bgp->stalepath_time);
     473             :             }
     474           0 :           BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
     475             :                         peer->v_gr_restart);
     476           0 :           BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
     477             :                         peer->bgp->stalepath_time);
     478             :         }
     479             :       else
     480             :         {
     481           0 :           UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
     482             : 
     483           0 :           for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     484           0 :             for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
     485           0 :               peer->nsf[afi][safi] = 0;
     486             :         }
     487             : 
     488             :       /* set last reset time */
     489           0 :       peer->resettime = peer->uptime = bgp_clock ();
     490             : 
     491             : #ifdef HAVE_SNMP
     492             :       bgpTrapBackwardTransition (peer);
     493             : #endif /* HAVE_SNMP */
     494             : 
     495             :       /* Reset peer synctime */
     496           0 :       peer->synctime = 0;
     497             :     }
     498             : 
     499             :   /* Stop read and write threads when exists. */
     500           0 :   BGP_READ_OFF (peer->t_read);
     501           0 :   BGP_WRITE_OFF (peer->t_write);
     502             : 
     503             :   /* Stop all timers. */
     504           0 :   BGP_TIMER_OFF (peer->t_start);
     505           0 :   BGP_TIMER_OFF (peer->t_connect);
     506           0 :   BGP_TIMER_OFF (peer->t_holdtime);
     507           0 :   BGP_TIMER_OFF (peer->t_keepalive);
     508           0 :   BGP_TIMER_OFF (peer->t_asorig);
     509           0 :   BGP_TIMER_OFF (peer->t_routeadv);
     510             : 
     511             :   /* Stream reset. */
     512           0 :   peer->packet_size = 0;
     513             : 
     514             :   /* Clear input and output buffer.  */
     515           0 :   if (peer->ibuf)
     516           0 :     stream_reset (peer->ibuf);
     517           0 :   if (peer->work)
     518           0 :     stream_reset (peer->work);
     519           0 :   if (peer->obuf)
     520           0 :     stream_fifo_clean (peer->obuf);
     521             : 
     522             :   /* Close of file descriptor. */
     523           0 :   if (peer->fd >= 0)
     524             :     {
     525           0 :       close (peer->fd);
     526           0 :       peer->fd = -1;
     527             :     }
     528             : 
     529           0 :   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     530           0 :     for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
     531             :       {
     532             :         /* Reset all negotiated variables */
     533           0 :         peer->afc_nego[afi][safi] = 0;
     534           0 :         peer->afc_adv[afi][safi] = 0;
     535           0 :         peer->afc_recv[afi][safi] = 0;
     536             : 
     537             :         /* peer address family capability flags*/
     538           0 :         peer->af_cap[afi][safi] = 0;
     539             : 
     540             :         /* peer address family status flags*/
     541           0 :         peer->af_sflags[afi][safi] = 0;
     542             : 
     543             :         /* Received ORF prefix-filter */
     544           0 :         peer->orf_plist[afi][safi] = NULL;
     545             : 
     546             :         /* ORF received prefix-filter pnt */
     547           0 :         sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
     548           0 :         prefix_bgp_orf_remove_all (orf_name);
     549             :       }
     550             : 
     551             :   /* Reset keepalive and holdtime */
     552           0 :   if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
     553             :     {
     554           0 :       peer->v_keepalive = peer->keepalive;
     555           0 :       peer->v_holdtime = peer->holdtime;
     556             :     }
     557             :   else
     558             :     {
     559           0 :       peer->v_keepalive = peer->bgp->default_keepalive;
     560           0 :       peer->v_holdtime = peer->bgp->default_holdtime;
     561             :     }
     562             : 
     563           0 :   peer->update_time = 0;
     564             : 
     565             :   /* Until we are sure that there is no problem about prefix count
     566             :      this should be commented out.*/
     567             : #if 0
     568             :   /* Reset prefix count */
     569             :   peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
     570             :   peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
     571             :   peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
     572             :   peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
     573             :   peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
     574             : #endif /* 0 */
     575             : 
     576           0 :   return 0;
     577             : }
     578             : 
     579             : /* BGP peer is stoped by the error. */
     580             : static int
     581           0 : bgp_stop_with_error (struct peer *peer)
     582             : {
     583             :   /* Double start timer. */
     584           0 :   peer->v_start *= 2;
     585             : 
     586             :   /* Overflow check. */
     587           0 :   if (peer->v_start >= (60 * 2))
     588           0 :     peer->v_start = (60 * 2);
     589             : 
     590           0 :   bgp_stop (peer);
     591             : 
     592           0 :   return 0;
     593             : }
     594             : 
     595             : 
     596             : /* something went wrong, send notify and tear down */
     597             : static int
     598           0 : bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code)
     599             : {
     600             :   /* Send notify to remote peer */
     601           0 :   bgp_notify_send (peer, code, sub_code);
     602             : 
     603             :   /* Sweep if it is temporary peer. */
     604           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
     605             :     {
     606           0 :       zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
     607           0 :       peer_delete (peer);
     608           0 :       return -1;
     609             :     }
     610             : 
     611             :   /* Clear start timer value to default. */
     612           0 :   peer->v_start = BGP_INIT_START_TIMER;
     613             : 
     614             :   /* bgp_stop needs to be invoked while in Established state */
     615           0 :   bgp_stop(peer);
     616             : 
     617           0 :   return 0;
     618             : }
     619             : 
     620             : 
     621             : /* TCP connection open.  Next we send open message to remote peer. And
     622             :    add read thread for reading open message. */
     623             : static int
     624           0 : bgp_connect_success (struct peer *peer)
     625             : {
     626           0 :   if (peer->fd < 0)
     627             :     {
     628           0 :       zlog_err ("bgp_connect_success peer's fd is negative value %d",
     629             :                 peer->fd);
     630           0 :       return -1;
     631             :     }
     632           0 :   BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
     633             : 
     634           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
     635           0 :     bgp_getsockname (peer);
     636             : 
     637           0 :   if (BGP_DEBUG (normal, NORMAL))
     638             :     {
     639             :       char buf1[SU_ADDRSTRLEN];
     640             : 
     641           0 :       if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
     642           0 :         zlog_debug ("%s open active, local address %s", peer->host,
     643             :                     sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
     644             :       else
     645           0 :         zlog_debug ("%s passive open", peer->host);
     646             :     }
     647             : 
     648           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
     649           0 :     bgp_open_send (peer);
     650             : 
     651           0 :   return 0;
     652             : }
     653             : 
     654             : /* TCP connect fail */
     655             : static int
     656           0 : bgp_connect_fail (struct peer *peer)
     657             : {
     658           0 :   bgp_stop (peer);
     659           0 :   return 0;
     660             : }
     661             : 
     662             : /* This function is the first starting point of all BGP connection. It
     663             :    try to connect to remote peer with non-blocking IO. */
     664             : int
     665           0 : bgp_start (struct peer *peer)
     666             : {
     667             :   int status;
     668             : 
     669           0 :   if (BGP_PEER_START_SUPPRESSED (peer))
     670             :     {
     671           0 :       if (BGP_DEBUG (fsm, FSM))
     672           0 :         plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
     673             :                   " - this is never supposed to happen!", peer->host);
     674           0 :       return -1;
     675             :     }
     676             : 
     677             :   /* Scrub some information that might be left over from a previous,
     678             :    * session
     679             :    */
     680             :   /* Connection information. */
     681           0 :   if (peer->su_local)
     682             :     {
     683           0 :       sockunion_free (peer->su_local);
     684           0 :       peer->su_local = NULL;
     685             :     }
     686             : 
     687           0 :   if (peer->su_remote)
     688             :     {
     689           0 :       sockunion_free (peer->su_remote);
     690           0 :       peer->su_remote = NULL;
     691             :     }
     692             : 
     693             :   /* Clear remote router-id. */
     694           0 :   peer->remote_id.s_addr = 0;
     695             : 
     696             :   /* Clear peer capability flag. */
     697           0 :   peer->cap = 0;
     698             :     
     699             :   /* If the peer is passive mode, force to move to Active mode. */
     700           0 :   if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
     701             :     {
     702           0 :       BGP_EVENT_ADD (peer, TCP_connection_open_failed);
     703           0 :       return 0;
     704             :     }
     705             : 
     706           0 :   status = bgp_connect (peer);
     707             : 
     708           0 :   switch (status)
     709             :     {
     710             :     case connect_error:
     711           0 :       if (BGP_DEBUG (fsm, FSM))
     712           0 :         plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
     713           0 :       BGP_EVENT_ADD (peer, TCP_connection_open_failed);
     714           0 :       break;
     715             :     case connect_success:
     716           0 :       if (BGP_DEBUG (fsm, FSM))
     717           0 :         plog_debug (peer->log, "%s [FSM] Connect immediately success",
     718             :                    peer->host);
     719           0 :       BGP_EVENT_ADD (peer, TCP_connection_open);
     720           0 :       break;
     721             :     case connect_in_progress:
     722             :       /* To check nonblocking connect, we wait until socket is
     723             :          readable or writable. */
     724           0 :       if (BGP_DEBUG (fsm, FSM))
     725           0 :         plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
     726             :                    peer->host);
     727           0 :       if (peer->fd < 0)
     728             :         {
     729           0 :           zlog_err ("bgp_start peer's fd is negative value %d",
     730             :                     peer->fd);
     731           0 :           return -1;
     732             :         }
     733           0 :       BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
     734           0 :       BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     735           0 :       break;
     736             :     }
     737           0 :   return 0;
     738             : }
     739             : 
     740             : /* Connect retry timer is expired when the peer status is Connect. */
     741             : static int
     742           0 : bgp_reconnect (struct peer *peer)
     743             : {
     744           0 :   bgp_stop (peer);
     745           0 :   bgp_start (peer);
     746           0 :   return 0;
     747             : }
     748             : 
     749             : static int
     750           0 : bgp_fsm_open (struct peer *peer)
     751             : {
     752             :   /* Send keepalive and make keepalive timer */
     753           0 :   bgp_keepalive_send (peer);
     754             : 
     755             :   /* Reset holdtimer value. */
     756           0 :   BGP_TIMER_OFF (peer->t_holdtime);
     757             : 
     758           0 :   return 0;
     759             : }
     760             : 
     761             : /* Keepalive send to peer. */
     762             : static int
     763           0 : bgp_fsm_keepalive_expire (struct peer *peer)
     764             : {
     765           0 :   bgp_keepalive_send (peer);
     766           0 :   return 0;
     767             : }
     768             : 
     769             : /* FSM error, unexpected event.  This is error of BGP connection. So cut the
     770             :    peer and change to Idle status. */
     771             : static int
     772           0 : bgp_fsm_event_error (struct peer *peer)
     773             : {
     774           0 :   plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
     775             :             peer->host, LOOKUP (bgp_status_msg, peer->status));
     776             : 
     777           0 :   return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
     778             : }
     779             : 
     780             : /* Hold timer expire.  This is error of BGP connection. So cut the
     781             :    peer and change to Idle status. */
     782             : static int
     783           0 : bgp_fsm_holdtime_expire (struct peer *peer)
     784             : {
     785           0 :   if (BGP_DEBUG (fsm, FSM))
     786           0 :     plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
     787             : 
     788           0 :   return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
     789             : }
     790             : 
     791             : /* Status goes to Established.  Send keepalive packet then make first
     792             :    update information. */
     793             : static int
     794           0 : bgp_establish (struct peer *peer)
     795             : {
     796             :   struct bgp_notify *notify;
     797             :   afi_t afi;
     798             :   safi_t safi;
     799           0 :   int nsf_af_count = 0;
     800             : 
     801             :   /* Reset capability open status flag. */
     802           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
     803           0 :     SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
     804             : 
     805             :   /* Clear last notification data. */
     806           0 :   notify = &peer->notify;
     807           0 :   if (notify->data)
     808           0 :     XFREE (MTYPE_TMP, notify->data);
     809           0 :   memset (notify, 0, sizeof (struct bgp_notify));
     810             : 
     811             :   /* Clear start timer value to default. */
     812           0 :   peer->v_start = BGP_INIT_START_TIMER;
     813             : 
     814             :   /* Increment established count. */
     815           0 :   peer->established++;
     816           0 :   bgp_fsm_change_status (peer, Established);
     817             : 
     818             :   /* bgp log-neighbor-changes of neighbor Up */
     819           0 :   if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
     820           0 :     zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
     821             : 
     822             :   /* graceful restart */
     823           0 :   UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
     824           0 :   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     825           0 :     for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
     826             :       {
     827           0 :         if (peer->afc_nego[afi][safi]
     828           0 :             && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
     829           0 :             && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
     830             :           {
     831           0 :             if (peer->nsf[afi][safi]
     832           0 :                 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
     833           0 :               bgp_clear_stale_route (peer, afi, safi);
     834             : 
     835           0 :             peer->nsf[afi][safi] = 1;
     836           0 :             nsf_af_count++;
     837             :           }
     838             :         else
     839             :           {
     840           0 :             if (peer->nsf[afi][safi])
     841           0 :               bgp_clear_stale_route (peer, afi, safi);
     842           0 :             peer->nsf[afi][safi] = 0;
     843             :           }
     844             :       }
     845             : 
     846           0 :   if (nsf_af_count)
     847           0 :     SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
     848             :   else
     849             :     {
     850           0 :       UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
     851           0 :       if (peer->t_gr_stale)
     852             :         {
     853           0 :           BGP_TIMER_OFF (peer->t_gr_stale);
     854           0 :           if (BGP_DEBUG (events, EVENTS))
     855           0 :             zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
     856             :         }
     857             :     }
     858             : 
     859           0 :   if (peer->t_gr_restart)
     860             :     {
     861           0 :       BGP_TIMER_OFF (peer->t_gr_restart);
     862           0 :       if (BGP_DEBUG (events, EVENTS))
     863           0 :         zlog_debug ("%s graceful restart timer stopped", peer->host);
     864             :     }
     865             : 
     866             : #ifdef HAVE_SNMP
     867             :   bgpTrapEstablished (peer);
     868             : #endif /* HAVE_SNMP */
     869             : 
     870             :   /* Reset uptime, send keepalive, send current table. */
     871           0 :   peer->uptime = bgp_clock ();
     872             : 
     873             :   /* Send route-refresh when ORF is enabled */
     874           0 :   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     875           0 :     for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
     876           0 :       if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
     877             :         {
     878           0 :           if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
     879           0 :             bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
     880             :                                     REFRESH_IMMEDIATE, 0);
     881           0 :           else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
     882           0 :             bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
     883             :                                     REFRESH_IMMEDIATE, 0);
     884             :         }
     885             : 
     886           0 :   if (peer->v_keepalive)
     887           0 :     bgp_keepalive_send (peer);
     888             : 
     889             :   /* First update is deferred until ORF or ROUTE-REFRESH is received */
     890           0 :   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     891           0 :     for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
     892           0 :       if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
     893           0 :         if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
     894           0 :             || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
     895           0 :           SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
     896             : 
     897           0 :   bgp_announce_route_all (peer);
     898             : 
     899           0 :   BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
     900             : 
     901           0 :   return 0;
     902             : }
     903             : 
     904             : /* Keepalive packet is received. */
     905             : static int
     906           0 : bgp_fsm_keepalive (struct peer *peer)
     907             : {
     908             :   /* peer count update */
     909           0 :   peer->keepalive_in++;
     910             : 
     911           0 :   BGP_TIMER_OFF (peer->t_holdtime);
     912           0 :   return 0;
     913             : }
     914             : 
     915             : /* Update packet is received. */
     916             : static int
     917           0 : bgp_fsm_update (struct peer *peer)
     918             : {
     919           0 :   BGP_TIMER_OFF (peer->t_holdtime);
     920           0 :   return 0;
     921             : }
     922             : 
     923             : /* This is empty event. */
     924             : static int
     925           0 : bgp_ignore (struct peer *peer)
     926             : {
     927           0 :   if (BGP_DEBUG (fsm, FSM))
     928           0 :     zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
     929           0 :   return 0;
     930             : }
     931             : 
     932             : /* Finite State Machine structure */
     933             : static const struct {
     934             :   int (*func) (struct peer *);
     935             :   int next_state;
     936             : } FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = 
     937             : {
     938             :   {
     939             :     /* Idle state: In Idle state, all events other than BGP_Start is
     940             :        ignored.  With BGP_Start event, finite state machine calls
     941             :        bgp_start(). */
     942             :     {bgp_start,  Connect},      /* BGP_Start                    */
     943             :     {bgp_stop,   Idle},         /* BGP_Stop                     */
     944             :     {bgp_stop,   Idle},         /* TCP_connection_open          */
     945             :     {bgp_stop,   Idle},         /* TCP_connection_closed        */
     946             :     {bgp_ignore, Idle},         /* TCP_connection_open_failed   */
     947             :     {bgp_stop,   Idle},         /* TCP_fatal_error              */
     948             :     {bgp_ignore, Idle},         /* ConnectRetry_timer_expired   */
     949             :     {bgp_ignore, Idle},         /* Hold_Timer_expired           */
     950             :     {bgp_ignore, Idle},         /* KeepAlive_timer_expired      */
     951             :     {bgp_ignore, Idle},         /* Receive_OPEN_message         */
     952             :     {bgp_ignore, Idle},         /* Receive_KEEPALIVE_message    */
     953             :     {bgp_ignore, Idle},         /* Receive_UPDATE_message       */
     954             :     {bgp_ignore, Idle},         /* Receive_NOTIFICATION_message */
     955             :     {bgp_ignore, Idle},         /* Clearing_Completed           */
     956             :   },
     957             :   {
     958             :     /* Connect */
     959             :     {bgp_ignore,  Connect},     /* BGP_Start                    */
     960             :     {bgp_stop,    Idle},        /* BGP_Stop                     */
     961             :     {bgp_connect_success, OpenSent}, /* TCP_connection_open          */
     962             :     {bgp_stop, Idle},           /* TCP_connection_closed        */
     963             :     {bgp_connect_fail, Active}, /* TCP_connection_open_failed   */
     964             :     {bgp_connect_fail, Idle},   /* TCP_fatal_error              */
     965             :     {bgp_reconnect, Connect},   /* ConnectRetry_timer_expired   */
     966             :     {bgp_ignore,  Idle},        /* Hold_Timer_expired           */
     967             :     {bgp_ignore,  Idle},        /* KeepAlive_timer_expired      */
     968             :     {bgp_ignore,  Idle},        /* Receive_OPEN_message         */
     969             :     {bgp_ignore,  Idle},        /* Receive_KEEPALIVE_message    */
     970             :     {bgp_ignore,  Idle},        /* Receive_UPDATE_message       */
     971             :     {bgp_stop,    Idle},        /* Receive_NOTIFICATION_message */
     972             :     {bgp_ignore,  Idle},         /* Clearing_Completed           */
     973             :   },
     974             :   {
     975             :     /* Active, */
     976             :     {bgp_ignore,  Active},      /* BGP_Start                    */
     977             :     {bgp_stop,    Idle},        /* BGP_Stop                     */
     978             :     {bgp_connect_success, OpenSent}, /* TCP_connection_open          */
     979             :     {bgp_stop,    Idle},        /* TCP_connection_closed        */
     980             :     {bgp_ignore,  Active},      /* TCP_connection_open_failed   */
     981             :     {bgp_ignore,  Idle},        /* TCP_fatal_error              */
     982             :     {bgp_start,   Connect},     /* ConnectRetry_timer_expired   */
     983             :     {bgp_ignore,  Idle},        /* Hold_Timer_expired           */
     984             :     {bgp_ignore,  Idle},        /* KeepAlive_timer_expired      */
     985             :     {bgp_ignore,  Idle},        /* Receive_OPEN_message         */
     986             :     {bgp_ignore,  Idle},        /* Receive_KEEPALIVE_message    */
     987             :     {bgp_ignore,  Idle},        /* Receive_UPDATE_message       */
     988             :     {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
     989             :     {bgp_ignore, Idle},         /* Clearing_Completed           */
     990             :   },
     991             :   {
     992             :     /* OpenSent, */
     993             :     {bgp_ignore,  OpenSent},    /* BGP_Start                    */
     994             :     {bgp_stop,    Idle},        /* BGP_Stop                     */
     995             :     {bgp_stop,    Active},      /* TCP_connection_open          */
     996             :     {bgp_stop,    Active},      /* TCP_connection_closed        */
     997             :     {bgp_stop,    Active},      /* TCP_connection_open_failed   */
     998             :     {bgp_stop,    Active},      /* TCP_fatal_error              */
     999             :     {bgp_ignore,  Idle},        /* ConnectRetry_timer_expired   */
    1000             :     {bgp_fsm_holdtime_expire, Idle},    /* Hold_Timer_expired           */
    1001             :     {bgp_ignore,  Idle},        /* KeepAlive_timer_expired      */
    1002             :     {bgp_fsm_open,    OpenConfirm},     /* Receive_OPEN_message         */
    1003             :     {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message    */
    1004             :     {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message       */
    1005             :     {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
    1006             :     {bgp_ignore, Idle},         /* Clearing_Completed           */
    1007             :   },
    1008             :   {
    1009             :     /* OpenConfirm, */
    1010             :     {bgp_ignore,  OpenConfirm}, /* BGP_Start                    */
    1011             :     {bgp_stop,    Idle},        /* BGP_Stop                     */
    1012             :     {bgp_stop,    Idle},        /* TCP_connection_open          */
    1013             :     {bgp_stop,    Idle},        /* TCP_connection_closed        */
    1014             :     {bgp_stop,    Idle},        /* TCP_connection_open_failed   */
    1015             :     {bgp_stop,    Idle},        /* TCP_fatal_error              */
    1016             :     {bgp_ignore,  Idle},        /* ConnectRetry_timer_expired   */
    1017             :     {bgp_fsm_holdtime_expire, Idle},    /* Hold_Timer_expired           */
    1018             :     {bgp_ignore,  OpenConfirm}, /* KeepAlive_timer_expired      */
    1019             :     {bgp_ignore,  Idle},        /* Receive_OPEN_message         */
    1020             :     {bgp_establish, Established}, /* Receive_KEEPALIVE_message    */
    1021             :     {bgp_ignore,  Idle},        /* Receive_UPDATE_message       */
    1022             :     {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
    1023             :     {bgp_ignore, Idle},         /* Clearing_Completed           */
    1024             :   },
    1025             :   {
    1026             :     /* Established, */
    1027             :     {bgp_ignore,               Established}, /* BGP_Start                    */
    1028             :     {bgp_stop,                    Clearing}, /* BGP_Stop                     */
    1029             :     {bgp_stop,                    Clearing}, /* TCP_connection_open          */
    1030             :     {bgp_stop,                    Clearing}, /* TCP_connection_closed        */
    1031             :     {bgp_stop,                 Clearing},       /* TCP_connection_open_failed   */
    1032             :     {bgp_stop,                    Clearing}, /* TCP_fatal_error              */
    1033             :     {bgp_stop,                 Clearing},       /* ConnectRetry_timer_expired   */
    1034             :     {bgp_fsm_holdtime_expire,     Clearing}, /* Hold_Timer_expired           */
    1035             :     {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired      */
    1036             :     {bgp_stop,                    Clearing}, /* Receive_OPEN_message         */
    1037             :     {bgp_fsm_keepalive,        Established}, /* Receive_KEEPALIVE_message    */
    1038             :     {bgp_fsm_update,           Established}, /* Receive_UPDATE_message       */
    1039             :     {bgp_stop_with_error,         Clearing}, /* Receive_NOTIFICATION_message */
    1040             :     {bgp_ignore,                      Idle}, /* Clearing_Completed           */
    1041             :   },
    1042             :   {
    1043             :     /* Clearing, */
    1044             :     {bgp_ignore,  Clearing},    /* BGP_Start                    */
    1045             :     {bgp_stop,                  Clearing},      /* BGP_Stop                     */
    1046             :     {bgp_stop,                  Clearing},      /* TCP_connection_open          */
    1047             :     {bgp_stop,                  Clearing},      /* TCP_connection_closed        */
    1048             :     {bgp_stop,                  Clearing},      /* TCP_connection_open_failed   */
    1049             :     {bgp_stop,                  Clearing},      /* TCP_fatal_error              */
    1050             :     {bgp_stop,                  Clearing},      /* ConnectRetry_timer_expired   */
    1051             :     {bgp_stop,                  Clearing},      /* Hold_Timer_expired           */
    1052             :     {bgp_stop,                  Clearing},      /* KeepAlive_timer_expired      */
    1053             :     {bgp_stop,                  Clearing},      /* Receive_OPEN_message         */
    1054             :     {bgp_stop,                  Clearing},      /* Receive_KEEPALIVE_message    */
    1055             :     {bgp_stop,                  Clearing},      /* Receive_UPDATE_message       */
    1056             :     {bgp_stop,                  Clearing},      /* Receive_NOTIFICATION_message */
    1057             :     {bgp_clearing_completed,    Idle},          /* Clearing_Completed           */
    1058             :   },
    1059             :   {
    1060             :     /* Deleted, */
    1061             :     {bgp_ignore,  Deleted},     /* BGP_Start                    */
    1062             :     {bgp_ignore,  Deleted},     /* BGP_Stop                     */
    1063             :     {bgp_ignore,  Deleted},     /* TCP_connection_open          */
    1064             :     {bgp_ignore,  Deleted},     /* TCP_connection_closed        */
    1065             :     {bgp_ignore,  Deleted},     /* TCP_connection_open_failed   */
    1066             :     {bgp_ignore,  Deleted},     /* TCP_fatal_error              */
    1067             :     {bgp_ignore,  Deleted},     /* ConnectRetry_timer_expired   */
    1068             :     {bgp_ignore,  Deleted},     /* Hold_Timer_expired           */
    1069             :     {bgp_ignore,  Deleted},     /* KeepAlive_timer_expired      */
    1070             :     {bgp_ignore,  Deleted},     /* Receive_OPEN_message         */
    1071             :     {bgp_ignore,  Deleted},     /* Receive_KEEPALIVE_message    */
    1072             :     {bgp_ignore,  Deleted},     /* Receive_UPDATE_message       */
    1073             :     {bgp_ignore,  Deleted},     /* Receive_NOTIFICATION_message */
    1074             :     {bgp_ignore,  Deleted},     /* Clearing_Completed           */
    1075             :   },
    1076             : };
    1077             : 
    1078             : static const char *bgp_event_str[] =
    1079             : {
    1080             :   NULL,
    1081             :   "BGP_Start",
    1082             :   "BGP_Stop",
    1083             :   "TCP_connection_open",
    1084             :   "TCP_connection_closed",
    1085             :   "TCP_connection_open_failed",
    1086             :   "TCP_fatal_error",
    1087             :   "ConnectRetry_timer_expired",
    1088             :   "Hold_Timer_expired",
    1089             :   "KeepAlive_timer_expired",
    1090             :   "Receive_OPEN_message",
    1091             :   "Receive_KEEPALIVE_message",
    1092             :   "Receive_UPDATE_message",
    1093             :   "Receive_NOTIFICATION_message",
    1094             :   "Clearing_Completed",
    1095             : };
    1096             : 
    1097             : /* Execute event process. */
    1098             : int
    1099           0 : bgp_event (struct thread *thread)
    1100             : {
    1101           0 :   int ret = 0;
    1102             :   int event;
    1103             :   int next;
    1104             :   struct peer *peer;
    1105             : 
    1106           0 :   peer = THREAD_ARG (thread);
    1107           0 :   event = THREAD_VAL (thread);
    1108             : 
    1109             :   /* Logging this event. */
    1110           0 :   next = FSM [peer->status -1][event - 1].next_state;
    1111             : 
    1112           0 :   if (BGP_DEBUG (fsm, FSM) && peer->status != next)
    1113           0 :     plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host, 
    1114             :                bgp_event_str[event],
    1115             :                LOOKUP (bgp_status_msg, peer->status),
    1116             :                LOOKUP (bgp_status_msg, next));
    1117             : 
    1118             :   /* Call function. */
    1119           0 :   if (FSM [peer->status -1][event - 1].func)
    1120           0 :     ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
    1121             : 
    1122             :   /* When function do not want proceed next job return -1. */
    1123           0 :   if (ret >= 0)
    1124             :     {
    1125             :       /* If status is changed. */
    1126           0 :       if (next != peer->status)
    1127           0 :         bgp_fsm_change_status (peer, next);
    1128             :       
    1129             :       /* Make sure timer is set. */
    1130           0 :       bgp_timer_set (peer);
    1131             :     }
    1132             :   
    1133           0 :   return ret;
    1134             : }

Generated by: LCOV version 1.10