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