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