File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_fsm.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>