blob: 84fddeb9bf62847af6d5b5f98f867f16285915e8 [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{
pauleb821182004-05-01 08:44:08 +0000659 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000660 {
661 zlog_err ("bgp_connect_success peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000662 peer->fd);
paul718e3742002-12-13 20:15:29 +0000663 return -1;
664 }
pauleb821182004-05-01 08:44:08 +0000665 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +0000666
hassof4184462005-02-01 20:13:16 +0000667 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
668 bgp_getsockname (peer);
669
670 if (BGP_DEBUG (normal, NORMAL))
671 {
Jorge Boncompte [DTI2]682ca042012-04-10 16:57:27 +0200672 char buf1[SU_ADDRSTRLEN];
673
hassof4184462005-02-01 20:13:16 +0000674 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
675 zlog_debug ("%s open active, local address %s", peer->host,
676 sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
677 else
678 zlog_debug ("%s passive open", peer->host);
679 }
paul718e3742002-12-13 20:15:29 +0000680
Paul Jakma2d81a7a2016-04-20 14:05:20 +0100681 bgp_open_send (peer);
paul718e3742002-12-13 20:15:29 +0000682
683 return 0;
684}
685
686/* TCP connect fail */
paul94f2b392005-06-28 12:44:16 +0000687static int
paul718e3742002-12-13 20:15:29 +0000688bgp_connect_fail (struct peer *peer)
689{
690 bgp_stop (peer);
691 return 0;
692}
693
694/* This function is the first starting point of all BGP connection. It
695 try to connect to remote peer with non-blocking IO. */
696int
697bgp_start (struct peer *peer)
698{
699 int status;
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700700 int connected = 0;
paul718e3742002-12-13 20:15:29 +0000701
Paul Jakmaca058a32006-09-14 02:58:49 +0000702 if (BGP_PEER_START_SUPPRESSED (peer))
703 {
704 if (BGP_DEBUG (fsm, FSM))
705 plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
706 " - this is never supposed to happen!", peer->host);
707 return -1;
708 }
709
Paul Jakma33d5ab92006-07-02 11:01:50 +0000710 /* Scrub some information that might be left over from a previous,
711 * session
712 */
713 /* Connection information. */
714 if (peer->su_local)
715 {
716 sockunion_free (peer->su_local);
717 peer->su_local = NULL;
718 }
719
720 if (peer->su_remote)
721 {
722 sockunion_free (peer->su_remote);
723 peer->su_remote = NULL;
724 }
725
726 /* Clear remote router-id. */
727 peer->remote_id.s_addr = 0;
728
729 /* Clear peer capability flag. */
730 peer->cap = 0;
731
paul718e3742002-12-13 20:15:29 +0000732 /* If the peer is passive mode, force to move to Active mode. */
733 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
734 {
735 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
736 return 0;
737 }
738
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700739 /* Register to be notified on peer up */
Timo Teräse3443a22016-10-19 16:02:34 +0300740 if ((peer_ttl(peer) == 1 || peer->gtsm_hops == 1) &&
Timo Teräsc9cc52a2016-10-19 16:02:33 +0300741 ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700742 connected = 1;
743
Paul Jakma3dda6b32016-09-06 16:57:40 +0100744 bgp_ensure_nexthop (NULL, peer, connected);
paul718e3742002-12-13 20:15:29 +0000745 status = bgp_connect (peer);
746
747 switch (status)
748 {
749 case connect_error:
750 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000751 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000752 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
753 break;
754 case connect_success:
755 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000756 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000757 peer->host);
paul718e3742002-12-13 20:15:29 +0000758 BGP_EVENT_ADD (peer, TCP_connection_open);
759 break;
760 case connect_in_progress:
761 /* To check nonblocking connect, we wait until socket is
762 readable or writable. */
763 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000764 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000765 peer->host);
766 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000767 {
768 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000769 peer->fd);
paul718e3742002-12-13 20:15:29 +0000770 return -1;
771 }
pauleb821182004-05-01 08:44:08 +0000772 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
773 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000774 break;
775 }
776 return 0;
777}
778
779/* Connect retry timer is expired when the peer status is Connect. */
paul94f2b392005-06-28 12:44:16 +0000780static int
paul718e3742002-12-13 20:15:29 +0000781bgp_reconnect (struct peer *peer)
782{
783 bgp_stop (peer);
784 bgp_start (peer);
785 return 0;
786}
787
paul94f2b392005-06-28 12:44:16 +0000788static int
paul718e3742002-12-13 20:15:29 +0000789bgp_fsm_open (struct peer *peer)
790{
791 /* Send keepalive and make keepalive timer */
792 bgp_keepalive_send (peer);
793
794 /* Reset holdtimer value. */
795 BGP_TIMER_OFF (peer->t_holdtime);
796
797 return 0;
798}
799
paul718e3742002-12-13 20:15:29 +0000800/* Keepalive send to peer. */
paul94f2b392005-06-28 12:44:16 +0000801static int
paul718e3742002-12-13 20:15:29 +0000802bgp_fsm_keepalive_expire (struct peer *peer)
803{
804 bgp_keepalive_send (peer);
805 return 0;
806}
807
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200808/* FSM error, unexpected event. This is error of BGP connection. So cut the
809 peer and change to Idle status. */
810static int
811bgp_fsm_event_error (struct peer *peer)
812{
813 plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
814 peer->host, LOOKUP (bgp_status_msg, peer->status));
815
816 return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
817}
818
paul718e3742002-12-13 20:15:29 +0000819/* Hold timer expire. This is error of BGP connection. So cut the
820 peer and change to Idle status. */
paul94f2b392005-06-28 12:44:16 +0000821static int
paul718e3742002-12-13 20:15:29 +0000822bgp_fsm_holdtime_expire (struct peer *peer)
823{
824 if (BGP_DEBUG (fsm, FSM))
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200825 plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
paul718e3742002-12-13 20:15:29 +0000826
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200827 return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
paul718e3742002-12-13 20:15:29 +0000828}
829
830/* Status goes to Established. Send keepalive packet then make first
831 update information. */
paul94f2b392005-06-28 12:44:16 +0000832static int
paul718e3742002-12-13 20:15:29 +0000833bgp_establish (struct peer *peer)
834{
835 struct bgp_notify *notify;
836 afi_t afi;
837 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000838 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000839
840 /* Reset capability open status flag. */
841 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
842 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
843
844 /* Clear last notification data. */
845 notify = &peer->notify;
846 if (notify->data)
847 XFREE (MTYPE_TMP, notify->data);
848 memset (notify, 0, sizeof (struct bgp_notify));
849
850 /* Clear start timer value to default. */
851 peer->v_start = BGP_INIT_START_TIMER;
852
853 /* Increment established count. */
854 peer->established++;
855 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000856
857 /* bgp log-neighbor-changes of neighbor Up */
858 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
859 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
860
hasso93406d82005-02-02 14:40:33 +0000861 /* graceful restart */
862 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
863 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400864 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000865 {
866 if (peer->afc_nego[afi][safi]
867 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
868 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
869 {
870 if (peer->nsf[afi][safi]
871 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
872 bgp_clear_stale_route (peer, afi, safi);
873
874 peer->nsf[afi][safi] = 1;
875 nsf_af_count++;
876 }
877 else
878 {
879 if (peer->nsf[afi][safi])
880 bgp_clear_stale_route (peer, afi, safi);
881 peer->nsf[afi][safi] = 0;
882 }
883 }
884
885 if (nsf_af_count)
886 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
887 else
888 {
889 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
890 if (peer->t_gr_stale)
891 {
892 BGP_TIMER_OFF (peer->t_gr_stale);
893 if (BGP_DEBUG (events, EVENTS))
894 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
895 }
896 }
897
898 if (peer->t_gr_restart)
899 {
900 BGP_TIMER_OFF (peer->t_gr_restart);
901 if (BGP_DEBUG (events, EVENTS))
902 zlog_debug ("%s graceful restart timer stopped", peer->host);
903 }
904
paul718e3742002-12-13 20:15:29 +0000905#ifdef HAVE_SNMP
906 bgpTrapEstablished (peer);
907#endif /* HAVE_SNMP */
908
909 /* Reset uptime, send keepalive, send current table. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300910 peer->uptime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000911
912 /* Send route-refresh when ORF is enabled */
913 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
914 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
915 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
916 {
917 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
918 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
919 REFRESH_IMMEDIATE, 0);
920 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
921 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
922 REFRESH_IMMEDIATE, 0);
923 }
924
925 if (peer->v_keepalive)
926 bgp_keepalive_send (peer);
927
928 /* First update is deferred until ORF or ROUTE-REFRESH is received */
929 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
930 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
931 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
932 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
933 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
934 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
935
936 bgp_announce_route_all (peer);
937
938 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
939
940 return 0;
941}
942
943/* Keepalive packet is received. */
paul94f2b392005-06-28 12:44:16 +0000944static int
paul718e3742002-12-13 20:15:29 +0000945bgp_fsm_keepalive (struct peer *peer)
946{
947 /* peer count update */
948 peer->keepalive_in++;
949
950 BGP_TIMER_OFF (peer->t_holdtime);
951 return 0;
952}
953
954/* Update packet is received. */
paul94f2b392005-06-28 12:44:16 +0000955static int
paul718e3742002-12-13 20:15:29 +0000956bgp_fsm_update (struct peer *peer)
957{
958 BGP_TIMER_OFF (peer->t_holdtime);
959 return 0;
960}
961
962/* This is empty event. */
paul94f2b392005-06-28 12:44:16 +0000963static int
paul718e3742002-12-13 20:15:29 +0000964bgp_ignore (struct peer *peer)
965{
966 if (BGP_DEBUG (fsm, FSM))
967 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
968 return 0;
969}
David Lamparter6b0655a2014-06-04 06:53:35 +0200970
paul718e3742002-12-13 20:15:29 +0000971/* Finite State Machine structure */
Stephen Hemmingerfda1d3e2009-05-15 10:02:27 -0700972static const struct {
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800973 int (*func) (struct peer *);
paul718e3742002-12-13 20:15:29 +0000974 int next_state;
975} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
976{
977 {
978 /* Idle state: In Idle state, all events other than BGP_Start is
979 ignored. With BGP_Start event, finite state machine calls
980 bgp_start(). */
981 {bgp_start, Connect}, /* BGP_Start */
982 {bgp_stop, Idle}, /* BGP_Stop */
983 {bgp_stop, Idle}, /* TCP_connection_open */
984 {bgp_stop, Idle}, /* TCP_connection_closed */
985 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
986 {bgp_stop, Idle}, /* TCP_fatal_error */
987 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
988 {bgp_ignore, Idle}, /* Hold_Timer_expired */
989 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
990 {bgp_ignore, Idle}, /* Receive_OPEN_message */
991 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
992 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
993 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000994 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +0100995 {bgp_ignore, Idle}, /* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +0000996 },
997 {
998 /* Connect */
999 {bgp_ignore, Connect}, /* BGP_Start */
1000 {bgp_stop, Idle}, /* BGP_Stop */
1001 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1002 {bgp_stop, Idle}, /* TCP_connection_closed */
1003 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
1004 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
1005 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
1006 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1007 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1008 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1009 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1010 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1011 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001012 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001013 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001014 },
1015 {
1016 /* Active, */
1017 {bgp_ignore, Active}, /* BGP_Start */
1018 {bgp_stop, Idle}, /* BGP_Stop */
1019 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1020 {bgp_stop, Idle}, /* TCP_connection_closed */
1021 {bgp_ignore, Active}, /* TCP_connection_open_failed */
1022 {bgp_ignore, Idle}, /* TCP_fatal_error */
1023 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
1024 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1025 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1026 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1027 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1028 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1029 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001030 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001031 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001032 },
1033 {
1034 /* OpenSent, */
1035 {bgp_ignore, OpenSent}, /* BGP_Start */
1036 {bgp_stop, Idle}, /* BGP_Stop */
Paul Jakma536792c2007-06-22 19:11:14 +00001037 {bgp_stop, Active}, /* TCP_connection_open */
paul718e3742002-12-13 20:15:29 +00001038 {bgp_stop, Active}, /* TCP_connection_closed */
Paul Jakma536792c2007-06-22 19:11:14 +00001039 {bgp_stop, Active}, /* TCP_connection_open_failed */
1040 {bgp_stop, Active}, /* TCP_fatal_error */
paul718e3742002-12-13 20:15:29 +00001041 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1042 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1043 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1044 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +02001045 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
1046 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
paul718e3742002-12-13 20:15:29 +00001047 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001048 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001049 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001050 },
1051 {
1052 /* OpenConfirm, */
1053 {bgp_ignore, OpenConfirm}, /* BGP_Start */
1054 {bgp_stop, Idle}, /* BGP_Stop */
1055 {bgp_stop, Idle}, /* TCP_connection_open */
1056 {bgp_stop, Idle}, /* TCP_connection_closed */
1057 {bgp_stop, Idle}, /* TCP_connection_open_failed */
1058 {bgp_stop, Idle}, /* TCP_fatal_error */
1059 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1060 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1061 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
1062 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1063 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
1064 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1065 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001066 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001067 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001068 },
1069 {
1070 /* Established, */
Paul Jakmaca058a32006-09-14 02:58:49 +00001071 {bgp_ignore, Established}, /* BGP_Start */
1072 {bgp_stop, Clearing}, /* BGP_Stop */
1073 {bgp_stop, Clearing}, /* TCP_connection_open */
1074 {bgp_stop, Clearing}, /* TCP_connection_closed */
Steve Hill3117b5c2009-07-28 17:50:00 +01001075 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
Paul Jakmaca058a32006-09-14 02:58:49 +00001076 {bgp_stop, Clearing}, /* TCP_fatal_error */
Steve Hill3117b5c2009-07-28 17:50:00 +01001077 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001078 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
paul718e3742002-12-13 20:15:29 +00001079 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001080 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1081 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
1082 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
1083 {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
1084 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001085 {bgp_stop_with_error, Clearing}, /* BGP_Stop_with_error */
Paul Jakmaca058a32006-09-14 02:58:49 +00001086 },
1087 {
1088 /* Clearing, */
1089 {bgp_ignore, Clearing}, /* BGP_Start */
Steve Hill3117b5c2009-07-28 17:50:00 +01001090 {bgp_stop, Clearing}, /* BGP_Stop */
1091 {bgp_stop, Clearing}, /* TCP_connection_open */
1092 {bgp_stop, Clearing}, /* TCP_connection_closed */
1093 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1094 {bgp_stop, Clearing}, /* TCP_fatal_error */
1095 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1096 {bgp_stop, Clearing}, /* Hold_Timer_expired */
1097 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
1098 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1099 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
1100 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
1101 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
1102 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001103 {bgp_stop_with_error, Clearing}, /* BGP_Stop_with_error */
Paul Jakmaca058a32006-09-14 02:58:49 +00001104 },
1105 {
1106 /* Deleted, */
1107 {bgp_ignore, Deleted}, /* BGP_Start */
1108 {bgp_ignore, Deleted}, /* BGP_Stop */
1109 {bgp_ignore, Deleted}, /* TCP_connection_open */
1110 {bgp_ignore, Deleted}, /* TCP_connection_closed */
1111 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
1112 {bgp_ignore, Deleted}, /* TCP_fatal_error */
1113 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
1114 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
1115 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
1116 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
1117 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
1118 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
1119 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
1120 {bgp_ignore, Deleted}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001121 {bgp_ignore, Deleted}, /* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001122 },
1123};
1124
paulfd79ac92004-10-13 05:06:08 +00001125static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +00001126{
1127 NULL,
1128 "BGP_Start",
1129 "BGP_Stop",
1130 "TCP_connection_open",
1131 "TCP_connection_closed",
1132 "TCP_connection_open_failed",
1133 "TCP_fatal_error",
1134 "ConnectRetry_timer_expired",
1135 "Hold_Timer_expired",
1136 "KeepAlive_timer_expired",
1137 "Receive_OPEN_message",
1138 "Receive_KEEPALIVE_message",
1139 "Receive_UPDATE_message",
Paul Jakmaca058a32006-09-14 02:58:49 +00001140 "Receive_NOTIFICATION_message",
1141 "Clearing_Completed",
Paul Jakmab1b15792016-09-21 18:50:23 +01001142 "BGP_Stop_with_error",
paul718e3742002-12-13 20:15:29 +00001143};
1144
1145/* Execute event process. */
1146int
1147bgp_event (struct thread *thread)
1148{
Paul Jakmaca058a32006-09-14 02:58:49 +00001149 int ret = 0;
paul718e3742002-12-13 20:15:29 +00001150 int event;
1151 int next;
1152 struct peer *peer;
1153
1154 peer = THREAD_ARG (thread);
1155 event = THREAD_VAL (thread);
1156
1157 /* Logging this event. */
1158 next = FSM [peer->status -1][event - 1].next_state;
1159
Paul Jakmaca058a32006-09-14 02:58:49 +00001160 if (BGP_DEBUG (fsm, FSM) && peer->status != next)
ajs8c2e2002004-12-08 20:08:54 +00001161 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001162 bgp_event_str[event],
1163 LOOKUP (bgp_status_msg, peer->status),
1164 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001165
1166 /* Call function. */
Paul Jakmaca058a32006-09-14 02:58:49 +00001167 if (FSM [peer->status -1][event - 1].func)
1168 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
paul718e3742002-12-13 20:15:29 +00001169
1170 /* When function do not want proceed next job return -1. */
paul200df112005-06-01 11:17:05 +00001171 if (ret >= 0)
1172 {
1173 /* If status is changed. */
1174 if (next != peer->status)
Paul Jakmaf2c31ac2007-02-22 17:48:42 +00001175 bgp_fsm_change_status (peer, next);
Paul Jakma95fdcd82006-12-08 00:31:22 +00001176
paul200df112005-06-01 11:17:05 +00001177 /* Make sure timer is set. */
1178 bgp_timer_set (peer);
1179 }
1180
paul200df112005-06-01 11:17:05 +00001181 return ret;
paul718e3742002-12-13 20:15:29 +00001182}