blob: ac25f151e4c07277b8db6689e70bc7233c9dec6a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4 Finite State Machine
2 From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
3 Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
4
5This file is part of GNU Zebra.
6
7GNU Zebra is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 2, or (at your option) any
10later version.
11
12GNU Zebra is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Zebra; see the file COPYING. If not, write to the Free
19Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
2002111-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. */
53int bgp_event (struct thread *);
54
55/* BGP thread functions. */
56static int bgp_start_timer (struct thread *);
57static int bgp_connect_timer (struct thread *);
58static int bgp_holdtime_timer (struct thread *);
59static int bgp_keepalive_timer (struct thread *);
60
61/* BGP FSM functions. */
62static int bgp_start (struct peer *);
63
64/* BGP start timer jitter. */
65int
66bgp_start_jitter (int time)
67{
68 return ((rand () % (time + 1)) - (time / 2));
69}
70
71/* Hook function called after bgp event is occered. And vty's
72 neighbor command invoke this function after making neighbor
73 structure. */
74void
75bgp_timer_set (struct peer *peer)
76{
77 int jitter = 0;
78
79 switch (peer->status)
80 {
81 case Idle:
82 /* First entry point of peer's finite state machine. In Idle
83 status start timer is on unless peer is shutdown or peer is
84 inactive. All other timer must be turned off */
85 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)
86 || CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)
87 || ! peer_active (peer))
88 {
89 BGP_TIMER_OFF (peer->t_start);
90 }
91 else
92 {
93 jitter = bgp_start_jitter (peer->v_start);
94 BGP_TIMER_ON (peer->t_start, bgp_start_timer,
95 peer->v_start + jitter);
96 }
97 BGP_TIMER_OFF (peer->t_connect);
98 BGP_TIMER_OFF (peer->t_holdtime);
99 BGP_TIMER_OFF (peer->t_keepalive);
100 BGP_TIMER_OFF (peer->t_asorig);
101 BGP_TIMER_OFF (peer->t_routeadv);
102 break;
103
104 case Connect:
105 /* After start timer is expired, the peer moves to Connnect
106 status. Make sure start timer is off and connect timer is
107 on. */
108 BGP_TIMER_OFF (peer->t_start);
109 BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
110 BGP_TIMER_OFF (peer->t_holdtime);
111 BGP_TIMER_OFF (peer->t_keepalive);
112 BGP_TIMER_OFF (peer->t_asorig);
113 BGP_TIMER_OFF (peer->t_routeadv);
114 break;
115
116 case Active:
117 /* Active is waiting connection from remote peer. And if
118 connect timer is expired, change status to Connect. */
119 BGP_TIMER_OFF (peer->t_start);
120 /* If peer is passive mode, do not set connect timer. */
121 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
122 {
123 BGP_TIMER_OFF (peer->t_connect);
124 }
125 else
126 {
127 BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
128 }
129 BGP_TIMER_OFF (peer->t_holdtime);
130 BGP_TIMER_OFF (peer->t_keepalive);
131 BGP_TIMER_OFF (peer->t_asorig);
132 BGP_TIMER_OFF (peer->t_routeadv);
133 break;
134
135 case OpenSent:
136 /* OpenSent status. */
137 BGP_TIMER_OFF (peer->t_start);
138 BGP_TIMER_OFF (peer->t_connect);
139 if (peer->v_holdtime != 0)
140 {
141 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
142 peer->v_holdtime);
143 }
144 else
145 {
146 BGP_TIMER_OFF (peer->t_holdtime);
147 }
148 BGP_TIMER_OFF (peer->t_keepalive);
149 BGP_TIMER_OFF (peer->t_asorig);
150 BGP_TIMER_OFF (peer->t_routeadv);
151 break;
152
153 case OpenConfirm:
154 /* OpenConfirm status. */
155 BGP_TIMER_OFF (peer->t_start);
156 BGP_TIMER_OFF (peer->t_connect);
157
158 /* If the negotiated Hold Time value is zero, then the Hold Time
159 timer and KeepAlive timers are not started. */
160 if (peer->v_holdtime == 0)
161 {
162 BGP_TIMER_OFF (peer->t_holdtime);
163 BGP_TIMER_OFF (peer->t_keepalive);
164 }
165 else
166 {
167 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
168 peer->v_holdtime);
169 BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
170 peer->v_keepalive);
171 }
172 BGP_TIMER_OFF (peer->t_asorig);
173 BGP_TIMER_OFF (peer->t_routeadv);
174 break;
175
176 case Established:
177 /* In Established status start and connect timer is turned
178 off. */
179 BGP_TIMER_OFF (peer->t_start);
180 BGP_TIMER_OFF (peer->t_connect);
181
182 /* Same as OpenConfirm, if holdtime is zero then both holdtime
183 and keepalive must be turned off. */
184 if (peer->v_holdtime == 0)
185 {
186 BGP_TIMER_OFF (peer->t_holdtime);
187 BGP_TIMER_OFF (peer->t_keepalive);
188 }
189 else
190 {
191 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
192 peer->v_holdtime);
193 BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
194 peer->v_keepalive);
195 }
196 BGP_TIMER_OFF (peer->t_asorig);
197 break;
198 }
199}
200
201/* BGP start timer. This function set BGP_Start event to thread value
202 and process event. */
203static int
204bgp_start_timer (struct thread *thread)
205{
206 struct peer *peer;
207
208 peer = THREAD_ARG (thread);
209 peer->t_start = NULL;
210
211 if (BGP_DEBUG (fsm, FSM))
212 zlog (peer->log, LOG_DEBUG,
213 "%s [FSM] Timer (start timer expire).", peer->host);
214
215 THREAD_VAL (thread) = BGP_Start;
216 bgp_event (thread);
217
218 return 0;
219}
220
221/* BGP connect retry timer. */
222static int
223bgp_connect_timer (struct thread *thread)
224{
225 struct peer *peer;
226
227 peer = THREAD_ARG (thread);
228 peer->t_connect = NULL;
229
230 if (BGP_DEBUG (fsm, FSM))
231 zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)",
232 peer->host);
233
234 THREAD_VAL (thread) = ConnectRetry_timer_expired;
235 bgp_event (thread);
236
237 return 0;
238}
239
240/* BGP holdtime timer. */
241static int
242bgp_holdtime_timer (struct thread *thread)
243{
244 struct peer *peer;
245
246 peer = THREAD_ARG (thread);
247 peer->t_holdtime = NULL;
248
249 if (BGP_DEBUG (fsm, FSM))
250 zlog (peer->log, LOG_DEBUG,
251 "%s [FSM] Timer (holdtime timer expire)",
252 peer->host);
253
254 THREAD_VAL (thread) = Hold_Timer_expired;
255 bgp_event (thread);
256
257 return 0;
258}
259
260/* BGP keepalive fire ! */
261static int
262bgp_keepalive_timer (struct thread *thread)
263{
264 struct peer *peer;
265
266 peer = THREAD_ARG (thread);
267 peer->t_keepalive = NULL;
268
269 if (BGP_DEBUG (fsm, FSM))
270 zlog (peer->log, LOG_DEBUG,
271 "%s [FSM] Timer (keepalive timer expire)",
272 peer->host);
273
274 THREAD_VAL (thread) = KeepAlive_timer_expired;
275 bgp_event (thread);
276
277 return 0;
278}
279
280int
281bgp_routeadv_timer (struct thread *thread)
282{
283 struct peer *peer;
284
285 peer = THREAD_ARG (thread);
286 peer->t_routeadv = NULL;
287
288 if (BGP_DEBUG (fsm, FSM))
289 zlog (peer->log, LOG_DEBUG,
290 "%s [FSM] Timer (routeadv timer expire)",
291 peer->host);
292
293 peer->synctime = time (NULL);
294
paul6ad23f02004-02-17 19:45:10 +0000295 BGP_WRITE_ON (peer->t_write, bgp_write, *peer->fd);
paul718e3742002-12-13 20:15:29 +0000296
297 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
298 peer->v_routeadv);
299
300 return 0;
301}
302
303/* Reset bgp update timer */
304static void
305bgp_uptime_reset (struct peer *peer)
306{
307 peer->uptime = time (NULL);
308}
309
paul6ad23f02004-02-17 19:45:10 +0000310void
311bgp_connection_stop (struct peer *peer)
312{
313 if (peer->fd_local >= 0)
314 {
315 close (peer->fd_local);
316 peer->fd_local = -1;
317 }
318 if (peer->fd_accept >= 0)
319 {
320 close (peer->fd_accept);
321 peer->fd_accept = -1;
322 }
323}
324
paul718e3742002-12-13 20:15:29 +0000325/* Administrative BGP peer stop event. */
326int
327bgp_stop (struct peer *peer)
328{
329 int established = 0;
330 afi_t afi;
331 safi_t safi;
332 char orf_name[BUFSIZ];
333
334 /* Increment Dropped count. */
335 if (peer->status == Established)
336 {
337 established = 1;
338 peer->dropped++;
339 bgp_fsm_change_status (peer, Idle);
paul848973c2003-08-13 00:32:49 +0000340
341 /* bgp log-neighbor-changes of neighbor Down */
342 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
343 zlog_info ("%%ADJCHANGE: neighbor %s Down", peer->host);
344
345 /* set last reset time */
346 peer->resettime = time (NULL);
347
paul718e3742002-12-13 20:15:29 +0000348#ifdef HAVE_SNMP
349 bgpTrapBackwardTransition (peer);
350#endif /* HAVE_SNMP */
351 }
352
353 /* Reset uptime. */
354 bgp_uptime_reset (peer);
355
356 /* Need of clear of peer. */
357 if (established)
358 bgp_clear_route_all (peer);
359
360 /* Stop read and write threads when exists. */
361 BGP_READ_OFF (peer->t_read);
362 BGP_WRITE_OFF (peer->t_write);
363
364 /* Stop all timers. */
365 BGP_TIMER_OFF (peer->t_start);
366 BGP_TIMER_OFF (peer->t_connect);
367 BGP_TIMER_OFF (peer->t_holdtime);
368 BGP_TIMER_OFF (peer->t_keepalive);
369 BGP_TIMER_OFF (peer->t_asorig);
370 BGP_TIMER_OFF (peer->t_routeadv);
371
372 /* Delete all existing events of the peer. */
373 BGP_EVENT_DELETE (peer);
374
375 /* Stream reset. */
376 peer->packet_size = 0;
377
378 /* Clear input and output buffer. */
379 if (peer->ibuf)
380 stream_reset (peer->ibuf);
381 if (peer->work)
382 stream_reset (peer->work);
383 stream_fifo_clean (peer->obuf);
384
paul6ad23f02004-02-17 19:45:10 +0000385 /* Close of connections. */
386 bgp_connection_stop (peer);
paul718e3742002-12-13 20:15:29 +0000387
388 /* Connection information. */
389 if (peer->su_local)
390 {
391 XFREE (MTYPE_SOCKUNION, peer->su_local);
392 peer->su_local = NULL;
393 }
394
395 if (peer->su_remote)
396 {
397 XFREE (MTYPE_SOCKUNION, peer->su_remote);
398 peer->su_remote = NULL;
399 }
paul6ad23f02004-02-17 19:45:10 +0000400
paul718e3742002-12-13 20:15:29 +0000401 /* Clear remote router-id. */
402 peer->remote_id.s_addr = 0;
403
404 /* Reset all negotiated variables */
405 peer->afc_nego[AFI_IP][SAFI_UNICAST] = 0;
406 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 0;
407 peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 0;
408 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 0;
409 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 0;
410 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 0;
411 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 0;
412 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 0;
413 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 0;
414 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 0;
415 peer->afc_recv[AFI_IP][SAFI_UNICAST] = 0;
416 peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 0;
417 peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 0;
418 peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 0;
419 peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 0;
420
421 /* Reset route refresh flag. */
422 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
423 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
424 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
425 UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
426 UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
427
428 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
429 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
430 {
431 /* peer address family capability flags*/
432 peer->af_cap[afi][safi] = 0;
433 /* peer address family status flags*/
434 peer->af_sflags[afi][safi] = 0;
435 /* Received ORF prefix-filter */
436 peer->orf_plist[afi][safi] = NULL;
437 /* ORF received prefix-filter pnt */
438 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
439 prefix_bgp_orf_remove_all (orf_name);
440 }
441
442 /* Reset keepalive and holdtime */
443 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
444 {
445 peer->v_keepalive = peer->keepalive;
446 peer->v_holdtime = peer->holdtime;
447 }
448 else
449 {
450 peer->v_keepalive = peer->bgp->default_keepalive;
451 peer->v_holdtime = peer->bgp->default_holdtime;
452 }
453
454 peer->update_time = 0;
455
456 /* Until we are sure that there is no problem about prefix count
457 this should be commented out.*/
458#if 0
459 /* Reset prefix count */
460 peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
461 peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
462 peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
463 peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
464 peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
465#endif /* 0 */
466
467 return 0;
468}
469
470/* BGP peer is stoped by the error. */
471int
472bgp_stop_with_error (struct peer *peer)
473{
474 /* Double start timer. */
475 peer->v_start *= 2;
476
477 /* Overflow check. */
478 if (peer->v_start >= (60 * 2))
479 peer->v_start = (60 * 2);
480
481 bgp_stop (peer);
482
483 return 0;
484}
485
486/* TCP connection open. Next we send open message to remote peer. And
487 add read thread for reading open message. */
488int
489bgp_connect_success (struct peer *peer)
490{
paul6ad23f02004-02-17 19:45:10 +0000491 if (peer->fd_local < 0)
paul718e3742002-12-13 20:15:29 +0000492 {
493 zlog_err ("bgp_connect_success peer's fd is negative value %d",
paul6ad23f02004-02-17 19:45:10 +0000494 peer->fd_local);
paul718e3742002-12-13 20:15:29 +0000495 return -1;
496 }
paul6ad23f02004-02-17 19:45:10 +0000497 BGP_READ_ON (peer->t_read, bgp_read, peer->fd_local);
paul718e3742002-12-13 20:15:29 +0000498
499 /* bgp_getsockname (peer); */
500
501 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
502 bgp_open_send (peer);
503
504 return 0;
505}
506
507/* TCP connect fail */
508int
509bgp_connect_fail (struct peer *peer)
510{
511 bgp_stop (peer);
512 return 0;
513}
514
515/* This function is the first starting point of all BGP connection. It
516 try to connect to remote peer with non-blocking IO. */
517int
518bgp_start (struct peer *peer)
519{
520 int status;
521
522 /* If the peer is passive mode, force to move to Active mode. */
523 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
524 {
525 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
526 return 0;
527 }
528
529 status = bgp_connect (peer);
530
531 switch (status)
532 {
533 case connect_error:
534 if (BGP_DEBUG (fsm, FSM))
paul6ad23f02004-02-17 19:45:10 +0000535 plog_info (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000536 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
537 break;
538 case connect_success:
539 if (BGP_DEBUG (fsm, FSM))
paul6ad23f02004-02-17 19:45:10 +0000540 plog_info (peer->log, "%s [FSM] Connect immediately success",
541 peer->host);
paul718e3742002-12-13 20:15:29 +0000542 BGP_EVENT_ADD (peer, TCP_connection_open);
543 break;
544 case connect_in_progress:
545 /* To check nonblocking connect, we wait until socket is
546 readable or writable. */
547 if (BGP_DEBUG (fsm, FSM))
paul6ad23f02004-02-17 19:45:10 +0000548 plog_info (peer->log, "%s [FSM] Non blocking connect waiting result",
549 peer->host);
550 if (*peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000551 {
552 zlog_err ("bgp_start peer's fd is negative value %d",
paul6ad23f02004-02-17 19:45:10 +0000553 *peer->fd);
paul718e3742002-12-13 20:15:29 +0000554 return -1;
555 }
paul6ad23f02004-02-17 19:45:10 +0000556 BGP_READ_ON (peer->t_read, bgp_read, *peer->fd);
557 BGP_WRITE_ON (peer->t_write, bgp_write, *peer->fd);
paul718e3742002-12-13 20:15:29 +0000558 break;
559 }
560 return 0;
561}
562
563/* Connect retry timer is expired when the peer status is Connect. */
564int
565bgp_reconnect (struct peer *peer)
566{
567 bgp_stop (peer);
568 bgp_start (peer);
569 return 0;
570}
571
572int
573bgp_fsm_open (struct peer *peer)
574{
575 /* Send keepalive and make keepalive timer */
576 bgp_keepalive_send (peer);
577
578 /* Reset holdtimer value. */
579 BGP_TIMER_OFF (peer->t_holdtime);
580
581 return 0;
582}
583
584/* Called after event occured, this function change status and reset
585 read/write and timer thread. */
586void
587bgp_fsm_change_status (struct peer *peer, int status)
588{
589 bgp_dump_state (peer, peer->status, status);
590
591 /* Preserve old status and change into new status. */
592 peer->ostatus = peer->status;
593 peer->status = status;
594}
595
596/* Keepalive send to peer. */
597int
598bgp_fsm_keepalive_expire (struct peer *peer)
599{
600 bgp_keepalive_send (peer);
601 return 0;
602}
603
604/* Hold timer expire. This is error of BGP connection. So cut the
605 peer and change to Idle status. */
606int
607bgp_fsm_holdtime_expire (struct peer *peer)
608{
609 if (BGP_DEBUG (fsm, FSM))
610 zlog (peer->log, LOG_DEBUG, "%s [FSM] Hold timer expire", peer->host);
611
612 /* Send notify to remote peer. */
613 bgp_notify_send (peer, BGP_NOTIFY_HOLD_ERR, 0);
614
615 /* Sweep if it is temporary peer. */
616 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
617 {
618 zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
619 peer_delete (peer);
620 return -1;
621 }
622
623 return 0;
624}
625
626/* Status goes to Established. Send keepalive packet then make first
627 update information. */
628int
629bgp_establish (struct peer *peer)
630{
631 struct bgp_notify *notify;
632 afi_t afi;
633 safi_t safi;
634
635 /* Reset capability open status flag. */
636 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
637 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
638
639 /* Clear last notification data. */
640 notify = &peer->notify;
641 if (notify->data)
642 XFREE (MTYPE_TMP, notify->data);
643 memset (notify, 0, sizeof (struct bgp_notify));
644
645 /* Clear start timer value to default. */
646 peer->v_start = BGP_INIT_START_TIMER;
647
648 /* Increment established count. */
649 peer->established++;
650 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000651
652 /* bgp log-neighbor-changes of neighbor Up */
653 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
654 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
655
paul718e3742002-12-13 20:15:29 +0000656#ifdef HAVE_SNMP
657 bgpTrapEstablished (peer);
658#endif /* HAVE_SNMP */
659
660 /* Reset uptime, send keepalive, send current table. */
661 bgp_uptime_reset (peer);
662
663 /* Send route-refresh when ORF is enabled */
664 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
665 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
666 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
667 {
668 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
669 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
670 REFRESH_IMMEDIATE, 0);
671 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
672 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
673 REFRESH_IMMEDIATE, 0);
674 }
675
676 if (peer->v_keepalive)
677 bgp_keepalive_send (peer);
678
679 /* First update is deferred until ORF or ROUTE-REFRESH is received */
680 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
681 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
682 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
683 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
684 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
685 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
686
687 bgp_announce_route_all (peer);
688
689 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
690
691 return 0;
692}
693
694/* Keepalive packet is received. */
695int
696bgp_fsm_keepalive (struct peer *peer)
697{
698 /* peer count update */
699 peer->keepalive_in++;
700
701 BGP_TIMER_OFF (peer->t_holdtime);
702 return 0;
703}
704
705/* Update packet is received. */
706int
707bgp_fsm_update (struct peer *peer)
708{
709 BGP_TIMER_OFF (peer->t_holdtime);
710 return 0;
711}
712
713/* This is empty event. */
714int
715bgp_ignore (struct peer *peer)
716{
717 if (BGP_DEBUG (fsm, FSM))
718 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
719 return 0;
720}
721
722/* Finite State Machine structure */
723struct {
724 int (*func) ();
725 int next_state;
726} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
727{
728 {
729 /* Idle state: In Idle state, all events other than BGP_Start is
730 ignored. With BGP_Start event, finite state machine calls
731 bgp_start(). */
732 {bgp_start, Connect}, /* BGP_Start */
733 {bgp_stop, Idle}, /* BGP_Stop */
734 {bgp_stop, Idle}, /* TCP_connection_open */
735 {bgp_stop, Idle}, /* TCP_connection_closed */
736 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
737 {bgp_stop, Idle}, /* TCP_fatal_error */
738 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
739 {bgp_ignore, Idle}, /* Hold_Timer_expired */
740 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
741 {bgp_ignore, Idle}, /* Receive_OPEN_message */
742 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
743 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
744 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
745 },
746 {
747 /* Connect */
748 {bgp_ignore, Connect}, /* BGP_Start */
749 {bgp_stop, Idle}, /* BGP_Stop */
750 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
751 {bgp_stop, Idle}, /* TCP_connection_closed */
752 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
753 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
754 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
755 {bgp_ignore, Idle}, /* Hold_Timer_expired */
756 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
757 {bgp_ignore, Idle}, /* Receive_OPEN_message */
758 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
759 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
760 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
761 },
762 {
763 /* Active, */
764 {bgp_ignore, Active}, /* BGP_Start */
765 {bgp_stop, Idle}, /* BGP_Stop */
766 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
767 {bgp_stop, Idle}, /* TCP_connection_closed */
768 {bgp_ignore, Active}, /* TCP_connection_open_failed */
769 {bgp_ignore, Idle}, /* TCP_fatal_error */
770 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
771 {bgp_ignore, Idle}, /* Hold_Timer_expired */
772 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
773 {bgp_ignore, Idle}, /* Receive_OPEN_message */
774 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
775 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
776 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
777 },
778 {
779 /* OpenSent, */
780 {bgp_ignore, OpenSent}, /* BGP_Start */
781 {bgp_stop, Idle}, /* BGP_Stop */
782 {bgp_stop, Idle}, /* TCP_connection_open */
783 {bgp_stop, Active}, /* TCP_connection_closed */
784 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
785 {bgp_stop, Idle}, /* TCP_fatal_error */
786 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
787 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
788 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
789 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
790 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
791 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
792 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
793 },
794 {
795 /* OpenConfirm, */
796 {bgp_ignore, OpenConfirm}, /* BGP_Start */
797 {bgp_stop, Idle}, /* BGP_Stop */
798 {bgp_stop, Idle}, /* TCP_connection_open */
799 {bgp_stop, Idle}, /* TCP_connection_closed */
800 {bgp_stop, Idle}, /* TCP_connection_open_failed */
801 {bgp_stop, Idle}, /* TCP_fatal_error */
802 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
803 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
804 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
805 {bgp_ignore, Idle}, /* Receive_OPEN_message */
806 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
807 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
808 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
809 },
810 {
811 /* Established, */
812 {bgp_ignore, Established}, /* BGP_Start */
813 {bgp_stop, Idle}, /* BGP_Stop */
814 {bgp_stop, Idle}, /* TCP_connection_open */
815 {bgp_stop, Idle}, /* TCP_connection_closed */
816 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
817 {bgp_stop, Idle}, /* TCP_fatal_error */
818 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
819 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
820 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
821 {bgp_stop, Idle}, /* Receive_OPEN_message */
822 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
823 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
824 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
825 },
826};
827
828static char *bgp_event_str[] =
829{
830 NULL,
831 "BGP_Start",
832 "BGP_Stop",
833 "TCP_connection_open",
834 "TCP_connection_closed",
835 "TCP_connection_open_failed",
836 "TCP_fatal_error",
837 "ConnectRetry_timer_expired",
838 "Hold_Timer_expired",
839 "KeepAlive_timer_expired",
840 "Receive_OPEN_message",
841 "Receive_KEEPALIVE_message",
842 "Receive_UPDATE_message",
843 "Receive_NOTIFICATION_message"
844};
845
846/* Execute event process. */
847int
848bgp_event (struct thread *thread)
849{
850 int ret;
851 int event;
852 int next;
853 struct peer *peer;
854
855 peer = THREAD_ARG (thread);
856 event = THREAD_VAL (thread);
857
858 /* Logging this event. */
859 next = FSM [peer->status -1][event - 1].next_state;
860
861 if (BGP_DEBUG (fsm, FSM))
862 plog_info (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
863 bgp_event_str[event],
864 LOOKUP (bgp_status_msg, peer->status),
865 LOOKUP (bgp_status_msg, next));
866 if (BGP_DEBUG (normal, NORMAL)
867 && strcmp (LOOKUP (bgp_status_msg, peer->status), LOOKUP (bgp_status_msg, next)))
868 zlog_info ("%s went from %s to %s",
869 peer->host,
870 LOOKUP (bgp_status_msg, peer->status),
871 LOOKUP (bgp_status_msg, next));
872
873 /* Call function. */
874 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
875
876 /* When function do not want proceed next job return -1. */
877 if (ret < 0)
878 return ret;
879
880 /* If status is changed. */
881 if (next != peer->status)
882 bgp_fsm_change_status (peer, next);
883
884 /* Make sure timer is set. */
885 bgp_timer_set (peer);
886
887 return 0;
888}