diff options
Diffstat (limited to 'bgpd/bgp_evpn_vty.c')
-rw-r--r-- | bgpd/bgp_evpn_vty.c | 425 |
1 files changed, 324 insertions, 101 deletions
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 5ad5cf8bf..f920a783b 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -373,7 +373,7 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf, char buf1[INET6_ADDRSTRLEN]; char *ecom_str; struct listnode *node, *nnode; - struct ecommunity *ecom; + struct vrf_route_target *l3rt; json_object *json_import_rtl = NULL; json_object *json_export_rtl = NULL; char buf2[ETHER_ADDR_STRLEN]; @@ -431,8 +431,8 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf, if (!json) vty_out(vty, " Import Route Target:\n"); - for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, ecom)) { - ecom_str = ecommunity_ecom2str(ecom, + for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, l3rt)) { + ecom_str = ecommunity_ecom2str(l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); if (json) @@ -449,8 +449,8 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf, else vty_out(vty, " Export Route Target:\n"); - for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, ecom)) { - ecom_str = ecommunity_ecom2str(ecom, + for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, l3rt)) { + ecom_str = ecommunity_ecom2str(l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); if (json) @@ -913,7 +913,7 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp, char rt_buf[25]; char *ecom_str; struct listnode *node, *nnode; - struct ecommunity *ecom; + struct vrf_route_target *l3rt; if (!bgp->l3vni) return; @@ -954,8 +954,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp, &bgp->vrf_prd); } - for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) { - ecom_str = ecommunity_ecom2str(ecom, + for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, l3rt)) { + ecom_str = ecommunity_ecom2str(l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); if (json) { @@ -982,8 +982,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp, if (json) json_object_object_add(json_vni, "importRTs", json_import_rtl); - for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, ecom)) { - ecom_str = ecommunity_ecom2str(ecom, + for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, l3rt)) { + ecom_str = ecommunity_ecom2str(l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); if (json) { @@ -1984,12 +1984,12 @@ DEFUN(no_evpnrt5_network, static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn) { - evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl); + evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl, false); } static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn) { - evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl); + evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl, false); } /* @@ -3980,11 +3980,13 @@ DEFUN (bgp_evpn_advertise_type5, DEFUN (no_bgp_evpn_advertise_type5, no_bgp_evpn_advertise_type5_cmd, - "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR, + "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]", NO_STR "Advertise prefix routes\n" BGP_AFI_HELP_STR - BGP_SAFI_HELP_STR) + BGP_SAFI_HELP_STR + "route-map for filtering specific routes\n" + "Name of the route map\n") { struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */ int idx_afi = 0; @@ -5654,18 +5656,35 @@ DEFUN (no_bgp_evpn_vni_rd_without_val, * Loop over all extended-communities in the route-target list rtl and * return 1 if we find ecomtarget */ -static int bgp_evpn_rt_matches_existing(struct list *rtl, - struct ecommunity *ecomtarget) +static bool bgp_evpn_rt_matches_existing(struct list *rtl, + struct ecommunity *ecomtarget) { - struct listnode *node, *nnode; + struct listnode *node; struct ecommunity *ecom; - for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) { + for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) { if (ecommunity_match(ecom, ecomtarget)) - return 1; + return true; } - return 0; + return false; +} + +/* + * L3 RT version of above. + */ +static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl, + struct ecommunity *ecomtarget) +{ + struct listnode *node; + struct vrf_route_target *l3rt; + + for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) { + if (ecommunity_match(l3rt->ecom, ecomtarget)) + return true; + } + + return false; } /* display L3VNI related info for a VRF instance */ @@ -5685,7 +5704,7 @@ DEFUN (show_bgp_vrf_l3vni_info, struct bgp *bgp = NULL; struct listnode *node = NULL; struct bgpevpn *vpn = NULL; - struct ecommunity *ecom = NULL; + struct vrf_route_target *l3rt; json_object *json = NULL; json_object *json_vnis = NULL; json_object *json_export_rts = NULL; @@ -5735,13 +5754,13 @@ DEFUN (show_bgp_vrf_l3vni_info, vty_out(vty, "\n"); vty_out(vty, " Export-RTs:\n"); vty_out(vty, " "); - for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom)) - vty_out(vty, "%s ", ecommunity_str(ecom)); + for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt)) + vty_out(vty, "%s ", ecommunity_str(l3rt->ecom)); vty_out(vty, "\n"); vty_out(vty, " Import-RTs:\n"); vty_out(vty, " "); - for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom)) - vty_out(vty, "%s ", ecommunity_str(ecom)); + for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt)) + vty_out(vty, "%s ", ecommunity_str(l3rt->ecom)); vty_out(vty, "\n"); vty_out(vty, " RD: %pRD\n", &bgp->vrf_prd); } else { @@ -5765,17 +5784,19 @@ DEFUN (show_bgp_vrf_l3vni_info, json_object_object_add(json, "l2vnis", json_vnis); /* export rts */ - for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom)) + for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt)) json_object_array_add( json_export_rts, - json_object_new_string(ecommunity_str(ecom))); + json_object_new_string( + ecommunity_str(l3rt->ecom))); json_object_object_add(json, "export-rts", json_export_rts); /* import rts */ - for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom)) + for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt)) json_object_array_add( json_import_rts, - json_object_new_string(ecommunity_str(ecom))); + json_object_new_string( + ecommunity_str(l3rt->ecom))); json_object_object_add(json, "import-rts", json_import_rts); json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd); } @@ -5785,22 +5806,133 @@ DEFUN (show_bgp_vrf_l3vni_info, return CMD_SUCCESS; } +static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import, + bool is_wildcard) +{ + /* Do nothing if we already have this route-target */ + if (is_import) { + if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl, + ecom)) + bgp_evpn_configure_import_rt_for_vrf(bgp, ecom, + is_wildcard); + else + return -1; + } else { + if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl, + ecom)) + bgp_evpn_configure_export_rt_for_vrf(bgp, ecom); + else + return -1; + } + + return 0; +} + +static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import) +{ + /* Verify we already have this route-target */ + if (is_import) { + if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl, + ecom)) + return -1; + + bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom); + } else { + if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl, + ecom)) + return -1; + + bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom); + } + + return 0; +} + +static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc, + struct cmd_token **argv, int rt_idx, bool is_add, + bool is_import) +{ + int ret = CMD_SUCCESS; + bool is_wildcard = false; + struct ecommunity *ecom = NULL; + + for (int i = rt_idx; i < argc; i++) { + is_wildcard = false; + + /* + * Special handling for wildcard '*' here. + * + * Let's just convert it to 0 here so we dont have to modify + * the ecommunity parser. + */ + if ((argv[i]->arg)[0] == '*') { + if (!is_import) { + vty_out(vty, + "%% Wildcard '*' only applicable for import\n"); + ret = CMD_WARNING; + continue; + } + + (argv[i]->arg)[0] = '0'; + is_wildcard = true; + } + + ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET, + 0); + + /* Put it back as was */ + if (is_wildcard) + (argv[i]->arg)[0] = '*'; + + if (!ecom) { + vty_out(vty, "%% Malformed Route Target list\n"); + ret = CMD_WARNING; + continue; + } + + ecommunity_str(ecom); + + if (is_add) { + if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) { + vty_out(vty, + "%% RT specified already configured for this VRF: %s\n", + argv[i]->arg); + ecommunity_free(&ecom); + ret = CMD_WARNING; + } + + } else { + if (del_rt(bgp, ecom, is_import) != 0) { + vty_out(vty, + "%% RT specified does not match configuration for this VRF: %s\n", + argv[i]->arg); + ret = CMD_WARNING; + } + + ecommunity_free(&ecom); + } + } + + return ret; +} + /* import/export rt for l3vni-vrf */ DEFUN (bgp_evpn_vrf_rt, bgp_evpn_vrf_rt_cmd, - "route-target <both|import|export> RT", + "route-target <both|import|export> RTLIST...", "Route Target\n" "import and export\n" "import\n" "export\n" - "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n") { + int ret = CMD_SUCCESS; + int tmp_ret = CMD_SUCCESS; int rt_type; struct bgp *bgp = VTY_GET_CONTEXT(bgp); - struct ecommunity *ecomadd = NULL; if (!bgp) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; if (!strcmp(argv[1]->arg, "import")) rt_type = RT_TYPE_IMPORT; @@ -5810,49 +5942,82 @@ DEFUN (bgp_evpn_vrf_rt, rt_type = RT_TYPE_BOTH; else { vty_out(vty, "%% Invalid Route Target type\n"); - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; } - ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0); - if (!ecomadd) { - vty_out(vty, "%% Malformed Route Target list\n"); - return CMD_WARNING; + if (strmatch(argv[2]->arg, "auto")) { + vty_out(vty, "%% `auto` cannot be configured via list\n"); + return CMD_WARNING_CONFIG_FAILED; } - ecommunity_str(ecomadd); /* Add/update the import route-target */ - if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) { - /* Do nothing if we already have this import route-target */ - if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd)) - bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd); - } + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) + tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true); - /* Add/update the export route-target */ - if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) { - /* Do nothing if we already have this export route-target */ - if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd)) - bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd); + if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS) + ret = tmp_ret; + + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) + tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false); + + if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS) + ret = tmp_ret; + + return ret; +} + +DEFPY (bgp_evpn_vrf_rt_auto, + bgp_evpn_vrf_rt_auto_cmd, + "route-target <both|import|export>$type auto", + "Route Target\n" + "import and export\n" + "import\n" + "export\n" + "Automatically derive route target\n") +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + int rt_type; + + if (!bgp) + return CMD_WARNING_CONFIG_FAILED; + + if (strmatch(type, "import")) + rt_type = RT_TYPE_IMPORT; + else if (strmatch(type, "export")) + rt_type = RT_TYPE_EXPORT; + else if (strmatch(type, "both")) + rt_type = RT_TYPE_BOTH; + else { + vty_out(vty, "%% Invalid Route Target type\n"); + return CMD_WARNING_CONFIG_FAILED; } + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) + bgp_evpn_configure_import_auto_rt_for_vrf(bgp); + + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) + bgp_evpn_configure_export_auto_rt_for_vrf(bgp); + return CMD_SUCCESS; } DEFUN (no_bgp_evpn_vrf_rt, no_bgp_evpn_vrf_rt_cmd, - "no route-target <both|import|export> RT", + "no route-target <both|import|export> RTLIST...", NO_STR "Route Target\n" "import and export\n" "import\n" "export\n" - EVPN_ASN_IP_HELP_STR) + "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { struct bgp *bgp = VTY_GET_CONTEXT(bgp); - int rt_type, found_ecomdel; - struct ecommunity *ecomdel = NULL; + int ret = CMD_SUCCESS; + int tmp_ret = CMD_SUCCESS; + int rt_type; if (!bgp) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; if (!strcmp(argv[2]->arg, "import")) rt_type = RT_TYPE_IMPORT; @@ -5862,79 +6027,104 @@ DEFUN (no_bgp_evpn_vrf_rt, rt_type = RT_TYPE_BOTH; else { vty_out(vty, "%% Invalid Route Target type\n"); - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; + } + + if (!strcmp(argv[3]->arg, "auto")) { + vty_out(vty, "%% `auto` cannot be unconfigured via list\n"); + return CMD_WARNING_CONFIG_FAILED; } if (rt_type == RT_TYPE_IMPORT) { if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) { vty_out(vty, "%% Import RT is not configured for this VRF\n"); - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; } } else if (rt_type == RT_TYPE_EXPORT) { if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) { vty_out(vty, "%% Export RT is not configured for this VRF\n"); - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; } } else if (rt_type == RT_TYPE_BOTH) { if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD) && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) { vty_out(vty, "%% Import/Export RT is not configured for this VRF\n"); - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; } } - ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0); - if (!ecomdel) { - vty_out(vty, "%% Malformed Route Target list\n"); - return CMD_WARNING; + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) + tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true); + + if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS) + ret = tmp_ret; + + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) + tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false); + + if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS) + ret = tmp_ret; + + return ret; +} + +DEFPY (no_bgp_evpn_vrf_rt_auto, + no_bgp_evpn_vrf_rt_auto_cmd, + "no route-target <both|import|export>$type auto", + NO_STR + "Route Target\n" + "import and export\n" + "import\n" + "export\n" + "Automatically derive route target\n") +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + int rt_type; + + if (!bgp) + return CMD_WARNING_CONFIG_FAILED; + + if (strmatch(type, "import")) + rt_type = RT_TYPE_IMPORT; + else if (strmatch(type, "export")) + rt_type = RT_TYPE_EXPORT; + else if (strmatch(type, "both")) + rt_type = RT_TYPE_BOTH; + else { + vty_out(vty, "%% Invalid Route Target type\n"); + return CMD_WARNING_CONFIG_FAILED; } - ecommunity_str(ecomdel); if (rt_type == RT_TYPE_IMPORT) { - if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, - ecomdel)) { - ecommunity_free(&ecomdel); + if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) { vty_out(vty, - "%% RT specified does not match configuration for this VRF\n"); - return CMD_WARNING; + "%% Import AUTO RT is not configured for this VRF\n"); + return CMD_WARNING_CONFIG_FAILED; } - bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel); } else if (rt_type == RT_TYPE_EXPORT) { - if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, - ecomdel)) { - ecommunity_free(&ecomdel); + if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) { vty_out(vty, - "%% RT specified does not match configuration for this VRF\n"); - return CMD_WARNING; + "%% Export AUTO RT is not configured for this VRF\n"); + return CMD_WARNING_CONFIG_FAILED; } - bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel); } else if (rt_type == RT_TYPE_BOTH) { - found_ecomdel = 0; - - if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, - ecomdel)) { - bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel); - found_ecomdel = 1; - } - - if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, - ecomdel)) { - bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel); - found_ecomdel = 1; - } - - if (!found_ecomdel) { - ecommunity_free(&ecomdel); + if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) && + !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) { vty_out(vty, - "%% RT specified does not match configuration for this VRF\n"); - return CMD_WARNING; + "%% Import/Export AUTO RT is not configured for this VRF\n"); + return CMD_WARNING_CONFIG_FAILED; } } - ecommunity_free(&ecomdel); + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) + bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp); + + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) + bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp); + return CMD_SUCCESS; } @@ -6421,31 +6611,62 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) { char *ecom_str; struct listnode *node, *nnode; - struct ecommunity *ecom; + struct vrf_route_target *l3rt; for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, - ecom)) { + l3rt)) { + + if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO)) + continue; + ecom_str = ecommunity_ecom2str( - ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out(vty, " route-target import %s\n", ecom_str); + l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + + if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) { + char *vni_str = NULL; + + vni_str = strchr(ecom_str, ':') + 1; + + if (!vni_str) + continue; /* This should never happen */ + + vty_out(vty, " route-target import *:%s\n", + vni_str); + + } else + vty_out(vty, " route-target import %s\n", + ecom_str); + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); } } + /* import route-target auto */ + if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) + vty_out(vty, " route-target import auto\n"); + /* export route-target */ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) { char *ecom_str; struct listnode *node, *nnode; - struct ecommunity *ecom; + struct vrf_route_target *l3rt; for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, - ecom)) { + l3rt)) { + + if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO)) + continue; + ecom_str = ecommunity_ecom2str( - ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); vty_out(vty, " route-target export %s\n", ecom_str); XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); } } + + /* export route-target auto */ + if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) + vty_out(vty, " route-target export auto\n"); } void bgp_ethernetvpn_init(void) @@ -6547,6 +6768,8 @@ void bgp_ethernetvpn_init(void) install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd); + install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd); + install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd); |