blob: 67c50c4755878b492aaca8d0371b0043a4bcfe1d [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 }
paul718e3742002-12-13 20:15:29 +0000510
511 /* 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
590/* BGP peer is stoped by the error. */
paul94f2b392005-06-28 12:44:16 +0000591static int
paul718e3742002-12-13 20:15:29 +0000592bgp_stop_with_error (struct peer *peer)
593{
594 /* Double start timer. */
595 peer->v_start *= 2;
596
597 /* Overflow check. */
598 if (peer->v_start >= (60 * 2))
599 peer->v_start = (60 * 2);
600
601 bgp_stop (peer);
602
603 return 0;
604}
605
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200606
607/* something went wrong, send notify and tear down */
608static int
609bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code)
610{
611 /* Send notify to remote peer */
612 bgp_notify_send (peer, code, sub_code);
613
614 /* Sweep if it is temporary peer. */
615 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
616 {
617 zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
618 peer_delete (peer);
619 return -1;
620 }
621
622 /* Clear start timer value to default. */
623 peer->v_start = BGP_INIT_START_TIMER;
624
625 /* bgp_stop needs to be invoked while in Established state */
626 bgp_stop(peer);
627
628 return 0;
629}
630
631
paul718e3742002-12-13 20:15:29 +0000632/* TCP connection open. Next we send open message to remote peer. And
633 add read thread for reading open message. */
paul94f2b392005-06-28 12:44:16 +0000634static int
paul718e3742002-12-13 20:15:29 +0000635bgp_connect_success (struct peer *peer)
636{
pauleb821182004-05-01 08:44:08 +0000637 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000638 {
639 zlog_err ("bgp_connect_success peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000640 peer->fd);
paul718e3742002-12-13 20:15:29 +0000641 return -1;
642 }
pauleb821182004-05-01 08:44:08 +0000643 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +0000644
hassof4184462005-02-01 20:13:16 +0000645 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
646 bgp_getsockname (peer);
647
648 if (BGP_DEBUG (normal, NORMAL))
649 {
Jorge Boncompte [DTI2]682ca042012-04-10 16:57:27 +0200650 char buf1[SU_ADDRSTRLEN];
651
hassof4184462005-02-01 20:13:16 +0000652 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
653 zlog_debug ("%s open active, local address %s", peer->host,
654 sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN));
655 else
656 zlog_debug ("%s passive open", peer->host);
657 }
paul718e3742002-12-13 20:15:29 +0000658
Paul Jakma6556d8a2008-08-26 14:33:28 +0100659 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
paul718e3742002-12-13 20:15:29 +0000660 bgp_open_send (peer);
661
662 return 0;
663}
664
665/* TCP connect fail */
paul94f2b392005-06-28 12:44:16 +0000666static int
paul718e3742002-12-13 20:15:29 +0000667bgp_connect_fail (struct peer *peer)
668{
669 bgp_stop (peer);
670 return 0;
671}
672
673/* This function is the first starting point of all BGP connection. It
674 try to connect to remote peer with non-blocking IO. */
675int
676bgp_start (struct peer *peer)
677{
678 int status;
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700679 int connected = 0;
paul718e3742002-12-13 20:15:29 +0000680
Paul Jakmaca058a32006-09-14 02:58:49 +0000681 if (BGP_PEER_START_SUPPRESSED (peer))
682 {
683 if (BGP_DEBUG (fsm, FSM))
684 plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
685 " - this is never supposed to happen!", peer->host);
686 return -1;
687 }
688
Paul Jakma33d5ab92006-07-02 11:01:50 +0000689 /* Scrub some information that might be left over from a previous,
690 * session
691 */
692 /* Connection information. */
693 if (peer->su_local)
694 {
695 sockunion_free (peer->su_local);
696 peer->su_local = NULL;
697 }
698
699 if (peer->su_remote)
700 {
701 sockunion_free (peer->su_remote);
702 peer->su_remote = NULL;
703 }
704
705 /* Clear remote router-id. */
706 peer->remote_id.s_addr = 0;
707
708 /* Clear peer capability flag. */
709 peer->cap = 0;
710
paul718e3742002-12-13 20:15:29 +0000711 /* If the peer is passive mode, force to move to Active mode. */
712 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
713 {
714 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
715 return 0;
716 }
717
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700718 /* Register to be notified on peer up */
Timo Teräse3443a22016-10-19 16:02:34 +0300719 if ((peer_ttl(peer) == 1 || peer->gtsm_hops == 1) &&
Timo Teräsc9cc52a2016-10-19 16:02:33 +0300720 ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
Dinesh Duttd9ab53a2015-05-19 17:47:21 -0700721 connected = 1;
722
723 bgp_find_or_add_nexthop(family2afi(peer->su.sa.sa_family), NULL, peer,
724 connected);
paul718e3742002-12-13 20:15:29 +0000725 status = bgp_connect (peer);
726
727 switch (status)
728 {
729 case connect_error:
730 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000731 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000732 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
733 break;
734 case connect_success:
735 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000736 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000737 peer->host);
paul718e3742002-12-13 20:15:29 +0000738 BGP_EVENT_ADD (peer, TCP_connection_open);
739 break;
740 case connect_in_progress:
741 /* To check nonblocking connect, we wait until socket is
742 readable or writable. */
743 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000744 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000745 peer->host);
746 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000747 {
748 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000749 peer->fd);
paul718e3742002-12-13 20:15:29 +0000750 return -1;
751 }
pauleb821182004-05-01 08:44:08 +0000752 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
753 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000754 break;
755 }
756 return 0;
757}
758
759/* Connect retry timer is expired when the peer status is Connect. */
paul94f2b392005-06-28 12:44:16 +0000760static int
paul718e3742002-12-13 20:15:29 +0000761bgp_reconnect (struct peer *peer)
762{
763 bgp_stop (peer);
764 bgp_start (peer);
765 return 0;
766}
767
paul94f2b392005-06-28 12:44:16 +0000768static int
paul718e3742002-12-13 20:15:29 +0000769bgp_fsm_open (struct peer *peer)
770{
771 /* Send keepalive and make keepalive timer */
772 bgp_keepalive_send (peer);
773
774 /* Reset holdtimer value. */
775 BGP_TIMER_OFF (peer->t_holdtime);
776
777 return 0;
778}
779
paul718e3742002-12-13 20:15:29 +0000780/* Keepalive send to peer. */
paul94f2b392005-06-28 12:44:16 +0000781static int
paul718e3742002-12-13 20:15:29 +0000782bgp_fsm_keepalive_expire (struct peer *peer)
783{
784 bgp_keepalive_send (peer);
785 return 0;
786}
787
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200788/* FSM error, unexpected event. This is error of BGP connection. So cut the
789 peer and change to Idle status. */
790static int
791bgp_fsm_event_error (struct peer *peer)
792{
793 plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
794 peer->host, LOOKUP (bgp_status_msg, peer->status));
795
796 return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
797}
798
paul718e3742002-12-13 20:15:29 +0000799/* Hold timer expire. This is error of BGP connection. So cut the
800 peer and change to Idle status. */
paul94f2b392005-06-28 12:44:16 +0000801static int
paul718e3742002-12-13 20:15:29 +0000802bgp_fsm_holdtime_expire (struct peer *peer)
803{
804 if (BGP_DEBUG (fsm, FSM))
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200805 plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
paul718e3742002-12-13 20:15:29 +0000806
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200807 return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
paul718e3742002-12-13 20:15:29 +0000808}
809
810/* Status goes to Established. Send keepalive packet then make first
811 update information. */
paul94f2b392005-06-28 12:44:16 +0000812static int
paul718e3742002-12-13 20:15:29 +0000813bgp_establish (struct peer *peer)
814{
815 struct bgp_notify *notify;
816 afi_t afi;
817 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000818 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000819
820 /* Reset capability open status flag. */
821 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
822 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
823
824 /* Clear last notification data. */
825 notify = &peer->notify;
826 if (notify->data)
827 XFREE (MTYPE_TMP, notify->data);
828 memset (notify, 0, sizeof (struct bgp_notify));
829
830 /* Clear start timer value to default. */
831 peer->v_start = BGP_INIT_START_TIMER;
832
833 /* Increment established count. */
834 peer->established++;
835 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000836
837 /* bgp log-neighbor-changes of neighbor Up */
838 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
839 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
840
hasso93406d82005-02-02 14:40:33 +0000841 /* graceful restart */
842 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
843 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400844 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000845 {
846 if (peer->afc_nego[afi][safi]
847 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
848 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
849 {
850 if (peer->nsf[afi][safi]
851 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
852 bgp_clear_stale_route (peer, afi, safi);
853
854 peer->nsf[afi][safi] = 1;
855 nsf_af_count++;
856 }
857 else
858 {
859 if (peer->nsf[afi][safi])
860 bgp_clear_stale_route (peer, afi, safi);
861 peer->nsf[afi][safi] = 0;
862 }
863 }
864
865 if (nsf_af_count)
866 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
867 else
868 {
869 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
870 if (peer->t_gr_stale)
871 {
872 BGP_TIMER_OFF (peer->t_gr_stale);
873 if (BGP_DEBUG (events, EVENTS))
874 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
875 }
876 }
877
878 if (peer->t_gr_restart)
879 {
880 BGP_TIMER_OFF (peer->t_gr_restart);
881 if (BGP_DEBUG (events, EVENTS))
882 zlog_debug ("%s graceful restart timer stopped", peer->host);
883 }
884
paul718e3742002-12-13 20:15:29 +0000885#ifdef HAVE_SNMP
886 bgpTrapEstablished (peer);
887#endif /* HAVE_SNMP */
888
889 /* Reset uptime, send keepalive, send current table. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300890 peer->uptime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000891
892 /* Send route-refresh when ORF is enabled */
893 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
894 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
895 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
896 {
897 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
898 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
899 REFRESH_IMMEDIATE, 0);
900 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
901 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
902 REFRESH_IMMEDIATE, 0);
903 }
904
905 if (peer->v_keepalive)
906 bgp_keepalive_send (peer);
907
908 /* First update is deferred until ORF or ROUTE-REFRESH is received */
909 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
910 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
911 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
912 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
913 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
914 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
915
916 bgp_announce_route_all (peer);
917
918 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
919
920 return 0;
921}
922
923/* Keepalive packet is received. */
paul94f2b392005-06-28 12:44:16 +0000924static int
paul718e3742002-12-13 20:15:29 +0000925bgp_fsm_keepalive (struct peer *peer)
926{
927 /* peer count update */
928 peer->keepalive_in++;
929
930 BGP_TIMER_OFF (peer->t_holdtime);
931 return 0;
932}
933
934/* Update packet is received. */
paul94f2b392005-06-28 12:44:16 +0000935static int
paul718e3742002-12-13 20:15:29 +0000936bgp_fsm_update (struct peer *peer)
937{
938 BGP_TIMER_OFF (peer->t_holdtime);
939 return 0;
940}
941
942/* This is empty event. */
paul94f2b392005-06-28 12:44:16 +0000943static int
paul718e3742002-12-13 20:15:29 +0000944bgp_ignore (struct peer *peer)
945{
946 if (BGP_DEBUG (fsm, FSM))
947 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
948 return 0;
949}
David Lamparter6b0655a2014-06-04 06:53:35 +0200950
paul718e3742002-12-13 20:15:29 +0000951/* Finite State Machine structure */
Stephen Hemmingerfda1d3e2009-05-15 10:02:27 -0700952static const struct {
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800953 int (*func) (struct peer *);
paul718e3742002-12-13 20:15:29 +0000954 int next_state;
955} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
956{
957 {
958 /* Idle state: In Idle state, all events other than BGP_Start is
959 ignored. With BGP_Start event, finite state machine calls
960 bgp_start(). */
961 {bgp_start, Connect}, /* BGP_Start */
962 {bgp_stop, Idle}, /* BGP_Stop */
963 {bgp_stop, Idle}, /* TCP_connection_open */
964 {bgp_stop, Idle}, /* TCP_connection_closed */
965 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
966 {bgp_stop, Idle}, /* TCP_fatal_error */
967 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
968 {bgp_ignore, Idle}, /* Hold_Timer_expired */
969 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
970 {bgp_ignore, Idle}, /* Receive_OPEN_message */
971 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
972 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
973 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000974 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +0100975 {bgp_start, Connect}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +0000976 },
977 {
978 /* Connect */
979 {bgp_ignore, Connect}, /* BGP_Start */
980 {bgp_stop, Idle}, /* BGP_Stop */
981 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
982 {bgp_stop, Idle}, /* TCP_connection_closed */
983 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
984 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
985 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
986 {bgp_ignore, Idle}, /* Hold_Timer_expired */
987 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
988 {bgp_ignore, Idle}, /* Receive_OPEN_message */
989 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
990 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
991 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000992 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +0100993 {bgp_reconnect, Connect},/* NHT_Update */
paul718e3742002-12-13 20:15:29 +0000994 },
995 {
996 /* Active, */
997 {bgp_ignore, Active}, /* BGP_Start */
998 {bgp_stop, Idle}, /* BGP_Stop */
999 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1000 {bgp_stop, Idle}, /* TCP_connection_closed */
1001 {bgp_ignore, Active}, /* TCP_connection_open_failed */
1002 {bgp_ignore, Idle}, /* TCP_fatal_error */
1003 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
1004 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1005 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1006 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1007 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1008 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1009 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001010 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001011 {bgp_start, Connect}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001012 },
1013 {
1014 /* OpenSent, */
1015 {bgp_ignore, OpenSent}, /* BGP_Start */
1016 {bgp_stop, Idle}, /* BGP_Stop */
Paul Jakma536792c2007-06-22 19:11:14 +00001017 {bgp_stop, Active}, /* TCP_connection_open */
paul718e3742002-12-13 20:15:29 +00001018 {bgp_stop, Active}, /* TCP_connection_closed */
Paul Jakma536792c2007-06-22 19:11:14 +00001019 {bgp_stop, Active}, /* TCP_connection_open_failed */
1020 {bgp_stop, Active}, /* TCP_fatal_error */
paul718e3742002-12-13 20:15:29 +00001021 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1022 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1023 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1024 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +02001025 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
1026 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
paul718e3742002-12-13 20:15:29 +00001027 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001028 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001029 {bgp_ignore, OpenSent}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001030 },
1031 {
1032 /* OpenConfirm, */
1033 {bgp_ignore, OpenConfirm}, /* BGP_Start */
1034 {bgp_stop, Idle}, /* BGP_Stop */
1035 {bgp_stop, Idle}, /* TCP_connection_open */
1036 {bgp_stop, Idle}, /* TCP_connection_closed */
1037 {bgp_stop, Idle}, /* TCP_connection_open_failed */
1038 {bgp_stop, Idle}, /* TCP_fatal_error */
1039 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1040 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1041 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
1042 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1043 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
1044 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1045 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001046 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001047 {bgp_ignore, OpenConfirm}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001048 },
1049 {
1050 /* Established, */
Paul Jakmaca058a32006-09-14 02:58:49 +00001051 {bgp_ignore, Established}, /* BGP_Start */
1052 {bgp_stop, Clearing}, /* BGP_Stop */
1053 {bgp_stop, Clearing}, /* TCP_connection_open */
1054 {bgp_stop, Clearing}, /* TCP_connection_closed */
Steve Hill3117b5c2009-07-28 17:50:00 +01001055 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
Paul Jakmaca058a32006-09-14 02:58:49 +00001056 {bgp_stop, Clearing}, /* TCP_fatal_error */
Steve Hill3117b5c2009-07-28 17:50:00 +01001057 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001058 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
paul718e3742002-12-13 20:15:29 +00001059 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001060 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1061 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
1062 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
1063 {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
1064 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001065 {bgp_ignore, Established}, /* NHT_Update */
Paul Jakmaca058a32006-09-14 02:58:49 +00001066 },
1067 {
1068 /* Clearing, */
1069 {bgp_ignore, Clearing}, /* BGP_Start */
Steve Hill3117b5c2009-07-28 17:50:00 +01001070 {bgp_stop, Clearing}, /* BGP_Stop */
1071 {bgp_stop, Clearing}, /* TCP_connection_open */
1072 {bgp_stop, Clearing}, /* TCP_connection_closed */
1073 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1074 {bgp_stop, Clearing}, /* TCP_fatal_error */
1075 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1076 {bgp_stop, Clearing}, /* Hold_Timer_expired */
1077 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
1078 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1079 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
1080 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
1081 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
1082 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001083 {bgp_ignore, Clearing}, /* NHT_Update */
Paul Jakmaca058a32006-09-14 02:58:49 +00001084 },
1085 {
1086 /* Deleted, */
1087 {bgp_ignore, Deleted}, /* BGP_Start */
1088 {bgp_ignore, Deleted}, /* BGP_Stop */
1089 {bgp_ignore, Deleted}, /* TCP_connection_open */
1090 {bgp_ignore, Deleted}, /* TCP_connection_closed */
1091 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
1092 {bgp_ignore, Deleted}, /* TCP_fatal_error */
1093 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
1094 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
1095 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
1096 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
1097 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
1098 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
1099 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
1100 {bgp_ignore, Deleted}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001101 {bgp_ignore, Deleted}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001102 },
1103};
1104
paulfd79ac92004-10-13 05:06:08 +00001105static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +00001106{
1107 NULL,
1108 "BGP_Start",
1109 "BGP_Stop",
1110 "TCP_connection_open",
1111 "TCP_connection_closed",
1112 "TCP_connection_open_failed",
1113 "TCP_fatal_error",
1114 "ConnectRetry_timer_expired",
1115 "Hold_Timer_expired",
1116 "KeepAlive_timer_expired",
1117 "Receive_OPEN_message",
1118 "Receive_KEEPALIVE_message",
1119 "Receive_UPDATE_message",
Paul Jakmaca058a32006-09-14 02:58:49 +00001120 "Receive_NOTIFICATION_message",
1121 "Clearing_Completed",
Paul Jakma743dd422016-09-30 13:55:47 +01001122 "NHT_Update",
paul718e3742002-12-13 20:15:29 +00001123};
1124
1125/* Execute event process. */
1126int
1127bgp_event (struct thread *thread)
1128{
Paul Jakmaca058a32006-09-14 02:58:49 +00001129 int ret = 0;
paul718e3742002-12-13 20:15:29 +00001130 int event;
1131 int next;
1132 struct peer *peer;
1133
1134 peer = THREAD_ARG (thread);
1135 event = THREAD_VAL (thread);
1136
1137 /* Logging this event. */
1138 next = FSM [peer->status -1][event - 1].next_state;
1139
Paul Jakmaca058a32006-09-14 02:58:49 +00001140 if (BGP_DEBUG (fsm, FSM) && peer->status != next)
ajs8c2e2002004-12-08 20:08:54 +00001141 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001142 bgp_event_str[event],
1143 LOOKUP (bgp_status_msg, peer->status),
1144 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001145
1146 /* Call function. */
Paul Jakmaca058a32006-09-14 02:58:49 +00001147 if (FSM [peer->status -1][event - 1].func)
1148 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
paul718e3742002-12-13 20:15:29 +00001149
1150 /* When function do not want proceed next job return -1. */
paul200df112005-06-01 11:17:05 +00001151 if (ret >= 0)
1152 {
1153 /* If status is changed. */
1154 if (next != peer->status)
Paul Jakmaf2c31ac2007-02-22 17:48:42 +00001155 bgp_fsm_change_status (peer, next);
Paul Jakma95fdcd82006-12-08 00:31:22 +00001156
paul200df112005-06-01 11:17:05 +00001157 /* Make sure timer is set. */
1158 bgp_timer_set (peer);
1159 }
1160
paul200df112005-06-01 11:17:05 +00001161 return ret;
paul718e3742002-12-13 20:15:29 +00001162}