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