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