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