]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_fsm.c
Merge pull request #10245 from anlancs/fix-spell-error
[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"
74ffbfe6 30#include "ringbuf.h"
718e3744 31#include "memory.h"
32#include "plist.h"
f188f2c4 33#include "workqueue.h"
3f9c7369 34#include "queue.h"
039f3a34 35#include "filter.h"
4dcadbef 36#include "command.h"
02705213 37#include "lib_errors.h"
8c48b3b6 38#include "zclient.h"
856ca177 39#include "lib/json.h"
718e3744 40#include "bgpd/bgpd.h"
41#include "bgpd/bgp_attr.h"
42#include "bgpd/bgp_debug.h"
14454c9f 43#include "bgpd/bgp_errors.h"
718e3744 44#include "bgpd/bgp_fsm.h"
45#include "bgpd/bgp_packet.h"
46#include "bgpd/bgp_network.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_dump.h"
49#include "bgpd/bgp_open.h"
f188f2c4 50#include "bgpd/bgp_advertise.h"
3f9c7369 51#include "bgpd/bgp_updgrp.h"
ffd0c037 52#include "bgpd/bgp_nht.h"
c43ed2e4 53#include "bgpd/bgp_bfd.h"
4a1ab8e4 54#include "bgpd/bgp_memory.h"
03014d48 55#include "bgpd/bgp_keepalives.h"
56257a44 56#include "bgpd/bgp_io.h"
c42eab4b 57#include "bgpd/bgp_zebra.h"
3742de8d 58#include "bgpd/bgp_vty.h"
6b0655a2 59
8451921b
DL
60DEFINE_HOOK(peer_backward_transition, (struct peer * peer), (peer));
61DEFINE_HOOK(peer_status_changed, (struct peer * peer), (peer));
3742de8d 62
6403814c
DS
63/* Definition of display strings corresponding to FSM events. This should be
64 * kept consistent with the events defined in bgpd.h
65 */
2b64873d 66static const char *const bgp_event_str[] = {
d62a17ae 67 NULL,
68 "BGP_Start",
69 "BGP_Stop",
70 "TCP_connection_open",
6c537a18 71 "TCP_connection_open_w_delay",
d62a17ae 72 "TCP_connection_closed",
73 "TCP_connection_open_failed",
74 "TCP_fatal_error",
75 "ConnectRetry_timer_expired",
76 "Hold_Timer_expired",
77 "KeepAlive_timer_expired",
6c537a18 78 "DelayOpen_timer_expired",
d62a17ae 79 "Receive_OPEN_message",
80 "Receive_KEEPALIVE_message",
81 "Receive_UPDATE_message",
82 "Receive_NOTIFICATION_message",
83 "Clearing_Completed",
6403814c
DS
84};
85
718e3744 86/* BGP FSM (finite state machine) has three types of functions. Type
87 one is thread functions. Type two is event functions. Type three
88 is FSM functions. Timer functions are set by bgp_timer_set
89 function. */
90
91/* BGP event function. */
d62a17ae 92int bgp_event(struct thread *);
718e3744 93
94/* BGP thread functions. */
d62a17ae 95static int bgp_start_timer(struct thread *);
96static int bgp_connect_timer(struct thread *);
97static int bgp_holdtime_timer(struct thread *);
6c537a18 98static int bgp_delayopen_timer(struct thread *);
718e3744 99
100/* BGP FSM functions. */
d62a17ae 101static int bgp_start(struct peer *);
718e3744 102
e2d3a909 103/* Register peer with NHT */
996319e6 104int bgp_peer_reg_with_nht(struct peer *peer)
e2d3a909 105{
106 int connected = 0;
107
c8d6f0d6 108 if (peer->sort == BGP_PEER_EBGP && peer->ttl == BGP_DEFAULT_TTL
e2d3a909 109 && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6 110 && !CHECK_FLAG(peer->bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
e2d3a909 111 connected = 1;
112
654a5978
PG
113 return bgp_find_or_add_nexthop(
114 peer->bgp, peer->bgp, family2afi(peer->su.sa.sa_family),
115 SAFI_UNICAST, NULL, peer, connected, NULL);
e2d3a909 116}
117
d62a17ae 118static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
1ff9a340 119{
d62a17ae 120 /* Copy stats over. These are only the pre-established state stats */
121 peer_dst->open_in += peer_src->open_in;
122 peer_dst->open_out += peer_src->open_out;
123 peer_dst->keepalive_in += peer_src->keepalive_in;
124 peer_dst->keepalive_out += peer_src->keepalive_out;
125 peer_dst->notify_in += peer_src->notify_in;
126 peer_dst->notify_out += peer_src->notify_out;
127 peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in;
128 peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out;
1ff9a340
DS
129}
130
d62a17ae 131static struct peer *peer_xfer_conn(struct peer *from_peer)
1ff9a340 132{
d62a17ae 133 struct peer *peer;
134 afi_t afi;
135 safi_t safi;
136 int fd;
8398b5d5 137 enum bgp_fsm_status status, pstatus;
d1060698 138 enum bgp_fsm_events last_evt, last_maj_evt;
d62a17ae 139
140 assert(from_peer != NULL);
141
142 peer = from_peer->doppelganger;
143
144 if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
145 return from_peer;
146
9bf904cc
DS
147 /*
148 * Let's check that we are not going to loose known configuration
149 * state based upon doppelganger rules.
150 */
151 FOREACH_AFI_SAFI (afi, safi) {
152 if (from_peer->afc[afi][safi] != peer->afc[afi][safi]) {
153 flog_err(
154 EC_BGP_DOPPELGANGER_CONFIG,
155 "from_peer->afc[%d][%d] is not the same as what we are overwriting",
156 afi, safi);
157 return NULL;
158 }
159 }
160
d62a17ae 161 if (bgp_debug_neighbor_events(peer))
162 zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
163 from_peer->host, from_peer, from_peer->fd, peer,
164 peer->fd);
165
424ab01d
QY
166 bgp_writes_off(peer);
167 bgp_reads_off(peer);
168 bgp_writes_off(from_peer);
169 bgp_reads_off(from_peer);
d62a17ae 170
74e00a55
S
171 /*
172 * Before exchanging FD remove doppelganger from
173 * keepalive peer hash. It could be possible conf peer
174 * fd is set to -1. If blocked on lock then keepalive
175 * thread can access peer pointer with fd -1.
176 */
177 bgp_keepalives_off(from_peer);
178
d62a17ae 179 BGP_TIMER_OFF(peer->t_routeadv);
424ab01d 180 BGP_TIMER_OFF(peer->t_connect);
6c537a18 181 BGP_TIMER_OFF(peer->t_delayopen);
387f984e
QY
182 BGP_TIMER_OFF(peer->t_connect_check_r);
183 BGP_TIMER_OFF(peer->t_connect_check_w);
d62a17ae 184 BGP_TIMER_OFF(from_peer->t_routeadv);
424ab01d 185 BGP_TIMER_OFF(from_peer->t_connect);
6c537a18 186 BGP_TIMER_OFF(from_peer->t_delayopen);
387f984e
QY
187 BGP_TIMER_OFF(from_peer->t_connect_check_r);
188 BGP_TIMER_OFF(from_peer->t_connect_check_w);
7a86aa5a 189 BGP_TIMER_OFF(from_peer->t_process_packet);
d3ecc69e 190
becedef6
QY
191 /*
192 * At this point in time, it is possible that there are packets pending
193 * on various buffers. Those need to be transferred or dropped,
194 * otherwise we'll get spurious failures during session establishment.
195 */
00dffa8c 196 frr_with_mutex(&peer->io_mtx, &from_peer->io_mtx) {
424ab01d
QY
197 fd = peer->fd;
198 peer->fd = from_peer->fd;
199 from_peer->fd = fd;
200
201 stream_fifo_clean(peer->ibuf);
d3ecc69e 202 stream_fifo_clean(peer->obuf);
d3ecc69e 203
becedef6
QY
204 /*
205 * this should never happen, since bgp_process_packet() is the
206 * only task that sets and unsets the current packet and it
207 * runs in our pthread.
208 */
424ab01d 209 if (peer->curr) {
af4c2728 210 flog_err(
e50f7cfd 211 EC_BGP_PKT_PROCESS,
424ab01d
QY
212 "[%s] Dropping pending packet on connection transfer:",
213 peer->host);
584470fb
DL
214 /* there used to be a bgp_packet_dump call here, but
215 * that's extremely confusing since there's no way to
216 * identify the packet in MRT dumps or BMP as dropped
217 * due to connection transfer.
218 */
424ab01d
QY
219 stream_free(peer->curr);
220 peer->curr = NULL;
221 }
222
223 // copy each packet from old peer's output queue to new peer
727c4f87
QY
224 while (from_peer->obuf->head)
225 stream_fifo_push(peer->obuf,
226 stream_fifo_pop(from_peer->obuf));
424ab01d
QY
227
228 // copy each packet from old peer's input queue to new peer
229 while (from_peer->ibuf->head)
230 stream_fifo_push(peer->ibuf,
231 stream_fifo_pop(from_peer->ibuf));
7db44ec8 232
74ffbfe6
QY
233 ringbuf_wipe(peer->ibuf_work);
234 ringbuf_copy(peer->ibuf_work, from_peer->ibuf_work,
235 ringbuf_remain(from_peer->ibuf_work));
d3ecc69e 236 }
d62a17ae 237
238 peer->as = from_peer->as;
239 peer->v_holdtime = from_peer->v_holdtime;
240 peer->v_keepalive = from_peer->v_keepalive;
d62a17ae 241 peer->v_routeadv = from_peer->v_routeadv;
6c537a18 242 peer->v_delayopen = from_peer->v_delayopen;
d62a17ae 243 peer->v_gr_restart = from_peer->v_gr_restart;
244 peer->cap = from_peer->cap;
245 status = peer->status;
246 pstatus = peer->ostatus;
247 last_evt = peer->last_event;
248 last_maj_evt = peer->last_major_event;
249 peer->status = from_peer->status;
250 peer->ostatus = from_peer->ostatus;
251 peer->last_event = from_peer->last_event;
252 peer->last_major_event = from_peer->last_major_event;
253 from_peer->status = status;
254 from_peer->ostatus = pstatus;
255 from_peer->last_event = last_evt;
256 from_peer->last_major_event = last_maj_evt;
257 peer->remote_id = from_peer->remote_id;
3577f1c5 258 peer->last_reset = from_peer->last_reset;
0db06e37 259 peer->max_packet_size = from_peer->max_packet_size;
d62a17ae 260
36235319
QY
261 BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
262 peer->bgp->peer);
8c48b3b6 263
d7b3cda6 264 if (bgp_peer_gr_mode_get(peer) == PEER_DISABLE) {
265
266 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
267
36235319 268 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
d7b3cda6 269 peer_nsf_stop(peer);
270 }
271 }
272
d62a17ae 273 if (from_peer->hostname != NULL) {
274 if (peer->hostname) {
275 XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
276 peer->hostname = NULL;
277 }
278
279 peer->hostname = from_peer->hostname;
280 from_peer->hostname = NULL;
281 }
282
283 if (from_peer->domainname != NULL) {
284 if (peer->domainname) {
285 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
286 peer->domainname = NULL;
287 }
288
289 peer->domainname = from_peer->domainname;
290 from_peer->domainname = NULL;
291 }
292
05c7a1cc 293 FOREACH_AFI_SAFI (afi, safi) {
05c7a1cc
QY
294 peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi];
295 peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
296 peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi];
297 peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi];
298 peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
299 peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
300 }
d62a17ae 301
302 if (bgp_getsockname(peer) < 0) {
af4c2728 303 flog_err(
450971aa 304 EC_LIB_SOCKET,
d62a17ae 305 "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
306 (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
307 ? "accept"
308 : ""),
309 peer->host, peer->fd, from_peer->fd);
6c4d8732
SP
310 BGP_EVENT_ADD(peer, BGP_Stop);
311 BGP_EVENT_ADD(from_peer, BGP_Stop);
d62a17ae 312 return NULL;
313 }
314 if (from_peer->status > Active) {
315 if (bgp_getsockname(from_peer) < 0) {
af4c2728 316 flog_err(
450971aa 317 EC_LIB_SOCKET,
d62a17ae 318 "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
14454c9f 319
d62a17ae 320 (CHECK_FLAG(from_peer->sflags,
321 PEER_STATUS_ACCEPT_PEER)
322 ? "accept"
323 : ""),
324 from_peer->host, from_peer->fd, peer->fd);
325 bgp_stop(from_peer);
326 from_peer = NULL;
327 }
328 }
329
0112e9e0
QY
330
331 // Note: peer_xfer_stats() must be called with I/O turned OFF
332 if (from_peer)
333 peer_xfer_stats(peer, from_peer);
334
e2d3a909 335 /* Register peer for NHT. This is to allow RAs to be enabled when
336 * needed, even on a passive connection.
337 */
338 bgp_peer_reg_with_nht(peer);
996319e6
DS
339 if (from_peer)
340 bgp_replace_nexthop_by_peer(from_peer, peer);
e2d3a909 341
424ab01d
QY
342 bgp_reads_on(peer);
343 bgp_writes_on(peer);
e0d550df
MS
344 thread_add_event(bm->master, bgp_process_packet, peer, 0,
345 &peer->t_process_packet);
d62a17ae 346
d62a17ae 347 return (peer);
1ff9a340
DS
348}
349
718e3744 350/* Hook function called after bgp event is occered. And vty's
351 neighbor command invoke this function after making neighbor
352 structure. */
d62a17ae 353void bgp_timer_set(struct peer *peer)
718e3744 354{
d62a17ae 355 switch (peer->status) {
356 case Idle:
357 /* First entry point of peer's finite state machine. In Idle
358 status start timer is on unless peer is shutdown or peer is
359 inactive. All other timer must be turned off */
f62abc7d 360 if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)
2c1eba8e 361 || peer->bgp->vrf_id == VRF_UNKNOWN) {
d62a17ae 362 BGP_TIMER_OFF(peer->t_start);
363 } else {
364 BGP_TIMER_ON(peer->t_start, bgp_start_timer,
365 peer->v_start);
366 }
367 BGP_TIMER_OFF(peer->t_connect);
368 BGP_TIMER_OFF(peer->t_holdtime);
b72b6f4f 369 bgp_keepalives_off(peer);
d62a17ae 370 BGP_TIMER_OFF(peer->t_routeadv);
6c537a18 371 BGP_TIMER_OFF(peer->t_delayopen);
d62a17ae 372 break;
373
374 case Connect:
375 /* After start timer is expired, the peer moves to Connect
376 status. Make sure start timer is off and connect timer is
377 on. */
378 BGP_TIMER_OFF(peer->t_start);
6c537a18
DS
379 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
380 BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
381 (peer->v_delayopen + peer->v_connect));
382 else
383 BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
384 peer->v_connect);
385
d62a17ae 386 BGP_TIMER_OFF(peer->t_holdtime);
b72b6f4f 387 bgp_keepalives_off(peer);
d62a17ae 388 BGP_TIMER_OFF(peer->t_routeadv);
389 break;
390
391 case Active:
392 /* Active is waiting connection from remote peer. And if
393 connect timer is expired, change status to Connect. */
394 BGP_TIMER_OFF(peer->t_start);
395 /* If peer is passive mode, do not set connect timer. */
396 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)
397 || CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
398 BGP_TIMER_OFF(peer->t_connect);
399 } else {
6c537a18
DS
400 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
401 BGP_TIMER_ON(
402 peer->t_connect, bgp_connect_timer,
403 (peer->v_delayopen + peer->v_connect));
404 else
405 BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
406 peer->v_connect);
d62a17ae 407 }
408 BGP_TIMER_OFF(peer->t_holdtime);
b72b6f4f 409 bgp_keepalives_off(peer);
d62a17ae 410 BGP_TIMER_OFF(peer->t_routeadv);
411 break;
412
413 case OpenSent:
414 /* OpenSent status. */
415 BGP_TIMER_OFF(peer->t_start);
416 BGP_TIMER_OFF(peer->t_connect);
417 if (peer->v_holdtime != 0) {
418 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
419 peer->v_holdtime);
420 } else {
421 BGP_TIMER_OFF(peer->t_holdtime);
422 }
b72b6f4f 423 bgp_keepalives_off(peer);
d62a17ae 424 BGP_TIMER_OFF(peer->t_routeadv);
6c537a18 425 BGP_TIMER_OFF(peer->t_delayopen);
d62a17ae 426 break;
427
428 case OpenConfirm:
429 /* OpenConfirm status. */
430 BGP_TIMER_OFF(peer->t_start);
431 BGP_TIMER_OFF(peer->t_connect);
432
433 /* If the negotiated Hold Time value is zero, then the Hold Time
434 timer and KeepAlive timers are not started. */
435 if (peer->v_holdtime == 0) {
436 BGP_TIMER_OFF(peer->t_holdtime);
b72b6f4f 437 bgp_keepalives_off(peer);
d62a17ae 438 } else {
439 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
440 peer->v_holdtime);
b72b6f4f 441 bgp_keepalives_on(peer);
d62a17ae 442 }
443 BGP_TIMER_OFF(peer->t_routeadv);
6c537a18 444 BGP_TIMER_OFF(peer->t_delayopen);
d62a17ae 445 break;
446
447 case Established:
448 /* In Established status start and connect timer is turned
449 off. */
450 BGP_TIMER_OFF(peer->t_start);
451 BGP_TIMER_OFF(peer->t_connect);
6c537a18 452 BGP_TIMER_OFF(peer->t_delayopen);
d62a17ae 453
454 /* Same as OpenConfirm, if holdtime is zero then both holdtime
455 and keepalive must be turned off. */
456 if (peer->v_holdtime == 0) {
457 BGP_TIMER_OFF(peer->t_holdtime);
bea01226 458 bgp_keepalives_off(peer);
d62a17ae 459 } else {
460 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
461 peer->v_holdtime);
bea01226 462 bgp_keepalives_on(peer);
d62a17ae 463 }
464 break;
465 case Deleted:
466 BGP_TIMER_OFF(peer->t_gr_restart);
467 BGP_TIMER_OFF(peer->t_gr_stale);
468 BGP_TIMER_OFF(peer->t_pmax_restart);
9af52ccf 469 BGP_TIMER_OFF(peer->t_refresh_stalepath);
d62a17ae 470 /* fallthru */
471 case Clearing:
472 BGP_TIMER_OFF(peer->t_start);
473 BGP_TIMER_OFF(peer->t_connect);
474 BGP_TIMER_OFF(peer->t_holdtime);
b72b6f4f 475 bgp_keepalives_off(peer);
d62a17ae 476 BGP_TIMER_OFF(peer->t_routeadv);
6c537a18 477 BGP_TIMER_OFF(peer->t_delayopen);
d62a17ae 478 break;
8398b5d5
DS
479 case BGP_STATUS_MAX:
480 flog_err(EC_LIB_DEVELOPMENT,
481 "BGP_STATUS_MAX while a legal state is not valid state for the FSM");
482 break;
718e3744 483 }
718e3744 484}
485
486/* BGP start timer. This function set BGP_Start event to thread value
487 and process event. */
d62a17ae 488static int bgp_start_timer(struct thread *thread)
718e3744 489{
d62a17ae 490 struct peer *peer;
718e3744 491
d62a17ae 492 peer = THREAD_ARG(thread);
718e3744 493
d62a17ae 494 if (bgp_debug_neighbor_events(peer))
495 zlog_debug("%s [FSM] Timer (start timer expire).", peer->host);
718e3744 496
d62a17ae 497 THREAD_VAL(thread) = BGP_Start;
498 bgp_event(thread); /* bgp_event unlocks peer */
718e3744 499
d62a17ae 500 return 0;
718e3744 501}
502
503/* BGP connect retry timer. */
d62a17ae 504static int bgp_connect_timer(struct thread *thread)
718e3744 505{
d62a17ae 506 struct peer *peer;
507 int ret;
508
509 peer = THREAD_ARG(thread);
424ab01d 510
6c537a18
DS
511 /* stop the DelayOpenTimer if it is running */
512 if (peer->t_delayopen)
513 BGP_TIMER_OFF(peer->t_delayopen);
514
424ab01d
QY
515 assert(!peer->t_write);
516 assert(!peer->t_read);
517
d62a17ae 518 if (bgp_debug_neighbor_events(peer))
519 zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
520
521 if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) {
522 bgp_stop(peer);
523 ret = -1;
524 } else {
525 THREAD_VAL(thread) = ConnectRetry_timer_expired;
526 bgp_event(thread); /* bgp_event unlocks peer */
527 ret = 0;
528 }
529
530 return ret;
718e3744 531}
532
533/* BGP holdtime timer. */
d62a17ae 534static int bgp_holdtime_timer(struct thread *thread)
718e3744 535{
d0874d19 536 atomic_size_t inq_count;
d62a17ae 537 struct peer *peer;
718e3744 538
d62a17ae 539 peer = THREAD_ARG(thread);
718e3744 540
d62a17ae 541 if (bgp_debug_neighbor_events(peer))
542 zlog_debug("%s [FSM] Timer (holdtime timer expire)",
543 peer->host);
718e3744 544
d0874d19
DS
545 /*
546 * Given that we do not have any expectation of ordering
547 * for handling packets from a peer -vs- handling
548 * the hold timer for a peer as that they are both
549 * events on the peer. If we have incoming
550 * data on the peers inq, let's give the system a chance
551 * to handle that data. This can be especially true
552 * for systems where we are heavily loaded for one
553 * reason or another.
554 */
555 inq_count = atomic_load_explicit(&peer->ibuf->count,
556 memory_order_relaxed);
557 if (inq_count) {
558 BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
559 peer->v_holdtime);
560
561 return 0;
562 }
563
d62a17ae 564 THREAD_VAL(thread) = Hold_Timer_expired;
565 bgp_event(thread); /* bgp_event unlocks peer */
718e3744 566
d62a17ae 567 return 0;
718e3744 568}
569
d62a17ae 570int bgp_routeadv_timer(struct thread *thread)
718e3744 571{
d62a17ae 572 struct peer *peer;
718e3744 573
d62a17ae 574 peer = THREAD_ARG(thread);
718e3744 575
d62a17ae 576 if (bgp_debug_neighbor_events(peer))
577 zlog_debug("%s [FSM] Timer (routeadv timer expire)",
578 peer->host);
718e3744 579
d62a17ae 580 peer->synctime = bgp_clock();
718e3744 581
a9794991 582 thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets, peer, 0,
424ab01d
QY
583 &peer->t_generate_updgrp_packets);
584
d62a17ae 585 /* MRAI timer will be started again when FIFO is built, no need to
586 * do it here.
587 */
588 return 0;
718e3744 589}
590
6c537a18
DS
591/* RFC 4271 DelayOpenTimer */
592int bgp_delayopen_timer(struct thread *thread)
593{
594 struct peer *peer;
595
596 peer = THREAD_ARG(thread);
597
598 if (bgp_debug_neighbor_events(peer))
599 zlog_debug("%s [FSM] Timer (DelayOpentimer expire)",
600 peer->host);
601
602 THREAD_VAL(thread) = DelayOpen_timer_expired;
603 bgp_event(thread); /* bgp_event unlocks peer */
604
605 return 0;
606}
607
e0701b79 608/* BGP Peer Down Cause */
2b64873d 609const char *const peer_down_str[] = {"",
d62a17ae 610 "Router ID changed",
611 "Remote AS changed",
612 "Local AS change",
613 "Cluster ID changed",
614 "Confederation identifier changed",
615 "Confederation peer changed",
616 "RR client config change",
617 "RS client config change",
618 "Update source change",
619 "Address family activated",
620 "Admin. shutdown",
621 "User reset",
622 "BGP Notification received",
623 "BGP Notification send",
624 "Peer closed the session",
625 "Neighbor deleted",
626 "Peer-group add member",
627 "Peer-group delete member",
628 "Capability changed",
629 "Passive config change",
630 "Multihop config change",
631 "NSF peer closed the session",
632 "Intf peering v6only config change",
633 "BFD down received",
634 "Interface down",
05912a17 635 "Neighbor address lost",
3577f1c5 636 "Waiting for NHT",
05912a17
DD
637 "Waiting for Peer IPv6 LLA",
638 "Waiting for VRF to be initialized",
1e91f1d1
DS
639 "No AFI/SAFI activated for peer",
640 "AS Set config change",
07d1e5d9 641 "Waiting for peer OPEN",
c5fe9095
DS
642 "Reached received prefix count",
643 "Socket Error"};
d62a17ae 644
645static int bgp_graceful_restart_timer_expire(struct thread *thread)
e0701b79 646{
d62a17ae 647 struct peer *peer;
648 afi_t afi;
649 safi_t safi;
650
651 peer = THREAD_ARG(thread);
d62a17ae 652
653 /* NSF delete stale route */
654 for (afi = AFI_IP; afi < AFI_MAX; afi++)
a08ca0a7 655 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
d62a17ae 656 if (peer->nsf[afi][safi])
657 bgp_clear_stale_route(peer, afi, safi);
658
659 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
660 BGP_TIMER_OFF(peer->t_gr_stale);
661
662 if (bgp_debug_neighbor_events(peer)) {
663 zlog_debug("%s graceful restart timer expired", peer->host);
664 zlog_debug("%s graceful restart stalepath timer stopped",
665 peer->host);
666 }
93406d87 667
d62a17ae 668 bgp_timer_set(peer);
93406d87 669
d62a17ae 670 return 0;
93406d87 671}
672
d62a17ae 673static int bgp_graceful_stale_timer_expire(struct thread *thread)
93406d87 674{
d62a17ae 675 struct peer *peer;
676 afi_t afi;
677 safi_t safi;
93406d87 678
d62a17ae 679 peer = THREAD_ARG(thread);
93406d87 680
d62a17ae 681 if (bgp_debug_neighbor_events(peer))
682 zlog_debug("%s graceful restart stalepath timer expired",
683 peer->host);
93406d87 684
d62a17ae 685 /* NSF delete stale route */
686 for (afi = AFI_IP; afi < AFI_MAX; afi++)
a08ca0a7 687 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
d62a17ae 688 if (peer->nsf[afi][safi])
689 bgp_clear_stale_route(peer, afi, safi);
93406d87 690
d62a17ae 691 return 0;
93406d87 692}
693
f009ff26 694/* Selection deferral timer processing function */
695static int bgp_graceful_deferral_timer_expire(struct thread *thread)
696{
697 struct afi_safi_info *info;
698 afi_t afi;
699 safi_t safi;
700 struct bgp *bgp;
701
702 info = THREAD_ARG(thread);
703 afi = info->afi;
704 safi = info->safi;
705 bgp = info->bgp;
706
707 if (BGP_DEBUG(update, UPDATE_OUT))
13909c4f
DS
708 zlog_debug(
709 "afi %d, safi %d : graceful restart deferral timer expired",
710 afi, safi);
f009ff26 711
f009ff26 712 bgp->gr_info[afi][safi].eor_required = 0;
713 bgp->gr_info[afi][safi].eor_received = 0;
714 XFREE(MTYPE_TMP, info);
715
716 /* Best path selection */
717 return bgp_best_path_select_defer(bgp, afi, safi);
718}
719
3dc339cd 720static bool bgp_update_delay_applicable(struct bgp *bgp)
f188f2c4 721{
d62a17ae 722 /* update_delay_over flag should be reset (set to 0) for any new
723 applicability of the update-delay during BGP process lifetime.
724 And it should be set after an occurence of the update-delay is
725 over)*/
726 if (!bgp->update_delay_over)
3dc339cd
DA
727 return true;
728 return false;
f188f2c4
DS
729}
730
3dc339cd 731bool bgp_update_delay_active(struct bgp *bgp)
f188f2c4 732{
d62a17ae 733 if (bgp->t_update_delay)
3dc339cd
DA
734 return true;
735 return false;
f188f2c4
DS
736}
737
3dc339cd 738bool bgp_update_delay_configured(struct bgp *bgp)
f188f2c4 739{
d62a17ae 740 if (bgp->v_update_delay)
3dc339cd
DA
741 return true;
742 return false;
f188f2c4
DS
743}
744
745/* Do the post-processing needed when bgp comes out of the read-only mode
746 on ending the update delay. */
d62a17ae 747void bgp_update_delay_end(struct bgp *bgp)
f188f2c4 748{
50478845
MS
749 THREAD_OFF(bgp->t_update_delay);
750 THREAD_OFF(bgp->t_establish_wait);
d62a17ae 751
752 /* Reset update-delay related state */
753 bgp->update_delay_over = 1;
754 bgp->established = 0;
755 bgp->restarted_peers = 0;
756 bgp->implicit_eors = 0;
757 bgp->explicit_eors = 0;
758
e36f61b5
DS
759 frr_timestamp(3, bgp->update_delay_end_time,
760 sizeof(bgp->update_delay_end_time));
d62a17ae 761
762 /*
763 * Add an end-of-initial-update marker to the main process queues so
764 * that
765 * the route advertisement timer for the peers can be started. Also set
766 * the zebra and peer update hold flags. These flags are used to achieve
767 * three stages in the update-delay post processing:
768 * 1. Finish best-path selection for all the prefixes held on the
769 * queues.
770 * (routes in BGP are updated, and peers sync queues are populated
771 * too)
772 * 2. As the eoiu mark is reached in the bgp process routine, ship all
773 * the
774 * routes to zebra. With that zebra should see updates from BGP
775 * close
776 * to each other.
777 * 3. Unblock the peer update writes. With that peer update packing
778 * with
779 * the prefixes should be at its maximum.
780 */
781 bgp_add_eoiu_mark(bgp);
782 bgp->main_zebra_update_hold = 1;
783 bgp->main_peers_update_hold = 1;
784
b6c386bb
DS
785 /*
786 * Resume the queue processing. This should trigger the event that would
787 * take care of processing any work that was queued during the read-only
788 * mode.
789 */
790 work_queue_unplug(bgp->process_queue);
f188f2c4
DS
791}
792
cb1faec9
DS
793/**
794 * see bgp_fsm.h
795 */
d62a17ae 796void bgp_start_routeadv(struct bgp *bgp)
cb1faec9 797{
d62a17ae 798 struct listnode *node, *nnode;
799 struct peer *peer;
cb1faec9 800
d62a17ae 801 zlog_info("bgp_start_routeadv(), update hold status %d",
802 bgp->main_peers_update_hold);
4a16ae86 803
d62a17ae 804 if (bgp->main_peers_update_hold)
805 return;
4a16ae86 806
e36f61b5
DS
807 frr_timestamp(3, bgp->update_delay_peers_resume_time,
808 sizeof(bgp->update_delay_peers_resume_time));
4a16ae86 809
d62a17ae 810 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
feb17238 811 if (!peer_established(peer))
d62a17ae 812 continue;
813 BGP_TIMER_OFF(peer->t_routeadv);
814 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
815 }
cb1faec9
DS
816}
817
818/**
819 * see bgp_fsm.h
820 */
d62a17ae 821void bgp_adjust_routeadv(struct peer *peer)
cb1faec9 822{
d62a17ae 823 time_t nowtime = bgp_clock();
824 double diff;
825 unsigned long remain;
826
827 /* Bypass checks for special case of MRAI being 0 */
828 if (peer->v_routeadv == 0) {
829 /* Stop existing timer, just in case it is running for a
830 * different
831 * duration and schedule write thread immediately.
832 */
833 if (peer->t_routeadv)
834 BGP_TIMER_OFF(peer->t_routeadv);
835
836 peer->synctime = bgp_clock();
a77e2f4b
S
837 /* If suppress fib pending is enabled, route is advertised to
838 * peers when the status is received from the FIB. The delay
839 * is added to update group packet generate which will allow
840 * more routes to be sent in the update message
841 */
842 BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
843 bgp_generate_updgrp_packets);
d62a17ae 844 return;
845 }
846
847
848 /*
849 * CASE I:
850 * If the last update was written more than MRAI back, expire the timer
851 * instantly so that we can send the update out sooner.
852 *
853 * <------- MRAI --------->
854 * |-----------------|-----------------------|
855 * <------------- m ------------>
856 * ^ ^ ^
857 * | | |
858 * | | current time
859 * | timer start
860 * last write
861 *
862 * m > MRAI
863 */
864 diff = difftime(nowtime, peer->last_update);
865 if (diff > (double)peer->v_routeadv) {
866 BGP_TIMER_OFF(peer->t_routeadv);
867 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
868 return;
869 }
870
871 /*
872 * CASE II:
873 * - Find when to expire the MRAI timer.
874 * If MRAI timer is not active, assume we can start it now.
875 *
876 * <------- MRAI --------->
877 * |------------|-----------------------|
878 * <-------- m ----------><----- r ----->
879 * ^ ^ ^
880 * | | |
881 * | | current time
882 * | timer start
883 * last write
884 *
885 * (MRAI - m) < r
886 */
887 if (peer->t_routeadv)
888 remain = thread_timer_remain_second(peer->t_routeadv);
889 else
890 remain = peer->v_routeadv;
891 diff = peer->v_routeadv - diff;
892 if (diff <= (double)remain) {
893 BGP_TIMER_OFF(peer->t_routeadv);
894 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff);
895 }
cb1faec9
DS
896}
897
3dc339cd 898static bool bgp_maxmed_onstartup_applicable(struct bgp *bgp)
abc920f8 899{
d62a17ae 900 if (!bgp->maxmed_onstartup_over)
3dc339cd
DA
901 return true;
902 return false;
abc920f8
DS
903}
904
3dc339cd 905bool bgp_maxmed_onstartup_configured(struct bgp *bgp)
abc920f8 906{
d62a17ae 907 if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
3dc339cd
DA
908 return true;
909 return false;
abc920f8
DS
910}
911
3dc339cd 912bool bgp_maxmed_onstartup_active(struct bgp *bgp)
abc920f8 913{
d62a17ae 914 if (bgp->t_maxmed_onstartup)
3dc339cd
DA
915 return true;
916 return false;
abc920f8
DS
917}
918
d62a17ae 919void bgp_maxmed_update(struct bgp *bgp)
abc920f8 920{
d7c0a89a
QY
921 uint8_t maxmed_active;
922 uint32_t maxmed_value;
d62a17ae 923
924 if (bgp->v_maxmed_admin) {
925 maxmed_active = 1;
926 maxmed_value = bgp->maxmed_admin_value;
927 } else if (bgp->t_maxmed_onstartup) {
928 maxmed_active = 1;
929 maxmed_value = bgp->maxmed_onstartup_value;
930 } else {
931 maxmed_active = 0;
932 maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
933 }
934
935 if (bgp->maxmed_active != maxmed_active
936 || bgp->maxmed_value != maxmed_value) {
937 bgp->maxmed_active = maxmed_active;
938 bgp->maxmed_value = maxmed_value;
939
940 update_group_announce(bgp);
941 }
abc920f8
DS
942}
943
3893aeee
DA
944int bgp_fsm_error_subcode(int status)
945{
946 int fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC;
947
948 switch (status) {
949 case OpenSent:
950 fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT;
951 break;
952 case OpenConfirm:
953 fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM;
954 break;
955 case Established:
956 fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED;
957 break;
958 default:
959 break;
960 }
961
962 return fsm_err_subcode;
963}
964
abc920f8 965/* The maxmed onstartup timer expiry callback. */
d62a17ae 966static int bgp_maxmed_onstartup_timer(struct thread *thread)
abc920f8 967{
d62a17ae 968 struct bgp *bgp;
abc920f8 969
d62a17ae 970 zlog_info("Max med on startup ended - timer expired.");
abc920f8 971
d62a17ae 972 bgp = THREAD_ARG(thread);
50478845 973 THREAD_OFF(bgp->t_maxmed_onstartup);
d62a17ae 974 bgp->maxmed_onstartup_over = 1;
abc920f8 975
d62a17ae 976 bgp_maxmed_update(bgp);
abc920f8 977
d62a17ae 978 return 0;
abc920f8
DS
979}
980
d62a17ae 981static void bgp_maxmed_onstartup_begin(struct bgp *bgp)
abc920f8 982{
d62a17ae 983 /* Applicable only once in the process lifetime on the startup */
984 if (bgp->maxmed_onstartup_over)
985 return;
abc920f8 986
d62a17ae 987 zlog_info("Begin maxmed onstartup mode - timer %d seconds",
988 bgp->v_maxmed_onstartup);
abc920f8 989
d62a17ae 990 thread_add_timer(bm->master, bgp_maxmed_onstartup_timer, bgp,
991 bgp->v_maxmed_onstartup, &bgp->t_maxmed_onstartup);
abc920f8 992
d62a17ae 993 if (!bgp->v_maxmed_admin) {
994 bgp->maxmed_active = 1;
995 bgp->maxmed_value = bgp->maxmed_onstartup_value;
996 }
abc920f8 997
d62a17ae 998 /* Route announce to all peers should happen after this in
999 * bgp_establish() */
abc920f8
DS
1000}
1001
d62a17ae 1002static void bgp_maxmed_onstartup_process_status_change(struct peer *peer)
abc920f8 1003{
feb17238 1004 if (peer_established(peer) && !peer->bgp->established) {
d62a17ae 1005 bgp_maxmed_onstartup_begin(peer->bgp);
1006 }
abc920f8
DS
1007}
1008
f188f2c4 1009/* The update delay timer expiry callback. */
d62a17ae 1010static int bgp_update_delay_timer(struct thread *thread)
f188f2c4 1011{
d62a17ae 1012 struct bgp *bgp;
f188f2c4 1013
d62a17ae 1014 zlog_info("Update delay ended - timer expired.");
f188f2c4 1015
d62a17ae 1016 bgp = THREAD_ARG(thread);
50478845 1017 THREAD_OFF(bgp->t_update_delay);
d62a17ae 1018 bgp_update_delay_end(bgp);
f188f2c4 1019
d62a17ae 1020 return 0;
f188f2c4
DS
1021}
1022
1023/* The establish wait timer expiry callback. */
d62a17ae 1024static int bgp_establish_wait_timer(struct thread *thread)
f188f2c4 1025{
d62a17ae 1026 struct bgp *bgp;
f188f2c4 1027
d62a17ae 1028 zlog_info("Establish wait - timer expired.");
f188f2c4 1029
d62a17ae 1030 bgp = THREAD_ARG(thread);
50478845 1031 THREAD_OFF(bgp->t_establish_wait);
d62a17ae 1032 bgp_check_update_delay(bgp);
f188f2c4 1033
d62a17ae 1034 return 0;
f188f2c4
DS
1035}
1036
1037/* Steps to begin the update delay:
1038 - initialize queues if needed
1039 - stop the queue processing
1040 - start the timer */
d62a17ae 1041static void bgp_update_delay_begin(struct bgp *bgp)
f188f2c4 1042{
d62a17ae 1043 struct listnode *node, *nnode;
1044 struct peer *peer;
f188f2c4 1045
d62a17ae 1046 /* Stop the processing of queued work. Enqueue shall continue */
b6c386bb 1047 work_queue_plug(bgp->process_queue);
f188f2c4 1048
d62a17ae 1049 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
1050 peer->update_delay_over = 0;
f188f2c4 1051
d62a17ae 1052 /* Start the update-delay timer */
1053 thread_add_timer(bm->master, bgp_update_delay_timer, bgp,
1054 bgp->v_update_delay, &bgp->t_update_delay);
f188f2c4 1055
d62a17ae 1056 if (bgp->v_establish_wait != bgp->v_update_delay)
1057 thread_add_timer(bm->master, bgp_establish_wait_timer, bgp,
1058 bgp->v_establish_wait, &bgp->t_establish_wait);
f188f2c4 1059
e36f61b5
DS
1060 frr_timestamp(3, bgp->update_delay_begin_time,
1061 sizeof(bgp->update_delay_begin_time));
f188f2c4
DS
1062}
1063
d62a17ae 1064static void bgp_update_delay_process_status_change(struct peer *peer)
f188f2c4 1065{
feb17238 1066 if (peer_established(peer)) {
d62a17ae 1067 if (!peer->bgp->established++) {
1068 bgp_update_delay_begin(peer->bgp);
1069 zlog_info(
1070 "Begin read-only mode - update-delay timer %d seconds",
1071 peer->bgp->v_update_delay);
1072 }
1073 if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV))
1074 bgp_update_restarted_peers(peer);
1075 }
1076 if (peer->ostatus == Established
1077 && bgp_update_delay_active(peer->bgp)) {
1078 /* Adjust the update-delay state to account for this flap.
1079 NOTE: Intentionally skipping adjusting implicit_eors or
1080 explicit_eors
1081 counters. Extra sanity check in bgp_check_update_delay()
1082 should
1083 be enough to take care of any additive discrepancy in bgp eor
1084 counters */
1085 peer->bgp->established--;
1086 peer->update_delay_over = 0;
1087 }
f188f2c4
DS
1088}
1089
0437e105 1090/* Called after event occurred, this function change status and reset
200df115 1091 read/write and timer thread. */
d62a17ae 1092void bgp_fsm_change_status(struct peer *peer, int status)
200df115 1093{
36dc7588 1094 struct bgp *bgp;
1095 uint32_t peer_count;
1ff9a340 1096
36dc7588 1097 bgp = peer->bgp;
1098 peer_count = bgp->established_peers;
1099
1100 if (status == Established)
1101 bgp->established_peers++;
feb17238 1102 else if ((peer_established(peer)) && (status != Established))
36dc7588 1103 bgp->established_peers--;
1104
1cfe005d
DS
1105 if (bgp_debug_neighbor_events(peer)) {
1106 struct vrf *vrf = vrf_lookup_by_id(bgp->vrf_id);
1107
1108 zlog_debug("%s : vrf %s(%u), Status: %s established_peers %u", __func__,
1109 vrf ? vrf->name : "Unknown", bgp->vrf_id,
1110 lookup_msg(bgp_status_msg, status, NULL),
1111 bgp->established_peers);
1112 }
1113
36dc7588 1114 /* Set to router ID to the value provided by RIB if there are no peers
1115 * in the established state and peer count did not change
1116 */
1117 if ((peer_count != bgp->established_peers) &&
1118 (bgp->established_peers == 0))
1119 bgp_router_id_zebra_bump(bgp->vrf_id, NULL);
1120
d62a17ae 1121 /* Transition into Clearing or Deleted must /always/ clear all routes..
1122 * (and must do so before actually changing into Deleted..
1123 */
1124 if (status >= Clearing) {
1125 bgp_clear_route_all(peer);
1126
1127 /* If no route was queued for the clear-node processing,
1128 * generate the
1129 * completion event here. This is needed because if there are no
1130 * routes
1131 * to trigger the background clear-node thread, the event won't
1132 * get
1133 * generated and the peer would be stuck in Clearing. Note that
1134 * this
1135 * event is for the peer and helps the peer transition out of
1136 * Clearing
1137 * state; it should not be generated per (AFI,SAFI). The event
1138 * is
1139 * directly posted here without calling clear_node_complete() as
1140 * we
1141 * shouldn't do an extra unlock. This event will get processed
1142 * after
1143 * the state change that happens below, so peer will be in
1144 * Clearing
1145 * (or Deleted).
1146 */
1147 if (!work_queue_is_scheduled(peer->clear_node_queue))
1148 BGP_EVENT_ADD(peer, Clearing_Completed);
1149 }
1150
1151 /* Preserve old status and change into new status. */
1152 peer->ostatus = peer->status;
1153 peer->status = status;
1154
8336c896
DA
1155 /* Reset received keepalives counter on every FSM change */
1156 peer->rtt_keepalive_rcv = 0;
1157
05e68acc
BC
1158 /* Fire backward transition hook if that's the case */
1159 if (peer->ostatus > peer->status)
1160 hook_call(peer_backward_transition, peer);
1161
d62a17ae 1162 /* Save event that caused status change. */
1163 peer->last_major_event = peer->cur_event;
1164
7d8d0eab
MKS
1165 /* Operations after status change */
1166 hook_call(peer_status_changed, peer);
1167
d62a17ae 1168 if (status == Established)
1169 UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
1170
1171 /* If max-med processing is applicable, do the necessary. */
1172 if (status == Established) {
1173 if (bgp_maxmed_onstartup_configured(peer->bgp)
1174 && bgp_maxmed_onstartup_applicable(peer->bgp))
1175 bgp_maxmed_onstartup_process_status_change(peer);
1176 else
1177 peer->bgp->maxmed_onstartup_over = 1;
1178 }
1179
1180 /* If update-delay processing is applicable, do the necessary. */
1181 if (bgp_update_delay_configured(peer->bgp)
1182 && bgp_update_delay_applicable(peer->bgp))
1183 bgp_update_delay_process_status_change(peer);
1184
1185 if (bgp_debug_neighbor_events(peer))
1186 zlog_debug("%s went from %s to %s", peer->host,
1187 lookup_msg(bgp_status_msg, peer->ostatus, NULL),
1188 lookup_msg(bgp_status_msg, peer->status, NULL));
200df115 1189}
1190
3117b5c4 1191/* Flush the event queue and ensure the peer is shut down */
d62a17ae 1192static int bgp_clearing_completed(struct peer *peer)
3117b5c4 1193{
d62a17ae 1194 int rc = bgp_stop(peer);
1ff9a340 1195
d62a17ae 1196 if (rc >= 0)
1197 BGP_EVENT_FLUSH(peer);
3117b5c4 1198
d62a17ae 1199 return rc;
3117b5c4
SH
1200}
1201
718e3744 1202/* Administrative BGP peer stop event. */
3117b5c4 1203/* May be called multiple times for the same peer */
d62a17ae 1204int bgp_stop(struct peer *peer)
718e3744 1205{
d62a17ae 1206 afi_t afi;
1207 safi_t safi;
1208 char orf_name[BUFSIZ];
1209 int ret = 0;
f009ff26 1210 struct bgp *bgp = peer->bgp;
1211 struct graceful_restart_info *gr_info = NULL;
d62a17ae 1212
2ba1fe69 1213 peer->nsf_af_count = 0;
1214
e7db872b 1215 /* deregister peer */
21bfce98
RZ
1216 if (peer->bfd_config
1217 && peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE)
1218 bfd_sess_uninstall(peer->bfd_config->session);
e7db872b 1219
d62a17ae 1220 if (peer_dynamic_neighbor(peer)
1221 && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
1222 if (bgp_debug_neighbor_events(peer))
1223 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
1224 peer_delete(peer);
1225 return -1;
c22767d8 1226 }
848973c7 1227
d62a17ae 1228 /* Can't do this in Clearing; events are used for state transitions */
1229 if (peer->status != Clearing) {
1230 /* Delete all existing events of the peer */
1231 BGP_EVENT_FLUSH(peer);
93406d87 1232 }
d62a17ae 1233
1234 /* Increment Dropped count. */
feb17238 1235 if (peer_established(peer)) {
d62a17ae 1236 peer->dropped++;
1237
1238 /* bgp log-neighbor-changes of neighbor Down */
892fedb6
DA
1239 if (CHECK_FLAG(peer->bgp->flags,
1240 BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
d62a17ae 1241 struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
2986cac2 1242
d62a17ae 1243 zlog_info(
1244 "%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s",
1245 peer->host,
1246 (peer->hostname) ? peer->hostname : "Unknown",
5742e42b
DS
1247 vrf ? ((vrf->vrf_id != VRF_DEFAULT)
1248 ? vrf->name
1249 : VRF_DEFAULT_NAME)
d62a17ae 1250 : "",
1251 peer_down_str[(int)peer->last_reset]);
1252 }
1253
1254 /* graceful restart */
1255 if (peer->t_gr_stale) {
1256 BGP_TIMER_OFF(peer->t_gr_stale);
1257 if (bgp_debug_neighbor_events(peer))
1258 zlog_debug(
1259 "%s graceful restart stalepath timer stopped",
1260 peer->host);
1261 }
1262 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
1263 if (bgp_debug_neighbor_events(peer)) {
1264 zlog_debug(
1265 "%s graceful restart timer started for %d sec",
1266 peer->host, peer->v_gr_restart);
1267 zlog_debug(
1268 "%s graceful restart stalepath timer started for %d sec",
1269 peer->host, peer->bgp->stalepath_time);
1270 }
1271 BGP_TIMER_ON(peer->t_gr_restart,
1272 bgp_graceful_restart_timer_expire,
1273 peer->v_gr_restart);
1274 BGP_TIMER_ON(peer->t_gr_stale,
1275 bgp_graceful_stale_timer_expire,
1276 peer->bgp->stalepath_time);
1277 } else {
1278 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
1279
1280 for (afi = AFI_IP; afi < AFI_MAX; afi++)
996c9314
LB
1281 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN;
1282 safi++)
d62a17ae 1283 peer->nsf[afi][safi] = 0;
1284 }
1285
9af52ccf
DA
1286 /* Stop route-refresh stalepath timer */
1287 if (peer->t_refresh_stalepath) {
1288 BGP_TIMER_OFF(peer->t_refresh_stalepath);
1289
1290 if (bgp_debug_neighbor_events(peer))
1291 zlog_debug(
1292 "%s: route-refresh restart stalepath timer stopped",
1293 peer->host);
1294 }
1295
f009ff26 1296 /* If peer reset before receiving EOR, decrement EOR count and
1297 * cancel the selection deferral timer if there are no
1298 * pending EOR messages to be received
1299 */
1300 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
1301 FOREACH_AFI_SAFI (afi, safi) {
13909c4f
DS
1302 if (!peer->afc_nego[afi][safi]
1303 || CHECK_FLAG(peer->af_sflags[afi][safi],
1304 PEER_STATUS_EOR_RECEIVED))
1305 continue;
1306
1307 gr_info = &bgp->gr_info[afi][safi];
1308 if (!gr_info)
1309 continue;
1310
1311 if (gr_info->eor_required)
1312 gr_info->eor_required--;
1313
1314 if (BGP_DEBUG(update, UPDATE_OUT))
1315 zlog_debug("peer %s, EOR_required %d",
1316 peer->host,
1317 gr_info->eor_required);
1318
1319 /* There is no pending EOR message */
1320 if (gr_info->eor_required == 0) {
1321 BGP_TIMER_OFF(
f009ff26 1322 gr_info->t_select_deferral);
13909c4f 1323 gr_info->eor_received = 0;
f009ff26 1324 }
1325 }
1326 }
1327
d62a17ae 1328 /* set last reset time */
1329 peer->resettime = peer->uptime = bgp_clock();
1330
1331 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
1332 zlog_debug("%s remove from all update group",
1333 peer->host);
1334 update_group_remove_peer_afs(peer);
1335
d62a17ae 1336 /* Reset peer synctime */
1337 peer->synctime = 0;
93406d87 1338 }
93406d87 1339
424ab01d 1340 /* stop keepalives */
b72b6f4f 1341 bgp_keepalives_off(peer);
424ab01d
QY
1342
1343 /* Stop read and write threads. */
1344 bgp_writes_off(peer);
1345 bgp_reads_off(peer);
1346
387f984e
QY
1347 THREAD_OFF(peer->t_connect_check_r);
1348 THREAD_OFF(peer->t_connect_check_w);
d62a17ae 1349
1350 /* Stop all timers. */
1351 BGP_TIMER_OFF(peer->t_start);
1352 BGP_TIMER_OFF(peer->t_connect);
1353 BGP_TIMER_OFF(peer->t_holdtime);
d62a17ae 1354 BGP_TIMER_OFF(peer->t_routeadv);
6c537a18 1355 BGP_TIMER_OFF(peer->t_delayopen);
d62a17ae 1356
1357 /* Clear input and output buffer. */
00dffa8c 1358 frr_with_mutex(&peer->io_mtx) {
424ab01d
QY
1359 if (peer->ibuf)
1360 stream_fifo_clean(peer->ibuf);
d3ecc69e
QY
1361 if (peer->obuf)
1362 stream_fifo_clean(peer->obuf);
424ab01d
QY
1363
1364 if (peer->ibuf_work)
74ffbfe6 1365 ringbuf_wipe(peer->ibuf_work);
424ab01d
QY
1366 if (peer->obuf_work)
1367 stream_reset(peer->obuf_work);
1368
1369 if (peer->curr) {
1370 stream_free(peer->curr);
1371 peer->curr = NULL;
1372 }
d3ecc69e 1373 }
d62a17ae 1374
1375 /* Close of file descriptor. */
1376 if (peer->fd >= 0) {
1377 close(peer->fd);
1378 peer->fd = -1;
93406d87 1379 }
1380
24f569e9
AS
1381 /* Reset capabilities. */
1382 peer->cap = 0;
1383
05c7a1cc
QY
1384 FOREACH_AFI_SAFI (afi, safi) {
1385 /* Reset all negotiated variables */
1386 peer->afc_nego[afi][safi] = 0;
1387 peer->afc_adv[afi][safi] = 0;
1388 peer->afc_recv[afi][safi] = 0;
1389
1390 /* peer address family capability flags*/
1391 peer->af_cap[afi][safi] = 0;
1392
1393 /* peer address family status flags*/
1394 peer->af_sflags[afi][safi] = 0;
1395
1396 /* Received ORF prefix-filter */
1397 peer->orf_plist[afi][safi] = NULL;
1398
feb17238 1399 if ((peer->status == OpenConfirm) || (peer_established(peer))) {
05c7a1cc 1400 /* ORF received prefix-filter pnt */
fc746f1c
QY
1401 snprintf(orf_name, sizeof(orf_name), "%s.%d.%d",
1402 peer->host, afi, safi);
05c7a1cc 1403 prefix_bgp_orf_remove_all(afi, orf_name);
d62a17ae 1404 }
05c7a1cc 1405 }
d62a17ae 1406
1407 /* Reset keepalive and holdtime */
b90a8e13 1408 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) {
d62a17ae 1409 peer->v_keepalive = peer->keepalive;
1410 peer->v_holdtime = peer->holdtime;
1411 } else {
1412 peer->v_keepalive = peer->bgp->default_keepalive;
1413 peer->v_holdtime = peer->bgp->default_holdtime;
1ff9a340 1414 }
d62a17ae 1415
6c537a18
DS
1416 /* Reset DelayOpenTime */
1417 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
1418 peer->v_delayopen = peer->delayopen;
1419 else
1420 peer->v_delayopen = peer->bgp->default_delayopen;
1421
d62a17ae 1422 peer->update_time = 0;
1423
d62a17ae 1424 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
1425 && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
1426 peer_delete(peer);
1427 ret = -1;
1428 } else {
1429 bgp_peer_conf_if_to_su_update(peer);
1430 }
d62a17ae 1431 return ret;
718e3744 1432}
1433
1434/* BGP peer is stoped by the error. */
d62a17ae 1435static int bgp_stop_with_error(struct peer *peer)
718e3744 1436{
d62a17ae 1437 /* Double start timer. */
1438 peer->v_start *= 2;
1439
1440 /* Overflow check. */
1441 if (peer->v_start >= (60 * 2))
1442 peer->v_start = (60 * 2);
1443
1444 if (peer_dynamic_neighbor(peer)) {
1445 if (bgp_debug_neighbor_events(peer))
1446 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
1447 peer_delete(peer);
1448 return -1;
1449 }
1450
1451 return (bgp_stop(peer));
718e3744 1452}
1453
397b5bde
LR
1454
1455/* something went wrong, send notify and tear down */
d7c0a89a
QY
1456static int bgp_stop_with_notify(struct peer *peer, uint8_t code,
1457 uint8_t sub_code)
397b5bde 1458{
d62a17ae 1459 /* Send notify to remote peer */
1460 bgp_notify_send(peer, code, sub_code);
1461
1462 if (peer_dynamic_neighbor(peer)) {
1463 if (bgp_debug_neighbor_events(peer))
1464 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
1465 peer_delete(peer);
1466 return -1;
1467 }
f14e6fdb 1468
d62a17ae 1469 /* Clear start timer value to default. */
1470 peer->v_start = BGP_INIT_START_TIMER;
397b5bde 1471
d62a17ae 1472 return (bgp_stop(peer));
397b5bde
LR
1473}
1474
07a16526
QY
1475/**
1476 * Determines whether a TCP session has successfully established for a peer and
1477 * events as appropriate.
1478 *
1479 * This function is called when setting up a new session. After connect() is
387f984e
QY
1480 * called on the peer's socket (in bgp_start()), the fd is passed to poll()
1481 * to wait for connection success or failure. When poll() returns, this
07a16526 1482 * function is called to evaluate the result.
387f984e
QY
1483 *
1484 * Due to differences in behavior of poll() on Linux and BSD - specifically,
1485 * the value of .revents in the case of a closed connection - this function is
1486 * scheduled both for a read and a write event. The write event is triggered
1487 * when the connection is established. A read event is triggered when the
1488 * connection is closed. Thus we need to cancel whichever one did not occur.
07a16526
QY
1489 */
1490static int bgp_connect_check(struct thread *thread)
1491{
1492 int status;
1493 socklen_t slen;
1494 int ret;
1495 struct peer *peer;
1496
1497 peer = THREAD_ARG(thread);
424ab01d
QY
1498 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
1499 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
1500 assert(!peer->t_read);
1501 assert(!peer->t_write);
07a16526 1502
387f984e
QY
1503 THREAD_OFF(peer->t_connect_check_r);
1504 THREAD_OFF(peer->t_connect_check_w);
dc1188bb 1505
07a16526
QY
1506 /* Check file descriptor. */
1507 slen = sizeof(status);
1508 ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *)&status,
1509 &slen);
1510
1511 /* If getsockopt is fail, this is fatal error. */
1512 if (ret < 0) {
4cb5e18b 1513 zlog_err("can't get sockopt for nonblocking connect: %d(%s)",
54ff5e9b 1514 errno, safe_strerror(errno));
07a16526
QY
1515 BGP_EVENT_ADD(peer, TCP_fatal_error);
1516 return -1;
1517 }
1518
1519 /* When status is 0 then TCP connection is established. */
1520 if (status == 0) {
6c537a18
DS
1521 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
1522 BGP_EVENT_ADD(peer, TCP_connection_open_w_delay);
1523 else
1524 BGP_EVENT_ADD(peer, TCP_connection_open);
07a16526
QY
1525 return 1;
1526 } else {
1527 if (bgp_debug_neighbor_events(peer))
54ff5e9b
DS
1528 zlog_debug("%s [Event] Connect failed %d(%s)",
1529 peer->host, status, safe_strerror(status));
07a16526
QY
1530 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1531 return 0;
1532 }
1533}
397b5bde 1534
718e3744 1535/* TCP connection open. Next we send open message to remote peer. And
1536 add read thread for reading open message. */
d62a17ae 1537static int bgp_connect_success(struct peer *peer)
718e3744 1538{
d62a17ae 1539 if (peer->fd < 0) {
e50f7cfd 1540 flog_err(EC_BGP_CONNECT,
1c50c1c0
QY
1541 "bgp_connect_success peer's fd is negative value %d",
1542 peer->fd);
d62a17ae 1543 bgp_stop(peer);
1544 return -1;
1545 }
1546
1547 if (bgp_getsockname(peer) < 0) {
450971aa 1548 flog_err_sys(EC_LIB_SOCKET,
09c866e3 1549 "%s: bgp_getsockname(): failed for peer %s, fd %d",
15569c58 1550 __func__, peer->host, peer->fd);
3893aeee
DA
1551 bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
1552 bgp_fsm_error_subcode(peer->status));
424ab01d 1553 bgp_writes_on(peer);
d62a17ae 1554 return -1;
1555 }
1556
424ab01d 1557 bgp_reads_on(peer);
d62a17ae 1558
1559 if (bgp_debug_neighbor_events(peer)) {
d62a17ae 1560 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
c0d72166
DS
1561 zlog_debug("%s open active, local address %pSU",
1562 peer->host, peer->su_local);
d62a17ae 1563 else
1564 zlog_debug("%s passive open", peer->host);
1565 }
1566
6c537a18 1567 /* Send an open message */
d62a17ae 1568 bgp_open_send(peer);
1569
1570 return 0;
718e3744 1571}
1572
6c537a18
DS
1573/* TCP connection open with RFC 4271 optional session attribute DelayOpen flag
1574 * set.
1575 */
1576static int bgp_connect_success_w_delayopen(struct peer *peer)
1577{
1578 if (peer->fd < 0) {
1579 flog_err(EC_BGP_CONNECT, "%s: peer's fd is negative value %d",
1580 __func__, peer->fd);
1581 bgp_stop(peer);
1582 return -1;
1583 }
1584
1585 if (bgp_getsockname(peer) < 0) {
1586 flog_err_sys(EC_LIB_SOCKET,
1587 "%s: bgp_getsockname(): failed for peer %s, fd %d",
1588 __func__, peer->host, peer->fd);
1589 bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
1590 bgp_fsm_error_subcode(peer->status));
1591 bgp_writes_on(peer);
1592 return -1;
1593 }
1594
1595 bgp_reads_on(peer);
1596
1597 if (bgp_debug_neighbor_events(peer)) {
6c537a18 1598 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
c0d72166
DS
1599 zlog_debug("%s open active, local address %pSU",
1600 peer->host, peer->su_local);
6c537a18
DS
1601 else
1602 zlog_debug("%s passive open", peer->host);
1603 }
1604
1605 /* set the DelayOpenTime to the inital value */
1606 peer->v_delayopen = peer->delayopen;
1607
1608 /* Start the DelayOpenTimer if it is not already running */
1609 if (!peer->t_delayopen)
1610 BGP_TIMER_ON(peer->t_delayopen, bgp_delayopen_timer,
1611 peer->v_delayopen);
1612
1613 if (bgp_debug_neighbor_events(peer))
1614 zlog_debug("%s [FSM] BGP OPEN message delayed for %d seconds",
1615 peer->host, peer->delayopen);
1616
1617 return 0;
1618}
1619
718e3744 1620/* TCP connect fail */
d62a17ae 1621static int bgp_connect_fail(struct peer *peer)
718e3744 1622{
d62a17ae 1623 if (peer_dynamic_neighbor(peer)) {
1624 if (bgp_debug_neighbor_events(peer))
1625 zlog_debug("%s (dynamic neighbor) deleted", peer->host);
1626 peer_delete(peer);
1627 return -1;
1628 }
1629
8761cd6d
DS
1630 /*
1631 * If we are doing nht for a peer that ls v6 LL based
1632 * massage the event system to make things happy
1633 */
1634 bgp_nht_interface_events(peer);
1635
d62a17ae 1636 return (bgp_stop(peer));
718e3744 1637}
1638
1639/* This function is the first starting point of all BGP connection. It
6c537a18
DS
1640 * try to connect to remote peer with non-blocking IO.
1641 */
d62a17ae 1642int bgp_start(struct peer *peer)
718e3744 1643{
d62a17ae 1644 int status;
d62a17ae 1645
1646 bgp_peer_conf_if_to_su_update(peer);
1647
1648 if (peer->su.sa.sa_family == AF_UNSPEC) {
1649 if (bgp_debug_neighbor_events(peer))
1650 zlog_debug(
1651 "%s [FSM] Unable to get neighbor's IP address, waiting...",
1652 peer->host);
3577f1c5 1653 peer->last_reset = PEER_DOWN_NBR_ADDR;
d62a17ae 1654 return -1;
1655 }
1656
1657 if (BGP_PEER_START_SUPPRESSED(peer)) {
1658 if (bgp_debug_neighbor_events(peer))
e50f7cfd 1659 flog_err(EC_BGP_FSM,
3efd0893 1660 "%s [FSM] Trying to start suppressed peer - this is never supposed to happen!",
1c50c1c0 1661 peer->host);
07d1e5d9
DA
1662 if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
1663 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
cb9196e7
DS
1664 else if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN))
1665 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
07d1e5d9
DA
1666 else if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
1667 peer->last_reset = PEER_DOWN_PFX_COUNT;
d62a17ae 1668 return -1;
1669 }
1670
1671 /* Scrub some information that might be left over from a previous,
1672 * session
1673 */
1674 /* Connection information. */
1675 if (peer->su_local) {
1676 sockunion_free(peer->su_local);
1677 peer->su_local = NULL;
1678 }
1679
1680 if (peer->su_remote) {
1681 sockunion_free(peer->su_remote);
1682 peer->su_remote = NULL;
1683 }
1684
1685 /* Clear remote router-id. */
975a328e 1686 peer->remote_id.s_addr = INADDR_ANY;
d62a17ae 1687
1688 /* Clear peer capability flag. */
1689 peer->cap = 0;
1690
1691 /* If the peer is passive mode, force to move to Active mode. */
1692 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
1693 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1694 return 0;
1695 }
1696
2c1eba8e 1697 if (peer->bgp->vrf_id == VRF_UNKNOWN) {
61cf4b37 1698 if (bgp_debug_neighbor_events(peer))
af4c2728 1699 flog_err(
e50f7cfd 1700 EC_BGP_FSM,
996c9314
LB
1701 "%s [FSM] In a VRF that is not initialised yet",
1702 peer->host);
3577f1c5 1703 peer->last_reset = PEER_DOWN_VRF_UNINIT;
61cf4b37
PG
1704 return -1;
1705 }
1706
e2d3a909 1707 /* Register peer for NHT. If next hop is already resolved, proceed
1708 * with connection setup, else wait.
1709 */
1710 if (!bgp_peer_reg_with_nht(peer)) {
c42eab4b
DS
1711 if (bgp_zebra_num_connects()) {
1712 if (bgp_debug_neighbor_events(peer))
1713 zlog_debug("%s [FSM] Waiting for NHT",
1714 peer->host);
3577f1c5 1715 peer->last_reset = PEER_DOWN_WAITING_NHT;
c42eab4b
DS
1716 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1717 return 0;
1718 }
718e3744 1719 }
d62a17ae 1720
424ab01d
QY
1721 assert(!peer->t_write);
1722 assert(!peer->t_read);
1723 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
1724 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
d62a17ae 1725 status = bgp_connect(peer);
1726
1727 switch (status) {
1728 case connect_error:
1729 if (bgp_debug_neighbor_events(peer))
1730 zlog_debug("%s [FSM] Connect error", peer->host);
1731 BGP_EVENT_ADD(peer, TCP_connection_open_failed);
1732 break;
1733 case connect_success:
1734 if (bgp_debug_neighbor_events(peer))
1735 zlog_debug(
1736 "%s [FSM] Connect immediately success, fd %d",
1737 peer->host, peer->fd);
6c537a18 1738
d62a17ae 1739 BGP_EVENT_ADD(peer, TCP_connection_open);
1740 break;
1741 case connect_in_progress:
1742 /* To check nonblocking connect, we wait until socket is
1743 readable or writable. */
1744 if (bgp_debug_neighbor_events(peer))
1745 zlog_debug(
1746 "%s [FSM] Non blocking connect waiting result, fd %d",
1747 peer->host, peer->fd);
1748 if (peer->fd < 0) {
e50f7cfd 1749 flog_err(EC_BGP_FSM,
1c50c1c0
QY
1750 "bgp_start peer's fd is negative value %d",
1751 peer->fd);
d62a17ae 1752 return -1;
1753 }
becedef6 1754 /*
387f984e
QY
1755 * - when the socket becomes ready, poll() will signify POLLOUT
1756 * - if it fails to connect, poll() will signify POLLHUP
1757 * - POLLHUP is handled as a 'read' event by thread.c
1758 *
1759 * therefore, we schedule both a read and a write event with
1760 * bgp_connect_check() as the handler for each and cancel the
1761 * unused event in that function.
becedef6 1762 */
424ab01d 1763 thread_add_read(bm->master, bgp_connect_check, peer, peer->fd,
387f984e
QY
1764 &peer->t_connect_check_r);
1765 thread_add_write(bm->master, bgp_connect_check, peer, peer->fd,
1766 &peer->t_connect_check_w);
d62a17ae 1767 break;
1768 }
1769 return 0;
718e3744 1770}
1771
1772/* Connect retry timer is expired when the peer status is Connect. */
d62a17ae 1773static int bgp_reconnect(struct peer *peer)
718e3744 1774{
d62a17ae 1775 if (bgp_stop(peer) < 0)
1776 return -1;
1ff9a340 1777
8c48b3b6 1778 /* Send graceful restart capabilty */
36235319
QY
1779 BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
1780 peer->bgp->peer);
8c48b3b6 1781
d62a17ae 1782 bgp_start(peer);
1783 return 0;
718e3744 1784}
1785
d62a17ae 1786static int bgp_fsm_open(struct peer *peer)
718e3744 1787{
6c537a18
DS
1788 /* If DelayOpen is active, we may still need to send an open message */
1789 if ((peer->status == Connect) || (peer->status == Active))
1790 bgp_open_send(peer);
1791
d62a17ae 1792 /* Send keepalive and make keepalive timer */
1793 bgp_keepalive_send(peer);
718e3744 1794
d62a17ae 1795 return 0;
718e3744 1796}
1797
397b5bde
LR
1798/* FSM error, unexpected event. This is error of BGP connection. So cut the
1799 peer and change to Idle status. */
d62a17ae 1800static int bgp_fsm_event_error(struct peer *peer)
397b5bde 1801{
1c50c1c0
QY
1802 flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s",
1803 peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
397b5bde 1804
3893aeee
DA
1805 return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR,
1806 bgp_fsm_error_subcode(peer->status));
397b5bde
LR
1807}
1808
718e3744 1809/* Hold timer expire. This is error of BGP connection. So cut the
1810 peer and change to Idle status. */
d62a17ae 1811static int bgp_fsm_holdtime_expire(struct peer *peer)
718e3744 1812{
d62a17ae 1813 if (bgp_debug_neighbor_events(peer))
1814 zlog_debug("%s [FSM] Hold timer expire", peer->host);
718e3744 1815
d62a17ae 1816 return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0);
718e3744 1817}
1818
6c537a18
DS
1819/* RFC 4271 DelayOpenTimer_Expires event */
1820static int bgp_fsm_delayopen_timer_expire(struct peer *peer)
1821{
1822 /* Stop the DelayOpenTimer */
1823 BGP_TIMER_OFF(peer->t_delayopen);
1824
1825 /* Send open message to peer */
1826 bgp_open_send(peer);
1827
1828 /* Set the HoldTimer to a large value (4 minutes) */
1829 peer->v_holdtime = 245;
1830
1831 return 0;
1832}
1833
f009ff26 1834/* Start the selection deferral timer thread for the specified AFI, SAFI */
1835static int bgp_start_deferral_timer(struct bgp *bgp, afi_t afi, safi_t safi,
36235319 1836 struct graceful_restart_info *gr_info)
f009ff26 1837{
1838 struct afi_safi_info *thread_info;
1839
1840 /* If the deferral timer is active, then increment eor count */
1841 if (gr_info->t_select_deferral) {
1842 gr_info->eor_required++;
1843 return 0;
1844 }
1845
1846 /* Start the deferral timer when the first peer enabled for the graceful
1847 * restart is established
1848 */
1849 if (gr_info->eor_required == 0) {
1850 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 1851
1852 thread_info->afi = afi;
1853 thread_info->safi = safi;
1854 thread_info->bgp = bgp;
1855
13909c4f
DS
1856 thread_add_timer(bm->master, bgp_graceful_deferral_timer_expire,
1857 thread_info, bgp->select_defer_time,
1858 &gr_info->t_select_deferral);
f009ff26 1859 }
f009ff26 1860 gr_info->eor_required++;
8c48b3b6 1861 /* Send message to RIB indicating route update pending */
1862 if (gr_info->af_enabled[afi][safi] == false) {
1863 gr_info->af_enabled[afi][safi] = true;
1864 /* Send message to RIB */
1865 bgp_zebra_update(afi, safi, bgp->vrf_id,
1866 ZEBRA_CLIENT_ROUTE_UPDATE_PENDING);
1867 }
f009ff26 1868 if (BGP_DEBUG(update, UPDATE_OUT))
1869 zlog_debug("Started the deferral timer for %s eor_required %d",
36235319
QY
1870 get_afi_safi_str(afi, safi, false),
1871 gr_info->eor_required);
f009ff26 1872 return 0;
1873}
1874
1875/* Update the graceful restart information for the specified AFI, SAFI */
1876static int bgp_update_gr_info(struct peer *peer, afi_t afi, safi_t safi)
1877{
1878 struct graceful_restart_info *gr_info;
1879 struct bgp *bgp = peer->bgp;
1880 int ret = 0;
1881
1882 if ((afi < AFI_IP) || (afi >= AFI_MAX)) {
1883 if (BGP_DEBUG(update, UPDATE_OUT))
1884 zlog_debug("%s : invalid afi %d", __func__, afi);
1885 return -1;
1886 }
1887
1888 if ((safi < SAFI_UNICAST) || (safi > SAFI_MPLS_VPN)) {
1889 if (BGP_DEBUG(update, UPDATE_OUT))
1890 zlog_debug("%s : invalid safi %d", __func__, safi);
1891 return -1;
1892 }
1893
1894 /* Restarting router */
36235319
QY
1895 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
1896 && BGP_PEER_RESTARTING_MODE(peer)) {
f009ff26 1897 /* Check if the forwarding state is preserved */
892fedb6 1898 if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD)) {
f009ff26 1899 gr_info = &(bgp->gr_info[afi][safi]);
1900 ret = bgp_start_deferral_timer(bgp, afi, safi, gr_info);
1901 }
1902 }
2ba1fe69 1903 return ret;
f009ff26 1904}
1905
727c4f87
QY
1906/**
1907 * Transition to Established state.
1908 *
1909 * Convert peer from stub to full fledged peer, set some timers, and generate
1910 * initial updates.
1911 */
d62a17ae 1912static int bgp_establish(struct peer *peer)
718e3744 1913{
d62a17ae 1914 afi_t afi;
1915 safi_t safi;
1916 int nsf_af_count = 0;
1917 int ret = 0;
1918 struct peer *other;
f009ff26 1919 int status;
d62a17ae 1920
1921 other = peer->doppelganger;
1922 peer = peer_xfer_conn(peer);
1923 if (!peer) {
e50f7cfd 1924 flog_err(EC_BGP_CONNECT, "%%Neighbor failed in xfer_conn");
d62a17ae 1925 return -1;
93406d87 1926 }
93406d87 1927
d62a17ae 1928 if (other == peer)
996c9314
LB
1929 ret = 1; /* bgp_establish specific code when xfer_conn
1930 happens. */
d62a17ae 1931
1932 /* Reset capability open status flag. */
1933 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
1934 SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1935
1936 /* Clear start timer value to default. */
1937 peer->v_start = BGP_INIT_START_TIMER;
1938
1939 /* Increment established count. */
1940 peer->established++;
1941 bgp_fsm_change_status(peer, Established);
1942
1943 /* bgp log-neighbor-changes of neighbor Up */
892fedb6 1944 if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
d62a17ae 1945 struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
892fedb6
DA
1946 zlog_info(
1947 "%%ADJCHANGE: neighbor %s(%s) in vrf %s Up", peer->host,
1948 (peer->hostname) ? peer->hostname : "Unknown",
1949 vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
1950 : VRF_DEFAULT_NAME)
1951 : "");
d62a17ae 1952 }
1953 /* assign update-group/subgroup */
1954 update_group_adjust_peer_afs(peer);
1955
1956 /* graceful restart */
1957 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
f009ff26 1958 if (bgp_debug_neighbor_events(peer)) {
1959 if (BGP_PEER_RESTARTING_MODE(peer))
36235319 1960 zlog_debug("peer %s BGP_RESTARTING_MODE", peer->host);
f009ff26 1961 else if (BGP_PEER_HELPER_MODE(peer))
36235319 1962 zlog_debug("peer %s BGP_HELPER_MODE", peer->host);
f009ff26 1963 }
d62a17ae 1964 for (afi = AFI_IP; afi < AFI_MAX; afi++)
a08ca0a7 1965 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++) {
d62a17ae 1966 if (peer->afc_nego[afi][safi]
1967 && CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV)
1968 && CHECK_FLAG(peer->af_cap[afi][safi],
1969 PEER_CAP_RESTART_AF_RCV)) {
1970 if (peer->nsf[afi][safi]
1971 && !CHECK_FLAG(
1972 peer->af_cap[afi][safi],
1973 PEER_CAP_RESTART_AF_PRESERVE_RCV))
1974 bgp_clear_stale_route(peer, afi, safi);
1975
1976 peer->nsf[afi][safi] = 1;
1977 nsf_af_count++;
1978 } else {
1979 if (peer->nsf[afi][safi])
1980 bgp_clear_stale_route(peer, afi, safi);
1981 peer->nsf[afi][safi] = 0;
1982 }
f009ff26 1983 /* Update the graceful restart information */
1984 if (peer->afc_nego[afi][safi]) {
1985 if (!BGP_SELECT_DEFER_DISABLE(peer->bgp)) {
1986 status = bgp_update_gr_info(peer, afi,
1987 safi);
1988 if (status < 0)
36235319
QY
1989 zlog_err(
1990 "Error in updating graceful restart for %s",
1991 get_afi_safi_str(
1992 afi, safi,
1993 false));
9e3b51a7 1994 } else {
1995 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(
36235319
QY
1996 peer)
1997 && BGP_PEER_RESTARTING_MODE(peer)
892fedb6
DA
1998 && CHECK_FLAG(
1999 peer->bgp->flags,
36235319 2000 BGP_FLAG_GR_PRESERVE_FWD))
9e3b51a7 2001 peer->bgp->gr_info[afi][safi]
2002 .eor_required++;
f009ff26 2003 }
2004 }
d62a17ae 2005 }
2006
77b34214
NT
2007 if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
2008 if ((bgp_peer_gr_mode_get(peer) == PEER_GR)
2009 || ((bgp_peer_gr_mode_get(peer) == PEER_GLOBAL_INHERIT)
2010 && (bgp_global_gr_mode_get(peer->bgp) == GLOBAL_GR))) {
2011 FOREACH_AFI_SAFI (afi, safi)
2012 /* Send route processing complete
2013 message to RIB */
2014 bgp_zebra_update(
2015 afi, safi, peer->bgp->vrf_id,
2016 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
2017 }
2018 } else {
2019 /* Peer sends R-bit. In this case, we need to send
2020 * ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE to Zebra. */
2021 if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV)) {
2022 FOREACH_AFI_SAFI (afi, safi)
2023 /* Send route processing complete
2024 message to RIB */
2025 bgp_zebra_update(
2026 afi, safi, peer->bgp->vrf_id,
2027 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
2028 }
2029 }
2030
794b37d5 2031 peer->nsf_af_count = nsf_af_count;
2032
d62a17ae 2033 if (nsf_af_count)
2034 SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
2035 else {
2036 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
2037 if (peer->t_gr_stale) {
2038 BGP_TIMER_OFF(peer->t_gr_stale);
2039 if (bgp_debug_neighbor_events(peer))
2040 zlog_debug(
2041 "%s graceful restart stalepath timer stopped",
2042 peer->host);
2043 }
2044 }
93406d87 2045
d62a17ae 2046 if (peer->t_gr_restart) {
2047 BGP_TIMER_OFF(peer->t_gr_restart);
2048 if (bgp_debug_neighbor_events(peer))
2049 zlog_debug("%s graceful restart timer stopped",
2050 peer->host);
2051 }
718e3744 2052
9eb217ff
QY
2053 /* Reset uptime, turn on keepalives, send current table. */
2054 if (!peer->v_holdtime)
2055 bgp_keepalives_on(peer);
2056
d62a17ae 2057 peer->uptime = bgp_clock();
2058
2059 /* Send route-refresh when ORF is enabled */
05c7a1cc
QY
2060 FOREACH_AFI_SAFI (afi, safi) {
2061 if (CHECK_FLAG(peer->af_cap[afi][safi],
2062 PEER_CAP_ORF_PREFIX_SM_ADV)) {
d62a17ae 2063 if (CHECK_FLAG(peer->af_cap[afi][safi],
05c7a1cc 2064 PEER_CAP_ORF_PREFIX_RM_RCV))
9af52ccf
DA
2065 bgp_route_refresh_send(
2066 peer, afi, safi, ORF_TYPE_PREFIX,
2067 REFRESH_IMMEDIATE, 0,
2068 BGP_ROUTE_REFRESH_NORMAL);
05c7a1cc
QY
2069 else if (CHECK_FLAG(peer->af_cap[afi][safi],
2070 PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
9af52ccf
DA
2071 bgp_route_refresh_send(
2072 peer, afi, safi, ORF_TYPE_PREFIX_OLD,
2073 REFRESH_IMMEDIATE, 0,
2074 BGP_ROUTE_REFRESH_NORMAL);
05c7a1cc
QY
2075 }
2076 }
d62a17ae 2077
2078 /* First update is deferred until ORF or ROUTE-REFRESH is received */
05c7a1cc
QY
2079 FOREACH_AFI_SAFI (afi, safi) {
2080 if (CHECK_FLAG(peer->af_cap[afi][safi],
2081 PEER_CAP_ORF_PREFIX_RM_ADV))
d62a17ae 2082 if (CHECK_FLAG(peer->af_cap[afi][safi],
05c7a1cc
QY
2083 PEER_CAP_ORF_PREFIX_SM_RCV)
2084 || CHECK_FLAG(peer->af_cap[afi][safi],
2085 PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
2086 SET_FLAG(peer->af_sflags[afi][safi],
2087 PEER_STATUS_ORF_WAIT_REFRESH);
2088 }
d62a17ae 2089
2090 bgp_announce_peer(peer);
2091
2092 /* Start the route advertisement timer to send updates to the peer - if
2093 * BGP
2094 * is not in read-only mode. If it is, the timer will be started at the
2095 * end
2096 * of read-only mode.
2097 */
2098 if (!bgp_update_delay_active(peer->bgp)) {
2099 BGP_TIMER_OFF(peer->t_routeadv);
2100 BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
2101 }
718e3744 2102
d62a17ae 2103 if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
2104 if (bgp_debug_neighbor_events(peer))
2105 zlog_debug(
2106 "[Event] Deleting stub connection for peer %s",
2107 peer->host);
2108
2109 if (peer->doppelganger->status > Active)
2110 bgp_notify_send(peer->doppelganger, BGP_NOTIFY_CEASE,
2111 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
2112 else
2113 peer_delete(peer->doppelganger);
718e3744 2114 }
2115
19bd3dff
DS
2116 /*
2117 * If we are replacing the old peer for a doppelganger
2118 * then switch it around in the bgp->peerhash
2119 * the doppelgangers su and this peer's su are the same
2120 * so the hash_release is the same for either.
2121 */
2122 hash_release(peer->bgp->peerhash, peer);
2123 hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
2124
21bfce98
RZ
2125 /* Start BFD peer if not already running. */
2126 if (peer->bfd_config)
2127 bgp_peer_bfd_update_source(peer);
2128
d62a17ae 2129 return ret;
718e3744 2130}
2131
2132/* Keepalive packet is received. */
d62a17ae 2133static int bgp_fsm_keepalive(struct peer *peer)
718e3744 2134{
d62a17ae 2135 BGP_TIMER_OFF(peer->t_holdtime);
2136 return 0;
718e3744 2137}
2138
2139/* Update packet is received. */
d62a17ae 2140static int bgp_fsm_update(struct peer *peer)
718e3744 2141{
d62a17ae 2142 BGP_TIMER_OFF(peer->t_holdtime);
2143 return 0;
718e3744 2144}
2145
2146/* This is empty event. */
d62a17ae 2147static int bgp_ignore(struct peer *peer)
718e3744 2148{
af4c2728 2149 flog_err(
e50f7cfd 2150 EC_BGP_FSM,
d62a17ae 2151 "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
2152 peer->host, bgp_event_str[peer->cur_event],
2153 lookup_msg(bgp_status_msg, peer->status, NULL),
2154 bgp_event_str[peer->last_event],
2155 bgp_event_str[peer->last_major_event], peer->fd);
2156 return 0;
718e3744 2157}
6b0655a2 2158
6403814c 2159/* This is to handle unexpected events.. */
d62a17ae 2160static int bgp_fsm_exeption(struct peer *peer)
6403814c 2161{
af4c2728 2162 flog_err(
e50f7cfd 2163 EC_BGP_FSM,
d62a17ae 2164 "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
2165 peer->host, bgp_event_str[peer->cur_event],
2166 lookup_msg(bgp_status_msg, peer->status, NULL),
2167 bgp_event_str[peer->last_event],
2168 bgp_event_str[peer->last_major_event], peer->fd);
2169 return (bgp_stop(peer));
6403814c
DS
2170}
2171
f8dcd38d 2172void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops)
fc9a856f 2173{
d62a17ae 2174 if (!peer)
2175 return;
2176
2177 switch (peer->status) {
2178 case Idle:
f8dcd38d 2179 if (has_valid_nexthops)
d62a17ae 2180 BGP_EVENT_ADD(peer, BGP_Start);
2181 break;
2182 case Connect:
f8dcd38d 2183 if (!has_valid_nexthops) {
d62a17ae 2184 BGP_TIMER_OFF(peer->t_connect);
2185 BGP_EVENT_ADD(peer, TCP_fatal_error);
2186 }
2187 break;
2188 case Active:
f8dcd38d 2189 if (has_valid_nexthops) {
d62a17ae 2190 BGP_TIMER_OFF(peer->t_connect);
2191 BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
2192 }
2193 break;
2194 case OpenSent:
2195 case OpenConfirm:
2196 case Established:
f8dcd38d 2197 if (!has_valid_nexthops
f852eb98
PG
2198 && (peer->gtsm_hops == BGP_GTSM_HOPS_CONNECTED
2199 || peer->bgp->fast_convergence))
d62a17ae 2200 BGP_EVENT_ADD(peer, TCP_fatal_error);
2201 case Clearing:
2202 case Deleted:
2203 default:
2204 break;
fc9a856f 2205 }
fc9a856f
DS
2206}
2207
718e3744 2208/* Finite State Machine structure */
fda1d3e0 2209static const struct {
d62a17ae 2210 int (*func)(struct peer *);
8398b5d5 2211 enum bgp_fsm_status next_state;
d62a17ae 2212} FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = {
2213 {
2214 /* Idle state: In Idle state, all events other than BGP_Start is
2215 ignored. With BGP_Start event, finite state machine calls
2216 bgp_start(). */
2217 {bgp_start, Connect}, /* BGP_Start */
2218 {bgp_stop, Idle}, /* BGP_Stop */
2219 {bgp_stop, Idle}, /* TCP_connection_open */
6c537a18 2220 {bgp_stop, Idle}, /* TCP_connection_open_w_delay */
d62a17ae 2221 {bgp_stop, Idle}, /* TCP_connection_closed */
2222 {bgp_ignore, Idle}, /* TCP_connection_open_failed */
2223 {bgp_stop, Idle}, /* TCP_fatal_error */
2224 {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
2225 {bgp_ignore, Idle}, /* Hold_Timer_expired */
2226 {bgp_ignore, Idle}, /* KeepAlive_timer_expired */
6c537a18 2227 {bgp_ignore, Idle}, /* DelayOpen_timer_expired */
d62a17ae 2228 {bgp_ignore, Idle}, /* Receive_OPEN_message */
2229 {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
2230 {bgp_ignore, Idle}, /* Receive_UPDATE_message */
2231 {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
2232 {bgp_ignore, Idle}, /* Clearing_Completed */
2233 },
2234 {
2235 /* Connect */
2236 {bgp_ignore, Connect}, /* BGP_Start */
2237 {bgp_stop, Idle}, /* BGP_Stop */
2238 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
6c537a18
DS
2239 {bgp_connect_success_w_delayopen,
2240 Connect}, /* TCP_connection_open_w_delay */
d62a17ae 2241 {bgp_stop, Idle}, /* TCP_connection_closed */
2242 {bgp_connect_fail, Active}, /* TCP_connection_open_failed */
2243 {bgp_connect_fail, Idle}, /* TCP_fatal_error */
2244 {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
2245 {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
2246 {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
6c537a18
DS
2247 {bgp_fsm_delayopen_timer_expire,
2248 OpenSent}, /* DelayOpen_timer_expired */
2249 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
2250 {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
2251 {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
2252 {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
2253 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
d62a17ae 2254 },
2255 {
2256 /* Active, */
2257 {bgp_ignore, Active}, /* BGP_Start */
2258 {bgp_stop, Idle}, /* BGP_Stop */
2259 {bgp_connect_success, OpenSent}, /* TCP_connection_open */
6c537a18
DS
2260 {bgp_connect_success_w_delayopen,
2261 Active}, /* TCP_connection_open_w_delay */
d62a17ae 2262 {bgp_stop, Idle}, /* TCP_connection_closed */
2263 {bgp_ignore, Active}, /* TCP_connection_open_failed */
2264 {bgp_fsm_exeption, Idle}, /* TCP_fatal_error */
2265 {bgp_start, Connect}, /* ConnectRetry_timer_expired */
2266 {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
2267 {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
6c537a18
DS
2268 {bgp_fsm_delayopen_timer_expire,
2269 OpenSent}, /* DelayOpen_timer_expired */
2270 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
2271 {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
2272 {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
2273 {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */
2274 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
d62a17ae 2275 },
2276 {
2277 /* OpenSent, */
2278 {bgp_ignore, OpenSent}, /* BGP_Start */
2279 {bgp_stop, Idle}, /* BGP_Stop */
2280 {bgp_stop, Active}, /* TCP_connection_open */
6c537a18 2281 {bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */
d62a17ae 2282 {bgp_stop, Active}, /* TCP_connection_closed */
2283 {bgp_stop, Active}, /* TCP_connection_open_failed */
2284 {bgp_stop, Active}, /* TCP_fatal_error */
2285 {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
2286 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
2287 {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
6c537a18 2288 {bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */
d62a17ae 2289 {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
2290 {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
2291 {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
53b4aaec 2292 {bgp_fsm_event_error, Idle}, /* Receive_NOTIFICATION_message */
d62a17ae 2293 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
2294 },
2295 {
2296 /* OpenConfirm, */
2297 {bgp_ignore, OpenConfirm}, /* BGP_Start */
2298 {bgp_stop, Idle}, /* BGP_Stop */
2299 {bgp_stop, Idle}, /* TCP_connection_open */
6c537a18 2300 {bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */
d62a17ae 2301 {bgp_stop, Idle}, /* TCP_connection_closed */
2302 {bgp_stop, Idle}, /* TCP_connection_open_failed */
2303 {bgp_stop, Idle}, /* TCP_fatal_error */
2304 {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
2305 {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
2306 {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
6c537a18 2307 {bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */
d62a17ae 2308 {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
2309 {bgp_establish, Established}, /* Receive_KEEPALIVE_message */
2310 {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
2311 {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
2312 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
2313 },
2314 {
2315 /* Established, */
2316 {bgp_ignore, Established}, /* BGP_Start */
2317 {bgp_stop, Clearing}, /* BGP_Stop */
2318 {bgp_stop, Clearing}, /* TCP_connection_open */
6c537a18 2319 {bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */
d62a17ae 2320 {bgp_stop, Clearing}, /* TCP_connection_closed */
2321 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
2322 {bgp_stop, Clearing}, /* TCP_fatal_error */
2323 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
2324 {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
03014d48 2325 {bgp_ignore, Established}, /* KeepAlive_timer_expired */
6c537a18 2326 {bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */
03014d48 2327 {bgp_stop, Clearing}, /* Receive_OPEN_message */
d62a17ae 2328 {bgp_fsm_keepalive,
2329 Established}, /* Receive_KEEPALIVE_message */
2330 {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
2331 {bgp_stop_with_error,
2332 Clearing}, /* Receive_NOTIFICATION_message */
2333 {bgp_fsm_exeption, Idle}, /* Clearing_Completed */
2334 },
2335 {
2336 /* Clearing, */
2337 {bgp_ignore, Clearing}, /* BGP_Start */
2338 {bgp_stop, Clearing}, /* BGP_Stop */
2339 {bgp_stop, Clearing}, /* TCP_connection_open */
6c537a18 2340 {bgp_stop, Clearing}, /* TCP_connection_open_w_delay */
d62a17ae 2341 {bgp_stop, Clearing}, /* TCP_connection_closed */
2342 {bgp_stop, Clearing}, /* TCP_connection_open_failed */
2343 {bgp_stop, Clearing}, /* TCP_fatal_error */
2344 {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
2345 {bgp_stop, Clearing}, /* Hold_Timer_expired */
2346 {bgp_stop, Clearing}, /* KeepAlive_timer_expired */
6c537a18 2347 {bgp_stop, Clearing}, /* DelayOpen_timer_expired */
d62a17ae 2348 {bgp_stop, Clearing}, /* Receive_OPEN_message */
2349 {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
2350 {bgp_stop, Clearing}, /* Receive_UPDATE_message */
2351 {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
2352 {bgp_clearing_completed, Idle}, /* Clearing_Completed */
2353 },
2354 {
2355 /* Deleted, */
2356 {bgp_ignore, Deleted}, /* BGP_Start */
2357 {bgp_ignore, Deleted}, /* BGP_Stop */
2358 {bgp_ignore, Deleted}, /* TCP_connection_open */
6c537a18 2359 {bgp_ignore, Deleted}, /* TCP_connection_open_w_delay */
d62a17ae 2360 {bgp_ignore, Deleted}, /* TCP_connection_closed */
2361 {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
2362 {bgp_ignore, Deleted}, /* TCP_fatal_error */
2363 {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
2364 {bgp_ignore, Deleted}, /* Hold_Timer_expired */
2365 {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
6c537a18 2366 {bgp_ignore, Deleted}, /* DelayOpen_timer_expired */
d62a17ae 2367 {bgp_ignore, Deleted}, /* Receive_OPEN_message */
2368 {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
2369 {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
2370 {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
2371 {bgp_ignore, Deleted}, /* Clearing_Completed */
2372 },
718e3744 2373};
2374
718e3744 2375/* Execute event process. */
d62a17ae 2376int bgp_event(struct thread *thread)
718e3744 2377{
d1060698 2378 enum bgp_fsm_events event;
d62a17ae 2379 struct peer *peer;
2380 int ret;
718e3744 2381
d62a17ae 2382 peer = THREAD_ARG(thread);
2383 event = THREAD_VAL(thread);
718e3744 2384
d62a17ae 2385 ret = bgp_event_update(peer, event);
1ff9a340 2386
d62a17ae 2387 return (ret);
1ff9a340
DS
2388}
2389
d1060698 2390int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
1ff9a340 2391{
8398b5d5 2392 enum bgp_fsm_status next;
d62a17ae 2393 int ret = 0;
2394 struct peer *other;
2395 int passive_conn = 0;
2396 int dyn_nbr;
2397
d8151687
QY
2398 /* default return code */
2399 ret = FSM_PEER_NOOP;
2400
d62a17ae 2401 other = peer->doppelganger;
2402 passive_conn =
2403 (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0;
2404 dyn_nbr = peer_dynamic_neighbor(peer);
2405
2406 /* Logging this event. */
2407 next = FSM[peer->status - 1][event - 1].next_state;
2408
2409 if (bgp_debug_neighbor_events(peer) && peer->status != next)
2410 zlog_debug("%s [FSM] %s (%s->%s), fd %d", peer->host,
2411 bgp_event_str[event],
2412 lookup_msg(bgp_status_msg, peer->status, NULL),
2413 lookup_msg(bgp_status_msg, next, NULL), peer->fd);
2414
2415 peer->last_event = peer->cur_event;
2416 peer->cur_event = event;
2417
2418 /* Call function. */
2419 if (FSM[peer->status - 1][event - 1].func)
2420 ret = (*(FSM[peer->status - 1][event - 1].func))(peer);
2421
d62a17ae 2422 if (ret >= 0) {
2423 if (ret == 1 && next == Established) {
2424 /* The case when doppelganger swap accurred in
2425 bgp_establish.
2426 Update the peer pointer accordingly */
d8151687 2427 ret = FSM_PEER_TRANSFERRED;
d62a17ae 2428 peer = other;
2429 }
2430
2431 /* If status is changed. */
d8151687 2432 if (next != peer->status) {
d62a17ae 2433 bgp_fsm_change_status(peer, next);
2434
becedef6
QY
2435 /*
2436 * If we're going to ESTABLISHED then we executed a
2437 * peer transfer. In this case we can either return
2438 * FSM_PEER_TRANSITIONED or FSM_PEER_TRANSFERRED.
2439 * Opting for TRANSFERRED since transfer implies
2440 * session establishment.
2441 */
d8151687
QY
2442 if (ret != FSM_PEER_TRANSFERRED)
2443 ret = FSM_PEER_TRANSITIONED;
2444 }
2445
d62a17ae 2446 /* Make sure timer is set. */
2447 bgp_timer_set(peer);
2448
bea01226 2449 } else {
becedef6
QY
2450 /*
2451 * If we got a return value of -1, that means there was an
2452 * error, restart the FSM. Since bgp_stop() was called on the
2453 * peer. only a few fields are safe to access here. In any case
2454 * we need to indicate that the peer was stopped in the return
2455 * code.
2456 */
bea01226 2457 if (!dyn_nbr && !passive_conn && peer->bgp) {
af4c2728 2458 flog_err(
e50f7cfd 2459 EC_BGP_FSM,
3efd0893 2460 "%s [FSM] Failure handling event %s in state %s, prior events %s, %s, fd %d",
bea01226
QY
2461 peer->host, bgp_event_str[peer->cur_event],
2462 lookup_msg(bgp_status_msg, peer->status, NULL),
2463 bgp_event_str[peer->last_event],
2464 bgp_event_str[peer->last_major_event],
2465 peer->fd);
2466 bgp_stop(peer);
2467 bgp_fsm_change_status(peer, Idle);
2468 bgp_timer_set(peer);
2469 }
2470 ret = FSM_PEER_STOPPED;
d62a17ae 2471 }
bea01226 2472
d62a17ae 2473 return ret;
718e3744 2474}
794b37d5 2475/* BGP GR Code */
2476
2477int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp,
36235319
QY
2478 enum global_mode global_new_state,
2479 enum global_mode global_old_state)
794b37d5 2480{
2481 struct peer *peer = {0};
2482 struct listnode *node = {0};
2483 struct listnode *nnode = {0};
36235319 2484 enum peer_mode peer_old_state = PEER_INVALID;
794b37d5 2485
2486 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
2487
2488 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319
QY
2489 zlog_debug("%s [BGP_GR] Peer: (%s) :", __func__,
2490 peer->host);
794b37d5 2491
2492 peer_old_state = bgp_peer_gr_mode_get(peer);
2493
2494 if (peer_old_state == PEER_GLOBAL_INHERIT) {
2495
36235319
QY
2496 /*
2497 *Reset only these peers and send a
2498 *new open message with the change capabilities.
2499 *Considering the mode to be "global_new_state" and
2500 *do all operation accordingly
2501 */
794b37d5 2502
2503 switch (global_new_state) {
794b37d5 2504 case GLOBAL_HELPER:
794b37d5 2505 BGP_PEER_GR_HELPER_ENABLE(peer);
2506 break;
2507 case GLOBAL_GR:
794b37d5 2508 BGP_PEER_GR_ENABLE(peer);
2509 break;
2510 case GLOBAL_DISABLE:
794b37d5 2511 BGP_PEER_GR_DISABLE(peer);
2512 break;
2513 case GLOBAL_INVALID:
36235319
QY
2514 zlog_debug("%s [BGP_GR] GLOBAL_INVALID",
2515 __func__);
794b37d5 2516 return BGP_ERR_GR_OPERATION_FAILED;
794b37d5 2517 }
2518 }
2519 }
2520
2521 bgp->global_gr_present_state = global_new_state;
2522
794b37d5 2523 return BGP_GR_SUCCESS;
2524}
2525
2ba1fe69 2526int bgp_gr_update_all(struct bgp *bgp, int global_gr_cmd)
794b37d5 2527{
2528 enum global_mode global_new_state = GLOBAL_INVALID;
2529 enum global_mode global_old_state = GLOBAL_INVALID;
2530
2531 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319
QY
2532 zlog_debug("%s [BGP_GR]START: global_gr_cmd :%s:", __func__,
2533 print_global_gr_cmd(global_gr_cmd));
794b37d5 2534
2535 global_old_state = bgp_global_gr_mode_get(bgp);
2536
2ba1fe69 2537 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319
QY
2538 zlog_debug("[BGP_GR] global_old_gr_state :%s:",
2539 print_global_gr_mode(global_old_state));
794b37d5 2540
2ba1fe69 2541 if (global_old_state != GLOBAL_INVALID) {
794b37d5 2542 global_new_state =
2ba1fe69 2543 bgp->GLOBAL_GR_FSM[global_old_state][global_gr_cmd];
2544
2545 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319
QY
2546 zlog_debug("[BGP_GR] global_new_gr_state :%s:",
2547 print_global_gr_mode(global_new_state));
794b37d5 2548 } else {
36235319
QY
2549 zlog_err("%s [BGP_GR] global_old_state == GLOBAL_INVALID",
2550 __func__);
794b37d5 2551 return BGP_ERR_GR_OPERATION_FAILED;
2552 }
2553
2554 if (global_new_state == GLOBAL_INVALID) {
36235319
QY
2555 zlog_err("%s [BGP_GR] global_new_state == GLOBAL_INVALID",
2556 __func__);
794b37d5 2557 return BGP_ERR_GR_INVALID_CMD;
2558 }
2559 if (global_new_state == global_old_state) {
2560 /* Trace msg */
2ba1fe69 2561 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2562 zlog_debug(
36235319
QY
2563 "%s [BGP_GR] global_new_state == global_old_state :%s",
2564 __func__,
2565 print_global_gr_mode(global_new_state));
794b37d5 2566 return BGP_GR_NO_OPERATION;
2567 }
2568
36235319
QY
2569 return bgp_gr_lookup_n_update_all_peer(bgp, global_new_state,
2570 global_old_state);
794b37d5 2571}
2572
2ba1fe69 2573const char *print_peer_gr_mode(enum peer_mode pr_mode)
2574{
2575 const char *peer_gr_mode = NULL;
2576
2577 switch (pr_mode) {
2578 case PEER_HELPER:
2579 peer_gr_mode = "PEER_HELPER";
2580 break;
2581 case PEER_GR:
2582 peer_gr_mode = "PEER_GR";
2583 break;
2584 case PEER_DISABLE:
2585 peer_gr_mode = "PEER_DISABLE";
2586 break;
2587 case PEER_INVALID:
2588 peer_gr_mode = "PEER_INVALID";
2589 break;
2590 case PEER_GLOBAL_INHERIT:
2591 peer_gr_mode = "PEER_GLOBAL_INHERIT";
2592 break;
2593 }
2594
2595 return peer_gr_mode;
2596}
2597
2598const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd)
2599{
2600 const char *peer_gr_cmd = NULL;
2601
2602 switch (pr_gr_cmd) {
2603 case PEER_GR_CMD:
2604 peer_gr_cmd = "PEER_GR_CMD";
2605 break;
2606 case NO_PEER_GR_CMD:
2607 peer_gr_cmd = "NO_PEER_GR_CMD";
2608 break;
2609 case PEER_DISABLE_CMD:
2610 peer_gr_cmd = "PEER_GR_CMD";
2611 break;
2612 case NO_PEER_DISABLE_CMD:
2613 peer_gr_cmd = "NO_PEER_GR_CMD";
2614 break;
2615 case PEER_HELPER_CMD:
2616 peer_gr_cmd = "PEER_HELPER_CMD";
2617 break;
2618 case NO_PEER_HELPER_CMD:
2619 peer_gr_cmd = "NO_PEER_HELPER_CMD";
2620 break;
2621 }
2622
2623 return peer_gr_cmd;
2624}
2625
2626const char *print_global_gr_mode(enum global_mode gl_mode)
2627{
2628 const char *global_gr_mode = NULL;
2629
2630 switch (gl_mode) {
2631 case GLOBAL_HELPER:
2632 global_gr_mode = "GLOBAL_HELPER";
2633 break;
2634 case GLOBAL_GR:
2635 global_gr_mode = "GLOBAL_GR";
2636 break;
2637 case GLOBAL_DISABLE:
2638 global_gr_mode = "GLOBAL_DISABLE";
2639 break;
2640 case GLOBAL_INVALID:
2641 global_gr_mode = "GLOBAL_INVALID";
2642 break;
2643 }
2644
2645 return global_gr_mode;
2646}
2647
2648const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd)
2649{
2650 const char *global_gr_cmd = NULL;
2651
2652 switch (gl_gr_cmd) {
2653 case GLOBAL_GR_CMD:
2654 global_gr_cmd = "GLOBAL_GR_CMD";
2655 break;
2656 case NO_GLOBAL_GR_CMD:
2657 global_gr_cmd = "NO_GLOBAL_GR_CMD";
2658 break;
2659 case GLOBAL_DISABLE_CMD:
2660 global_gr_cmd = "GLOBAL_DISABLE_CMD";
2661 break;
2662 case NO_GLOBAL_DISABLE_CMD:
2663 global_gr_cmd = "NO_GLOBAL_DISABLE_CMD";
2664 break;
2665 }
2666
2667 return global_gr_cmd;
2668}
2669
794b37d5 2670enum global_mode bgp_global_gr_mode_get(struct bgp *bgp)
2671{
2672 return bgp->global_gr_present_state;
2673}
2674
2675enum peer_mode bgp_peer_gr_mode_get(struct peer *peer)
2676{
2677 return peer->peer_gr_present_state;
2678}
2679
36235319 2680int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd)
794b37d5 2681{
36235319
QY
2682 enum peer_mode peer_new_state = PEER_INVALID;
2683 enum peer_mode peer_old_state = PEER_INVALID;
794b37d5 2684 struct bgp_peer_gr peer_state;
2685 int result = BGP_GR_FAILURE;
2686
2687 /*
2688 * fetch peer_old_state from peer structure also
2689 * fetch global_old_state from bgp structure,
2690 * peer had a back pointer to bgpo struct ;
2691 */
2692
2693 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319
QY
2694 zlog_debug("%s [BGP_GR] START:Peer: (%s) : peer_gr_cmd :%s:",
2695 __func__, peer->host,
2696 print_peer_gr_cmd(peer_gr_cmd));
794b37d5 2697
2698 peer_old_state = bgp_peer_gr_mode_get(peer);
2699
2700 if (peer_old_state == PEER_INVALID) {
36235319 2701 zlog_debug("[BGP_GR] peer_old_state == Invalid state !");
794b37d5 2702 return BGP_ERR_GR_OPERATION_FAILED;
2703 }
2704
2ba1fe69 2705 peer_state = peer->PEER_GR_FSM[peer_old_state][peer_gr_cmd];
794b37d5 2706 peer_new_state = peer_state.next_state;
2707
2708 if (peer_new_state == PEER_INVALID) {
794b37d5 2709 zlog_debug(
2ba1fe69 2710 "[BGP_GR] Invalid bgp graceful restart command used !");
794b37d5 2711 return BGP_ERR_GR_INVALID_CMD;
2712 }
2713
2714 if (peer_new_state != peer_old_state) {
36235319
QY
2715 result = peer_state.action_fun(peer, peer_old_state,
2716 peer_new_state);
794b37d5 2717 } else {
2ba1fe69 2718 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2719 zlog_debug(
36235319 2720 "[BGP_GR] peer_old_state == peer_new_state !");
794b37d5 2721 return BGP_GR_NO_OPERATION;
2722 }
2723
2724 if (result == BGP_GR_SUCCESS) {
2725
2726 /* Update the mode i.e peer_new_state into the peer structure */
2727 peer->peer_gr_present_state = peer_new_state;
794b37d5 2728 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319 2729 zlog_debug(
2089dd80 2730 "[BGP_GR] Successfully change the state of the peer to : %s : !",
36235319 2731 print_peer_gr_mode(peer_new_state));
794b37d5 2732
2733 return BGP_GR_SUCCESS;
2734 }
2735
2736 return result;
2737}
2738
36235319
QY
2739unsigned int bgp_peer_gr_action(struct peer *peer, int old_peer_state,
2740 int new_peer_state)
794b37d5 2741{
2742 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2743 zlog_debug(
2ba1fe69 2744 "%s [BGP_GR] Move peer from old_peer_state :%s: to new_peer_state :%s: !!!!",
2745 __func__, print_peer_gr_mode(old_peer_state),
2746 print_peer_gr_mode(new_peer_state));
794b37d5 2747
2748 int bgp_gr_global_mode = GLOBAL_INVALID;
2749 unsigned int ret = BGP_GR_FAILURE;
2750
2751 if (old_peer_state == new_peer_state) {
36235319
QY
2752 /* Nothing to do over here as the present and old state is the
2753 * same */
794b37d5 2754 return BGP_GR_NO_OPERATION;
2755 }
36235319
QY
2756 if ((old_peer_state == PEER_INVALID)
2757 || (new_peer_state == PEER_INVALID)) {
2758 /* something bad happend , print error message */
794b37d5 2759 return BGP_ERR_GR_INVALID_CMD;
2760 }
2761
2762 bgp_gr_global_mode = bgp_global_gr_mode_get(peer->bgp);
2763
36235319
QY
2764 if ((old_peer_state == PEER_GLOBAL_INHERIT)
2765 && (new_peer_state != PEER_GLOBAL_INHERIT)) {
794b37d5 2766
2767 /* fetch the Mode running in the Global state machine
2768 *from the bgp structure into a variable called
2769 *bgp_gr_global_mode
2770 */
2771
2772 /* Here we are checking if the
2773 *1. peer_new_state == global_mode == helper_mode
2774 *2. peer_new_state == global_mode == GR_mode
2775 *3. peer_new_state == global_mode == disabled_mode
2776 */
2777
2778 BGP_PEER_GR_GLOBAL_INHERIT_UNSET(peer);
2779
2780 if (new_peer_state == bgp_gr_global_mode) {
36235319
QY
2781 /*This is incremental updates i.e no tear down
2782 *of the existing session
2783 *as the peer is already working in the same mode.
2784 */
794b37d5 2785 ret = BGP_GR_SUCCESS;
2786 } else {
2787 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2788 zlog_debug(
2ba1fe69 2789 "[BGP_GR] Peer state changed from :%s ",
2790 print_peer_gr_mode(old_peer_state));
794b37d5 2791
2792 bgp_peer_move_to_gr_mode(peer, new_peer_state);
2793
2794 ret = BGP_GR_SUCCESS;
2795 }
2796 }
2797 /* In the case below peer is going into Global inherit mode i.e.
2798 * the peer would work as the mode configured at the global level
2799 */
36235319
QY
2800 else if ((new_peer_state == PEER_GLOBAL_INHERIT)
2801 && (old_peer_state != PEER_GLOBAL_INHERIT)) {
794b37d5 2802 /* Here in this case it would be destructive
2803 * in all the cases except one case when,
2804 * Global GR is configured Disabled
2805 * and present_peer_state is not disable
2806 */
2807
2808 BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
2809
2810 if (old_peer_state == bgp_gr_global_mode) {
2811
2812 /* This is incremental updates
2813 *i.e no tear down of the existing session
2814 *as the peer is already working in the same mode.
2815 */
2816 ret = BGP_GR_SUCCESS;
2817 } else {
2818 /* Destructive always */
2819 /* Tear down the old session
2820 * and send the new capability
2821 * as per the bgp_gr_global_mode
2822 */
2823
2824 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319
QY
2825 zlog_debug(
2826 "[BGP_GR] Peer state changed from :%s",
2ba1fe69 2827 print_peer_gr_mode(old_peer_state));
794b37d5 2828
2829 bgp_peer_move_to_gr_mode(peer, bgp_gr_global_mode);
2830
2831 ret = BGP_GR_SUCCESS;
2832 }
2833 } else {
2834 /*
2835 *This else case, it include all the cases except -->
2836 *(new_peer_state != Peer_Global) &&
2837 *( old_peer_state != Peer_Global )
2838 */
2839 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2ba1fe69 2840 zlog_debug("[BGP_GR] Peer state changed from :%s",
36235319 2841 print_peer_gr_mode(old_peer_state));
794b37d5 2842
2843 bgp_peer_move_to_gr_mode(peer, new_peer_state);
2844
2845 ret = BGP_GR_SUCCESS;
2846 }
2847
2848 return ret;
2849}
2850
2851inline void bgp_peer_move_to_gr_mode(struct peer *peer, int new_state)
2852
2853{
2854 int bgp_global_gr_mode = bgp_global_gr_mode_get(peer->bgp);
2855
2856 switch (new_state) {
794b37d5 2857 case PEER_HELPER:
2858 BGP_PEER_GR_HELPER_ENABLE(peer);
2859 break;
794b37d5 2860 case PEER_GR:
2861 BGP_PEER_GR_ENABLE(peer);
2862 break;
794b37d5 2863 case PEER_DISABLE:
2864 BGP_PEER_GR_DISABLE(peer);
2865 break;
794b37d5 2866 case PEER_GLOBAL_INHERIT:
2867 BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
2868
2869 if (bgp_global_gr_mode == GLOBAL_HELPER) {
2870 BGP_PEER_GR_HELPER_ENABLE(peer);
36235319 2871 } else if (bgp_global_gr_mode == GLOBAL_GR) {
794b37d5 2872 BGP_PEER_GR_ENABLE(peer);
2873 } else if (bgp_global_gr_mode == GLOBAL_DISABLE) {
2874 BGP_PEER_GR_DISABLE(peer);
2875 } else {
2ba1fe69 2876 zlog_err(
36235319 2877 "[BGP_GR] Default switch inherit mode ::: SOMETHING IS WRONG !!!");
794b37d5 2878 }
2879 break;
2880 default:
36235319
QY
2881 zlog_err(
2882 "[BGP_GR] Default switch mode ::: SOMETHING IS WRONG !!!");
794b37d5 2883 break;
2884 }
2885 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2ba1fe69 2886 zlog_debug("[BGP_GR] Peer state changed --to--> : %d : !",
36235319 2887 new_state);
794b37d5 2888}
2889
2890void bgp_peer_gr_flags_update(struct peer *peer)
2891{
2892 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319 2893 zlog_debug("%s [BGP_GR] called !", __func__);
794b37d5 2894 if (CHECK_FLAG(peer->peer_gr_new_status_flag,
36235319
QY
2895 PEER_GRACEFUL_RESTART_NEW_STATE_HELPER))
2896 SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
794b37d5 2897 else
36235319 2898 UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
794b37d5 2899 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2900 zlog_debug(
2ba1fe69 2901 "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_HELPER : %s : !",
794b37d5 2902 peer->host,
2986cac2 2903 (CHECK_FLAG(peer->flags,
36235319
QY
2904 PEER_FLAG_GRACEFUL_RESTART_HELPER)
2905 ? "Set"
2906 : "UnSet"));
794b37d5 2907 if (CHECK_FLAG(peer->peer_gr_new_status_flag,
36235319
QY
2908 PEER_GRACEFUL_RESTART_NEW_STATE_RESTART))
2909 SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
794b37d5 2910 else
36235319 2911 UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
794b37d5 2912 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2913 zlog_debug(
2ba1fe69 2914 "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART : %s : !",
794b37d5 2915 peer->host,
36235319
QY
2916 (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
2917 ? "Set"
2918 : "UnSet"));
794b37d5 2919 if (CHECK_FLAG(peer->peer_gr_new_status_flag,
36235319 2920 PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT))
2986cac2 2921 SET_FLAG(peer->flags,
36235319 2922 PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT);
794b37d5 2923 else
2986cac2 2924 UNSET_FLAG(peer->flags,
36235319 2925 PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT);
794b37d5 2926 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
2927 zlog_debug(
36235319 2928 "[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT : %s : !",
794b37d5 2929 peer->host,
2986cac2 2930 (CHECK_FLAG(peer->flags,
36235319
QY
2931 PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT)
2932 ? "Set"
2933 : "UnSet"));
d7b3cda6 2934
36235319
QY
2935 if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
2936 && !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER)) {
2937 zlog_debug("[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_MODE!",
2938 peer->host);
d7b3cda6 2939
2940 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
2941
36235319 2942 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
d7b3cda6 2943
2944 peer_nsf_stop(peer);
2945 zlog_debug(
2ba1fe69 2946 "[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_WAIT!",
d7b3cda6 2947 peer->host);
2948 }
2949 }
794b37d5 2950}