From ecbbc3a750f055d1ea8adc2da2c6225840696b13 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Tue, 2 Jul 2019 11:20:34 -0700 Subject: [PATCH] pimd, zebra: request for replay of SG entries on startup zvni setup in zebra is controlled via bgpd i.e. advertise_all_vni from bgpd triggers this setup. As a part of zvni creation we may need to setup BUM mcast SG entries which are propagated to pimd for MDT setup. Now pimd may not be present at the time of zvni creation or may restart post zvni creation so we need a mechanism to replay (on pimd startup) and to cleanup (on pimd stop). This is addressed via zebra_vxlan_sg_replay and zebra_evpn_pim_cfg_clean_up. Signed-off-by: Anuradha Karuppiah --- lib/log.c | 1 + lib/zclient.h | 1 + pimd/pim_zebra.c | 20 +++++++++++++ zebra/zapi_msg.c | 1 + zebra/zebra_vrf.h | 1 + zebra/zebra_vxlan.c | 69 +++++++++++++++++++++++++++++++++++++++------ zebra/zebra_vxlan.h | 1 + 7 files changed, 85 insertions(+), 9 deletions(-) diff --git a/lib/log.c b/lib/log.c index 5ce3bd7020..c6e1c4ac5f 100644 --- a/lib/log.c +++ b/lib/log.c @@ -953,6 +953,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 d651738687..493c5cde4f 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 61200806ba..4de1c41535 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2512,6 +2512,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 a3a630d53e..4a7132a103 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -9483,8 +9483,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; @@ -9493,6 +9494,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); @@ -9592,7 +9596,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; } @@ -9614,8 +9619,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); @@ -9699,6 +9704,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, @@ -9793,14 +9823,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) @@ -9810,6 +9837,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);