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

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

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