blob: 41f623ff390967c88effefbaa455f8a9e75af0f9 [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 Jakma6556d8a2008-08-26 14:33:28 +0100681 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
paul718e3742002-12-13 20:15:29 +0000682 bgp_open_send (peer);
683
684 return 0;
685}
686
687/* TCP connect fail */
paul94f2b392005-06-28 12:44:16 +0000688static int
paul718e3742002-12-13 20:15:29 +0000689bgp_connect_fail (struct peer *peer)
690{
691 bgp_stop (peer);
692 return 0;
693}
694
695/* This function is the first starting point of all BGP connection. It
696 try to connect to remote peer with non-blocking IO. */
697int
698bgp_start (struct peer *peer)
699{
700 int status;
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700701 int connected = 0;
paul718e3742002-12-13 20:15:29 +0000702
Paul Jakmaca058a32006-09-14 02:58:49 +0000703 if (BGP_PEER_START_SUPPRESSED (peer))
704 {
705 if (BGP_DEBUG (fsm, FSM))
706 plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
707 " - this is never supposed to happen!", peer->host);
708 return -1;
709 }
710
Paul Jakma33d5ab92006-07-02 11:01:50 +0000711 /* Scrub some information that might be left over from a previous,
712 * session
713 */
714 /* Connection information. */
715 if (peer->su_local)
716 {
717 sockunion_free (peer->su_local);
718 peer->su_local = NULL;
719 }
720
721 if (peer->su_remote)
722 {
723 sockunion_free (peer->su_remote);
724 peer->su_remote = NULL;
725 }
726
727 /* Clear remote router-id. */
728 peer->remote_id.s_addr = 0;
729
730 /* Clear peer capability flag. */
731 peer->cap = 0;
732
paul718e3742002-12-13 20:15:29 +0000733 /* If the peer is passive mode, force to move to Active mode. */
734 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
735 {
736 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
737 return 0;
738 }
739
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700740 /* Register to be notified on peer up */
Timo Teräse3443a22016-10-19 16:02:34 +0300741 if ((peer_ttl(peer) == 1 || peer->gtsm_hops == 1) &&
Timo Teräsc9cc52a2016-10-19 16:02:33 +0300742 ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700743 connected = 1;
744
Paul Jakma3dda6b32016-09-06 16:57:40 +0100745 bgp_ensure_nexthop (NULL, peer, connected);
paul718e3742002-12-13 20:15:29 +0000746 status = bgp_connect (peer);
747
748 switch (status)
749 {
750 case connect_error:
751 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000752 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000753 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
754 break;
755 case connect_success:
756 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000757 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000758 peer->host);
paul718e3742002-12-13 20:15:29 +0000759 BGP_EVENT_ADD (peer, TCP_connection_open);
760 break;
761 case connect_in_progress:
762 /* To check nonblocking connect, we wait until socket is
763 readable or writable. */
764 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000765 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000766 peer->host);
767 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000768 {
769 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000770 peer->fd);
paul718e3742002-12-13 20:15:29 +0000771 return -1;
772 }
pauleb821182004-05-01 08:44:08 +0000773 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
774 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000775 break;
776 }
777 return 0;
778}
779
780/* Connect retry timer is expired when the peer status is Connect. */
paul94f2b392005-06-28 12:44:16 +0000781static int
paul718e3742002-12-13 20:15:29 +0000782bgp_reconnect (struct peer *peer)
783{
784 bgp_stop (peer);
785 bgp_start (peer);
786 return 0;
787}
788
paul94f2b392005-06-28 12:44:16 +0000789static int
paul718e3742002-12-13 20:15:29 +0000790bgp_fsm_open (struct peer *peer)
791{
792 /* Send keepalive and make keepalive timer */
793 bgp_keepalive_send (peer);
794
795 /* Reset holdtimer value. */
796 BGP_TIMER_OFF (peer->t_holdtime);
797
798 return 0;
799}
800
paul718e3742002-12-13 20:15:29 +0000801/* Keepalive send to peer. */
paul94f2b392005-06-28 12:44:16 +0000802static int
paul718e3742002-12-13 20:15:29 +0000803bgp_fsm_keepalive_expire (struct peer *peer)
804{
805 bgp_keepalive_send (peer);
806 return 0;
807}
808
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200809/* FSM error, unexpected event. This is error of BGP connection. So cut the
810 peer and change to Idle status. */
811static int
812bgp_fsm_event_error (struct peer *peer)
813{
814 plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
815 peer->host, LOOKUP (bgp_status_msg, peer->status));
816
817 return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
818}
819
paul718e3742002-12-13 20:15:29 +0000820/* Hold timer expire. This is error of BGP connection. So cut the
821 peer and change to Idle status. */
paul94f2b392005-06-28 12:44:16 +0000822static int
paul718e3742002-12-13 20:15:29 +0000823bgp_fsm_holdtime_expire (struct peer *peer)
824{
825 if (BGP_DEBUG (fsm, FSM))
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200826 plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
paul718e3742002-12-13 20:15:29 +0000827
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200828 return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
paul718e3742002-12-13 20:15:29 +0000829}
830
831/* Status goes to Established. Send keepalive packet then make first
832 update information. */
paul94f2b392005-06-28 12:44:16 +0000833static int
paul718e3742002-12-13 20:15:29 +0000834bgp_establish (struct peer *peer)
835{
836 struct bgp_notify *notify;
837 afi_t afi;
838 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000839 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000840
841 /* Reset capability open status flag. */
842 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
843 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
844
845 /* Clear last notification data. */
846 notify = &peer->notify;
847 if (notify->data)
848 XFREE (MTYPE_TMP, notify->data);
849 memset (notify, 0, sizeof (struct bgp_notify));
850
851 /* Clear start timer value to default. */
852 peer->v_start = BGP_INIT_START_TIMER;
853
854 /* Increment established count. */
855 peer->established++;
856 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000857
858 /* bgp log-neighbor-changes of neighbor Up */
859 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
860 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
861
hasso93406d82005-02-02 14:40:33 +0000862 /* graceful restart */
863 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
864 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400865 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000866 {
867 if (peer->afc_nego[afi][safi]
868 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
869 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
870 {
871 if (peer->nsf[afi][safi]
872 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
873 bgp_clear_stale_route (peer, afi, safi);
874
875 peer->nsf[afi][safi] = 1;
876 nsf_af_count++;
877 }
878 else
879 {
880 if (peer->nsf[afi][safi])
881 bgp_clear_stale_route (peer, afi, safi);
882 peer->nsf[afi][safi] = 0;
883 }
884 }
885
886 if (nsf_af_count)
887 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
888 else
889 {
890 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
891 if (peer->t_gr_stale)
892 {
893 BGP_TIMER_OFF (peer->t_gr_stale);
894 if (BGP_DEBUG (events, EVENTS))
895 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
896 }
897 }
898
899 if (peer->t_gr_restart)
900 {
901 BGP_TIMER_OFF (peer->t_gr_restart);
902 if (BGP_DEBUG (events, EVENTS))
903 zlog_debug ("%s graceful restart timer stopped", peer->host);
904 }
905
paul718e3742002-12-13 20:15:29 +0000906#ifdef HAVE_SNMP
907 bgpTrapEstablished (peer);
908#endif /* HAVE_SNMP */
909
910 /* Reset uptime, send keepalive, send current table. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300911 peer->uptime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000912
913 /* Send route-refresh when ORF is enabled */
914 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
915 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
916 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
917 {
918 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
919 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
920 REFRESH_IMMEDIATE, 0);
921 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
922 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
923 REFRESH_IMMEDIATE, 0);
924 }
925
926 if (peer->v_keepalive)
927 bgp_keepalive_send (peer);
928
929 /* First update is deferred until ORF or ROUTE-REFRESH is received */
930 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
931 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
932 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
933 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
934 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
935 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
936
937 bgp_announce_route_all (peer);
938
939 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
940
941 return 0;
942}
943
944/* Keepalive packet is received. */
paul94f2b392005-06-28 12:44:16 +0000945static int
paul718e3742002-12-13 20:15:29 +0000946bgp_fsm_keepalive (struct peer *peer)
947{
948 /* peer count update */
949 peer->keepalive_in++;
950
951 BGP_TIMER_OFF (peer->t_holdtime);
952 return 0;
953}
954
955/* Update packet is received. */
paul94f2b392005-06-28 12:44:16 +0000956static int
paul718e3742002-12-13 20:15:29 +0000957bgp_fsm_update (struct peer *peer)
958{
959 BGP_TIMER_OFF (peer->t_holdtime);
960 return 0;
961}
962
963/* This is empty event. */
paul94f2b392005-06-28 12:44:16 +0000964static int
paul718e3742002-12-13 20:15:29 +0000965bgp_ignore (struct peer *peer)
966{
967 if (BGP_DEBUG (fsm, FSM))
968 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
969 return 0;
970}
David Lamparter6b0655a2014-06-04 06:53:35 +0200971
paul718e3742002-12-13 20:15:29 +0000972/* Finite State Machine structure */
Stephen Hemmingerfda1d3e2009-05-15 10:02:27 -0700973static const struct {
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800974 int (*func) (struct peer *);
paul718e3742002-12-13 20:15:29 +0000975 int next_state;
976} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
977{
978 {
979 /* Idle state: In Idle state, all events other than BGP_Start is
980 ignored. With BGP_Start event, finite state machine calls
981 bgp_start(). */
982 {bgp_start, Connect}, /* BGP_Start */
983 {bgp_stop, Idle}, /* BGP_Stop */
984 {bgp_stop, Idle}, /* TCP_connection_open */
985 {bgp_stop, Idle}, /* TCP_connection_closed */
986 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
987 {bgp_stop, Idle}, /* TCP_fatal_error */
988 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
989 {bgp_ignore, Idle}, /* Hold_Timer_expired */
990 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
991 {bgp_ignore, Idle}, /* Receive_OPEN_message */
992 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
993 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
994 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000995 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +0100996 {bgp_ignore, Idle}, /* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +0000997 },
998 {
999 /* Connect */
1000 {bgp_ignore, Connect}, /* BGP_Start */
1001 {bgp_stop, Idle}, /* BGP_Stop */
1002 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1003 {bgp_stop, Idle}, /* TCP_connection_closed */
1004 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
1005 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
1006 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
1007 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1008 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1009 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1010 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1011 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1012 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001013 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001014 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001015 },
1016 {
1017 /* Active, */
1018 {bgp_ignore, Active}, /* BGP_Start */
1019 {bgp_stop, Idle}, /* BGP_Stop */
1020 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1021 {bgp_stop, Idle}, /* TCP_connection_closed */
1022 {bgp_ignore, Active}, /* TCP_connection_open_failed */
1023 {bgp_ignore, Idle}, /* TCP_fatal_error */
1024 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
1025 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1026 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1027 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1028 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1029 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1030 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001031 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001032 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001033 },
1034 {
1035 /* OpenSent, */
1036 {bgp_ignore, OpenSent}, /* BGP_Start */
1037 {bgp_stop, Idle}, /* BGP_Stop */
Paul Jakma536792c2007-06-22 19:11:14 +00001038 {bgp_stop, Active}, /* TCP_connection_open */
paul718e3742002-12-13 20:15:29 +00001039 {bgp_stop, Active}, /* TCP_connection_closed */
Paul Jakma536792c2007-06-22 19:11:14 +00001040 {bgp_stop, Active}, /* TCP_connection_open_failed */
1041 {bgp_stop, Active}, /* TCP_fatal_error */
paul718e3742002-12-13 20:15:29 +00001042 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1043 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1044 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1045 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +02001046 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
1047 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
paul718e3742002-12-13 20:15:29 +00001048 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001049 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001050 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001051 },
1052 {
1053 /* OpenConfirm, */
1054 {bgp_ignore, OpenConfirm}, /* BGP_Start */
1055 {bgp_stop, Idle}, /* BGP_Stop */
1056 {bgp_stop, Idle}, /* TCP_connection_open */
1057 {bgp_stop, Idle}, /* TCP_connection_closed */
1058 {bgp_stop, Idle}, /* TCP_connection_open_failed */
1059 {bgp_stop, Idle}, /* TCP_fatal_error */
1060 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1061 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1062 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
1063 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1064 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
1065 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1066 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001067 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001068 {bgp_stop_with_error, Idle},/* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001069 },
1070 {
1071 /* Established, */
Paul Jakmaca058a32006-09-14 02:58:49 +00001072 {bgp_ignore, Established}, /* BGP_Start */
1073 {bgp_stop, Clearing}, /* BGP_Stop */
1074 {bgp_stop, Clearing}, /* TCP_connection_open */
1075 {bgp_stop, Clearing}, /* TCP_connection_closed */
Steve Hill3117b5c2009-07-28 17:50:00 +01001076 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
Paul Jakmaca058a32006-09-14 02:58:49 +00001077 {bgp_stop, Clearing}, /* TCP_fatal_error */
Steve Hill3117b5c2009-07-28 17:50:00 +01001078 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001079 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
paul718e3742002-12-13 20:15:29 +00001080 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001081 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1082 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
1083 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
1084 {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
1085 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001086 {bgp_stop_with_error, Clearing}, /* BGP_Stop_with_error */
Paul Jakmaca058a32006-09-14 02:58:49 +00001087 },
1088 {
1089 /* Clearing, */
1090 {bgp_ignore, Clearing}, /* BGP_Start */
Steve Hill3117b5c2009-07-28 17:50:00 +01001091 {bgp_stop, Clearing}, /* BGP_Stop */
1092 {bgp_stop, Clearing}, /* TCP_connection_open */
1093 {bgp_stop, Clearing}, /* TCP_connection_closed */
1094 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1095 {bgp_stop, Clearing}, /* TCP_fatal_error */
1096 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1097 {bgp_stop, Clearing}, /* Hold_Timer_expired */
1098 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
1099 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1100 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
1101 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
1102 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
1103 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001104 {bgp_stop_with_error, Clearing}, /* BGP_Stop_with_error */
Paul Jakmaca058a32006-09-14 02:58:49 +00001105 },
1106 {
1107 /* Deleted, */
1108 {bgp_ignore, Deleted}, /* BGP_Start */
1109 {bgp_ignore, Deleted}, /* BGP_Stop */
1110 {bgp_ignore, Deleted}, /* TCP_connection_open */
1111 {bgp_ignore, Deleted}, /* TCP_connection_closed */
1112 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
1113 {bgp_ignore, Deleted}, /* TCP_fatal_error */
1114 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
1115 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
1116 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
1117 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
1118 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
1119 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
1120 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
1121 {bgp_ignore, Deleted}, /* Clearing_Completed */
Paul Jakmab1b15792016-09-21 18:50:23 +01001122 {bgp_ignore, Deleted}, /* BGP_Stop_with_error */
paul718e3742002-12-13 20:15:29 +00001123 },
1124};
1125
paulfd79ac92004-10-13 05:06:08 +00001126static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +00001127{
1128 NULL,
1129 "BGP_Start",
1130 "BGP_Stop",
1131 "TCP_connection_open",
1132 "TCP_connection_closed",
1133 "TCP_connection_open_failed",
1134 "TCP_fatal_error",
1135 "ConnectRetry_timer_expired",
1136 "Hold_Timer_expired",
1137 "KeepAlive_timer_expired",
1138 "Receive_OPEN_message",
1139 "Receive_KEEPALIVE_message",
1140 "Receive_UPDATE_message",
Paul Jakmaca058a32006-09-14 02:58:49 +00001141 "Receive_NOTIFICATION_message",
1142 "Clearing_Completed",
Paul Jakmab1b15792016-09-21 18:50:23 +01001143 "BGP_Stop_with_error",
paul718e3742002-12-13 20:15:29 +00001144};
1145
1146/* Execute event process. */
1147int
1148bgp_event (struct thread *thread)
1149{
Paul Jakmaca058a32006-09-14 02:58:49 +00001150 int ret = 0;
paul718e3742002-12-13 20:15:29 +00001151 int event;
1152 int next;
1153 struct peer *peer;
1154
1155 peer = THREAD_ARG (thread);
1156 event = THREAD_VAL (thread);
1157
1158 /* Logging this event. */
1159 next = FSM [peer->status -1][event - 1].next_state;
1160
Paul Jakmaca058a32006-09-14 02:58:49 +00001161 if (BGP_DEBUG (fsm, FSM) && peer->status != next)
ajs8c2e2002004-12-08 20:08:54 +00001162 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001163 bgp_event_str[event],
1164 LOOKUP (bgp_status_msg, peer->status),
1165 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001166
1167 /* Call function. */
Paul Jakmaca058a32006-09-14 02:58:49 +00001168 if (FSM [peer->status -1][event - 1].func)
1169 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
paul718e3742002-12-13 20:15:29 +00001170
1171 /* When function do not want proceed next job return -1. */
paul200df112005-06-01 11:17:05 +00001172 if (ret >= 0)
1173 {
1174 /* If status is changed. */
1175 if (next != peer->status)
Paul Jakmaf2c31ac2007-02-22 17:48:42 +00001176 bgp_fsm_change_status (peer, next);
Paul Jakma95fdcd82006-12-08 00:31:22 +00001177
paul200df112005-06-01 11:17:05 +00001178 /* Make sure timer is set. */
1179 bgp_timer_set (peer);
1180 }
1181
paul200df112005-06-01 11:17:05 +00001182 return ret;
paul718e3742002-12-13 20:15:29 +00001183}