summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_evpn_vty.c
diff options
context:
space:
mode:
authorStephen Worley <sworley@nvidia.com>2021-02-25 22:27:07 +0100
committerStephen Worley <sworley@nvidia.com>2022-08-23 18:41:25 +0200
commit58d8948cf43073ee0ea617ecadf5518372fef12c (patch)
tree32e67746767a009add2f0df29320df333decb2e1 /bgpd/bgp_evpn_vty.c
parentbgpd: abstract ecom into struct for l3 route targets (diff)
downloadfrr-58d8948cf43073ee0ea617ecadf5518372fef12c.tar.xz
frr-58d8948cf43073ee0ea617ecadf5518372fef12c.zip
bgpd: evpn L3 RT auto config and wildcard implementation
Implement forcing L3 auto derivation via configs even when manually RTs are set. This will allow both to coexist in BGP RTs. Without using auto config command, it will remove auto derived RTs when you manually configure your own. To allow both, use the auto command ond import/export/both. Implement '*' wildcard import L3 RTs so we can import a route into any AS. This is necessary to avoid a user from having to configure an L3 RT for every AS they care to import evpn route from. Signed-off-by: Stephen Worley <sworley@nvidia.com>
Diffstat (limited to 'bgpd/bgp_evpn_vty.c')
-rw-r--r--bgpd/bgp_evpn_vty.c161
1 files changed, 146 insertions, 15 deletions
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 500fa6ea8..13a63f153 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -5852,13 +5852,15 @@ DEFUN (show_bgp_vrf_l3vni_info,
return CMD_SUCCESS;
}
-static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
+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);
+ bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
+ is_wildcard);
else
return -1;
} else {
@@ -5897,12 +5899,37 @@ static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
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;
@@ -5912,7 +5939,7 @@ static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
ecommunity_str(ecom);
if (is_add) {
- if (add_rt(bgp, ecom, is_import) != 0) {
+ 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);
@@ -5943,7 +5970,7 @@ DEFUN (bgp_evpn_vrf_rt,
"import and export\n"
"import\n"
"export\n"
- "Space separated route target list (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;
@@ -5964,6 +5991,11 @@ DEFUN (bgp_evpn_vrf_rt,
return CMD_WARNING_CONFIG_FAILED;
}
+ if (strmatch(argv[2]->arg, "auto")) {
+ vty_out(vty, "%% `auto` cannot be configured via list\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
/* Add/update the import route-target */
if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
@@ -5989,9 +6021,30 @@ DEFUN (bgp_evpn_vrf_rt_auto,
"export\n"
"Automatically derive route target\n")
{
- // TODO: auto
- vty_out(vty, "AUTO TODO\n");
- return CMD_WARNING_CONFIG_FAILED;
+ struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+ int rt_type;
+
+ if (!bgp)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!strcmp(argv[1]->arg, "import"))
+ rt_type = RT_TYPE_IMPORT;
+ else if (!strcmp(argv[1]->arg, "export"))
+ rt_type = RT_TYPE_EXPORT;
+ else if (!strcmp(argv[1]->arg, "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,
@@ -6010,7 +6063,7 @@ DEFUN (no_bgp_evpn_vrf_rt,
int rt_type;
if (!bgp)
- return CMD_WARNING;
+ return CMD_WARNING_CONFIG_FAILED;
if (!strcmp(argv[2]->arg, "import"))
rt_type = RT_TYPE_IMPORT;
@@ -6023,24 +6076,29 @@ DEFUN (no_bgp_evpn_vrf_rt,
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;
}
}
@@ -6069,9 +6127,51 @@ DEFUN (no_bgp_evpn_vrf_rt_auto,
"export\n"
"Automatically derive route target\n")
{
- // TODO: auto
- vty_out(vty, "AUTO TODO\n");
- return CMD_WARNING_CONFIG_FAILED;
+ struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+ int rt_type;
+
+ if (!bgp)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!strcmp(argv[2]->arg, "import"))
+ rt_type = RT_TYPE_IMPORT;
+ else if (!strcmp(argv[2]->arg, "export"))
+ rt_type = RT_TYPE_EXPORT;
+ else if (!strcmp(argv[2]->arg, "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_IMPORT) {
+ if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
+ vty_out(vty,
+ "%% Import AUTO RT is not configured for this VRF\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else if (rt_type == RT_TYPE_EXPORT) {
+ if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
+ vty_out(vty,
+ "%% Export AUTO RT is not configured for this VRF\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else if (rt_type == RT_TYPE_BOTH) {
+ 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,
+ "%% Import/Export AUTO RT is not configured for this VRF\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ 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;
}
DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
@@ -6559,13 +6659,36 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
l3rt)) {
+
+ if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
+ continue;
+
ecom_str = ecommunity_ecom2str(
l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
- vty_out(vty, " route-target import %s\n", ecom_str);
+
+ 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;
@@ -6574,12 +6697,20 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
l3rt)) {
+
+ if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
+ continue;
+
ecom_str = ecommunity_ecom2str(
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)