File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_fsm.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (11 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_21, HEAD
quagga

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

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