]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Tie in more clear events to clear code
authorDonald Sharp <sharpd@nvidia.com>
Wed, 12 Mar 2025 16:37:21 +0000 (12:37 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Thu, 20 Mar 2025 13:38:51 +0000 (09:38 -0400)
The `clear bgp *` and the interface down events
cause a global clearing of data from the bgp rib.
Let's tie those into the clear peer code such
that we can take advantage of the reduced load
in these cases too.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
bgpd/bgp_nht.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 268d8046995ed6c9cea87b466da82b5df48163a1..bd27562134c7c0c6bc326e49834c00a7707935fb 100644 (file)
@@ -804,6 +804,9 @@ static void bgp_nht_ifp_handle(struct interface *ifp, bool up)
        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,
@@ -812,6 +815,9 @@ static void bgp_nht_ifp_handle(struct interface *ifp, bool up)
                                 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)
index 2897169d38120e8ae8bd9b82932ec2e39dbaeda5..66a2fe7997903972666d94541a4f8fe6f88cf92b 100644 (file)
@@ -1111,9 +1111,12 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
        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
@@ -1121,6 +1124,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
         * 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);
@@ -1147,6 +1152,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                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;
        }
 
@@ -1202,6 +1209,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                        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);
 
@@ -1210,6 +1219,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                        else
                                found = true;
                }
+               if (afi_safi_unspec)
+                       bgp_clearing_batch_end_event_start(bgp);
 
                if (!found)
                        vty_out(vty,
@@ -1221,6 +1232,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
 
        /* 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;
@@ -1245,7 +1258,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                           && 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",
@@ -1263,6 +1277,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                        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;
@@ -1288,6 +1304,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                        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",
index 70ae4d20143d1a77ea326d96f83c00c148f780fe..1427318925b00078563a12078c37aa6b6748c2f9 100644 (file)
@@ -4152,6 +4152,7 @@ int bgp_delete(struct bgp *bgp)
        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);
@@ -9094,10 +9095,13 @@ static void bgp_clearing_peer_done(struct peer *peer)
 /*
  * 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;
@@ -9120,6 +9124,9 @@ static void bgp_clearing_batch_end(struct 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);
@@ -9143,6 +9150,23 @@ static void bgp_clearing_batch_end(struct bgp *bgp)
        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)
index 5656774bc5d6680ae74432cf5f6640630d0b719d..8d3a73df9b73fe9c174a873c096634fac80894a0 100644 (file)
@@ -554,6 +554,8 @@ struct bgp {
        /* 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
@@ -3059,6 +3061,10 @@ bool bgp_clearing_batch_dests_present(struct bgp_clearing_info *cinfo);
 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 */