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