blob: 5c8224c67a9f0e774393c5c8e10173d84afa76ab [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
pauleb821182004-05-01 08:44:08 +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
310/* Administrative BGP peer stop event. */
311int
312bgp_stop (struct peer *peer)
313{
314 int established = 0;
315 afi_t afi;
316 safi_t safi;
317 char orf_name[BUFSIZ];
318
319 /* Increment Dropped count. */
320 if (peer->status == Established)
321 {
322 established = 1;
323 peer->dropped++;
324 bgp_fsm_change_status (peer, Idle);
paul848973c2003-08-13 00:32:49 +0000325
326 /* bgp log-neighbor-changes of neighbor Down */
327 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
328 zlog_info ("%%ADJCHANGE: neighbor %s Down", peer->host);
329
330 /* set last reset time */
331 peer->resettime = time (NULL);
paulc5317402004-05-03 13:25:06 +0000332 /* Reset uptime. */
333 bgp_uptime_reset (peer);
paul848973c2003-08-13 00:32:49 +0000334
paul718e3742002-12-13 20:15:29 +0000335#ifdef HAVE_SNMP
336 bgpTrapBackwardTransition (peer);
337#endif /* HAVE_SNMP */
338 }
339
paul718e3742002-12-13 20:15:29 +0000340 /* Need of clear of peer. */
341 if (established)
342 bgp_clear_route_all (peer);
343
344 /* Stop read and write threads when exists. */
345 BGP_READ_OFF (peer->t_read);
346 BGP_WRITE_OFF (peer->t_write);
347
348 /* Stop all timers. */
349 BGP_TIMER_OFF (peer->t_start);
350 BGP_TIMER_OFF (peer->t_connect);
351 BGP_TIMER_OFF (peer->t_holdtime);
352 BGP_TIMER_OFF (peer->t_keepalive);
353 BGP_TIMER_OFF (peer->t_asorig);
354 BGP_TIMER_OFF (peer->t_routeadv);
355
356 /* Delete all existing events of the peer. */
357 BGP_EVENT_DELETE (peer);
358
359 /* Stream reset. */
360 peer->packet_size = 0;
361
362 /* Clear input and output buffer. */
363 if (peer->ibuf)
364 stream_reset (peer->ibuf);
365 if (peer->work)
366 stream_reset (peer->work);
367 stream_fifo_clean (peer->obuf);
368
pauleb821182004-05-01 08:44:08 +0000369 /* Close of file descriptor. */
370 if (peer->fd >= 0)
371 {
372 close (peer->fd);
373 peer->fd = -1;
374 }
paul718e3742002-12-13 20:15:29 +0000375
376 /* Connection information. */
377 if (peer->su_local)
378 {
379 XFREE (MTYPE_SOCKUNION, peer->su_local);
380 peer->su_local = NULL;
381 }
382
383 if (peer->su_remote)
384 {
385 XFREE (MTYPE_SOCKUNION, peer->su_remote);
386 peer->su_remote = NULL;
387 }
pauleb821182004-05-01 08:44:08 +0000388
paul718e3742002-12-13 20:15:29 +0000389 /* Clear remote router-id. */
390 peer->remote_id.s_addr = 0;
391
392 /* Reset all negotiated variables */
393 peer->afc_nego[AFI_IP][SAFI_UNICAST] = 0;
394 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 0;
395 peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 0;
396 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 0;
397 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 0;
398 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 0;
399 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 0;
400 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 0;
401 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 0;
402 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 0;
403 peer->afc_recv[AFI_IP][SAFI_UNICAST] = 0;
404 peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 0;
405 peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 0;
406 peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 0;
407 peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 0;
408
409 /* Reset route refresh flag. */
410 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
411 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
412 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
413 UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
414 UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
415
416 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
417 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
418 {
419 /* peer address family capability flags*/
420 peer->af_cap[afi][safi] = 0;
421 /* peer address family status flags*/
422 peer->af_sflags[afi][safi] = 0;
423 /* Received ORF prefix-filter */
424 peer->orf_plist[afi][safi] = NULL;
425 /* ORF received prefix-filter pnt */
426 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
427 prefix_bgp_orf_remove_all (orf_name);
428 }
429
430 /* Reset keepalive and holdtime */
431 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
432 {
433 peer->v_keepalive = peer->keepalive;
434 peer->v_holdtime = peer->holdtime;
435 }
436 else
437 {
438 peer->v_keepalive = peer->bgp->default_keepalive;
439 peer->v_holdtime = peer->bgp->default_holdtime;
440 }
441
442 peer->update_time = 0;
443
444 /* Until we are sure that there is no problem about prefix count
445 this should be commented out.*/
446#if 0
447 /* Reset prefix count */
448 peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
449 peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
450 peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
451 peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
452 peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
453#endif /* 0 */
454
455 return 0;
456}
457
458/* BGP peer is stoped by the error. */
459int
460bgp_stop_with_error (struct peer *peer)
461{
462 /* Double start timer. */
463 peer->v_start *= 2;
464
465 /* Overflow check. */
466 if (peer->v_start >= (60 * 2))
467 peer->v_start = (60 * 2);
468
469 bgp_stop (peer);
470
471 return 0;
472}
473
474/* TCP connection open. Next we send open message to remote peer. And
475 add read thread for reading open message. */
476int
477bgp_connect_success (struct peer *peer)
478{
pauleb821182004-05-01 08:44:08 +0000479 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000480 {
481 zlog_err ("bgp_connect_success peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000482 peer->fd);
paul718e3742002-12-13 20:15:29 +0000483 return -1;
484 }
pauleb821182004-05-01 08:44:08 +0000485 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +0000486
487 /* bgp_getsockname (peer); */
488
489 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
490 bgp_open_send (peer);
491
492 return 0;
493}
494
495/* TCP connect fail */
496int
497bgp_connect_fail (struct peer *peer)
498{
499 bgp_stop (peer);
500 return 0;
501}
502
503/* This function is the first starting point of all BGP connection. It
504 try to connect to remote peer with non-blocking IO. */
505int
506bgp_start (struct peer *peer)
507{
508 int status;
509
510 /* If the peer is passive mode, force to move to Active mode. */
511 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
512 {
513 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
514 return 0;
515 }
516
517 status = bgp_connect (peer);
518
519 switch (status)
520 {
521 case connect_error:
522 if (BGP_DEBUG (fsm, FSM))
pauleb821182004-05-01 08:44:08 +0000523 plog_info (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000524 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
525 break;
526 case connect_success:
527 if (BGP_DEBUG (fsm, FSM))
pauleb821182004-05-01 08:44:08 +0000528 plog_info (peer->log, "%s [FSM] Connect immediately success",
529 peer->host);
paul718e3742002-12-13 20:15:29 +0000530 BGP_EVENT_ADD (peer, TCP_connection_open);
531 break;
532 case connect_in_progress:
533 /* To check nonblocking connect, we wait until socket is
534 readable or writable. */
535 if (BGP_DEBUG (fsm, FSM))
pauleb821182004-05-01 08:44:08 +0000536 plog_info (peer->log, "%s [FSM] Non blocking connect waiting result",
537 peer->host);
538 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000539 {
540 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000541 peer->fd);
paul718e3742002-12-13 20:15:29 +0000542 return -1;
543 }
pauleb821182004-05-01 08:44:08 +0000544 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
545 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000546 break;
547 }
548 return 0;
549}
550
551/* Connect retry timer is expired when the peer status is Connect. */
552int
553bgp_reconnect (struct peer *peer)
554{
555 bgp_stop (peer);
556 bgp_start (peer);
557 return 0;
558}
559
560int
561bgp_fsm_open (struct peer *peer)
562{
563 /* Send keepalive and make keepalive timer */
564 bgp_keepalive_send (peer);
565
566 /* Reset holdtimer value. */
567 BGP_TIMER_OFF (peer->t_holdtime);
568
569 return 0;
570}
571
572/* Called after event occured, this function change status and reset
573 read/write and timer thread. */
574void
575bgp_fsm_change_status (struct peer *peer, int status)
576{
577 bgp_dump_state (peer, peer->status, status);
578
579 /* Preserve old status and change into new status. */
580 peer->ostatus = peer->status;
581 peer->status = status;
582}
583
584/* Keepalive send to peer. */
585int
586bgp_fsm_keepalive_expire (struct peer *peer)
587{
588 bgp_keepalive_send (peer);
589 return 0;
590}
591
592/* Hold timer expire. This is error of BGP connection. So cut the
593 peer and change to Idle status. */
594int
595bgp_fsm_holdtime_expire (struct peer *peer)
596{
597 if (BGP_DEBUG (fsm, FSM))
598 zlog (peer->log, LOG_DEBUG, "%s [FSM] Hold timer expire", peer->host);
599
600 /* Send notify to remote peer. */
601 bgp_notify_send (peer, BGP_NOTIFY_HOLD_ERR, 0);
602
603 /* Sweep if it is temporary peer. */
604 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
605 {
606 zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
607 peer_delete (peer);
608 return -1;
609 }
610
611 return 0;
612}
613
614/* Status goes to Established. Send keepalive packet then make first
615 update information. */
616int
617bgp_establish (struct peer *peer)
618{
619 struct bgp_notify *notify;
620 afi_t afi;
621 safi_t safi;
622
623 /* Reset capability open status flag. */
624 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
625 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
626
627 /* Clear last notification data. */
628 notify = &peer->notify;
629 if (notify->data)
630 XFREE (MTYPE_TMP, notify->data);
631 memset (notify, 0, sizeof (struct bgp_notify));
632
633 /* Clear start timer value to default. */
634 peer->v_start = BGP_INIT_START_TIMER;
635
636 /* Increment established count. */
637 peer->established++;
638 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000639
640 /* bgp log-neighbor-changes of neighbor Up */
641 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
642 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
643
paul718e3742002-12-13 20:15:29 +0000644#ifdef HAVE_SNMP
645 bgpTrapEstablished (peer);
646#endif /* HAVE_SNMP */
647
648 /* Reset uptime, send keepalive, send current table. */
649 bgp_uptime_reset (peer);
650
651 /* Send route-refresh when ORF is enabled */
652 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
653 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
654 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
655 {
656 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
657 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
658 REFRESH_IMMEDIATE, 0);
659 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
660 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
661 REFRESH_IMMEDIATE, 0);
662 }
663
664 if (peer->v_keepalive)
665 bgp_keepalive_send (peer);
666
667 /* First update is deferred until ORF or ROUTE-REFRESH is received */
668 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
669 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
670 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
671 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
672 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
673 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
674
675 bgp_announce_route_all (peer);
676
677 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
678
679 return 0;
680}
681
682/* Keepalive packet is received. */
683int
684bgp_fsm_keepalive (struct peer *peer)
685{
686 /* peer count update */
687 peer->keepalive_in++;
688
689 BGP_TIMER_OFF (peer->t_holdtime);
690 return 0;
691}
692
693/* Update packet is received. */
694int
695bgp_fsm_update (struct peer *peer)
696{
697 BGP_TIMER_OFF (peer->t_holdtime);
698 return 0;
699}
700
701/* This is empty event. */
702int
703bgp_ignore (struct peer *peer)
704{
705 if (BGP_DEBUG (fsm, FSM))
706 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
707 return 0;
708}
709
710/* Finite State Machine structure */
711struct {
712 int (*func) ();
713 int next_state;
714} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
715{
716 {
717 /* Idle state: In Idle state, all events other than BGP_Start is
718 ignored. With BGP_Start event, finite state machine calls
719 bgp_start(). */
720 {bgp_start, Connect}, /* BGP_Start */
721 {bgp_stop, Idle}, /* BGP_Stop */
722 {bgp_stop, Idle}, /* TCP_connection_open */
723 {bgp_stop, Idle}, /* TCP_connection_closed */
724 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
725 {bgp_stop, Idle}, /* TCP_fatal_error */
726 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
727 {bgp_ignore, Idle}, /* Hold_Timer_expired */
728 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
729 {bgp_ignore, Idle}, /* Receive_OPEN_message */
730 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
731 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
732 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
733 },
734 {
735 /* Connect */
736 {bgp_ignore, Connect}, /* BGP_Start */
737 {bgp_stop, Idle}, /* BGP_Stop */
738 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
739 {bgp_stop, Idle}, /* TCP_connection_closed */
740 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
741 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
742 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
743 {bgp_ignore, Idle}, /* Hold_Timer_expired */
744 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
745 {bgp_ignore, Idle}, /* Receive_OPEN_message */
746 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
747 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
748 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
749 },
750 {
751 /* Active, */
752 {bgp_ignore, Active}, /* BGP_Start */
753 {bgp_stop, Idle}, /* BGP_Stop */
754 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
755 {bgp_stop, Idle}, /* TCP_connection_closed */
756 {bgp_ignore, Active}, /* TCP_connection_open_failed */
757 {bgp_ignore, Idle}, /* TCP_fatal_error */
758 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
759 {bgp_ignore, Idle}, /* Hold_Timer_expired */
760 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
761 {bgp_ignore, Idle}, /* Receive_OPEN_message */
762 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
763 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
764 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
765 },
766 {
767 /* OpenSent, */
768 {bgp_ignore, OpenSent}, /* BGP_Start */
769 {bgp_stop, Idle}, /* BGP_Stop */
770 {bgp_stop, Idle}, /* TCP_connection_open */
771 {bgp_stop, Active}, /* TCP_connection_closed */
772 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
773 {bgp_stop, Idle}, /* TCP_fatal_error */
774 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
775 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
776 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
777 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
778 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
779 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
780 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
781 },
782 {
783 /* OpenConfirm, */
784 {bgp_ignore, OpenConfirm}, /* BGP_Start */
785 {bgp_stop, Idle}, /* BGP_Stop */
786 {bgp_stop, Idle}, /* TCP_connection_open */
787 {bgp_stop, Idle}, /* TCP_connection_closed */
788 {bgp_stop, Idle}, /* TCP_connection_open_failed */
789 {bgp_stop, Idle}, /* TCP_fatal_error */
790 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
791 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
792 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
793 {bgp_ignore, Idle}, /* Receive_OPEN_message */
794 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
795 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
796 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
797 },
798 {
799 /* Established, */
800 {bgp_ignore, Established}, /* BGP_Start */
801 {bgp_stop, Idle}, /* BGP_Stop */
802 {bgp_stop, Idle}, /* TCP_connection_open */
803 {bgp_stop, Idle}, /* TCP_connection_closed */
804 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
805 {bgp_stop, Idle}, /* TCP_fatal_error */
806 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
807 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
808 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
809 {bgp_stop, Idle}, /* Receive_OPEN_message */
810 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
811 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
812 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
813 },
814};
815
816static char *bgp_event_str[] =
817{
818 NULL,
819 "BGP_Start",
820 "BGP_Stop",
821 "TCP_connection_open",
822 "TCP_connection_closed",
823 "TCP_connection_open_failed",
824 "TCP_fatal_error",
825 "ConnectRetry_timer_expired",
826 "Hold_Timer_expired",
827 "KeepAlive_timer_expired",
828 "Receive_OPEN_message",
829 "Receive_KEEPALIVE_message",
830 "Receive_UPDATE_message",
831 "Receive_NOTIFICATION_message"
832};
833
834/* Execute event process. */
835int
836bgp_event (struct thread *thread)
837{
838 int ret;
839 int event;
840 int next;
841 struct peer *peer;
842
843 peer = THREAD_ARG (thread);
844 event = THREAD_VAL (thread);
845
846 /* Logging this event. */
847 next = FSM [peer->status -1][event - 1].next_state;
848
849 if (BGP_DEBUG (fsm, FSM))
850 plog_info (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
851 bgp_event_str[event],
852 LOOKUP (bgp_status_msg, peer->status),
853 LOOKUP (bgp_status_msg, next));
854 if (BGP_DEBUG (normal, NORMAL)
855 && strcmp (LOOKUP (bgp_status_msg, peer->status), LOOKUP (bgp_status_msg, next)))
856 zlog_info ("%s went from %s to %s",
857 peer->host,
858 LOOKUP (bgp_status_msg, peer->status),
859 LOOKUP (bgp_status_msg, next));
860
861 /* Call function. */
862 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
863
864 /* When function do not want proceed next job return -1. */
865 if (ret < 0)
866 return ret;
867
868 /* If status is changed. */
869 if (next != peer->status)
870 bgp_fsm_change_status (peer, next);
871
872 /* Make sure timer is set. */
873 bgp_timer_set (peer);
874
875 return 0;
876}