diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 39f8f84a02eb..bac43c4abd72 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -3753,7 +3753,8 @@ vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey) * This function gets called when the default instance ("router bgp NNN") * is created. */ -void vpn_leak_postchange_all(void) +static void vpn_leak_postchange_all_internal(struct event *t + __attribute__((__unused__))) { struct listnode *next; struct bgp *bgp; @@ -3761,6 +3762,8 @@ void vpn_leak_postchange_all(void) assert(bgp_default); + EVENT_OFF(bm->t_vpn_leak_postchange); + /* First, do any exporting from VRFs to the single VPN RIB */ for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { @@ -3800,6 +3803,18 @@ void vpn_leak_postchange_all(void) } } +/* if event is true, delay the vpn processing by 1 second + * in a separate thread + */ +void vpn_leak_postchange_all(bool event) +{ + if (event) + event_add_timer(bm->master, vpn_leak_postchange_all_internal, + NULL, 1, &bm->t_vpn_leak_postchange); + else + vpn_leak_postchange_all_internal(NULL); +} + /* When a bgp vrf instance is unconfigured, remove its routes * from the VPN table and this vrf could be importing routes from other * bgp vrf instnaces, unimport them. diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 92a9fba887ae..dc1c759a38fa 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -347,7 +347,7 @@ extern void vpn_policy_routemap_event(const char *rmap_name); extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey); -extern void vpn_leak_postchange_all(void); +extern void vpn_leak_postchange_all(bool event); extern void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw, bool is_config); extern void bgp_vpn_leak_unimport(struct bgp *from_bgp); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index be9942afb6ea..2259fb49a9c9 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -344,7 +344,7 @@ static int bgp_srv6_locator_unset(struct bgp *bgp) } /* update vpn bgp processes */ - vpn_leak_postchange_all(); + vpn_leak_postchange_all(false); /* refresh tovpn_sid_locator */ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) { @@ -1598,7 +1598,7 @@ DEFUN_NOSH (router_bgp, * earlier "router bgp X vrf FOO" blocks. */ if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT) - vpn_leak_postchange_all(); + vpn_leak_postchange_all(false); if (inst_type == BGP_INSTANCE_TYPE_VRF) bgp_vpn_leak_export(bgp); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1c2f08465d70..e2ed78d13221 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -240,7 +240,7 @@ static int bgp_ifp_up(struct interface *ifp) vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6); vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP); vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6); - vpn_leak_postchange_all(); + vpn_leak_postchange_all(true); } return 0; @@ -295,7 +295,7 @@ static int bgp_ifp_down(struct interface *ifp) vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6); vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP); vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP6); - vpn_leak_postchange_all(); + vpn_leak_postchange_all(true); } return 0; @@ -3364,7 +3364,7 @@ static int bgp_ifp_create(struct interface *ifp) vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6); vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP); vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6); - vpn_leak_postchange_all(); + vpn_leak_postchange_all(true); } return 0; @@ -3396,7 +3396,7 @@ static int bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS) } listnode_add(bgp->srv6_locator_chunks, chunk); - vpn_leak_postchange_all(); + vpn_leak_postchange_all(true); return 0; } @@ -3496,7 +3496,7 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) } } - vpn_leak_postchange_all(); + vpn_leak_postchange_all(false); /* refresh tovpn_sid_locator */ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) { @@ -3649,7 +3649,8 @@ static bool bgp_zebra_label_manager_connect(void) /* tell BGP L3VPN that label manager is available */ if (bgp_get_default()) - vpn_leak_postchange_all(); + vpn_leak_postchange_all(false); + return true; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 09e64cf9ec31..8ff5c15bd59e 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -8381,6 +8381,7 @@ void bgp_master_init(struct event_loop *master, const int buffer_size, bm->t_bgp_sync_label_manager = NULL; bm->t_bgp_start_label_manager = NULL; bm->t_bgp_zebra_route = NULL; + bm->t_vpn_leak_postchange = NULL; bgp_mac_init(); /* init the rd id space. @@ -8632,6 +8633,7 @@ void bgp_terminate(void) EVENT_OFF(bm->t_bgp_sync_label_manager); EVENT_OFF(bm->t_bgp_start_label_manager); EVENT_OFF(bm->t_bgp_zebra_route); + EVENT_OFF(bm->t_vpn_leak_postchange); bgp_mac_finish(); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index ad749ba67675..900593a39733 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -169,6 +169,9 @@ struct bgp_master { /* DSCP value for TCP sessions */ uint8_t tcp_dscp; + /* L3VPN processing thread */ + struct event *t_vpn_leak_postchange; + #define BM_DEFAULT_Q_LIMIT 10000 uint32_t inq_limit; uint32_t outq_limit;