]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_evpn_vty.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
index 3c7fb4cb17546851ea845f4a4d15bcea4a09df9f..e28a8c8057ed1dc3c847fcd1257066ca84aafe85 100644 (file)
@@ -1,21 +1,8 @@
+// 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>
@@ -387,7 +374,9 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
                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");
@@ -411,7 +400,10 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
                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");
@@ -474,8 +466,10 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
        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();
@@ -484,7 +478,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
                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",
@@ -525,7 +520,9 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
                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 &&
@@ -1004,7 +1001,9 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
                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");
@@ -1020,7 +1019,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
                        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);
        }
 
@@ -1104,11 +1104,13 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
        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();
@@ -1125,7 +1127,9 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
                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",
@@ -1155,8 +1159,8 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
                        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)) {
@@ -1345,9 +1349,9 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                                        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,
@@ -2216,7 +2220,8 @@ static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
 /*
  * 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
@@ -2225,6 +2230,7 @@ static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
 
        /* 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.
@@ -2246,7 +2252,8 @@ static void evpn_unconfigure_vrf_rd(struct bgp *bgp_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
         */
@@ -2257,7 +2264,7 @@ static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
  * 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,
@@ -2268,6 +2275,7 @@ static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
 
        /* 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))
@@ -2485,7 +2493,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
 
        /* 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) {
@@ -2587,7 +2595,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
 
        /* 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);
 
@@ -2722,7 +2730,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
 
        /* 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();
@@ -2791,7 +2799,8 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
 
        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);
@@ -2830,7 +2839,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
                        /* 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++;
                }
@@ -2874,7 +2883,9 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
 
        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;
@@ -2929,7 +2940,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
                        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.
@@ -2965,7 +2976,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
                        /* 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).
@@ -3023,7 +3034,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
  * 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;
@@ -3056,7 +3067,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
 
                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();
@@ -3081,6 +3092,9 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
 
                        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,
@@ -3119,7 +3133,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
                                        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
@@ -3200,7 +3214,7 @@ int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
        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);
@@ -3473,7 +3487,7 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
        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,
@@ -4773,7 +4787,7 @@ int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
  */
 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
@@ -4782,12 +4796,15 @@ DEFUN(show_bgp_l2vpn_evpn_route,
       "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);
@@ -4805,16 +4822,18 @@ DEFUN(show_bgp_l2vpn_evpn_route,
        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;
 }
@@ -4872,7 +4891,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd,
                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);
 
@@ -6125,7 +6144,7 @@ DEFUN (bgp_evpn_vrf_rd,
                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;
 }
 
@@ -6217,7 +6236,7 @@ DEFUN (bgp_evpn_vni_rd,
                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;
 }
 
@@ -6402,7 +6421,9 @@ DEFUN (show_bgp_vrf_l3vni_info,
                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",
@@ -6438,7 +6459,9 @@ DEFUN (show_bgp_vrf_l3vni_info,
                                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)
@@ -6897,15 +6920,17 @@ DEFUN (bgp_evpn_vni_rt,
                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);
@@ -6913,6 +6938,15 @@ DEFUN (bgp_evpn_vni_rt,
 
        /* 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);
@@ -7254,7 +7288,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
                }
        }
        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)) {