Annotation of embedaddon/quagga/bgpd/bgp_fsm.c, revision 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>