diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index d211f1afff..4c4659ad54 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1488,6 +1488,97 @@ static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name) } } +/* This API is used during router-id change, reflect VPNs + * auto RD and RT values and readvertise routes to VPN table. + */ +void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw) +{ + afi_t afi; + int debug; + char *vname; + const char *export_name; + char buf[RD_ADDRSTRLEN]; + struct bgp *bgp_import; + struct listnode *node; + struct ecommunity *ecom; + vpn_policy_direction_t idir, edir; + + if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT + && bgp->inst_type != BGP_INSTANCE_TYPE_VRF) + return; + + export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME; + debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) | + BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)); + + idir = BGP_VPN_POLICY_DIR_FROMVPN; + edir = BGP_VPN_POLICY_DIR_TOVPN; + + for (afi = 0; afi < AFI_MAX; ++afi) { + if (!vpn_leak_to_vpn_active(bgp, afi, NULL)) + continue; + + if (withdraw) { + vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, + afi, bgp_get_default(), bgp); + if (debug) + zlog_debug("%s: %s after to_vpn vpn_leak_prechange", + __func__, export_name); + + /* Remove import RT from VRFs */ + ecom = bgp->vpn_policy[afi].rtlist[edir]; + for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi]. + export_vrf, node, vname)) { + bgp_import = bgp_lookup_by_name(vname); + if (!bgp_import) + continue; + + ecommunity_del_val(bgp_import->vpn_policy[afi]. + rtlist[idir], + (struct ecommunity_val *)ecom->val); + + } + } else { + /* New router-id derive auto RD and RT and export + * to VPN + */ + form_auto_rd(bgp->router_id, bgp->vrf_rd_id, + &bgp->vrf_prd_auto); + bgp->vpn_policy[afi].tovpn_rd = bgp->vrf_prd_auto; + prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf, + sizeof(buf)); + bgp->vpn_policy[afi].rtlist[edir] = + ecommunity_str2com(buf, + ECOMMUNITY_ROUTE_TARGET, 0); + + /* Update import_vrf rt_list */ + ecom = bgp->vpn_policy[afi].rtlist[edir]; + for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi]. + export_vrf, node, vname)) { + bgp_import = bgp_lookup_by_name(vname); + if (!bgp_import) + continue; + if (bgp_import->vpn_policy[afi].rtlist[idir]) + bgp_import->vpn_policy[afi].rtlist[idir] + = ecommunity_merge( + bgp_import->vpn_policy[afi] + .rtlist[idir], ecom); + else + bgp_import->vpn_policy[afi].rtlist[idir] + = ecommunity_dup(ecom); + + } + /* Update routes to VPN */ + vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, + afi, bgp_get_default(), + bgp); + if (debug) + zlog_debug("%s: %s after to_vpn vpn_leak_postchange", + __func__, export_name); + } + } +} + void vpn_policy_routemap_event(const char *rmap_name) { int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT); @@ -1513,11 +1604,15 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, char buf[1000]; struct ecommunity *ecom; bool first_export = false; + int debug; export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME; idir = BGP_VPN_POLICY_DIR_FROMVPN; edir = BGP_VPN_POLICY_DIR_TOVPN; + debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) | + BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)); + /* * Cross-ref both VRFs. Also, note if this is the first time * any VRF is importing from "import_vrf". @@ -1560,6 +1655,23 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, to_bgp->vpn_policy[afi].rtlist[idir] = ecommunity_dup(ecom); SET_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT); + if (debug) { + const char *from_name; + + from_name = from_bgp->name ? from_bgp->name : + VRF_DEFAULT_NAME; + zlog_debug("%s from %s to %s first_export %u import-rt %s export-rt %s", + __func__, from_name, export_name, first_export, + to_bgp->vpn_policy[afi].rtlist[idir] ? + (ecommunity_ecom2str(to_bgp->vpn_policy[afi]. + rtlist[idir], + ECOMMUNITY_FORMAT_ROUTE_MAP, 0)) : " ", + to_bgp->vpn_policy[afi].rtlist[edir] ? + (ecommunity_ecom2str(to_bgp->vpn_policy[afi]. + rtlist[edir], + ECOMMUNITY_FORMAT_ROUTE_MAP, 0)) : " "); + } + /* Does "import_vrf" first need to export its routes or that * is already done and we just need to import those routes * from the global table? @@ -1578,12 +1690,16 @@ void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, char *vname; struct ecommunity *ecom; struct listnode *node; + int debug; export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME; tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME; idir = BGP_VPN_POLICY_DIR_FROMVPN; edir = BGP_VPN_POLICY_DIR_TOVPN; + debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) | + BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)); + /* Were we importing from "import_vrf"? */ for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf, node, vname)) { @@ -1601,6 +1717,9 @@ void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, if (!vname) return; + if (debug) + zlog_debug("%s from %s to %s", __func__, tmp_name, export_name); + /* Remove "import_vrf" from our import list. */ listnode_delete(to_bgp->vpn_policy[afi].import_vrf, vname); XFREE(MTYPE_TMP, vname); diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 2ef9570aac..1526a8111e 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -264,5 +264,6 @@ 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_handle_router_id_update(struct bgp *bgp, bool withdraw); #endif /* _QUAGGA_BGP_MPLSVPN_H */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 54e8f5f369..298418b113 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -253,6 +253,8 @@ static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id) if (is_evpn_enabled()) bgp_evpn_handle_router_id_update(bgp, TRUE); + vpn_handle_router_id_update(bgp, TRUE); + IPV4_ADDR_COPY(&bgp->router_id, id); /* Set all peer's local identifier with this value. */ @@ -270,6 +272,8 @@ static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id) if (is_evpn_enabled()) bgp_evpn_handle_router_id_update(bgp, FALSE); + vpn_handle_router_id_update(bgp, FALSE); + return 0; }