blob: 4198a8e42c6b19e9063f0809a21858150cd900e8 [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"
Dinesh Duttd9ab53a2015-05-19 17:47:21 -070045#include "bgpd/bgp_nht.h"
paul718e3742002-12-13 20:15:29 +000046#ifdef HAVE_SNMP
47#include "bgpd/bgp_snmp.h"
48#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020049
paul718e3742002-12-13 20:15:29 +000050/* BGP FSM (finite state machine) has three types of functions. Type
51 one is thread functions. Type two is event functions. Type three
52 is FSM functions. Timer functions are set by bgp_timer_set
53 function. */
54
55/* BGP event function. */
56int bgp_event (struct thread *);
57
58/* BGP thread functions. */
59static int bgp_start_timer (struct thread *);
60static int bgp_connect_timer (struct thread *);
61static int bgp_holdtime_timer (struct thread *);
62static int bgp_keepalive_timer (struct thread *);
63
64/* BGP FSM functions. */
65static int bgp_start (struct peer *);
66
67/* BGP start timer jitter. */
paul94f2b392005-06-28 12:44:16 +000068static int
paul718e3742002-12-13 20:15:29 +000069bgp_start_jitter (int time)
70{
Donald Sharpf31bab42015-06-19 19:26:19 -040071 return ((random () % (time + 1)) - (time / 2));
paul718e3742002-12-13 20:15:29 +000072}
73
Paul Jakmaca058a32006-09-14 02:58:49 +000074/* Check if suppress start/restart of sessions to peer. */
75#define BGP_PEER_START_SUPPRESSED(P) \
76 (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \
77 || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW))
78
paul718e3742002-12-13 20:15:29 +000079/* Hook function called after bgp event is occered. And vty's
80 neighbor command invoke this function after making neighbor
81 structure. */
82void
83bgp_timer_set (struct peer *peer)
84{
85 int jitter = 0;
86
87 switch (peer->status)
88 {
89 case Idle:
90 /* First entry point of peer's finite state machine. In Idle
91 status start timer is on unless peer is shutdown or peer is
92 inactive. All other timer must be turned off */
Paul Jakmaca058a32006-09-14 02:58:49 +000093 if (BGP_PEER_START_SUPPRESSED (peer) || ! peer_active (peer))
paul718e3742002-12-13 20:15:29 +000094 {
95 BGP_TIMER_OFF (peer->t_start);
96 }
97 else
98 {
99 jitter = bgp_start_jitter (peer->v_start);
100 BGP_TIMER_ON (peer->t_start, bgp_start_timer,
101 peer->v_start + jitter);
102 }
103 BGP_TIMER_OFF (peer->t_connect);
104 BGP_TIMER_OFF (peer->t_holdtime);
105 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000106 BGP_TIMER_OFF (peer->t_routeadv);
107 break;
108
109 case Connect:
Daniel Walton6c6c1bf2015-11-09 20:21:56 -0500110 /* After start timer is expired, the peer moves to Connect
paul718e3742002-12-13 20:15:29 +0000111 status. Make sure start timer is off and connect timer is
112 on. */
113 BGP_TIMER_OFF (peer->t_start);
114 BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
115 BGP_TIMER_OFF (peer->t_holdtime);
116 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000117 BGP_TIMER_OFF (peer->t_routeadv);
118 break;
119
120 case Active:
121 /* Active is waiting connection from remote peer. And if
122 connect timer is expired, change status to Connect. */
123 BGP_TIMER_OFF (peer->t_start);
124 /* If peer is passive mode, do not set connect timer. */
hasso93406d82005-02-02 14:40:33 +0000125 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)
126 || CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
paul718e3742002-12-13 20:15:29 +0000127 {
128 BGP_TIMER_OFF (peer->t_connect);
129 }
130 else
131 {
132 BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
133 }
134 BGP_TIMER_OFF (peer->t_holdtime);
135 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000136 BGP_TIMER_OFF (peer->t_routeadv);
137 break;
138
139 case OpenSent:
140 /* OpenSent status. */
141 BGP_TIMER_OFF (peer->t_start);
142 BGP_TIMER_OFF (peer->t_connect);
143 if (peer->v_holdtime != 0)
144 {
145 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
146 peer->v_holdtime);
147 }
148 else
149 {
150 BGP_TIMER_OFF (peer->t_holdtime);
151 }
152 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000153 BGP_TIMER_OFF (peer->t_routeadv);
154 break;
155
156 case OpenConfirm:
157 /* OpenConfirm status. */
158 BGP_TIMER_OFF (peer->t_start);
159 BGP_TIMER_OFF (peer->t_connect);
160
161 /* If the negotiated Hold Time value is zero, then the Hold Time
162 timer and KeepAlive timers are not started. */
163 if (peer->v_holdtime == 0)
164 {
165 BGP_TIMER_OFF (peer->t_holdtime);
166 BGP_TIMER_OFF (peer->t_keepalive);
167 }
168 else
169 {
170 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
171 peer->v_holdtime);
172 BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
173 peer->v_keepalive);
174 }
paul718e3742002-12-13 20:15:29 +0000175 BGP_TIMER_OFF (peer->t_routeadv);
176 break;
177
178 case Established:
179 /* In Established status start and connect timer is turned
180 off. */
181 BGP_TIMER_OFF (peer->t_start);
182 BGP_TIMER_OFF (peer->t_connect);
183
184 /* Same as OpenConfirm, if holdtime is zero then both holdtime
185 and keepalive must be turned off. */
186 if (peer->v_holdtime == 0)
187 {
188 BGP_TIMER_OFF (peer->t_holdtime);
189 BGP_TIMER_OFF (peer->t_keepalive);
190 }
191 else
192 {
193 BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
194 peer->v_holdtime);
195 BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
196 peer->v_keepalive);
197 }
paul718e3742002-12-13 20:15:29 +0000198 break;
Paul Jakmaca058a32006-09-14 02:58:49 +0000199 case Deleted:
200 BGP_TIMER_OFF (peer->t_gr_restart);
201 BGP_TIMER_OFF (peer->t_gr_stale);
202 BGP_TIMER_OFF (peer->t_pmax_restart);
203 case Clearing:
204 BGP_TIMER_OFF (peer->t_start);
205 BGP_TIMER_OFF (peer->t_connect);
206 BGP_TIMER_OFF (peer->t_holdtime);
207 BGP_TIMER_OFF (peer->t_keepalive);
Paul Jakmaca058a32006-09-14 02:58:49 +0000208 BGP_TIMER_OFF (peer->t_routeadv);
paul718e3742002-12-13 20:15:29 +0000209 }
210}
211
212/* BGP start timer. This function set BGP_Start event to thread value
213 and process event. */
214static int
215bgp_start_timer (struct thread *thread)
216{
217 struct peer *peer;
218
219 peer = THREAD_ARG (thread);
220 peer->t_start = NULL;
221
222 if (BGP_DEBUG (fsm, FSM))
223 zlog (peer->log, LOG_DEBUG,
224 "%s [FSM] Timer (start timer expire).", peer->host);
225
226 THREAD_VAL (thread) = BGP_Start;
paul200df112005-06-01 11:17:05 +0000227 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000228
229 return 0;
230}
231
232/* BGP connect retry timer. */
233static int
234bgp_connect_timer (struct thread *thread)
235{
236 struct peer *peer;
237
238 peer = THREAD_ARG (thread);
239 peer->t_connect = NULL;
240
241 if (BGP_DEBUG (fsm, FSM))
242 zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)",
243 peer->host);
244
245 THREAD_VAL (thread) = ConnectRetry_timer_expired;
paul200df112005-06-01 11:17:05 +0000246 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000247
248 return 0;
249}
250
251/* BGP holdtime timer. */
252static int
253bgp_holdtime_timer (struct thread *thread)
254{
255 struct peer *peer;
256
257 peer = THREAD_ARG (thread);
258 peer->t_holdtime = NULL;
259
260 if (BGP_DEBUG (fsm, FSM))
261 zlog (peer->log, LOG_DEBUG,
262 "%s [FSM] Timer (holdtime timer expire)",
263 peer->host);
264
265 THREAD_VAL (thread) = Hold_Timer_expired;
paul200df112005-06-01 11:17:05 +0000266 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000267
268 return 0;
269}
270
271/* BGP keepalive fire ! */
272static int
273bgp_keepalive_timer (struct thread *thread)
274{
275 struct peer *peer;
276
277 peer = THREAD_ARG (thread);
278 peer->t_keepalive = NULL;
279
280 if (BGP_DEBUG (fsm, FSM))
281 zlog (peer->log, LOG_DEBUG,
282 "%s [FSM] Timer (keepalive timer expire)",
283 peer->host);
284
285 THREAD_VAL (thread) = KeepAlive_timer_expired;
paul200df112005-06-01 11:17:05 +0000286 bgp_event (thread); /* bgp_event unlocks peer */
paul718e3742002-12-13 20:15:29 +0000287
288 return 0;
289}
290
paul94f2b392005-06-28 12:44:16 +0000291static int
paul718e3742002-12-13 20:15:29 +0000292bgp_routeadv_timer (struct thread *thread)
293{
294 struct peer *peer;
295
296 peer = THREAD_ARG (thread);
297 peer->t_routeadv = NULL;
298
299 if (BGP_DEBUG (fsm, FSM))
300 zlog (peer->log, LOG_DEBUG,
301 "%s [FSM] Timer (routeadv timer expire)",
302 peer->host);
303
Stephen Hemminger65957882010-01-15 16:22:10 +0300304 peer->synctime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000305
pauleb821182004-05-01 08:44:08 +0000306 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000307
308 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
309 peer->v_routeadv);
310
311 return 0;
312}
313
hassoe0701b72004-05-20 09:19:34 +0000314/* BGP Peer Down Cause */
paulfd79ac92004-10-13 05:06:08 +0000315const char *peer_down_str[] =
hassoe0701b72004-05-20 09:19:34 +0000316{
317 "",
318 "Router ID changed",
319 "Remote AS changed",
320 "Local AS change",
321 "Cluster ID changed",
322 "Confederation identifier changed",
323 "Confederation peer changed",
324 "RR client config change",
325 "RS client config change",
326 "Update source change",
327 "Address family activated",
328 "Admin. shutdown",
329 "User reset",
330 "BGP Notification received",
331 "BGP Notification send",
332 "Peer closed the session",
333 "Neighbor deleted",
334 "Peer-group add member",
335 "Peer-group delete member",
336 "Capability changed",
337 "Passive config change",
hasso93406d82005-02-02 14:40:33 +0000338 "Multihop config change",
339 "NSF peer closed the session"
hassoe0701b72004-05-20 09:19:34 +0000340};
341
paul94f2b392005-06-28 12:44:16 +0000342static int
hasso93406d82005-02-02 14:40:33 +0000343bgp_graceful_restart_timer_expire (struct thread *thread)
344{
345 struct peer *peer;
346 afi_t afi;
347 safi_t safi;
348
349 peer = THREAD_ARG (thread);
350 peer->t_gr_restart = NULL;
351
352 /* NSF delete stale route */
353 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400354 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000355 if (peer->nsf[afi][safi])
356 bgp_clear_stale_route (peer, afi, safi);
357
358 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
359 BGP_TIMER_OFF (peer->t_gr_stale);
360
361 if (BGP_DEBUG (events, EVENTS))
362 {
363 zlog_debug ("%s graceful restart timer expired", peer->host);
364 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
365 }
366
367 bgp_timer_set (peer);
368
369 return 0;
370}
371
paul94f2b392005-06-28 12:44:16 +0000372static int
hasso93406d82005-02-02 14:40:33 +0000373bgp_graceful_stale_timer_expire (struct thread *thread)
374{
375 struct peer *peer;
376 afi_t afi;
377 safi_t safi;
378
379 peer = THREAD_ARG (thread);
380 peer->t_gr_stale = NULL;
381
382 if (BGP_DEBUG (events, EVENTS))
383 zlog_debug ("%s graceful restart stalepath timer expired", peer->host);
384
385 /* NSF delete stale route */
386 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400387 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000388 if (peer->nsf[afi][safi])
389 bgp_clear_stale_route (peer, afi, safi);
390
391 return 0;
392}
393
paul200df112005-06-01 11:17:05 +0000394/* Called after event occured, this function change status and reset
395 read/write and timer thread. */
396void
397bgp_fsm_change_status (struct peer *peer, int status)
398{
399 bgp_dump_state (peer, peer->status, status);
400
Paul Jakmaf2c31ac2007-02-22 17:48:42 +0000401 /* Transition into Clearing or Deleted must /always/ clear all routes..
402 * (and must do so before actually changing into Deleted..
403 */
404 if (status >= Clearing)
Donald Sharp7ef42212015-03-30 06:32:52 -0700405 {
406 bgp_clear_route_all (peer);
407
408 /* If no route was queued for the clear-node processing, generate the
409 * completion event here. This is needed because if there are no routes
410 * to trigger the background clear-node thread, the event won't get
411 * generated and the peer would be stuck in Clearing. Note that this
412 * event is for the peer and helps the peer transition out of Clearing
413 * state; it should not be generated per (AFI,SAFI). The event is
414 * directly posted here without calling clear_node_complete() as we
415 * shouldn't do an extra unlock. This event will get processed after
416 * the state change that happens below, so peer will be in Clearing
417 * (or Deleted).
418 */
Paul Jakma782fb072015-09-15 16:17:22 +0100419 if (!work_queue_is_scheduled (peer->clear_node_queue))
Donald Sharp7ef42212015-03-30 06:32:52 -0700420 BGP_EVENT_ADD (peer, Clearing_Completed);
421 }
Paul Jakmaf2c31ac2007-02-22 17:48:42 +0000422
paul200df112005-06-01 11:17:05 +0000423 /* Preserve old status and change into new status. */
424 peer->ostatus = peer->status;
425 peer->status = status;
Paul Jakmaf2c31ac2007-02-22 17:48:42 +0000426
paul200df112005-06-01 11:17:05 +0000427 if (BGP_DEBUG (normal, NORMAL))
428 zlog_debug ("%s went from %s to %s",
429 peer->host,
430 LOOKUP (bgp_status_msg, peer->ostatus),
431 LOOKUP (bgp_status_msg, peer->status));
432}
433
Steve Hill3117b5c2009-07-28 17:50:00 +0100434/* Flush the event queue and ensure the peer is shut down */
Stephen Hemminger9e4ca892009-12-10 11:57:05 +0300435static int
Steve Hill3117b5c2009-07-28 17:50:00 +0100436bgp_clearing_completed (struct peer *peer)
437{
438 int rc = bgp_stop(peer);
439 BGP_EVENT_FLUSH (peer);
440
441 return rc;
442}
443
paul718e3742002-12-13 20:15:29 +0000444/* Administrative BGP peer stop event. */
Steve Hill3117b5c2009-07-28 17:50:00 +0100445/* May be called multiple times for the same peer */
paul718e3742002-12-13 20:15:29 +0000446int
447bgp_stop (struct peer *peer)
448{
paul718e3742002-12-13 20:15:29 +0000449 afi_t afi;
450 safi_t safi;
451 char orf_name[BUFSIZ];
452
Steve Hill3117b5c2009-07-28 17:50:00 +0100453 /* Can't do this in Clearing; events are used for state transitions */
454 if (peer->status != Clearing)
Paul Jakma2158ad22009-07-28 18:10:55 +0100455 {
456 /* Delete all existing events of the peer */
457 BGP_EVENT_FLUSH (peer);
458 }
Paul Jakmadcdf3992006-10-15 23:39:59 +0000459
paul718e3742002-12-13 20:15:29 +0000460 /* Increment Dropped count. */
461 if (peer->status == Established)
462 {
paul718e3742002-12-13 20:15:29 +0000463 peer->dropped++;
paul848973c2003-08-13 00:32:49 +0000464
465 /* bgp log-neighbor-changes of neighbor Down */
466 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
hassoe0701b72004-05-20 09:19:34 +0000467 zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
468 peer_down_str [(int) peer->last_reset]);
paul848973c2003-08-13 00:32:49 +0000469
hasso93406d82005-02-02 14:40:33 +0000470 /* graceful restart */
471 if (peer->t_gr_stale)
472 {
473 BGP_TIMER_OFF (peer->t_gr_stale);
474 if (BGP_DEBUG (events, EVENTS))
475 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
476 }
477 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
478 {
479 if (BGP_DEBUG (events, EVENTS))
480 {
481 zlog_debug ("%s graceful restart timer started for %d sec",
482 peer->host, peer->v_gr_restart);
483 zlog_debug ("%s graceful restart stalepath timer started for %d sec",
484 peer->host, peer->bgp->stalepath_time);
485 }
486 BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
487 peer->v_gr_restart);
488 BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
489 peer->bgp->stalepath_time);
490 }
491 else
492 {
493 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
494
495 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400496 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000497 peer->nsf[afi][safi] = 0;
498 }
499
paul848973c2003-08-13 00:32:49 +0000500 /* set last reset time */
Stephen Hemminger65957882010-01-15 16:22:10 +0300501 peer->resettime = peer->uptime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000502
paul718e3742002-12-13 20:15:29 +0000503#ifdef HAVE_SNMP
504 bgpTrapBackwardTransition (peer);
505#endif /* HAVE_SNMP */
paul718e3742002-12-13 20:15:29 +0000506
hassof4184462005-02-01 20:13:16 +0000507 /* Reset peer synctime */
508 peer->synctime = 0;
hasso538621f2004-05-21 09:31:30 +0000509 }
Paul Jakma3dda6b32016-09-06 16:57:40 +0100510
paul718e3742002-12-13 20:15:29 +0000511 /* Stop read and write threads when exists. */
512 BGP_READ_OFF (peer->t_read);
513 BGP_WRITE_OFF (peer->t_write);
514
515 /* Stop all timers. */
516 BGP_TIMER_OFF (peer->t_start);
517 BGP_TIMER_OFF (peer->t_connect);
518 BGP_TIMER_OFF (peer->t_holdtime);
519 BGP_TIMER_OFF (peer->t_keepalive);
paul718e3742002-12-13 20:15:29 +0000520 BGP_TIMER_OFF (peer->t_routeadv);
521
paul718e3742002-12-13 20:15:29 +0000522 /* Stream reset. */
523 peer->packet_size = 0;
524
525 /* Clear input and output buffer. */
526 if (peer->ibuf)
527 stream_reset (peer->ibuf);
528 if (peer->work)
529 stream_reset (peer->work);
paul200df112005-06-01 11:17:05 +0000530 if (peer->obuf)
531 stream_fifo_clean (peer->obuf);
paul718e3742002-12-13 20:15:29 +0000532
pauleb821182004-05-01 08:44:08 +0000533 /* Close of file descriptor. */
534 if (peer->fd >= 0)
535 {
536 close (peer->fd);
537 peer->fd = -1;
538 }
paul718e3742002-12-13 20:15:29 +0000539
paul718e3742002-12-13 20:15:29 +0000540 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
541 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
542 {
hasso538621f2004-05-21 09:31:30 +0000543 /* Reset all negotiated variables */
544 peer->afc_nego[afi][safi] = 0;
545 peer->afc_adv[afi][safi] = 0;
546 peer->afc_recv[afi][safi] = 0;
547
paul718e3742002-12-13 20:15:29 +0000548 /* peer address family capability flags*/
549 peer->af_cap[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000550
paul718e3742002-12-13 20:15:29 +0000551 /* peer address family status flags*/
552 peer->af_sflags[afi][safi] = 0;
hasso538621f2004-05-21 09:31:30 +0000553
paul718e3742002-12-13 20:15:29 +0000554 /* Received ORF prefix-filter */
555 peer->orf_plist[afi][safi] = NULL;
hasso538621f2004-05-21 09:31:30 +0000556
paul718e3742002-12-13 20:15:29 +0000557 /* ORF received prefix-filter pnt */
558 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200559 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000560 }
561
562 /* Reset keepalive and holdtime */
563 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
564 {
565 peer->v_keepalive = peer->keepalive;
566 peer->v_holdtime = peer->holdtime;
567 }
568 else
569 {
570 peer->v_keepalive = peer->bgp->default_keepalive;
571 peer->v_holdtime = peer->bgp->default_holdtime;
572 }
573
574 peer->update_time = 0;
575
576 /* Until we are sure that there is no problem about prefix count
577 this should be commented out.*/
578#if 0
579 /* Reset prefix count */
580 peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
581 peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
582 peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
583 peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
584 peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
585#endif /* 0 */
586
587 return 0;
588}
589
Paul Jakmab8f8ba12016-09-28 16:54:48 +0100590/* first-val * 2**x back-off, where x is the number of sucessive calls
591 * originally used for peer v_start back-off
592 */
593__attribute__((unused))
594static int
595back_off_exp2 (const int first, int val, const int max)
596{
597 val <<= 1;
598 return (val < max ? val : max);
599}
600
601/* exponential back off, but biased downward by the initial value.
602 * this bias is significant at lower values, and tends to
603 * insignificance fairly quickly, so it is equal to the previous at
604 * scale. Is below first-val * 1.7**x at x == 6, and below first-val
605 * * 1.75**x at x=10.
606 *
607 * I.e., this function is useful to get slower growth for the initial
608 * points of x.
609 */
610__attribute__((unused))
611static int
612back_off_exp2_bias (const int first, int val, const int max)
613{
614 val = (val << 1) - (val > first ? first : 0);
615 return (val < max ? val : max);
616}
617
paul718e3742002-12-13 20:15:29 +0000618/* BGP peer is stoped by the error. */
paul94f2b392005-06-28 12:44:16 +0000619static int
paul718e3742002-12-13 20:15:29 +0000620bgp_stop_with_error (struct peer *peer)
621{
Paul Jakmab8f8ba12016-09-28 16:54:48 +0100622 peer->v_start
623 = back_off_exp2_bias (BGP_INIT_START_TIMER, peer->v_start, 60);
paul718e3742002-12-13 20:15:29 +0000624 bgp_stop (peer);
paul718e3742002-12-13 20:15:29 +0000625 return 0;
626}
627
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200628
629/* something went wrong, send notify and tear down */
630static int
631bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code)
632{
633 /* Send notify to remote peer */
634 bgp_notify_send (peer, code, sub_code);
635
636 /* Sweep if it is temporary peer. */
637 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
638 {
639 zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
640 peer_delete (peer);
641 return -1;
642 }
643
644 /* Clear start timer value to default. */
645 peer->v_start = BGP_INIT_START_TIMER;
646
647 /* bgp_stop needs to be invoked while in Established state */
648 bgp_stop(peer);
649
650 return 0;
651}
652
653
paul718e3742002-12-13 20:15:29 +0000654/* TCP connection open. Next we send open message to remote peer. And
655 add read thread for reading open message. */
paul94f2b392005-06-28 12:44:16 +0000656static int
paul718e3742002-12-13 20:15:29 +0000657bgp_connect_success (struct peer *peer)
658{
Paul Jakmad023f9f2016-09-16 15:13:43 +0100659 struct peer *realpeer;
660
pauleb821182004-05-01 08:44:08 +0000661 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000662 {
663 zlog_err ("bgp_connect_success peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000664 peer->fd);
paul718e3742002-12-13 20:15:29 +0000665 return -1;
666 }
pauleb821182004-05-01 08:44:08 +0000667 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +0000668
hassof4184462005-02-01 20:13:16 +0000669 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
670 bgp_getsockname (peer);
671
672 if (BGP_DEBUG (normal, NORMAL))
673 {
Jorge Boncompte [DTI2]682ca042012-04-10 16:57:27 +0200674 char buf1[SU_ADDRSTRLEN];
675
hassof4184462005-02-01 20:13:16 +0000676 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
677 zlog_debug ("%s open active, local address %s", peer->host,
678 sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
679 else
680 zlog_debug ("%s passive open", peer->host);
681 }
Paul Jakmad023f9f2016-09-16 15:13:43 +0100682
683 /* Generally we want to send OPEN ASAP. Except, some partial BGP
684 * implementations out there (e.g., conformance test tools / BGP
685 * traffic generators) seem to be a bit funny about connection collisions,
686 * and OPENs before they have sent.
687 *
688 * As a hack, delay sending OPEN on an inbound accept-peer session
689 * _IF_ we locally have an outbound connection in progress, i.e.
690 * we're in middle of a connection collision. If we delay, we delay until
691 * an Open is received - as per old Quagga behaviour.
692 */
693 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
694 {
695 realpeer = peer_lookup (peer->bgp, &peer->su);
696
697 if (realpeer->status > Idle && realpeer->status <= Established)
698 {
699 SET_FLAG (peer->sflags, PEER_STATUS_OPEN_DEFERRED);
700 return 0;
701 }
702 }
703
Paul Jakma2d81a7a2016-04-20 14:05:20 +0100704 bgp_open_send (peer);
paul718e3742002-12-13 20:15:29 +0000705
706 return 0;
707}
708
709/* TCP connect fail */
paul94f2b392005-06-28 12:44:16 +0000710static int
paul718e3742002-12-13 20:15:29 +0000711bgp_connect_fail (struct peer *peer)
712{
713 bgp_stop (peer);
714 return 0;
715}
716
717/* This function is the first starting point of all BGP connection. It
718 try to connect to remote peer with non-blocking IO. */
719int
720bgp_start (struct peer *peer)
721{
722 int status;
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700723 int connected = 0;
paul718e3742002-12-13 20:15:29 +0000724
Paul Jakmaca058a32006-09-14 02:58:49 +0000725 if (BGP_PEER_START_SUPPRESSED (peer))
726 {
727 if (BGP_DEBUG (fsm, FSM))
728 plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
729 " - this is never supposed to happen!", peer->host);
730 return -1;
731 }
732
Paul Jakma33d5ab92006-07-02 11:01:50 +0000733 /* Scrub some information that might be left over from a previous,
734 * session
735 */
736 /* Connection information. */
737 if (peer->su_local)
738 {
739 sockunion_free (peer->su_local);
740 peer->su_local = NULL;
741 }
742
743 if (peer->su_remote)
744 {
745 sockunion_free (peer->su_remote);
746 peer->su_remote = NULL;
747 }
748
749 /* Clear remote router-id. */
750 peer->remote_id.s_addr = 0;
751
752 /* Clear peer capability flag. */
753 peer->cap = 0;
754
paul718e3742002-12-13 20:15:29 +0000755 /* If the peer is passive mode, force to move to Active mode. */
756 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
757 {
758 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
759 return 0;
760 }
761
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700762 /* Register to be notified on peer up */
Timo Teräse3443a22016-10-19 16:02:34 +0300763 if ((peer_ttl(peer) == 1 || peer->gtsm_hops == 1) &&
Timo Teräsc9cc52a2016-10-19 16:02:33 +0300764 ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700765 connected = 1;
766
Paul Jakma3dda6b32016-09-06 16:57:40 +0100767 bgp_ensure_nexthop (NULL, peer, connected);
paul718e3742002-12-13 20:15:29 +0000768 status = bgp_connect (peer);
769
770 switch (status)
771 {
772 case connect_error:
773 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000774 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000775 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
776 break;
777 case connect_success:
778 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000779 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000780 peer->host);
paul718e3742002-12-13 20:15:29 +0000781 BGP_EVENT_ADD (peer, TCP_connection_open);
782 break;
783 case connect_in_progress:
784 /* To check nonblocking connect, we wait until socket is
785 readable or writable. */
786 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000787 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000788 peer->host);
789 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000790 {
791 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000792 peer->fd);
paul718e3742002-12-13 20:15:29 +0000793 return -1;
794 }
pauleb821182004-05-01 08:44:08 +0000795 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
796 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000797 break;
798 }
799 return 0;
800}
801
802/* Connect retry timer is expired when the peer status is Connect. */
paul94f2b392005-06-28 12:44:16 +0000803static int
paul718e3742002-12-13 20:15:29 +0000804bgp_reconnect (struct peer *peer)
805{
806 bgp_stop (peer);
807 bgp_start (peer);
808 return 0;
809}
810
paul94f2b392005-06-28 12:44:16 +0000811static int
paul718e3742002-12-13 20:15:29 +0000812bgp_fsm_open (struct peer *peer)
813{
814 /* Send keepalive and make keepalive timer */
815 bgp_keepalive_send (peer);
816
817 /* Reset holdtimer value. */
818 BGP_TIMER_OFF (peer->t_holdtime);
819
820 return 0;
821}
822
paul718e3742002-12-13 20:15:29 +0000823/* Keepalive send to peer. */
paul94f2b392005-06-28 12:44:16 +0000824static int
paul718e3742002-12-13 20:15:29 +0000825bgp_fsm_keepalive_expire (struct peer *peer)
826{
827 bgp_keepalive_send (peer);
828 return 0;
829}
830
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200831/* FSM error, unexpected event. This is error of BGP connection. So cut the
832 peer and change to Idle status. */
833static int
834bgp_fsm_event_error (struct peer *peer)
835{
836 plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
837 peer->host, LOOKUP (bgp_status_msg, peer->status));
838
839 return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
840}
841
paul718e3742002-12-13 20:15:29 +0000842/* Hold timer expire. This is error of BGP connection. So cut the
843 peer and change to Idle status. */
paul94f2b392005-06-28 12:44:16 +0000844static int
paul718e3742002-12-13 20:15:29 +0000845bgp_fsm_holdtime_expire (struct peer *peer)
846{
847 if (BGP_DEBUG (fsm, FSM))
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200848 plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
paul718e3742002-12-13 20:15:29 +0000849
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200850 return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
paul718e3742002-12-13 20:15:29 +0000851}
852
853/* Status goes to Established. Send keepalive packet then make first
854 update information. */
paul94f2b392005-06-28 12:44:16 +0000855static int
paul718e3742002-12-13 20:15:29 +0000856bgp_establish (struct peer *peer)
857{
858 struct bgp_notify *notify;
859 afi_t afi;
860 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000861 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000862
863 /* Reset capability open status flag. */
864 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
865 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
866
867 /* Clear last notification data. */
868 notify = &peer->notify;
869 if (notify->data)
870 XFREE (MTYPE_TMP, notify->data);
871 memset (notify, 0, sizeof (struct bgp_notify));
872
873 /* Clear start timer value to default. */
874 peer->v_start = BGP_INIT_START_TIMER;
875
876 /* Increment established count. */
877 peer->established++;
878 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000879
880 /* bgp log-neighbor-changes of neighbor Up */
881 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
882 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
883
hasso93406d82005-02-02 14:40:33 +0000884 /* graceful restart */
885 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
886 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400887 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000888 {
889 if (peer->afc_nego[afi][safi]
890 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
891 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
892 {
893 if (peer->nsf[afi][safi]
894 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
895 bgp_clear_stale_route (peer, afi, safi);
896
897 peer->nsf[afi][safi] = 1;
898 nsf_af_count++;
899 }
900 else
901 {
902 if (peer->nsf[afi][safi])
903 bgp_clear_stale_route (peer, afi, safi);
904 peer->nsf[afi][safi] = 0;
905 }
906 }
907
908 if (nsf_af_count)
909 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
910 else
911 {
912 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
913 if (peer->t_gr_stale)
914 {
915 BGP_TIMER_OFF (peer->t_gr_stale);
916 if (BGP_DEBUG (events, EVENTS))
917 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
918 }
919 }
920
921 if (peer->t_gr_restart)
922 {
923 BGP_TIMER_OFF (peer->t_gr_restart);
924 if (BGP_DEBUG (events, EVENTS))
925 zlog_debug ("%s graceful restart timer stopped", peer->host);
926 }
927
paul718e3742002-12-13 20:15:29 +0000928#ifdef HAVE_SNMP
929 bgpTrapEstablished (peer);
930#endif /* HAVE_SNMP */
931
932 /* Reset uptime, send keepalive, send current table. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300933 peer->uptime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000934
935 /* Send route-refresh when ORF is enabled */
936 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
937 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
938 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
939 {
940 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
941 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
942 REFRESH_IMMEDIATE, 0);
943 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
944 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
945 REFRESH_IMMEDIATE, 0);
946 }
947
948 if (peer->v_keepalive)
949 bgp_keepalive_send (peer);
950
951 /* First update is deferred until ORF or ROUTE-REFRESH is received */
952 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
953 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
954 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
955 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
956 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
957 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
958
959 bgp_announce_route_all (peer);
960
961 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
962
963 return 0;
964}
965
966/* Keepalive packet is received. */
paul94f2b392005-06-28 12:44:16 +0000967static int
paul718e3742002-12-13 20:15:29 +0000968bgp_fsm_keepalive (struct peer *peer)
969{
970 /* peer count update */
971 peer->keepalive_in++;
972
973 BGP_TIMER_OFF (peer->t_holdtime);
974 return 0;
975}
976
977/* Update packet is received. */
paul94f2b392005-06-28 12:44:16 +0000978static int
paul718e3742002-12-13 20:15:29 +0000979bgp_fsm_update (struct peer *peer)
980{
981 BGP_TIMER_OFF (peer->t_holdtime);
982 return 0;
983}
984
985/* This is empty event. */
paul94f2b392005-06-28 12:44:16 +0000986static int
paul718e3742002-12-13 20:15:29 +0000987bgp_ignore (struct peer *peer)
988{
989 if (BGP_DEBUG (fsm, FSM))
990 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
991 return 0;
992}
David Lamparter6b0655a2014-06-04 06:53:35 +0200993
paul718e3742002-12-13 20:15:29 +0000994/* Finite State Machine structure */
Stephen Hemmingerfda1d3e2009-05-15 10:02:27 -0700995static const struct {
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800996 int (*func) (struct peer *);
paul718e3742002-12-13 20:15:29 +0000997 int next_state;
998} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
999{
1000 {
1001 /* Idle state: In Idle state, all events other than BGP_Start is
1002 ignored. With BGP_Start event, finite state machine calls
1003 bgp_start(). */
1004 {bgp_start, Connect}, /* BGP_Start */
1005 {bgp_stop, Idle}, /* BGP_Stop */
1006 {bgp_stop, Idle}, /* TCP_connection_open */
1007 {bgp_stop, Idle}, /* TCP_connection_closed */
1008 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
1009 {bgp_stop, Idle}, /* TCP_fatal_error */
1010 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1011 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1012 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1013 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1014 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1015 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1016 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001017 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001018 {bgp_ignore, Idle}, /* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001019 },
1020 {
1021 /* Connect */
1022 {bgp_ignore, Connect}, /* BGP_Start */
1023 {bgp_stop, Idle}, /* BGP_Stop */
1024 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1025 {bgp_stop, Idle}, /* TCP_connection_closed */
1026 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
1027 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
1028 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
1029 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1030 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1031 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1032 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1033 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1034 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001035 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001036 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001037 },
1038 {
1039 /* Active, */
1040 {bgp_ignore, Active}, /* BGP_Start */
1041 {bgp_stop, Idle}, /* BGP_Stop */
1042 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1043 {bgp_stop, Idle}, /* TCP_connection_closed */
1044 {bgp_ignore, Active}, /* TCP_connection_open_failed */
1045 {bgp_ignore, Idle}, /* TCP_fatal_error */
1046 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
1047 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1048 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1049 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1050 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1051 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1052 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001053 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001054 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001055 },
1056 {
1057 /* OpenSent, */
1058 {bgp_ignore, OpenSent}, /* BGP_Start */
1059 {bgp_stop, Idle}, /* BGP_Stop */
Paul Jakma536792c2007-06-22 19:11:14 +00001060 {bgp_stop, Active}, /* TCP_connection_open */
paul718e3742002-12-13 20:15:29 +00001061 {bgp_stop, Active}, /* TCP_connection_closed */
Paul Jakma536792c2007-06-22 19:11:14 +00001062 {bgp_stop, Active}, /* TCP_connection_open_failed */
1063 {bgp_stop, Active}, /* TCP_fatal_error */
paul718e3742002-12-13 20:15:29 +00001064 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1065 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1066 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1067 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +02001068 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
1069 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
paul718e3742002-12-13 20:15:29 +00001070 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001071 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001072 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001073 },
1074 {
1075 /* OpenConfirm, */
1076 {bgp_ignore, OpenConfirm}, /* BGP_Start */
1077 {bgp_stop, Idle}, /* BGP_Stop */
1078 {bgp_stop, Idle}, /* TCP_connection_open */
1079 {bgp_stop, Idle}, /* TCP_connection_closed */
1080 {bgp_stop, Idle}, /* TCP_connection_open_failed */
1081 {bgp_stop, Idle}, /* TCP_fatal_error */
1082 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1083 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1084 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
1085 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1086 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
1087 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1088 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001089 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001090 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001091 },
1092 {
1093 /* Established, */
Paul Jakmaca058a32006-09-14 02:58:49 +00001094 {bgp_ignore, Established}, /* BGP_Start */
1095 {bgp_stop, Clearing}, /* BGP_Stop */
1096 {bgp_stop, Clearing}, /* TCP_connection_open */
1097 {bgp_stop, Clearing}, /* TCP_connection_closed */
Steve Hill3117b5c2009-07-28 17:50:00 +01001098 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
Paul Jakmaca058a32006-09-14 02:58:49 +00001099 {bgp_stop, Clearing}, /* TCP_fatal_error */
Steve Hill3117b5c2009-07-28 17:50:00 +01001100 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001101 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
paul718e3742002-12-13 20:15:29 +00001102 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001103 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1104 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
1105 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
1106 {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
1107 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001108 {bgp_stop_with_error, Clearing}, /* BGP_Stop_with_error */
Paul Jakmaca058a32006-09-14 02:58:49 +00001109 },
1110 {
1111 /* Clearing, */
1112 {bgp_ignore, Clearing}, /* BGP_Start */
Steve Hill3117b5c2009-07-28 17:50:00 +01001113 {bgp_stop, Clearing}, /* BGP_Stop */
1114 {bgp_stop, Clearing}, /* TCP_connection_open */
1115 {bgp_stop, Clearing}, /* TCP_connection_closed */
1116 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1117 {bgp_stop, Clearing}, /* TCP_fatal_error */
1118 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1119 {bgp_stop, Clearing}, /* Hold_Timer_expired */
1120 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
1121 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1122 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
1123 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
1124 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
1125 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001126 {bgp_stop_with_error, Clearing}, /* BGP_Stop_with_error */
Paul Jakmaca058a32006-09-14 02:58:49 +00001127 },
1128 {
1129 /* Deleted, */
1130 {bgp_ignore, Deleted}, /* BGP_Start */
1131 {bgp_ignore, Deleted}, /* BGP_Stop */
1132 {bgp_ignore, Deleted}, /* TCP_connection_open */
1133 {bgp_ignore, Deleted}, /* TCP_connection_closed */
1134 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
1135 {bgp_ignore, Deleted}, /* TCP_fatal_error */
1136 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
1137 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
1138 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
1139 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
1140 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
1141 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
1142 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
1143 {bgp_ignore, Deleted}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001144 {bgp_ignore, Deleted}, /* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001145 },
1146};
1147
paulfd79ac92004-10-13 05:06:08 +00001148static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +00001149{
1150 NULL,
1151 "BGP_Start",
1152 "BGP_Stop",
1153 "TCP_connection_open",
1154 "TCP_connection_closed",
1155 "TCP_connection_open_failed",
1156 "TCP_fatal_error",
1157 "ConnectRetry_timer_expired",
1158 "Hold_Timer_expired",
1159 "KeepAlive_timer_expired",
1160 "Receive_OPEN_message",
1161 "Receive_KEEPALIVE_message",
1162 "Receive_UPDATE_message",
Paul Jakmaca058a32006-09-14 02:58:49 +00001163 "Receive_NOTIFICATION_message",
1164 "Clearing_Completed",
Paul Jakmab1b15792016-09-21 18:50:23 +01001165 "BGP_Stop_with_error",
paul718e3742002-12-13 20:15:29 +00001166};
1167
1168/* Execute event process. */
1169int
1170bgp_event (struct thread *thread)
1171{
Paul Jakmaca058a32006-09-14 02:58:49 +00001172 int ret = 0;
paul718e3742002-12-13 20:15:29 +00001173 int event;
1174 int next;
1175 struct peer *peer;
1176
1177 peer = THREAD_ARG (thread);
1178 event = THREAD_VAL (thread);
1179
1180 /* Logging this event. */
1181 next = FSM [peer->status -1][event - 1].next_state;
1182
Paul Jakmaca058a32006-09-14 02:58:49 +00001183 if (BGP_DEBUG (fsm, FSM) && peer->status != next)
ajs8c2e2002004-12-08 20:08:54 +00001184 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001185 bgp_event_str[event],
1186 LOOKUP (bgp_status_msg, peer->status),
1187 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001188
1189 /* Call function. */
Paul Jakmaca058a32006-09-14 02:58:49 +00001190 if (FSM [peer->status -1][event - 1].func)
1191 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
paul718e3742002-12-13 20:15:29 +00001192
1193 /* When function do not want proceed next job return -1. */
paul200df112005-06-01 11:17:05 +00001194 if (ret >= 0)
1195 {
1196 /* If status is changed. */
1197 if (next != peer->status)
Paul Jakmaf2c31ac2007-02-22 17:48:42 +00001198 bgp_fsm_change_status (peer, next);
Paul Jakma95fdcd82006-12-08 00:31:22 +00001199
paul200df112005-06-01 11:17:05 +00001200 /* Make sure timer is set. */
1201 bgp_timer_set (peer);
1202 }
1203
paul200df112005-06-01 11:17:05 +00001204 return ret;
paul718e3742002-12-13 20:15:29 +00001205}