blob: fc7654f0c1e8d930491d53ceedbfd8e316a2d8b6 [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;
paul200df112005-06-01 11:17:05 +0000217 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000218
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;
paul200df112005-06-01 11:17:05 +0000236 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000237
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;
paul200df112005-06-01 11:17:05 +0000256 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000257
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;
paul200df112005-06-01 11:17:05 +0000276 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000277
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
paul200df112005-06-01 11:17:05 +0000391/* Called after event occured, this function change status and reset
392 read/write and timer thread. */
393void
394bgp_fsm_change_status (struct peer *peer, int status)
395{
396 bgp_dump_state (peer, peer->status, status);
397
398 /* Preserve old status and change into new status. */
399 peer->ostatus = peer->status;
400 peer->status = status;
401
402 if (BGP_DEBUG (normal, NORMAL))
403 zlog_debug ("%s went from %s to %s",
404 peer->host,
405 LOOKUP (bgp_status_msg, peer->ostatus),
406 LOOKUP (bgp_status_msg, peer->status));
407}
408
paul718e3742002-12-13 20:15:29 +0000409/* Administrative BGP peer stop event. */
410int
411bgp_stop (struct peer *peer)
412{
paul718e3742002-12-13 20:15:29 +0000413 afi_t afi;
414 safi_t safi;
paul200df112005-06-01 11:17:05 +0000415 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000416 char orf_name[BUFSIZ];
417
418 /* Increment Dropped count. */
419 if (peer->status == Established)
420 {
paul718e3742002-12-13 20:15:29 +0000421 peer->dropped++;
422 bgp_fsm_change_status (peer, Idle);
paul848973c2003-08-13 00:32:49 +0000423
424 /* bgp log-neighbor-changes of neighbor Down */
425 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
hassoe0701b72004-05-20 09:19:34 +0000426 zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
427 peer_down_str [(int) peer->last_reset]);
paul848973c2003-08-13 00:32:49 +0000428
hasso93406d82005-02-02 14:40:33 +0000429 /* graceful restart */
430 if (peer->t_gr_stale)
431 {
432 BGP_TIMER_OFF (peer->t_gr_stale);
433 if (BGP_DEBUG (events, EVENTS))
434 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
435 }
436 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
437 {
438 if (BGP_DEBUG (events, EVENTS))
439 {
440 zlog_debug ("%s graceful restart timer started for %d sec",
441 peer->host, peer->v_gr_restart);
442 zlog_debug ("%s graceful restart stalepath timer started for %d sec",
443 peer->host, peer->bgp->stalepath_time);
444 }
445 BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
446 peer->v_gr_restart);
447 BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
448 peer->bgp->stalepath_time);
449 }
450 else
451 {
452 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
453
454 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
455 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
456 peer->nsf[afi][safi] = 0;
457 }
458
paul848973c2003-08-13 00:32:49 +0000459 /* set last reset time */
460 peer->resettime = time (NULL);
paulc5317402004-05-03 13:25:06 +0000461 /* Reset uptime. */
462 bgp_uptime_reset (peer);
paul848973c2003-08-13 00:32:49 +0000463
paul718e3742002-12-13 20:15:29 +0000464#ifdef HAVE_SNMP
465 bgpTrapBackwardTransition (peer);
466#endif /* HAVE_SNMP */
paul718e3742002-12-13 20:15:29 +0000467
hasso538621f2004-05-21 09:31:30 +0000468 /* Reset uptime. */
469 bgp_uptime_reset (peer);
470
471 /* Need of clear of peer. */
472 bgp_clear_route_all (peer);
hassof4184462005-02-01 20:13:16 +0000473
474 /* Reset peer synctime */
475 peer->synctime = 0;
hasso538621f2004-05-21 09:31:30 +0000476 }
paul718e3742002-12-13 20:15:29 +0000477
478 /* Stop read and write threads when exists. */
479 BGP_READ_OFF (peer->t_read);
480 BGP_WRITE_OFF (peer->t_write);
481
482 /* Stop all timers. */
483 BGP_TIMER_OFF (peer->t_start);
484 BGP_TIMER_OFF (peer->t_connect);
485 BGP_TIMER_OFF (peer->t_holdtime);
486 BGP_TIMER_OFF (peer->t_keepalive);
487 BGP_TIMER_OFF (peer->t_asorig);
488 BGP_TIMER_OFF (peer->t_routeadv);
489
paul200df112005-06-01 11:17:05 +0000490 /* Delete all existing events of the peer,
491 and corresponding peer ref-count */
492 for (i = thread_cancel_event (master, peer); i > 0; i--)
493 peer_unlock (peer); /* thread event reference */
494
paul718e3742002-12-13 20:15:29 +0000495 /* Stream reset. */
496 peer->packet_size = 0;
497
498 /* Clear input and output buffer. */
499 if (peer->ibuf)
500 stream_reset (peer->ibuf);
501 if (peer->work)
502 stream_reset (peer->work);
paul200df112005-06-01 11:17:05 +0000503 if (peer->obuf)
504 stream_fifo_clean (peer->obuf);
paul718e3742002-12-13 20:15:29 +0000505
pauleb821182004-05-01 08:44:08 +0000506 /* Close of file descriptor. */
507 if (peer->fd >= 0)
508 {
509 close (peer->fd);
510 peer->fd = -1;
511 }
paul718e3742002-12-13 20:15:29 +0000512
513 /* Connection information. */
514 if (peer->su_local)
515 {
paul22db9de2005-05-19 01:50:11 +0000516 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +0000517 peer->su_local = NULL;
518 }
519
520 if (peer->su_remote)
521 {
paul22db9de2005-05-19 01:50:11 +0000522 sockunion_free (peer->su_remote);
paul718e3742002-12-13 20:15:29 +0000523 peer->su_remote = NULL;
524 }
pauleb821182004-05-01 08:44:08 +0000525
paul718e3742002-12-13 20:15:29 +0000526 /* Clear remote router-id. */
527 peer->remote_id.s_addr = 0;
528
hasso538621f2004-05-21 09:31:30 +0000529 /* Clear peer capability flag. */
530 peer->cap = 0;
paul718e3742002-12-13 20:15:29 +0000531
532 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
533 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
534 {
hasso538621f2004-05-21 09:31:30 +0000535 /* Reset all negotiated variables */
536 peer->afc_nego[afi][safi] = 0;
537 peer->afc_adv[afi][safi] = 0;
538 peer->afc_recv[afi][safi] = 0;
539
paul718e3742002-12-13 20:15:29 +0000540 /* peer address family capability flags*/
541 peer->af_cap[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000542
paul718e3742002-12-13 20:15:29 +0000543 /* peer address family status flags*/
544 peer->af_sflags[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000545
paul718e3742002-12-13 20:15:29 +0000546 /* Received ORF prefix-filter */
547 peer->orf_plist[afi][safi] = NULL;
hasso538621f2004-05-21 09:31:30 +0000548
paul718e3742002-12-13 20:15:29 +0000549 /* ORF received prefix-filter pnt */
550 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
551 prefix_bgp_orf_remove_all (orf_name);
552 }
553
554 /* Reset keepalive and holdtime */
555 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
556 {
557 peer->v_keepalive = peer->keepalive;
558 peer->v_holdtime = peer->holdtime;
559 }
560 else
561 {
562 peer->v_keepalive = peer->bgp->default_keepalive;
563 peer->v_holdtime = peer->bgp->default_holdtime;
564 }
565
566 peer->update_time = 0;
567
568 /* Until we are sure that there is no problem about prefix count
569 this should be commented out.*/
570#if 0
571 /* Reset prefix count */
572 peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
573 peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
574 peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
575 peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
576 peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
577#endif /* 0 */
578
579 return 0;
580}
581
582/* BGP peer is stoped by the error. */
583int
584bgp_stop_with_error (struct peer *peer)
585{
586 /* Double start timer. */
587 peer->v_start *= 2;
588
589 /* Overflow check. */
590 if (peer->v_start >= (60 * 2))
591 peer->v_start = (60 * 2);
592
593 bgp_stop (peer);
594
595 return 0;
596}
597
598/* TCP connection open. Next we send open message to remote peer. And
599 add read thread for reading open message. */
600int
601bgp_connect_success (struct peer *peer)
602{
hassof4184462005-02-01 20:13:16 +0000603 char buf1[BUFSIZ];
604
pauleb821182004-05-01 08:44:08 +0000605 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000606 {
607 zlog_err ("bgp_connect_success peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000608 peer->fd);
paul718e3742002-12-13 20:15:29 +0000609 return -1;
610 }
pauleb821182004-05-01 08:44:08 +0000611 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +0000612
hassof4184462005-02-01 20:13:16 +0000613 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
614 bgp_getsockname (peer);
615
616 if (BGP_DEBUG (normal, NORMAL))
617 {
618 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
619 zlog_debug ("%s open active, local address %s", peer->host,
620 sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
621 else
622 zlog_debug ("%s passive open", peer->host);
623 }
paul718e3742002-12-13 20:15:29 +0000624
625 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
626 bgp_open_send (peer);
627
628 return 0;
629}
630
631/* TCP connect fail */
632int
633bgp_connect_fail (struct peer *peer)
634{
635 bgp_stop (peer);
636 return 0;
637}
638
639/* This function is the first starting point of all BGP connection. It
640 try to connect to remote peer with non-blocking IO. */
641int
642bgp_start (struct peer *peer)
643{
644 int status;
645
646 /* If the peer is passive mode, force to move to Active mode. */
647 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
648 {
649 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
650 return 0;
651 }
652
653 status = bgp_connect (peer);
654
655 switch (status)
656 {
657 case connect_error:
658 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000659 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000660 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
661 break;
662 case connect_success:
663 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000664 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000665 peer->host);
paul718e3742002-12-13 20:15:29 +0000666 BGP_EVENT_ADD (peer, TCP_connection_open);
667 break;
668 case connect_in_progress:
669 /* To check nonblocking connect, we wait until socket is
670 readable or writable. */
671 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000672 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000673 peer->host);
674 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000675 {
676 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000677 peer->fd);
paul718e3742002-12-13 20:15:29 +0000678 return -1;
679 }
pauleb821182004-05-01 08:44:08 +0000680 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
681 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000682 break;
683 }
684 return 0;
685}
686
687/* Connect retry timer is expired when the peer status is Connect. */
688int
689bgp_reconnect (struct peer *peer)
690{
691 bgp_stop (peer);
692 bgp_start (peer);
693 return 0;
694}
695
696int
697bgp_fsm_open (struct peer *peer)
698{
699 /* Send keepalive and make keepalive timer */
700 bgp_keepalive_send (peer);
701
702 /* Reset holdtimer value. */
703 BGP_TIMER_OFF (peer->t_holdtime);
704
705 return 0;
706}
707
paul718e3742002-12-13 20:15:29 +0000708/* Keepalive send to peer. */
709int
710bgp_fsm_keepalive_expire (struct peer *peer)
711{
712 bgp_keepalive_send (peer);
713 return 0;
714}
715
716/* Hold timer expire. This is error of BGP connection. So cut the
717 peer and change to Idle status. */
718int
719bgp_fsm_holdtime_expire (struct peer *peer)
720{
721 if (BGP_DEBUG (fsm, FSM))
722 zlog (peer->log, LOG_DEBUG, "%s [FSM] Hold timer expire", peer->host);
723
724 /* Send notify to remote peer. */
725 bgp_notify_send (peer, BGP_NOTIFY_HOLD_ERR, 0);
726
727 /* Sweep if it is temporary peer. */
728 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
729 {
730 zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
731 peer_delete (peer);
732 return -1;
733 }
734
735 return 0;
736}
737
738/* Status goes to Established. Send keepalive packet then make first
739 update information. */
740int
741bgp_establish (struct peer *peer)
742{
743 struct bgp_notify *notify;
744 afi_t afi;
745 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000746 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000747
748 /* Reset capability open status flag. */
749 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
750 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
751
752 /* Clear last notification data. */
753 notify = &peer->notify;
754 if (notify->data)
755 XFREE (MTYPE_TMP, notify->data);
756 memset (notify, 0, sizeof (struct bgp_notify));
757
758 /* Clear start timer value to default. */
759 peer->v_start = BGP_INIT_START_TIMER;
760
761 /* Increment established count. */
762 peer->established++;
763 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000764
765 /* bgp log-neighbor-changes of neighbor Up */
766 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
767 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
768
hasso93406d82005-02-02 14:40:33 +0000769 /* graceful restart */
770 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
771 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
772 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
773 {
774 if (peer->afc_nego[afi][safi]
775 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
776 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
777 {
778 if (peer->nsf[afi][safi]
779 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
780 bgp_clear_stale_route (peer, afi, safi);
781
782 peer->nsf[afi][safi] = 1;
783 nsf_af_count++;
784 }
785 else
786 {
787 if (peer->nsf[afi][safi])
788 bgp_clear_stale_route (peer, afi, safi);
789 peer->nsf[afi][safi] = 0;
790 }
791 }
792
793 if (nsf_af_count)
794 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
795 else
796 {
797 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
798 if (peer->t_gr_stale)
799 {
800 BGP_TIMER_OFF (peer->t_gr_stale);
801 if (BGP_DEBUG (events, EVENTS))
802 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
803 }
804 }
805
806 if (peer->t_gr_restart)
807 {
808 BGP_TIMER_OFF (peer->t_gr_restart);
809 if (BGP_DEBUG (events, EVENTS))
810 zlog_debug ("%s graceful restart timer stopped", peer->host);
811 }
812
paul718e3742002-12-13 20:15:29 +0000813#ifdef HAVE_SNMP
814 bgpTrapEstablished (peer);
815#endif /* HAVE_SNMP */
816
817 /* Reset uptime, send keepalive, send current table. */
818 bgp_uptime_reset (peer);
819
820 /* Send route-refresh when ORF is enabled */
821 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
822 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
823 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
824 {
825 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
826 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
827 REFRESH_IMMEDIATE, 0);
828 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
829 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
830 REFRESH_IMMEDIATE, 0);
831 }
832
833 if (peer->v_keepalive)
834 bgp_keepalive_send (peer);
835
836 /* First update is deferred until ORF or ROUTE-REFRESH is received */
837 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
838 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
839 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
840 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
841 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
842 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
843
844 bgp_announce_route_all (peer);
845
846 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
847
848 return 0;
849}
850
851/* Keepalive packet is received. */
852int
853bgp_fsm_keepalive (struct peer *peer)
854{
855 /* peer count update */
856 peer->keepalive_in++;
857
858 BGP_TIMER_OFF (peer->t_holdtime);
859 return 0;
860}
861
862/* Update packet is received. */
863int
864bgp_fsm_update (struct peer *peer)
865{
866 BGP_TIMER_OFF (peer->t_holdtime);
867 return 0;
868}
869
870/* This is empty event. */
871int
872bgp_ignore (struct peer *peer)
873{
874 if (BGP_DEBUG (fsm, FSM))
875 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
876 return 0;
877}
878
879/* Finite State Machine structure */
880struct {
881 int (*func) ();
882 int next_state;
883} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
884{
885 {
886 /* Idle state: In Idle state, all events other than BGP_Start is
887 ignored. With BGP_Start event, finite state machine calls
888 bgp_start(). */
889 {bgp_start, Connect}, /* BGP_Start */
890 {bgp_stop, Idle}, /* BGP_Stop */
891 {bgp_stop, Idle}, /* TCP_connection_open */
892 {bgp_stop, Idle}, /* TCP_connection_closed */
893 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
894 {bgp_stop, Idle}, /* TCP_fatal_error */
895 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
896 {bgp_ignore, Idle}, /* Hold_Timer_expired */
897 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
898 {bgp_ignore, Idle}, /* Receive_OPEN_message */
899 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
900 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
901 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
902 },
903 {
904 /* Connect */
905 {bgp_ignore, Connect}, /* BGP_Start */
906 {bgp_stop, Idle}, /* BGP_Stop */
907 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
908 {bgp_stop, Idle}, /* TCP_connection_closed */
909 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
910 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
911 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
912 {bgp_ignore, Idle}, /* Hold_Timer_expired */
913 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
914 {bgp_ignore, Idle}, /* Receive_OPEN_message */
915 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
916 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
917 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
918 },
919 {
920 /* Active, */
921 {bgp_ignore, Active}, /* BGP_Start */
922 {bgp_stop, Idle}, /* BGP_Stop */
923 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
924 {bgp_stop, Idle}, /* TCP_connection_closed */
925 {bgp_ignore, Active}, /* TCP_connection_open_failed */
926 {bgp_ignore, Idle}, /* TCP_fatal_error */
927 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
928 {bgp_ignore, Idle}, /* Hold_Timer_expired */
929 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
930 {bgp_ignore, Idle}, /* Receive_OPEN_message */
931 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
932 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
933 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
934 },
935 {
936 /* OpenSent, */
937 {bgp_ignore, OpenSent}, /* BGP_Start */
938 {bgp_stop, Idle}, /* BGP_Stop */
939 {bgp_stop, Idle}, /* TCP_connection_open */
940 {bgp_stop, Active}, /* TCP_connection_closed */
941 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
942 {bgp_stop, Idle}, /* TCP_fatal_error */
943 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
944 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
945 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
946 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
947 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
948 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
949 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
950 },
951 {
952 /* OpenConfirm, */
953 {bgp_ignore, OpenConfirm}, /* BGP_Start */
954 {bgp_stop, Idle}, /* BGP_Stop */
955 {bgp_stop, Idle}, /* TCP_connection_open */
956 {bgp_stop, Idle}, /* TCP_connection_closed */
957 {bgp_stop, Idle}, /* TCP_connection_open_failed */
958 {bgp_stop, Idle}, /* TCP_fatal_error */
959 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
960 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
961 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
962 {bgp_ignore, Idle}, /* Receive_OPEN_message */
963 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
964 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
965 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
966 },
967 {
968 /* Established, */
969 {bgp_ignore, Established}, /* BGP_Start */
970 {bgp_stop, Idle}, /* BGP_Stop */
971 {bgp_stop, Idle}, /* TCP_connection_open */
972 {bgp_stop, Idle}, /* TCP_connection_closed */
973 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
974 {bgp_stop, Idle}, /* TCP_fatal_error */
975 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
976 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
977 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
978 {bgp_stop, Idle}, /* Receive_OPEN_message */
979 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
980 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
981 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
982 },
983};
984
paulfd79ac92004-10-13 05:06:08 +0000985static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +0000986{
987 NULL,
988 "BGP_Start",
989 "BGP_Stop",
990 "TCP_connection_open",
991 "TCP_connection_closed",
992 "TCP_connection_open_failed",
993 "TCP_fatal_error",
994 "ConnectRetry_timer_expired",
995 "Hold_Timer_expired",
996 "KeepAlive_timer_expired",
997 "Receive_OPEN_message",
998 "Receive_KEEPALIVE_message",
999 "Receive_UPDATE_message",
1000 "Receive_NOTIFICATION_message"
1001};
1002
1003/* Execute event process. */
1004int
1005bgp_event (struct thread *thread)
1006{
1007 int ret;
1008 int event;
1009 int next;
1010 struct peer *peer;
1011
1012 peer = THREAD_ARG (thread);
1013 event = THREAD_VAL (thread);
1014
1015 /* Logging this event. */
1016 next = FSM [peer->status -1][event - 1].next_state;
1017
1018 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +00001019 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001020 bgp_event_str[event],
1021 LOOKUP (bgp_status_msg, peer->status),
1022 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001023
1024 /* Call function. */
1025 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
1026
1027 /* When function do not want proceed next job return -1. */
paul200df112005-06-01 11:17:05 +00001028 if (ret >= 0)
1029 {
1030 /* If status is changed. */
1031 if (next != peer->status)
1032 bgp_fsm_change_status (peer, next);
paul718e3742002-12-13 20:15:29 +00001033
paul200df112005-06-01 11:17:05 +00001034 /* Make sure timer is set. */
1035 bgp_timer_set (peer);
1036 }
1037
1038 peer_unlock (peer); /* bgp-event peer reference */
1039 return ret;
paul718e3742002-12-13 20:15:29 +00001040}