+// SPDX-License-Identifier: GPL-2.0-or-later
/* Ethernet-VPN Packet and vty Processing File
* Copyright (C) 2017 6WIND
*
* This file is part of FRRouting
- *
- * FRRouting is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * FRRouting is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
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_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd);
+ json_object_string_addf(json, "rd",
+ BGP_RD_AS_FORMAT(bgp_vrf->asnotation),
+ &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: %pRD\n", &bgp_vrf->vrf_prd);
+ vty_out(vty, " RD: ");
+ vty_out(vty, BGP_RD_AS_FORMAT(bgp_vrf->asnotation),
+ &bgp_vrf->vrf_prd);
+ vty_out(vty, "\n");
vty_out(vty, " Originator IP: %pI4\n",
&bgp_vrf->originator_ip);
vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
json_object *json_import_rtl = NULL;
json_object *json_export_rtl = NULL;
struct bgp *bgp_evpn;
+ enum asnotation_mode asnotation;
bgp_evpn = bgp_get_evpn();
+ asnotation = bgp_get_asnotation(bgp_evpn);
if (json) {
json_import_rtl = json_object_new_array();
json_object_string_add(json, "type", "L2");
json_object_string_add(json, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_addf(json, "rd", "%pRD", &vpn->prd);
+ json_object_string_addf(
+ json, "rd", BGP_RD_AS_FORMAT(asnotation), &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: %pRD\n", &vpn->prd);
+ vty_out(vty, " RD: ");
+ vty_out(vty, BGP_RD_AS_FORMAT(asnotation), &vpn->prd);
+ vty_out(vty, "\n");
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 &&
json_object_string_add(json_vni, "inKernel", "True");
json_object_string_addf(json_vni, "originatorIp", "%pI4",
&bgp->originator_ip);
- json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd);
+ json_object_string_addf(json_vni, "rd",
+ BGP_RD_AS_FORMAT(bgp->asnotation),
+ &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 %-21pRD", buf1, bgp->l3vni, "L3",
+ vty_out(vty, "%-1s %-10u %-4s ", buf1, bgp->l3vni, "L3");
+ vty_out(vty, BGP_RD_AS_FORMAT_SPACE(bgp->asnotation),
&bgp->vrf_prd);
}
struct listnode *node, *nnode;
struct ecommunity *ecom;
struct bgp *bgp_evpn;
+ enum asnotation_mode asnotation;
vty = args[0];
json = args[1];
bgp_evpn = bgp_get_evpn();
+ asnotation = bgp_get_asnotation(bgp_evpn);
if (json) {
json_vni = json_object_new_object();
json_object_string_add(json_vni, "type", "L2");
json_object_string_add(json_vni, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd);
+ json_object_string_addf(json_vni, "rd",
+ BGP_RD_AS_FORMAT(asnotation),
+ &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 %-21pRD", buf1, vpn->vni, "L2",
- &vpn->prd);
+ vty_out(vty, "%-1s %-10u %-4s ", buf1, vpn->vni, "L2");
+ vty_out(vty, BGP_RD_AS_FORMAT_SPACE(asnotation), &vpn->prd);
}
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
json,
"defaultLocPrf",
bgp->default_local_pref);
- json_object_int_add(
- json, "localAS",
- bgp->as);
+ asn_asn2json(json, "localAS",
+ bgp->as,
+ bgp->asnotation);
} else {
if (option == SHOW_DISPLAY_TAGS)
vty_out(vty,
/*
* Configure RD for VRF
*/
-static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
+static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd,
+ const char *rd_pretty)
{
/* If we have already advertise type-5 routes with a diffrent RD, we
* have to delete and withdraw them firs
/* update RD */
memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
+ bgp_vrf->vrf_prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
/* We have a new RD for VRF.
/* fall back to default RD */
bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
-
+ if (bgp_vrf->vrf_prd_pretty)
+ XFREE(MTYPE_BGP, bgp_vrf->vrf_prd_pretty);
/* We have a new RD for VRF.
* Advertise all type-5 routes again with the new RD
*/
* Configure RD for a VNI (vty handler)
*/
static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_rd *rd)
+ struct prefix_rd *rd, const char *rd_pretty)
{
/* If the VNI is "live", we need to delete and withdraw this VNI's
* local routes with the prior RD first. Then, after updating RD,
/* update RD */
memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
+ vpn->prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
if (is_vni_live(vpn))
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
- NULL, afi, safi, json);
+ NULL, afi, safi, json, false);
/* Display each path for this prefix. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL,
- afi, safi, json);
+ afi, safi, json, false);
evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
- prd, afi, safi, json);
+ prd, afi, safi, json, false);
if (json)
json_paths = json_object_new_array();
if (json) {
json_rd = json_object_new_object();
- json_object_string_addf(json_rd, "rd", "%pRD", prd);
+ json_object_string_addf(json_rd, "rd",
+ BGP_RD_AS_FORMAT(bgp->asnotation), prd);
}
bgp_dest_unlock_node(rd_dest);
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(
vty, bgp, dest, bgp_dest_get_prefix(dest), prd,
- afi, safi, json_prefix);
+ afi, safi, json_prefix, false);
prefix_cnt++;
}
if (json) {
if (add_rd_to_json)
- json_object_object_addf(json, json_rd, "%pRD", prd);
+ json_object_object_addf(
+ json, json_rd,
+ BGP_RD_AS_FORMAT(bgp->asnotation), prd);
else {
json_object_free(json_rd);
json_rd = NULL;
continue;
prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
- sizeof(rd_str));
+ sizeof(rd_str), bgp->asnotation);
/* Construct an RT-2 from the user-supplied mac(ip),
* then search the l2vpn evpn table for it.
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(
vty, bgp, dest, p, (struct prefix_rd *)rd_destp,
- AFI_L2VPN, SAFI_EVPN, json_prefix);
+ AFI_L2VPN, SAFI_EVPN, json_prefix, false);
/* For EVPN, the prefix is displayed for each path (to
* fit in with code that already exists).
* If 'type' is non-zero, only routes matching that type are shown.
*/
static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
- json_object *json, int detail)
+ json_object *json, int detail, bool self_orig)
{
struct bgp_dest *rd_dest;
struct bgp_table *table;
tbl_ver = table->version;
prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
- sizeof(rd_str));
+ sizeof(rd_str), bgp->asnotation);
if (json)
json_rd = json_object_new_object();
pi = bgp_dest_get_bgp_path_info(dest);
if (pi) {
+ if (self_orig && (pi->peer != bgp->peer_self))
+ continue;
+
/* Overall header/legend displayed once. */
if (header) {
bgp_evpn_show_route_header(vty, bgp,
vty, bgp, dest,
bgp_dest_get_prefix(dest),
(struct prefix_rd *)rd_destp, AFI_L2VPN,
- SAFI_EVPN, json_prefix);
+ SAFI_EVPN, json_prefix, false);
/* For EVPN, the prefix is displayed for each path (to
* fit in
if (use_json)
json = json_object_new_object();
- evpn_show_all_routes(vty, bgp, type, json, detail);
+ evpn_show_all_routes(vty, bgp, type, json, detail, false);
if (use_json)
vty_json(vty, json);
if (is_vni_configured(vpn)) {
vty_out(vty, " vni %u\n", vpn->vni);
if (is_rd_configured(vpn))
- vty_out(vty, " rd %pRD\n", &vpn->prd);
+ vty_out(vty, " rd %s\n", vpn->prd_pretty);
if (is_import_rt_configured(vpn)) {
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
*/
DEFUN(show_bgp_l2vpn_evpn_route,
show_bgp_l2vpn_evpn_route_cmd,
- "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] [json]",
+ "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] ["BGP_SELF_ORIG_CMD_STR"] [json]",
SHOW_STR
BGP_STR
L2VPN_HELP_STR
"Display Detailed Information\n"
EVPN_TYPE_HELP_STR
EVPN_TYPE_ALL_LIST_HELP_STR
+ BGP_SELF_ORIG_HELP_STR
JSON_STR)
{
struct bgp *bgp;
int detail = 0;
int type = 0;
bool uj = false;
+ int arg_idx = 0;
+ bool self_orig = false;
json_object *json = NULL;
uj = use_json(argc, argv);
if (argv_find(argv, argc, "detail", &detail))
detail = 1;
- evpn_show_all_routes(vty, bgp, type, json, detail);
+ if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &arg_idx))
+ self_orig = true;
- if (uj) {
- if (detail) {
- vty_out(vty, "%s\n", json_object_to_json_string(json));
- json_object_free(json);
- } else {
- vty_json(vty, json);
- }
- }
+ evpn_show_all_routes(vty, bgp, type, json, detail, self_orig);
+
+ /*
+ * This is an extremely expensive operation at scale
+ * and as such we need to save as much time as is
+ * possible.
+ */
+ if (uj)
+ vty_json_no_pretty(vty, json);
return CMD_SUCCESS;
}
return CMD_WARNING;
if (rd_all)
- evpn_show_all_routes(vty, bgp, type, json, 1);
+ evpn_show_all_routes(vty, bgp, type, json, 1, false);
else
evpn_show_route_rd(vty, bgp, &prd, type, json);
return CMD_SUCCESS;
/* Configure or update the RD. */
- evpn_configure_vrf_rd(bgp_vrf, &prd);
+ evpn_configure_vrf_rd(bgp_vrf, &prd, argv[1]->arg);
return CMD_SUCCESS;
}
return CMD_SUCCESS;
/* Configure or update the RD. */
- evpn_configure_rd(bgp, vpn, &prd);
+ evpn_configure_rd(bgp, vpn, &prd, argv[1]->arg);
return CMD_SUCCESS;
}
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);
+ vty_out(vty, " RD: ");
+ vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vrf_prd);
+ vty_out(vty, "\n");
} else {
json_object_string_add(json, "vrf", name);
json_object_string_addf(json, "local-ip", "%pI4",
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);
+ json_object_string_addf(json, "rd",
+ BGP_RD_AS_FORMAT(bgp->asnotation),
+ &bgp->vrf_prd);
}
if (uj)
return CMD_WARNING;
}
- ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
- if (!ecomadd) {
- vty_out(vty, "%% Malformed Route Target list\n");
- return CMD_WARNING;
- }
- ecommunity_str(ecomadd);
-
/* Add/update the import route-target */
if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
+ /* Note that first of the two RTs is created for "both" type */
+ ecomadd = ecommunity_str2com(argv[2]->arg,
+ ECOMMUNITY_ROUTE_TARGET, 0);
+ if (!ecomadd) {
+ vty_out(vty, "%% Malformed Route Target list\n");
+ return CMD_WARNING;
+ }
+ ecommunity_str(ecomadd);
+
/* Do nothing if we already have this import route-target */
if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
evpn_configure_import_rt(bgp, vpn, ecomadd);
/* Add/update the export route-target */
if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
+ /* Note that second of the two RTs is created for "both" type */
+ ecomadd = ecommunity_str2com(argv[2]->arg,
+ ECOMMUNITY_ROUTE_TARGET, 0);
+ if (!ecomadd) {
+ vty_out(vty, "%% Malformed Route Target list\n");
+ return CMD_WARNING;
+ }
+ ecommunity_str(ecomadd);
+
/* Do nothing if we already have this export route-target */
if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
evpn_configure_export_rt(bgp, vpn, ecomadd);
}
}
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
- vty_out(vty, " rd %pRD\n", &bgp->vrf_prd);
+ vty_out(vty, " rd %s\n", bgp->vrf_prd_pretty);
/* import route-target */
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {