bgpd: add an API to get incoming VRF from a RT

This commit is relying on bgp vpn-policy. It is needed to configure
several bgp vrf instances, and in each of the bgp instance, configure
the following command under address-family ipv4 unicast node:
[no] rt redirect import RTLIST

Then, a function is provided, that will parse the BGP instances.
The incoming ecommunity will be compared with the configured rt redirect
import ecommunity list, and return the VRF first instance of the matching
route target.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2018-01-23 18:09:12 +01:00
parent 6a32d26634
commit 301ad80a99
5 changed files with 99 additions and 0 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -6588,6 +6588,63 @@ DEFPY (bgp_imexport_vpn,
return CMD_SUCCESS;
}
DEFPY (af_routetarget_import,
af_routetarget_import_cmd,
"[no] <rt|route-target> 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 [<unicast|multicast|vpn|labeled-unicast>]",
@ -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);

View File

@ -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.
*/

View File

@ -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];