blob: 2e07d938ca61d5b4f9fbf533d0f4ef27e1831b5e [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 */
719 if ((peer->ttl == 1) || (peer->gtsm_hops == 1))
720 connected = 1;
721
722 bgp_find_or_add_nexthop(family2afi(peer->su.sa.sa_family), NULL, peer,
723 connected);
paul718e3742002-12-13 20:15:29 +0000724 status = bgp_connect (peer);
725
726 switch (status)
727 {
728 case connect_error:
729 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000730 plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
paul718e3742002-12-13 20:15:29 +0000731 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
732 break;
733 case connect_success:
734 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000735 plog_debug (peer->log, "%s [FSM] Connect immediately success",
pauleb821182004-05-01 08:44:08 +0000736 peer->host);
paul718e3742002-12-13 20:15:29 +0000737 BGP_EVENT_ADD (peer, TCP_connection_open);
738 break;
739 case connect_in_progress:
740 /* To check nonblocking connect, we wait until socket is
741 readable or writable. */
742 if (BGP_DEBUG (fsm, FSM))
ajs8c2e2002004-12-08 20:08:54 +0000743 plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
pauleb821182004-05-01 08:44:08 +0000744 peer->host);
745 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +0000746 {
747 zlog_err ("bgp_start peer's fd is negative value %d",
pauleb821182004-05-01 08:44:08 +0000748 peer->fd);
paul718e3742002-12-13 20:15:29 +0000749 return -1;
750 }
pauleb821182004-05-01 08:44:08 +0000751 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
752 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000753 break;
754 }
755 return 0;
756}
757
758/* Connect retry timer is expired when the peer status is Connect. */
paul94f2b392005-06-28 12:44:16 +0000759static int
paul718e3742002-12-13 20:15:29 +0000760bgp_reconnect (struct peer *peer)
761{
762 bgp_stop (peer);
763 bgp_start (peer);
764 return 0;
765}
766
paul94f2b392005-06-28 12:44:16 +0000767static int
paul718e3742002-12-13 20:15:29 +0000768bgp_fsm_open (struct peer *peer)
769{
770 /* Send keepalive and make keepalive timer */
771 bgp_keepalive_send (peer);
772
773 /* Reset holdtimer value. */
774 BGP_TIMER_OFF (peer->t_holdtime);
775
776 return 0;
777}
778
paul718e3742002-12-13 20:15:29 +0000779/* Keepalive send to peer. */
paul94f2b392005-06-28 12:44:16 +0000780static int
paul718e3742002-12-13 20:15:29 +0000781bgp_fsm_keepalive_expire (struct peer *peer)
782{
783 bgp_keepalive_send (peer);
784 return 0;
785}
786
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200787/* FSM error, unexpected event. This is error of BGP connection. So cut the
788 peer and change to Idle status. */
789static int
790bgp_fsm_event_error (struct peer *peer)
791{
792 plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
793 peer->host, LOOKUP (bgp_status_msg, peer->status));
794
795 return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
796}
797
paul718e3742002-12-13 20:15:29 +0000798/* Hold timer expire. This is error of BGP connection. So cut the
799 peer and change to Idle status. */
paul94f2b392005-06-28 12:44:16 +0000800static int
paul718e3742002-12-13 20:15:29 +0000801bgp_fsm_holdtime_expire (struct peer *peer)
802{
803 if (BGP_DEBUG (fsm, FSM))
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200804 plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
paul718e3742002-12-13 20:15:29 +0000805
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +0200806 return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
paul718e3742002-12-13 20:15:29 +0000807}
808
809/* Status goes to Established. Send keepalive packet then make first
810 update information. */
paul94f2b392005-06-28 12:44:16 +0000811static int
paul718e3742002-12-13 20:15:29 +0000812bgp_establish (struct peer *peer)
813{
814 struct bgp_notify *notify;
815 afi_t afi;
816 safi_t safi;
hasso93406d82005-02-02 14:40:33 +0000817 int nsf_af_count = 0;
paul718e3742002-12-13 20:15:29 +0000818
819 /* Reset capability open status flag. */
820 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
821 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
822
823 /* Clear last notification data. */
824 notify = &peer->notify;
825 if (notify->data)
826 XFREE (MTYPE_TMP, notify->data);
827 memset (notify, 0, sizeof (struct bgp_notify));
828
829 /* Clear start timer value to default. */
830 peer->v_start = BGP_INIT_START_TIMER;
831
832 /* Increment established count. */
833 peer->established++;
834 bgp_fsm_change_status (peer, Established);
paul848973c2003-08-13 00:32:49 +0000835
836 /* bgp log-neighbor-changes of neighbor Up */
837 if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
838 zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
839
hasso93406d82005-02-02 14:40:33 +0000840 /* graceful restart */
841 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
842 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +0400843 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +0000844 {
845 if (peer->afc_nego[afi][safi]
846 && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
847 && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
848 {
849 if (peer->nsf[afi][safi]
850 && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
851 bgp_clear_stale_route (peer, afi, safi);
852
853 peer->nsf[afi][safi] = 1;
854 nsf_af_count++;
855 }
856 else
857 {
858 if (peer->nsf[afi][safi])
859 bgp_clear_stale_route (peer, afi, safi);
860 peer->nsf[afi][safi] = 0;
861 }
862 }
863
864 if (nsf_af_count)
865 SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
866 else
867 {
868 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
869 if (peer->t_gr_stale)
870 {
871 BGP_TIMER_OFF (peer->t_gr_stale);
872 if (BGP_DEBUG (events, EVENTS))
873 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
874 }
875 }
876
877 if (peer->t_gr_restart)
878 {
879 BGP_TIMER_OFF (peer->t_gr_restart);
880 if (BGP_DEBUG (events, EVENTS))
881 zlog_debug ("%s graceful restart timer stopped", peer->host);
882 }
883
paul718e3742002-12-13 20:15:29 +0000884#ifdef HAVE_SNMP
885 bgpTrapEstablished (peer);
886#endif /* HAVE_SNMP */
887
888 /* Reset uptime, send keepalive, send current table. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300889 peer->uptime = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000890
891 /* Send route-refresh when ORF is enabled */
892 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
893 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
894 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
895 {
896 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
897 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
898 REFRESH_IMMEDIATE, 0);
899 else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
900 bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
901 REFRESH_IMMEDIATE, 0);
902 }
903
904 if (peer->v_keepalive)
905 bgp_keepalive_send (peer);
906
907 /* First update is deferred until ORF or ROUTE-REFRESH is received */
908 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
909 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
910 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
911 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
912 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
913 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
914
915 bgp_announce_route_all (peer);
916
917 BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
918
919 return 0;
920}
921
922/* Keepalive packet is received. */
paul94f2b392005-06-28 12:44:16 +0000923static int
paul718e3742002-12-13 20:15:29 +0000924bgp_fsm_keepalive (struct peer *peer)
925{
926 /* peer count update */
927 peer->keepalive_in++;
928
929 BGP_TIMER_OFF (peer->t_holdtime);
930 return 0;
931}
932
933/* Update packet is received. */
paul94f2b392005-06-28 12:44:16 +0000934static int
paul718e3742002-12-13 20:15:29 +0000935bgp_fsm_update (struct peer *peer)
936{
937 BGP_TIMER_OFF (peer->t_holdtime);
938 return 0;
939}
940
941/* This is empty event. */
paul94f2b392005-06-28 12:44:16 +0000942static int
paul718e3742002-12-13 20:15:29 +0000943bgp_ignore (struct peer *peer)
944{
945 if (BGP_DEBUG (fsm, FSM))
946 zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
947 return 0;
948}
David Lamparter6b0655a2014-06-04 06:53:35 +0200949
paul718e3742002-12-13 20:15:29 +0000950/* Finite State Machine structure */
Stephen Hemmingerfda1d3e2009-05-15 10:02:27 -0700951static const struct {
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800952 int (*func) (struct peer *);
paul718e3742002-12-13 20:15:29 +0000953 int next_state;
954} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] =
955{
956 {
957 /* Idle state: In Idle state, all events other than BGP_Start is
958 ignored. With BGP_Start event, finite state machine calls
959 bgp_start(). */
960 {bgp_start, Connect}, /* BGP_Start */
961 {bgp_stop, Idle}, /* BGP_Stop */
962 {bgp_stop, Idle}, /* TCP_connection_open */
963 {bgp_stop, Idle}, /* TCP_connection_closed */
964 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
965 {bgp_stop, Idle}, /* TCP_fatal_error */
966 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
967 {bgp_ignore, Idle}, /* Hold_Timer_expired */
968 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
969 {bgp_ignore, Idle}, /* Receive_OPEN_message */
970 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
971 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
972 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000973 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +0100974 {bgp_start, Connect}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +0000975 },
976 {
977 /* Connect */
978 {bgp_ignore, Connect}, /* BGP_Start */
979 {bgp_stop, Idle}, /* BGP_Stop */
980 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
981 {bgp_stop, Idle}, /* TCP_connection_closed */
982 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
983 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
984 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
985 {bgp_ignore, Idle}, /* Hold_Timer_expired */
986 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
987 {bgp_ignore, Idle}, /* Receive_OPEN_message */
988 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
989 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
990 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +0000991 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +0100992 {bgp_reconnect, Connect},/* NHT_Update */
paul718e3742002-12-13 20:15:29 +0000993 },
994 {
995 /* Active, */
996 {bgp_ignore, Active}, /* BGP_Start */
997 {bgp_stop, Idle}, /* BGP_Stop */
998 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
999 {bgp_stop, Idle}, /* TCP_connection_closed */
1000 {bgp_ignore, Active}, /* TCP_connection_open_failed */
1001 {bgp_ignore, Idle}, /* TCP_fatal_error */
1002 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
1003 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1004 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1005 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1006 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1007 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1008 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001009 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001010 {bgp_start, Connect}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001011 },
1012 {
1013 /* OpenSent, */
1014 {bgp_ignore, OpenSent}, /* BGP_Start */
1015 {bgp_stop, Idle}, /* BGP_Stop */
Paul Jakma536792c2007-06-22 19:11:14 +00001016 {bgp_stop, Active}, /* TCP_connection_open */
paul718e3742002-12-13 20:15:29 +00001017 {bgp_stop, Active}, /* TCP_connection_closed */
Paul Jakma536792c2007-06-22 19:11:14 +00001018 {bgp_stop, Active}, /* TCP_connection_open_failed */
1019 {bgp_stop, Active}, /* TCP_fatal_error */
paul718e3742002-12-13 20:15:29 +00001020 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1021 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1022 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1023 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
Leonid Rosenboim397b5bd2013-07-30 20:14:25 +02001024 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
1025 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
paul718e3742002-12-13 20:15:29 +00001026 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001027 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001028 {bgp_ignore, OpenSent}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001029 },
1030 {
1031 /* OpenConfirm, */
1032 {bgp_ignore, OpenConfirm}, /* BGP_Start */
1033 {bgp_stop, Idle}, /* BGP_Stop */
1034 {bgp_stop, Idle}, /* TCP_connection_open */
1035 {bgp_stop, Idle}, /* TCP_connection_closed */
1036 {bgp_stop, Idle}, /* TCP_connection_open_failed */
1037 {bgp_stop, Idle}, /* TCP_fatal_error */
1038 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1039 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1040 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
1041 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1042 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
1043 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1044 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
Paul Jakmaca058a32006-09-14 02:58:49 +00001045 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001046 {bgp_ignore, OpenConfirm}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001047 },
1048 {
1049 /* Established, */
Paul Jakmaca058a32006-09-14 02:58:49 +00001050 {bgp_ignore, Established}, /* BGP_Start */
1051 {bgp_stop, Clearing}, /* BGP_Stop */
1052 {bgp_stop, Clearing}, /* TCP_connection_open */
1053 {bgp_stop, Clearing}, /* TCP_connection_closed */
Steve Hill3117b5c2009-07-28 17:50:00 +01001054 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
Paul Jakmaca058a32006-09-14 02:58:49 +00001055 {bgp_stop, Clearing}, /* TCP_fatal_error */
Steve Hill3117b5c2009-07-28 17:50:00 +01001056 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001057 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
paul718e3742002-12-13 20:15:29 +00001058 {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
Paul Jakmaca058a32006-09-14 02:58:49 +00001059 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1060 {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
1061 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
1062 {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
1063 {bgp_ignore, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001064 {bgp_ignore, Established}, /* NHT_Update */
Paul Jakmaca058a32006-09-14 02:58:49 +00001065 },
1066 {
1067 /* Clearing, */
1068 {bgp_ignore, Clearing}, /* BGP_Start */
Steve Hill3117b5c2009-07-28 17:50:00 +01001069 {bgp_stop, Clearing}, /* BGP_Stop */
1070 {bgp_stop, Clearing}, /* TCP_connection_open */
1071 {bgp_stop, Clearing}, /* TCP_connection_closed */
1072 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1073 {bgp_stop, Clearing}, /* TCP_fatal_error */
1074 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1075 {bgp_stop, Clearing}, /* Hold_Timer_expired */
1076 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
1077 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1078 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
1079 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
1080 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
1081 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001082 {bgp_ignore, Clearing}, /* NHT_Update */
Paul Jakmaca058a32006-09-14 02:58:49 +00001083 },
1084 {
1085 /* Deleted, */
1086 {bgp_ignore, Deleted}, /* BGP_Start */
1087 {bgp_ignore, Deleted}, /* BGP_Stop */
1088 {bgp_ignore, Deleted}, /* TCP_connection_open */
1089 {bgp_ignore, Deleted}, /* TCP_connection_closed */
1090 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
1091 {bgp_ignore, Deleted}, /* TCP_fatal_error */
1092 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
1093 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
1094 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
1095 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
1096 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
1097 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
1098 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
1099 {bgp_ignore, Deleted}, /* Clearing_Completed */
Paul Jakma743dd422016-09-30 13:55:47 +01001100 {bgp_ignore, Deleted}, /* NHT_Update */
paul718e3742002-12-13 20:15:29 +00001101 },
1102};
1103
paulfd79ac92004-10-13 05:06:08 +00001104static const char *bgp_event_str[] =
paul718e3742002-12-13 20:15:29 +00001105{
1106 NULL,
1107 "BGP_Start",
1108 "BGP_Stop",
1109 "TCP_connection_open",
1110 "TCP_connection_closed",
1111 "TCP_connection_open_failed",
1112 "TCP_fatal_error",
1113 "ConnectRetry_timer_expired",
1114 "Hold_Timer_expired",
1115 "KeepAlive_timer_expired",
1116 "Receive_OPEN_message",
1117 "Receive_KEEPALIVE_message",
1118 "Receive_UPDATE_message",
Paul Jakmaca058a32006-09-14 02:58:49 +00001119 "Receive_NOTIFICATION_message",
1120 "Clearing_Completed",
Paul Jakma743dd422016-09-30 13:55:47 +01001121 "NHT_Update",
paul718e3742002-12-13 20:15:29 +00001122};
1123
1124/* Execute event process. */
1125int
1126bgp_event (struct thread *thread)
1127{
Paul Jakmaca058a32006-09-14 02:58:49 +00001128 int ret = 0;
paul718e3742002-12-13 20:15:29 +00001129 int event;
1130 int next;
1131 struct peer *peer;
1132
1133 peer = THREAD_ARG (thread);
1134 event = THREAD_VAL (thread);
1135
1136 /* Logging this event. */
1137 next = FSM [peer->status -1][event - 1].next_state;
1138
Paul Jakmaca058a32006-09-14 02:58:49 +00001139 if (BGP_DEBUG (fsm, FSM) && peer->status != next)
ajs8c2e2002004-12-08 20:08:54 +00001140 plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
paul718e3742002-12-13 20:15:29 +00001141 bgp_event_str[event],
1142 LOOKUP (bgp_status_msg, peer->status),
1143 LOOKUP (bgp_status_msg, next));
paul718e3742002-12-13 20:15:29 +00001144
1145 /* Call function. */
Paul Jakmaca058a32006-09-14 02:58:49 +00001146 if (FSM [peer->status -1][event - 1].func)
1147 ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
paul718e3742002-12-13 20:15:29 +00001148
1149 /* When function do not want proceed next job return -1. */
paul200df112005-06-01 11:17:05 +00001150 if (ret >= 0)
1151 {
1152 /* If status is changed. */
1153 if (next != peer->status)
Paul Jakmaf2c31ac2007-02-22 17:48:42 +00001154 bgp_fsm_change_status (peer, next);
Paul Jakma95fdcd82006-12-08 00:31:22 +00001155
paul200df112005-06-01 11:17:05 +00001156 /* Make sure timer is set. */
1157 bgp_timer_set (peer);
1158 }
1159
paul200df112005-06-01 11:17:05 +00001160 return ret;
paul718e3742002-12-13 20:15:29 +00001161}