2002-12-13 21:15:29 +01:00
|
|
|
/* BGP-4 Finite State Machine
|
2017-05-13 10:25:29 +02:00
|
|
|
* From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
|
|
|
|
* Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
|
|
|
|
*
|
|
|
|
* This file is part of GNU Zebra.
|
|
|
|
*
|
|
|
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
* later version.
|
|
|
|
*
|
|
|
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "linklist.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "sockunion.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "stream.h"
|
2018-01-02 19:20:00 +01:00
|
|
|
#include "ringbuf.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "memory.h"
|
|
|
|
#include "plist.h"
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
#include "workqueue.h"
|
2015-05-20 03:03:47 +02:00
|
|
|
#include "queue.h"
|
2016-01-07 16:03:01 +01:00
|
|
|
#include "filter.h"
|
2016-09-22 17:15:50 +02:00
|
|
|
#include "command.h"
|
2018-06-19 20:42:55 +02:00
|
|
|
#include "lib_errors.h"
|
2019-10-26 18:40:33 +02:00
|
|
|
#include "zclient.h"
|
2015-08-12 15:59:18 +02:00
|
|
|
#include "lib/json.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "bgpd/bgpd.h"
|
|
|
|
#include "bgpd/bgp_attr.h"
|
|
|
|
#include "bgpd/bgp_debug.h"
|
2018-06-15 23:08:53 +02:00
|
|
|
#include "bgpd/bgp_errors.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "bgpd/bgp_fsm.h"
|
|
|
|
#include "bgpd/bgp_packet.h"
|
|
|
|
#include "bgpd/bgp_network.h"
|
|
|
|
#include "bgpd/bgp_route.h"
|
|
|
|
#include "bgpd/bgp_dump.h"
|
|
|
|
#include "bgpd/bgp_open.h"
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
#include "bgpd/bgp_advertise.h"
|
2021-12-20 22:03:09 +01:00
|
|
|
#include "bgpd/bgp_community.h"
|
2015-05-20 03:03:47 +02:00
|
|
|
#include "bgpd/bgp_updgrp.h"
|
2015-05-20 03:12:17 +02:00
|
|
|
#include "bgpd/bgp_nht.h"
|
2015-06-12 16:59:11 +02:00
|
|
|
#include "bgpd/bgp_bfd.h"
|
2015-05-29 05:48:31 +02:00
|
|
|
#include "bgpd/bgp_memory.h"
|
2017-01-06 00:13:16 +01:00
|
|
|
#include "bgpd/bgp_keepalives.h"
|
2017-04-18 20:11:43 +02:00
|
|
|
#include "bgpd/bgp_io.h"
|
2018-05-11 13:40:55 +02:00
|
|
|
#include "bgpd/bgp_zebra.h"
|
2020-12-17 22:36:22 +01:00
|
|
|
#include "bgpd/bgp_vty.h"
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2016-06-12 17:32:23 +02:00
|
|
|
DEFINE_HOOK(peer_backward_transition, (struct peer * peer), (peer));
|
2019-08-09 19:53:01 +02:00
|
|
|
DEFINE_HOOK(peer_status_changed, (struct peer * peer), (peer));
|
2020-12-17 22:36:22 +01:00
|
|
|
|
2015-05-20 03:04:12 +02:00
|
|
|
/* Definition of display strings corresponding to FSM events. This should be
|
|
|
|
* kept consistent with the events defined in bgpd.h
|
|
|
|
*/
|
2019-11-20 17:26:59 +01:00
|
|
|
static const char *const bgp_event_str[] = {
|
2015-05-20 03:04:12 +02:00
|
|
|
NULL,
|
|
|
|
"BGP_Start",
|
|
|
|
"BGP_Stop",
|
|
|
|
"TCP_connection_open",
|
2020-10-20 16:49:58 +02:00
|
|
|
"TCP_connection_open_w_delay",
|
2015-05-20 03:04:12 +02:00
|
|
|
"TCP_connection_closed",
|
|
|
|
"TCP_connection_open_failed",
|
|
|
|
"TCP_fatal_error",
|
|
|
|
"ConnectRetry_timer_expired",
|
|
|
|
"Hold_Timer_expired",
|
|
|
|
"KeepAlive_timer_expired",
|
2020-10-20 16:49:58 +02:00
|
|
|
"DelayOpen_timer_expired",
|
2015-05-20 03:04:12 +02:00
|
|
|
"Receive_OPEN_message",
|
|
|
|
"Receive_KEEPALIVE_message",
|
|
|
|
"Receive_UPDATE_message",
|
|
|
|
"Receive_NOTIFICATION_message",
|
|
|
|
"Clearing_Completed",
|
|
|
|
};
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* BGP FSM (finite state machine) has three types of functions. Type
|
|
|
|
one is thread functions. Type two is event functions. Type three
|
|
|
|
is FSM functions. Timer functions are set by bgp_timer_set
|
|
|
|
function. */
|
|
|
|
|
|
|
|
/* BGP event function. */
|
|
|
|
int bgp_event(struct thread *);
|
|
|
|
|
|
|
|
/* BGP thread functions. */
|
|
|
|
static int bgp_start_timer(struct thread *);
|
|
|
|
static int bgp_connect_timer(struct thread *);
|
|
|
|
static int bgp_holdtime_timer(struct thread *);
|
2020-10-20 16:49:58 +02:00
|
|
|
static int bgp_delayopen_timer(struct thread *);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* BGP FSM functions. */
|
|
|
|
static int bgp_start(struct peer *);
|
|
|
|
|
2019-08-19 07:12:06 +02:00
|
|
|
/* Register peer with NHT */
|
2021-04-12 20:16:30 +02:00
|
|
|
int bgp_peer_reg_with_nht(struct peer *peer)
|
2019-08-19 07:12:06 +02:00
|
|
|
{
|
|
|
|
int connected = 0;
|
|
|
|
|
2019-11-27 09:48:17 +01:00
|
|
|
if (peer->sort == BGP_PEER_EBGP && peer->ttl == BGP_DEFAULT_TTL
|
2019-08-19 07:12:06 +02:00
|
|
|
&& !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
|
2020-02-06 15:37:20 +01:00
|
|
|
&& !CHECK_FLAG(peer->bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
|
2019-08-19 07:12:06 +02:00
|
|
|
connected = 1;
|
|
|
|
|
2021-06-30 10:52:29 +02:00
|
|
|
return bgp_find_or_add_nexthop(
|
|
|
|
peer->bgp, peer->bgp, family2afi(peer->su.sa.sa_family),
|
|
|
|
SAFI_UNICAST, NULL, peer, connected, NULL);
|
2019-08-19 07:12:06 +02:00
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
|
|
|
|
{
|
|
|
|
/* Copy stats over. These are only the pre-established state stats */
|
|
|
|
peer_dst->open_in += peer_src->open_in;
|
|
|
|
peer_dst->open_out += peer_src->open_out;
|
|
|
|
peer_dst->keepalive_in += peer_src->keepalive_in;
|
|
|
|
peer_dst->keepalive_out += peer_src->keepalive_out;
|
|
|
|
peer_dst->notify_in += peer_src->notify_in;
|
|
|
|
peer_dst->notify_out += peer_src->notify_out;
|
|
|
|
peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in;
|
|
|
|
peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct peer *peer_xfer_conn(struct peer *from_peer)
|
|
|
|
{
|
|
|
|
struct peer *peer;
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
int fd;
|
2020-03-20 14:03:08 +01:00
|
|
|
enum bgp_fsm_status status, pstatus;
|
2020-03-20 01:19:50 +01:00
|
|
|
enum bgp_fsm_events last_evt, last_maj_evt;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
assert(from_peer != NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
peer = from_peer->doppelganger;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
|
|
|
return from_peer;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-09-11 14:13:42 +02:00
|
|
|
/*
|
|
|
|
* Let's check that we are not going to loose known configuration
|
|
|
|
* state based upon doppelganger rules.
|
|
|
|
*/
|
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
if (from_peer->afc[afi][safi] != peer->afc[afi][safi]) {
|
|
|
|
flog_err(
|
|
|
|
EC_BGP_DOPPELGANGER_CONFIG,
|
|
|
|
"from_peer->afc[%d][%d] is not the same as what we are overwriting",
|
|
|
|
afi, safi);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 03:03:47 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2015-05-20 03:04:19 +02:00
|
|
|
zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
|
|
|
|
from_peer->host, from_peer, from_peer->fd, peer,
|
|
|
|
peer->fd);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-05-02 02:37:45 +02:00
|
|
|
bgp_writes_off(peer);
|
|
|
|
bgp_reads_off(peer);
|
|
|
|
bgp_writes_off(from_peer);
|
|
|
|
bgp_reads_off(from_peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-11-25 17:49:38 +01:00
|
|
|
/*
|
|
|
|
* Before exchanging FD remove doppelganger from
|
|
|
|
* keepalive peer hash. It could be possible conf peer
|
|
|
|
* fd is set to -1. If blocked on lock then keepalive
|
|
|
|
* thread can access peer pointer with fd -1.
|
|
|
|
*/
|
|
|
|
bgp_keepalives_off(from_peer);
|
|
|
|
|
2015-05-20 03:03:47 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2017-05-02 02:37:45 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2017-09-25 04:18:15 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect_check_r);
|
|
|
|
BGP_TIMER_OFF(peer->t_connect_check_w);
|
2015-05-20 03:03:47 +02:00
|
|
|
BGP_TIMER_OFF(from_peer->t_routeadv);
|
2017-05-02 02:37:45 +02:00
|
|
|
BGP_TIMER_OFF(from_peer->t_connect);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(from_peer->t_delayopen);
|
2017-09-25 04:18:15 +02:00
|
|
|
BGP_TIMER_OFF(from_peer->t_connect_check_r);
|
|
|
|
BGP_TIMER_OFF(from_peer->t_connect_check_w);
|
bgpd: schedule packet job after connection xfer
During initial session establishment, bgpd performs a "connection
transfer" to a new peer struct if the connection was initiated passively
(i.e. by the remote peer). With the addition of buffered input and a
reorganized packet processor, the following race condition manifests:
1. Remote peer initiates a connection. After exchanging OPEN messages,
we send them a KEEPALIVE. They send us a KEEPALIVE followed by
10,000 UPDATE messages. The I/O thread pushes these onto our local
peer's input buffer and schedules a packet processing job on the
main thread.
2. The packet job runs and processes the KEEPALIVE, which completes the
handshake on our end. As part of transferring to ESTABLISHED we
transfer all peer state to a new struct, as mentioned. Upon returning
from the KEEPALIVE processing routing, the peer context we had has
now been destroyed. We notice this and stop processing. Meanwhile
10k UPDATE messages are sitting on the input buffer.
3. N seconds later, the remote peer sends us a KEEPALIVE. The I/O thread
schedules another process job, which finds 10k UPDATEs waiting for
it. Convergence is achieved, but has been delayed by the value of the
KEEPALIVE timer.
The racey part is that if the remote peer takes a little bit of time to
send UPDATEs after KEEPALIVEs -- somewhere on the order of a few hundred
milliseconds -- we complete the transfer successfully and the packet
processing job is scheduled on the new peer upon arrival of the UPDATE
messages. Yuck.
The solution is to schedule a packet processing job on the new peer
struct after transferring state.
Lengthy commit message in case someone has to debug similar problems in
the future...
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
2017-11-06 06:33:46 +01:00
|
|
|
BGP_TIMER_OFF(from_peer->t_process_packet);
|
2017-02-07 00:39:06 +01:00
|
|
|
|
2017-09-08 17:51:12 +02:00
|
|
|
/*
|
|
|
|
* At this point in time, it is possible that there are packets pending
|
|
|
|
* on various buffers. Those need to be transferred or dropped,
|
|
|
|
* otherwise we'll get spurious failures during session establishment.
|
|
|
|
*/
|
2019-06-21 10:58:02 +02:00
|
|
|
frr_with_mutex(&peer->io_mtx, &from_peer->io_mtx) {
|
2017-05-02 02:37:45 +02:00
|
|
|
fd = peer->fd;
|
|
|
|
peer->fd = from_peer->fd;
|
|
|
|
from_peer->fd = fd;
|
|
|
|
|
|
|
|
stream_fifo_clean(peer->ibuf);
|
2017-02-07 00:39:06 +01:00
|
|
|
stream_fifo_clean(peer->obuf);
|
|
|
|
|
2017-09-08 17:51:12 +02:00
|
|
|
/*
|
|
|
|
* this should never happen, since bgp_process_packet() is the
|
|
|
|
* only task that sets and unsets the current packet and it
|
|
|
|
* runs in our pthread.
|
|
|
|
*/
|
2017-05-02 02:37:45 +02:00
|
|
|
if (peer->curr) {
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 20:23:42 +02:00
|
|
|
EC_BGP_PKT_PROCESS,
|
2017-05-02 02:37:45 +02:00
|
|
|
"[%s] Dropping pending packet on connection transfer:",
|
|
|
|
peer->host);
|
2019-04-24 17:19:09 +02:00
|
|
|
/* there used to be a bgp_packet_dump call here, but
|
|
|
|
* that's extremely confusing since there's no way to
|
|
|
|
* identify the packet in MRT dumps or BMP as dropped
|
|
|
|
* due to connection transfer.
|
|
|
|
*/
|
2017-05-02 02:37:45 +02:00
|
|
|
stream_free(peer->curr);
|
|
|
|
peer->curr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy each packet from old peer's output queue to new peer
|
2017-04-06 03:09:33 +02:00
|
|
|
while (from_peer->obuf->head)
|
|
|
|
stream_fifo_push(peer->obuf,
|
|
|
|
stream_fifo_pop(from_peer->obuf));
|
2017-05-02 02:37:45 +02:00
|
|
|
|
|
|
|
// copy each packet from old peer's input queue to new peer
|
|
|
|
while (from_peer->ibuf->head)
|
|
|
|
stream_fifo_push(peer->ibuf,
|
|
|
|
stream_fifo_pop(from_peer->ibuf));
|
2017-11-03 19:47:56 +01:00
|
|
|
|
2018-01-02 19:20:00 +01:00
|
|
|
ringbuf_wipe(peer->ibuf_work);
|
|
|
|
ringbuf_copy(peer->ibuf_work, from_peer->ibuf_work,
|
|
|
|
ringbuf_remain(from_peer->ibuf_work));
|
2017-02-07 00:39:06 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:04:25 +02:00
|
|
|
peer->as = from_peer->as;
|
2015-05-20 02:40:37 +02:00
|
|
|
peer->v_holdtime = from_peer->v_holdtime;
|
|
|
|
peer->v_keepalive = from_peer->v_keepalive;
|
|
|
|
peer->v_routeadv = from_peer->v_routeadv;
|
2020-10-20 16:49:58 +02:00
|
|
|
peer->v_delayopen = from_peer->v_delayopen;
|
2015-05-20 02:40:37 +02:00
|
|
|
peer->v_gr_restart = from_peer->v_gr_restart;
|
|
|
|
peer->cap = from_peer->cap;
|
|
|
|
status = peer->status;
|
|
|
|
pstatus = peer->ostatus;
|
2015-05-20 03:04:12 +02:00
|
|
|
last_evt = peer->last_event;
|
|
|
|
last_maj_evt = peer->last_major_event;
|
2015-05-20 02:40:37 +02:00
|
|
|
peer->status = from_peer->status;
|
|
|
|
peer->ostatus = from_peer->ostatus;
|
2015-05-20 03:04:12 +02:00
|
|
|
peer->last_event = from_peer->last_event;
|
|
|
|
peer->last_major_event = from_peer->last_major_event;
|
2015-05-20 02:40:37 +02:00
|
|
|
from_peer->status = status;
|
|
|
|
from_peer->ostatus = pstatus;
|
2015-05-20 03:04:12 +02:00
|
|
|
from_peer->last_event = last_evt;
|
|
|
|
from_peer->last_major_event = last_maj_evt;
|
2015-05-20 02:40:37 +02:00
|
|
|
peer->remote_id = from_peer->remote_id;
|
bgpd: Add a new command to only show failed peerings
In a data center, having 32-128 peers is not uncommon. In such a situation, to find a
peer that has failed and why is several commands. This hinders both the automatability of
failure detection and the ease/speed with which the reason can be found. To simplify this
process of catching a failure and its cause quicker, this patch does the following:
1. Created a new function, bgp_show_failed_summary to display the
failed summary output for JSON and vty
2. Created a new function to display the reset code/subcode. This is now used in the
failed summary code and in the show neighbors code
3. Added a new variable failedPeers in all the JSON outputs, including the vanilla
"show bgp summary" family. This lists the failed session count.
4. Display peer, dropped count, estd count, uptime and the reason for failure as the
output of "show bgp summary failed" family of commands
5. Added three resset codes for the case where we're waiting for NHT, waiting for peer
IPv6 addr, waiting for VRF to init.
This also counts the case where only one peer has advertised an AFI/SAFI.
The new command has the optional keyword "failed" added to the classical summary command.
The changes affect only one existing output, that of "show [ip] bgp neighbors <nbr>". As
we track the lack of NHT resolution for a peer or the lack of knowing a peer IPv6 addr,
the output of that command will show a "waiting for NHT" etc. as the last reset reason.
This patch includes update to the documentation too.
Signed-off-by: Dinesh G Dutt <5016467+ddutt@users.noreply.github.com>
2019-08-31 18:24:49 +02:00
|
|
|
peer->last_reset = from_peer->last_reset;
|
2021-07-02 15:50:39 +02:00
|
|
|
peer->max_packet_size = from_peer->max_packet_size;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
|
|
|
|
peer->bgp->peer);
|
2019-10-26 18:40:33 +02:00
|
|
|
|
2019-10-24 06:40:53 +02:00
|
|
|
if (bgp_peer_gr_mode_get(peer) == PEER_DISABLE) {
|
|
|
|
|
|
|
|
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
|
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
|
2019-10-24 06:40:53 +02:00
|
|
|
peer_nsf_stop(peer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-11 05:10:16 +02:00
|
|
|
if (from_peer->hostname != NULL) {
|
2016-03-10 04:58:48 +01:00
|
|
|
if (peer->hostname) {
|
2015-05-29 05:48:31 +02:00
|
|
|
XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
|
2016-03-10 04:58:48 +01:00
|
|
|
peer->hostname = NULL;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-11-01 10:37:50 +01:00
|
|
|
peer->hostname = from_peer->hostname;
|
2016-03-10 04:58:48 +01:00
|
|
|
from_peer->hostname = NULL;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-09-11 05:10:16 +02:00
|
|
|
if (from_peer->domainname != NULL) {
|
2016-03-10 04:58:48 +01:00
|
|
|
if (peer->domainname) {
|
2015-05-29 05:48:31 +02:00
|
|
|
XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
|
2016-03-10 04:58:48 +01:00
|
|
|
peer->domainname = NULL;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-11-01 10:37:50 +01:00
|
|
|
peer->domainname = from_peer->domainname;
|
2016-03-10 04:58:48 +01:00
|
|
|
from_peer->domainname = NULL;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-11-21 19:02:06 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi];
|
|
|
|
peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
|
|
|
|
peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi];
|
|
|
|
peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi];
|
|
|
|
peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
|
|
|
|
peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
|
2021-12-20 22:03:09 +01:00
|
|
|
peer->llgr[afi][safi] = from_peer->llgr[afi][safi];
|
2017-11-21 19:02:06 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
if (bgp_getsockname(peer) < 0) {
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 21:34:28 +02:00
|
|
|
EC_LIB_SOCKET,
|
2015-05-20 02:40:37 +02:00
|
|
|
"%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
|
|
|
|
(CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
|
|
|
|
? "accept"
|
|
|
|
: ""),
|
|
|
|
peer->host, peer->fd, from_peer->fd);
|
2020-08-21 08:33:09 +02:00
|
|
|
BGP_EVENT_ADD(peer, BGP_Stop);
|
|
|
|
BGP_EVENT_ADD(from_peer, BGP_Stop);
|
2015-05-20 02:40:37 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (from_peer->status > Active) {
|
|
|
|
if (bgp_getsockname(from_peer) < 0) {
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 21:34:28 +02:00
|
|
|
EC_LIB_SOCKET,
|
2015-05-20 02:40:37 +02:00
|
|
|
"%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
|
2018-06-15 23:08:53 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
(CHECK_FLAG(from_peer->sflags,
|
|
|
|
PEER_STATUS_ACCEPT_PEER)
|
|
|
|
? "accept"
|
|
|
|
: ""),
|
|
|
|
from_peer->host, from_peer->fd, peer->fd);
|
|
|
|
bgp_stop(from_peer);
|
|
|
|
from_peer = NULL;
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-01-09 21:38:17 +01:00
|
|
|
|
|
|
|
// Note: peer_xfer_stats() must be called with I/O turned OFF
|
|
|
|
if (from_peer)
|
|
|
|
peer_xfer_stats(peer, from_peer);
|
|
|
|
|
2019-08-19 07:12:06 +02:00
|
|
|
/* Register peer for NHT. This is to allow RAs to be enabled when
|
|
|
|
* needed, even on a passive connection.
|
|
|
|
*/
|
|
|
|
bgp_peer_reg_with_nht(peer);
|
2021-04-12 20:16:30 +02:00
|
|
|
if (from_peer)
|
|
|
|
bgp_replace_nexthop_by_peer(from_peer, peer);
|
2019-08-19 07:12:06 +02:00
|
|
|
|
2017-05-02 02:37:45 +02:00
|
|
|
bgp_reads_on(peer);
|
|
|
|
bgp_writes_on(peer);
|
2021-03-17 21:10:13 +01:00
|
|
|
thread_add_event(bm->master, bgp_process_packet, peer, 0,
|
|
|
|
&peer->t_process_packet);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
return (peer);
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Hook function called after bgp event is occered. And vty's
|
|
|
|
neighbor command invoke this function after making neighbor
|
|
|
|
structure. */
|
|
|
|
void bgp_timer_set(struct peer *peer)
|
|
|
|
{
|
2021-12-20 22:03:09 +01:00
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
switch (peer->status) {
|
|
|
|
case Idle:
|
|
|
|
/* First entry point of peer's finite state machine. In Idle
|
|
|
|
status start timer is on unless peer is shutdown or peer is
|
|
|
|
inactive. All other timer must be turned off */
|
2018-01-30 15:30:10 +01:00
|
|
|
if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)
|
2021-09-03 16:36:40 +02:00
|
|
|
|| peer->bgp->vrf_id == VRF_UNKNOWN) {
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
|
|
|
} else {
|
|
|
|
BGP_TIMER_ON(peer->t_start, bgp_start_timer,
|
2015-05-20 02:40:42 +02:00
|
|
|
peer->v_start);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_off(peer);
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
|
2015-05-20 02:47:21 +02:00
|
|
|
case Connect:
|
2002-12-13 21:15:29 +01:00
|
|
|
/* After start timer is expired, the peer moves to Connect
|
|
|
|
status. Make sure start timer is off and connect timer is
|
2017-07-17 14:03:14 +02:00
|
|
|
on. */
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
2020-10-20 16:49:58 +02:00
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
|
|
|
|
BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
|
|
|
|
(peer->v_delayopen + peer->v_connect));
|
|
|
|
else
|
|
|
|
BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
|
|
|
|
peer->v_connect);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_off(peer);
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
case Active:
|
|
|
|
/* Active is waiting connection from remote peer. And if
|
|
|
|
connect timer is expired, change status to Connect. */
|
2015-05-20 02:40:42 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
|
|
|
/* If peer is passive mode, do not set connect timer. */
|
2005-02-02 15:40:33 +01:00
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)
|
|
|
|
|| CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2020-10-20 16:49:58 +02:00
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
|
|
|
|
BGP_TIMER_ON(
|
|
|
|
peer->t_connect, bgp_connect_timer,
|
|
|
|
(peer->v_delayopen + peer->v_connect));
|
|
|
|
else
|
|
|
|
BGP_TIMER_ON(peer->t_connect, bgp_connect_timer,
|
|
|
|
peer->v_connect);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_off(peer);
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
case OpenSent:
|
|
|
|
/* OpenSent status. */
|
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (peer->v_holdtime != 0) {
|
|
|
|
BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
|
|
|
|
peer->v_holdtime);
|
2015-05-20 02:40:42 +02:00
|
|
|
} else {
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_off(peer);
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2015-05-20 02:40:42 +02:00
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:42 +02:00
|
|
|
case OpenConfirm:
|
2002-12-13 21:15:29 +01:00
|
|
|
/* OpenConfirm status. */
|
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:42 +02:00
|
|
|
/* If the negotiated Hold Time value is zero, then the Hold Time
|
2002-12-13 21:15:29 +01:00
|
|
|
timer and KeepAlive timers are not started. */
|
|
|
|
if (peer->v_holdtime == 0) {
|
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_off(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
|
|
|
|
peer->v_holdtime);
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_on(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
case Established:
|
|
|
|
/* In Established status start and connect timer is turned
|
|
|
|
off. */
|
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Same as OpenConfirm, if holdtime is zero then both holdtime
|
|
|
|
and keepalive must be turned off. */
|
|
|
|
if (peer->v_holdtime == 0) {
|
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2017-06-12 04:53:42 +02:00
|
|
|
bgp_keepalives_off(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
|
|
|
|
peer->v_holdtime);
|
2017-06-12 04:53:42 +02:00
|
|
|
bgp_keepalives_on(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
|
|
|
case Deleted:
|
|
|
|
BGP_TIMER_OFF(peer->t_gr_restart);
|
|
|
|
BGP_TIMER_OFF(peer->t_gr_stale);
|
2021-12-20 22:03:09 +01:00
|
|
|
|
|
|
|
FOREACH_AFI_SAFI (afi, safi)
|
|
|
|
BGP_TIMER_OFF(peer->t_llgr_stale[afi][safi]);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_pmax_restart);
|
2020-10-01 22:08:06 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_refresh_stalepath);
|
2002-12-13 21:15:29 +01:00
|
|
|
/* fallthru */
|
|
|
|
case Clearing:
|
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_off(peer);
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
2020-03-20 14:03:08 +01:00
|
|
|
case BGP_STATUS_MAX:
|
|
|
|
flog_err(EC_LIB_DEVELOPMENT,
|
|
|
|
"BGP_STATUS_MAX while a legal state is not valid state for the FSM");
|
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* BGP start timer. This function set BGP_Start event to thread value
|
|
|
|
and process event. */
|
|
|
|
static int bgp_start_timer(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Timer (start timer expire).", peer->host);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
THREAD_VAL(thread) = BGP_Start;
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
bgp_event(thread); /* bgp_event unlocks peer */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* BGP connect retry timer. */
|
|
|
|
static int bgp_connect_timer(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct peer *peer;
|
2015-05-20 02:40:37 +02:00
|
|
|
int ret;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
peer = THREAD_ARG(thread);
|
2017-05-02 02:37:45 +02:00
|
|
|
|
2020-10-20 16:49:58 +02:00
|
|
|
/* stop the DelayOpenTimer if it is running */
|
2021-12-21 09:57:07 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2020-10-20 16:49:58 +02:00
|
|
|
|
2017-05-02 02:37:45 +02:00
|
|
|
assert(!peer->t_write);
|
|
|
|
assert(!peer->t_read);
|
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) {
|
|
|
|
bgp_stop(peer);
|
|
|
|
ret = -1;
|
|
|
|
} else {
|
|
|
|
THREAD_VAL(thread) = ConnectRetry_timer_expired;
|
|
|
|
bgp_event(thread); /* bgp_event unlocks peer */
|
|
|
|
ret = 0;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* BGP holdtime timer. */
|
|
|
|
static int bgp_holdtime_timer(struct thread *thread)
|
|
|
|
{
|
2020-06-15 16:35:50 +02:00
|
|
|
atomic_size_t inq_count;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Timer (holdtime timer expire)",
|
|
|
|
peer->host);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-06-15 16:35:50 +02:00
|
|
|
/*
|
|
|
|
* Given that we do not have any expectation of ordering
|
|
|
|
* for handling packets from a peer -vs- handling
|
|
|
|
* the hold timer for a peer as that they are both
|
|
|
|
* events on the peer. If we have incoming
|
|
|
|
* data on the peers inq, let's give the system a chance
|
|
|
|
* to handle that data. This can be especially true
|
|
|
|
* for systems where we are heavily loaded for one
|
|
|
|
* reason or another.
|
|
|
|
*/
|
|
|
|
inq_count = atomic_load_explicit(&peer->ibuf->count,
|
|
|
|
memory_order_relaxed);
|
|
|
|
if (inq_count) {
|
|
|
|
BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
|
|
|
|
peer->v_holdtime);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
THREAD_VAL(thread) = Hold_Timer_expired;
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
bgp_event(thread); /* bgp_event unlocks peer */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bgp_routeadv_timer(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Timer (routeadv timer expire)",
|
|
|
|
peer->host);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2010-01-15 14:22:10 +01:00
|
|
|
peer->synctime = bgp_clock();
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-06-08 22:41:21 +02:00
|
|
|
thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets, peer, 0,
|
2017-05-02 02:37:45 +02:00
|
|
|
&peer->t_generate_updgrp_packets);
|
|
|
|
|
2015-05-20 03:03:47 +02:00
|
|
|
/* MRAI timer will be started again when FIFO is built, no need to
|
|
|
|
* do it here.
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-20 16:49:58 +02:00
|
|
|
/* RFC 4271 DelayOpenTimer */
|
|
|
|
int bgp_delayopen_timer(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
|
|
|
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Timer (DelayOpentimer expire)",
|
|
|
|
peer->host);
|
|
|
|
|
|
|
|
THREAD_VAL(thread) = DelayOpen_timer_expired;
|
|
|
|
bgp_event(thread); /* bgp_event unlocks peer */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-05-20 11:19:34 +02:00
|
|
|
/* BGP Peer Down Cause */
|
2019-11-20 17:26:59 +01:00
|
|
|
const char *const peer_down_str[] = {"",
|
2004-05-20 11:19:34 +02:00
|
|
|
"Router ID changed",
|
|
|
|
"Remote AS changed",
|
|
|
|
"Local AS change",
|
|
|
|
"Cluster ID changed",
|
|
|
|
"Confederation identifier changed",
|
|
|
|
"Confederation peer changed",
|
|
|
|
"RR client config change",
|
|
|
|
"RS client config change",
|
|
|
|
"Update source change",
|
|
|
|
"Address family activated",
|
|
|
|
"Admin. shutdown",
|
|
|
|
"User reset",
|
|
|
|
"BGP Notification received",
|
|
|
|
"BGP Notification send",
|
|
|
|
"Peer closed the session",
|
|
|
|
"Neighbor deleted",
|
|
|
|
"Peer-group add member",
|
|
|
|
"Peer-group delete member",
|
|
|
|
"Capability changed",
|
|
|
|
"Passive config change",
|
2005-02-02 15:40:33 +01:00
|
|
|
"Multihop config change",
|
2015-07-22 21:35:37 +02:00
|
|
|
"NSF peer closed the session",
|
2015-07-22 21:35:37 +02:00
|
|
|
"Intf peering v6only config change",
|
2016-04-23 00:15:25 +02:00
|
|
|
"BFD down received",
|
|
|
|
"Interface down",
|
2019-09-03 21:55:49 +02:00
|
|
|
"Neighbor address lost",
|
bgpd: Add a new command to only show failed peerings
In a data center, having 32-128 peers is not uncommon. In such a situation, to find a
peer that has failed and why is several commands. This hinders both the automatability of
failure detection and the ease/speed with which the reason can be found. To simplify this
process of catching a failure and its cause quicker, this patch does the following:
1. Created a new function, bgp_show_failed_summary to display the
failed summary output for JSON and vty
2. Created a new function to display the reset code/subcode. This is now used in the
failed summary code and in the show neighbors code
3. Added a new variable failedPeers in all the JSON outputs, including the vanilla
"show bgp summary" family. This lists the failed session count.
4. Display peer, dropped count, estd count, uptime and the reason for failure as the
output of "show bgp summary failed" family of commands
5. Added three resset codes for the case where we're waiting for NHT, waiting for peer
IPv6 addr, waiting for VRF to init.
This also counts the case where only one peer has advertised an AFI/SAFI.
The new command has the optional keyword "failed" added to the classical summary command.
The changes affect only one existing output, that of "show [ip] bgp neighbors <nbr>". As
we track the lack of NHT resolution for a peer or the lack of knowing a peer IPv6 addr,
the output of that command will show a "waiting for NHT" etc. as the last reset reason.
This patch includes update to the documentation too.
Signed-off-by: Dinesh G Dutt <5016467+ddutt@users.noreply.github.com>
2019-08-31 18:24:49 +02:00
|
|
|
"Waiting for NHT",
|
2019-09-03 21:55:49 +02:00
|
|
|
"Waiting for Peer IPv6 LLA",
|
|
|
|
"Waiting for VRF to be initialized",
|
2020-02-11 01:25:52 +01:00
|
|
|
"No AFI/SAFI activated for peer",
|
|
|
|
"AS Set config change",
|
2020-02-14 22:21:55 +01:00
|
|
|
"Waiting for peer OPEN",
|
2021-09-03 13:56:35 +02:00
|
|
|
"Reached received prefix count",
|
|
|
|
"Socket Error"};
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-12-20 22:03:09 +01:00
|
|
|
static void bgp_graceful_restart_timer_off(struct peer *peer)
|
2004-05-20 11:19:34 +02:00
|
|
|
{
|
2005-02-02 15:40:33 +01:00
|
|
|
afi_t afi;
|
2004-05-20 11:19:34 +02:00
|
|
|
safi_t safi;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-12-20 22:03:09 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi)
|
|
|
|
if (CHECK_FLAG(peer->af_sflags[afi][safi],
|
|
|
|
PEER_STATUS_LLGR_WAIT))
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-02-02 15:40:33 +01:00
|
|
|
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
|
|
|
|
BGP_TIMER_OFF(peer->t_gr_stale);
|
bgpd: Do not delete BGP dynamic peers if graceful restart kicks in
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
*donatas-pc(192.168.10.17) 4 65002 8 12 0 0 0 00:01:35 2 14 N/A
```
Before shutting down 192.168.10.17:
```
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Last update: Sat Jan 15 21:45:47 2022
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (Older Path)
Last update: Sat Jan 15 21:25:19 2022
```
After 192.168.10.17 is down:
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
donatas-pc(192.168.10.17) 4 65002 5 9 0 0 0 00:00:12 Active 0 N/A
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Community: llgr-stale
Last update: Sat Jan 15 21:49:01 2022
Time until Long-lived stale route deleted: 16
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Sat Jan 15 21:25:19 2022
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
2022-01-15 22:16:15 +01:00
|
|
|
|
|
|
|
if (peer_dynamic_neighbor(peer) &&
|
|
|
|
!(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2022-01-15 22:44:26 +01:00
|
|
|
zlog_debug("%s (dynamic neighbor) deleted (%s)",
|
|
|
|
peer->host, __func__);
|
bgpd: Do not delete BGP dynamic peers if graceful restart kicks in
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
*donatas-pc(192.168.10.17) 4 65002 8 12 0 0 0 00:01:35 2 14 N/A
```
Before shutting down 192.168.10.17:
```
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Last update: Sat Jan 15 21:45:47 2022
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (Older Path)
Last update: Sat Jan 15 21:25:19 2022
```
After 192.168.10.17 is down:
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
donatas-pc(192.168.10.17) 4 65002 5 9 0 0 0 00:00:12 Active 0 N/A
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Community: llgr-stale
Last update: Sat Jan 15 21:49:01 2022
Time until Long-lived stale route deleted: 16
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Sat Jan 15 21:25:19 2022
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
2022-01-15 22:16:15 +01:00
|
|
|
peer_delete(peer);
|
|
|
|
}
|
|
|
|
|
2021-12-20 22:03:09 +01:00
|
|
|
bgp_timer_set(peer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bgp_llgr_stale_timer_expire(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct peer_af *paf;
|
|
|
|
struct peer *peer;
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
|
|
|
|
paf = THREAD_ARG(thread);
|
|
|
|
|
|
|
|
peer = paf->peer;
|
|
|
|
afi = paf->afi;
|
|
|
|
safi = paf->safi;
|
|
|
|
|
|
|
|
/* If the timer for the "Long-lived Stale Time" expires before the
|
|
|
|
* session is re-established, the helper MUST delete all the
|
|
|
|
* stale routes from the neighbor that it is retaining.
|
|
|
|
*/
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s Long-lived stale timer (%s) expired", peer->host,
|
|
|
|
get_afi_safi_str(afi, safi, false));
|
|
|
|
|
|
|
|
UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_LLGR_WAIT);
|
|
|
|
|
|
|
|
bgp_clear_stale_route(peer, afi, safi);
|
|
|
|
|
|
|
|
bgp_graceful_restart_timer_off(peer);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
|
|
|
|
{
|
|
|
|
struct bgp_dest *dest;
|
|
|
|
struct bgp_path_info *pi;
|
|
|
|
struct bgp_table *table;
|
|
|
|
struct attr attr;
|
|
|
|
|
|
|
|
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
|
|
|
|
for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
|
|
|
|
dest = bgp_route_next(dest)) {
|
|
|
|
struct bgp_dest *rm;
|
|
|
|
|
|
|
|
table = bgp_dest_get_bgp_table_info(dest);
|
|
|
|
if (!table)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (rm = bgp_table_top(table); rm;
|
|
|
|
rm = bgp_route_next(rm))
|
|
|
|
for (pi = bgp_dest_get_bgp_path_info(rm); pi;
|
|
|
|
pi = pi->next) {
|
|
|
|
if (pi->peer != peer)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pi->attr->community &&
|
|
|
|
community_include(
|
|
|
|
pi->attr->community,
|
|
|
|
COMMUNITY_NO_LLGR))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug(
|
|
|
|
"%s Long-lived set stale community (LLGR_STALE) for: %pFX",
|
|
|
|
peer->host, &dest->p);
|
|
|
|
|
|
|
|
attr = *pi->attr;
|
|
|
|
bgp_attr_add_llgr_community(&attr);
|
|
|
|
pi->attr = bgp_attr_intern(&attr);
|
|
|
|
bgp_recalculate_afi_safi_bestpaths(
|
|
|
|
peer->bgp, afi, safi);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
|
|
|
|
dest = bgp_route_next(dest))
|
|
|
|
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
|
|
|
|
pi = pi->next) {
|
|
|
|
if (pi->peer != peer)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pi->attr->community &&
|
|
|
|
community_include(pi->attr->community,
|
|
|
|
COMMUNITY_NO_LLGR))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug(
|
|
|
|
"%s Long-lived set stale community (LLGR_STALE) for: %pFX",
|
|
|
|
peer->host, &dest->p);
|
|
|
|
|
|
|
|
attr = *pi->attr;
|
|
|
|
bgp_attr_add_llgr_community(&attr);
|
|
|
|
pi->attr = bgp_attr_intern(&attr);
|
|
|
|
bgp_recalculate_afi_safi_bestpaths(peer->bgp,
|
|
|
|
afi, safi);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bgp_graceful_restart_timer_expire(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct peer *peer, *tmp_peer;
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct peer_af *paf;
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer)) {
|
2005-02-02 15:40:33 +01:00
|
|
|
zlog_debug("%s graceful restart timer expired", peer->host);
|
|
|
|
zlog_debug("%s graceful restart stalepath timer stopped",
|
|
|
|
peer->host);
|
|
|
|
}
|
|
|
|
|
2021-12-20 22:03:09 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
if (!peer->nsf[afi][safi])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Once the "Restart Time" period ends, the LLGR period is
|
|
|
|
* said to have begun and the following procedures MUST be
|
|
|
|
* performed:
|
|
|
|
*
|
|
|
|
* The helper router MUST start a timer for the
|
|
|
|
* "Long-lived Stale Time".
|
|
|
|
*
|
|
|
|
* The helper router MUST attach the LLGR_STALE community
|
|
|
|
* for the stale routes being retained. Note that this
|
|
|
|
* requirement implies that the routes would need to be
|
|
|
|
* readvertised, to disseminate the modified community.
|
|
|
|
*/
|
|
|
|
if (peer->llgr[afi][safi].stale_time) {
|
|
|
|
paf = peer_af_find(peer, afi, safi);
|
|
|
|
if (!paf)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug(
|
|
|
|
"%s Long-lived stale timer (%s) started for %d sec",
|
|
|
|
peer->host,
|
|
|
|
get_afi_safi_str(afi, safi, false),
|
|
|
|
peer->llgr[afi][safi].stale_time);
|
|
|
|
|
|
|
|
SET_FLAG(peer->af_sflags[afi][safi],
|
|
|
|
PEER_STATUS_LLGR_WAIT);
|
|
|
|
|
|
|
|
bgp_set_llgr_stale(peer, afi, safi);
|
|
|
|
bgp_clear_stale_route(peer, afi, safi);
|
|
|
|
|
|
|
|
thread_add_timer(bm->master,
|
|
|
|
bgp_llgr_stale_timer_expire, paf,
|
|
|
|
peer->llgr[afi][safi].stale_time,
|
|
|
|
&peer->t_llgr_stale[afi][safi]);
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS(peer->bgp->peer, node, nnode,
|
|
|
|
tmp_peer))
|
|
|
|
bgp_announce_route(tmp_peer, afi, safi, false);
|
|
|
|
} else {
|
|
|
|
bgp_clear_stale_route(peer, afi, safi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bgp_graceful_restart_timer_off(peer);
|
2005-02-02 15:40:33 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bgp_graceful_stale_timer_expire(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct peer *peer;
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2005-02-02 15:40:33 +01:00
|
|
|
zlog_debug("%s graceful restart stalepath timer expired",
|
|
|
|
peer->host);
|
|
|
|
|
|
|
|
/* NSF delete stale route */
|
2022-01-12 21:43:52 +01:00
|
|
|
FOREACH_AFI_SAFI_NSF (afi, safi)
|
|
|
|
if (peer->nsf[afi][safi])
|
|
|
|
bgp_clear_stale_route(peer, afi, safi);
|
2005-02-02 15:40:33 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-10-23 20:14:51 +02:00
|
|
|
/* Selection deferral timer processing function */
|
|
|
|
static int bgp_graceful_deferral_timer_expire(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct afi_safi_info *info;
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
struct bgp *bgp;
|
|
|
|
|
|
|
|
info = THREAD_ARG(thread);
|
|
|
|
afi = info->afi;
|
|
|
|
safi = info->safi;
|
|
|
|
bgp = info->bgp;
|
|
|
|
|
|
|
|
if (BGP_DEBUG(update, UPDATE_OUT))
|
2020-01-31 15:19:24 +01:00
|
|
|
zlog_debug(
|
|
|
|
"afi %d, safi %d : graceful restart deferral timer expired",
|
|
|
|
afi, safi);
|
2019-10-23 20:14:51 +02:00
|
|
|
|
|
|
|
bgp->gr_info[afi][safi].eor_required = 0;
|
|
|
|
bgp->gr_info[afi][safi].eor_received = 0;
|
|
|
|
XFREE(MTYPE_TMP, info);
|
|
|
|
|
|
|
|
/* Best path selection */
|
|
|
|
return bgp_best_path_select_defer(bgp, afi, safi);
|
|
|
|
}
|
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
static bool bgp_update_delay_applicable(struct bgp *bgp)
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
{
|
|
|
|
/* update_delay_over flag should be reset (set to 0) for any new
|
|
|
|
applicability of the update-delay during BGP process lifetime.
|
|
|
|
And it should be set after an occurence of the update-delay is
|
|
|
|
over)*/
|
|
|
|
if (!bgp->update_delay_over)
|
2020-03-20 10:57:54 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
}
|
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
bool bgp_update_delay_active(struct bgp *bgp)
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
{
|
|
|
|
if (bgp->t_update_delay)
|
2020-03-20 10:57:54 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
}
|
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
bool bgp_update_delay_configured(struct bgp *bgp)
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
{
|
|
|
|
if (bgp->v_update_delay)
|
2020-03-20 10:57:54 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Do the post-processing needed when bgp comes out of the read-only mode
|
|
|
|
on ending the update delay. */
|
|
|
|
void bgp_update_delay_end(struct bgp *bgp)
|
|
|
|
{
|
2020-07-17 23:09:51 +02:00
|
|
|
THREAD_OFF(bgp->t_update_delay);
|
|
|
|
THREAD_OFF(bgp->t_establish_wait);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
/* Reset update-delay related state */
|
|
|
|
bgp->update_delay_over = 1;
|
|
|
|
bgp->established = 0;
|
|
|
|
bgp->restarted_peers = 0;
|
|
|
|
bgp->implicit_eors = 0;
|
|
|
|
bgp->explicit_eors = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-11-11 20:33:41 +01:00
|
|
|
frr_timestamp(3, bgp->update_delay_end_time,
|
|
|
|
sizeof(bgp->update_delay_end_time));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
/*
|
|
|
|
* Add an end-of-initial-update marker to the main process queues so
|
|
|
|
* that
|
2015-05-20 02:40:42 +02:00
|
|
|
* the route advertisement timer for the peers can be started. Also set
|
|
|
|
* the zebra and peer update hold flags. These flags are used to achieve
|
|
|
|
* three stages in the update-delay post processing:
|
|
|
|
* 1. Finish best-path selection for all the prefixes held on the
|
|
|
|
* queues.
|
|
|
|
* (routes in BGP are updated, and peers sync queues are populated
|
|
|
|
* too)
|
|
|
|
* 2. As the eoiu mark is reached in the bgp process routine, ship all
|
|
|
|
* the
|
|
|
|
* routes to zebra. With that zebra should see updates from BGP
|
|
|
|
* close
|
|
|
|
* to each other.
|
|
|
|
* 3. Unblock the peer update writes. With that peer update packing
|
|
|
|
* with
|
|
|
|
* the prefixes should be at its maximum.
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
*/
|
2015-11-10 16:29:12 +01:00
|
|
|
bgp_add_eoiu_mark(bgp);
|
2015-05-20 02:40:42 +02:00
|
|
|
bgp->main_zebra_update_hold = 1;
|
|
|
|
bgp->main_peers_update_hold = 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-10-17 15:43:14 +02:00
|
|
|
/*
|
|
|
|
* Resume the queue processing. This should trigger the event that would
|
|
|
|
* take care of processing any work that was queued during the read-only
|
|
|
|
* mode.
|
|
|
|
*/
|
|
|
|
work_queue_unplug(bgp->process_queue);
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
}
|
|
|
|
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
/**
|
|
|
|
* see bgp_fsm.h
|
|
|
|
*/
|
|
|
|
void bgp_start_routeadv(struct bgp *bgp)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct peer *peer;
|
|
|
|
|
2015-11-10 16:29:12 +01:00
|
|
|
zlog_info("bgp_start_routeadv(), update hold status %d",
|
|
|
|
bgp->main_peers_update_hold);
|
2015-05-20 02:40:42 +02:00
|
|
|
|
2015-11-10 16:29:12 +01:00
|
|
|
if (bgp->main_peers_update_hold)
|
2015-05-20 02:40:42 +02:00
|
|
|
return;
|
|
|
|
|
2021-11-11 20:33:41 +01:00
|
|
|
frr_timestamp(3, bgp->update_delay_peers_resume_time,
|
|
|
|
sizeof(bgp->update_delay_peers_resume_time));
|
2015-05-20 02:40:42 +02:00
|
|
|
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
2021-06-07 15:39:10 +02:00
|
|
|
if (!peer_established(peer))
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
continue;
|
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
|
|
|
BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* see bgp_fsm.h
|
|
|
|
*/
|
|
|
|
void bgp_adjust_routeadv(struct peer *peer)
|
|
|
|
{
|
|
|
|
time_t nowtime = bgp_clock();
|
|
|
|
double diff;
|
|
|
|
unsigned long remain;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
/* Bypass checks for special case of MRAI being 0 */
|
|
|
|
if (peer->v_routeadv == 0) {
|
|
|
|
/* Stop existing timer, just in case it is running for a
|
|
|
|
* different
|
|
|
|
* duration and schedule write thread immediately.
|
|
|
|
*/
|
2021-12-21 09:57:07 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
peer->synctime = bgp_clock();
|
2020-11-06 04:25:56 +01:00
|
|
|
/* If suppress fib pending is enabled, route is advertised to
|
|
|
|
* peers when the status is received from the FIB. The delay
|
|
|
|
* is added to update group packet generate which will allow
|
|
|
|
* more routes to be sent in the update message
|
|
|
|
*/
|
|
|
|
BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
|
|
|
|
bgp_generate_updgrp_packets);
|
2015-05-20 02:58:12 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
/*
|
|
|
|
* CASE I:
|
|
|
|
* If the last update was written more than MRAI back, expire the timer
|
|
|
|
* instantly so that we can send the update out sooner.
|
|
|
|
*
|
|
|
|
* <------- MRAI --------->
|
|
|
|
* |-----------------|-----------------------|
|
|
|
|
* <------------- m ------------>
|
|
|
|
* ^ ^ ^
|
|
|
|
* | | |
|
|
|
|
* | | current time
|
|
|
|
* | timer start
|
|
|
|
* last write
|
|
|
|
*
|
|
|
|
* m > MRAI
|
|
|
|
*/
|
2016-10-06 15:20:02 +02:00
|
|
|
diff = difftime(nowtime, peer->last_update);
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
if (diff > (double)peer->v_routeadv) {
|
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
|
|
|
BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
|
|
|
|
return;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
/*
|
|
|
|
* CASE II:
|
|
|
|
* - Find when to expire the MRAI timer.
|
|
|
|
* If MRAI timer is not active, assume we can start it now.
|
|
|
|
*
|
|
|
|
* <------- MRAI --------->
|
|
|
|
* |------------|-----------------------|
|
|
|
|
* <-------- m ----------><----- r ----->
|
|
|
|
* ^ ^ ^
|
|
|
|
* | | |
|
|
|
|
* | | current time
|
|
|
|
* | timer start
|
|
|
|
* last write
|
|
|
|
*
|
|
|
|
* (MRAI - m) < r
|
|
|
|
*/
|
|
|
|
if (peer->t_routeadv)
|
|
|
|
remain = thread_timer_remain_second(peer->t_routeadv);
|
|
|
|
else
|
|
|
|
remain = peer->v_routeadv;
|
|
|
|
diff = peer->v_routeadv - diff;
|
|
|
|
if (diff <= (double)remain) {
|
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
|
|
|
BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
static bool bgp_maxmed_onstartup_applicable(struct bgp *bgp)
|
2015-05-20 02:40:42 +02:00
|
|
|
{
|
|
|
|
if (!bgp->maxmed_onstartup_over)
|
2020-03-20 10:57:54 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
2015-05-20 02:40:42 +02:00
|
|
|
}
|
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
bool bgp_maxmed_onstartup_configured(struct bgp *bgp)
|
2015-05-20 02:40:42 +02:00
|
|
|
{
|
|
|
|
if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
|
2020-03-20 10:57:54 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
2015-05-20 02:40:42 +02:00
|
|
|
}
|
|
|
|
|
2020-03-20 10:57:54 +01:00
|
|
|
bool bgp_maxmed_onstartup_active(struct bgp *bgp)
|
2015-05-20 02:40:42 +02:00
|
|
|
{
|
|
|
|
if (bgp->t_maxmed_onstartup)
|
2020-03-20 10:57:54 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
2015-05-20 02:40:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void bgp_maxmed_update(struct bgp *bgp)
|
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t maxmed_active;
|
|
|
|
uint32_t maxmed_value;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:42 +02:00
|
|
|
if (bgp->v_maxmed_admin) {
|
|
|
|
maxmed_active = 1;
|
|
|
|
maxmed_value = bgp->maxmed_admin_value;
|
|
|
|
} else if (bgp->t_maxmed_onstartup) {
|
|
|
|
maxmed_active = 1;
|
|
|
|
maxmed_value = bgp->maxmed_onstartup_value;
|
|
|
|
} else {
|
|
|
|
maxmed_active = 0;
|
|
|
|
maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:42 +02:00
|
|
|
if (bgp->maxmed_active != maxmed_active
|
|
|
|
|| bgp->maxmed_value != maxmed_value) {
|
|
|
|
bgp->maxmed_active = maxmed_active;
|
|
|
|
bgp->maxmed_value = maxmed_value;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:03:47 +02:00
|
|
|
update_group_announce(bgp);
|
2015-05-20 02:40:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-15 13:19:11 +01:00
|
|
|
int bgp_fsm_error_subcode(int status)
|
|
|
|
{
|
|
|
|
int fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC;
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case OpenSent:
|
|
|
|
fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT;
|
|
|
|
break;
|
|
|
|
case OpenConfirm:
|
|
|
|
fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM;
|
|
|
|
break;
|
|
|
|
case Established:
|
|
|
|
fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fsm_err_subcode;
|
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:42 +02:00
|
|
|
/* The maxmed onstartup timer expiry callback. */
|
|
|
|
static int bgp_maxmed_onstartup_timer(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct bgp *bgp;
|
|
|
|
|
|
|
|
zlog_info("Max med on startup ended - timer expired.");
|
|
|
|
|
|
|
|
bgp = THREAD_ARG(thread);
|
2020-07-17 23:09:51 +02:00
|
|
|
THREAD_OFF(bgp->t_maxmed_onstartup);
|
2015-05-20 02:40:42 +02:00
|
|
|
bgp->maxmed_onstartup_over = 1;
|
|
|
|
|
|
|
|
bgp_maxmed_update(bgp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bgp_maxmed_onstartup_begin(struct bgp *bgp)
|
|
|
|
{
|
|
|
|
/* Applicable only once in the process lifetime on the startup */
|
|
|
|
if (bgp->maxmed_onstartup_over)
|
|
|
|
return;
|
|
|
|
|
|
|
|
zlog_info("Begin maxmed onstartup mode - timer %d seconds",
|
|
|
|
bgp->v_maxmed_onstartup);
|
|
|
|
|
2017-04-25 00:33:25 +02:00
|
|
|
thread_add_timer(bm->master, bgp_maxmed_onstartup_timer, bgp,
|
|
|
|
bgp->v_maxmed_onstartup, &bgp->t_maxmed_onstartup);
|
2015-05-20 02:40:42 +02:00
|
|
|
|
|
|
|
if (!bgp->v_maxmed_admin) {
|
|
|
|
bgp->maxmed_active = 1;
|
|
|
|
bgp->maxmed_value = bgp->maxmed_onstartup_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route announce to all peers should happen after this in
|
|
|
|
* bgp_establish() */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bgp_maxmed_onstartup_process_status_change(struct peer *peer)
|
|
|
|
{
|
2021-06-07 15:39:10 +02:00
|
|
|
if (peer_established(peer) && !peer->bgp->established) {
|
2015-05-20 02:40:42 +02:00
|
|
|
bgp_maxmed_onstartup_begin(peer->bgp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
/* The update delay timer expiry callback. */
|
|
|
|
static int bgp_update_delay_timer(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct bgp *bgp;
|
|
|
|
|
|
|
|
zlog_info("Update delay ended - timer expired.");
|
|
|
|
|
|
|
|
bgp = THREAD_ARG(thread);
|
2020-07-17 23:09:51 +02:00
|
|
|
THREAD_OFF(bgp->t_update_delay);
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
bgp_update_delay_end(bgp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The establish wait timer expiry callback. */
|
|
|
|
static int bgp_establish_wait_timer(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct bgp *bgp;
|
|
|
|
|
|
|
|
zlog_info("Establish wait - timer expired.");
|
|
|
|
|
|
|
|
bgp = THREAD_ARG(thread);
|
2020-07-17 23:09:51 +02:00
|
|
|
THREAD_OFF(bgp->t_establish_wait);
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
bgp_check_update_delay(bgp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Steps to begin the update delay:
|
|
|
|
- initialize queues if needed
|
|
|
|
- stop the queue processing
|
|
|
|
- start the timer */
|
|
|
|
static void bgp_update_delay_begin(struct bgp *bgp)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
/* Stop the processing of queued work. Enqueue shall continue */
|
2020-10-17 15:43:14 +02:00
|
|
|
work_queue_plug(bgp->process_queue);
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
|
|
|
|
peer->update_delay_over = 0;
|
|
|
|
|
|
|
|
/* Start the update-delay timer */
|
2017-04-25 00:33:25 +02:00
|
|
|
thread_add_timer(bm->master, bgp_update_delay_timer, bgp,
|
|
|
|
bgp->v_update_delay, &bgp->t_update_delay);
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
|
|
|
|
if (bgp->v_establish_wait != bgp->v_update_delay)
|
2017-04-25 00:33:25 +02:00
|
|
|
thread_add_timer(bm->master, bgp_establish_wait_timer, bgp,
|
|
|
|
bgp->v_establish_wait, &bgp->t_establish_wait);
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
|
2021-11-11 20:33:41 +01:00
|
|
|
frr_timestamp(3, bgp->update_delay_begin_time,
|
|
|
|
sizeof(bgp->update_delay_begin_time));
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void bgp_update_delay_process_status_change(struct peer *peer)
|
|
|
|
{
|
2021-06-07 15:39:10 +02:00
|
|
|
if (peer_established(peer)) {
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
if (!peer->bgp->established++) {
|
|
|
|
bgp_update_delay_begin(peer->bgp);
|
|
|
|
zlog_info(
|
|
|
|
"Begin read-only mode - update-delay timer %d seconds",
|
|
|
|
peer->bgp->v_update_delay);
|
|
|
|
}
|
|
|
|
if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV))
|
|
|
|
bgp_update_restarted_peers(peer);
|
|
|
|
}
|
|
|
|
if (peer->ostatus == Established
|
|
|
|
&& bgp_update_delay_active(peer->bgp)) {
|
|
|
|
/* Adjust the update-delay state to account for this flap.
|
|
|
|
NOTE: Intentionally skipping adjusting implicit_eors or
|
|
|
|
explicit_eors
|
|
|
|
counters. Extra sanity check in bgp_check_update_delay()
|
|
|
|
should
|
|
|
|
be enough to take care of any additive discrepancy in bgp eor
|
|
|
|
counters */
|
|
|
|
peer->bgp->established--;
|
|
|
|
peer->update_delay_over = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-25 20:06:59 +02:00
|
|
|
/* Called after event occurred, this function change status and reset
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
read/write and timer thread. */
|
|
|
|
void bgp_fsm_change_status(struct peer *peer, int status)
|
|
|
|
{
|
2018-11-19 13:35:32 +01:00
|
|
|
struct bgp *bgp;
|
|
|
|
uint32_t peer_count;
|
2015-05-20 02:40:37 +02:00
|
|
|
|
2018-11-19 13:35:32 +01:00
|
|
|
bgp = peer->bgp;
|
|
|
|
peer_count = bgp->established_peers;
|
|
|
|
|
|
|
|
if (status == Established)
|
|
|
|
bgp->established_peers++;
|
2021-06-07 15:39:10 +02:00
|
|
|
else if ((peer_established(peer)) && (status != Established))
|
2018-11-19 13:35:32 +01:00
|
|
|
bgp->established_peers--;
|
|
|
|
|
2019-05-29 00:08:28 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer)) {
|
|
|
|
struct vrf *vrf = vrf_lookup_by_id(bgp->vrf_id);
|
|
|
|
|
|
|
|
zlog_debug("%s : vrf %s(%u), Status: %s established_peers %u", __func__,
|
|
|
|
vrf ? vrf->name : "Unknown", bgp->vrf_id,
|
|
|
|
lookup_msg(bgp_status_msg, status, NULL),
|
|
|
|
bgp->established_peers);
|
|
|
|
}
|
|
|
|
|
2018-11-19 13:35:32 +01:00
|
|
|
/* Set to router ID to the value provided by RIB if there are no peers
|
|
|
|
* in the established state and peer count did not change
|
|
|
|
*/
|
|
|
|
if ((peer_count != bgp->established_peers) &&
|
|
|
|
(bgp->established_peers == 0))
|
|
|
|
bgp_router_id_zebra_bump(bgp->vrf_id, NULL);
|
|
|
|
|
2007-02-22 18:48:42 +01:00
|
|
|
/* Transition into Clearing or Deleted must /always/ clear all routes..
|
|
|
|
* (and must do so before actually changing into Deleted..
|
|
|
|
*/
|
|
|
|
if (status >= Clearing) {
|
2015-05-20 03:04:12 +02:00
|
|
|
bgp_clear_route_all(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:04:12 +02:00
|
|
|
/* If no route was queued for the clear-node processing,
|
|
|
|
* generate the
|
|
|
|
* completion event here. This is needed because if there are no
|
|
|
|
* routes
|
|
|
|
* to trigger the background clear-node thread, the event won't
|
|
|
|
* get
|
|
|
|
* generated and the peer would be stuck in Clearing. Note that
|
|
|
|
* this
|
|
|
|
* event is for the peer and helps the peer transition out of
|
|
|
|
* Clearing
|
|
|
|
* state; it should not be generated per (AFI,SAFI). The event
|
|
|
|
* is
|
|
|
|
* directly posted here without calling clear_node_complete() as
|
|
|
|
* we
|
|
|
|
* shouldn't do an extra unlock. This event will get processed
|
|
|
|
* after
|
|
|
|
* the state change that happens below, so peer will be in
|
|
|
|
* Clearing
|
|
|
|
* (or Deleted).
|
|
|
|
*/
|
2015-09-15 17:17:22 +02:00
|
|
|
if (!work_queue_is_scheduled(peer->clear_node_queue))
|
2015-05-20 03:04:12 +02:00
|
|
|
BGP_EVENT_ADD(peer, Clearing_Completed);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
/* Preserve old status and change into new status. */
|
|
|
|
peer->ostatus = peer->status;
|
|
|
|
peer->status = status;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-07-25 08:10:56 +02:00
|
|
|
/* Reset received keepalives counter on every FSM change */
|
|
|
|
peer->rtt_keepalive_rcv = 0;
|
|
|
|
|
2020-08-04 15:19:25 +02:00
|
|
|
/* Fire backward transition hook if that's the case */
|
|
|
|
if (peer->ostatus > peer->status)
|
|
|
|
hook_call(peer_backward_transition, peer);
|
|
|
|
|
2015-05-20 03:04:12 +02:00
|
|
|
/* Save event that caused status change. */
|
|
|
|
peer->last_major_event = peer->cur_event;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-08-09 19:53:01 +02:00
|
|
|
/* Operations after status change */
|
|
|
|
hook_call(peer_status_changed, peer);
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
if (status == Established)
|
|
|
|
UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:42 +02:00
|
|
|
/* If max-med processing is applicable, do the necessary. */
|
|
|
|
if (status == Established) {
|
|
|
|
if (bgp_maxmed_onstartup_configured(peer->bgp)
|
|
|
|
&& bgp_maxmed_onstartup_applicable(peer->bgp))
|
|
|
|
bgp_maxmed_onstartup_process_status_change(peer);
|
|
|
|
else
|
|
|
|
peer->bgp->maxmed_onstartup_over = 1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
bgpd: bgpd-update-delay.patch
COMMAND:
'update-delay <max-delay in seconds> [<establish-wait in seconds>]'
DESCRIPTION:
This feature is used to enable read-only mode on BGP process restart or when
BGP process is cleared using 'clear ip bgp *'. When applicable, read-only mode
would begin as soon as the first peer reaches Established state and a timer
for <max-delay> seconds is started.
During this mode BGP doesn't run any best-path or generate any updates to its
peers. This mode continues until:
1. All the configured peers, except the shutdown peers, have sent explicit EOR
(End-Of-RIB) or an implicit-EOR. The first keep-alive after BGP has reached
Established is considered an implicit-EOR.
If the <establish-wait> optional value is given, then BGP will wait for
peers to reach establish from the begining of the update-delay till the
establish-wait period is over, i.e. the minimum set of established peers for
which EOR is expected would be peers established during the establish-wait
window, not necessarily all the configured neighbors.
2. max-delay period is over.
On hitting any of the above two conditions, BGP resumes the decision process
and generates updates to its peers.
Default <max-delay> is 0, i.e. the feature is off by default.
This feature can be useful in reducing CPU/network used as BGP restarts/clears.
Particularly useful in the topologies where BGP learns a prefix from many peers.
Intermediate bestpaths are possible for the same prefix as peers get established
and start receiving updates at different times. This feature should offer a
value-add if the network has a high number of such prefixes.
IMPLEMENTATION OBJECTIVES:
Given this is an optional feature, minimized the code-churn. Used existing
constructs wherever possible (existing queue-plug/unplug were used to achieve
delay and resume of best-paths/update-generation). As a result, no new
data-structure(s) had to be defined and allocated. When the feature is disabled,
the new node is not exercised for the most part.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Dinesh Dutt <ddutt@cumulusnetworks.com>
2015-05-20 02:40:33 +02:00
|
|
|
/* If update-delay processing is applicable, do the necessary. */
|
|
|
|
if (bgp_update_delay_configured(peer->bgp)
|
|
|
|
&& bgp_update_delay_applicable(peer->bgp))
|
|
|
|
bgp_update_delay_process_status_change(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
zlog_debug("%s went from %s to %s", peer->host,
|
2017-06-21 01:56:50 +02:00
|
|
|
lookup_msg(bgp_status_msg, peer->ostatus, NULL),
|
|
|
|
lookup_msg(bgp_status_msg, peer->status, NULL));
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
}
|
|
|
|
|
2009-07-28 18:50:00 +02:00
|
|
|
/* Flush the event queue and ensure the peer is shut down */
|
|
|
|
static int bgp_clearing_completed(struct peer *peer)
|
|
|
|
{
|
|
|
|
int rc = bgp_stop(peer);
|
2015-05-20 02:40:37 +02:00
|
|
|
|
|
|
|
if (rc >= 0)
|
|
|
|
BGP_EVENT_FLUSH(peer);
|
2009-07-28 18:50:00 +02:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Administrative BGP peer stop event. */
|
2009-07-28 18:50:00 +02:00
|
|
|
/* May be called multiple times for the same peer */
|
2002-12-13 21:15:29 +01:00
|
|
|
int bgp_stop(struct peer *peer)
|
|
|
|
{
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
char orf_name[BUFSIZ];
|
2015-05-20 02:40:37 +02:00
|
|
|
int ret = 0;
|
2019-10-23 20:14:51 +02:00
|
|
|
struct bgp *bgp = peer->bgp;
|
|
|
|
struct graceful_restart_info *gr_info = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-11-25 16:18:15 +01:00
|
|
|
peer->nsf_af_count = 0;
|
|
|
|
|
2020-03-10 09:20:09 +01:00
|
|
|
/* deregister peer */
|
2021-02-26 20:50:51 +01:00
|
|
|
if (peer->bfd_config
|
|
|
|
&& peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE)
|
|
|
|
bfd_sess_uninstall(peer->bfd_config->session);
|
2020-03-10 09:20:09 +01:00
|
|
|
|
bgpd: Do not delete BGP dynamic peers if graceful restart kicks in
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
*donatas-pc(192.168.10.17) 4 65002 8 12 0 0 0 00:01:35 2 14 N/A
```
Before shutting down 192.168.10.17:
```
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Last update: Sat Jan 15 21:45:47 2022
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (Older Path)
Last update: Sat Jan 15 21:25:19 2022
```
After 192.168.10.17 is down:
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
donatas-pc(192.168.10.17) 4 65002 5 9 0 0 0 00:00:12 Active 0 N/A
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Community: llgr-stale
Last update: Sat Jan 15 21:49:01 2022
Time until Long-lived stale route deleted: 16
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Sat Jan 15 21:25:19 2022
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
2022-01-15 22:16:15 +01:00
|
|
|
if (peer_dynamic_neighbor_no_nsf(peer) &&
|
|
|
|
!(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
|
2003-08-13 02:32:49 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2022-01-15 22:44:26 +01:00
|
|
|
zlog_debug("%s (dynamic neighbor) deleted (%s)",
|
|
|
|
peer->host, __func__);
|
2016-11-15 16:16:52 +01:00
|
|
|
peer_delete(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
2003-08-13 02:32:49 +02:00
|
|
|
|
2005-02-02 15:40:33 +01:00
|
|
|
/* Can't do this in Clearing; events are used for state transitions */
|
|
|
|
if (peer->status != Clearing) {
|
|
|
|
/* Delete all existing events of the peer */
|
|
|
|
BGP_EVENT_FLUSH(peer);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Increment Dropped count. */
|
2021-06-07 15:39:10 +02:00
|
|
|
if (peer_established(peer)) {
|
2002-12-13 21:15:29 +01:00
|
|
|
peer->dropped++;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-08-13 02:32:49 +02:00
|
|
|
/* bgp log-neighbor-changes of neighbor Down */
|
2020-02-06 15:37:20 +01:00
|
|
|
if (CHECK_FLAG(peer->bgp->flags,
|
|
|
|
BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
|
2016-11-15 16:16:52 +01:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
|
2019-10-23 12:02:48 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zlog_info(
|
2016-11-15 16:16:52 +01:00
|
|
|
"%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s",
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
peer->host,
|
2016-11-15 16:16:52 +01:00
|
|
|
(peer->hostname) ? peer->hostname : "Unknown",
|
2018-07-20 17:02:15 +02:00
|
|
|
vrf ? ((vrf->vrf_id != VRF_DEFAULT)
|
|
|
|
? vrf->name
|
|
|
|
: VRF_DEFAULT_NAME)
|
2017-07-17 14:03:14 +02:00
|
|
|
: "",
|
2016-11-15 16:16:52 +01:00
|
|
|
peer_down_str[(int)peer->last_reset]);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-02 15:40:33 +01:00
|
|
|
/* graceful restart */
|
|
|
|
if (peer->t_gr_stale) {
|
|
|
|
BGP_TIMER_OFF(peer->t_gr_stale);
|
2015-05-20 03:03:47 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2015-05-20 02:40:37 +02:00
|
|
|
zlog_debug(
|
2005-02-02 15:40:33 +01:00
|
|
|
"%s graceful restart stalepath timer stopped",
|
2015-05-20 03:03:47 +02:00
|
|
|
peer->host);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2005-02-02 15:40:33 +01:00
|
|
|
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer)) {
|
2005-02-02 15:40:33 +01:00
|
|
|
zlog_debug(
|
|
|
|
"%s graceful restart timer started for %d sec",
|
|
|
|
peer->host, peer->v_gr_restart);
|
|
|
|
zlog_debug(
|
|
|
|
"%s graceful restart stalepath timer started for %d sec",
|
|
|
|
peer->host, peer->bgp->stalepath_time);
|
|
|
|
}
|
|
|
|
BGP_TIMER_ON(peer->t_gr_restart,
|
|
|
|
bgp_graceful_restart_timer_expire,
|
|
|
|
peer->v_gr_restart);
|
|
|
|
BGP_TIMER_ON(peer->t_gr_stale,
|
|
|
|
bgp_graceful_stale_timer_expire,
|
|
|
|
peer->bgp->stalepath_time);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2005-02-02 15:40:33 +01:00
|
|
|
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-12 21:43:52 +01:00
|
|
|
FOREACH_AFI_SAFI_NSF (afi, safi)
|
|
|
|
peer->nsf[afi][safi] = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2020-10-01 22:08:06 +02:00
|
|
|
/* Stop route-refresh stalepath timer */
|
|
|
|
if (peer->t_refresh_stalepath) {
|
|
|
|
BGP_TIMER_OFF(peer->t_refresh_stalepath);
|
|
|
|
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug(
|
|
|
|
"%s: route-refresh restart stalepath timer stopped",
|
|
|
|
peer->host);
|
|
|
|
}
|
|
|
|
|
2019-10-23 20:14:51 +02:00
|
|
|
/* If peer reset before receiving EOR, decrement EOR count and
|
|
|
|
* cancel the selection deferral timer if there are no
|
|
|
|
* pending EOR messages to be received
|
|
|
|
*/
|
|
|
|
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
|
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
2020-01-31 15:19:24 +01:00
|
|
|
if (!peer->afc_nego[afi][safi]
|
|
|
|
|| CHECK_FLAG(peer->af_sflags[afi][safi],
|
|
|
|
PEER_STATUS_EOR_RECEIVED))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gr_info = &bgp->gr_info[afi][safi];
|
|
|
|
if (!gr_info)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (gr_info->eor_required)
|
|
|
|
gr_info->eor_required--;
|
|
|
|
|
|
|
|
if (BGP_DEBUG(update, UPDATE_OUT))
|
|
|
|
zlog_debug("peer %s, EOR_required %d",
|
|
|
|
peer->host,
|
|
|
|
gr_info->eor_required);
|
|
|
|
|
|
|
|
/* There is no pending EOR message */
|
|
|
|
if (gr_info->eor_required == 0) {
|
|
|
|
BGP_TIMER_OFF(
|
2019-10-23 20:14:51 +02:00
|
|
|
gr_info->t_select_deferral);
|
2020-01-31 15:19:24 +01:00
|
|
|
gr_info->eor_received = 0;
|
2019-10-23 20:14:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-13 02:32:49 +02:00
|
|
|
/* set last reset time */
|
2010-01-15 14:22:10 +01:00
|
|
|
peer->resettime = peer->uptime = bgp_clock();
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:03:47 +02:00
|
|
|
if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
|
|
|
|
zlog_debug("%s remove from all update group",
|
|
|
|
peer->host);
|
|
|
|
update_group_remove_peer_afs(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-02-01 21:13:16 +01:00
|
|
|
/* Reset peer synctime */
|
|
|
|
peer->synctime = 0;
|
2005-02-02 15:40:33 +01:00
|
|
|
}
|
|
|
|
|
2017-05-02 02:37:45 +02:00
|
|
|
/* stop keepalives */
|
2017-05-12 05:54:18 +02:00
|
|
|
bgp_keepalives_off(peer);
|
2017-05-02 02:37:45 +02:00
|
|
|
|
|
|
|
/* Stop read and write threads. */
|
|
|
|
bgp_writes_off(peer);
|
|
|
|
bgp_reads_off(peer);
|
|
|
|
|
2017-09-25 04:18:15 +02:00
|
|
|
THREAD_OFF(peer->t_connect_check_r);
|
|
|
|
THREAD_OFF(peer->t_connect_check_w);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-05-25 17:28:31 +02:00
|
|
|
/* Stop all timers. */
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_start);
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
2015-05-20 03:03:47 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
2020-10-20 16:49:58 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Clear input and output buffer. */
|
2019-06-21 10:58:02 +02:00
|
|
|
frr_with_mutex(&peer->io_mtx) {
|
2017-05-02 02:37:45 +02:00
|
|
|
if (peer->ibuf)
|
|
|
|
stream_fifo_clean(peer->ibuf);
|
2017-02-07 00:39:06 +01:00
|
|
|
if (peer->obuf)
|
|
|
|
stream_fifo_clean(peer->obuf);
|
2017-05-02 02:37:45 +02:00
|
|
|
|
|
|
|
if (peer->ibuf_work)
|
2018-01-02 19:20:00 +01:00
|
|
|
ringbuf_wipe(peer->ibuf_work);
|
2017-05-02 02:37:45 +02:00
|
|
|
if (peer->obuf_work)
|
|
|
|
stream_reset(peer->obuf_work);
|
|
|
|
|
|
|
|
if (peer->curr) {
|
|
|
|
stream_free(peer->curr);
|
|
|
|
peer->curr = NULL;
|
|
|
|
}
|
2017-02-07 00:39:06 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-02-02 15:40:33 +01:00
|
|
|
/* Close of file descriptor. */
|
2004-05-01 10:44:08 +02:00
|
|
|
if (peer->fd >= 0) {
|
|
|
|
close(peer->fd);
|
|
|
|
peer->fd = -1;
|
2005-02-02 15:40:33 +01:00
|
|
|
}
|
|
|
|
|
bgpd: Clear capabilities field when resetting a bgp neighbor
Currently, the following sequence of events between peers could
result in erroneous capability reports on the peer
with enabled dont-capability-negotiate option:
- having some of the capabilities advertised to a bgp neighbor,
- then disabling capability negotiation to that neighbor,
- then resetting connection to it,
- and no capabilities are actually sent to the neighbor,
- but "show bgp neighbors" on the host still displays them
as advertised to the neighbor.
There are two possibilities for establishing a new connection
- the established connection was initiated by us with bgp_start(),
- the connection was initiated on the neighbor side and processed by
us via bgp_accept() in bgp_network.c.
The former case results in "show bgp neighbors" displaying only
"received" in capabilities, as the peer's cap is initiated to zero
in bgp_start().
In the latter case, if bgp_accept() happens before bgp_start()
is called, then new peer capabilities are being transferred
from its previous record before being zeroed in bgp_start().
This results in "show bgp neighbors" still displaying
"advertised and received" in capabilities.
Following the logic of a similar af_cap field clearing,
treated correctly in both cases, we
- reset peer's capability during bgp_stop()
- don't pass it over to a new peer structure in bgp_accept().
This fix prevents transferring of the previous capabilities record
to a new peer instance in arbitrary reconnect scenario.
Signed-off-by: Alexander Skorichenko <askorichenko@netgate.com>
2021-07-14 22:43:37 +02:00
|
|
|
/* Reset capabilities. */
|
|
|
|
peer->cap = 0;
|
|
|
|
|
2017-11-21 19:02:06 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
/* Reset all negotiated variables */
|
|
|
|
peer->afc_nego[afi][safi] = 0;
|
|
|
|
peer->afc_adv[afi][safi] = 0;
|
|
|
|
peer->afc_recv[afi][safi] = 0;
|
|
|
|
|
|
|
|
/* peer address family capability flags*/
|
|
|
|
peer->af_cap[afi][safi] = 0;
|
|
|
|
|
|
|
|
/* peer address family status flags*/
|
|
|
|
peer->af_sflags[afi][safi] = 0;
|
|
|
|
|
|
|
|
/* Received ORF prefix-filter */
|
|
|
|
peer->orf_plist[afi][safi] = NULL;
|
|
|
|
|
2021-06-07 15:39:10 +02:00
|
|
|
if ((peer->status == OpenConfirm) || (peer_established(peer))) {
|
2017-11-21 19:02:06 +01:00
|
|
|
/* ORF received prefix-filter pnt */
|
2020-04-20 23:59:31 +02:00
|
|
|
snprintf(orf_name, sizeof(orf_name), "%s.%d.%d",
|
|
|
|
peer->host, afi, safi);
|
2017-11-21 19:02:06 +01:00
|
|
|
prefix_bgp_orf_remove_all(afi, orf_name);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-11-21 19:02:06 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-21 11:31:30 +02:00
|
|
|
/* Reset keepalive and holdtime */
|
2018-06-13 02:34:43 +02:00
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) {
|
2015-05-20 02:40:37 +02:00
|
|
|
peer->v_keepalive = peer->keepalive;
|
|
|
|
peer->v_holdtime = peer->holdtime;
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2015-04-13 10:21:35 +02:00
|
|
|
peer->v_keepalive = peer->bgp->default_keepalive;
|
|
|
|
peer->v_holdtime = peer->bgp->default_holdtime;
|
2015-05-20 02:40:37 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-10-20 16:49:58 +02:00
|
|
|
/* Reset DelayOpenTime */
|
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
|
|
|
|
peer->v_delayopen = peer->delayopen;
|
|
|
|
else
|
|
|
|
peer->v_delayopen = peer->bgp->default_delayopen;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
peer->update_time = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
|
|
|
|
&& !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
|
|
|
|
peer_delete(peer);
|
|
|
|
ret = -1;
|
2015-05-20 02:40:40 +02:00
|
|
|
} else {
|
|
|
|
bgp_peer_conf_if_to_su_update(peer);
|
|
|
|
}
|
2015-05-20 02:40:37 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* BGP peer is stoped by the error. */
|
|
|
|
static int bgp_stop_with_error(struct peer *peer)
|
|
|
|
{
|
|
|
|
/* Double start timer. */
|
|
|
|
peer->v_start *= 2;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Overflow check. */
|
|
|
|
if (peer->v_start >= (60 * 2))
|
|
|
|
peer->v_start = (60 * 2);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
bgpd: Do not delete BGP dynamic peers if graceful restart kicks in
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
*donatas-pc(192.168.10.17) 4 65002 8 12 0 0 0 00:01:35 2 14 N/A
```
Before shutting down 192.168.10.17:
```
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Last update: Sat Jan 15 21:45:47 2022
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (Older Path)
Last update: Sat Jan 15 21:25:19 2022
```
After 192.168.10.17 is down:
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
donatas-pc(192.168.10.17) 4 65002 5 9 0 0 0 00:00:12 Active 0 N/A
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Community: llgr-stale
Last update: Sat Jan 15 21:49:01 2022
Time until Long-lived stale route deleted: 16
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Sat Jan 15 21:25:19 2022
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
2022-01-15 22:16:15 +01:00
|
|
|
if (peer_dynamic_neighbor_no_nsf(peer)) {
|
2015-05-20 03:03:47 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2022-01-15 22:44:26 +01:00
|
|
|
zlog_debug("%s (dynamic neighbor) deleted (%s)",
|
|
|
|
peer->host, __func__);
|
2015-05-20 03:03:47 +02:00
|
|
|
peer_delete(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
return (bgp_stop(peer));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2013-07-30 20:14:25 +02:00
|
|
|
|
|
|
|
/* something went wrong, send notify and tear down */
|
2018-03-27 21:13:34 +02:00
|
|
|
static int bgp_stop_with_notify(struct peer *peer, uint8_t code,
|
|
|
|
uint8_t sub_code)
|
2013-07-30 20:14:25 +02:00
|
|
|
{
|
|
|
|
/* Send notify to remote peer */
|
|
|
|
bgp_notify_send(peer, code, sub_code);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
bgpd: Do not delete BGP dynamic peers if graceful restart kicks in
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
*donatas-pc(192.168.10.17) 4 65002 8 12 0 0 0 00:01:35 2 14 N/A
```
Before shutting down 192.168.10.17:
```
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Last update: Sat Jan 15 21:45:47 2022
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (Older Path)
Last update: Sat Jan 15 21:25:19 2022
```
After 192.168.10.17 is down:
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
donatas-pc(192.168.10.17) 4 65002 5 9 0 0 0 00:00:12 Active 0 N/A
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Community: llgr-stale
Last update: Sat Jan 15 21:49:01 2022
Time until Long-lived stale route deleted: 16
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Sat Jan 15 21:25:19 2022
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
2022-01-15 22:16:15 +01:00
|
|
|
if (peer_dynamic_neighbor_no_nsf(peer)) {
|
2015-05-20 03:03:47 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2022-01-15 22:44:26 +01:00
|
|
|
zlog_debug("%s (dynamic neighbor) deleted (%s)",
|
|
|
|
peer->host, __func__);
|
2015-05-20 03:03:47 +02:00
|
|
|
peer_delete(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-30 20:14:25 +02:00
|
|
|
/* Clear start timer value to default. */
|
|
|
|
peer->v_start = BGP_INIT_START_TIMER;
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
return (bgp_stop(peer));
|
2013-07-30 20:14:25 +02:00
|
|
|
}
|
|
|
|
|
2017-03-24 20:05:56 +01:00
|
|
|
/**
|
|
|
|
* Determines whether a TCP session has successfully established for a peer and
|
|
|
|
* events as appropriate.
|
|
|
|
*
|
|
|
|
* This function is called when setting up a new session. After connect() is
|
2017-09-25 04:18:15 +02:00
|
|
|
* called on the peer's socket (in bgp_start()), the fd is passed to poll()
|
|
|
|
* to wait for connection success or failure. When poll() returns, this
|
2017-03-24 20:05:56 +01:00
|
|
|
* function is called to evaluate the result.
|
2017-09-25 04:18:15 +02:00
|
|
|
*
|
|
|
|
* Due to differences in behavior of poll() on Linux and BSD - specifically,
|
|
|
|
* the value of .revents in the case of a closed connection - this function is
|
|
|
|
* scheduled both for a read and a write event. The write event is triggered
|
|
|
|
* when the connection is established. A read event is triggered when the
|
|
|
|
* connection is closed. Thus we need to cancel whichever one did not occur.
|
2017-03-24 20:05:56 +01:00
|
|
|
*/
|
|
|
|
static int bgp_connect_check(struct thread *thread)
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
socklen_t slen;
|
|
|
|
int ret;
|
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
2017-05-02 02:37:45 +02:00
|
|
|
assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
|
|
|
|
assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
|
|
|
|
assert(!peer->t_read);
|
|
|
|
assert(!peer->t_write);
|
2017-03-24 20:05:56 +01:00
|
|
|
|
2017-09-25 04:18:15 +02:00
|
|
|
THREAD_OFF(peer->t_connect_check_r);
|
|
|
|
THREAD_OFF(peer->t_connect_check_w);
|
2017-04-07 01:45:57 +02:00
|
|
|
|
2017-03-24 20:05:56 +01:00
|
|
|
/* Check file descriptor. */
|
|
|
|
slen = sizeof(status);
|
|
|
|
ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *)&status,
|
|
|
|
&slen);
|
|
|
|
|
|
|
|
/* If getsockopt is fail, this is fatal error. */
|
|
|
|
if (ret < 0) {
|
2019-08-21 05:16:20 +02:00
|
|
|
zlog_err("can't get sockopt for nonblocking connect: %d(%s)",
|
2018-05-11 13:34:24 +02:00
|
|
|
errno, safe_strerror(errno));
|
2017-03-24 20:05:56 +01:00
|
|
|
BGP_EVENT_ADD(peer, TCP_fatal_error);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* When status is 0 then TCP connection is established. */
|
|
|
|
if (status == 0) {
|
2020-10-20 16:49:58 +02:00
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN))
|
|
|
|
BGP_EVENT_ADD(peer, TCP_connection_open_w_delay);
|
|
|
|
else
|
|
|
|
BGP_EVENT_ADD(peer, TCP_connection_open);
|
2017-03-24 20:05:56 +01:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2018-05-11 13:34:24 +02:00
|
|
|
zlog_debug("%s [Event] Connect failed %d(%s)",
|
|
|
|
peer->host, status, safe_strerror(status));
|
2017-03-24 20:05:56 +01:00
|
|
|
BGP_EVENT_ADD(peer, TCP_connection_open_failed);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2013-07-30 20:14:25 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* TCP connection open. Next we send open message to remote peer. And
|
|
|
|
add read thread for reading open message. */
|
|
|
|
static int bgp_connect_success(struct peer *peer)
|
|
|
|
{
|
2004-05-01 10:44:08 +02:00
|
|
|
if (peer->fd < 0) {
|
2018-09-13 20:23:42 +02:00
|
|
|
flog_err(EC_BGP_CONNECT,
|
2018-09-13 21:38:57 +02:00
|
|
|
"bgp_connect_success peer's fd is negative value %d",
|
|
|
|
peer->fd);
|
2015-05-20 02:40:37 +02:00
|
|
|
bgp_stop(peer);
|
2002-12-13 21:15:29 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
if (bgp_getsockname(peer) < 0) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
2018-08-06 18:36:50 +02:00
|
|
|
"%s: bgp_getsockname(): failed for peer %s, fd %d",
|
2020-03-05 19:17:54 +01:00
|
|
|
__func__, peer->host, peer->fd);
|
2020-03-15 13:19:11 +01:00
|
|
|
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
|
|
|
|
bgp_fsm_error_subcode(peer->status));
|
2017-05-02 02:37:45 +02:00
|
|
|
bgp_writes_on(peer);
|
2015-05-20 02:40:37 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-05-02 02:37:45 +02:00
|
|
|
bgp_reads_on(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer)) {
|
2005-02-01 21:13:16 +01:00
|
|
|
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
|
2021-03-10 01:50:42 +01:00
|
|
|
zlog_debug("%s open active, local address %pSU",
|
|
|
|
peer->host, peer->su_local);
|
2005-02-01 21:13:16 +01:00
|
|
|
else
|
|
|
|
zlog_debug("%s passive open", peer->host);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-10-20 16:49:58 +02:00
|
|
|
/* Send an open message */
|
2015-05-20 02:40:37 +02:00
|
|
|
bgp_open_send(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-20 16:49:58 +02:00
|
|
|
/* TCP connection open with RFC 4271 optional session attribute DelayOpen flag
|
|
|
|
* set.
|
|
|
|
*/
|
|
|
|
static int bgp_connect_success_w_delayopen(struct peer *peer)
|
|
|
|
{
|
|
|
|
if (peer->fd < 0) {
|
|
|
|
flog_err(EC_BGP_CONNECT, "%s: peer's fd is negative value %d",
|
|
|
|
__func__, peer->fd);
|
|
|
|
bgp_stop(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bgp_getsockname(peer) < 0) {
|
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
|
|
|
"%s: bgp_getsockname(): failed for peer %s, fd %d",
|
|
|
|
__func__, peer->host, peer->fd);
|
|
|
|
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
|
|
|
|
bgp_fsm_error_subcode(peer->status));
|
|
|
|
bgp_writes_on(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bgp_reads_on(peer);
|
|
|
|
|
|
|
|
if (bgp_debug_neighbor_events(peer)) {
|
|
|
|
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
|
2021-03-10 01:50:42 +01:00
|
|
|
zlog_debug("%s open active, local address %pSU",
|
|
|
|
peer->host, peer->su_local);
|
2020-10-20 16:49:58 +02:00
|
|
|
else
|
|
|
|
zlog_debug("%s passive open", peer->host);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set the DelayOpenTime to the inital value */
|
|
|
|
peer->v_delayopen = peer->delayopen;
|
|
|
|
|
|
|
|
/* Start the DelayOpenTimer if it is not already running */
|
|
|
|
if (!peer->t_delayopen)
|
|
|
|
BGP_TIMER_ON(peer->t_delayopen, bgp_delayopen_timer,
|
|
|
|
peer->v_delayopen);
|
|
|
|
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] BGP OPEN message delayed for %d seconds",
|
|
|
|
peer->host, peer->delayopen);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* TCP connect fail */
|
|
|
|
static int bgp_connect_fail(struct peer *peer)
|
|
|
|
{
|
bgpd: Do not delete BGP dynamic peers if graceful restart kicks in
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
*donatas-pc(192.168.10.17) 4 65002 8 12 0 0 0 00:01:35 2 14 N/A
```
Before shutting down 192.168.10.17:
```
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Last update: Sat Jan 15 21:45:47 2022
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (Older Path)
Last update: Sat Jan 15 21:25:19 2022
```
After 192.168.10.17 is down:
```
~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17
donatas-pc(192.168.10.17) 4 65002 5 9 0 0 0 00:00:12 Active 0 N/A
~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32'
BGP routing table entry for 100.100.100.100/32, version 7
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
home-spine1.donatas.net(192.168.0.2)
65002, (stale)
192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0)
Origin incomplete, valid, external
Community: llgr-stale
Last update: Sat Jan 15 21:49:01 2022
Time until Long-lived stale route deleted: 16
65001
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Sat Jan 15 21:25:19 2022
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
2022-01-15 22:16:15 +01:00
|
|
|
if (peer_dynamic_neighbor_no_nsf(peer)) {
|
2015-05-20 03:03:47 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2022-01-15 22:44:26 +01:00
|
|
|
zlog_debug("%s (dynamic neighbor) deleted (%s)",
|
|
|
|
peer->host, __func__);
|
2015-05-20 03:03:47 +02:00
|
|
|
peer_delete(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-12-17 15:46:30 +01:00
|
|
|
/*
|
|
|
|
* If we are doing nht for a peer that ls v6 LL based
|
|
|
|
* massage the event system to make things happy
|
|
|
|
*/
|
|
|
|
bgp_nht_interface_events(peer);
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
return (bgp_stop(peer));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is the first starting point of all BGP connection. It
|
2020-10-20 16:49:58 +02:00
|
|
|
* try to connect to remote peer with non-blocking IO.
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
int bgp_start(struct peer *peer)
|
|
|
|
{
|
|
|
|
int status;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:40:40 +02:00
|
|
|
bgp_peer_conf_if_to_su_update(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-10-21 07:01:49 +02:00
|
|
|
if (peer->su.sa.sa_family == AF_UNSPEC) {
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug(
|
|
|
|
"%s [FSM] Unable to get neighbor's IP address, waiting...",
|
|
|
|
peer->host);
|
bgpd: Add a new command to only show failed peerings
In a data center, having 32-128 peers is not uncommon. In such a situation, to find a
peer that has failed and why is several commands. This hinders both the automatability of
failure detection and the ease/speed with which the reason can be found. To simplify this
process of catching a failure and its cause quicker, this patch does the following:
1. Created a new function, bgp_show_failed_summary to display the
failed summary output for JSON and vty
2. Created a new function to display the reset code/subcode. This is now used in the
failed summary code and in the show neighbors code
3. Added a new variable failedPeers in all the JSON outputs, including the vanilla
"show bgp summary" family. This lists the failed session count.
4. Display peer, dropped count, estd count, uptime and the reason for failure as the
output of "show bgp summary failed" family of commands
5. Added three resset codes for the case where we're waiting for NHT, waiting for peer
IPv6 addr, waiting for VRF to init.
This also counts the case where only one peer has advertised an AFI/SAFI.
The new command has the optional keyword "failed" added to the classical summary command.
The changes affect only one existing output, that of "show [ip] bgp neighbors <nbr>". As
we track the lack of NHT resolution for a peer or the lack of knowing a peer IPv6 addr,
the output of that command will show a "waiting for NHT" etc. as the last reset reason.
This patch includes update to the documentation too.
Signed-off-by: Dinesh G Dutt <5016467+ddutt@users.noreply.github.com>
2019-08-31 18:24:49 +02:00
|
|
|
peer->last_reset = PEER_DOWN_NBR_ADDR;
|
2015-10-21 07:01:49 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
if (BGP_PEER_START_SUPPRESSED(peer)) {
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2018-09-13 20:23:42 +02:00
|
|
|
flog_err(EC_BGP_FSM,
|
2020-03-27 12:35:23 +01:00
|
|
|
"%s [FSM] Trying to start suppressed peer - this is never supposed to happen!",
|
2018-09-13 21:38:57 +02:00
|
|
|
peer->host);
|
2020-02-14 22:21:55 +01:00
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
|
|
|
|
peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
|
2020-08-14 10:23:34 +02:00
|
|
|
else if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN))
|
|
|
|
peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
|
2020-02-14 22:21:55 +01:00
|
|
|
else if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
|
|
|
|
peer->last_reset = PEER_DOWN_PFX_COUNT;
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2006-07-02 13:01:50 +02:00
|
|
|
/* Scrub some information that might be left over from a previous,
|
|
|
|
* session
|
|
|
|
*/
|
|
|
|
/* Connection information. */
|
|
|
|
if (peer->su_local) {
|
|
|
|
sockunion_free(peer->su_local);
|
|
|
|
peer->su_local = NULL;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2006-07-02 13:01:50 +02:00
|
|
|
if (peer->su_remote) {
|
|
|
|
sockunion_free(peer->su_remote);
|
|
|
|
peer->su_remote = NULL;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2006-07-02 13:01:50 +02:00
|
|
|
/* Clear remote router-id. */
|
2020-02-06 07:49:02 +01:00
|
|
|
peer->remote_id.s_addr = INADDR_ANY;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2006-07-02 13:01:50 +02:00
|
|
|
/* Clear peer capability flag. */
|
|
|
|
peer->cap = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* If the peer is passive mode, force to move to Active mode. */
|
|
|
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
|
|
|
|
BGP_EVENT_ADD(peer, TCP_connection_open_failed);
|
|
|
|
return 0;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-09-03 16:36:40 +02:00
|
|
|
if (peer->bgp->vrf_id == VRF_UNKNOWN) {
|
2017-12-20 12:37:18 +01:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 20:23:42 +02:00
|
|
|
EC_BGP_FSM,
|
2017-12-20 12:37:18 +01:00
|
|
|
"%s [FSM] In a VRF that is not initialised yet",
|
|
|
|
peer->host);
|
bgpd: Add a new command to only show failed peerings
In a data center, having 32-128 peers is not uncommon. In such a situation, to find a
peer that has failed and why is several commands. This hinders both the automatability of
failure detection and the ease/speed with which the reason can be found. To simplify this
process of catching a failure and its cause quicker, this patch does the following:
1. Created a new function, bgp_show_failed_summary to display the
failed summary output for JSON and vty
2. Created a new function to display the reset code/subcode. This is now used in the
failed summary code and in the show neighbors code
3. Added a new variable failedPeers in all the JSON outputs, including the vanilla
"show bgp summary" family. This lists the failed session count.
4. Display peer, dropped count, estd count, uptime and the reason for failure as the
output of "show bgp summary failed" family of commands
5. Added three resset codes for the case where we're waiting for NHT, waiting for peer
IPv6 addr, waiting for VRF to init.
This also counts the case where only one peer has advertised an AFI/SAFI.
The new command has the optional keyword "failed" added to the classical summary command.
The changes affect only one existing output, that of "show [ip] bgp neighbors <nbr>". As
we track the lack of NHT resolution for a peer or the lack of knowing a peer IPv6 addr,
the output of that command will show a "waiting for NHT" etc. as the last reset reason.
This patch includes update to the documentation too.
Signed-off-by: Dinesh G Dutt <5016467+ddutt@users.noreply.github.com>
2019-08-31 18:24:49 +02:00
|
|
|
peer->last_reset = PEER_DOWN_VRF_UNINIT;
|
2017-12-20 12:37:18 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-08-19 07:12:06 +02:00
|
|
|
/* Register peer for NHT. If next hop is already resolved, proceed
|
|
|
|
* with connection setup, else wait.
|
|
|
|
*/
|
|
|
|
if (!bgp_peer_reg_with_nht(peer)) {
|
2018-05-11 13:40:55 +02:00
|
|
|
if (bgp_zebra_num_connects()) {
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Waiting for NHT",
|
|
|
|
peer->host);
|
bgpd: Add a new command to only show failed peerings
In a data center, having 32-128 peers is not uncommon. In such a situation, to find a
peer that has failed and why is several commands. This hinders both the automatability of
failure detection and the ease/speed with which the reason can be found. To simplify this
process of catching a failure and its cause quicker, this patch does the following:
1. Created a new function, bgp_show_failed_summary to display the
failed summary output for JSON and vty
2. Created a new function to display the reset code/subcode. This is now used in the
failed summary code and in the show neighbors code
3. Added a new variable failedPeers in all the JSON outputs, including the vanilla
"show bgp summary" family. This lists the failed session count.
4. Display peer, dropped count, estd count, uptime and the reason for failure as the
output of "show bgp summary failed" family of commands
5. Added three resset codes for the case where we're waiting for NHT, waiting for peer
IPv6 addr, waiting for VRF to init.
This also counts the case where only one peer has advertised an AFI/SAFI.
The new command has the optional keyword "failed" added to the classical summary command.
The changes affect only one existing output, that of "show [ip] bgp neighbors <nbr>". As
we track the lack of NHT resolution for a peer or the lack of knowing a peer IPv6 addr,
the output of that command will show a "waiting for NHT" etc. as the last reset reason.
This patch includes update to the documentation too.
Signed-off-by: Dinesh G Dutt <5016467+ddutt@users.noreply.github.com>
2019-08-31 18:24:49 +02:00
|
|
|
peer->last_reset = PEER_DOWN_WAITING_NHT;
|
2018-05-11 13:40:55 +02:00
|
|
|
BGP_EVENT_ADD(peer, TCP_connection_open_failed);
|
|
|
|
return 0;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-05-02 02:37:45 +02:00
|
|
|
assert(!peer->t_write);
|
|
|
|
assert(!peer->t_read);
|
|
|
|
assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
|
|
|
|
assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
|
2002-12-13 21:15:29 +01:00
|
|
|
status = bgp_connect(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-01 10:44:08 +02:00
|
|
|
switch (status) {
|
2002-12-13 21:15:29 +01:00
|
|
|
case connect_error:
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Connect error", peer->host);
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_EVENT_ADD(peer, TCP_connection_open_failed);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
case connect_success:
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2015-05-20 02:40:37 +02:00
|
|
|
zlog_debug(
|
2015-05-20 03:04:19 +02:00
|
|
|
"%s [FSM] Connect immediately success, fd %d",
|
|
|
|
peer->host, peer->fd);
|
2020-10-20 16:49:58 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_EVENT_ADD(peer, TCP_connection_open);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
case connect_in_progress:
|
|
|
|
/* To check nonblocking connect, we wait until socket is
|
|
|
|
readable or writable. */
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2015-05-20 02:40:37 +02:00
|
|
|
zlog_debug(
|
2004-05-01 10:44:08 +02:00
|
|
|
"%s [FSM] Non blocking connect waiting result, fd %d",
|
2015-05-20 03:04:19 +02:00
|
|
|
peer->host, peer->fd);
|
2004-05-01 10:44:08 +02:00
|
|
|
if (peer->fd < 0) {
|
2018-09-13 20:23:42 +02:00
|
|
|
flog_err(EC_BGP_FSM,
|
2018-09-13 21:38:57 +02:00
|
|
|
"bgp_start peer's fd is negative value %d",
|
|
|
|
peer->fd);
|
2002-12-13 21:15:29 +01:00
|
|
|
return -1;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-09-08 17:51:12 +02:00
|
|
|
/*
|
2017-09-25 04:18:15 +02:00
|
|
|
* - when the socket becomes ready, poll() will signify POLLOUT
|
|
|
|
* - if it fails to connect, poll() will signify POLLHUP
|
|
|
|
* - POLLHUP is handled as a 'read' event by thread.c
|
|
|
|
*
|
|
|
|
* therefore, we schedule both a read and a write event with
|
|
|
|
* bgp_connect_check() as the handler for each and cancel the
|
|
|
|
* unused event in that function.
|
2017-09-08 17:51:12 +02:00
|
|
|
*/
|
2017-05-02 02:37:45 +02:00
|
|
|
thread_add_read(bm->master, bgp_connect_check, peer, peer->fd,
|
2017-09-25 04:18:15 +02:00
|
|
|
&peer->t_connect_check_r);
|
|
|
|
thread_add_write(bm->master, bgp_connect_check, peer, peer->fd,
|
|
|
|
&peer->t_connect_check_w);
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Connect retry timer is expired when the peer status is Connect. */
|
|
|
|
static int bgp_reconnect(struct peer *peer)
|
|
|
|
{
|
2015-05-20 03:04:17 +02:00
|
|
|
if (bgp_stop(peer) < 0)
|
|
|
|
return -1;
|
2015-05-20 02:40:37 +02:00
|
|
|
|
2019-10-26 18:40:33 +02:00
|
|
|
/* Send graceful restart capabilty */
|
2020-01-31 19:04:00 +01:00
|
|
|
BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
|
|
|
|
peer->bgp->peer);
|
2019-10-26 18:40:33 +02:00
|
|
|
|
2015-05-20 03:04:17 +02:00
|
|
|
bgp_start(peer);
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int bgp_fsm_open(struct peer *peer)
|
|
|
|
{
|
2020-10-20 16:49:58 +02:00
|
|
|
/* If DelayOpen is active, we may still need to send an open message */
|
|
|
|
if ((peer->status == Connect) || (peer->status == Active))
|
|
|
|
bgp_open_send(peer);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Send keepalive and make keepalive timer */
|
|
|
|
bgp_keepalive_send(peer);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-07-30 20:14:25 +02:00
|
|
|
/* FSM error, unexpected event. This is error of BGP connection. So cut the
|
|
|
|
peer and change to Idle status. */
|
|
|
|
static int bgp_fsm_event_error(struct peer *peer)
|
|
|
|
{
|
2018-09-13 21:38:57 +02:00
|
|
|
flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s",
|
|
|
|
peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
|
2013-07-30 20:14:25 +02:00
|
|
|
|
2020-03-15 13:19:11 +01:00
|
|
|
return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR,
|
|
|
|
bgp_fsm_error_subcode(peer->status));
|
2013-07-30 20:14:25 +02:00
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Hold timer expire. This is error of BGP connection. So cut the
|
|
|
|
peer and change to Idle status. */
|
|
|
|
static int bgp_fsm_holdtime_expire(struct peer *peer)
|
|
|
|
{
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s [FSM] Hold timer expire", peer->host);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2013-07-30 20:14:25 +02:00
|
|
|
return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-10-20 16:49:58 +02:00
|
|
|
/* RFC 4271 DelayOpenTimer_Expires event */
|
|
|
|
static int bgp_fsm_delayopen_timer_expire(struct peer *peer)
|
|
|
|
{
|
|
|
|
/* Stop the DelayOpenTimer */
|
|
|
|
BGP_TIMER_OFF(peer->t_delayopen);
|
|
|
|
|
|
|
|
/* Send open message to peer */
|
|
|
|
bgp_open_send(peer);
|
|
|
|
|
|
|
|
/* Set the HoldTimer to a large value (4 minutes) */
|
|
|
|
peer->v_holdtime = 245;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-10-23 20:14:51 +02:00
|
|
|
/* Start the selection deferral timer thread for the specified AFI, SAFI */
|
|
|
|
static int bgp_start_deferral_timer(struct bgp *bgp, afi_t afi, safi_t safi,
|
2020-01-31 19:04:00 +01:00
|
|
|
struct graceful_restart_info *gr_info)
|
2019-10-23 20:14:51 +02:00
|
|
|
{
|
|
|
|
struct afi_safi_info *thread_info;
|
|
|
|
|
|
|
|
/* If the deferral timer is active, then increment eor count */
|
|
|
|
if (gr_info->t_select_deferral) {
|
|
|
|
gr_info->eor_required++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start the deferral timer when the first peer enabled for the graceful
|
|
|
|
* restart is established
|
|
|
|
*/
|
|
|
|
if (gr_info->eor_required == 0) {
|
|
|
|
thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
|
|
|
|
|
|
|
|
thread_info->afi = afi;
|
|
|
|
thread_info->safi = safi;
|
|
|
|
thread_info->bgp = bgp;
|
|
|
|
|
2020-01-31 15:19:24 +01:00
|
|
|
thread_add_timer(bm->master, bgp_graceful_deferral_timer_expire,
|
|
|
|
thread_info, bgp->select_defer_time,
|
|
|
|
&gr_info->t_select_deferral);
|
2019-10-23 20:14:51 +02:00
|
|
|
}
|
|
|
|
gr_info->eor_required++;
|
2019-10-26 18:40:33 +02:00
|
|
|
/* Send message to RIB indicating route update pending */
|
|
|
|
if (gr_info->af_enabled[afi][safi] == false) {
|
|
|
|
gr_info->af_enabled[afi][safi] = true;
|
|
|
|
/* Send message to RIB */
|
|
|
|
bgp_zebra_update(afi, safi, bgp->vrf_id,
|
|
|
|
ZEBRA_CLIENT_ROUTE_UPDATE_PENDING);
|
|
|
|
}
|
2019-10-23 20:14:51 +02:00
|
|
|
if (BGP_DEBUG(update, UPDATE_OUT))
|
|
|
|
zlog_debug("Started the deferral timer for %s eor_required %d",
|
2020-01-31 19:04:00 +01:00
|
|
|
get_afi_safi_str(afi, safi, false),
|
|
|
|
gr_info->eor_required);
|
2019-10-23 20:14:51 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the graceful restart information for the specified AFI, SAFI */
|
|
|
|
static int bgp_update_gr_info(struct peer *peer, afi_t afi, safi_t safi)
|
|
|
|
{
|
|
|
|
struct graceful_restart_info *gr_info;
|
|
|
|
struct bgp *bgp = peer->bgp;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if ((afi < AFI_IP) || (afi >= AFI_MAX)) {
|
|
|
|
if (BGP_DEBUG(update, UPDATE_OUT))
|
|
|
|
zlog_debug("%s : invalid afi %d", __func__, afi);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((safi < SAFI_UNICAST) || (safi > SAFI_MPLS_VPN)) {
|
|
|
|
if (BGP_DEBUG(update, UPDATE_OUT))
|
|
|
|
zlog_debug("%s : invalid safi %d", __func__, safi);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Restarting router */
|
2020-01-31 19:04:00 +01:00
|
|
|
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
|
|
|
|
&& BGP_PEER_RESTARTING_MODE(peer)) {
|
2019-10-23 20:14:51 +02:00
|
|
|
/* Check if the forwarding state is preserved */
|
2020-02-06 15:37:20 +01:00
|
|
|
if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD)) {
|
2019-10-23 20:14:51 +02:00
|
|
|
gr_info = &(bgp->gr_info[afi][safi]);
|
|
|
|
ret = bgp_start_deferral_timer(bgp, afi, safi, gr_info);
|
|
|
|
}
|
|
|
|
}
|
2019-11-25 16:18:15 +01:00
|
|
|
return ret;
|
2019-10-23 20:14:51 +02:00
|
|
|
}
|
|
|
|
|
2017-04-06 03:09:33 +02:00
|
|
|
/**
|
|
|
|
* Transition to Established state.
|
|
|
|
*
|
|
|
|
* Convert peer from stub to full fledged peer, set some timers, and generate
|
|
|
|
* initial updates.
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
static int bgp_establish(struct peer *peer)
|
|
|
|
{
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
2015-05-20 02:40:37 +02:00
|
|
|
int nsf_af_count = 0;
|
|
|
|
int ret = 0;
|
2016-11-15 16:16:52 +01:00
|
|
|
struct peer *other;
|
2019-10-23 20:14:51 +02:00
|
|
|
int status;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-02-02 15:40:33 +01:00
|
|
|
other = peer->doppelganger;
|
|
|
|
peer = peer_xfer_conn(peer);
|
|
|
|
if (!peer) {
|
2018-09-13 20:23:42 +02:00
|
|
|
flog_err(EC_BGP_CONNECT, "%%Neighbor failed in xfer_conn");
|
2005-02-02 15:40:33 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
if (other == peer)
|
2017-07-22 14:52:33 +02:00
|
|
|
ret = 1; /* bgp_establish specific code when xfer_conn
|
|
|
|
happens. */
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Reset capability open status flag. */
|
|
|
|
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
|
|
|
|
SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Clear start timer value to default. */
|
|
|
|
peer->v_start = BGP_INIT_START_TIMER;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Increment established count. */
|
|
|
|
peer->established++;
|
|
|
|
bgp_fsm_change_status(peer, Established);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-08-13 02:32:49 +02:00
|
|
|
/* bgp log-neighbor-changes of neighbor Up */
|
2020-02-06 15:37:20 +01:00
|
|
|
if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
|
2016-11-15 16:16:52 +01:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
|
2020-02-06 15:37:20 +01:00
|
|
|
zlog_info(
|
|
|
|
"%%ADJCHANGE: neighbor %s(%s) in vrf %s Up", peer->host,
|
|
|
|
(peer->hostname) ? peer->hostname : "Unknown",
|
|
|
|
vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
|
|
|
|
: VRF_DEFAULT_NAME)
|
|
|
|
: "");
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2015-05-20 03:03:47 +02:00
|
|
|
/* assign update-group/subgroup */
|
|
|
|
update_group_adjust_peer_afs(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-02-02 15:40:33 +01:00
|
|
|
/* graceful restart */
|
|
|
|
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
|
2019-10-23 20:14:51 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer)) {
|
|
|
|
if (BGP_PEER_RESTARTING_MODE(peer))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("peer %s BGP_RESTARTING_MODE", peer->host);
|
2019-10-23 20:14:51 +02:00
|
|
|
else if (BGP_PEER_HELPER_MODE(peer))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("peer %s BGP_HELPER_MODE", peer->host);
|
2019-10-23 20:14:51 +02:00
|
|
|
}
|
2022-01-12 21:43:52 +01:00
|
|
|
|
|
|
|
FOREACH_AFI_SAFI_NSF (afi, safi) {
|
|
|
|
if (peer->afc_nego[afi][safi] &&
|
|
|
|
CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV) &&
|
|
|
|
CHECK_FLAG(peer->af_cap[afi][safi],
|
|
|
|
PEER_CAP_RESTART_AF_RCV)) {
|
|
|
|
if (peer->nsf[afi][safi] &&
|
|
|
|
!CHECK_FLAG(peer->af_cap[afi][safi],
|
|
|
|
PEER_CAP_RESTART_AF_PRESERVE_RCV))
|
|
|
|
bgp_clear_stale_route(peer, afi, safi);
|
|
|
|
|
|
|
|
peer->nsf[afi][safi] = 1;
|
|
|
|
nsf_af_count++;
|
|
|
|
} else {
|
|
|
|
if (peer->nsf[afi][safi])
|
|
|
|
bgp_clear_stale_route(peer, afi, safi);
|
|
|
|
peer->nsf[afi][safi] = 0;
|
|
|
|
}
|
|
|
|
/* Update the graceful restart information */
|
|
|
|
if (peer->afc_nego[afi][safi]) {
|
|
|
|
if (!BGP_SELECT_DEFER_DISABLE(peer->bgp)) {
|
|
|
|
status = bgp_update_gr_info(peer, afi, safi);
|
|
|
|
if (status < 0)
|
|
|
|
zlog_err(
|
|
|
|
"Error in updating graceful restart for %s",
|
|
|
|
get_afi_safi_str(afi, safi,
|
|
|
|
false));
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2022-01-12 21:43:52 +01:00
|
|
|
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer) &&
|
|
|
|
BGP_PEER_RESTARTING_MODE(peer) &&
|
|
|
|
CHECK_FLAG(peer->bgp->flags,
|
|
|
|
BGP_FLAG_GR_PRESERVE_FWD))
|
|
|
|
peer->bgp->gr_info[afi][safi]
|
|
|
|
.eor_required++;
|
2019-10-23 20:14:51 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2022-01-12 21:43:52 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-06-16 14:20:41 +02:00
|
|
|
if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
|
|
|
|
if ((bgp_peer_gr_mode_get(peer) == PEER_GR)
|
|
|
|
|| ((bgp_peer_gr_mode_get(peer) == PEER_GLOBAL_INHERIT)
|
|
|
|
&& (bgp_global_gr_mode_get(peer->bgp) == GLOBAL_GR))) {
|
|
|
|
FOREACH_AFI_SAFI (afi, safi)
|
|
|
|
/* Send route processing complete
|
|
|
|
message to RIB */
|
|
|
|
bgp_zebra_update(
|
|
|
|
afi, safi, peer->bgp->vrf_id,
|
|
|
|
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Peer sends R-bit. In this case, we need to send
|
|
|
|
* ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE to Zebra. */
|
|
|
|
if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV)) {
|
|
|
|
FOREACH_AFI_SAFI (afi, safi)
|
|
|
|
/* Send route processing complete
|
|
|
|
message to RIB */
|
|
|
|
bgp_zebra_update(
|
|
|
|
afi, safi, peer->bgp->vrf_id,
|
|
|
|
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-23 07:40:22 +02:00
|
|
|
peer->nsf_af_count = nsf_af_count;
|
|
|
|
|
2005-02-02 15:40:33 +01:00
|
|
|
if (nsf_af_count)
|
|
|
|
SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
|
2017-07-17 14:03:14 +02:00
|
|
|
else {
|
2005-02-02 15:40:33 +01:00
|
|
|
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
|
|
|
|
if (peer->t_gr_stale) {
|
|
|
|
BGP_TIMER_OFF(peer->t_gr_stale);
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2005-02-02 15:40:33 +01:00
|
|
|
zlog_debug(
|
|
|
|
"%s graceful restart stalepath timer stopped",
|
|
|
|
peer->host);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2005-02-02 15:40:33 +01:00
|
|
|
|
2016-06-12 17:32:23 +02:00
|
|
|
if (peer->t_gr_restart) {
|
|
|
|
BGP_TIMER_OFF(peer->t_gr_restart);
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
|
|
|
zlog_debug("%s graceful restart timer stopped",
|
|
|
|
peer->host);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-06-02 03:52:39 +02:00
|
|
|
/* Reset uptime, turn on keepalives, send current table. */
|
|
|
|
if (!peer->v_holdtime)
|
|
|
|
bgp_keepalives_on(peer);
|
|
|
|
|
2010-01-15 14:22:10 +01:00
|
|
|
peer->uptime = bgp_clock();
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Send route-refresh when ORF is enabled */
|
2017-11-21 19:02:06 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
if (CHECK_FLAG(peer->af_cap[afi][safi],
|
|
|
|
PEER_CAP_ORF_PREFIX_SM_ADV)) {
|
2002-12-13 21:15:29 +01:00
|
|
|
if (CHECK_FLAG(peer->af_cap[afi][safi],
|
2017-11-21 19:02:06 +01:00
|
|
|
PEER_CAP_ORF_PREFIX_RM_RCV))
|
2020-10-01 22:08:06 +02:00
|
|
|
bgp_route_refresh_send(
|
|
|
|
peer, afi, safi, ORF_TYPE_PREFIX,
|
|
|
|
REFRESH_IMMEDIATE, 0,
|
|
|
|
BGP_ROUTE_REFRESH_NORMAL);
|
2017-11-21 19:02:06 +01:00
|
|
|
else if (CHECK_FLAG(peer->af_cap[afi][safi],
|
|
|
|
PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
|
2020-10-01 22:08:06 +02:00
|
|
|
bgp_route_refresh_send(
|
|
|
|
peer, afi, safi, ORF_TYPE_PREFIX_OLD,
|
|
|
|
REFRESH_IMMEDIATE, 0,
|
|
|
|
BGP_ROUTE_REFRESH_NORMAL);
|
2017-11-21 19:02:06 +01:00
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* First update is deferred until ORF or ROUTE-REFRESH is received */
|
2017-11-21 19:02:06 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
if (CHECK_FLAG(peer->af_cap[afi][safi],
|
|
|
|
PEER_CAP_ORF_PREFIX_RM_ADV))
|
2002-12-13 21:15:29 +01:00
|
|
|
if (CHECK_FLAG(peer->af_cap[afi][safi],
|
2017-11-21 19:02:06 +01:00
|
|
|
PEER_CAP_ORF_PREFIX_SM_RCV)
|
|
|
|
|| CHECK_FLAG(peer->af_cap[afi][safi],
|
|
|
|
PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
|
|
|
|
SET_FLAG(peer->af_sflags[afi][safi],
|
|
|
|
PEER_STATUS_ORF_WAIT_REFRESH);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:03:47 +02:00
|
|
|
bgp_announce_peer(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
/* Start the route advertisement timer to send updates to the peer - if
|
2017-07-17 14:03:14 +02:00
|
|
|
* BGP
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
* is not in read-only mode. If it is, the timer will be started at the
|
2017-07-17 14:03:14 +02:00
|
|
|
* end
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
* of read-only mode.
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
bgpd: bgpd-mrai.patch
BGP: Event-driven route announcement taking into account min route advertisement interval
ISSUE
BGP starts the routeadv timer (peer->t_routeadv) to expire in 1 sec
when a peer is established. From then on, the timer expires
periodically based on the configured MRAI value (default: 30sec for
EBGP, 5sec for IBGP). At the expiry, the write thread is triggered
that takes the routes from peer's sync FIFO (adj-rib-out) and sends
UPDATEs. This has a few drawbacks:
(1) Delay in new route announcement: Even when the last UPDATE message
was sent a while back, the next route change will necessarily have
to wait for routeadv expiry
(2) CPU usage: The timer is always armed. If the operator chooses to
configure a lower value of MRAI (zero second is a preferred choice
in many deployments) for better convergence, it leads to high CPU
usage for BGP process, even at the times of no network churn.
PATCH
Make the route advertisement event-driven - When routes are added to
peer's sync FIFO, check if the routeadv timer needs to be adjusted (or
started). Conversely, do not arm the routeadv timer unconditionally.
The patch also addresses route announcements during read-only mode
(update-delay). During read-only mode operation, the routeadv timer
is not started. When BGP comes out of read-only mode and all the
routes are processed, the timer is started for all peers with zero
expiry, so that the UPDATEs can be sent all at once. This leads to
(near-)optimal UPDATE packing.
Finally, the patch makes the "max # packets to write to peer socket at
a time" configurable. Currently it is hard-coded to 10. The command is
at the top router-bgp mode and is called "write-quanta <number>". It
is a useful convergence parameter to tweak.
Signed-off-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
2015-05-20 02:40:37 +02:00
|
|
|
if (!bgp_update_delay_active(peer->bgp)) {
|
2015-05-20 03:03:47 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_routeadv);
|
|
|
|
BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
|
|
|
|
if (bgp_debug_neighbor_events(peer))
|
2015-05-20 02:40:37 +02:00
|
|
|
zlog_debug(
|
2002-12-13 21:15:29 +01:00
|
|
|
"[Event] Deleting stub connection for peer %s",
|
2015-05-20 02:40:37 +02:00
|
|
|
peer->host);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (peer->doppelganger->status > Active)
|
|
|
|
bgp_notify_send(peer->doppelganger, BGP_NOTIFY_CEASE,
|
|
|
|
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
|
2017-07-17 14:03:14 +02:00
|
|
|
else
|
2002-12-13 21:15:29 +01:00
|
|
|
peer_delete(peer->doppelganger);
|
|
|
|
}
|
|
|
|
|
2018-10-08 02:34:31 +02:00
|
|
|
/*
|
|
|
|
* If we are replacing the old peer for a doppelganger
|
|
|
|
* then switch it around in the bgp->peerhash
|
|
|
|
* the doppelgangers su and this peer's su are the same
|
|
|
|
* so the hash_release is the same for either.
|
|
|
|
*/
|
|
|
|
hash_release(peer->bgp->peerhash, peer);
|
|
|
|
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
|
|
|
|
|
2021-02-26 20:50:51 +01:00
|
|
|
/* Start BFD peer if not already running. */
|
|
|
|
if (peer->bfd_config)
|
|
|
|
bgp_peer_bfd_update_source(peer);
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Keepalive packet is received. */
|
|
|
|
static int bgp_fsm_keepalive(struct peer *peer)
|
|
|
|
{
|
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update packet is received. */
|
|
|
|
static int bgp_fsm_update(struct peer *peer)
|
|
|
|
{
|
|
|
|
BGP_TIMER_OFF(peer->t_holdtime);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is empty event. */
|
|
|
|
static int bgp_ignore(struct peer *peer)
|
|
|
|
{
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 20:23:42 +02:00
|
|
|
EC_BGP_FSM,
|
2015-05-20 03:04:19 +02:00
|
|
|
"%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
|
2015-05-20 03:04:12 +02:00
|
|
|
peer->host, bgp_event_str[peer->cur_event],
|
2017-06-21 01:56:50 +02:00
|
|
|
lookup_msg(bgp_status_msg, peer->status, NULL),
|
2015-05-20 03:04:12 +02:00
|
|
|
bgp_event_str[peer->last_event],
|
2015-05-20 03:04:19 +02:00
|
|
|
bgp_event_str[peer->last_major_event], peer->fd);
|
2002-12-13 21:15:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2015-05-20 03:04:12 +02:00
|
|
|
/* This is to handle unexpected events.. */
|
|
|
|
static int bgp_fsm_exeption(struct peer *peer)
|
|
|
|
{
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 20:23:42 +02:00
|
|
|
EC_BGP_FSM,
|
2015-05-20 03:04:19 +02:00
|
|
|
"%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
|
2015-05-20 03:04:12 +02:00
|
|
|
peer->host, bgp_event_str[peer->cur_event],
|
2017-06-21 01:56:50 +02:00
|
|
|
lookup_msg(bgp_status_msg, peer->status, NULL),
|
2015-05-20 03:04:12 +02:00
|
|
|
bgp_event_str[peer->last_event],
|
2015-05-20 03:04:19 +02:00
|
|
|
bgp_event_str[peer->last_major_event], peer->fd);
|
2015-05-20 03:04:12 +02:00
|
|
|
return (bgp_stop(peer));
|
|
|
|
}
|
|
|
|
|
2020-09-17 18:38:12 +02:00
|
|
|
void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops)
|
2015-05-20 02:47:21 +02:00
|
|
|
{
|
|
|
|
if (!peer)
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:47:21 +02:00
|
|
|
switch (peer->status) {
|
|
|
|
case Idle:
|
2020-09-17 18:38:12 +02:00
|
|
|
if (has_valid_nexthops)
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_EVENT_ADD(peer, BGP_Start);
|
|
|
|
break;
|
|
|
|
case Connect:
|
2020-09-17 18:38:12 +02:00
|
|
|
if (!has_valid_nexthops) {
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
2015-05-20 03:04:08 +02:00
|
|
|
BGP_EVENT_ADD(peer, TCP_fatal_error);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
break;
|
2015-05-20 02:47:21 +02:00
|
|
|
case Active:
|
2020-09-17 18:38:12 +02:00
|
|
|
if (has_valid_nexthops) {
|
2015-05-20 02:47:21 +02:00
|
|
|
BGP_TIMER_OFF(peer->t_connect);
|
|
|
|
BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
break;
|
2015-05-20 02:47:21 +02:00
|
|
|
case OpenSent:
|
|
|
|
case OpenConfirm:
|
|
|
|
case Established:
|
2020-09-17 18:38:12 +02:00
|
|
|
if (!has_valid_nexthops
|
2021-08-06 17:17:04 +02:00
|
|
|
&& (peer->gtsm_hops == BGP_GTSM_HOPS_CONNECTED
|
|
|
|
|| peer->bgp->fast_convergence))
|
2015-05-20 03:04:08 +02:00
|
|
|
BGP_EVENT_ADD(peer, TCP_fatal_error);
|
2015-05-20 02:47:21 +02:00
|
|
|
case Clearing:
|
|
|
|
case Deleted:
|
2017-07-17 14:03:14 +02:00
|
|
|
default:
|
|
|
|
break;
|
2015-05-20 02:47:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Finite State Machine structure */
|
2009-05-15 19:02:27 +02:00
|
|
|
static const struct {
|
2009-02-09 19:14:16 +01:00
|
|
|
int (*func)(struct peer *);
|
2020-03-20 14:03:08 +01:00
|
|
|
enum bgp_fsm_status next_state;
|
2002-12-13 21:15:29 +01:00
|
|
|
} FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = {
|
|
|
|
{
|
|
|
|
/* Idle state: In Idle state, all events other than BGP_Start is
|
|
|
|
ignored. With BGP_Start event, finite state machine calls
|
|
|
|
bgp_start(). */
|
|
|
|
{bgp_start, Connect}, /* BGP_Start */
|
|
|
|
{bgp_stop, Idle}, /* BGP_Stop */
|
|
|
|
{bgp_stop, Idle}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_stop, Idle}, /* TCP_connection_open_w_delay */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_stop, Idle}, /* TCP_connection_closed */
|
|
|
|
{bgp_ignore, Idle}, /* TCP_connection_open_failed */
|
|
|
|
{bgp_stop, Idle}, /* TCP_fatal_error */
|
|
|
|
{bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
|
|
|
|
{bgp_ignore, Idle}, /* Hold_Timer_expired */
|
|
|
|
{bgp_ignore, Idle}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_ignore, Idle}, /* DelayOpen_timer_expired */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_ignore, Idle}, /* Receive_OPEN_message */
|
|
|
|
{bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
|
|
|
|
{bgp_ignore, Idle}, /* Receive_UPDATE_message */
|
|
|
|
{bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_ignore, Idle}, /* Clearing_Completed */
|
2002-12-13 21:15:29 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Connect */
|
|
|
|
{bgp_ignore, Connect}, /* BGP_Start */
|
|
|
|
{bgp_stop, Idle}, /* BGP_Stop */
|
|
|
|
{bgp_connect_success, OpenSent}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_connect_success_w_delayopen,
|
|
|
|
Connect}, /* TCP_connection_open_w_delay */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_stop, Idle}, /* TCP_connection_closed */
|
|
|
|
{bgp_connect_fail, Active}, /* TCP_connection_open_failed */
|
|
|
|
{bgp_connect_fail, Idle}, /* TCP_fatal_error */
|
|
|
|
{bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_delayopen_timer_expire,
|
|
|
|
OpenSent}, /* DelayOpen_timer_expired */
|
|
|
|
{bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
|
|
|
|
{bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* Clearing_Completed */
|
2002-12-13 21:15:29 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Active, */
|
|
|
|
{bgp_ignore, Active}, /* BGP_Start */
|
|
|
|
{bgp_stop, Idle}, /* BGP_Stop */
|
|
|
|
{bgp_connect_success, OpenSent}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_connect_success_w_delayopen,
|
|
|
|
Active}, /* TCP_connection_open_w_delay */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_stop, Idle}, /* TCP_connection_closed */
|
|
|
|
{bgp_ignore, Active}, /* TCP_connection_open_failed */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* TCP_fatal_error */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_start, Connect}, /* ConnectRetry_timer_expired */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_delayopen_timer_expire,
|
|
|
|
OpenSent}, /* DelayOpen_timer_expired */
|
|
|
|
{bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */
|
|
|
|
{bgp_fsm_exeption, Idle}, /* Clearing_Completed */
|
2002-12-13 21:15:29 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/* OpenSent, */
|
|
|
|
{bgp_ignore, OpenSent}, /* BGP_Start */
|
|
|
|
{bgp_stop, Idle}, /* BGP_Stop */
|
2007-06-22 21:11:14 +02:00
|
|
|
{bgp_stop, Active}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_stop, Active}, /* TCP_connection_closed */
|
2007-06-22 21:11:14 +02:00
|
|
|
{bgp_stop, Active}, /* TCP_connection_open_failed */
|
|
|
|
{bgp_stop, Active}, /* TCP_fatal_error */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */
|
2013-07-30 20:14:25 +02:00
|
|
|
{bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */
|
|
|
|
{bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */
|
2019-12-30 16:11:04 +01:00
|
|
|
{bgp_fsm_event_error, Idle}, /* Receive_NOTIFICATION_message */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* Clearing_Completed */
|
2002-12-13 21:15:29 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/* OpenConfirm, */
|
|
|
|
{bgp_ignore, OpenConfirm}, /* BGP_Start */
|
|
|
|
{bgp_stop, Idle}, /* BGP_Stop */
|
|
|
|
{bgp_stop, Idle}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_stop, Idle}, /* TCP_connection_closed */
|
|
|
|
{bgp_stop, Idle}, /* TCP_connection_open_failed */
|
|
|
|
{bgp_stop, Idle}, /* TCP_fatal_error */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
|
|
|
|
{bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_establish, Established}, /* Receive_KEEPALIVE_message */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */
|
2002-12-13 21:15:29 +01:00
|
|
|
{bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* Clearing_Completed */
|
2002-12-13 21:15:29 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Established, */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_ignore, Established}, /* BGP_Start */
|
|
|
|
{bgp_stop, Clearing}, /* BGP_Stop */
|
|
|
|
{bgp_stop, Clearing}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_stop, Clearing}, /* TCP_connection_closed */
|
2009-07-28 18:50:00 +02:00
|
|
|
{bgp_stop, Clearing}, /* TCP_connection_open_failed */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_stop, Clearing}, /* TCP_fatal_error */
|
2009-07-28 18:50:00 +02:00
|
|
|
{bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
|
2017-01-06 00:13:16 +01:00
|
|
|
{bgp_ignore, Established}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */
|
2017-01-06 00:13:16 +01:00
|
|
|
{bgp_stop, Clearing}, /* Receive_OPEN_message */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_fsm_keepalive,
|
|
|
|
Established}, /* Receive_KEEPALIVE_message */
|
|
|
|
{bgp_fsm_update, Established}, /* Receive_UPDATE_message */
|
|
|
|
{bgp_stop_with_error,
|
|
|
|
Clearing}, /* Receive_NOTIFICATION_message */
|
2015-05-20 03:04:12 +02:00
|
|
|
{bgp_fsm_exeption, Idle}, /* Clearing_Completed */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Clearing, */
|
|
|
|
{bgp_ignore, Clearing}, /* BGP_Start */
|
2009-07-28 18:50:00 +02:00
|
|
|
{bgp_stop, Clearing}, /* BGP_Stop */
|
|
|
|
{bgp_stop, Clearing}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_stop, Clearing}, /* TCP_connection_open_w_delay */
|
2009-07-28 18:50:00 +02:00
|
|
|
{bgp_stop, Clearing}, /* TCP_connection_closed */
|
|
|
|
{bgp_stop, Clearing}, /* TCP_connection_open_failed */
|
|
|
|
{bgp_stop, Clearing}, /* TCP_fatal_error */
|
|
|
|
{bgp_stop, Clearing}, /* ConnectRetry_timer_expired */
|
|
|
|
{bgp_stop, Clearing}, /* Hold_Timer_expired */
|
|
|
|
{bgp_stop, Clearing}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_stop, Clearing}, /* DelayOpen_timer_expired */
|
2009-07-28 18:50:00 +02:00
|
|
|
{bgp_stop, Clearing}, /* Receive_OPEN_message */
|
|
|
|
{bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */
|
|
|
|
{bgp_stop, Clearing}, /* Receive_UPDATE_message */
|
|
|
|
{bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */
|
|
|
|
{bgp_clearing_completed, Idle}, /* Clearing_Completed */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Deleted, */
|
|
|
|
{bgp_ignore, Deleted}, /* BGP_Start */
|
|
|
|
{bgp_ignore, Deleted}, /* BGP_Stop */
|
|
|
|
{bgp_ignore, Deleted}, /* TCP_connection_open */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_ignore, Deleted}, /* TCP_connection_open_w_delay */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_ignore, Deleted}, /* TCP_connection_closed */
|
|
|
|
{bgp_ignore, Deleted}, /* TCP_connection_open_failed */
|
|
|
|
{bgp_ignore, Deleted}, /* TCP_fatal_error */
|
|
|
|
{bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
|
|
|
|
{bgp_ignore, Deleted}, /* Hold_Timer_expired */
|
|
|
|
{bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
|
2020-10-20 16:49:58 +02:00
|
|
|
{bgp_ignore, Deleted}, /* DelayOpen_timer_expired */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
{bgp_ignore, Deleted}, /* Receive_OPEN_message */
|
|
|
|
{bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
|
|
|
|
{bgp_ignore, Deleted}, /* Receive_UPDATE_message */
|
|
|
|
{bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
|
|
|
|
{bgp_ignore, Deleted}, /* Clearing_Completed */
|
2002-12-13 21:15:29 +01:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Execute event process. */
|
|
|
|
int bgp_event(struct thread *thread)
|
|
|
|
{
|
2020-03-20 01:19:50 +01:00
|
|
|
enum bgp_fsm_events event;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct peer *peer;
|
2015-05-20 02:40:37 +02:00
|
|
|
int ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
peer = THREAD_ARG(thread);
|
|
|
|
event = THREAD_VAL(thread);
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
ret = bgp_event_update(peer, event);
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2020-03-20 01:19:50 +01:00
|
|
|
int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
|
2015-05-20 02:40:37 +02:00
|
|
|
{
|
2020-03-20 14:03:08 +01:00
|
|
|
enum bgp_fsm_status next;
|
2015-05-20 02:40:37 +02:00
|
|
|
int ret = 0;
|
|
|
|
struct peer *other;
|
|
|
|
int passive_conn = 0;
|
2015-05-20 03:03:47 +02:00
|
|
|
int dyn_nbr;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-06-10 03:01:56 +02:00
|
|
|
/* default return code */
|
|
|
|
ret = FSM_PEER_NOOP;
|
|
|
|
|
2015-05-20 02:40:37 +02:00
|
|
|
other = peer->doppelganger;
|
|
|
|
passive_conn =
|
|
|
|
(CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0;
|
2015-05-20 03:03:47 +02:00
|
|
|
dyn_nbr = peer_dynamic_neighbor(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Logging this event. */
|
|
|
|
next = FSM[peer->status - 1][event - 1].next_state;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 02:58:12 +02:00
|
|
|
if (bgp_debug_neighbor_events(peer) && peer->status != next)
|
2015-05-20 03:04:19 +02:00
|
|
|
zlog_debug("%s [FSM] %s (%s->%s), fd %d", peer->host,
|
2002-12-13 21:15:29 +01:00
|
|
|
bgp_event_str[event],
|
2017-06-21 01:56:50 +02:00
|
|
|
lookup_msg(bgp_status_msg, peer->status, NULL),
|
|
|
|
lookup_msg(bgp_status_msg, next, NULL), peer->fd);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:04:12 +02:00
|
|
|
peer->last_event = peer->cur_event;
|
|
|
|
peer->cur_event = event;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Call function. */
|
[bgpd] Fix 0.99 shutdown regression, introduce Clearing and Deleted states
2006-09-14 Paul Jakma <paul.jakma@sun.com>
* (general) Fix some niggly issues around 'shutdown' and clearing
by adding a Clearing FSM wait-state and a hidden 'Deleted'
FSM state, to allow deleted peers to 'cool off' and hit 0
references. This introduces a slow memory leak of struct peer,
however that's more a testament to the fragility of the
reference counting than a bug in this patch, cleanup of
reference counting to fix this is to follow.
* bgpd.h: Add Clearing, Deleted states and Clearing_Completed
and event.
* bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
Deleted.
* bgp_fsm.h: Don't allow timer/event threads to set anything
for Deleted peers.
* bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
needs to stop everything.
(bgp_stop) Remove explicit fsm_change_status call, the
general framework handles the transition.
(bgp_start) Log a warning if a start is attempted on a peer
that should stay down, trying to start a peer.
(struct .. FSM) Add Clearing_Completed
events, has little influence except when in state
Clearing to signal wait-state can end.
Add Clearing and Deleted states, former is a wait-state,
latter is a placeholder state to allow peers to disappear
quietly once refcounts settle.
(bgp_event) Try reduce verbosity of FSM state-change debug,
changes to same state are not interesting (Established->Established)
Allow NULL action functions in FSM.
* bgp_packet.c: (bgp_write) Use FSM events, rather than trying
to twiddle directly with FSM state behind the back of FSM.
(bgp_write_notify) ditto.
(bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
this patch crashes, now it leaks instead.
* bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
event, to end clearing.
(bgp_clear_route) See extensive comments.
* bgpd.c: (peer_free) should only be called while in Deleted,
peer refcounting controls when peer_free is called.
bgp_sync_delete should be here, not in peer_delete.
(peer_delete) Initiate delete.
Transition to Deleted state manually.
When removing peer from indices that provide visibility of it,
take great care to be idempotent wrt the reference counting
of struct peer through those indices.
Use bgp_timer_set, rather than replicating.
Call to bgp_sync_delete isn't appropriate here, sync can be
referenced while shutting down and finishing deletion.
(peer_group_bind) Take care to be idempotent wrt list references
indexing peers.
2006-09-14 04:58:49 +02:00
|
|
|
if (FSM[peer->status - 1][event - 1].func)
|
|
|
|
ret = (*(FSM[peer->status - 1][event - 1].func))(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
if (ret >= 0) {
|
2015-05-20 02:40:37 +02:00
|
|
|
if (ret == 1 && next == Established) {
|
|
|
|
/* The case when doppelganger swap accurred in
|
|
|
|
bgp_establish.
|
|
|
|
Update the peer pointer accordingly */
|
2017-06-10 03:01:56 +02:00
|
|
|
ret = FSM_PEER_TRANSFERRED;
|
2015-05-20 02:40:37 +02:00
|
|
|
peer = other;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
/* If status is changed. */
|
2017-06-10 03:01:56 +02:00
|
|
|
if (next != peer->status) {
|
2007-02-22 18:48:42 +01:00
|
|
|
bgp_fsm_change_status(peer, next);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-09-08 17:51:12 +02:00
|
|
|
/*
|
|
|
|
* If we're going to ESTABLISHED then we executed a
|
|
|
|
* peer transfer. In this case we can either return
|
|
|
|
* FSM_PEER_TRANSITIONED or FSM_PEER_TRANSFERRED.
|
|
|
|
* Opting for TRANSFERRED since transfer implies
|
|
|
|
* session establishment.
|
|
|
|
*/
|
2017-06-10 03:01:56 +02:00
|
|
|
if (ret != FSM_PEER_TRANSFERRED)
|
|
|
|
ret = FSM_PEER_TRANSITIONED;
|
|
|
|
}
|
|
|
|
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
/* Make sure timer is set. */
|
|
|
|
bgp_timer_set(peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-06-12 04:53:42 +02:00
|
|
|
} else {
|
2017-09-08 17:51:12 +02:00
|
|
|
/*
|
|
|
|
* If we got a return value of -1, that means there was an
|
|
|
|
* error, restart the FSM. Since bgp_stop() was called on the
|
|
|
|
* peer. only a few fields are safe to access here. In any case
|
|
|
|
* we need to indicate that the peer was stopped in the return
|
|
|
|
* code.
|
|
|
|
*/
|
2017-06-12 04:53:42 +02:00
|
|
|
if (!dyn_nbr && !passive_conn && peer->bgp) {
|
2018-08-03 20:03:29 +02:00
|
|
|
flog_err(
|
2018-09-13 20:23:42 +02:00
|
|
|
EC_BGP_FSM,
|
2020-03-27 12:35:23 +01:00
|
|
|
"%s [FSM] Failure handling event %s in state %s, prior events %s, %s, fd %d",
|
2017-06-12 04:53:42 +02:00
|
|
|
peer->host, bgp_event_str[peer->cur_event],
|
|
|
|
lookup_msg(bgp_status_msg, peer->status, NULL),
|
|
|
|
bgp_event_str[peer->last_event],
|
|
|
|
bgp_event_str[peer->last_major_event],
|
|
|
|
peer->fd);
|
|
|
|
bgp_stop(peer);
|
|
|
|
bgp_fsm_change_status(peer, Idle);
|
|
|
|
bgp_timer_set(peer);
|
|
|
|
}
|
|
|
|
ret = FSM_PEER_STOPPED;
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
}
|
2017-06-12 04:53:42 +02:00
|
|
|
|
2005-06-01 Paul Jakma <paul.jakma@sun.com>
* bgpd/(general) refcount struct peer and bgp_info, hence allowing us
add work_queues for bgp_process.
* bgpd/bgp_route.h: (struct bgp_info) Add 'lock' field for refcount.
Add bgp_info_{lock,unlock} helper functions.
Add bgp_info_{add,delete} helpers, to remove need for
users managing locking/freeing of bgp_info and bgp_node's.
* bgpd/bgp_table.h: (struct bgp_node) Add a flags field, and
BGP_NODE_PROCESS_SCHEDULED to merge redundant processing of
nodes.
* bgpd/bgp_fsm.h: Make the ON/OFF/ADD/REMOVE macros lock and unlock
peer reference as appropriate.
* bgpd/bgp_damp.c: Remove its internal prototypes for
bgp_info_delete/free. Just use bgp_info_delete.
* bgpd/bgpd.h: (struct bgp_master) Add work_queue pointers.
(struct peer) Add reference count 'lock'
(peer_lock,peer_unlock) New helpers to take/release reference
on struct peer.
* bgpd/bgp_advertise.c: (general) Add peer and bgp_info refcounting
and balance how references are taken and released.
(bgp_advertise_free) release bgp_info reference, if appropriate
(bgp_adj_out_free) unlock peer
(bgp_advertise_clean) leave the adv references alone, or else
call bgp_advertise_free cant unlock them.
(bgp_adj_out_set) lock the peer on new adj's, leave the reference
alone otherwise. lock the new bgp_info reference.
(bgp_adj_in_set) lock the peer reference
(bgp_adj_in_remove) and unlock it here
(bgp_sync_delete) make hash_free on peer conditional, just in
case.
* bgpd/bgp_fsm.c: (general) document that the timers depend on
bgp_event to release a peer reference.
(bgp_fsm_change_status) moved up the file, unchanged.
(bgp_stop) Decrement peer lock as many times as cancel_event
canceled - shouldnt be needed but just in case.
stream_fifo_clean of obuf made conditional, just in case.
(bgp_event) always unlock the peer, regardless of return value
of bgp_fsm_change_status.
* bgpd/bgp_packet.c: (general) change several bgp_stop's to BGP_EVENT's.
(bgp_read) Add a mysterious extra peer_unlock for ACCEPT_PEERs
along with a comment on it.
* bgpd/bgp_route.c: (general) Add refcounting of bgp_info, cleanup
some of the resource management around bgp_info. Refcount peer.
Add workqueues for bgp_process and clear_table.
(bgp_info_new) make static
(bgp_info_free) Ditto, and unlock the peer reference.
(bgp_info_lock,bgp_info_unlock) new exported functions
(bgp_info_add) Add a bgp_info to a bgp_node in correct fashion,
taking care of reference counts.
(bgp_info_delete) do the opposite of bgp_info_add.
(bgp_process_rsclient) Converted into a work_queue work function.
(bgp_process_main) ditto.
(bgp_processq_del) process work queue item deconstructor
(bgp_process_queue_init) process work queue init
(bgp_process) call init function if required, set up queue item
and add to queue, rather than calling process functions directly.
(bgp_rib_remove) let bgp_info_delete manage bgp_info refcounts
(bgp_rib_withdraw) ditto
(bgp_update_rsclient) let bgp_info_add manage refcounts
(bgp_update_main) ditto
(bgp_clear_route_node) clear_node_queue work function, does
per-node aspects of what bgp_clear_route_table did previously
(bgp_clear_node_queue_del) clear_node_queue item delete function
(bgp_clear_node_complete) clear_node_queue completion function,
it unplugs the process queues, which have to be blocked while
clear_node_queue is being processed to prevent a race.
(bgp_clear_node_queue_init) init function for clear_node_queue
work queues
(bgp_clear_route_table) Sets up items onto a workqueue now, rather
than clearing each node directly. Plugs both process queues to
avoid potential race.
(bgp_static_withdraw_rsclient) let bgp_info_{add,delete} manage
bgp_info refcounts.
(bgp_static_update_rsclient) ditto
(bgp_static_update_main) ditto
(bgp_static_update_vpnv4) ditto, remove unneeded cast.
(bgp_static_withdraw) see bgp_static_withdraw_rsclient
(bgp_static_withdraw_vpnv4) ditto
(bgp_aggregate_{route,add,delete}) ditto
(bgp_redistribute_{add,delete,withdraw}) ditto
* bgpd/bgp_vty.c: (peer_rsclient_set_vty) lock rsclient list peer
reference
(peer_rsclient_unset_vty) ditto, but unlock same reference
* bgpd/bgpd.c: (peer_free) handle frees of info to be kept for lifetime
of struct peer.
(peer_lock,peer_unlock) peer refcount helpers
(peer_new) add initial refcounts
(peer_create,peer_create_accept) lock peer as appropriate
(peer_delete) unlock as appropriate, move out some free's to
peer_free.
(peer_group_bind,peer_group_unbind) peer refcounting as
appropriate.
(bgp_create) check CALLOC return value.
(bgp_terminate) free workqueues too.
* lib/memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and
MTYPE_BGP_CLEAR_NODE_QUEUE
2005-06-01 13:17:05 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2019-10-23 07:40:22 +02:00
|
|
|
/* BGP GR Code */
|
|
|
|
|
|
|
|
int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp,
|
2020-01-31 19:04:00 +01:00
|
|
|
enum global_mode global_new_state,
|
|
|
|
enum global_mode global_old_state)
|
2019-10-23 07:40:22 +02:00
|
|
|
{
|
|
|
|
struct peer *peer = {0};
|
|
|
|
struct listnode *node = {0};
|
|
|
|
struct listnode *nnode = {0};
|
2020-01-31 19:04:00 +01:00
|
|
|
enum peer_mode peer_old_state = PEER_INVALID;
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
|
|
|
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("%s [BGP_GR] Peer: (%s) :", __func__,
|
|
|
|
peer->host);
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
peer_old_state = bgp_peer_gr_mode_get(peer);
|
|
|
|
|
|
|
|
if (peer_old_state == PEER_GLOBAL_INHERIT) {
|
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
/*
|
|
|
|
*Reset only these peers and send a
|
|
|
|
*new open message with the change capabilities.
|
|
|
|
*Considering the mode to be "global_new_state" and
|
|
|
|
*do all operation accordingly
|
|
|
|
*/
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
switch (global_new_state) {
|
|
|
|
case GLOBAL_HELPER:
|
|
|
|
BGP_PEER_GR_HELPER_ENABLE(peer);
|
|
|
|
break;
|
|
|
|
case GLOBAL_GR:
|
|
|
|
BGP_PEER_GR_ENABLE(peer);
|
|
|
|
break;
|
|
|
|
case GLOBAL_DISABLE:
|
|
|
|
BGP_PEER_GR_DISABLE(peer);
|
|
|
|
break;
|
|
|
|
case GLOBAL_INVALID:
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("%s [BGP_GR] GLOBAL_INVALID",
|
|
|
|
__func__);
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_ERR_GR_OPERATION_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bgp->global_gr_present_state = global_new_state;
|
|
|
|
|
|
|
|
return BGP_GR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-11-25 16:18:15 +01:00
|
|
|
int bgp_gr_update_all(struct bgp *bgp, int global_gr_cmd)
|
2019-10-23 07:40:22 +02:00
|
|
|
{
|
|
|
|
enum global_mode global_new_state = GLOBAL_INVALID;
|
|
|
|
enum global_mode global_old_state = GLOBAL_INVALID;
|
|
|
|
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("%s [BGP_GR]START: global_gr_cmd :%s:", __func__,
|
|
|
|
print_global_gr_cmd(global_gr_cmd));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
global_old_state = bgp_global_gr_mode_get(bgp);
|
|
|
|
|
2019-11-25 16:18:15 +01:00
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("[BGP_GR] global_old_gr_state :%s:",
|
|
|
|
print_global_gr_mode(global_old_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
2019-11-25 16:18:15 +01:00
|
|
|
if (global_old_state != GLOBAL_INVALID) {
|
2019-10-23 07:40:22 +02:00
|
|
|
global_new_state =
|
2019-11-25 16:18:15 +01:00
|
|
|
bgp->GLOBAL_GR_FSM[global_old_state][global_gr_cmd];
|
|
|
|
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("[BGP_GR] global_new_gr_state :%s:",
|
|
|
|
print_global_gr_mode(global_new_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
} else {
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_err("%s [BGP_GR] global_old_state == GLOBAL_INVALID",
|
|
|
|
__func__);
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_ERR_GR_OPERATION_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (global_new_state == GLOBAL_INVALID) {
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_err("%s [BGP_GR] global_new_state == GLOBAL_INVALID",
|
|
|
|
__func__);
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_ERR_GR_INVALID_CMD;
|
|
|
|
}
|
|
|
|
if (global_new_state == global_old_state) {
|
|
|
|
/* Trace msg */
|
2019-11-25 16:18:15 +01:00
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
|
|
|
zlog_debug(
|
2020-01-31 19:04:00 +01:00
|
|
|
"%s [BGP_GR] global_new_state == global_old_state :%s",
|
|
|
|
__func__,
|
|
|
|
print_global_gr_mode(global_new_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_GR_NO_OPERATION;
|
|
|
|
}
|
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
return bgp_gr_lookup_n_update_all_peer(bgp, global_new_state,
|
|
|
|
global_old_state);
|
2019-10-23 07:40:22 +02:00
|
|
|
}
|
|
|
|
|
2019-11-25 16:18:15 +01:00
|
|
|
const char *print_peer_gr_mode(enum peer_mode pr_mode)
|
|
|
|
{
|
|
|
|
const char *peer_gr_mode = NULL;
|
|
|
|
|
|
|
|
switch (pr_mode) {
|
|
|
|
case PEER_HELPER:
|
|
|
|
peer_gr_mode = "PEER_HELPER";
|
|
|
|
break;
|
|
|
|
case PEER_GR:
|
|
|
|
peer_gr_mode = "PEER_GR";
|
|
|
|
break;
|
|
|
|
case PEER_DISABLE:
|
|
|
|
peer_gr_mode = "PEER_DISABLE";
|
|
|
|
break;
|
|
|
|
case PEER_INVALID:
|
|
|
|
peer_gr_mode = "PEER_INVALID";
|
|
|
|
break;
|
|
|
|
case PEER_GLOBAL_INHERIT:
|
|
|
|
peer_gr_mode = "PEER_GLOBAL_INHERIT";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return peer_gr_mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd)
|
|
|
|
{
|
|
|
|
const char *peer_gr_cmd = NULL;
|
|
|
|
|
|
|
|
switch (pr_gr_cmd) {
|
|
|
|
case PEER_GR_CMD:
|
|
|
|
peer_gr_cmd = "PEER_GR_CMD";
|
|
|
|
break;
|
|
|
|
case NO_PEER_GR_CMD:
|
|
|
|
peer_gr_cmd = "NO_PEER_GR_CMD";
|
|
|
|
break;
|
|
|
|
case PEER_DISABLE_CMD:
|
|
|
|
peer_gr_cmd = "PEER_GR_CMD";
|
|
|
|
break;
|
|
|
|
case NO_PEER_DISABLE_CMD:
|
|
|
|
peer_gr_cmd = "NO_PEER_GR_CMD";
|
|
|
|
break;
|
|
|
|
case PEER_HELPER_CMD:
|
|
|
|
peer_gr_cmd = "PEER_HELPER_CMD";
|
|
|
|
break;
|
|
|
|
case NO_PEER_HELPER_CMD:
|
|
|
|
peer_gr_cmd = "NO_PEER_HELPER_CMD";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return peer_gr_cmd;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *print_global_gr_mode(enum global_mode gl_mode)
|
|
|
|
{
|
|
|
|
const char *global_gr_mode = NULL;
|
|
|
|
|
|
|
|
switch (gl_mode) {
|
|
|
|
case GLOBAL_HELPER:
|
|
|
|
global_gr_mode = "GLOBAL_HELPER";
|
|
|
|
break;
|
|
|
|
case GLOBAL_GR:
|
|
|
|
global_gr_mode = "GLOBAL_GR";
|
|
|
|
break;
|
|
|
|
case GLOBAL_DISABLE:
|
|
|
|
global_gr_mode = "GLOBAL_DISABLE";
|
|
|
|
break;
|
|
|
|
case GLOBAL_INVALID:
|
|
|
|
global_gr_mode = "GLOBAL_INVALID";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return global_gr_mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd)
|
|
|
|
{
|
|
|
|
const char *global_gr_cmd = NULL;
|
|
|
|
|
|
|
|
switch (gl_gr_cmd) {
|
|
|
|
case GLOBAL_GR_CMD:
|
|
|
|
global_gr_cmd = "GLOBAL_GR_CMD";
|
|
|
|
break;
|
|
|
|
case NO_GLOBAL_GR_CMD:
|
|
|
|
global_gr_cmd = "NO_GLOBAL_GR_CMD";
|
|
|
|
break;
|
|
|
|
case GLOBAL_DISABLE_CMD:
|
|
|
|
global_gr_cmd = "GLOBAL_DISABLE_CMD";
|
|
|
|
break;
|
|
|
|
case NO_GLOBAL_DISABLE_CMD:
|
|
|
|
global_gr_cmd = "NO_GLOBAL_DISABLE_CMD";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return global_gr_cmd;
|
|
|
|
}
|
|
|
|
|
2019-10-23 07:40:22 +02:00
|
|
|
enum global_mode bgp_global_gr_mode_get(struct bgp *bgp)
|
|
|
|
{
|
|
|
|
return bgp->global_gr_present_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum peer_mode bgp_peer_gr_mode_get(struct peer *peer)
|
|
|
|
{
|
|
|
|
return peer->peer_gr_present_state;
|
|
|
|
}
|
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd)
|
2019-10-23 07:40:22 +02:00
|
|
|
{
|
2020-01-31 19:04:00 +01:00
|
|
|
enum peer_mode peer_new_state = PEER_INVALID;
|
|
|
|
enum peer_mode peer_old_state = PEER_INVALID;
|
2019-10-23 07:40:22 +02:00
|
|
|
struct bgp_peer_gr peer_state;
|
|
|
|
int result = BGP_GR_FAILURE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* fetch peer_old_state from peer structure also
|
|
|
|
* fetch global_old_state from bgp structure,
|
|
|
|
* peer had a back pointer to bgpo struct ;
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("%s [BGP_GR] START:Peer: (%s) : peer_gr_cmd :%s:",
|
|
|
|
__func__, peer->host,
|
|
|
|
print_peer_gr_cmd(peer_gr_cmd));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
peer_old_state = bgp_peer_gr_mode_get(peer);
|
|
|
|
|
|
|
|
if (peer_old_state == PEER_INVALID) {
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("[BGP_GR] peer_old_state == Invalid state !");
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_ERR_GR_OPERATION_FAILED;
|
|
|
|
}
|
|
|
|
|
2019-11-25 16:18:15 +01:00
|
|
|
peer_state = peer->PEER_GR_FSM[peer_old_state][peer_gr_cmd];
|
2019-10-23 07:40:22 +02:00
|
|
|
peer_new_state = peer_state.next_state;
|
|
|
|
|
|
|
|
if (peer_new_state == PEER_INVALID) {
|
|
|
|
zlog_debug(
|
2019-11-25 16:18:15 +01:00
|
|
|
"[BGP_GR] Invalid bgp graceful restart command used !");
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_ERR_GR_INVALID_CMD;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (peer_new_state != peer_old_state) {
|
2020-01-31 19:04:00 +01:00
|
|
|
result = peer_state.action_fun(peer, peer_old_state,
|
|
|
|
peer_new_state);
|
2019-10-23 07:40:22 +02:00
|
|
|
} else {
|
2019-11-25 16:18:15 +01:00
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
|
|
|
zlog_debug(
|
2020-01-31 19:04:00 +01:00
|
|
|
"[BGP_GR] peer_old_state == peer_new_state !");
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_GR_NO_OPERATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == BGP_GR_SUCCESS) {
|
|
|
|
|
|
|
|
/* Update the mode i.e peer_new_state into the peer structure */
|
|
|
|
peer->peer_gr_present_state = peer_new_state;
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug(
|
2020-03-14 00:05:18 +01:00
|
|
|
"[BGP_GR] Successfully change the state of the peer to : %s : !",
|
2020-01-31 19:04:00 +01:00
|
|
|
print_peer_gr_mode(peer_new_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
return BGP_GR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
unsigned int bgp_peer_gr_action(struct peer *peer, int old_peer_state,
|
|
|
|
int new_peer_state)
|
2019-10-23 07:40:22 +02:00
|
|
|
{
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
|
|
|
zlog_debug(
|
2019-11-25 16:18:15 +01:00
|
|
|
"%s [BGP_GR] Move peer from old_peer_state :%s: to new_peer_state :%s: !!!!",
|
|
|
|
__func__, print_peer_gr_mode(old_peer_state),
|
|
|
|
print_peer_gr_mode(new_peer_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
int bgp_gr_global_mode = GLOBAL_INVALID;
|
|
|
|
unsigned int ret = BGP_GR_FAILURE;
|
|
|
|
|
|
|
|
if (old_peer_state == new_peer_state) {
|
2020-01-31 19:04:00 +01:00
|
|
|
/* Nothing to do over here as the present and old state is the
|
|
|
|
* same */
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_GR_NO_OPERATION;
|
|
|
|
}
|
2020-01-31 19:04:00 +01:00
|
|
|
if ((old_peer_state == PEER_INVALID)
|
|
|
|
|| (new_peer_state == PEER_INVALID)) {
|
|
|
|
/* something bad happend , print error message */
|
2019-10-23 07:40:22 +02:00
|
|
|
return BGP_ERR_GR_INVALID_CMD;
|
|
|
|
}
|
|
|
|
|
|
|
|
bgp_gr_global_mode = bgp_global_gr_mode_get(peer->bgp);
|
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
if ((old_peer_state == PEER_GLOBAL_INHERIT)
|
|
|
|
&& (new_peer_state != PEER_GLOBAL_INHERIT)) {
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
/* fetch the Mode running in the Global state machine
|
|
|
|
*from the bgp structure into a variable called
|
|
|
|
*bgp_gr_global_mode
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Here we are checking if the
|
|
|
|
*1. peer_new_state == global_mode == helper_mode
|
|
|
|
*2. peer_new_state == global_mode == GR_mode
|
|
|
|
*3. peer_new_state == global_mode == disabled_mode
|
|
|
|
*/
|
|
|
|
|
|
|
|
BGP_PEER_GR_GLOBAL_INHERIT_UNSET(peer);
|
|
|
|
|
|
|
|
if (new_peer_state == bgp_gr_global_mode) {
|
2020-01-31 19:04:00 +01:00
|
|
|
/*This is incremental updates i.e no tear down
|
|
|
|
*of the existing session
|
|
|
|
*as the peer is already working in the same mode.
|
|
|
|
*/
|
2019-10-23 07:40:22 +02:00
|
|
|
ret = BGP_GR_SUCCESS;
|
|
|
|
} else {
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
|
|
|
zlog_debug(
|
2019-11-25 16:18:15 +01:00
|
|
|
"[BGP_GR] Peer state changed from :%s ",
|
|
|
|
print_peer_gr_mode(old_peer_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
bgp_peer_move_to_gr_mode(peer, new_peer_state);
|
|
|
|
|
|
|
|
ret = BGP_GR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* In the case below peer is going into Global inherit mode i.e.
|
|
|
|
* the peer would work as the mode configured at the global level
|
|
|
|
*/
|
2020-01-31 19:04:00 +01:00
|
|
|
else if ((new_peer_state == PEER_GLOBAL_INHERIT)
|
|
|
|
&& (old_peer_state != PEER_GLOBAL_INHERIT)) {
|
2019-10-23 07:40:22 +02:00
|
|
|
/* Here in this case it would be destructive
|
|
|
|
* in all the cases except one case when,
|
|
|
|
* Global GR is configured Disabled
|
|
|
|
* and present_peer_state is not disable
|
|
|
|
*/
|
|
|
|
|
|
|
|
BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
|
|
|
|
|
|
|
|
if (old_peer_state == bgp_gr_global_mode) {
|
|
|
|
|
|
|
|
/* This is incremental updates
|
|
|
|
*i.e no tear down of the existing session
|
|
|
|
*as the peer is already working in the same mode.
|
|
|
|
*/
|
|
|
|
ret = BGP_GR_SUCCESS;
|
|
|
|
} else {
|
|
|
|
/* Destructive always */
|
|
|
|
/* Tear down the old session
|
|
|
|
* and send the new capability
|
|
|
|
* as per the bgp_gr_global_mode
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug(
|
|
|
|
"[BGP_GR] Peer state changed from :%s",
|
2019-11-25 16:18:15 +01:00
|
|
|
print_peer_gr_mode(old_peer_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
bgp_peer_move_to_gr_mode(peer, bgp_gr_global_mode);
|
|
|
|
|
|
|
|
ret = BGP_GR_SUCCESS;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
*This else case, it include all the cases except -->
|
|
|
|
*(new_peer_state != Peer_Global) &&
|
|
|
|
*( old_peer_state != Peer_Global )
|
|
|
|
*/
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2019-11-25 16:18:15 +01:00
|
|
|
zlog_debug("[BGP_GR] Peer state changed from :%s",
|
2020-01-31 19:04:00 +01:00
|
|
|
print_peer_gr_mode(old_peer_state));
|
2019-10-23 07:40:22 +02:00
|
|
|
|
|
|
|
bgp_peer_move_to_gr_mode(peer, new_peer_state);
|
|
|
|
|
|
|
|
ret = BGP_GR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void bgp_peer_move_to_gr_mode(struct peer *peer, int new_state)
|
|
|
|
|
|
|
|
{
|
|
|
|
int bgp_global_gr_mode = bgp_global_gr_mode_get(peer->bgp);
|
|
|
|
|
|
|
|
switch (new_state) {
|
|
|
|
case PEER_HELPER:
|
|
|
|
BGP_PEER_GR_HELPER_ENABLE(peer);
|
|
|
|
break;
|
|
|
|
case PEER_GR:
|
|
|
|
BGP_PEER_GR_ENABLE(peer);
|
|
|
|
break;
|
|
|
|
case PEER_DISABLE:
|
|
|
|
BGP_PEER_GR_DISABLE(peer);
|
|
|
|
break;
|
|
|
|
case PEER_GLOBAL_INHERIT:
|
|
|
|
BGP_PEER_GR_GLOBAL_INHERIT_SET(peer);
|
|
|
|
|
|
|
|
if (bgp_global_gr_mode == GLOBAL_HELPER) {
|
|
|
|
BGP_PEER_GR_HELPER_ENABLE(peer);
|
2020-01-31 19:04:00 +01:00
|
|
|
} else if (bgp_global_gr_mode == GLOBAL_GR) {
|
2019-10-23 07:40:22 +02:00
|
|
|
BGP_PEER_GR_ENABLE(peer);
|
|
|
|
} else if (bgp_global_gr_mode == GLOBAL_DISABLE) {
|
|
|
|
BGP_PEER_GR_DISABLE(peer);
|
|
|
|
} else {
|
2019-11-25 16:18:15 +01:00
|
|
|
zlog_err(
|
2020-01-31 19:04:00 +01:00
|
|
|
"[BGP_GR] Default switch inherit mode ::: SOMETHING IS WRONG !!!");
|
2019-10-23 07:40:22 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_err(
|
|
|
|
"[BGP_GR] Default switch mode ::: SOMETHING IS WRONG !!!");
|
2019-10-23 07:40:22 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2019-11-25 16:18:15 +01:00
|
|
|
zlog_debug("[BGP_GR] Peer state changed --to--> : %d : !",
|
2020-01-31 19:04:00 +01:00
|
|
|
new_state);
|
2019-10-23 07:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void bgp_peer_gr_flags_update(struct peer *peer)
|
|
|
|
{
|
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
2020-01-31 19:04:00 +01:00
|
|
|
zlog_debug("%s [BGP_GR] called !", __func__);
|
2019-10-23 07:40:22 +02:00
|
|
|
if (CHECK_FLAG(peer->peer_gr_new_status_flag,
|
2020-01-31 19:04:00 +01:00
|
|
|
PEER_GRACEFUL_RESTART_NEW_STATE_HELPER))
|
|
|
|
SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
|
2019-10-23 07:40:22 +02:00
|
|
|
else
|
2020-01-31 19:04:00 +01:00
|
|
|
UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER);
|
2019-10-23 07:40:22 +02:00
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
|
|
|
zlog_debug(
|
2019-11-25 16:18:15 +01:00
|
|
|
"[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_HELPER : %s : !",
|
2019-10-23 07:40:22 +02:00
|
|
|
peer->host,
|
2019-10-23 12:02:48 +02:00
|
|
|
(CHECK_FLAG(peer->flags,
|
2020-01-31 19:04:00 +01:00
|
|
|
PEER_FLAG_GRACEFUL_RESTART_HELPER)
|
|
|
|
? "Set"
|
|
|
|
: "UnSet"));
|
2019-10-23 07:40:22 +02:00
|
|
|
if (CHECK_FLAG(peer->peer_gr_new_status_flag,
|
2020-01-31 19:04:00 +01:00
|
|
|
PEER_GRACEFUL_RESTART_NEW_STATE_RESTART))
|
|
|
|
SET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
|
2019-10-23 07:40:22 +02:00
|
|
|
else
|
2020-01-31 19:04:00 +01:00
|
|
|
UNSET_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART);
|
2019-10-23 07:40:22 +02:00
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
|
|
|
zlog_debug(
|
2019-11-25 16:18:15 +01:00
|
|
|
"[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART : %s : !",
|
2019-10-23 07:40:22 +02:00
|
|
|
peer->host,
|
2020-01-31 19:04:00 +01:00
|
|
|
(CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
|
|
|
|
? "Set"
|
|
|
|
: "UnSet"));
|
2019-10-23 07:40:22 +02:00
|
|
|
if (CHECK_FLAG(peer->peer_gr_new_status_flag,
|
2020-01-31 19:04:00 +01:00
|
|
|
PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT))
|
2019-10-23 12:02:48 +02:00
|
|
|
SET_FLAG(peer->flags,
|
2020-01-31 19:04:00 +01:00
|
|
|
PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT);
|
2019-10-23 07:40:22 +02:00
|
|
|
else
|
2019-10-23 12:02:48 +02:00
|
|
|
UNSET_FLAG(peer->flags,
|
2020-01-31 19:04:00 +01:00
|
|
|
PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT);
|
2019-10-23 07:40:22 +02:00
|
|
|
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
|
|
|
|
zlog_debug(
|
2020-01-31 19:04:00 +01:00
|
|
|
"[BGP_GR] Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT : %s : !",
|
2019-10-23 07:40:22 +02:00
|
|
|
peer->host,
|
2019-10-23 12:02:48 +02:00
|
|
|
(CHECK_FLAG(peer->flags,
|
2020-01-31 19:04:00 +01:00
|
|
|
PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT)
|
|
|
|
? "Set"
|
|
|
|
: "UnSet"));
|
2019-10-24 06:40:53 +02:00
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
|
|
|
|
&& !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER)) {
|
|
|
|
zlog_debug("[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_MODE!",
|
|
|
|
peer->host);
|
2019-10-24 06:40:53 +02:00
|
|
|
|
|
|
|
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
|
|
|
|
|
2020-01-31 19:04:00 +01:00
|
|
|
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) {
|
2019-10-24 06:40:53 +02:00
|
|
|
|
|
|
|
peer_nsf_stop(peer);
|
|
|
|
zlog_debug(
|
2019-11-25 16:18:15 +01:00
|
|
|
"[BGP_GR] Peer %s UNSET PEER_STATUS_NSF_WAIT!",
|
2019-10-24 06:40:53 +02:00
|
|
|
peer->host);
|
|
|
|
}
|
|
|
|
}
|
2019-10-23 07:40:22 +02:00
|
|
|
}
|