Annotation of embedaddon/quagga/bgpd/bgp_fsm.c, revision 1.1.1.1

1.1       misho       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_UNICAST_MULTICAST ; 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_UNICAST_MULTICAST ; 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_UNICAST_MULTICAST ; 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_UNICAST_MULTICAST ; 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>