diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 9f740db325..68eb35776e 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1774,3 +1774,22 @@ void bgp_mplsvpn_init(void) &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ } + +vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey) +{ + struct listnode *mnode, *mnnode; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + struct ecommunity *ec; + + if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF) + continue; + + ec = bgp->vpn_policy[AFI_IP].import_redirect_rtlist; + + if (ecom_intersect(ec, eckey)) + return bgp->vrf_id; + } + return VRF_UNKNOWN; +} diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index d35568b838..fa3ddbac73 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -176,4 +176,6 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction, extern void vpn_policy_routemap_event(const char *rmap_name); +extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey); + #endif /* _QUAGGA_BGP_MPLSVPN_H */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index ad6f1a5588..3f51c1509c 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6588,6 +6588,63 @@ DEFPY (bgp_imexport_vpn, return CMD_SUCCESS; } +DEFPY (af_routetarget_import, + af_routetarget_import_cmd, + "[no] redirect import RTLIST...", + NO_STR + "Specify route target list\n" + "Specify route target list\n" + "Flow-spec redirect type route target\n" + "Import routes to this address-family\n" + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct ecommunity *ecom = NULL; + int doafi[AFI_MAX] = {0}; + afi_t afi; + int idx = 0; + int yes = 1; + + if (argv_find(argv, argc, "no", &idx)) + yes = 0; + + ret = vpn_policy_getafi(vty, doafi); + if (ret != CMD_SUCCESS) + return ret; + if (yes) { + if (!argv_find(argv, argc, "RTLIST", &idx)) { + vty_out(vty, "%% Missing RTLIST\n"); + return CMD_WARNING_CONFIG_FAILED; + } + ret = set_ecom_list(vty, argc - idx, argv + idx, &ecom); + if (ret != CMD_SUCCESS) + return ret; + } + for (afi = 0; afi < AFI_MAX; ++afi) { + if (!doafi[afi]) + continue; + if (yes) { + if (bgp->vpn_policy[afi].import_redirect_rtlist) + ecommunity_free( + &bgp->vpn_policy[afi] + .import_redirect_rtlist); + bgp->vpn_policy[afi].import_redirect_rtlist = + ecommunity_dup(ecom); + } else { + if (bgp->vpn_policy[afi].import_redirect_rtlist) + ecommunity_free( + &bgp->vpn_policy[afi] + .import_redirect_rtlist); + bgp->vpn_policy[afi].import_redirect_rtlist = NULL; + } + } + if (ecom) + ecommunity_free(&ecom); + + return CMD_SUCCESS; +} + DEFUN_NOSH (address_family_ipv4_safi, address_family_ipv4_safi_cmd, "address-family ipv4 []", @@ -11685,7 +11742,16 @@ void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, bgp->vpn_policy[afi] .rmap_name[BGP_VPN_POLICY_DIR_TOVPN]); } + if (bgp->vpn_policy[afi].import_redirect_rtlist) { + char *b = ecommunity_ecom2str( + bgp->vpn_policy[afi] + .import_redirect_rtlist, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, "%*srt redirect import %s\n", indent, "", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } } @@ -12897,6 +12963,9 @@ void bgp_vty_init(void) install_element(BGP_IPV4_NODE, &af_route_map_vpn_imexport_cmd); install_element(BGP_IPV6_NODE, &af_route_map_vpn_imexport_cmd); + install_element(BGP_IPV4_NODE, &af_routetarget_import_cmd); + install_element(BGP_IPV6_NODE, &af_routetarget_import_cmd); + install_element(BGP_IPV4_NODE, &af_no_rd_vpn_export_cmd); install_element(BGP_IPV6_NODE, &af_no_rd_vpn_export_cmd); install_element(BGP_IPV4_NODE, &af_no_label_vpn_export_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d103584594..c1c1ee07df 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3272,6 +3272,14 @@ int bgp_delete(struct bgp *bgp) #endif bgp_cleanup_routes(bgp); + for (afi = 0; afi < AFI_MAX; ++afi) { + if (!bgp->vpn_policy[afi].import_redirect_rtlist) + continue; + ecommunity_free( + &bgp->vpn_policy[afi] + .import_redirect_rtlist); + bgp->vpn_policy[afi].import_redirect_rtlist = NULL; + } /* Remove visibility via the master list - there may however still be * routes to be processed still referencing the struct bgp. */ diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 79fe8c8c3b..d4c2a1aba9 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -465,6 +465,7 @@ struct bgp { /* vpn-policy */ struct { struct ecommunity *rtlist[BGP_VPN_POLICY_DIR_MAX]; + struct ecommunity *import_redirect_rtlist; char *rmap_name[BGP_VPN_POLICY_DIR_MAX]; struct route_map *rmap[BGP_VPN_POLICY_DIR_MAX];