if (!bgp)
return;
+ if (!up)
+ bgp_clearing_batch_begin(bgp);
+
bgp_nht_ifp_table_handle(bgp, &bgp->nexthop_cache_table[AFI_IP], ifp,
up);
bgp_nht_ifp_table_handle(bgp, &bgp->import_check_table[AFI_IP], ifp,
up);
bgp_nht_ifp_table_handle(bgp, &bgp->import_check_table[AFI_IP6], ifp,
up);
+
+ if (!up)
+ bgp_clearing_batch_end_event_start(bgp);
}
void bgp_nht_ifp_up(struct interface *ifp)
int ret = 0;
bool found = false;
struct peer *peer;
+ bool afi_safi_unspec = false;
VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+ afi_safi_unspec = ((afi == AFI_UNSPEC) && (safi == SAFI_UNSPEC));
+
/* Clear all neighbors. */
/*
* Pass along pointer to next node to peer_clear() when walking all
* doppelganger
*/
if (sort == clear_all) {
+ if (afi_safi_unspec)
+ bgp_clearing_batch_begin(bgp);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
bgp_peer_gr_flags_update(peer);
if (stype == BGP_CLEAR_SOFT_NONE)
bgp->update_delay_over = 0;
+ if (afi_safi_unspec)
+ bgp_clearing_batch_end_event_start(bgp);
return CMD_SUCCESS;
}
return CMD_WARNING;
}
+ if (afi_safi_unspec)
+ bgp_clearing_batch_begin(bgp);
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
ret = bgp_peer_clear(peer, afi, safi, &nnode, stype);
else
found = true;
}
+ if (afi_safi_unspec)
+ bgp_clearing_batch_end_event_start(bgp);
if (!found)
vty_out(vty,
/* Clear all external (eBGP) neighbors. */
if (sort == clear_external) {
+ if (afi_safi_unspec)
+ bgp_clearing_batch_begin(bgp);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->sort == BGP_PEER_IBGP)
continue;
&& bgp->present_zebra_gr_state == ZEBRA_GR_ENABLE) {
bgp_zebra_send_capabilities(bgp, true);
}
-
+ if (afi_safi_unspec)
+ bgp_clearing_batch_end_event_start(bgp);
if (!found)
vty_out(vty,
"%% BGP: No external %s peer is configured\n",
return CMD_WARNING;
}
+ if (afi_safi_unspec)
+ bgp_clearing_batch_begin(bgp);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->as != as)
continue;
bgp_zebra_send_capabilities(bgp, true);
}
+ if (afi_safi_unspec)
+ bgp_clearing_batch_end_event_start(bgp);
if (!found)
vty_out(vty,
"%% BGP: No %s peer is configured with AS %s\n",
EVENT_OFF(bgp->t_maxmed_onstartup);
EVENT_OFF(bgp->t_update_delay);
EVENT_OFF(bgp->t_establish_wait);
+ EVENT_OFF(bgp->clearing_end);
/* Set flag indicating bgp instance delete in progress */
SET_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS);
/*
* Initialize a new batch struct for clearing peer(s) from the RIB
*/
-static void bgp_clearing_batch_begin(struct bgp *bgp)
+void bgp_clearing_batch_begin(struct bgp *bgp)
{
struct bgp_clearing_info *cinfo;
+ if (event_is_scheduled(bgp->clearing_end))
+ return;
+
cinfo = XCALLOC(MTYPE_CLEARING_BATCH, sizeof(struct bgp_clearing_info));
cinfo->bgp = bgp;
{
struct bgp_clearing_info *cinfo;
+ if (event_is_scheduled(bgp->clearing_end))
+ return;
+
cinfo = bgp_clearing_info_first(&bgp->clearing_list);
assert(cinfo != NULL);
bgp_clear_route_batch(cinfo);
}
+static void bgp_clearing_batch_end_event(struct event *event)
+{
+ struct bgp *bgp = EVENT_ARG(event);
+
+ bgp_clearing_batch_end(bgp);
+ bgp_unlock(bgp);
+}
+
+void bgp_clearing_batch_end_event_start(struct bgp *bgp)
+{
+ if (!event_is_scheduled(bgp->clearing_end))
+ bgp_lock(bgp);
+
+ EVENT_OFF(bgp->clearing_end);
+ event_add_timer_msec(bm->master, bgp_clearing_batch_end_event, bgp, 100, &bgp->clearing_end);
+}
+
/* Check whether a dest's peer is relevant to a clearing batch */
bool bgp_clearing_batch_check_peer(struct bgp_clearing_info *cinfo,
const struct peer *peer)
/* start-up timer on only once at the beginning */
struct event *t_startup;
+ struct event *clearing_end;
+
uint32_t v_maxmed_onstartup; /* Duration of max-med on start-up */
#define BGP_MAXMED_ONSTARTUP_UNCONFIGURED 0 /* 0 means off, its the default */
uint32_t maxmed_onstartup_value; /* Max-med value when active on
struct bgp_dest *bgp_clearing_batch_next_dest(struct bgp_clearing_info *cinfo);
/* Done with a peer clearing batch; deal with refcounts, free memory */
void bgp_clearing_batch_completed(struct bgp_clearing_info *cinfo);
+/* Start a new batch of peers to clear */
+void bgp_clearing_batch_begin(struct bgp *bgp);
+/* End a new batch of peers to clear */
+void bgp_clearing_batch_end_event_start(struct bgp *bgp);
#ifdef _FRR_ATTRIBUTE_PRINTFRR
/* clang-format off */