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