blob: 6368ff47ad170ea34b6aa439476efb1e78d8b5fa [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. */
hasso93406d82005-02-02 14:40:33 +0000121 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)
122 || CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
paul718e3742002-12-13 20:15:29 +0000123 {
124 BGP_TIMER_OFF (peer->t_connect);
125 }
126 else
127 {
128 BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
129 }
130 BGP_TIMER_OFF (peer->t_holdtime);
131 BGP_TIMER_OFF (peer->t_keepalive);
132 BGP_TIMER_OFF (peer->t_asorig);
133 BGP_TIMER_OFF (peer->t_routeadv);
134 break;
135
136 case OpenSent:
137 /* OpenSent status. */
138 BGP_TIMER_OFF (peer->t_start);
139 BGP_TIMER_OFF (peer->t_connect);
140 if (peer->v_holdtime != 0)
141 {
142 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
143 peer->v_holdtime);
144 }
145 else
146 {
147 BGP_TIMER_OFF (peer->t_holdtime);
148 }
149 BGP_TIMER_OFF (peer->t_keepalive);
150 BGP_TIMER_OFF (peer->t_asorig);
151 BGP_TIMER_OFF (peer->t_routeadv);
152 break;
153
154 case OpenConfirm:
155 /* OpenConfirm status. */
156 BGP_TIMER_OFF (peer->t_start);
157 BGP_TIMER_OFF (peer->t_connect);
158
159 /* If the negotiated Hold Time value is zero, then the Hold Time
160 timer and KeepAlive timers are not started. */
161 if (peer->v_holdtime == 0)
162 {
163 BGP_TIMER_OFF (peer->t_holdtime);
164 BGP_TIMER_OFF (peer->t_keepalive);
165 }
166 else
167 {
168 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
169 peer->v_holdtime);
170 BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
171 peer->v_keepalive);
172 }
173 BGP_TIMER_OFF (peer->t_asorig);
174 BGP_TIMER_OFF (peer->t_routeadv);
175 break;
176
177 case Established:
178 /* In Established status start and connect timer is turned
179 off. */
180 BGP_TIMER_OFF (peer->t_start);
181 BGP_TIMER_OFF (peer->t_connect);
182
183 /* Same as OpenConfirm, if holdtime is zero then both holdtime
184 and keepalive must be turned off. */
185 if (peer->v_holdtime == 0)
186 {
187 BGP_TIMER_OFF (peer->t_holdtime);
188 BGP_TIMER_OFF (peer->t_keepalive);
189 }
190 else
191 {
192 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
193 peer->v_holdtime);
194 BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
195 peer->v_keepalive);
196 }
197 BGP_TIMER_OFF (peer->t_asorig);
198 break;
199 }
200}
201
202/* BGP start timer. This function set BGP_Start event to thread value
203 and process event. */
204static int
205bgp_start_timer (struct thread *thread)
206{
207 struct peer *peer;
208
209 peer = THREAD_ARG (thread);
210 peer->t_start = NULL;
211
212 if (BGP_DEBUG (fsm, FSM))
213 zlog (peer->log, LOG_DEBUG,
214 "%s [FSM] Timer (start timer expire).", peer->host);
215
216 THREAD_VAL (thread) = BGP_Start;
217 bgp_event (thread);
218
219 return 0;
220}
221
222/* BGP connect retry timer. */
223static int
224bgp_connect_timer (struct thread *thread)
225{
226 struct peer *peer;
227
228 peer = THREAD_ARG (thread);
229 peer->t_connect = NULL;
230
231 if (BGP_DEBUG (fsm, FSM))
232 zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)",
233 peer->host);
234
235 THREAD_VAL (thread) = ConnectRetry_timer_expired;
236 bgp_event (thread);
237
238 return 0;
239}
240
241/* BGP holdtime timer. */
242static int
243bgp_holdtime_timer (struct thread *thread)
244{
245 struct peer *peer;
246
247 peer = THREAD_ARG (thread);
248 peer->t_holdtime = NULL;
249
250 if (BGP_DEBUG (fsm, FSM))
251 zlog (peer->log, LOG_DEBUG,
252 "%s [FSM] Timer (holdtime timer expire)",
253 peer->host);
254
255 THREAD_VAL (thread) = Hold_Timer_expired;
256 bgp_event (thread);
257
258 return 0;
259}
260
261/* BGP keepalive fire ! */
262static int
263bgp_keepalive_timer (struct thread *thread)
264{
265 struct peer *peer;
266
267 peer = THREAD_ARG (thread);
268 peer->t_keepalive = NULL;
269
270 if (BGP_DEBUG (fsm, FSM))
271 zlog (peer->log, LOG_DEBUG,
272 "%s [FSM] Timer (keepalive timer expire)",
273 peer->host);
274
275 THREAD_VAL (thread) = KeepAlive_timer_expired;
276 bgp_event (thread);
277
278 return 0;
279}
280
281int
282bgp_routeadv_timer (struct thread *thread)
283{
284 struct peer *peer;
285
286 peer = THREAD_ARG (thread);
287 peer->t_routeadv = NULL;
288
289 if (BGP_DEBUG (fsm, FSM))
290 zlog (peer->log, LOG_DEBUG,
291 "%s [FSM] Timer (routeadv timer expire)",
292 peer->host);
293
294 peer->synctime = time (NULL);
295
pauleb821182004-05-01 08:44:08 +0000296 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000297
298 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
299 peer->v_routeadv);
300
301 return 0;
302}
303
304/* Reset bgp update timer */
305static void
306bgp_uptime_reset (struct peer *peer)
307{
308 peer->uptime = time (NULL);
309}
310
hassoe0701b72004-05-20 09:19:34 +0000311/* BGP Peer Down Cause */
paulfd79ac92004-10-13 05:06:08 +0000312const char *peer_down_str[] =
hassoe0701b72004-05-20 09:19:34 +0000313{
314 "",
315 "Router ID changed",
316 "Remote AS changed",
317 "Local AS change",
318 "Cluster ID changed",
319 "Confederation identifier changed",
320 "Confederation peer changed",
321 "RR client config change",
322 "RS client config change",
323 "Update source change",
324 "Address family activated",
325 "Admin. shutdown",
326 "User reset",
327 "BGP Notification received",
328 "BGP Notification send",
329 "Peer closed the session",
330 "Neighbor deleted",
331 "Peer-group add member",
332 "Peer-group delete member",
333 "Capability changed",
334 "Passive config change",
hasso93406d82005-02-02 14:40:33 +0000335 "Multihop config change",
336 "NSF peer closed the session"
hassoe0701b72004-05-20 09:19:34 +0000337};
338
hasso93406d82005-02-02 14:40:33 +0000339int
340bgp_graceful_restart_timer_expire (struct thread *thread)
341{
342 struct peer *peer;
343 afi_t afi;
344 safi_t safi;
345
346 peer = THREAD_ARG (thread);
347 peer->t_gr_restart = NULL;
348
349 /* NSF delete stale route */
350 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
351 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
352 if (peer->nsf[afi][safi])
353 bgp_clear_stale_route (peer, afi, safi);
354
355 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
356 BGP_TIMER_OFF (peer->t_gr_stale);
357
358 if (BGP_DEBUG (events, EVENTS))
359 {
360 zlog_debug ("%s graceful restart timer expired", peer->host);
361 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
362 }
363
364 bgp_timer_set (peer);
365
366 return 0;
367}
368
369int
370bgp_graceful_stale_timer_expire (struct thread *thread)
371{
372 struct peer *peer;
373 afi_t afi;
374 safi_t safi;
375
376 peer = THREAD_ARG (thread);
377 peer->t_gr_stale = NULL;
378
379 if (BGP_DEBUG (events, EVENTS))
380 zlog_debug ("%s graceful restart stalepath timer expired", peer->host);
381
382 /* NSF delete stale route */
383 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
384 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
385 if (peer->nsf[afi][safi])
386 bgp_clear_stale_route (peer, afi, safi);
387
388 return 0;
389}
390
paul718e3742002-12-13 20:15:29 +0000391/* Administrative BGP peer stop event. */
392int
393bgp_stop (struct peer *peer)
394{
paul718e3742002-12-13 20:15:29 +0000395 afi_t afi;
396 safi_t safi;
397 char orf_name[BUFSIZ];
398
399 /* Increment Dropped count. */
400 if (peer->status == Established)
401 {
paul718e3742002-12-13 20:15:29 +0000402 peer->dropped++;
403 bgp_fsm_change_status (peer, Idle);
paul848973c2003-08-13 00:32:49 +0000404
405 /* bgp log-neighbor-changes of neighbor Down */
406 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
hassoe0701b72004-05-20 09:19:34 +0000407 zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
408 peer_down_str [(int) peer->last_reset]);
paul848973c2003-08-13 00:32:49 +0000409
hasso93406d82005-02-02 14:40:33 +0000410 /* graceful restart */
411 if (peer->t_gr_stale)
412 {
413 BGP_TIMER_OFF (peer->t_gr_stale);
414 if (BGP_DEBUG (events, EVENTS))
415 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
416 }
417 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
418 {
419 if (BGP_DEBUG (events, EVENTS))
420 {
421 zlog_debug ("%s graceful restart timer started for %d sec",
422 peer->host, peer->v_gr_restart);
423 zlog_debug ("%s graceful restart stalepath timer started for %d sec",
424 peer->host, peer->bgp->stalepath_time);
425 }
426 BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
427 peer->v_gr_restart);
428 BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
429 peer->bgp->stalepath_time);
430 }
431 else
432 {
433 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
434
435 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
436 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
437 peer->nsf[afi][safi] = 0;
438 }
439
paul848973c2003-08-13 00:32:49 +0000440 /* set last reset time */
441 peer->resettime = time (NULL);
paulc5317402004-05-03 13:25:06 +0000442 /* Reset uptime. */
443 bgp_uptime_reset (peer);
paul848973c2003-08-13 00:32:49 +0000444
paul718e3742002-12-13 20:15:29 +0000445#ifdef HAVE_SNMP
446 bgpTrapBackwardTransition (peer);
447#endif /* HAVE_SNMP */
paul718e3742002-12-13 20:15:29 +0000448
hasso538621f2004-05-21 09:31:30 +0000449 /* Reset uptime. */
450 bgp_uptime_reset (peer);
451
452 /* Need of clear of peer. */
453 bgp_clear_route_all (peer);
hassof4184462005-02-01 20:13:16 +0000454
455 /* Reset peer synctime */
456 peer->synctime = 0;
hasso538621f2004-05-21 09:31:30 +0000457 }
paul718e3742002-12-13 20:15:29 +0000458
459 /* Stop read and write threads when exists. */
460 BGP_READ_OFF (peer->t_read);
461 BGP_WRITE_OFF (peer->t_write);
462
463 /* Stop all timers. */
464 BGP_TIMER_OFF (peer->t_start);
465 BGP_TIMER_OFF (peer->t_connect);
466 BGP_TIMER_OFF (peer->t_holdtime);
467 BGP_TIMER_OFF (peer->t_keepalive);
468 BGP_TIMER_OFF (peer->t_asorig);
469 BGP_TIMER_OFF (peer->t_routeadv);
470
471 /* Delete all existing events of the peer. */
472 BGP_EVENT_DELETE (peer);
473
474 /* Stream reset. */
475 peer->packet_size = 0;
476
477 /* Clear input and output buffer. */
478 if (peer->ibuf)
479 stream_reset (peer->ibuf);
480 if (peer->work)
481 stream_reset (peer->work);
482 stream_fifo_clean (peer->obuf);
483
pauleb821182004-05-01 08:44:08 +0000484 /* Close of file descriptor. */
485 if (peer->fd >= 0)
486 {
487 close (peer->fd);
488 peer->fd = -1;
489 }
paul718e3742002-12-13 20:15:29 +0000490
491 /* Connection information. */
492 if (peer->su_local)
493 {
paul22db9de2005-05-19 01:50:11 +0000494 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +0000495 peer->su_local = NULL;
496 }
497
498 if (peer->su_remote)
499 {
paul22db9de2005-05-19 01:50:11 +0000500 sockunion_free (peer->su_remote);
paul718e3742002-12-13 20:15:29 +0000501 peer->su_remote = NULL;
502 }
pauleb821182004-05-01 08:44:08 +0000503
paul718e3742002-12-13 20:15:29 +0000504 /* Clear remote router-id. */
505 peer->remote_id.s_addr = 0;
506
hasso538621f2004-05-21 09:31:30 +0000507 /* Clear peer capability flag. */
508 peer->cap = 0;
paul718e3742002-12-13 20:15:29 +0000509
510 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
511 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
512 {
hasso538621f2004-05-21 09:31:30 +0000513 /* Reset all negotiated variables */
514 peer->afc_nego[afi][safi] = 0;
515 peer->afc_adv[afi][safi] = 0;
516 peer->afc_recv[afi][safi] = 0;
517
paul718e3742002-12-13 20:15:29 +0000518 /* peer address family capability flags*/
519 peer->af_cap[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000520
paul718e3742002-12-13 20:15:29 +0000521 /* peer address family status flags*/
522 peer->af_sflags[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000523
paul718e3742002-12-13 20:15:29 +0000524 /* Received ORF prefix-filter */
525 peer->orf_plist[afi][safi] = NULL;
hasso538621f2004-05-21 09:31:30 +0000526
paul718e3742002-12-13 20:15:29 +0000527 /* ORF received prefix-filter pnt */
528 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
529 prefix_bgp_orf_remove_all (orf_name);
530 }
531
532 /* Reset keepalive and holdtime */
533 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
534 {
535 peer->v_keepalive = peer->keepalive;
536 peer->v_holdtime = peer->holdtime;
537 }
538 else
539 {
540 peer->v_keepalive = peer->bgp->default_keepalive;
541 peer->v_holdtime = peer->bgp->default_holdtime;
542 }
543
544 peer->update_time = 0;
545
546 /* Until we are sure that there is no problem about prefix count
547 this should be commented out.*/
548#if 0
549 /* Reset prefix count */
550 peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
551 peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
552 peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
553 peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
554 peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
555#endif /* 0 */
556
557 return 0;
558}
559
560/* BGP peer is stoped by the error. */
561int
562bgp_stop_with_error (struct peer *peer)
563{
564 /* Double start timer. */
565 peer->v_start *= 2;
566
567 /* Overflow check. */
568 if (peer->v_start >= (60 * 2))
569 peer->v_start = (60 * 2);
570
571 bgp_stop (peer);
572
573 return 0;
574}
575
576/* TCP connection open. Next we send open message to remote peer. And
577 add read thread for reading open message. */
578int
579bgp_connect_success (struct peer *peer)
580{
hassof4184462005-02-01 20:13:16 +0000581 char buf1[BUFSIZ];
582
pauleb821182004-05-01 08:44:08 +0000583 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000584 {
585 zlog_err ("bgp_connect_success peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000586 peer->fd);
paul718e3742002-12-13 20:15:29 +0000587 return -1;
588 }
pauleb821182004-05-01 08:44:08 +0000589 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +0000590
hassof4184462005-02-01 20:13:16 +0000591 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
592 bgp_getsockname (peer);
593
594 if (BGP_DEBUG (normal, NORMAL))
595 {
596 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
597 zlog_debug ("%s open active, local address %s", peer->host,
598 sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
599 else
600 zlog_debug ("%s passive open", peer->host);
601 }
paul718e3742002-12-13 20:15:29 +0000602
603 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
604 bgp_open_send (peer);
605
606 return 0;
607}
608
609/* TCP connect fail */
610int
611bgp_connect_fail (struct peer *peer)
612{
613 bgp_stop (peer);
614 return 0;
615}
616
617/* This function is the first starting point of all BGP connection. It
618 try to connect to remote peer with non-blocking IO. */
619int
620bgp_start (struct peer *peer)
621{
622 int status;
623
624 /* If the peer is passive mode, force to move to Active mode. */
625 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
626 {
627 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
628 return 0;
629 }
630
631 status = bgp_connect (peer);
632
633 switch (status)
634 {
635 case connect_error:
636 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000637 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000638 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
639 break;
640 case connect_success:
641 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000642 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000643 peer->host);
paul718e3742002-12-13 20:15:29 +0000644 BGP_EVENT_ADD (peer, TCP_connection_open);
645 break;
646 case connect_in_progress:
647 /* To check nonblocking connect, we wait until socket is
648 readable or writable. */
649 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000650 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000651 peer->host);
652 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000653 {
654 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000655 peer->fd);
paul718e3742002-12-13 20:15:29 +0000656 return -1;
657 }
pauleb821182004-05-01 08:44:08 +0000658 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
659 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000660 break;
661 }
662 return 0;
663}
664
665/* Connect retry timer is expired when the peer status is Connect. */
666int
667bgp_reconnect (struct peer *peer)
668{
669 bgp_stop (peer);
670 bgp_start (peer);
671 return 0;
672}
673
674int
675bgp_fsm_open (struct peer *peer)
676{
677 /* Send keepalive and make keepalive timer */
678 bgp_keepalive_send (peer);
679
680 /* Reset holdtimer value. */
681 BGP_TIMER_OFF (peer->t_holdtime);
682
683 return 0;
684}
685
686/* Called after event occured, this function change status and reset
687 read/write and timer thread. */
688void
689bgp_fsm_change_status (struct peer *peer, int status)
690{
691 bgp_dump_state (peer, peer->status, status);
692
693 /* Preserve old status and change into new status. */
694 peer->ostatus = peer->status;
695 peer->status = status;
hassof4184462005-02-01 20:13:16 +0000696
697 if (BGP_DEBUG (normal, NORMAL))
698 zlog_debug ("%s went from %s to %s",
699 peer->host,
700 LOOKUP (bgp_status_msg, peer->ostatus),
701 LOOKUP (bgp_status_msg, peer->status));
paul718e3742002-12-13 20:15:29 +0000702}
703
704/* Keepalive send to peer. */
705int
706bgp_fsm_keepalive_expire (struct peer *peer)
707{
708 bgp_keepalive_send (peer);
709 return 0;
710}
711
712/* Hold timer expire. This is error of BGP connection. So cut the
713 peer and change to Idle status. */
714int
715bgp_fsm_holdtime_expire (struct peer *peer)
716{
717 if (BGP_DEBUG (fsm, FSM))
718 zlog (peer->log, LOG_DEBUG, "%s [FSM] Hold timer expire", peer->host);
719
720 /* Send notify to remote peer. */
721 bgp_notify_send (peer, BGP_NOTIFY_HOLD_ERR, 0);
722
723 /* Sweep if it is temporary peer. */
724 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
725 {
726 zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
727 peer_delete (peer);
728 return -1;
729 }
730
731 return 0;
732}
733
734/* Status goes to Established. Send keepalive packet then make first
735 update information. */
736int
737bgp_establish (struct peer *peer)
738{
739 struct bgp_notify *notify;
740 afi_t afi;
741 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000742 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000743
744 /* Reset capability open status flag. */
745 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
746 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
747
748 /* Clear last notification data. */
749 notify = &peer->notify;
750 if (notify->data)
751 XFREE (MTYPE_TMP, notify->data);
752 memset (notify, 0, sizeof (struct bgp_notify));
753
754 /* Clear start timer value to default. */
755 peer->v_start = BGP_INIT_START_TIMER;
756
757 /* Increment established count. */
758 peer->established++;
759 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000760
761 /* bgp log-neighbor-changes of neighbor Up */
762 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
763 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
764
hasso93406d82005-02-02 14:40:33 +0000765 /* graceful restart */
766 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
767 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
768 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
769 {
770 if (peer->afc_nego[afi][safi]
771 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
772 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
773 {
774 if (peer->nsf[afi][safi]
775 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
776 bgp_clear_stale_route (peer, afi, safi);
777
778 peer->nsf[afi][safi] = 1;
779 nsf_af_count++;
780 }
781 else
782 {
783 if (peer->nsf[afi][safi])
784 bgp_clear_stale_route (peer, afi, safi);
785 peer->nsf[afi][safi] = 0;
786 }
787 }
788
789 if (nsf_af_count)
790 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
791 else
792 {
793 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
794 if (peer->t_gr_stale)
795 {
796 BGP_TIMER_OFF (peer->t_gr_stale);
797 if (BGP_DEBUG (events, EVENTS))
798 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
799 }
800 }
801
802 if (peer->t_gr_restart)
803 {
804 BGP_TIMER_OFF (peer->t_gr_restart);
805 if (BGP_DEBUG (events, EVENTS))
806 zlog_debug ("%s graceful restart timer stopped", peer->host);
807 }
808
paul718e3742002-12-13 20:15:29 +0000809#ifdef HAVE_SNMP
810 bgpTrapEstablished (peer);
811#endif /* HAVE_SNMP */
812
813 /* Reset uptime, send keepalive, send current table. */
814 bgp_uptime_reset (peer);
815
816 /* Send route-refresh when ORF is enabled */
817 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
818 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
819 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
820 {
821 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
822 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
823 REFRESH_IMMEDIATE, 0);
824 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
825 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
826 REFRESH_IMMEDIATE, 0);
827 }
828
829 if (peer->v_keepalive)
830 bgp_keepalive_send (peer);
831
832 /* First update is deferred until ORF or ROUTE-REFRESH is received */
833 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
834 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
835 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
836 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
837 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
838 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
839
840 bgp_announce_route_all (peer);
841
842 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
843
844 return 0;
845}
846
847/* Keepalive packet is received. */
848int
849bgp_fsm_keepalive (struct peer *peer)
850{
851 /* peer count update */
852 peer->keepalive_in++;
853
854 BGP_TIMER_OFF (peer->t_holdtime);
855 return 0;
856}
857
858/* Update packet is received. */
859int
860bgp_fsm_update (struct peer *peer)
861{
862 BGP_TIMER_OFF (peer->t_holdtime);
863 return 0;
864}
865
866/* This is empty event. */
867int
868bgp_ignore (struct peer *peer)
869{
870 if (BGP_DEBUG (fsm, FSM))
871 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
872 return 0;
873}
874
875/* Finite State Machine structure */
876struct {
877 int (*func) ();
878 int next_state;
879} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
880{
881 {
882 /* Idle state: In Idle state, all events other than BGP_Start is
883 ignored. With BGP_Start event, finite state machine calls
884 bgp_start(). */
885 {bgp_start, Connect}, /* BGP_Start */
886 {bgp_stop, Idle}, /* BGP_Stop */
887 {bgp_stop, Idle}, /* TCP_connection_open */
888 {bgp_stop, Idle}, /* TCP_connection_closed */
889 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
890 {bgp_stop, Idle}, /* TCP_fatal_error */
891 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
892 {bgp_ignore, Idle}, /* Hold_Timer_expired */
893 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
894 {bgp_ignore, Idle}, /* Receive_OPEN_message */
895 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
896 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
897 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
898 },
899 {
900 /* Connect */
901 {bgp_ignore, Connect}, /* BGP_Start */
902 {bgp_stop, Idle}, /* BGP_Stop */
903 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
904 {bgp_stop, Idle}, /* TCP_connection_closed */
905 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
906 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
907 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
908 {bgp_ignore, Idle}, /* Hold_Timer_expired */
909 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
910 {bgp_ignore, Idle}, /* Receive_OPEN_message */
911 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
912 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
913 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
914 },
915 {
916 /* Active, */
917 {bgp_ignore, Active}, /* BGP_Start */
918 {bgp_stop, Idle}, /* BGP_Stop */
919 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
920 {bgp_stop, Idle}, /* TCP_connection_closed */
921 {bgp_ignore, Active}, /* TCP_connection_open_failed */
922 {bgp_ignore, Idle}, /* TCP_fatal_error */
923 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
924 {bgp_ignore, Idle}, /* Hold_Timer_expired */
925 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
926 {bgp_ignore, Idle}, /* Receive_OPEN_message */
927 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
928 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
929 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
930 },
931 {
932 /* OpenSent, */
933 {bgp_ignore, OpenSent}, /* BGP_Start */
934 {bgp_stop, Idle}, /* BGP_Stop */
935 {bgp_stop, Idle}, /* TCP_connection_open */
936 {bgp_stop, Active}, /* TCP_connection_closed */
937 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
938 {bgp_stop, Idle}, /* TCP_fatal_error */
939 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
940 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
941 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
942 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
943 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
944 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
945 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
946 },
947 {
948 /* OpenConfirm, */
949 {bgp_ignore, OpenConfirm}, /* BGP_Start */
950 {bgp_stop, Idle}, /* BGP_Stop */
951 {bgp_stop, Idle}, /* TCP_connection_open */
952 {bgp_stop, Idle}, /* TCP_connection_closed */
953 {bgp_stop, Idle}, /* TCP_connection_open_failed */
954 {bgp_stop, Idle}, /* TCP_fatal_error */
955 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
956 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
957 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
958 {bgp_ignore, Idle}, /* Receive_OPEN_message */
959 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
960 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
961 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
962 },
963 {
964 /* Established, */
965 {bgp_ignore, Established}, /* BGP_Start */
966 {bgp_stop, Idle}, /* BGP_Stop */
967 {bgp_stop, Idle}, /* TCP_connection_open */
968 {bgp_stop, Idle}, /* TCP_connection_closed */
969 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
970 {bgp_stop, Idle}, /* TCP_fatal_error */
971 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
972 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
973 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
974 {bgp_stop, Idle}, /* Receive_OPEN_message */
975 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
976 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
977 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
978 },
979};
980
paulfd79ac92004-10-13 05:06:08 +0000981static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +0000982{
983 NULL,
984 "BGP_Start",
985 "BGP_Stop",
986 "TCP_connection_open",
987 "TCP_connection_closed",
988 "TCP_connection_open_failed",
989 "TCP_fatal_error",
990 "ConnectRetry_timer_expired",
991 "Hold_Timer_expired",
992 "KeepAlive_timer_expired",
993 "Receive_OPEN_message",
994 "Receive_KEEPALIVE_message",
995 "Receive_UPDATE_message",
996 "Receive_NOTIFICATION_message"
997};
998
999/* Execute event process. */
1000int
1001bgp_event (struct thread *thread)
1002{
1003 int ret;
1004 int event;
1005 int next;
1006 struct peer *peer;
1007
1008 peer = THREAD_ARG (thread);
1009 event = THREAD_VAL (thread);
1010
1011 /* Logging this event. */
1012 next = FSM [peer->status -1][event - 1].next_state;
1013
1014 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +00001015 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001016 bgp_event_str[event],
1017 LOOKUP (bgp_status_msg, peer->status),
1018 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001019
1020 /* Call function. */
1021 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
1022
1023 /* When function do not want proceed next job return -1. */
1024 if (ret < 0)
1025 return ret;
1026
1027 /* If status is changed. */
1028 if (next != peer->status)
1029 bgp_fsm_change_status (peer, next);
1030
1031 /* Make sure timer is set. */
1032 bgp_timer_set (peer);
1033
1034 return 0;
1035}