blob: c4cfd58e56d9af58a7a5fdf77f55a8294eecb688 [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"
Paul Jakma782fb072015-09-15 16:17:22 +010033#include "workqueue.h"
Donald Sharp04907292016-01-07 10:03:01 -050034#include "filter.h"
paul718e3742002-12-13 20:15:29 +000035
36#include "bgpd/bgpd.h"
37#include "bgpd/bgp_attr.h"
38#include "bgpd/bgp_debug.h"
39#include "bgpd/bgp_fsm.h"
40#include "bgpd/bgp_packet.h"
41#include "bgpd/bgp_network.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_open.h"
45#ifdef HAVE_SNMP
46#include "bgpd/bgp_snmp.h"
47#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020048
paul718e3742002-12-13 20:15:29 +000049/* BGP FSM (finite state machine) has three types of functions. Type
50 one is thread functions. Type two is event functions. Type three
51 is FSM functions. Timer functions are set by bgp_timer_set
52 function. */
53
54/* BGP event function. */
55int bgp_event (struct thread *);
56
57/* BGP thread functions. */
58static int bgp_start_timer (struct thread *);
59static int bgp_connect_timer (struct thread *);
60static int bgp_holdtime_timer (struct thread *);
61static int bgp_keepalive_timer (struct thread *);
62
63/* BGP FSM functions. */
64static int bgp_start (struct peer *);
65
66/* BGP start timer jitter. */
paul94f2b392005-06-28 12:44:16 +000067static int
paul718e3742002-12-13 20:15:29 +000068bgp_start_jitter (int time)
69{
Donald Sharpf31bab42015-06-19 19:26:19 -040070 return ((random () % (time + 1)) - (time / 2));
paul718e3742002-12-13 20:15:29 +000071}
72
Paul Jakmaca058a32006-09-14 02:58:49 +000073/* Check if suppress start/restart of sessions to peer. */
74#define BGP_PEER_START_SUPPRESSED(P) \
75 (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \
76 || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW))
77
paul718e3742002-12-13 20:15:29 +000078/* Hook function called after bgp event is occered. And vty's
79 neighbor command invoke this function after making neighbor
80 structure. */
81void
82bgp_timer_set (struct peer *peer)
83{
84 int jitter = 0;
85
86 switch (peer->status)
87 {
88 case Idle:
89 /* First entry point of peer's finite state machine. In Idle
90 status start timer is on unless peer is shutdown or peer is
91 inactive. All other timer must be turned off */
Paul Jakmaca058a32006-09-14 02:58:49 +000092 if (BGP_PEER_START_SUPPRESSED (peer) || ! peer_active (peer))
paul718e3742002-12-13 20:15:29 +000093 {
94 BGP_TIMER_OFF (peer->t_start);
95 }
96 else
97 {
98 jitter = bgp_start_jitter (peer->v_start);
99 BGP_TIMER_ON (peer->t_start, bgp_start_timer,
100 peer->v_start + jitter);
101 }
102 BGP_TIMER_OFF (peer->t_connect);
103 BGP_TIMER_OFF (peer->t_holdtime);
104 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000105 BGP_TIMER_OFF (peer->t_routeadv);
106 break;
107
108 case Connect:
109 /* After start timer is expired, the peer moves to Connnect
110 status. Make sure start timer is off and connect timer is
111 on. */
112 BGP_TIMER_OFF (peer->t_start);
113 BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
114 BGP_TIMER_OFF (peer->t_holdtime);
115 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000116 BGP_TIMER_OFF (peer->t_routeadv);
117 break;
118
119 case Active:
120 /* Active is waiting connection from remote peer. And if
121 connect timer is expired, change status to Connect. */
122 BGP_TIMER_OFF (peer->t_start);
123 /* If peer is passive mode, do not set connect timer. */
hasso93406d82005-02-02 14:40:33 +0000124 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)
125 || CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
paul718e3742002-12-13 20:15:29 +0000126 {
127 BGP_TIMER_OFF (peer->t_connect);
128 }
129 else
130 {
131 BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
132 }
133 BGP_TIMER_OFF (peer->t_holdtime);
134 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000135 BGP_TIMER_OFF (peer->t_routeadv);
136 break;
137
138 case OpenSent:
139 /* OpenSent status. */
140 BGP_TIMER_OFF (peer->t_start);
141 BGP_TIMER_OFF (peer->t_connect);
142 if (peer->v_holdtime != 0)
143 {
144 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
145 peer->v_holdtime);
146 }
147 else
148 {
149 BGP_TIMER_OFF (peer->t_holdtime);
150 }
151 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000152 BGP_TIMER_OFF (peer->t_routeadv);
153 break;
154
155 case OpenConfirm:
156 /* OpenConfirm status. */
157 BGP_TIMER_OFF (peer->t_start);
158 BGP_TIMER_OFF (peer->t_connect);
159
160 /* If the negotiated Hold Time value is zero, then the Hold Time
161 timer and KeepAlive timers are not started. */
162 if (peer->v_holdtime == 0)
163 {
164 BGP_TIMER_OFF (peer->t_holdtime);
165 BGP_TIMER_OFF (peer->t_keepalive);
166 }
167 else
168 {
169 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
170 peer->v_holdtime);
171 BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
172 peer->v_keepalive);
173 }
paul718e3742002-12-13 20:15:29 +0000174 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 }
paul718e3742002-12-13 20:15:29 +0000197 break;
Paul Jakmaca058a32006-09-14 02:58:49 +0000198 case Deleted:
199 BGP_TIMER_OFF (peer->t_gr_restart);
200 BGP_TIMER_OFF (peer->t_gr_stale);
201 BGP_TIMER_OFF (peer->t_pmax_restart);
202 case Clearing:
203 BGP_TIMER_OFF (peer->t_start);
204 BGP_TIMER_OFF (peer->t_connect);
205 BGP_TIMER_OFF (peer->t_holdtime);
206 BGP_TIMER_OFF (peer->t_keepalive);
Paul Jakmaca058a32006-09-14 02:58:49 +0000207 BGP_TIMER_OFF (peer->t_routeadv);
paul718e3742002-12-13 20:15:29 +0000208 }
209}
210
211/* BGP start timer. This function set BGP_Start event to thread value
212 and process event. */
213static int
214bgp_start_timer (struct thread *thread)
215{
216 struct peer *peer;
217
218 peer = THREAD_ARG (thread);
219 peer->t_start = NULL;
220
221 if (BGP_DEBUG (fsm, FSM))
222 zlog (peer->log, LOG_DEBUG,
223 "%s [FSM] Timer (start timer expire).", peer->host);
224
225 THREAD_VAL (thread) = BGP_Start;
paul200df112005-06-01 11:17:05 +0000226 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000227
228 return 0;
229}
230
231/* BGP connect retry timer. */
232static int
233bgp_connect_timer (struct thread *thread)
234{
235 struct peer *peer;
236
237 peer = THREAD_ARG (thread);
238 peer->t_connect = NULL;
239
240 if (BGP_DEBUG (fsm, FSM))
241 zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)",
242 peer->host);
243
244 THREAD_VAL (thread) = ConnectRetry_timer_expired;
paul200df112005-06-01 11:17:05 +0000245 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000246
247 return 0;
248}
249
250/* BGP holdtime timer. */
251static int
252bgp_holdtime_timer (struct thread *thread)
253{
254 struct peer *peer;
255
256 peer = THREAD_ARG (thread);
257 peer->t_holdtime = NULL;
258
259 if (BGP_DEBUG (fsm, FSM))
260 zlog (peer->log, LOG_DEBUG,
261 "%s [FSM] Timer (holdtime timer expire)",
262 peer->host);
263
264 THREAD_VAL (thread) = Hold_Timer_expired;
paul200df112005-06-01 11:17:05 +0000265 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000266
267 return 0;
268}
269
270/* BGP keepalive fire ! */
271static int
272bgp_keepalive_timer (struct thread *thread)
273{
274 struct peer *peer;
275
276 peer = THREAD_ARG (thread);
277 peer->t_keepalive = NULL;
278
279 if (BGP_DEBUG (fsm, FSM))
280 zlog (peer->log, LOG_DEBUG,
281 "%s [FSM] Timer (keepalive timer expire)",
282 peer->host);
283
284 THREAD_VAL (thread) = KeepAlive_timer_expired;
paul200df112005-06-01 11:17:05 +0000285 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000286
287 return 0;
288}
289
paul94f2b392005-06-28 12:44:16 +0000290static int
paul718e3742002-12-13 20:15:29 +0000291bgp_routeadv_timer (struct thread *thread)
292{
293 struct peer *peer;
294
295 peer = THREAD_ARG (thread);
296 peer->t_routeadv = NULL;
297
298 if (BGP_DEBUG (fsm, FSM))
299 zlog (peer->log, LOG_DEBUG,
300 "%s [FSM] Timer (routeadv timer expire)",
301 peer->host);
302
Stephen Hemminger65957882010-01-15 16:22:10 +0300303 peer->synctime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000304
pauleb821182004-05-01 08:44:08 +0000305 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000306
307 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
308 peer->v_routeadv);
309
310 return 0;
311}
312
hassoe0701b72004-05-20 09:19:34 +0000313/* BGP Peer Down Cause */
paulfd79ac92004-10-13 05:06:08 +0000314const char *peer_down_str[] =
hassoe0701b72004-05-20 09:19:34 +0000315{
316 "",
317 "Router ID changed",
318 "Remote AS changed",
319 "Local AS change",
320 "Cluster ID changed",
321 "Confederation identifier changed",
322 "Confederation peer changed",
323 "RR client config change",
324 "RS client config change",
325 "Update source change",
326 "Address family activated",
327 "Admin. shutdown",
328 "User reset",
329 "BGP Notification received",
330 "BGP Notification send",
331 "Peer closed the session",
332 "Neighbor deleted",
333 "Peer-group add member",
334 "Peer-group delete member",
335 "Capability changed",
336 "Passive config change",
hasso93406d82005-02-02 14:40:33 +0000337 "Multihop config change",
338 "NSF peer closed the session"
hassoe0701b72004-05-20 09:19:34 +0000339};
340
paul94f2b392005-06-28 12:44:16 +0000341static int
hasso93406d82005-02-02 14:40:33 +0000342bgp_graceful_restart_timer_expire (struct thread *thread)
343{
344 struct peer *peer;
345 afi_t afi;
346 safi_t safi;
347
348 peer = THREAD_ARG (thread);
349 peer->t_gr_restart = NULL;
350
351 /* NSF delete stale route */
352 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400353 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000354 if (peer->nsf[afi][safi])
355 bgp_clear_stale_route (peer, afi, safi);
356
357 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
358 BGP_TIMER_OFF (peer->t_gr_stale);
359
360 if (BGP_DEBUG (events, EVENTS))
361 {
362 zlog_debug ("%s graceful restart timer expired", peer->host);
363 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
364 }
365
366 bgp_timer_set (peer);
367
368 return 0;
369}
370
paul94f2b392005-06-28 12:44:16 +0000371static int
hasso93406d82005-02-02 14:40:33 +0000372bgp_graceful_stale_timer_expire (struct thread *thread)
373{
374 struct peer *peer;
375 afi_t afi;
376 safi_t safi;
377
378 peer = THREAD_ARG (thread);
379 peer->t_gr_stale = NULL;
380
381 if (BGP_DEBUG (events, EVENTS))
382 zlog_debug ("%s graceful restart stalepath timer expired", peer->host);
383
384 /* NSF delete stale route */
385 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400386 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000387 if (peer->nsf[afi][safi])
388 bgp_clear_stale_route (peer, afi, safi);
389
390 return 0;
391}
392
paul200df112005-06-01 11:17:05 +0000393/* Called after event occured, this function change status and reset
394 read/write and timer thread. */
395void
396bgp_fsm_change_status (struct peer *peer, int status)
397{
398 bgp_dump_state (peer, peer->status, status);
399
Paul Jakmaf2c31ac2007-02-22 17:48:42 +0000400 /* Transition into Clearing or Deleted must /always/ clear all routes..
401 * (and must do so before actually changing into Deleted..
402 */
403 if (status >= Clearing)
Donald Sharp7ef42212015-03-30 06:32:52 -0700404 {
405 bgp_clear_route_all (peer);
406
407 /* If no route was queued for the clear-node processing, generate the
408 * completion event here. This is needed because if there are no routes
409 * to trigger the background clear-node thread, the event won't get
410 * generated and the peer would be stuck in Clearing. Note that this
411 * event is for the peer and helps the peer transition out of Clearing
412 * state; it should not be generated per (AFI,SAFI). The event is
413 * directly posted here without calling clear_node_complete() as we
414 * shouldn't do an extra unlock. This event will get processed after
415 * the state change that happens below, so peer will be in Clearing
416 * (or Deleted).
417 */
Paul Jakma782fb072015-09-15 16:17:22 +0100418 if (!work_queue_is_scheduled (peer->clear_node_queue))
Donald Sharp7ef42212015-03-30 06:32:52 -0700419 BGP_EVENT_ADD (peer, Clearing_Completed);
420 }
Paul Jakmaf2c31ac2007-02-22 17:48:42 +0000421
paul200df112005-06-01 11:17:05 +0000422 /* Preserve old status and change into new status. */
423 peer->ostatus = peer->status;
424 peer->status = status;
Paul Jakmaf2c31ac2007-02-22 17:48:42 +0000425
paul200df112005-06-01 11:17:05 +0000426 if (BGP_DEBUG (normal, NORMAL))
427 zlog_debug ("%s went from %s to %s",
428 peer->host,
429 LOOKUP (bgp_status_msg, peer->ostatus),
430 LOOKUP (bgp_status_msg, peer->status));
431}
432
Steve Hill3117b5c2009-07-28 17:50:00 +0100433/* Flush the event queue and ensure the peer is shut down */
Stephen Hemminger9e4ca892009-12-10 11:57:05 +0300434static int
Steve Hill3117b5c2009-07-28 17:50:00 +0100435bgp_clearing_completed (struct peer *peer)
436{
437 int rc = bgp_stop(peer);
438 BGP_EVENT_FLUSH (peer);
439
440 return rc;
441}
442
paul718e3742002-12-13 20:15:29 +0000443/* Administrative BGP peer stop event. */
Steve Hill3117b5c2009-07-28 17:50:00 +0100444/* May be called multiple times for the same peer */
paul718e3742002-12-13 20:15:29 +0000445int
446bgp_stop (struct peer *peer)
447{
paul718e3742002-12-13 20:15:29 +0000448 afi_t afi;
449 safi_t safi;
450 char orf_name[BUFSIZ];
451
Steve Hill3117b5c2009-07-28 17:50:00 +0100452 /* Can't do this in Clearing; events are used for state transitions */
453 if (peer->status != Clearing)
Paul Jakma2158ad22009-07-28 18:10:55 +0100454 {
455 /* Delete all existing events of the peer */
456 BGP_EVENT_FLUSH (peer);
457 }
Paul Jakmadcdf3992006-10-15 23:39:59 +0000458
paul718e3742002-12-13 20:15:29 +0000459 /* Increment Dropped count. */
460 if (peer->status == Established)
461 {
paul718e3742002-12-13 20:15:29 +0000462 peer->dropped++;
paul848973c2003-08-13 00:32:49 +0000463
464 /* bgp log-neighbor-changes of neighbor Down */
465 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
hassoe0701b72004-05-20 09:19:34 +0000466 zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
467 peer_down_str [(int) peer->last_reset]);
paul848973c2003-08-13 00:32:49 +0000468
hasso93406d82005-02-02 14:40:33 +0000469 /* graceful restart */
470 if (peer->t_gr_stale)
471 {
472 BGP_TIMER_OFF (peer->t_gr_stale);
473 if (BGP_DEBUG (events, EVENTS))
474 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
475 }
476 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
477 {
478 if (BGP_DEBUG (events, EVENTS))
479 {
480 zlog_debug ("%s graceful restart timer started for %d sec",
481 peer->host, peer->v_gr_restart);
482 zlog_debug ("%s graceful restart stalepath timer started for %d sec",
483 peer->host, peer->bgp->stalepath_time);
484 }
485 BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
486 peer->v_gr_restart);
487 BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
488 peer->bgp->stalepath_time);
489 }
490 else
491 {
492 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
493
494 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400495 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000496 peer->nsf[afi][safi] = 0;
497 }
498
paul848973c2003-08-13 00:32:49 +0000499 /* set last reset time */
Stephen Hemminger65957882010-01-15 16:22:10 +0300500 peer->resettime = peer->uptime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000501
paul718e3742002-12-13 20:15:29 +0000502#ifdef HAVE_SNMP
503 bgpTrapBackwardTransition (peer);
504#endif /* HAVE_SNMP */
paul718e3742002-12-13 20:15:29 +0000505
hassof4184462005-02-01 20:13:16 +0000506 /* Reset peer synctime */
507 peer->synctime = 0;
hasso538621f2004-05-21 09:31:30 +0000508 }
paul718e3742002-12-13 20:15:29 +0000509
510 /* Stop read and write threads when exists. */
511 BGP_READ_OFF (peer->t_read);
512 BGP_WRITE_OFF (peer->t_write);
513
514 /* Stop all timers. */
515 BGP_TIMER_OFF (peer->t_start);
516 BGP_TIMER_OFF (peer->t_connect);
517 BGP_TIMER_OFF (peer->t_holdtime);
518 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000519 BGP_TIMER_OFF (peer->t_routeadv);
520
paul718e3742002-12-13 20:15:29 +0000521 /* Stream reset. */
522 peer->packet_size = 0;
523
524 /* Clear input and output buffer. */
525 if (peer->ibuf)
526 stream_reset (peer->ibuf);
527 if (peer->work)
528 stream_reset (peer->work);
paul200df112005-06-01 11:17:05 +0000529 if (peer->obuf)
530 stream_fifo_clean (peer->obuf);
paul718e3742002-12-13 20:15:29 +0000531
pauleb821182004-05-01 08:44:08 +0000532 /* Close of file descriptor. */
533 if (peer->fd >= 0)
534 {
535 close (peer->fd);
536 peer->fd = -1;
537 }
paul718e3742002-12-13 20:15:29 +0000538
paul718e3742002-12-13 20:15:29 +0000539 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
540 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
541 {
hasso538621f2004-05-21 09:31:30 +0000542 /* Reset all negotiated variables */
543 peer->afc_nego[afi][safi] = 0;
544 peer->afc_adv[afi][safi] = 0;
545 peer->afc_recv[afi][safi] = 0;
546
paul718e3742002-12-13 20:15:29 +0000547 /* peer address family capability flags*/
548 peer->af_cap[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000549
paul718e3742002-12-13 20:15:29 +0000550 /* peer address family status flags*/
551 peer->af_sflags[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000552
paul718e3742002-12-13 20:15:29 +0000553 /* Received ORF prefix-filter */
554 peer->orf_plist[afi][safi] = NULL;
hasso538621f2004-05-21 09:31:30 +0000555
paul718e3742002-12-13 20:15:29 +0000556 /* ORF received prefix-filter pnt */
557 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200558 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000559 }
560
561 /* Reset keepalive and holdtime */
562 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
563 {
564 peer->v_keepalive = peer->keepalive;
565 peer->v_holdtime = peer->holdtime;
566 }
567 else
568 {
569 peer->v_keepalive = peer->bgp->default_keepalive;
570 peer->v_holdtime = peer->bgp->default_holdtime;
571 }
572
573 peer->update_time = 0;
574
575 /* Until we are sure that there is no problem about prefix count
576 this should be commented out.*/
577#if 0
578 /* Reset prefix count */
579 peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
580 peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
581 peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
582 peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
583 peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
584#endif /* 0 */
585
586 return 0;
587}
588
589/* BGP peer is stoped by the error. */
paul94f2b392005-06-28 12:44:16 +0000590static int
paul718e3742002-12-13 20:15:29 +0000591bgp_stop_with_error (struct peer *peer)
592{
593 /* Double start timer. */
594 peer->v_start *= 2;
595
596 /* Overflow check. */
597 if (peer->v_start >= (60 * 2))
598 peer->v_start = (60 * 2);
599
600 bgp_stop (peer);
601
602 return 0;
603}
604
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200605
606/* something went wrong, send notify and tear down */
607static int
608bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code)
609{
610 /* Send notify to remote peer */
611 bgp_notify_send (peer, code, sub_code);
612
613 /* Sweep if it is temporary peer. */
614 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
615 {
616 zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
617 peer_delete (peer);
618 return -1;
619 }
620
621 /* Clear start timer value to default. */
622 peer->v_start = BGP_INIT_START_TIMER;
623
624 /* bgp_stop needs to be invoked while in Established state */
625 bgp_stop(peer);
626
627 return 0;
628}
629
630
paul718e3742002-12-13 20:15:29 +0000631/* TCP connection open. Next we send open message to remote peer. And
632 add read thread for reading open message. */
paul94f2b392005-06-28 12:44:16 +0000633static int
paul718e3742002-12-13 20:15:29 +0000634bgp_connect_success (struct peer *peer)
635{
pauleb821182004-05-01 08:44:08 +0000636 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000637 {
638 zlog_err ("bgp_connect_success peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000639 peer->fd);
paul718e3742002-12-13 20:15:29 +0000640 return -1;
641 }
pauleb821182004-05-01 08:44:08 +0000642 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +0000643
hassof4184462005-02-01 20:13:16 +0000644 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
645 bgp_getsockname (peer);
646
647 if (BGP_DEBUG (normal, NORMAL))
648 {
Jorge Boncompte [DTI2]682ca042012-04-10 16:57:27 +0200649 char buf1[SU_ADDRSTRLEN];
650
hassof4184462005-02-01 20:13:16 +0000651 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
652 zlog_debug ("%s open active, local address %s", peer->host,
653 sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
654 else
655 zlog_debug ("%s passive open", peer->host);
656 }
paul718e3742002-12-13 20:15:29 +0000657
Paul Jakma6556d8a2008-08-26 14:33:28 +0100658 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
paul718e3742002-12-13 20:15:29 +0000659 bgp_open_send (peer);
660
661 return 0;
662}
663
664/* TCP connect fail */
paul94f2b392005-06-28 12:44:16 +0000665static int
paul718e3742002-12-13 20:15:29 +0000666bgp_connect_fail (struct peer *peer)
667{
668 bgp_stop (peer);
669 return 0;
670}
671
672/* This function is the first starting point of all BGP connection. It
673 try to connect to remote peer with non-blocking IO. */
674int
675bgp_start (struct peer *peer)
676{
677 int status;
678
Paul Jakmaca058a32006-09-14 02:58:49 +0000679 if (BGP_PEER_START_SUPPRESSED (peer))
680 {
681 if (BGP_DEBUG (fsm, FSM))
682 plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
683 " - this is never supposed to happen!", peer->host);
684 return -1;
685 }
686
Paul Jakma33d5ab92006-07-02 11:01:50 +0000687 /* Scrub some information that might be left over from a previous,
688 * session
689 */
690 /* Connection information. */
691 if (peer->su_local)
692 {
693 sockunion_free (peer->su_local);
694 peer->su_local = NULL;
695 }
696
697 if (peer->su_remote)
698 {
699 sockunion_free (peer->su_remote);
700 peer->su_remote = NULL;
701 }
702
703 /* Clear remote router-id. */
704 peer->remote_id.s_addr = 0;
705
706 /* Clear peer capability flag. */
707 peer->cap = 0;
708
paul718e3742002-12-13 20:15:29 +0000709 /* If the peer is passive mode, force to move to Active mode. */
710 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
711 {
712 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
713 return 0;
714 }
715
716 status = bgp_connect (peer);
717
718 switch (status)
719 {
720 case connect_error:
721 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000722 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000723 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
724 break;
725 case connect_success:
726 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000727 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000728 peer->host);
paul718e3742002-12-13 20:15:29 +0000729 BGP_EVENT_ADD (peer, TCP_connection_open);
730 break;
731 case connect_in_progress:
732 /* To check nonblocking connect, we wait until socket is
733 readable or writable. */
734 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000735 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000736 peer->host);
737 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000738 {
739 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000740 peer->fd);
paul718e3742002-12-13 20:15:29 +0000741 return -1;
742 }
pauleb821182004-05-01 08:44:08 +0000743 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
744 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000745 break;
746 }
747 return 0;
748}
749
750/* Connect retry timer is expired when the peer status is Connect. */
paul94f2b392005-06-28 12:44:16 +0000751static int
paul718e3742002-12-13 20:15:29 +0000752bgp_reconnect (struct peer *peer)
753{
754 bgp_stop (peer);
755 bgp_start (peer);
756 return 0;
757}
758
paul94f2b392005-06-28 12:44:16 +0000759static int
paul718e3742002-12-13 20:15:29 +0000760bgp_fsm_open (struct peer *peer)
761{
762 /* Send keepalive and make keepalive timer */
763 bgp_keepalive_send (peer);
764
765 /* Reset holdtimer value. */
766 BGP_TIMER_OFF (peer->t_holdtime);
767
768 return 0;
769}
770
paul718e3742002-12-13 20:15:29 +0000771/* Keepalive send to peer. */
paul94f2b392005-06-28 12:44:16 +0000772static int
paul718e3742002-12-13 20:15:29 +0000773bgp_fsm_keepalive_expire (struct peer *peer)
774{
775 bgp_keepalive_send (peer);
776 return 0;
777}
778
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200779/* FSM error, unexpected event. This is error of BGP connection. So cut the
780 peer and change to Idle status. */
781static int
782bgp_fsm_event_error (struct peer *peer)
783{
784 plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
785 peer->host, LOOKUP (bgp_status_msg, peer->status));
786
787 return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
788}
789
paul718e3742002-12-13 20:15:29 +0000790/* Hold timer expire. This is error of BGP connection. So cut the
791 peer and change to Idle status. */
paul94f2b392005-06-28 12:44:16 +0000792static int
paul718e3742002-12-13 20:15:29 +0000793bgp_fsm_holdtime_expire (struct peer *peer)
794{
795 if (BGP_DEBUG (fsm, FSM))
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200796 plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
paul718e3742002-12-13 20:15:29 +0000797
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200798 return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
paul718e3742002-12-13 20:15:29 +0000799}
800
801/* Status goes to Established. Send keepalive packet then make first
802 update information. */
paul94f2b392005-06-28 12:44:16 +0000803static int
paul718e3742002-12-13 20:15:29 +0000804bgp_establish (struct peer *peer)
805{
806 struct bgp_notify *notify;
807 afi_t afi;
808 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000809 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000810
811 /* Reset capability open status flag. */
812 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
813 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
814
815 /* Clear last notification data. */
816 notify = &peer->notify;
817 if (notify->data)
818 XFREE (MTYPE_TMP, notify->data);
819 memset (notify, 0, sizeof (struct bgp_notify));
820
821 /* Clear start timer value to default. */
822 peer->v_start = BGP_INIT_START_TIMER;
823
824 /* Increment established count. */
825 peer->established++;
826 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000827
828 /* bgp log-neighbor-changes of neighbor Up */
829 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
830 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
831
hasso93406d82005-02-02 14:40:33 +0000832 /* graceful restart */
833 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
834 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400835 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000836 {
837 if (peer->afc_nego[afi][safi]
838 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
839 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
840 {
841 if (peer->nsf[afi][safi]
842 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
843 bgp_clear_stale_route (peer, afi, safi);
844
845 peer->nsf[afi][safi] = 1;
846 nsf_af_count++;
847 }
848 else
849 {
850 if (peer->nsf[afi][safi])
851 bgp_clear_stale_route (peer, afi, safi);
852 peer->nsf[afi][safi] = 0;
853 }
854 }
855
856 if (nsf_af_count)
857 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
858 else
859 {
860 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
861 if (peer->t_gr_stale)
862 {
863 BGP_TIMER_OFF (peer->t_gr_stale);
864 if (BGP_DEBUG (events, EVENTS))
865 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
866 }
867 }
868
869 if (peer->t_gr_restart)
870 {
871 BGP_TIMER_OFF (peer->t_gr_restart);
872 if (BGP_DEBUG (events, EVENTS))
873 zlog_debug ("%s graceful restart timer stopped", peer->host);
874 }
875
paul718e3742002-12-13 20:15:29 +0000876#ifdef HAVE_SNMP
877 bgpTrapEstablished (peer);
878#endif /* HAVE_SNMP */
879
880 /* Reset uptime, send keepalive, send current table. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300881 peer->uptime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000882
883 /* Send route-refresh when ORF is enabled */
884 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
885 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
886 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
887 {
888 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
889 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
890 REFRESH_IMMEDIATE, 0);
891 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
892 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
893 REFRESH_IMMEDIATE, 0);
894 }
895
896 if (peer->v_keepalive)
897 bgp_keepalive_send (peer);
898
899 /* First update is deferred until ORF or ROUTE-REFRESH is received */
900 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
901 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
902 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
903 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
904 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
905 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
906
907 bgp_announce_route_all (peer);
908
909 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
910
911 return 0;
912}
913
914/* Keepalive packet is received. */
paul94f2b392005-06-28 12:44:16 +0000915static int
paul718e3742002-12-13 20:15:29 +0000916bgp_fsm_keepalive (struct peer *peer)
917{
918 /* peer count update */
919 peer->keepalive_in++;
920
921 BGP_TIMER_OFF (peer->t_holdtime);
922 return 0;
923}
924
925/* Update packet is received. */
paul94f2b392005-06-28 12:44:16 +0000926static int
paul718e3742002-12-13 20:15:29 +0000927bgp_fsm_update (struct peer *peer)
928{
929 BGP_TIMER_OFF (peer->t_holdtime);
930 return 0;
931}
932
933/* This is empty event. */
paul94f2b392005-06-28 12:44:16 +0000934static int
paul718e3742002-12-13 20:15:29 +0000935bgp_ignore (struct peer *peer)
936{
937 if (BGP_DEBUG (fsm, FSM))
938 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
939 return 0;
940}
David Lamparter6b0655a2014-06-04 06:53:35 +0200941
paul718e3742002-12-13 20:15:29 +0000942/* Finite State Machine structure */
Stephen Hemmingerfda1d3e2009-05-15 10:02:27 -0700943static const struct {
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800944 int (*func) (struct peer *);
paul718e3742002-12-13 20:15:29 +0000945 int next_state;
946} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
947{
948 {
949 /* Idle state: In Idle state, all events other than BGP_Start is
950 ignored. With BGP_Start event, finite state machine calls
951 bgp_start(). */
952 {bgp_start, Connect}, /* BGP_Start */
953 {bgp_stop, Idle}, /* BGP_Stop */
954 {bgp_stop, Idle}, /* TCP_connection_open */
955 {bgp_stop, Idle}, /* TCP_connection_closed */
956 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
957 {bgp_stop, Idle}, /* TCP_fatal_error */
958 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
959 {bgp_ignore, Idle}, /* Hold_Timer_expired */
960 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
961 {bgp_ignore, Idle}, /* Receive_OPEN_message */
962 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
963 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
964 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000965 {bgp_ignore, Idle}, /* Clearing_Completed */
paul718e3742002-12-13 20:15:29 +0000966 },
967 {
968 /* Connect */
969 {bgp_ignore, Connect}, /* BGP_Start */
970 {bgp_stop, Idle}, /* BGP_Stop */
971 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
972 {bgp_stop, Idle}, /* TCP_connection_closed */
973 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
974 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
975 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
976 {bgp_ignore, Idle}, /* Hold_Timer_expired */
977 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
978 {bgp_ignore, Idle}, /* Receive_OPEN_message */
979 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
980 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
981 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000982 {bgp_ignore, Idle}, /* Clearing_Completed */
paul718e3742002-12-13 20:15:29 +0000983 },
984 {
985 /* Active, */
986 {bgp_ignore, Active}, /* BGP_Start */
987 {bgp_stop, Idle}, /* BGP_Stop */
988 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
989 {bgp_stop, Idle}, /* TCP_connection_closed */
990 {bgp_ignore, Active}, /* TCP_connection_open_failed */
991 {bgp_ignore, Idle}, /* TCP_fatal_error */
992 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
993 {bgp_ignore, Idle}, /* Hold_Timer_expired */
994 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
995 {bgp_ignore, Idle}, /* Receive_OPEN_message */
996 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
997 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
998 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000999 {bgp_ignore, Idle}, /* Clearing_Completed */
paul718e3742002-12-13 20:15:29 +00001000 },
1001 {
1002 /* OpenSent, */
1003 {bgp_ignore, OpenSent}, /* BGP_Start */
1004 {bgp_stop, Idle}, /* BGP_Stop */
Paul Jakma536792c2007-06-22 19:11:14 +00001005 {bgp_stop, Active}, /* TCP_connection_open */
paul718e3742002-12-13 20:15:29 +00001006 {bgp_stop, Active}, /* TCP_connection_closed */
Paul Jakma536792c2007-06-22 19:11:14 +00001007 {bgp_stop, Active}, /* TCP_connection_open_failed */
1008 {bgp_stop, Active}, /* TCP_fatal_error */
paul718e3742002-12-13 20:15:29 +00001009 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1010 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1011 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1012 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +02001013 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
1014 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
paul718e3742002-12-13 20:15:29 +00001015 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001016 {bgp_ignore, Idle}, /* Clearing_Completed */
paul718e3742002-12-13 20:15:29 +00001017 },
1018 {
1019 /* OpenConfirm, */
1020 {bgp_ignore, OpenConfirm}, /* BGP_Start */
1021 {bgp_stop, Idle}, /* BGP_Stop */
1022 {bgp_stop, Idle}, /* TCP_connection_open */
1023 {bgp_stop, Idle}, /* TCP_connection_closed */
1024 {bgp_stop, Idle}, /* TCP_connection_open_failed */
1025 {bgp_stop, Idle}, /* TCP_fatal_error */
1026 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1027 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1028 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
1029 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1030 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
1031 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1032 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001033 {bgp_ignore, Idle}, /* Clearing_Completed */
paul718e3742002-12-13 20:15:29 +00001034 },
1035 {
1036 /* Established, */
Paul Jakmaca058a32006-09-14 02:58:49 +00001037 {bgp_ignore, Established}, /* BGP_Start */
1038 {bgp_stop, Clearing}, /* BGP_Stop */
1039 {bgp_stop, Clearing}, /* TCP_connection_open */
1040 {bgp_stop, Clearing}, /* TCP_connection_closed */
Steve Hill3117b5c2009-07-28 17:50:00 +01001041 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
Paul Jakmaca058a32006-09-14 02:58:49 +00001042 {bgp_stop, Clearing}, /* TCP_fatal_error */
Steve Hill3117b5c2009-07-28 17:50:00 +01001043 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001044 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
paul718e3742002-12-13 20:15:29 +00001045 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001046 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1047 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
1048 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
1049 {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
1050 {bgp_ignore, Idle}, /* Clearing_Completed */
1051 },
1052 {
1053 /* Clearing, */
1054 {bgp_ignore, Clearing}, /* BGP_Start */
Steve Hill3117b5c2009-07-28 17:50:00 +01001055 {bgp_stop, Clearing}, /* BGP_Stop */
1056 {bgp_stop, Clearing}, /* TCP_connection_open */
1057 {bgp_stop, Clearing}, /* TCP_connection_closed */
1058 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1059 {bgp_stop, Clearing}, /* TCP_fatal_error */
1060 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1061 {bgp_stop, Clearing}, /* Hold_Timer_expired */
1062 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
1063 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1064 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
1065 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
1066 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
1067 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
Paul Jakmaca058a32006-09-14 02:58:49 +00001068 },
1069 {
1070 /* Deleted, */
1071 {bgp_ignore, Deleted}, /* BGP_Start */
1072 {bgp_ignore, Deleted}, /* BGP_Stop */
1073 {bgp_ignore, Deleted}, /* TCP_connection_open */
1074 {bgp_ignore, Deleted}, /* TCP_connection_closed */
1075 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
1076 {bgp_ignore, Deleted}, /* TCP_fatal_error */
1077 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
1078 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
1079 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
1080 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
1081 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
1082 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
1083 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
1084 {bgp_ignore, Deleted}, /* Clearing_Completed */
paul718e3742002-12-13 20:15:29 +00001085 },
1086};
1087
paulfd79ac92004-10-13 05:06:08 +00001088static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +00001089{
1090 NULL,
1091 "BGP_Start",
1092 "BGP_Stop",
1093 "TCP_connection_open",
1094 "TCP_connection_closed",
1095 "TCP_connection_open_failed",
1096 "TCP_fatal_error",
1097 "ConnectRetry_timer_expired",
1098 "Hold_Timer_expired",
1099 "KeepAlive_timer_expired",
1100 "Receive_OPEN_message",
1101 "Receive_KEEPALIVE_message",
1102 "Receive_UPDATE_message",
Paul Jakmaca058a32006-09-14 02:58:49 +00001103 "Receive_NOTIFICATION_message",
1104 "Clearing_Completed",
paul718e3742002-12-13 20:15:29 +00001105};
1106
1107/* Execute event process. */
1108int
1109bgp_event (struct thread *thread)
1110{
Paul Jakmaca058a32006-09-14 02:58:49 +00001111 int ret = 0;
paul718e3742002-12-13 20:15:29 +00001112 int event;
1113 int next;
1114 struct peer *peer;
1115
1116 peer = THREAD_ARG (thread);
1117 event = THREAD_VAL (thread);
1118
1119 /* Logging this event. */
1120 next = FSM [peer->status -1][event - 1].next_state;
1121
Paul Jakmaca058a32006-09-14 02:58:49 +00001122 if (BGP_DEBUG (fsm, FSM) && peer->status != next)
ajs8c2e2002004-12-08 20:08:54 +00001123 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001124 bgp_event_str[event],
1125 LOOKUP (bgp_status_msg, peer->status),
1126 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001127
1128 /* Call function. */
Paul Jakmaca058a32006-09-14 02:58:49 +00001129 if (FSM [peer->status -1][event - 1].func)
1130 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
paul718e3742002-12-13 20:15:29 +00001131
1132 /* When function do not want proceed next job return -1. */
paul200df112005-06-01 11:17:05 +00001133 if (ret >= 0)
1134 {
1135 /* If status is changed. */
1136 if (next != peer->status)
Paul Jakmaf2c31ac2007-02-22 17:48:42 +00001137 bgp_fsm_change_status (peer, next);
Paul Jakma95fdcd82006-12-08 00:31:22 +00001138
paul200df112005-06-01 11:17:05 +00001139 /* Make sure timer is set. */
1140 bgp_timer_set (peer);
1141 }
1142
paul200df112005-06-01 11:17:05 +00001143 return ret;
paul718e3742002-12-13 20:15:29 +00001144}