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