diff --git a/lib/log.c b/lib/log.c index 732b238b1e..48ee0f6adb 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1122,6 +1122,7 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL), DESC_ENTRY(ZEBRA_VXLAN_SG_ADD), DESC_ENTRY(ZEBRA_VXLAN_SG_DEL), + DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY), }; #undef DESC_ENTRY diff --git a/lib/zclient.h b/lib/zclient.h index be2ef69dc1..81e454d192 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -176,6 +176,7 @@ typedef enum { ZEBRA_VXLAN_FLOOD_CONTROL, ZEBRA_VXLAN_SG_ADD, ZEBRA_VXLAN_SG_DEL, + ZEBRA_VXLAN_SG_REPLAY, } zebra_message_types_t; struct redist_proto { diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 2c814d0fdc..675e81f5a1 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -580,6 +580,23 @@ static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS) return 0; } +static void pim_zebra_vxlan_replay(void) +{ + struct stream *s = NULL; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT); + stream_putw_at(s, 0, stream_get_endp(s)); + + zclient_send_message(zclient); +} + void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) { struct in_addr vif_source; @@ -783,6 +800,9 @@ static void pim_zebra_connected(struct zclient *zclient) bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id); zclient_send_reg_requests(zclient, router->vrf_id); + + /* request for VxLAN BUM group addresses */ + pim_zebra_vxlan_replay(); } static void pim_zebra_capabilities(struct zclient_capabilities *cap) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 007e554929..98bb2eda60 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2491,6 +2491,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_IPTABLE_ADD] = zread_iptable, [ZEBRA_IPTABLE_DELETE] = zread_iptable, [ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control, + [ZEBRA_VXLAN_SG_REPLAY] = zebra_vxlan_sg_replay, }; #if defined(HANDLE_ZAPI_FUZZING) diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 972fe381cc..f92e1a010b 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -69,6 +69,7 @@ struct zebra_vrf { /* Flags. */ uint16_t flags; #define ZEBRA_VRF_RETAIN (1 << 0) +#define ZEBRA_PIM_SEND_VXLAN_SG (1 << 1) uint32_t table_id; diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index d551fa8842..dff50ceef4 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -9481,8 +9481,9 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t) /************************** vxlan SG cache management ************************/ /* Inform PIM about the mcast group */ -static int zebra_vxlan_sg_send(struct prefix_sg *sg, - char *sg_str, uint16_t cmd) +static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf, + struct prefix_sg *sg, + char *sg_str, uint16_t cmd) { struct zserv *client = NULL; struct stream *s = NULL; @@ -9491,6 +9492,9 @@ static int zebra_vxlan_sg_send(struct prefix_sg *sg, if (!client) return 0; + if (!CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) + return 0; + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, VRF_DEFAULT); @@ -9590,7 +9594,8 @@ static zebra_vxlan_sg_t *zebra_vxlan_sg_add(struct zebra_vrf *zvrf, return vxlan_sg; } - zebra_vxlan_sg_send(sg, vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD); + zebra_vxlan_sg_send(zvrf, sg, vxlan_sg->sg_str, + ZEBRA_VXLAN_SG_ADD); return vxlan_sg; } @@ -9612,8 +9617,8 @@ static void zebra_vxlan_sg_del(zebra_vxlan_sg_t *vxlan_sg) zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp); } - zebra_vxlan_sg_send(&vxlan_sg->sg, vxlan_sg->sg_str, - ZEBRA_VXLAN_SG_DEL); + zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg, + vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL); hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg); @@ -9697,6 +9702,31 @@ static void zebra_vxlan_sg_cleanup(struct hash_backet *backet, void *arg) zebra_vxlan_sg_del(vxlan_sg); } +static void zebra_vxlan_sg_replay_send(struct hash_backet *backet, void *arg) +{ + zebra_vxlan_sg_t *vxlan_sg = (zebra_vxlan_sg_t *)backet->data; + + zebra_vxlan_sg_send(vxlan_sg->zvrf, &vxlan_sg->sg, + vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD); +} + +/* Handle message from client to replay vxlan SG entries */ +void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS) +{ + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("VxLAN SG updates to PIM, start"); + + SET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG); + + if (!EVPN_ENABLED(zvrf)) { + zlog_debug("VxLAN SG replay request on unexpected vrf %d", + zvrf->vrf->vrf_id); + return; + } + + hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL); +} + /************************** EVPN BGP config management ************************/ /* Notify Local MACs to the clienti, skips GW MAC */ static void zvni_send_mac_hash_entry_to_client(struct hash_bucket *bucket, @@ -9804,14 +9834,11 @@ static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf) } /* Cleanup BGP EVPN configuration upon client disconnect */ -static int zebra_evpn_cfg_clean_up(struct zserv *client) +static int zebra_evpn_bgp_cfg_clean_up(struct zserv *client) { struct vrf *vrf; struct zebra_vrf *zvrf; - if (client->proto != ZEBRA_ROUTE_BGP) - return 0; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { zvrf = vrf->info; if (zvrf) @@ -9821,6 +9848,30 @@ static int zebra_evpn_cfg_clean_up(struct zserv *client) return 0; } +static int zebra_evpn_pim_cfg_clean_up(struct zserv *client) +{ + struct zebra_vrf *zvrf = zebra_vrf_get_evpn(); + + if (CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("VxLAN SG updates to PIM, stop"); + UNSET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG); + } + + return 0; +} + +static int zebra_evpn_cfg_clean_up(struct zserv *client) +{ + if (client->proto == ZEBRA_ROUTE_BGP) + return zebra_evpn_bgp_cfg_clean_up(client); + + if (client->proto == ZEBRA_ROUTE_PIM) + return zebra_evpn_pim_cfg_clean_up(client); + + return 0; +} + /* Cleanup BGP EVPN configuration upon client disconnect */ extern void zebra_evpn_init(void) { diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 6117567bc1..c71953d6bb 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -79,6 +79,7 @@ extern void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS); extern int is_l3vni_for_prefix_routes_only(vni_t vni); extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);