]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_fsm.c
bgpd: stop pseudo-blocking in bgp_write
[mirror_frr.git] / bgpd / bgp_fsm.c
CommitLineData
d62a17ae 1/* BGP-4 Finite State Machine
896014f4
DL
2 * From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
3 * Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
23
24#include "linklist.h"
25#include "prefix.h"
718e3744 26#include "sockunion.h"
27#include "thread.h"
28#include "log.h"
29#include "stream.h"
30#include "memory.h"
31#include "plist.h"
f188f2c4 32#include "workqueue.h"
3f9c7369 33#include "queue.h"
039f3a34 34#include "filter.h"
4dcadbef 35#include "command.h"
718e3744 36
856ca177 37#include "lib/json.h"
718e3744 38#include "bgpd/bgpd.h"
39#include "bgpd/bgp_attr.h"
40#include "bgpd/bgp_debug.h"
41#include "bgpd/bgp_fsm.h"
42#include "bgpd/bgp_packet.h"
43#include "bgpd/bgp_network.h"
44#include "bgpd/bgp_route.h"
45#include "bgpd/bgp_dump.h"
46#include "bgpd/bgp_open.h"
f188f2c4 47#include "bgpd/bgp_advertise.h"
3f9c7369 48#include "bgpd/bgp_updgrp.h"
ffd0c037 49#include "bgpd/bgp_nht.h"
c43ed2e4 50#include "bgpd/bgp_bfd.h"
4a1ab8e4 51#include "bgpd/bgp_memory.h"
03014d48 52#include "bgpd/bgp_keepalives.h"
6b0655a2 53
d62a17ae 54DEFINE_HOOK(peer_backward_transition, (struct peer * peer), (peer))
55DEFINE_HOOK(peer_established, (struct peer * peer), (peer))
3012671f 56
6403814c
DS
57/* Definition of display strings corresponding to FSM events. This should be
58 * kept consistent with the events defined in bgpd.h
59 */
d62a17ae 60static const char *bgp_event_str[] = {
61 NULL,
62 "BGP_Start",
63 "BGP_Stop",
64 "TCP_connection_open",
65 "TCP_connection_closed",
66 "TCP_connection_open_failed",
67 "TCP_fatal_error",
68 "ConnectRetry_timer_expired",
69 "Hold_Timer_expired",
70 "KeepAlive_timer_expired",
71 "Receive_OPEN_message",
72 "Receive_KEEPALIVE_message",
73 "Receive_UPDATE_message",
74 "Receive_NOTIFICATION_message",
75 "Clearing_Completed",
6403814c
DS
76};
77
718e3744 78/* BGP FSM (finite state machine) has three types of functions. Type
79 one is thread functions. Type two is event functions. Type three
80 is FSM functions. Timer functions are set by bgp_timer_set
81 function. */
82
83/* BGP event function. */
d62a17ae 84int bgp_event(struct thread *);
718e3744 85
86/* BGP thread functions. */
d62a17ae 87static int bgp_start_timer(struct thread *);
88static int bgp_connect_timer(struct thread *);
89static int bgp_holdtime_timer(struct thread *);
718e3744 90
91/* BGP FSM functions. */
d62a17ae 92static int bgp_start(struct peer *);
718e3744 93
d62a17ae 94static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
1ff9a340 95{
d62a17ae 96 /* Copy stats over. These are only the pre-established state stats */
97 peer_dst->open_in += peer_src->open_in;
98 peer_dst->open_out += peer_src->open_out;
99 peer_dst->keepalive_in += peer_src->keepalive_in;
100 peer_dst->keepalive_out += peer_src->keepalive_out;
101 peer_dst->notify_in += peer_src->notify_in;
102 peer_dst->notify_out += peer_src->notify_out;
103 peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in;
104 peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out;
1ff9a340
DS
105}
106
d62a17ae 107static struct peer *peer_xfer_conn(struct peer *from_peer)
1ff9a340 108{
d62a17ae 109 struct peer *peer;
110 afi_t afi;
111 safi_t safi;
112 int fd;
113 int status, pstatus;
114 unsigned char last_evt, last_maj_evt;
115
116 assert(from_peer != NULL);
117
118 peer = from_peer->doppelganger;
119
120 if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
121 return from_peer;
122
123 if (bgp_debug_neighbor_events(peer))
124 zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
125 from_peer->host, from_peer, from_peer->fd, peer,
126 peer->fd);
127
d3ecc69e 128 peer_writes_off(peer);
d62a17ae 129 BGP_READ_OFF(peer->t_read);
d3ecc69e 130 peer_writes_off(from_peer);
d62a17ae 131 BGP_READ_OFF(from_peer->t_read);
132
133 BGP_TIMER_OFF(peer->t_routeadv);
134 BGP_TIMER_OFF(from_peer->t_routeadv);
135
136 fd = peer->fd;
137 peer->fd = from_peer->fd;
138 from_peer->fd = fd;
139 stream_reset(peer->ibuf);
d3ecc69e
QY
140
141 pthread_mutex_lock(&peer->obuf_mtx);
142 {
143 stream_fifo_clean(peer->obuf);
144 }
145 pthread_mutex_unlock(&peer->obuf_mtx);
146
147 pthread_mutex_lock(&from_peer->obuf_mtx);
148 {
149 stream_fifo_clean(from_peer->obuf);
150 }
151 pthread_mutex_unlock(&from_peer->obuf_mtx);
d62a17ae 152
153 peer->as = from_peer->as;
154 peer->v_holdtime = from_peer->v_holdtime;
155 peer->v_keepalive = from_peer->v_keepalive;
156 peer->routeadv = from_peer->routeadv;
157 peer->v_routeadv = from_peer->v_routeadv;
158 peer->v_gr_restart = from_peer->v_gr_restart;
159 peer->cap = from_peer->cap;
160 status = peer->status;
161 pstatus = peer->ostatus;
162 last_evt = peer->last_event;
163 last_maj_evt = peer->last_major_event;
164 peer->status = from_peer->status;
165 peer->ostatus = from_peer->ostatus;
166 peer->last_event = from_peer->last_event;
167 peer->last_major_event = from_peer->last_major_event;
168 from_peer->status = status;
169 from_peer->ostatus = pstatus;
170 from_peer->last_event = last_evt;
171 from_peer->last_major_event = last_maj_evt;
172 peer->remote_id = from_peer->remote_id;
173
174 if (from_peer->hostname != NULL) {
175 if (peer->hostname) {
176 XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
177 peer->hostname = NULL;
178 }
179
180 peer->hostname = from_peer->hostname;
181 from_peer->hostname = NULL;
182 }
183
184 if (from_peer->domainname != NULL) {
185 if (peer->domainname) {
186 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
187 peer->domainname = NULL;
188 }
189
190 peer->domainname = from_peer->domainname;
191 from_peer->domainname = NULL;
192 }
193
05c7a1cc
QY
194 FOREACH_AFI_SAFI (afi, safi) {
195 peer->af_flags[afi][safi] = from_peer->af_flags[afi][safi];
196 peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi];
197 peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
198 peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi];
199 peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi];
200 peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
201 peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
202 }
d62a17ae 203
204 if (bgp_getsockname(peer) < 0) {
205 zlog_err(
206 "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
207 (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
208 ? "accept"
209 : ""),
210 peer->host, peer->fd, from_peer->fd);
211 bgp_stop(peer);
212 bgp_stop(from_peer);
213 return NULL;
214 }
215 if (from_peer->status > Active) {
216 if (bgp_getsockname(from_peer) < 0) {
217 zlog_err(
218 "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
219 (CHECK_FLAG(from_peer->sflags,
220 PEER_STATUS_ACCEPT_PEER)
221 ? "accept"
222 : ""),
223 from_peer->host, from_peer->fd, peer->fd);
224 bgp_stop(from_peer);
225 from_peer = NULL;
226 }
227 }
228
229 BGP_READ_ON(peer->t_read, bgp_read, peer->fd);
d3ecc69e 230 peer_writes_on(peer);
d62a17ae 231
232 if (from_peer)
233 peer_xfer_stats(peer, from_peer);
234
235 return (peer);
1ff9a340
DS
236}
237
718e3744 238/* Hook function called after bgp event is occered. And vty's
239 neighbor command invoke this function after making neighbor
240 structure. */
d62a17ae 241void bgp_timer_set(struct peer *peer)
718e3744 242{
d62a17ae 243 switch (peer->status) {
244 case Idle:
245 /* First entry point of peer's finite state machine. In Idle
246 status start timer is on unless peer is shutdown or peer is
247 inactive. All other timer must be turned off */
248 if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)) {
249 BGP_TIMER_OFF(peer->t_start);
250 } else {
251 BGP_TIMER_ON(peer->t_start, bgp_start_timer,
252 peer->v_start);
253 }
254 BGP_TIMER_OFF(peer->t_connect);
255 BGP_TIMER_OFF(peer->t_holdtime);
03014d48 256 peer_keepalives_off(peer);
d62a17ae 257 BGP_TIMER_OFF(peer->t_routeadv);
258 break;
259
260 case Connect:
261 /* After start timer is expired, the peer moves to Connect
262 status. Make sure start timer is off and connect timer is
263 on. */
264 BGP_TIMER_OFF(peer->t_start);
265 BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
266 peer->v_connect);
267 BGP_TIMER_OFF(peer->t_holdtime);
03014d48 268 peer_keepalives_off(peer);
d62a17ae 269 BGP_TIMER_OFF(peer->t_routeadv);
270 break;
271
272 case Active:
273 /* Active is waiting connection from remote peer. And if
274 connect timer is expired, change status to Connect. */
275 BGP_TIMER_OFF(peer->t_start);
276 /* If peer is passive mode, do not set connect timer. */
277 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)
278 || CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
279 BGP_TIMER_OFF(peer->t_connect);
280 } else {
281 BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
282 peer->v_connect);
283 }
284 BGP_TIMER_OFF(peer->t_holdtime);
03014d48 285 peer_keepalives_off(peer);
d62a17ae 286 BGP_TIMER_OFF(peer->t_routeadv);
287 break;
288
289 case OpenSent:
290 /* OpenSent status. */
291 BGP_TIMER_OFF(peer->t_start);
292 BGP_TIMER_OFF(peer->t_connect);
293 if (peer->v_holdtime != 0) {
294 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
295 peer->v_holdtime);
296 } else {
297 BGP_TIMER_OFF(peer->t_holdtime);
298 }
03014d48 299 peer_keepalives_off(peer);
d62a17ae 300 BGP_TIMER_OFF(peer->t_routeadv);
301 break;
302
303 case OpenConfirm:
304 /* OpenConfirm status. */
305 BGP_TIMER_OFF(peer->t_start);
306 BGP_TIMER_OFF(peer->t_connect);
307
308 /* If the negotiated Hold Time value is zero, then the Hold Time
309 timer and KeepAlive timers are not started. */
310 if (peer->v_holdtime == 0) {
311 BGP_TIMER_OFF(peer->t_holdtime);
03014d48 312 peer_keepalives_off(peer);
d62a17ae 313 } else {
314 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
315 peer->v_holdtime);
03014d48 316 peer_keepalives_on(peer);
d62a17ae 317 }
318 BGP_TIMER_OFF(peer->t_routeadv);
319 break;
320
321 case Established:
322 /* In Established status start and connect timer is turned
323 off. */
324 BGP_TIMER_OFF(peer->t_start);
325 BGP_TIMER_OFF(peer->t_connect);
326
327 /* Same as OpenConfirm, if holdtime is zero then both holdtime
328 and keepalive must be turned off. */
329 if (peer->v_holdtime == 0) {
330 BGP_TIMER_OFF(peer->t_holdtime);
03014d48 331 peer_keepalives_off(peer);
d62a17ae 332 } else {
333 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
334 peer->v_holdtime);
03014d48 335 peer_keepalives_on(peer);
d62a17ae 336 }
337 break;
338 case Deleted:
339 BGP_TIMER_OFF(peer->t_gr_restart);
340 BGP_TIMER_OFF(peer->t_gr_stale);
341 BGP_TIMER_OFF(peer->t_pmax_restart);
342 /* fallthru */
343 case Clearing:
344 BGP_TIMER_OFF(peer->t_start);
345 BGP_TIMER_OFF(peer->t_connect);
346 BGP_TIMER_OFF(peer->t_holdtime);
03014d48 347 peer_keepalives_off(peer);
d62a17ae 348 BGP_TIMER_OFF(peer->t_routeadv);
349 break;
718e3744 350 }
718e3744 351}
352
353/* BGP start timer. This function set BGP_Start event to thread value
354 and process event. */
d62a17ae 355static int bgp_start_timer(struct thread *thread)
718e3744 356{
d62a17ae 357 struct peer *peer;
718e3744 358
d62a17ae 359 peer = THREAD_ARG(thread);
360 peer->t_start = NULL;
718e3744 361
d62a17ae 362 if (bgp_debug_neighbor_events(peer))
363 zlog_debug("%s [FSM] Timer (start timer expire).", peer->host);
718e3744 364
d62a17ae 365 THREAD_VAL(thread) = BGP_Start;
366 bgp_event(thread); /* bgp_event unlocks peer */
718e3744 367
d62a17ae 368 return 0;
718e3744 369}
370
371/* BGP connect retry timer. */
d62a17ae 372static int bgp_connect_timer(struct thread *thread)
718e3744 373{
d62a17ae 374 struct peer *peer;
375 int ret;
376
377 peer = THREAD_ARG(thread);
378 peer->t_connect = NULL;
379
380 if (bgp_debug_neighbor_events(peer))
381 zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
382
383 if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) {
384 bgp_stop(peer);
385 ret = -1;
386 } else {
387 THREAD_VAL(thread) = ConnectRetry_timer_expired;
388 bgp_event(thread); /* bgp_event unlocks peer */
389 ret = 0;
390 }
391
392 return ret;
718e3744 393}
394
395/* BGP holdtime timer. */
d62a17ae 396static int bgp_holdtime_timer(struct thread *thread)
718e3744 397{
d62a17ae 398 struct peer *peer;
718e3744 399
d62a17ae 400 peer = THREAD_ARG(thread);
401 peer->t_holdtime = NULL;
718e3744 402
d62a17ae 403 if (bgp_debug_neighbor_events(peer))
404 zlog_debug("%s [FSM] Timer (holdtime timer expire)",
405 peer->host);
718e3744 406
d62a17ae 407 THREAD_VAL(thread) = Hold_Timer_expired;
408 bgp_event(thread); /* bgp_event unlocks peer */
718e3744 409
d62a17ae 410 return 0;
718e3744 411}
412
d62a17ae 413int bgp_routeadv_timer(struct thread *thread)
718e3744 414{
d62a17ae 415 struct peer *peer;
718e3744 416
d62a17ae 417 peer = THREAD_ARG(thread);
418 peer->t_routeadv = NULL;
718e3744 419
d62a17ae 420 if (bgp_debug_neighbor_events(peer))
421 zlog_debug("%s [FSM] Timer (routeadv timer expire)",
422 peer->host);
718e3744 423
d62a17ae 424 peer->synctime = bgp_clock();
718e3744 425
d62a17ae 426 /* MRAI timer will be started again when FIFO is built, no need to
427 * do it here.
428 */
429 return 0;
718e3744 430}
431
e0701b79 432/* BGP Peer Down Cause */
d62a17ae 433const char *peer_down_str[] = {"",
434 "Router ID changed",
435 "Remote AS changed",
436 "Local AS change",
437 "Cluster ID changed",
438 "Confederation identifier changed",
439 "Confederation peer changed",
440 "RR client config change",
441 "RS client config change",
442 "Update source change",
443 "Address family activated",
444 "Admin. shutdown",
445 "User reset",
446 "BGP Notification received",
447 "BGP Notification send",
448 "Peer closed the session",
449 "Neighbor deleted",
450 "Peer-group add member",
451 "Peer-group delete member",
452 "Capability changed",
453 "Passive config change",
454 "Multihop config change",
455 "NSF peer closed the session",
456 "Intf peering v6only config change",
457 "BFD down received",
458 "Interface down",
459 "Neighbor address lost"};
460
461static int bgp_graceful_restart_timer_expire(struct thread *thread)
e0701b79 462{
d62a17ae 463 struct peer *peer;
464 afi_t afi;
465 safi_t safi;
466
467 peer = THREAD_ARG(thread);
468 peer->t_gr_restart = NULL;
469
470 /* NSF delete stale route */
471 for (afi = AFI_IP; afi < AFI_MAX; afi++)
a08ca0a7 472 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
d62a17ae 473 if (peer->nsf[afi][safi])
474 bgp_clear_stale_route(peer, afi, safi);
475
476 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
477 BGP_TIMER_OFF(peer->t_gr_stale);
478
479 if (bgp_debug_neighbor_events(peer)) {
480 zlog_debug("%s graceful restart timer expired", peer->host);
481 zlog_debug("%s graceful restart stalepath timer stopped",
482 peer->host);
483 }
93406d87 484
d62a17ae 485 bgp_timer_set(peer);
93406d87 486
d62a17ae 487 return 0;
93406d87 488}
489
d62a17ae 490static int bgp_graceful_stale_timer_expire(struct thread *thread)
93406d87 491{
d62a17ae 492 struct peer *peer;
493 afi_t afi;
494 safi_t safi;
93406d87 495
d62a17ae 496 peer = THREAD_ARG(thread);
497 peer->t_gr_stale = NULL;
93406d87 498
d62a17ae 499 if (bgp_debug_neighbor_events(peer))
500 zlog_debug("%s graceful restart stalepath timer expired",
501 peer->host);
93406d87 502
d62a17ae 503 /* NSF delete stale route */
504 for (afi = AFI_IP; afi < AFI_MAX; afi++)
a08ca0a7 505 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
d62a17ae 506 if (peer->nsf[afi][safi])
507 bgp_clear_stale_route(peer, afi, safi);
93406d87 508
d62a17ae 509 return 0;
93406d87 510}
511
d62a17ae 512static int bgp_update_delay_applicable(struct bgp *bgp)
f188f2c4 513{
d62a17ae 514 /* update_delay_over flag should be reset (set to 0) for any new
515 applicability of the update-delay during BGP process lifetime.
516 And it should be set after an occurence of the update-delay is
517 over)*/
518 if (!bgp->update_delay_over)
519 return 1;
520
521 return 0;
f188f2c4
DS
522}
523
d62a17ae 524int bgp_update_delay_active(struct bgp *bgp)
f188f2c4 525{
d62a17ae 526 if (bgp->t_update_delay)
527 return 1;
f188f2c4 528
d62a17ae 529 return 0;
f188f2c4
DS
530}
531
d62a17ae 532int bgp_update_delay_configured(struct bgp *bgp)
f188f2c4 533{
d62a17ae 534 if (bgp->v_update_delay)
535 return 1;
f188f2c4 536
d62a17ae 537 return 0;
f188f2c4
DS
538}
539
540/* Do the post-processing needed when bgp comes out of the read-only mode
541 on ending the update delay. */
d62a17ae 542void bgp_update_delay_end(struct bgp *bgp)
f188f2c4 543{
d62a17ae 544 THREAD_TIMER_OFF(bgp->t_update_delay);
545 THREAD_TIMER_OFF(bgp->t_establish_wait);
546
547 /* Reset update-delay related state */
548 bgp->update_delay_over = 1;
549 bgp->established = 0;
550 bgp->restarted_peers = 0;
551 bgp->implicit_eors = 0;
552 bgp->explicit_eors = 0;
553
554 quagga_timestamp(3, bgp->update_delay_end_time,
555 sizeof(bgp->update_delay_end_time));
556
557 /*
558 * Add an end-of-initial-update marker to the main process queues so
559 * that
560 * the route advertisement timer for the peers can be started. Also set
561 * the zebra and peer update hold flags. These flags are used to achieve
562 * three stages in the update-delay post processing:
563 * 1. Finish best-path selection for all the prefixes held on the
564 * queues.
565 * (routes in BGP are updated, and peers sync queues are populated
566 * too)
567 * 2. As the eoiu mark is reached in the bgp process routine, ship all
568 * the
569 * routes to zebra. With that zebra should see updates from BGP
570 * close
571 * to each other.
572 * 3. Unblock the peer update writes. With that peer update packing
573 * with
574 * the prefixes should be at its maximum.
575 */
576 bgp_add_eoiu_mark(bgp);
577 bgp->main_zebra_update_hold = 1;
578 bgp->main_peers_update_hold = 1;
579
580 /* Resume the queue processing. This should trigger the event that would
581 take
582 care of processing any work that was queued during the read-only
583 mode. */
584 work_queue_unplug(bm->process_main_queue);
f188f2c4
DS
585}
586
cb1faec9
DS
587/**
588 * see bgp_fsm.h
589 */
d62a17ae 590void bgp_start_routeadv(struct bgp *bgp)
cb1faec9 591{
d62a17ae 592 struct listnode *node, *nnode;
593 struct peer *peer;
cb1faec9 594
d62a17ae 595 zlog_info("bgp_start_routeadv(), update hold status %d",
596 bgp->main_peers_update_hold);
4a16ae86 597
d62a17ae 598 if (bgp->main_peers_update_hold)
599 return;
4a16ae86 600
d62a17ae 601 quagga_timestamp(3, bgp->update_delay_peers_resume_time,
602 sizeof(bgp->update_delay_peers_resume_time));
4a16ae86 603
d62a17ae 604 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
605 if (peer->status != Established)
606 continue;
607 BGP_TIMER_OFF(peer->t_routeadv);
608 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
609 }
cb1faec9
DS
610}
611
612/**
613 * see bgp_fsm.h
614 */
d62a17ae 615void bgp_adjust_routeadv(struct peer *peer)
cb1faec9 616{
d62a17ae 617 time_t nowtime = bgp_clock();
618 double diff;
619 unsigned long remain;
620
621 /* Bypass checks for special case of MRAI being 0 */
622 if (peer->v_routeadv == 0) {
623 /* Stop existing timer, just in case it is running for a
624 * different
625 * duration and schedule write thread immediately.
626 */
627 if (peer->t_routeadv)
628 BGP_TIMER_OFF(peer->t_routeadv);
629
630 peer->synctime = bgp_clock();
d62a17ae 631 return;
632 }
633
634
635 /*
636 * CASE I:
637 * If the last update was written more than MRAI back, expire the timer
638 * instantly so that we can send the update out sooner.
639 *
640 * <------- MRAI --------->
641 * |-----------------|-----------------------|
642 * <------------- m ------------>
643 * ^ ^ ^
644 * | | |
645 * | | current time
646 * | timer start
647 * last write
648 *
649 * m > MRAI
650 */
651 diff = difftime(nowtime, peer->last_update);
652 if (diff > (double)peer->v_routeadv) {
653 BGP_TIMER_OFF(peer->t_routeadv);
654 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
655 return;
656 }
657
658 /*
659 * CASE II:
660 * - Find when to expire the MRAI timer.
661 * If MRAI timer is not active, assume we can start it now.
662 *
663 * <------- MRAI --------->
664 * |------------|-----------------------|
665 * <-------- m ----------><----- r ----->
666 * ^ ^ ^
667 * | | |
668 * | | current time
669 * | timer start
670 * last write
671 *
672 * (MRAI - m) < r
673 */
674 if (peer->t_routeadv)
675 remain = thread_timer_remain_second(peer->t_routeadv);
676 else
677 remain = peer->v_routeadv;
678 diff = peer->v_routeadv - diff;
679 if (diff <= (double)remain) {
680 BGP_TIMER_OFF(peer->t_routeadv);
681 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff);
682 }
cb1faec9
DS
683}
684
d62a17ae 685static int bgp_maxmed_onstartup_applicable(struct bgp *bgp)
abc920f8 686{
d62a17ae 687 if (!bgp->maxmed_onstartup_over)
688 return 1;
abc920f8 689
d62a17ae 690 return 0;
abc920f8
DS
691}
692
d62a17ae 693int bgp_maxmed_onstartup_configured(struct bgp *bgp)
abc920f8 694{
d62a17ae 695 if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
696 return 1;
abc920f8 697
d62a17ae 698 return 0;
abc920f8
DS
699}
700
d62a17ae 701int bgp_maxmed_onstartup_active(struct bgp *bgp)
abc920f8 702{
d62a17ae 703 if (bgp->t_maxmed_onstartup)
704 return 1;
abc920f8 705
d62a17ae 706 return 0;
abc920f8
DS
707}
708
d62a17ae 709void bgp_maxmed_update(struct bgp *bgp)
abc920f8 710{
d62a17ae 711 u_char maxmed_active;
712 u_int32_t maxmed_value;
713
714 if (bgp->v_maxmed_admin) {
715 maxmed_active = 1;
716 maxmed_value = bgp->maxmed_admin_value;
717 } else if (bgp->t_maxmed_onstartup) {
718 maxmed_active = 1;
719 maxmed_value = bgp->maxmed_onstartup_value;
720 } else {
721 maxmed_active = 0;
722 maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
723 }
724
725 if (bgp->maxmed_active != maxmed_active
726 || bgp->maxmed_value != maxmed_value) {
727 bgp->maxmed_active = maxmed_active;
728 bgp->maxmed_value = maxmed_value;
729
730 update_group_announce(bgp);
731 }
abc920f8
DS
732}
733
734/* The maxmed onstartup timer expiry callback. */
d62a17ae 735static int bgp_maxmed_onstartup_timer(struct thread *thread)
abc920f8 736{
d62a17ae 737 struct bgp *bgp;
abc920f8 738
d62a17ae 739 zlog_info("Max med on startup ended - timer expired.");
abc920f8 740
d62a17ae 741 bgp = THREAD_ARG(thread);
742 THREAD_TIMER_OFF(bgp->t_maxmed_onstartup);
743 bgp->maxmed_onstartup_over = 1;
abc920f8 744
d62a17ae 745 bgp_maxmed_update(bgp);
abc920f8 746
d62a17ae 747 return 0;
abc920f8
DS
748}
749
d62a17ae 750static void bgp_maxmed_onstartup_begin(struct bgp *bgp)
abc920f8 751{
d62a17ae 752 /* Applicable only once in the process lifetime on the startup */
753 if (bgp->maxmed_onstartup_over)
754 return;
abc920f8 755
d62a17ae 756 zlog_info("Begin maxmed onstartup mode - timer %d seconds",
757 bgp->v_maxmed_onstartup);
abc920f8 758
d62a17ae 759 thread_add_timer(bm->master, bgp_maxmed_onstartup_timer, bgp,
760 bgp->v_maxmed_onstartup, &bgp->t_maxmed_onstartup);
abc920f8 761
d62a17ae 762 if (!bgp->v_maxmed_admin) {
763 bgp->maxmed_active = 1;
764 bgp->maxmed_value = bgp->maxmed_onstartup_value;
765 }
abc920f8 766
d62a17ae 767 /* Route announce to all peers should happen after this in
768 * bgp_establish() */
abc920f8
DS
769}
770
d62a17ae 771static void bgp_maxmed_onstartup_process_status_change(struct peer *peer)
abc920f8 772{
d62a17ae 773 if (peer->status == Established && !peer->bgp->established) {
774 bgp_maxmed_onstartup_begin(peer->bgp);
775 }
abc920f8
DS
776}
777
f188f2c4 778/* The update delay timer expiry callback. */
d62a17ae 779static int bgp_update_delay_timer(struct thread *thread)
f188f2c4 780{
d62a17ae 781 struct bgp *bgp;
f188f2c4 782
d62a17ae 783 zlog_info("Update delay ended - timer expired.");
f188f2c4 784
d62a17ae 785 bgp = THREAD_ARG(thread);
786 THREAD_TIMER_OFF(bgp->t_update_delay);
787 bgp_update_delay_end(bgp);
f188f2c4 788
d62a17ae 789 return 0;
f188f2c4
DS
790}
791
792/* The establish wait timer expiry callback. */
d62a17ae 793static int bgp_establish_wait_timer(struct thread *thread)
f188f2c4 794{
d62a17ae 795 struct bgp *bgp;
f188f2c4 796
d62a17ae 797 zlog_info("Establish wait - timer expired.");
f188f2c4 798
d62a17ae 799 bgp = THREAD_ARG(thread);
800 THREAD_TIMER_OFF(bgp->t_establish_wait);
801 bgp_check_update_delay(bgp);
f188f2c4 802
d62a17ae 803 return 0;
f188f2c4
DS
804}
805
806/* Steps to begin the update delay:
807 - initialize queues if needed
808 - stop the queue processing
809 - start the timer */
d62a17ae 810static void bgp_update_delay_begin(struct bgp *bgp)
f188f2c4 811{
d62a17ae 812 struct listnode *node, *nnode;
813 struct peer *peer;
f188f2c4 814
d62a17ae 815 /* Stop the processing of queued work. Enqueue shall continue */
816 work_queue_plug(bm->process_main_queue);
f188f2c4 817
d62a17ae 818 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
819 peer->update_delay_over = 0;
f188f2c4 820
d62a17ae 821 /* Start the update-delay timer */
822 thread_add_timer(bm->master, bgp_update_delay_timer, bgp,
823 bgp->v_update_delay, &bgp->t_update_delay);
f188f2c4 824
d62a17ae 825 if (bgp->v_establish_wait != bgp->v_update_delay)
826 thread_add_timer(bm->master, bgp_establish_wait_timer, bgp,
827 bgp->v_establish_wait, &bgp->t_establish_wait);
f188f2c4 828
d62a17ae 829 quagga_timestamp(3, bgp->update_delay_begin_time,
830 sizeof(bgp->update_delay_begin_time));
f188f2c4
DS
831}
832
d62a17ae 833static void bgp_update_delay_process_status_change(struct peer *peer)
f188f2c4 834{
d62a17ae 835 if (peer->status == Established) {
836 if (!peer->bgp->established++) {
837 bgp_update_delay_begin(peer->bgp);
838 zlog_info(
839 "Begin read-only mode - update-delay timer %d seconds",
840 peer->bgp->v_update_delay);
841 }
842 if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV))
843 bgp_update_restarted_peers(peer);
844 }
845 if (peer->ostatus == Established
846 && bgp_update_delay_active(peer->bgp)) {
847 /* Adjust the update-delay state to account for this flap.
848 NOTE: Intentionally skipping adjusting implicit_eors or
849 explicit_eors
850 counters. Extra sanity check in bgp_check_update_delay()
851 should
852 be enough to take care of any additive discrepancy in bgp eor
853 counters */
854 peer->bgp->established--;
855 peer->update_delay_over = 0;
856 }
f188f2c4
DS
857}
858
200df115 859/* Called after event occured, this function change status and reset
860 read/write and timer thread. */
d62a17ae 861void bgp_fsm_change_status(struct peer *peer, int status)
200df115 862{
1ff9a340 863
d62a17ae 864 bgp_dump_state(peer, peer->status, status);
865
866 /* Transition into Clearing or Deleted must /always/ clear all routes..
867 * (and must do so before actually changing into Deleted..
868 */
869 if (status >= Clearing) {
870 bgp_clear_route_all(peer);
871
872 /* If no route was queued for the clear-node processing,
873 * generate the
874 * completion event here. This is needed because if there are no
875 * routes
876 * to trigger the background clear-node thread, the event won't
877 * get
878 * generated and the peer would be stuck in Clearing. Note that
879 * this
880 * event is for the peer and helps the peer transition out of
881 * Clearing
882 * state; it should not be generated per (AFI,SAFI). The event
883 * is
884 * directly posted here without calling clear_node_complete() as
885 * we
886 * shouldn't do an extra unlock. This event will get processed
887 * after
888 * the state change that happens below, so peer will be in
889 * Clearing
890 * (or Deleted).
891 */
892 if (!work_queue_is_scheduled(peer->clear_node_queue))
893 BGP_EVENT_ADD(peer, Clearing_Completed);
894 }
895
896 /* Preserve old status and change into new status. */
897 peer->ostatus = peer->status;
898 peer->status = status;
899
900 /* Save event that caused status change. */
901 peer->last_major_event = peer->cur_event;
902
903 if (status == Established)
904 UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
905
906 /* If max-med processing is applicable, do the necessary. */
907 if (status == Established) {
908 if (bgp_maxmed_onstartup_configured(peer->bgp)
909 && bgp_maxmed_onstartup_applicable(peer->bgp))
910 bgp_maxmed_onstartup_process_status_change(peer);
911 else
912 peer->bgp->maxmed_onstartup_over = 1;
913 }
914
915 /* If update-delay processing is applicable, do the necessary. */
916 if (bgp_update_delay_configured(peer->bgp)
917 && bgp_update_delay_applicable(peer->bgp))
918 bgp_update_delay_process_status_change(peer);
919
920 if (bgp_debug_neighbor_events(peer))
921 zlog_debug("%s went from %s to %s", peer->host,
922 lookup_msg(bgp_status_msg, peer->ostatus, NULL),
923 lookup_msg(bgp_status_msg, peer->status, NULL));
200df115 924}
925
3117b5c4 926/* Flush the event queue and ensure the peer is shut down */
d62a17ae 927static int bgp_clearing_completed(struct peer *peer)
3117b5c4 928{
d62a17ae 929 int rc = bgp_stop(peer);
1ff9a340 930
d62a17ae 931 if (rc >= 0)
932 BGP_EVENT_FLUSH(peer);
3117b5c4 933
d62a17ae 934 return rc;
3117b5c4
SH
935}
936
718e3744 937/* Administrative BGP peer stop event. */
3117b5c4 938/* May be called multiple times for the same peer */
d62a17ae 939int bgp_stop(struct peer *peer)
718e3744 940{
d62a17ae 941 afi_t afi;
942 safi_t safi;
943 char orf_name[BUFSIZ];
944 int ret = 0;
945
946 if (peer_dynamic_neighbor(peer)
947 && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
948 if (bgp_debug_neighbor_events(peer))
949 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
950 peer_delete(peer);
951 return -1;
c22767d8 952 }
848973c7 953
d62a17ae 954 /* Can't do this in Clearing; events are used for state transitions */
955 if (peer->status != Clearing) {
956 /* Delete all existing events of the peer */
957 BGP_EVENT_FLUSH(peer);
93406d87 958 }
d62a17ae 959
960 /* Increment Dropped count. */
961 if (peer->status == Established) {
962 peer->dropped++;
963
964 /* bgp log-neighbor-changes of neighbor Down */
965 if (bgp_flag_check(peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
966 struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
967 zlog_info(
968 "%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s",
969 peer->host,
970 (peer->hostname) ? peer->hostname : "Unknown",
971 vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
972 : "Default")
973 : "",
974 peer_down_str[(int)peer->last_reset]);
975 }
976
977 /* graceful restart */
978 if (peer->t_gr_stale) {
979 BGP_TIMER_OFF(peer->t_gr_stale);
980 if (bgp_debug_neighbor_events(peer))
981 zlog_debug(
982 "%s graceful restart stalepath timer stopped",
983 peer->host);
984 }
985 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
986 if (bgp_debug_neighbor_events(peer)) {
987 zlog_debug(
988 "%s graceful restart timer started for %d sec",
989 peer->host, peer->v_gr_restart);
990 zlog_debug(
991 "%s graceful restart stalepath timer started for %d sec",
992 peer->host, peer->bgp->stalepath_time);
993 }
994 BGP_TIMER_ON(peer->t_gr_restart,
995 bgp_graceful_restart_timer_expire,
996 peer->v_gr_restart);
997 BGP_TIMER_ON(peer->t_gr_stale,
998 bgp_graceful_stale_timer_expire,
999 peer->bgp->stalepath_time);
1000 } else {
1001 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
1002
1003 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1004 for (safi = SAFI_UNICAST;
a08ca0a7 1005 safi <= SAFI_MPLS_VPN; safi++)
d62a17ae 1006 peer->nsf[afi][safi] = 0;
1007 }
1008
1009 /* set last reset time */
1010 peer->resettime = peer->uptime = bgp_clock();
1011
1012 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
1013 zlog_debug("%s remove from all update group",
1014 peer->host);
1015 update_group_remove_peer_afs(peer);
1016
1017 hook_call(peer_backward_transition, peer);
1018
1019 /* Reset peer synctime */
1020 peer->synctime = 0;
1021
1022 bgp_bfd_deregister_peer(peer);
93406d87 1023 }
93406d87 1024
d62a17ae 1025 /* Stop read and write threads when exists. */
1026 BGP_READ_OFF(peer->t_read);
d3ecc69e 1027 peer_writes_off(peer);
d62a17ae 1028
1029 /* Stop all timers. */
1030 BGP_TIMER_OFF(peer->t_start);
1031 BGP_TIMER_OFF(peer->t_connect);
1032 BGP_TIMER_OFF(peer->t_holdtime);
03014d48 1033 peer_keepalives_off(peer);
d62a17ae 1034 BGP_TIMER_OFF(peer->t_routeadv);
1035
1036 /* Stream reset. */
1037 peer->packet_size = 0;
1038
1039 /* Clear input and output buffer. */
1040 if (peer->ibuf)
1041 stream_reset(peer->ibuf);
1042 if (peer->work)
1043 stream_reset(peer->work);
d3ecc69e
QY
1044
1045 pthread_mutex_lock(&peer->obuf_mtx);
1046 {
1047 if (peer->obuf)
1048 stream_fifo_clean(peer->obuf);
1049 }
1050 pthread_mutex_unlock(&peer->obuf_mtx);
d62a17ae 1051
1052 /* Close of file descriptor. */
1053 if (peer->fd >= 0) {
1054 close(peer->fd);
1055 peer->fd = -1;
93406d87 1056 }
1057
05c7a1cc
QY
1058 FOREACH_AFI_SAFI (afi, safi) {
1059 /* Reset all negotiated variables */
1060 peer->afc_nego[afi][safi] = 0;
1061 peer->afc_adv[afi][safi] = 0;
1062 peer->afc_recv[afi][safi] = 0;
1063
1064 /* peer address family capability flags*/
1065 peer->af_cap[afi][safi] = 0;
1066
1067 /* peer address family status flags*/
1068 peer->af_sflags[afi][safi] = 0;
1069
1070 /* Received ORF prefix-filter */
1071 peer->orf_plist[afi][safi] = NULL;
1072
1073 if ((peer->status == OpenConfirm)
1074 || (peer->status == Established)) {
1075 /* ORF received prefix-filter pnt */
1076 sprintf(orf_name, "%s.%d.%d", peer->host, afi, safi);
1077 prefix_bgp_orf_remove_all(afi, orf_name);
d62a17ae 1078 }
05c7a1cc 1079 }
d62a17ae 1080
1081 /* Reset keepalive and holdtime */
d25e4efc 1082 if (PEER_OR_GROUP_TIMER_SET(peer)) {
d62a17ae 1083 peer->v_keepalive = peer->keepalive;
1084 peer->v_holdtime = peer->holdtime;
1085 } else {
1086 peer->v_keepalive = peer->bgp->default_keepalive;
1087 peer->v_holdtime = peer->bgp->default_holdtime;
1ff9a340 1088 }
d62a17ae 1089
1090 peer->update_time = 0;
1091
1092/* Until we are sure that there is no problem about prefix count
1093 this should be commented out.*/
718e3744 1094#if 0
1095 /* Reset prefix count */
1096 peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
1097 peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
cd1964ff 1098 peer->pcount[AFI_IP][SAFI_LABELED_UNICAST] = 0;
718e3744 1099 peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
1100 peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
1101 peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
cd1964ff 1102 peer->pcount[AFI_IP6][SAFI_LABELED_UNICAST] = 0;
718e3744 1103#endif /* 0 */
1104
d62a17ae 1105 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
1106 && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
1107 peer_delete(peer);
1108 ret = -1;
1109 } else {
1110 bgp_peer_conf_if_to_su_update(peer);
1111 }
1112
1113 return ret;
718e3744 1114}
1115
1116/* BGP peer is stoped by the error. */
d62a17ae 1117static int bgp_stop_with_error(struct peer *peer)
718e3744 1118{
d62a17ae 1119 /* Double start timer. */
1120 peer->v_start *= 2;
1121
1122 /* Overflow check. */
1123 if (peer->v_start >= (60 * 2))
1124 peer->v_start = (60 * 2);
1125
1126 if (peer_dynamic_neighbor(peer)) {
1127 if (bgp_debug_neighbor_events(peer))
1128 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
1129 peer_delete(peer);
1130 return -1;
1131 }
1132
1133 return (bgp_stop(peer));
718e3744 1134}
1135
397b5bde
LR
1136
1137/* something went wrong, send notify and tear down */
d62a17ae 1138static int bgp_stop_with_notify(struct peer *peer, u_char code, u_char sub_code)
397b5bde 1139{
d62a17ae 1140 /* Send notify to remote peer */
1141 bgp_notify_send(peer, code, sub_code);
1142
1143 if (peer_dynamic_neighbor(peer)) {
1144 if (bgp_debug_neighbor_events(peer))
1145 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
1146 peer_delete(peer);
1147 return -1;
1148 }
f14e6fdb 1149
d62a17ae 1150 /* Clear start timer value to default. */
1151 peer->v_start = BGP_INIT_START_TIMER;
397b5bde 1152
d62a17ae 1153 return (bgp_stop(peer));
397b5bde
LR
1154}
1155
07a16526
QY
1156/**
1157 * Determines whether a TCP session has successfully established for a peer and
1158 * events as appropriate.
1159 *
1160 * This function is called when setting up a new session. After connect() is
1161 * called on the peer's socket (in bgp_start()), the fd is passed to select()
1162 * to wait for connection success or failure. When select() returns, this
1163 * function is called to evaluate the result.
1164 */
1165static int bgp_connect_check(struct thread *thread)
1166{
1167 int status;
1168 socklen_t slen;
1169 int ret;
1170 struct peer *peer;
1171
1172 peer = THREAD_ARG(thread);
1173
1174 /* Check file descriptor. */
1175 slen = sizeof(status);
1176 ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *)&status,
1177 &slen);
1178
1179 /* If getsockopt is fail, this is fatal error. */
1180 if (ret < 0) {
1181 zlog_info("can't get sockopt for nonblocking connect");
1182 BGP_EVENT_ADD(peer, TCP_fatal_error);
1183 return -1;
1184 }
1185
1186 /* When status is 0 then TCP connection is established. */
1187 if (status == 0) {
1188 BGP_EVENT_ADD(peer, TCP_connection_open);
1189 return 1;
1190 } else {
1191 if (bgp_debug_neighbor_events(peer))
1192 zlog_debug("%s [Event] Connect failed (%s)", peer->host,
1193 safe_strerror(errno));
1194 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1195 return 0;
1196 }
1197}
397b5bde 1198
718e3744 1199/* TCP connection open. Next we send open message to remote peer. And
1200 add read thread for reading open message. */
d62a17ae 1201static int bgp_connect_success(struct peer *peer)
718e3744 1202{
d62a17ae 1203 if (peer->fd < 0) {
1204 zlog_err("bgp_connect_success peer's fd is negative value %d",
1205 peer->fd);
1206 bgp_stop(peer);
1207 return -1;
1208 }
1209
d3ecc69e
QY
1210 peer_writes_on(peer);
1211
d62a17ae 1212 if (bgp_getsockname(peer) < 0) {
1213 zlog_err("%s: bgp_getsockname(): failed for peer %s, fd %d",
1214 __FUNCTION__, peer->host, peer->fd);
1215 bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
1216 0); /* internal error */
1217 return -1;
1218 }
1219
1220 BGP_READ_ON(peer->t_read, bgp_read, peer->fd);
1221
1222 if (bgp_debug_neighbor_events(peer)) {
1223 char buf1[SU_ADDRSTRLEN];
1224
1225 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
1226 zlog_debug("%s open active, local address %s",
1227 peer->host,
1228 sockunion2str(peer->su_local, buf1,
1229 SU_ADDRSTRLEN));
1230 else
1231 zlog_debug("%s passive open", peer->host);
1232 }
1233
1234 bgp_open_send(peer);
1235
1236 return 0;
718e3744 1237}
1238
1239/* TCP connect fail */
d62a17ae 1240static int bgp_connect_fail(struct peer *peer)
718e3744 1241{
d62a17ae 1242 if (peer_dynamic_neighbor(peer)) {
1243 if (bgp_debug_neighbor_events(peer))
1244 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
1245 peer_delete(peer);
1246 return -1;
1247 }
1248
1249 return (bgp_stop(peer));
718e3744 1250}
1251
1252/* This function is the first starting point of all BGP connection. It
1253 try to connect to remote peer with non-blocking IO. */
d62a17ae 1254int bgp_start(struct peer *peer)
718e3744 1255{
d62a17ae 1256 int status;
1257 int connected = 0;
1258
1259 bgp_peer_conf_if_to_su_update(peer);
1260
1261 if (peer->su.sa.sa_family == AF_UNSPEC) {
1262 if (bgp_debug_neighbor_events(peer))
1263 zlog_debug(
1264 "%s [FSM] Unable to get neighbor's IP address, waiting...",
1265 peer->host);
1266 return -1;
1267 }
1268
1269 if (BGP_PEER_START_SUPPRESSED(peer)) {
1270 if (bgp_debug_neighbor_events(peer))
1271 zlog_err(
1272 "%s [FSM] Trying to start suppressed peer"
1273 " - this is never supposed to happen!",
1274 peer->host);
1275 return -1;
1276 }
1277
1278 /* Scrub some information that might be left over from a previous,
1279 * session
1280 */
1281 /* Connection information. */
1282 if (peer->su_local) {
1283 sockunion_free(peer->su_local);
1284 peer->su_local = NULL;
1285 }
1286
1287 if (peer->su_remote) {
1288 sockunion_free(peer->su_remote);
1289 peer->su_remote = NULL;
1290 }
1291
1292 /* Clear remote router-id. */
1293 peer->remote_id.s_addr = 0;
1294
1295 /* Clear peer capability flag. */
1296 peer->cap = 0;
1297
1298 /* If the peer is passive mode, force to move to Active mode. */
1299 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
1300 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1301 return 0;
1302 }
1303
1304 /* Register to be notified on peer up */
1305 if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
1306 && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
1307 && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
1308 connected = 1;
1309 else
1310 connected = 0;
1311
1312 if (!bgp_find_or_add_nexthop(peer->bgp,
1313 family2afi(peer->su.sa.sa_family), NULL,
1314 peer, connected)) {
1315#if defined(HAVE_CUMULUS)
1316 if (bgp_debug_neighbor_events(peer))
1317 zlog_debug("%s [FSM] Waiting for NHT", peer->host);
1318
1319 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1320 return 0;
b5826a12 1321#endif
718e3744 1322 }
d62a17ae 1323
1324 status = bgp_connect(peer);
1325
1326 switch (status) {
1327 case connect_error:
1328 if (bgp_debug_neighbor_events(peer))
1329 zlog_debug("%s [FSM] Connect error", peer->host);
1330 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1331 break;
1332 case connect_success:
1333 if (bgp_debug_neighbor_events(peer))
1334 zlog_debug(
1335 "%s [FSM] Connect immediately success, fd %d",
1336 peer->host, peer->fd);
1337 BGP_EVENT_ADD(peer, TCP_connection_open);
1338 break;
1339 case connect_in_progress:
1340 /* To check nonblocking connect, we wait until socket is
1341 readable or writable. */
1342 if (bgp_debug_neighbor_events(peer))
1343 zlog_debug(
1344 "%s [FSM] Non blocking connect waiting result, fd %d",
1345 peer->host, peer->fd);
1346 if (peer->fd < 0) {
1347 zlog_err("bgp_start peer's fd is negative value %d",
1348 peer->fd);
1349 return -1;
1350 }
07a16526
QY
1351 // when the socket becomes ready (or fails to connect),
1352 // bgp_connect_check
1353 // will be called.
1354 thread_add_read(bm->master, bgp_connect_check, peer, peer->fd);
d62a17ae 1355 break;
1356 }
1357 return 0;
718e3744 1358}
1359
1360/* Connect retry timer is expired when the peer status is Connect. */
d62a17ae 1361static int bgp_reconnect(struct peer *peer)
718e3744 1362{
d62a17ae 1363 if (bgp_stop(peer) < 0)
1364 return -1;
1ff9a340 1365
d62a17ae 1366 bgp_start(peer);
1367 return 0;
718e3744 1368}
1369
d62a17ae 1370static int bgp_fsm_open(struct peer *peer)
718e3744 1371{
d62a17ae 1372 /* Send keepalive and make keepalive timer */
1373 bgp_keepalive_send(peer);
718e3744 1374
d62a17ae 1375 /* Reset holdtimer value. */
1376 BGP_TIMER_OFF(peer->t_holdtime);
718e3744 1377
d62a17ae 1378 return 0;
718e3744 1379}
1380
397b5bde
LR
1381/* FSM error, unexpected event. This is error of BGP connection. So cut the
1382 peer and change to Idle status. */
d62a17ae 1383static int bgp_fsm_event_error(struct peer *peer)
397b5bde 1384{
d62a17ae 1385 zlog_err("%s [FSM] unexpected packet received in state %s", peer->host,
1386 lookup_msg(bgp_status_msg, peer->status, NULL));
397b5bde 1387
d62a17ae 1388 return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, 0);
397b5bde
LR
1389}
1390
718e3744 1391/* Hold timer expire. This is error of BGP connection. So cut the
1392 peer and change to Idle status. */
d62a17ae 1393static int bgp_fsm_holdtime_expire(struct peer *peer)
718e3744 1394{
d62a17ae 1395 if (bgp_debug_neighbor_events(peer))
1396 zlog_debug("%s [FSM] Hold timer expire", peer->host);
718e3744 1397
d62a17ae 1398 return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0);
718e3744 1399}
1400
1401/* Status goes to Established. Send keepalive packet then make first
1402 update information. */
d62a17ae 1403static int bgp_establish(struct peer *peer)
718e3744 1404{
d62a17ae 1405 afi_t afi;
1406 safi_t safi;
1407 int nsf_af_count = 0;
1408 int ret = 0;
1409 struct peer *other;
1410
1411 other = peer->doppelganger;
1412 peer = peer_xfer_conn(peer);
1413 if (!peer) {
1414 zlog_err("%%Neighbor failed in xfer_conn");
1415 return -1;
93406d87 1416 }
93406d87 1417
d62a17ae 1418 if (other == peer)
9d303b37
DL
1419 ret =
1420 1; /* bgp_establish specific code when xfer_conn
1421 happens. */
d62a17ae 1422
1423 /* Reset capability open status flag. */
1424 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
1425 SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1426
1427 /* Clear start timer value to default. */
1428 peer->v_start = BGP_INIT_START_TIMER;
1429
1430 /* Increment established count. */
1431 peer->established++;
1432 bgp_fsm_change_status(peer, Established);
1433
1434 /* bgp log-neighbor-changes of neighbor Up */
1435 if (bgp_flag_check(peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
1436 struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
1437 zlog_info("%%ADJCHANGE: neighbor %s(%s) in vrf %s Up",
1438 peer->host,
1439 (peer->hostname) ? peer->hostname : "Unknown",
1440 vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
1441 : "Default")
1442 : "");
1443 }
1444 /* assign update-group/subgroup */
1445 update_group_adjust_peer_afs(peer);
1446
1447 /* graceful restart */
1448 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
1449 for (afi = AFI_IP; afi < AFI_MAX; afi++)
a08ca0a7 1450 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++) {
d62a17ae 1451 if (peer->afc_nego[afi][safi]
1452 && CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV)
1453 && CHECK_FLAG(peer->af_cap[afi][safi],
1454 PEER_CAP_RESTART_AF_RCV)) {
1455 if (peer->nsf[afi][safi]
1456 && !CHECK_FLAG(
1457 peer->af_cap[afi][safi],
1458 PEER_CAP_RESTART_AF_PRESERVE_RCV))
1459 bgp_clear_stale_route(peer, afi, safi);
1460
1461 peer->nsf[afi][safi] = 1;
1462 nsf_af_count++;
1463 } else {
1464 if (peer->nsf[afi][safi])
1465 bgp_clear_stale_route(peer, afi, safi);
1466 peer->nsf[afi][safi] = 0;
1467 }
1468 }
1469
1470 if (nsf_af_count)
1471 SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
1472 else {
1473 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
1474 if (peer->t_gr_stale) {
1475 BGP_TIMER_OFF(peer->t_gr_stale);
1476 if (bgp_debug_neighbor_events(peer))
1477 zlog_debug(
1478 "%s graceful restart stalepath timer stopped",
1479 peer->host);
1480 }
1481 }
93406d87 1482
d62a17ae 1483 if (peer->t_gr_restart) {
1484 BGP_TIMER_OFF(peer->t_gr_restart);
1485 if (bgp_debug_neighbor_events(peer))
1486 zlog_debug("%s graceful restart timer stopped",
1487 peer->host);
1488 }
718e3744 1489
d62a17ae 1490 hook_call(peer_established, peer);
1491
1492 /* Reset uptime, send keepalive, send current table. */
1493 peer->uptime = bgp_clock();
1494
1495 /* Send route-refresh when ORF is enabled */
05c7a1cc
QY
1496 FOREACH_AFI_SAFI (afi, safi) {
1497 if (CHECK_FLAG(peer->af_cap[afi][safi],
1498 PEER_CAP_ORF_PREFIX_SM_ADV)) {
d62a17ae 1499 if (CHECK_FLAG(peer->af_cap[afi][safi],
05c7a1cc
QY
1500 PEER_CAP_ORF_PREFIX_RM_RCV))
1501 bgp_route_refresh_send(peer, afi, safi,
1502 ORF_TYPE_PREFIX,
1503 REFRESH_IMMEDIATE, 0);
1504 else if (CHECK_FLAG(peer->af_cap[afi][safi],
1505 PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
1506 bgp_route_refresh_send(peer, afi, safi,
1507 ORF_TYPE_PREFIX_OLD,
1508 REFRESH_IMMEDIATE, 0);
1509 }
1510 }
d62a17ae 1511
1512 /* First update is deferred until ORF or ROUTE-REFRESH is received */
05c7a1cc
QY
1513 FOREACH_AFI_SAFI (afi, safi) {
1514 if (CHECK_FLAG(peer->af_cap[afi][safi],
1515 PEER_CAP_ORF_PREFIX_RM_ADV))
d62a17ae 1516 if (CHECK_FLAG(peer->af_cap[afi][safi],
05c7a1cc
QY
1517 PEER_CAP_ORF_PREFIX_SM_RCV)
1518 || CHECK_FLAG(peer->af_cap[afi][safi],
1519 PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
1520 SET_FLAG(peer->af_sflags[afi][safi],
1521 PEER_STATUS_ORF_WAIT_REFRESH);
1522 }
d62a17ae 1523
1524 bgp_announce_peer(peer);
1525
1526 /* Start the route advertisement timer to send updates to the peer - if
1527 * BGP
1528 * is not in read-only mode. If it is, the timer will be started at the
1529 * end
1530 * of read-only mode.
1531 */
1532 if (!bgp_update_delay_active(peer->bgp)) {
1533 BGP_TIMER_OFF(peer->t_routeadv);
1534 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
1535 }
718e3744 1536
d62a17ae 1537 if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
1538 if (bgp_debug_neighbor_events(peer))
1539 zlog_debug(
1540 "[Event] Deleting stub connection for peer %s",
1541 peer->host);
1542
1543 if (peer->doppelganger->status > Active)
1544 bgp_notify_send(peer->doppelganger, BGP_NOTIFY_CEASE,
1545 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
1546 else
1547 peer_delete(peer->doppelganger);
718e3744 1548 }
1549
d62a17ae 1550 bgp_bfd_register_peer(peer);
1551 return ret;
718e3744 1552}
1553
1554/* Keepalive packet is received. */
d62a17ae 1555static int bgp_fsm_keepalive(struct peer *peer)
718e3744 1556{
d62a17ae 1557 bgp_update_implicit_eors(peer);
f188f2c4 1558
d62a17ae 1559 /* peer count update */
1560 peer->keepalive_in++;
718e3744 1561
d62a17ae 1562 BGP_TIMER_OFF(peer->t_holdtime);
1563 return 0;
718e3744 1564}
1565
1566/* Update packet is received. */
d62a17ae 1567static int bgp_fsm_update(struct peer *peer)
718e3744 1568{
d62a17ae 1569 BGP_TIMER_OFF(peer->t_holdtime);
1570 return 0;
718e3744 1571}
1572
1573/* This is empty event. */
d62a17ae 1574static int bgp_ignore(struct peer *peer)
718e3744 1575{
d62a17ae 1576 zlog_err(
1577 "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
1578 peer->host, bgp_event_str[peer->cur_event],
1579 lookup_msg(bgp_status_msg, peer->status, NULL),
1580 bgp_event_str[peer->last_event],
1581 bgp_event_str[peer->last_major_event], peer->fd);
1582 return 0;
718e3744 1583}
6b0655a2 1584
6403814c 1585/* This is to handle unexpected events.. */
d62a17ae 1586static int bgp_fsm_exeption(struct peer *peer)
6403814c 1587{
d62a17ae 1588 zlog_err(
1589 "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
1590 peer->host, bgp_event_str[peer->cur_event],
1591 lookup_msg(bgp_status_msg, peer->status, NULL),
1592 bgp_event_str[peer->last_event],
1593 bgp_event_str[peer->last_major_event], peer->fd);
1594 return (bgp_stop(peer));
6403814c
DS
1595}
1596
d62a17ae 1597void bgp_fsm_nht_update(struct peer *peer, int valid)
fc9a856f 1598{
d62a17ae 1599 if (!peer)
1600 return;
1601
1602 switch (peer->status) {
1603 case Idle:
1604 if (valid)
1605 BGP_EVENT_ADD(peer, BGP_Start);
1606 break;
1607 case Connect:
1608 if (!valid) {
1609 BGP_TIMER_OFF(peer->t_connect);
1610 BGP_EVENT_ADD(peer, TCP_fatal_error);
1611 }
1612 break;
1613 case Active:
1614 if (valid) {
1615 BGP_TIMER_OFF(peer->t_connect);
1616 BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
1617 }
1618 break;
1619 case OpenSent:
1620 case OpenConfirm:
1621 case Established:
1622 if (!valid && (peer->gtsm_hops == 1))
1623 BGP_EVENT_ADD(peer, TCP_fatal_error);
1624 case Clearing:
1625 case Deleted:
1626 default:
1627 break;
fc9a856f 1628 }
fc9a856f
DS
1629}
1630
1631
718e3744 1632/* Finite State Machine structure */
fda1d3e0 1633static const struct {
d62a17ae 1634 int (*func)(struct peer *);
1635 int next_state;
1636} FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = {
1637 {
1638 /* Idle state: In Idle state, all events other than BGP_Start is
1639 ignored. With BGP_Start event, finite state machine calls
1640 bgp_start(). */
1641 {bgp_start, Connect}, /* BGP_Start */
1642 {bgp_stop, Idle}, /* BGP_Stop */
1643 {bgp_stop, Idle}, /* TCP_connection_open */
1644 {bgp_stop, Idle}, /* TCP_connection_closed */
1645 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
1646 {bgp_stop, Idle}, /* TCP_fatal_error */
1647 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
1648 {bgp_ignore, Idle}, /* Hold_Timer_expired */
1649 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
1650 {bgp_ignore, Idle}, /* Receive_OPEN_message */
1651 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
1652 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
1653 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
1654 {bgp_ignore, Idle}, /* Clearing_Completed */
1655 },
1656 {
1657 /* Connect */
1658 {bgp_ignore, Connect}, /* BGP_Start */
1659 {bgp_stop, Idle}, /* BGP_Stop */
1660 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1661 {bgp_stop, Idle}, /* TCP_connection_closed */
1662 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
1663 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
1664 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
1665 {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
1666 {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
1667 {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
1668 {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
1669 {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
1670 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
1671 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
1672 },
1673 {
1674 /* Active, */
1675 {bgp_ignore, Active}, /* BGP_Start */
1676 {bgp_stop, Idle}, /* BGP_Stop */
1677 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
1678 {bgp_stop, Idle}, /* TCP_connection_closed */
1679 {bgp_ignore, Active}, /* TCP_connection_open_failed */
1680 {bgp_fsm_exeption, Idle}, /* TCP_fatal_error */
1681 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
1682 {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
1683 {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
1684 {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
1685 {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
1686 {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
1687 {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */
1688 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
1689 },
1690 {
1691 /* OpenSent, */
1692 {bgp_ignore, OpenSent}, /* BGP_Start */
1693 {bgp_stop, Idle}, /* BGP_Stop */
1694 {bgp_stop, Active}, /* TCP_connection_open */
1695 {bgp_stop, Active}, /* TCP_connection_closed */
1696 {bgp_stop, Active}, /* TCP_connection_open_failed */
1697 {bgp_stop, Active}, /* TCP_fatal_error */
1698 {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
1699 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1700 {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
1701 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
1702 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
1703 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
1704 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
1705 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
1706 },
1707 {
1708 /* OpenConfirm, */
1709 {bgp_ignore, OpenConfirm}, /* BGP_Start */
1710 {bgp_stop, Idle}, /* BGP_Stop */
1711 {bgp_stop, Idle}, /* TCP_connection_open */
1712 {bgp_stop, Idle}, /* TCP_connection_closed */
1713 {bgp_stop, Idle}, /* TCP_connection_open_failed */
1714 {bgp_stop, Idle}, /* TCP_fatal_error */
1715 {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
1716 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
1717 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
1718 {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
1719 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
1720 {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
1721 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
1722 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
1723 },
1724 {
1725 /* Established, */
1726 {bgp_ignore, Established}, /* BGP_Start */
1727 {bgp_stop, Clearing}, /* BGP_Stop */
1728 {bgp_stop, Clearing}, /* TCP_connection_open */
1729 {bgp_stop, Clearing}, /* TCP_connection_closed */
1730 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1731 {bgp_stop, Clearing}, /* TCP_fatal_error */
1732 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1733 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
03014d48
QY
1734 {bgp_ignore, Established}, /* KeepAlive_timer_expired */
1735 {bgp_stop, Clearing}, /* Receive_OPEN_message */
d62a17ae 1736 {bgp_fsm_keepalive,
1737 Established}, /* Receive_KEEPALIVE_message */
1738 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
1739 {bgp_stop_with_error,
1740 Clearing}, /* Receive_NOTIFICATION_message */
1741 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
1742 },
1743 {
1744 /* Clearing, */
1745 {bgp_ignore, Clearing}, /* BGP_Start */
1746 {bgp_stop, Clearing}, /* BGP_Stop */
1747 {bgp_stop, Clearing}, /* TCP_connection_open */
1748 {bgp_stop, Clearing}, /* TCP_connection_closed */
1749 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
1750 {bgp_stop, Clearing}, /* TCP_fatal_error */
1751 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
1752 {bgp_stop, Clearing}, /* Hold_Timer_expired */
1753 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
1754 {bgp_stop, Clearing}, /* Receive_OPEN_message */
1755 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
1756 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
1757 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
1758 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
1759 },
1760 {
1761 /* Deleted, */
1762 {bgp_ignore, Deleted}, /* BGP_Start */
1763 {bgp_ignore, Deleted}, /* BGP_Stop */
1764 {bgp_ignore, Deleted}, /* TCP_connection_open */
1765 {bgp_ignore, Deleted}, /* TCP_connection_closed */
1766 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
1767 {bgp_ignore, Deleted}, /* TCP_fatal_error */
1768 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
1769 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
1770 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
1771 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
1772 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
1773 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
1774 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
1775 {bgp_ignore, Deleted}, /* Clearing_Completed */
1776 },
718e3744 1777};
1778
718e3744 1779/* Execute event process. */
d62a17ae 1780int bgp_event(struct thread *thread)
718e3744 1781{
d62a17ae 1782 int event;
1783 struct peer *peer;
1784 int ret;
718e3744 1785
d62a17ae 1786 peer = THREAD_ARG(thread);
1787 event = THREAD_VAL(thread);
718e3744 1788
d62a17ae 1789 ret = bgp_event_update(peer, event);
1ff9a340 1790
d62a17ae 1791 return (ret);
1ff9a340
DS
1792}
1793
d62a17ae 1794int bgp_event_update(struct peer *peer, int event)
1ff9a340 1795{
d62a17ae 1796 int next;
1797 int ret = 0;
1798 struct peer *other;
1799 int passive_conn = 0;
1800 int dyn_nbr;
1801
1802 other = peer->doppelganger;
1803 passive_conn =
1804 (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0;
1805 dyn_nbr = peer_dynamic_neighbor(peer);
1806
1807 /* Logging this event. */
1808 next = FSM[peer->status - 1][event - 1].next_state;
1809
1810 if (bgp_debug_neighbor_events(peer) && peer->status != next)
1811 zlog_debug("%s [FSM] %s (%s->%s), fd %d", peer->host,
1812 bgp_event_str[event],
1813 lookup_msg(bgp_status_msg, peer->status, NULL),
1814 lookup_msg(bgp_status_msg, next, NULL), peer->fd);
1815
1816 peer->last_event = peer->cur_event;
1817 peer->cur_event = event;
1818
1819 /* Call function. */
1820 if (FSM[peer->status - 1][event - 1].func)
1821 ret = (*(FSM[peer->status - 1][event - 1].func))(peer);
1822
1823 /* When function do not want proceed next job return -1. */
1824 if (ret >= 0) {
1825 if (ret == 1 && next == Established) {
1826 /* The case when doppelganger swap accurred in
1827 bgp_establish.
1828 Update the peer pointer accordingly */
1829 peer = other;
1830 }
1831
1832 /* If status is changed. */
1833 if (next != peer->status)
1834 bgp_fsm_change_status(peer, next);
1835
1836 /* Make sure timer is set. */
1837 bgp_timer_set(peer);
1838
1839 } else if (!dyn_nbr && !passive_conn && peer->bgp) {
1840 /* If we got a return value of -1, that means there was an
1841 * error, restart
1842 * the FSM. If the peer structure was deleted
1843 */
1844 zlog_err(
1845 "%s [FSM] Failure handling event %s in state %s, "
1846 "prior events %s, %s, fd %d",
1847 peer->host, bgp_event_str[peer->cur_event],
1848 lookup_msg(bgp_status_msg, peer->status, NULL),
1849 bgp_event_str[peer->last_event],
1850 bgp_event_str[peer->last_major_event], peer->fd);
1851 bgp_stop(peer);
1852 bgp_fsm_change_status(peer, Idle);
1853 bgp_timer_set(peer);
1854 }
1855 return ret;
718e3744 1856}