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];
json_object_int_add(json, "vni", bgp_vrf->l3vni);
json_object_string_add(json, "type", "L3");
json_object_string_add(json, "inKernel", "True");
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd);
json_object_string_addf(json, "originatorIp", "%pI4",
&bgp_vrf->originator_ip);
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
vty_out(vty, " Type: %s\n", "L3");
vty_out(vty, " Tenant VRF: %s\n",
vrf_id_to_name(bgp_vrf->vrf_id));
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
+ vty_out(vty, " RD: %pRD\n", &bgp_vrf->vrf_prd);
vty_out(vty, " Originator IP: %pI4\n",
&bgp_vrf->originator_ip);
vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
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)
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)
static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
{
- char buf1[RD_ADDRSTRLEN];
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
json_object_string_add(json, "type", "L2");
json_object_string_add(json, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ json_object_string_addf(json, "rd", "%pRD", &vpn->prd);
json_object_string_addf(json, "originatorIp", "%pI4",
&vpn->originator_ip);
json_object_string_addf(json, "mcastGroup", "%pI4",
vty_out(vty, " Type: %s\n", "L2");
vty_out(vty, " Tenant-Vrf: %s\n",
vrf_id_to_name(vpn->tenant_vrf_id));
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ vty_out(vty, " RD: %pRD\n", &vpn->prd);
vty_out(vty, " Originator IP: %pI4\n", &vpn->originator_ip);
vty_out(vty, " Mcast group: %pI4\n", &vpn->mcast_grp);
if (!vpn->advertise_gw_macip &&
char rt_buf[25];
char *ecom_str;
struct listnode *node, *nnode;
- struct ecommunity *ecom;
+ struct vrf_route_target *l3rt;
if (!bgp->l3vni)
return;
json_object_string_add(json_vni, "inKernel", "True");
json_object_string_addf(json_vni, "originatorIp", "%pI4",
&bgp->originator_ip);
- json_object_string_add(
- json_vni, "rd",
- prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
+ json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd);
json_object_string_add(json_vni, "advertiseGatewayMacip",
"n/a");
json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
json_vni, "rmac",
prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
} else {
- vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
- prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
+ vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, bgp->l3vni, "L3",
+ &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) {
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) {
json_object *json_export_rtl = NULL;
struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
char buf1[10];
- char buf2[RD_ADDRSTRLEN];
char rt_buf[25];
char *ecom_str;
struct listnode *node, *nnode;
json_object_string_add(json_vni, "type", "L2");
json_object_string_add(json_vni, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_add(
- json_vni, "rd",
- prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
+ json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd);
json_object_string_addf(json_vni, "originatorIp", "%pI4",
&vpn->originator_ip);
json_object_string_addf(json_vni, "mcastGroup", "%pI4",
json_object_string_add(json_vni, "advertiseSviMacIp",
"Disabled");
} else {
- vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
- prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+ vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, vpn->vni, "L2",
+ &vpn->prd);
}
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
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);
}
/*
afi_t afi;
safi_t safi;
uint32_t prefix_cnt, path_cnt;
- char rd_str[RD_ADDRSTRLEN];
json_object *json_rd = NULL;
int add_rd_to_json = 0;
safi = SAFI_EVPN;
prefix_cnt = path_cnt = 0;
- prefix_rd2str(prd, rd_str, sizeof(rd_str));
-
rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
if (!rd_dest)
return;
if (json) {
json_rd = json_object_new_object();
- json_object_string_add(json_rd, "rd", rd_str);
+ json_object_string_addf(json_rd, "rd", "%pRD", prd);
}
bgp_dest_unlock_node(rd_dest);
if (json) {
if (add_rd_to_json)
- json_object_object_add(json, rd_str, json_rd);
+ json_object_object_addf(json, json_rd, "%pRD", prd);
else {
json_object_free(json_rd);
json_rd = NULL;
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
{
- char buf1[RD_ADDRSTRLEN];
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
if (is_vni_configured(vpn)) {
vty_out(vty, " vni %d\n", vpn->vni);
if (is_rd_configured(vpn))
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ vty_out(vty, " rd %pRD\n", &vpn->prd);
if (is_import_rt_configured(vpn)) {
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
}
}
-#ifndef VTYSH_EXTRACT_PL
#include "bgpd/bgp_evpn_vty_clippy.c"
-#endif
DEFPY(bgp_evpn_flood_control,
bgp_evpn_flood_control_cmd,
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;
* 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 */
JSON_STR)
{
char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
int idx_vrf = 3;
const char *name = NULL;
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;
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: %s\n",
- prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
+ vty_out(vty, " RD: %pRD\n", &bgp->vrf_prd);
} else {
json_object_string_add(json, "vrf", name);
json_object_string_addf(json, "local-ip", "%pI4",
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_add(
- json, "rd",
- prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd);
}
if (uj)
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;
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;
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;
}
if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match EAD-ES RT configuration\n");
return CMD_WARNING;
if (rt_type == RT_TYPE_IMPORT) {
if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
} else if (rt_type == RT_TYPE_EXPORT) {
if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
}
if (!found_ecomdel) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
{
- char buf1[RD_ADDRSTRLEN];
char buf2[INET6_ADDRSTRLEN];
if (bgp->advertise_all_vni)
}
}
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
+ vty_out(vty, " rd %pRD\n", &bgp->vrf_prd);
/* import route-target */
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, ':');
+
+ if (!vni_str)
+ continue; /* This should never happen */
+
+ /* Move pointer to vni */
+ vni_str += 1;
+
+ 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)
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);