]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Json support for evpn commands
authorMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>
Fri, 21 Jul 2017 00:42:20 +0000 (17:42 -0700)
committerMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>
Thu, 17 Aug 2017 08:29:07 +0000 (01:29 -0700)
Ticket:CM-16241
Reviewed By:CCR-6451
Testing: Manual

Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_route.c

index d9735e7ffa052b5a73690b202c9e986a71afdde8..707728f9da7ae32179f5e282ba66068a1a31a874 100644 (file)
@@ -2187,6 +2187,61 @@ char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len)
        return buf;
 }
 
+/*
+ * Function to convert evpn route to json format.
+ * NOTE: We don't use prefix2str as the output here is a bit different.
+ */
+void
+bgp_evpn_route2json (struct prefix_evpn *p, json_object *json)
+{
+  char buf1[ETHER_ADDR_STRLEN];
+  char buf2[PREFIX2STR_BUFFER];
+
+  if (!json)
+    return;
+
+  if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE)
+    {
+      json_object_int_add (json, "routeType", p->prefix.route_type);
+      json_object_int_add (json, "ethTag", 0);
+      json_object_int_add (json, "ipLen", IS_EVPN_PREFIX_IPADDR_V4 (p) ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN);
+      json_object_string_add (json, "ip", inet_ntoa (p->prefix.ip.ipaddr_v4));
+    }
+  else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
+    {
+      if (IS_EVPN_PREFIX_IPADDR_NONE(p))
+        {
+          json_object_int_add (json, "routeType", p->prefix.route_type);
+          json_object_int_add (json, "esi", 0); /* TODO: we don't support esi yet */
+          json_object_int_add (json, "ethTag", 0);
+          json_object_int_add (json, "macLen", 8 * ETHER_ADDR_LEN);
+          json_object_string_add (json, "mac", prefix_mac2str (&p->prefix.mac, buf1, sizeof (buf1)));
+        }
+      else
+        {
+          u_char family;
+
+          family = IS_EVPN_PREFIX_IPADDR_V4(p) ? \
+                   AF_INET : AF_INET6;
+
+          json_object_int_add (json, "routeType", p->prefix.route_type);
+          json_object_int_add (json, "esi", 0); /* TODO: we don't support esi yet */
+          json_object_int_add (json, "ethTag", 0);
+          json_object_int_add (json, "macLen", 8 * ETHER_ADDR_LEN);
+          json_object_string_add (json, "mac", prefix_mac2str (&p->prefix.mac, buf1, sizeof (buf1)));
+          json_object_int_add (json, "ipLen", IS_EVPN_PREFIX_IPADDR_V4 (p) ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN);
+          json_object_string_add (json, "ip", inet_ntop (family, &p->prefix.ip.ip.addr, buf2, PREFIX2STR_BUFFER));
+        }
+    }
+  else
+    {
+      /* Currently, this is to cater to other AF_ETHERNET code. */
+    }
+
+  return;
+}
+
+
 /*
  * Function to convert evpn route to string.
  * NOTE: We don't use prefix2str as the output here is a bit different.
index ef63199395de47dcf5be67be03b94aea6f630063..01474b09d85d09bea4d821fbfc8cf7c6cb99994b 100644 (file)
@@ -28,6 +28,8 @@
 extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
 extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len);
 extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
+extern void
+bgp_evpn_route2json (struct prefix_evpn *p, json_object *json);
 extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
                                   struct prefix_rd *prd, mpls_label_t *label,
                                   struct attr *attr, int addpath_encode,
index 9dc459cd4e3c1ff88c6233fa492f2693f9427534..7102038f1738962951b3c277d6bdcac33996057d 100644 (file)
@@ -28,6 +28,8 @@
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_ecommunity.h"
 
+#define RT_ADDRSTRLEN                    28
+
 /* EVPN prefix lengths. */
 #define EVPN_TYPE_2_ROUTE_PREFIXLEN      224
 #define EVPN_TYPE_3_ROUTE_PREFIXLEN      224
index 948c7f50f24162cf5b408cb3a7384336a00a152a..2ba8f29260fe972d499096153da1bb26931f4575 100644 (file)
@@ -38,6 +38,7 @@
 #define SHOW_DISPLAY_STANDARD 0
 #define SHOW_DISPLAY_TAGS 1
 #define SHOW_DISPLAY_OVERLAY 2
+#define VNI_STR_LEN          32
 
 /*
  * Context for VNI hash walk - used by callbacks.
@@ -46,6 +47,7 @@ struct vni_walk_ctx {
        struct bgp *bgp;
        struct vty *vty;
        struct in_addr vtep_ip;
+       json_object *json;
 };
 
 struct evpn_config_write {
@@ -54,7 +56,8 @@ struct evpn_config_write {
 };
 
 #if defined(HAVE_CUMULUS)
-static void display_import_rt(struct vty *vty, struct irt_node *irt)
+static void display_import_rt(struct vty *vty, struct irt_node *irt,
+                             json_object *json)
 {
        u_char *pnt;
        u_char type, sub_type;
@@ -68,7 +71,14 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
        } eip;
        struct listnode *node, *nnode;
        struct bgpevpn *tmp_vpn;
+       json_object *json_rt = NULL;
+       json_object *json_vnis = NULL;
+       char rt_buf[RT_ADDRSTRLEN];
 
+       if (json) {
+               json_rt = json_object_new_object ();
+               json_vnis = json_object_new_array ();
+       }
 
        /* TODO: This needs to go into a function */
 
@@ -88,7 +98,13 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
                eas.val |= (*pnt++ << 8);
                eas.val |= (*pnt++);
 
-               vty_out(vty, "Route-target: %u:%u", eas.as, eas.val);
+               snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
+
+               if (json)
+                       json_object_string_add(json_rt, "rt", rt_buf);
+               else
+                       vty_out(vty, "Route-target: %s", rt_buf);
+
                break;
 
        case ECOMMUNITY_ENCODE_IP:
@@ -97,7 +113,14 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
                eip.val = (*pnt++ << 8);
                eip.val |= (*pnt++);
 
-               vty_out(vty, "Route-target: %s:%u", inet_ntoa(eip.ip), eip.val);
+               snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
+                        eip.val);
+
+               if (json)
+                       json_object_string_add(json_rt, "rt", rt_buf);
+               else
+                       vty_out(vty, "Route-target: %s", rt_buf);
+
                break;
 
        case ECOMMUNITY_ENCODE_AS4:
@@ -109,65 +132,103 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
                eas.val = (*pnt++ << 8);
                eas.val |= (*pnt++);
 
-               vty_out(vty, "Route-target: %u:%u", eas.as, eas.val);
+               snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
+
+               if (json)
+                       json_object_string_add(json_rt, "rt", rt_buf);
+               else
+                       vty_out(vty, "Route-target: %s", rt_buf);
+
                break;
 
        default:
                return;
        }
 
-       vty_out(vty, "\n");
-       vty_out(vty, "List of VNIs importing routes with this route-target:\n");
+       if (!json) {
+               vty_out(vty,
+                       "\nList of VNIs importing routes with this route-target:\n");
+       }
+
+       for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
+               if (json)
+                       json_object_array_add(
+                               json_vnis, json_object_new_int64(tmp_vpn->vni));
+               else
+                       vty_out(vty, "  %u\n", tmp_vpn->vni);
+       }
+
+       if (json) {
+               json_object_object_add(json_rt, "vnis", json_vnis);
+               json_object_object_add(json, rt_buf, json_rt);
+       }
 
-       for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn))
-               vty_out(vty, "  %u\n", tmp_vpn->vni);
 }
 
-static void show_import_rt_entry(struct hash_backet *backet, struct vty *vty)
+static void show_import_rt_entry(struct hash_backet *backet, void *args[])
 {
+       json_object *json = NULL;
+       struct vty *vty = NULL;
        struct irt_node *irt = (struct irt_node *)backet->data;
+
+       vty = args[0];
+       json = args[1];
+
        display_import_rt(vty, irt);
+
+       return;
 }
 
 static void bgp_evpn_show_route_rd_header(struct vty *vty,
-                                         struct bgp_node *rd_rn)
+                                         struct bgp_node *rd_rn,
+                                         json_object *json)
 {
        u_int16_t type;
        struct rd_as rd_as;
        struct rd_ip rd_ip;
        u_char *pnt;
+       char rd_str[RD_ADDRSTRLEN];
 
        pnt = rd_rn->p.u.val;
 
        /* Decode RD type. */
        type = decode_rd_type(pnt);
 
+       if (json)
+               return;
+
        vty_out(vty, "Route Distinguisher: ");
 
        switch (type) {
        case RD_TYPE_AS:
                decode_rd_as(pnt + 2, &rd_as);
-               vty_out(vty, "%u:%d", rd_as.as, rd_as.val);
+               snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
                break;
 
        case RD_TYPE_IP:
                decode_rd_ip(pnt + 2, &rd_ip);
-               vty_out(vty, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val);
+               snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
+                        rd_ip.val);
                break;
 
        default:
-               vty_out(vty, "Unknown RD type");
+               snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
                break;
        }
 
-       vty_out(vty, "\n");
+       vty_out(vty, "%s\n", rd_str);
 }
 
-static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp)
+static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
+                                      json_object *json)
 {
        char ri_header[] =
                "   Network          Next Hop            Metric LocPrf Weight Path\n";
 
+       if (json)
+               return;
+
+
        vty_out(vty, "BGP table version is 0, local router ID is %s\n",
                inet_ntoa(bgp->router_id));
        vty_out(vty,
@@ -180,43 +241,83 @@ static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp)
        vty_out(vty, "%s", ri_header);
 }
 
-static void display_vni(struct vty *vty, struct bgpevpn *vpn)
+static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
 {
        char buf1[INET6_ADDRSTRLEN];
        char *ecom_str;
        struct listnode *node, *nnode;
        struct ecommunity *ecom;
+       json_object *json_import_rtl;
+       json_object *json_export_rtl;
+
+       if (json) {
+               json_import_rtl = json_object_new_array();
+               json_export_rtl = json_object_new_array();
+               json_object_int_add(json, "vni", vpn->vni);
+               json_object_string_add(json, "kernelFlag",
+                                      is_vni_live(vpn) ? "Yes" : "No");
+               json_object_string_add(
+                       json, "rd",
+                       prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
+               json_object_string_add(json, "originatorIp",
+                                      inet_ntoa(vpn->originator_ip));
+               json_object_string_add(json, "advertiseGatewayMacip",
+                                      vpn->advertise_gw_macip ? "Yes" : "No");
+       } else {
+               vty_out(vty, "VNI: %d", vpn->vni);
+               if (is_vni_live(vpn))
+                       vty_out(vty, " (known to the kernel)");
+               vty_out(vty, "\n");
 
-       vty_out(vty, "VNI: %d", vpn->vni);
-       if (is_vni_live(vpn))
-               vty_out(vty, " (known to the kernel)");
-       vty_out(vty, "\n");
+               vty_out(vty, "  RD: %s\n",
+                       prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
+               vty_out(vty, "  Originator IP: %s\n",
+                       inet_ntoa(vpn->originator_ip));
+               vty_out(vty, "  Advertise-gw-macip : %s\n",
+                       vpn->advertise_gw_macip ? "Yes" : "No");
+       }
 
-       vty_out(vty, "  RD: %s\n",
-               prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
-       vty_out(vty, "  Originator IP: %s\n", inet_ntoa(vpn->originator_ip));
-       vty_out(vty, "  Advertise-gw-macip : %s\n",
-               vpn->advertise_gw_macip ? "Yes" : "No");
+       if (!json)
+               vty_out(vty, "  Import Route Target:\n");
 
-       vty_out(vty, "  Import Route Target:\n");
        for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               vty_out(vty, "    %s\n", ecom_str);
+
+               if (json)
+                       json_object_array_add(json_import_rtl,
+                                             json_object_new_string(ecom_str));
+               else
+                       vty_out(vty, "    %s\n", ecom_str);
+
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
        }
 
-       vty_out(vty, "  Export Route Target:\n");
+       if (json)
+               json_object_object_add(json, "importRts", json_import_rtl);
+       else
+               vty_out(vty, "  Export Route Target:\n");
+
        for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               vty_out(vty, "    %s\n", ecom_str);
+
+               if (json)
+                       json_object_array_add(json_export_rtl,
+                                             json_object_new_string(ecom_str));
+               else
+                       vty_out(vty, "    %s\n", ecom_str);
+
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
        }
+
+       if (json)
+               json_object_object_add(json, "exportRts", json_export_rtl);
 }
 
 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
-                           struct vty *vty, struct in_addr vtep_ip)
+                           struct vty *vty, struct in_addr vtep_ip,
+                           json_object *json)
 {
        struct bgp_node *rn;
        struct bgp_info *ri;
@@ -228,41 +329,79 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
        for (rn = bgp_table_top(vpn->route_table); rn;
             rn = bgp_route_next(rn)) {
                struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+               int add_prefix_to_json = 0;
+               char prefix_str[BUFSIZ];
+               json_object *json_paths = NULL;
+               json_object *json_prefix = NULL;
+
+               bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
+                                  sizeof(prefix_str));
 
                if (type && evp->prefix.route_type != type)
                        continue;
 
+               if (json)
+                       json_prefix = json_object_new_object();
+
                if (rn->info) {
                        /* Overall header/legend displayed once. */
                        if (header) {
-                               bgp_evpn_show_route_header(vty, bgp);
+                               bgp_evpn_show_route_header(vty, bgp, json);
                                header = 0;
                        }
 
                        prefix_cnt++;
                }
 
+               if (json)
+                       json_paths = json_object_new_array();
+
                /* For EVPN, the prefix is displayed for each path (to fit in
                 * with code that already exists).
                 */
                for (ri = rn->info; ri; ri = ri->next) {
+                       json_object *json_path = NULL;
+
                        if (vtep_ip.s_addr
                            && !IPV4_ADDR_SAME(&(vtep_ip),
                                               &(ri->attr->nexthop)))
                                continue;
 
+                       if (json)
+                               json_path = json_object_new_array();
+
+                       route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path);
+
+                       if (json)
+                               json_object_array_add(json_paths, json_path);
+
                        path_cnt++;
-                       route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, NULL);
+                       add_prefix_to_json = 1;
+               }
+
+               if (json && add_prefix_to_json) {
+                       json_object_string_add(json_prefix, "prefix",
+                                              prefix_str);
+                       json_object_int_add(json_prefix, "prefixLen",
+                                           rn->p.prefixlen);
+                       json_object_object_add(json_prefix, "paths",
+                                              json_paths);
+                       json_object_object_add(json, prefix_str, json_prefix);
                }
        }
 
-       if (prefix_cnt == 0)
-               vty_out(vty, "No EVPN prefixes %sexist for this VNI\n",
-                       type ? "(of requested type) " : "");
-       else
-               vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
-                       prefix_cnt, path_cnt,
-                       type ? " (of requested type)" : "");
+       if (json) {
+               json_object_int_add(json, "numPrefix", prefix_cnt);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               if (prefix_cnt == 0)
+                       vty_out(vty, "No EVPN prefixes %sexist for this VNI",
+                               type ? "(of requested type) " : "");
+               else
+                       vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s",
+                               prefix_cnt, path_cnt,
+                               type ? " (of requested type)" : "");
+       }
 }
 
 static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
@@ -270,13 +409,31 @@ static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
        struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
        struct vni_walk_ctx *wctx = arg;
        struct vty *vty = wctx->vty;
+       json_object *json = wctx->json;
+       json_object *json_vni = NULL;
+       char vni_str[VNI_STR_LEN];
+
+       snprintf(vni_str, VNI_STR_LEN, "%d", vpn->vni);
+       if (json) {
+               json_vni = json_object_new_object();
+               json_object_int_add(json_vni, "vni", vpn->vni);
+       } else {
+               vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
+       }
+
+       show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni);
 
-       vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
-       show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip);
+       if (json)
+               json_object_object_add(json, vni_str, json_vni);
 }
 
-static void show_vni_entry(struct hash_backet *backet, struct vty *vty)
+static void show_vni_entry(struct hash_backet *backet, void *args[])
 {
+       struct vty *vty;
+       json_object *json;
+       json_object *json_vni;
+       json_object *json_import_rtl;
+       json_object *json_export_rtl;
        struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
        char buf1[10];
        char buf2[INET6_ADDRSTRLEN];
@@ -285,42 +442,91 @@ static void show_vni_entry(struct hash_backet *backet, struct vty *vty)
        struct listnode *node, *nnode;
        struct ecommunity *ecom;
 
+       vty = args[0];
+       json = args[1];
+
+       if (json) {
+               json_vni = json_object_new_object();
+               json_import_rtl = json_object_new_array();
+               json_export_rtl = json_object_new_array();
+       }
+
        buf1[0] = '\0';
        if (is_vni_live(vpn))
                sprintf(buf1, "*");
 
-       vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni,
-               inet_ntoa(vpn->originator_ip),
-               prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+       if (json) {
+               json_object_int_add(json_vni, "vni", vpn->vni);
+               json_object_string_add(json_vni, "inKernel",
+                                      is_vni_live(vpn) ? "True" : "False");
+               json_object_string_add(json_vni, "originatorIp",
+                                      inet_ntoa(vpn->originator_ip));
+               json_object_string_add(
+                       json_vni, "rd",
+                       prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+       } else {
+               vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni,
+                       inet_ntoa(vpn->originator_ip),
+                       prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+       }
 
        for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
-               if (listcount(vpn->import_rtl) > 1)
-                       sprintf(rt_buf, "%s, ...", ecom_str);
-               else
-                       sprintf(rt_buf, "%s", ecom_str);
-               vty_out(vty, " %-25s", rt_buf);
+               if (json) {
+                       json_object_array_add(json_import_rtl,
+                                             json_object_new_string(ecom_str));
+               } else {
+                       if (listcount(vpn->import_rtl) > 1)
+                               sprintf(rt_buf, "%s, ...", ecom_str);
+                       else
+                               sprintf(rt_buf, "%s", ecom_str);
+                       vty_out(vty, " %-25s", rt_buf);
+               }
 
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
-               break;
+
+               /* If there are multiple import RTs we break here and show only
+                * one */
+               if (!json)
+                       break;
        }
 
+       if (json)
+               json_object_object_add(json_vni, "importRTs", json_import_rtl);
+
        for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
-               if (listcount(vpn->export_rtl) > 1)
-                       sprintf(rt_buf, "%s, ...", ecom_str);
-               else
-                       sprintf(rt_buf, "%s", ecom_str);
-               vty_out(vty, " %-25s", rt_buf);
+               if (json) {
+                       json_object_array_add(json_export_rtl,
+                                             json_object_new_string(ecom_str));
+               } else {
+                       if (listcount(vpn->export_rtl) > 1)
+                               sprintf(rt_buf, "%s, ...", ecom_str);
+                       else
+                               sprintf(rt_buf, "%s", ecom_str);
+                       vty_out(vty, " %-25s", rt_buf);
+               }
 
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
-               break;
+
+               /* If there are multiple export RTs we break here and show only
+                * one */
+               if (!json)
+                       break;
+       }
+
+       if (json) {
+               char vni_str[VNI_STR_LEN];
+               json_object_object_add(json_vni, "exportRTs", json_export_rtl);
+               snprintf(vni_str, VNI_STR_LEN, "%u", vpn->vni);
+               json_object_object_add(json, vni_str, json_vni);
+       } else {
+               vty_out(vty, "\n");
        }
-       vty_out(vty, "\n");
 }
 #endif /* HAVE_CUMULUS */
 
@@ -1281,19 +1487,26 @@ static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
 /*
  * Display import RT mapping to VNIs (vty handler)
  */
-static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp)
+static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
+                                json_object *json)
 {
+       void *args[2];
+
+       args[0] = vty;
+       args[1] = json;
+
        hash_iterate(
                bgp->import_rt_hash,
                (void (*)(struct hash_backet *, void *))show_import_rt_entry,
-               vty);
+               args);
 }
 
 /*
  * Display EVPN routes for all VNIs - vty handler.
  */
 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
-                                    struct in_addr vtep_ip)
+                                    struct in_addr vtep_ip,
+                                    json_object *json)
 {
        u_int32_t num_vnis;
        struct vni_walk_ctx wctx;
@@ -1305,6 +1518,7 @@ static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
        wctx.bgp = bgp;
        wctx.vty = vty;
        wctx.vtep_ip = vtep_ip;
+       wctx.json = json;
        hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *,
                                             void *))show_vni_routes_hash,
                     &wctx);
@@ -1314,7 +1528,8 @@ static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
  * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
  */
 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
-                                         vni_t vni, struct in_addr orig_ip)
+                                         vni_t vni, struct in_addr orig_ip,
+                                         json_object *json)
 {
        struct bgpevpn *vpn;
        struct prefix_evpn p;
@@ -1323,6 +1538,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
        u_int32_t path_cnt = 0;
        afi_t afi;
        safi_t safi;
+       json_object *json_paths = NULL;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
@@ -1338,20 +1554,42 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
        build_evpn_type3_prefix(&p, orig_ip);
        rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
        if (!rn || !rn->info) {
-               vty_out(vty, "%% Network not in table\n");
+               if (!json)
+                       vty_out(vty, "%% Network not in table\n");
                return;
        }
 
+       if (json)
+               json_paths = json_object_new_array();
+
        /* Prefix and num paths displayed once per prefix. */
-       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, NULL);
+       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
 
        /* Display each path for this prefix. */
        for (ri = rn->info; ri; ri = ri->next) {
-               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL);
+               json_object *json_path = NULL;
+
+               if (json)
+                       json_path = json_object_new_array();
+
+               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
                path_cnt++;
        }
 
-       vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt);
+       if (json) {
+               if (path_cnt)
+                       json_object_object_add(json, "paths", json_paths);
+
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
+                       path_cnt);
+       }
 }
 
 /*
@@ -1360,7 +1598,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
  */
 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
                                      vni_t vni, struct ethaddr *mac,
-                                     struct ipaddr *ip)
+                                     struct ipaddr *ip, json_object *json)
 {
        struct bgpevpn *vpn;
        struct prefix_evpn p;
@@ -1369,6 +1607,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
        u_int32_t path_cnt = 0;
        afi_t afi;
        safi_t safi;
+       json_object *json_paths = NULL;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
@@ -1376,7 +1615,8 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
        /* Locate VNI. */
        vpn = bgp_evpn_lookup_vni(bgp, vni);
        if (!vpn) {
-               vty_out(vty, "VNI not found\n");
+               if (!json)
+                       vty_out(vty, "VNI not found\n");
                return;
        }
 
@@ -1384,20 +1624,42 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
        build_evpn_type2_prefix(&p, mac, ip);
        rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
        if (!rn || !rn->info) {
-               vty_out(vty, "%% Network not in table\n");
+               if (!json)
+                       vty_out(vty, "%% Network not in table\n");
                return;
        }
 
+       if (json)
+               json_paths = json_object_new_array();
+
        /* Prefix and num paths displayed once per prefix. */
-       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, NULL);
+       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
 
        /* Display each path for this prefix. */
        for (ri = rn->info; ri; ri = ri->next) {
-               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL);
+               json_object *json_path = NULL;
+
+               if (json)
+                       json_path = json_object_new_array();
+
+               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
                path_cnt++;
        }
 
-       vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt);
+       if (json) {
+               if (path_cnt)
+                       json_object_object_add(json, "paths", json_paths);
+
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
+                       path_cnt);
+       }
 }
 
 /*
@@ -1406,19 +1668,21 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
  * If the vtep_ip is non zero, only routes behind that vtep are shown
  */
 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
-                                int type, struct in_addr vtep_ip)
+                                int type, struct in_addr vtep_ip,
+                                json_object *json)
 {
        struct bgpevpn *vpn;
 
        /* Locate VNI. */
        vpn = bgp_evpn_lookup_vni(bgp, vni);
        if (!vpn) {
-               vty_out(vty, "VNI not found\n");
+               if (!json)
+                       vty_out(vty, "VNI not found\n");
                return;
        }
 
        /* Walk this VNI's route table and display appropriate routes. */
-       show_vni_routes(bgp, vpn, type, vty, vtep_ip);
+       show_vni_routes(bgp, vpn, type, vty, vtep_ip, json);
 }
 
 /*
@@ -1428,7 +1692,7 @@ static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
  */
 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
                                     struct prefix_rd *prd, struct ethaddr *mac,
-                                    struct ipaddr *ip)
+                                    struct ipaddr *ip, json_object *json)
 {
        struct prefix_evpn p;
        struct bgp_node *rn;
@@ -1436,6 +1700,8 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
        afi_t afi;
        safi_t safi;
        u_int32_t path_cnt = 0;
+       json_object *json_paths = NULL;
+       char prefix_str[BUFSIZ];
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
@@ -1445,20 +1711,44 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
        rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
                                 (struct prefix *)&p, prd);
        if (!rn || !rn->info) {
-               vty_out(vty, "%% Network not in table\n");
+               if (!json)
+                       vty_out(vty, "%% Network not in table\n");
                return;
        }
 
+       bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
+                          sizeof(prefix_str));
+
        /* Prefix and num paths displayed once per prefix. */
-       route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, NULL);
+       route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
+
+       if (json)
+               json_paths = json_object_new_array();
 
        /* Display each path for this prefix. */
        for (ri = rn->info; ri; ri = ri->next) {
-               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL);
+               json_object *json_path = NULL;
+
+               if (json)
+                       json_path = json_object_new_array();
+
+               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
                path_cnt++;
        }
 
-       vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt);
+       if (json && path_cnt) {
+               if (path_cnt)
+                       json_object_object_add(json, prefix_str, json_paths);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
+                       path_cnt);
+       }
 }
 
 /*
@@ -1466,7 +1756,8 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
  * If 'type' is non-zero, only routes matching that type are shown.
  */
 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
-                              struct prefix_rd *prd, int type)
+                              struct prefix_rd *prd, int type,
+                              json_object *json)
 {
        struct bgp_node *rd_rn;
        struct bgp_table *table;
@@ -1476,28 +1767,49 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
        afi_t afi;
        safi_t safi;
        u_int32_t prefix_cnt, path_cnt;
+       char rd_str[RD_ADDRSTRLEN];
+       json_object *json_rd = NULL;
+       int add_rd_to_json = 0;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
        prefix_cnt = path_cnt = 0;
 
+       prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
+
        rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
        if (!rd_rn)
                return;
+
        table = (struct bgp_table *)rd_rn->info;
        if (table == NULL)
                return;
 
+       if (json) {
+               json_rd = json_object_new_object();
+               json_object_string_add(json_rd, "rd", rd_str);
+       }
+
        /* Display all prefixes with this RD. */
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
                struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+               json_object *json_prefix = NULL;
+               json_object *json_paths = NULL;
+               char prefix_str[BUFSIZ];
+               int add_prefix_to_json = 0;
+
+               bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
+                                  sizeof(prefix_str));
 
                if (type && evp->prefix.route_type != type)
                        continue;
 
+               if (json)
+                       json_prefix = json_object_new_object();
+
                if (rn->info) {
                        /* RD header and legend - once overall. */
-                       if (rd_header) {
+                       if (rd_header && !json) {
                                vty_out(vty,
                                        "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
                                        "[MAC]\n");
@@ -1509,34 +1821,64 @@ 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, rn, prd, afi,
-                                                   safi, NULL);
+                                                   safi, json_prefix);
 
                        prefix_cnt++;
                }
 
+               if (json)
+                       json_paths = json_object_new_array();
+
                /* Display each path for this prefix. */
                for (ri = rn->info; ri; ri = ri->next) {
+                       json_object *json_path = NULL;
+
+                       if (json)
+                               json_path = json_object_new_array();
+
                        route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
-                                            NULL);
+                                            json_path);
+
+                       if (json)
+                               json_object_array_add(json_paths, json_path);
+
                        path_cnt++;
+                       add_prefix_to_json = 1;
+                       add_rd_to_json = 1;
+               }
+
+               if (json && add_prefix_to_json) {
+                       json_object_object_add(json_prefix, "paths",
+                                              json_paths);
+                       json_object_object_add(json_rd, prefix_str,
+                                              json_prefix);
                }
        }
 
-       if (prefix_cnt == 0)
-               vty_out(vty, "No prefixes exist with this RD%s\n",
-                       type ? " (of requested type)" : "");
-       else
-               vty_out(vty,
-                       "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
-                       prefix_cnt, path_cnt,
-                       type ? " (of requested type)" : "");
+       if (json && add_rd_to_json)
+               json_object_object_add(json, rd_str, json_rd);
+
+       if (json) {
+               json_object_int_add(json, "numPrefix", prefix_cnt);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               if (prefix_cnt == 0)
+                       vty_out(vty, "No prefixes exist with this RD%s\n",
+                               type ? " (of requested type)" : "");
+               else
+                       vty_out(vty,
+                               "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
+                               prefix_cnt, path_cnt,
+                               type ? " (of requested type)" : "");
+       }
 }
 
 /*
  * Display BGP EVPN routing table - all routes (vty handler).
  * 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)
+static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
+                                json_object *json)
 {
        struct bgp_node *rd_rn;
        struct bgp_table *table;
@@ -1557,15 +1899,36 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type)
         */
        for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
             rd_rn = bgp_route_next(rd_rn)) {
+               char rd_str[RD_ADDRSTRLEN];
+               json_object *json_rd = NULL; /* contains routes for an RD */
+               int add_rd_to_json = 0;
+
                table = (struct bgp_table *)rd_rn->info;
                if (table == NULL)
                        continue;
 
+               prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
+                             sizeof(rd_str));
+
+               if (json) {
+                       json_rd = json_object_new_object();
+                       json_object_string_add(json_rd, "rd", rd_str);
+               }
+
                rd_header = 1;
 
                /* Display all prefixes for an RD */
                for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+                       json_object *json_prefix =
+                               NULL; /* contains prefix under a RD */
+                       json_object *json_paths =
+                               NULL; /* array of paths under a prefix*/
                        struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+                       char prefix_str[BUFSIZ];
+                       int add_prefix_to_json = 0;
+
+                       bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
+                                          prefix_str, sizeof(prefix_str));
 
                        if (type && evp->prefix.route_type != type)
                                continue;
@@ -1573,74 +1936,126 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type)
                        if (rn->info) {
                                /* Overall header/legend displayed once. */
                                if (header) {
-                                       bgp_evpn_show_route_header(vty, bgp);
+                                       bgp_evpn_show_route_header(vty, bgp,
+                                                                  json);
                                        header = 0;
                                }
 
                                /* RD header - per RD. */
                                if (rd_header) {
-                                       bgp_evpn_show_route_rd_header(vty,
-                                                                     rd_rn);
+                                       bgp_evpn_show_route_rd_header(
+                                               vty, rd_rn, json);
                                        rd_header = 0;
                                }
 
                                prefix_cnt++;
                        }
 
+                       if (json) {
+                               json_prefix = json_object_new_object();
+                               json_paths = json_object_new_array();
+                               json_object_string_add(json_prefix, "prefix",
+                                                      prefix_str);
+                               json_object_int_add(json_prefix, "prefixLen",
+                                                   rn->p.prefixlen);
+                       }
+
                        /* For EVPN, the prefix is displayed for each path (to
                         * fit in
                         * with code that already exists).
                         */
                        for (ri = rn->info; ri; ri = ri->next) {
+                               json_object *json_path = NULL;
                                path_cnt++;
+                               add_prefix_to_json = 1;
+                               add_rd_to_json = 1;
+
+                               if (json)
+                                       json_path = json_object_new_array();
+
                                route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN,
-                                             NULL);
+                                             json_path);
+
+                               if (json)
+                                       json_object_array_add(json_paths,
+                                                             json_path);
+                       }
+
+                       if (json && add_prefix_to_json) {
+                               json_object_object_add(json_prefix, "paths",
+                                                      json_paths);
+                               json_object_object_add(json_rd, prefix_str,
+                                                      json_prefix);
                        }
                }
+
+               if (json && add_rd_to_json)
+                       json_object_object_add(json, rd_str, json_rd);
        }
 
-       if (prefix_cnt == 0)
-               vty_out(vty, "No EVPN prefixes %sexist\n",
-                       type ? "(of requested type) " : "");
-       else
-               vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
-                       prefix_cnt, path_cnt,
-                       type ? " (of requested type)" : "");
+       if (json) {
+               json_object_int_add(json, "numPrefix", prefix_cnt);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               if (prefix_cnt == 0) {
+                       vty_out(vty, "No EVPN prefixes %sexist\n",
+                               type ? "(of requested type) " : "");
+               } else {
+                       vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
+                               prefix_cnt, path_cnt,
+                               type ? " (of requested type)" : "");
+               }
+       }
 }
 
 /*
  * Display specified VNI (vty handler)
  */
-static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni)
+static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
+                         json_object *json)
 {
        struct bgpevpn *vpn;
 
        vpn = bgp_evpn_lookup_vni(bgp, vni);
        if (!vpn) {
-               vty_out(vty, "VNI not found\n");
-               return;
+               if (json) {
+                       vty_out(vty, "{}\n");
+               } else {
+                       vty_out(vty, "VNI not found\n");
+                       return;
+               }
        }
 
-       display_vni(vty, vpn);
+       display_vni(vty, vpn, json);
 }
 
 /*
  * Display a VNI (upon user query).
  */
-static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp)
+static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
+                              json_object *json)
 {
        u_int32_t num_vnis;
+       void *args[2];
 
        num_vnis = hashcount(bgp->vnihash);
        if (!num_vnis)
                return;
-       vty_out(vty, "Number of VNIs: %u\n", num_vnis);
-       vty_out(vty, "Flags: * - Kernel \n");
-       vty_out(vty, "  %-10s %-15s %-21s %-25s %-25s\n", "VNI", "Orig IP",
-               "RD", "Import RT", "Export RT");
+
+       if (json) {
+               json_object_int_add(json, "numVnis", num_vnis);
+       } else {
+               vty_out(vty, "Number of VNIs: %u\n", num_vnis);
+               vty_out(vty, "Flags: * - Kernel\n");
+               vty_out(vty, "  %-10s %-15s %-21s %-25s %-25s\n", "VNI",
+                       "Orig IP", "RD", "Import RT", "Export RT");
+       }
+
+       args[0] = vty;
+       args[1] = json;
        hash_iterate(bgp->vnihash,
                     (void (*)(struct hash_backet *, void *))show_vni_entry,
-                    vty);
+                    args);
 }
 
 /*
@@ -1863,19 +2278,24 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
 /*
  * Display VNI information - for all or a specific VNI
  */
-DEFUN (show_bgp_l2vpn_evpn_vni,
-       show_bgp_l2vpn_evpn_vni_cmd,
-       "show bgp l2vpn evpn vni [(1-16777215)]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "Show VNI\n"
-       "VNI number\n")
+DEFUN(show_bgp_l2vpn_evpn_vni,
+      show_bgp_l2vpn_evpn_vni_cmd,
+      "show bgp l2vpn evpn vni [(1-16777215)] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "Show VNI\n"
+      "VNI number\n"
+      JSON_STR)
 {
        struct bgp *bgp;
        vni_t vni;
        int idx = 0;
+       u_char uj = 0;
+       json_object *json = NULL;
+
+       uj = use_json(argc, argv);
 
        bgp = bgp_get_default();
        if (!bgp)
@@ -1884,18 +2304,46 @@ DEFUN (show_bgp_l2vpn_evpn_vni,
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
-       if (argc == ((idx + 1) + 1)) {
-               vty_out(vty, "Advertise gateway macip flag: %s\n",
-                       bgp->advertise_gw_macip ? "Enabled" : "Disabled");
+       if (uj)
+               json = json_object_new_object();
 
-               /* Display all VNIs */
-               vty_out(vty, "Advertise All VNI flag: %s\n",
-                       bgp->advertise_all_vni ? "Enabled" : "Disabled");
-               evpn_show_all_vnis(vty, bgp);
+       if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
+               if (uj) {
+                       json_object_string_add(json, "advertiseGatewayMacip",
+                                              bgp->advertise_gw_macip
+                                                      ? "Enabled"
+                                                      : "Disabled");
+                       json_object_string_add(json, "advertiseAllVnis",
+                                              bgp->advertise_all_vni
+                                                      ? "Enabled"
+                                                      : "Disabled");
+               } else {
+                       vty_out(vty, "Advertise Gateway Macip: %s\n",
+                               bgp->advertise_gw_macip ? "Enabled"
+                                                       : "Disabled");
+
+                       /* Display all VNIs */
+                       vty_out(vty, "Advertise All VNI flag: %s\n",
+                               bgp->advertise_all_vni ? "Enabled"
+                                                      : "Disabled");
+               }
+
+               evpn_show_all_vnis(vty, bgp, json);
        } else {
+               int vni_idx = 0;
+
+               if (!argv_find(argv, argc, "vni", &vni_idx))
+                       return CMD_WARNING;
+
                /* Display specific VNI */
-               vni = strtoul(argv[argc - 1]->arg, NULL, 10);
-               evpn_show_vni(vty, bgp, vni);
+               vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
+               evpn_show_vni(vty, bgp, vni, json);
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
        }
 
        return CMD_SUCCESS;
@@ -1904,15 +2352,15 @@ DEFUN (show_bgp_l2vpn_evpn_vni,
 /*
  * Display EVPN neighbor summary.
  */
-DEFUN (show_bgp_l2vpn_evpn_summary,
-       show_bgp_l2vpn_evpn_summary_cmd,
-       "show bgp l2vpn evpn summary [json]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "Summary of BGP neighbor status\n"
-       JSON_STR)
+DEFUN(show_bgp_l2vpn_evpn_summary,
+      show_bgp_l2vpn_evpn_summary_cmd,
+      "show bgp l2vpn evpn summary [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "Summary of BGP neighbor status\n"
+      JSON_STR)
 {
        u_char uj = use_json(argc, argv);
        return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
@@ -1921,176 +2369,236 @@ DEFUN (show_bgp_l2vpn_evpn_summary,
 /*
  * Display global EVPN routing table.
  */
-DEFUN (show_bgp_l2vpn_evpn_route,
-       show_bgp_l2vpn_evpn_route_cmd,
-       "show bgp l2vpn evpn route [type <macip|multicast>]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "Specify Route type\n"
-       "MAC-IP (Type-2) route\n"
-       "Multicast (Type-3) route\n")
+DEFUN(show_bgp_l2vpn_evpn_route, show_bgp_l2vpn_evpn_route_cmd,
+      "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "Specify Route type\n"
+      "MAC-IP (Type-2) route\n"
+      "Multicast (Type-3) route\n"
+      JSON_STR)
 {
        struct bgp *bgp;
-       int idx = 0;
+       int type_idx;
        int type = 0;
+       u_char uj = 0;
+       json_object *json = NULL;
+
+       uj = use_json(argc, argv);
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       if (!argv_find(argv, argc, "evpn", &idx))
-               return CMD_WARNING;
+       if (uj)
+               json = json_object_new_object();
 
-       if (argc == ((idx + 1) + 3)) {
+       /* get the type */
+       if (argv_find(argv, argc, "type", &type_idx)) {
                /* Specific type is requested */
-               if (strncmp(argv[argc - 1]->arg, "ma", 2) == 0)
+               if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
                        type = BGP_EVPN_MAC_IP_ROUTE;
-               else if (strncmp(argv[argc - 1]->arg, "mu", 2) == 0)
+               else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
                        type = BGP_EVPN_IMET_ROUTE;
                else
                        return CMD_WARNING;
        }
 
-       evpn_show_all_routes(vty, bgp, type);
+       evpn_show_all_routes(vty, bgp, type, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display global EVPN routing table for specific RD.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_rd,
-       show_bgp_l2vpn_evpn_route_rd_cmd,
-       "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "Route Distinguisher\n"
-       "ASN:XX or A.B.C.D:XX\n"
-       "Specify Route type\n"
-       "MAC-IP (Type-2) route\n"
-       "Multicast (Type-3) route\n")
+DEFUN(show_bgp_l2vpn_evpn_route_rd, show_bgp_l2vpn_evpn_route_rd_cmd,
+      "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "Route Distinguisher\n"
+      "ASN:XX or A.B.C.D:XX\n"
+      "Specify Route type\n"
+      "MAC-IP (Type-2) route\n"
+      "Multicast (Type-3) route\n"
+      JSON_STR)
 {
        struct bgp *bgp;
        int ret;
        struct prefix_rd prd;
-       int idx = 0;
        int type = 0;
+       int rd_idx = 0;
+       int type_idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       if (!argv_find(argv, argc, "evpn", &idx))
-               return CMD_WARNING;
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
 
-       ret = str2prefix_rd(argv[idx + 3]->arg, &prd);
-       if (!ret) {
-               vty_out(vty, "%% Malformed Route Distinguisher\n");
-               return CMD_WARNING;
+       /* get the RD */
+       if (argv_find(argv, argc, "rd", &rd_idx)) {
+               ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
+
+               if (!ret) {
+                       vty_out(vty, "%% Malformed Route Distinguisher\n");
+                       return CMD_WARNING;
+               }
        }
 
-       if (argc == ((idx + 1) + 5)) {
+       /* get the type */
+       if (argv_find(argv, argc, "type", &type_idx)) {
                /* Specific type is requested */
-               if (strncmp(argv[argc - 1]->arg, "ma", 2) == 0)
+               if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
                        type = BGP_EVPN_MAC_IP_ROUTE;
-               else if (strncmp(argv[argc - 1]->arg, "mu", 2) == 0)
+               else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
                        type = BGP_EVPN_IMET_ROUTE;
                else
                        return CMD_WARNING;
        }
 
-       evpn_show_route_rd(vty, bgp, &prd, type);
+       evpn_show_route_rd(vty, bgp, &prd, type, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display global EVPN routing table for specific RD and MACIP.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_rd_macip,
-       show_bgp_l2vpn_evpn_route_rd_macip_cmd,
-       "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "Route Distinguisher\n"
-       "ASN:XX or A.B.C.D:XX\n"
-       "MAC\n"
-       "MAC address (e.g., 00:e0:ec:20:12:62)\n"
-       "IP\n"
-       "IP address (IPv4 or IPv6)\n")
-{
-       struct bgp *bgp;
-       int ret;
-       struct prefix_rd prd;
-       struct ethaddr mac;
-       struct ipaddr ip;
-       int idx = 0;
+DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
+      show_bgp_l2vpn_evpn_route_rd_macip_cmd,
+      "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "Route Distinguisher\n"
+      "ASN:XX or A.B.C.D:XX\n"
+      "MAC\n"
+      "MAC address (e.g., 00:e0:ec:20:12:62)\n"
+      "IP\n"
+      "IP address (IPv4 or IPv6)\n"
+      JSON_STR)
+{
+       struct bgp              *bgp;
+       int                     ret;
+       struct prefix_rd        prd;
+       struct ethaddr          mac;
+       struct ipaddr           ip;
+       int                     rd_idx = 0;
+       int                     mac_idx = 0;
+       int                     ip_idx = 0;
+       int                     uj = 0;
+       json_object             *json = NULL;
+
+       memset(&mac, 0, sizeof(struct ethaddr));
+       memset(&ip, 0, sizeof(struct ipaddr));
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       if (!argv_find(argv, argc, "evpn", &idx))
-               return CMD_WARNING;
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
 
-       ret = str2prefix_rd(argv[idx + 3]->arg, &prd);
-       if (!ret) {
-               vty_out(vty, "%% Malformed Route Distinguisher\n");
-               return CMD_WARNING;
+       /* get the prd */
+       if (argv_find(argv, argc, "rd", &rd_idx)) {
+               ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
+               if (!ret) {
+                       vty_out(vty, "%% Malformed Route Distinguisher\n");
+                       return CMD_WARNING;
+               }
        }
-       if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
-               vty_out(vty, "%% Malformed MAC address\n");
-               return CMD_WARNING;
+
+       /* get the mac */
+       if (argv_find(argv, argc, "mac", &mac_idx)) {
+               if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
+                       vty_out(vty, "%% Malformed MAC address\n");
+                       return CMD_WARNING;
+               }
        }
-       memset(&ip, 0, sizeof(ip));
-       if (argc == (idx + 1 + 7) && argv[argc - 1]->arg != NULL) {
-               /* Specific MAC+IP requested */
-               if (str2ipaddr(argv[argc - 1]->arg, &ip) != 0) {
+
+       /* get the ip if specified */
+       if (argv_find(argv, argc, "ip", &ip_idx)) {
+               if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
                        vty_out(vty, "%% Malformed IP address\n");
                        return CMD_WARNING;
                }
        }
 
-       evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip);
+       evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni,
-       show_bgp_l2vpn_evpn_route_vni_cmd,
-       "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "VNI number\n"
-       "Specify Route type\n"
-       "MAC-IP (Type-2) route\n"
-       "Multicast (Type-3) route\n"
-       "Remote VTEP\n"
-       "Remote VTEP IP address\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
+      "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "VNI number\n"
+      "Specify Route type\n"
+      "MAC-IP (Type-2) route\n"
+      "Multicast (Type-3) route\n"
+      "Remote VTEP\n"
+      "Remote VTEP IP address\n"
+      JSON_STR)
 {
        vni_t vni;
        struct bgp *bgp;
        struct in_addr vtep_ip;
        int type = 0;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
@@ -2098,7 +2606,8 @@ DEFUN (show_bgp_l2vpn_evpn_route_vni,
 
        vni = strtoul(argv[idx + 3]->arg, NULL, 10);
 
-       if (argc == (idx + 1 + 5) && argv[idx + 4]->arg) {
+       if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
+           || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
                if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
                        if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
                                type = BGP_EVPN_MAC_IP_ROUTE;
@@ -2115,156 +2624,231 @@ DEFUN (show_bgp_l2vpn_evpn_route_vni,
                        return CMD_WARNING;
        }
 
-       evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip);
+       evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table for specific MACIP.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni_macip,
-       show_bgp_l2vpn_evpn_route_vni_macip_cmd,
-       "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "VNI number\n"
-       "MAC\n"
-       "MAC address (e.g., 00:e0:ec:20:12:62)\n"
-       "IP\n"
-       "IP address (IPv4 or IPv6)\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
+      show_bgp_l2vpn_evpn_route_vni_macip_cmd,
+      "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "VNI number\n"
+      "MAC\n"
+      "MAC address (e.g., 00:e0:ec:20:12:62)\n"
+      "IP\n"
+      "IP address (IPv4 or IPv6)\n"
+      JSON_STR)
 {
        vni_t vni;
        struct bgp *bgp;
        struct ethaddr mac;
        struct ipaddr ip;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
+       /* get the VNI */
        vni = strtoul(argv[idx + 3]->arg, NULL, 10);
+
+       /* get the mac */
        if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
                vty_out(vty, "%% Malformed MAC address\n");
                return CMD_WARNING;
        }
+
+       /* get the ip */
        memset(&ip, 0, sizeof(ip));
-       if (argc == (idx + 1 + 7) && argv[idx + 7]->arg != NULL) {
+       if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
+           || (uj
+               && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
                if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
                        vty_out(vty, "%% Malformed IP address\n");
                        return CMD_WARNING;
                }
        }
 
-       evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip);
+       evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni_multicast,
-       show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
-       "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "VNI number\n"
-       "Multicast (Type-3) route\n"
-       "Originating Router IP address\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
+      show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
+      "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "VNI number\n"
+      "Multicast (Type-3) route\n"
+      "Originating Router IP address\n"
+      JSON_STR)
 {
        vni_t vni;
        struct bgp *bgp;
        int ret;
        struct in_addr orig_ip;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
+       /* get the VNI */
        vni = strtoul(argv[idx + 3]->arg, NULL, 10);
+
+       /* get the ip */
        ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
        if (!ret) {
                vty_out(vty, "%% Malformed Originating Router IP address\n");
                return CMD_WARNING;
        }
 
-       evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip);
+       evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table - for all VNIs.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni_all,
-       show_bgp_l2vpn_evpn_route_vni_all_cmd,
-       "show bgp l2vpn evpn route vni all [vtep A.B.C.D]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "All VNIs\n"
-       "Remote VTEP\n"
-       "Remote VTEP IP address\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_l2vpn_evpn_route_vni_all_cmd,
+      "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "All VNIs\n"
+      "Remote VTEP\n"
+      "Remote VTEP IP address\n"
+      JSON_STR)
 {
        struct bgp *bgp;
        struct in_addr vtep_ip;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
        vtep_ip.s_addr = 0;
-       if (argc == (idx + 1 + 5) && argv[idx + 5]->arg) {
+       if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
+           || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
                if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
                        vty_out(vty, "%% Malformed VTEP IP address\n");
                        return CMD_WARNING;
                }
        }
 
-       evpn_show_routes_vni_all(vty, bgp, vtep_ip);
+       evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display EVPN import route-target hash table
  */
-DEFUN (show_bgp_l2vpn_evpn_import_rt,
-       show_bgp_l2vpn_evpn_import_rt_cmd,
-       "show bgp l2vpn evpn import-rt",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "Show import route target\n")
+DEFUN(show_bgp_l2vpn_evpn_import_rt, show_bgp_l2vpn_evpn_import_rt_cmd,
+      "show bgp l2vpn evpn import-rt [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "Show import route target\n"
+      JSON_STR)
 {
        struct bgp *bgp;
+       u_char uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       evpn_show_import_rts(vty, bgp);
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
+       evpn_show_import_rts(vty, bgp, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
index fc226428338abe14d18cd105c7c386157528e300..40d6fd7bfd4c6885e3ce754627d75c806fc1d81a 100644 (file)
@@ -6227,7 +6227,8 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
 }
 
 /* Static function to display route. */
-static void route_vty_out_route(struct prefix *p, struct vty *vty)
+static void route_vty_out_route(struct prefix *p, struct vty *vty,
+                               json_object *json)
 {
        int len;
        u_int32_t destination;
@@ -6250,23 +6251,29 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty)
                len = vty_out(vty, "%s", buf);
        } else if (p->family == AF_EVPN) {
 #if defined(HAVE_CUMULUS)
-               len = vty_out(vty, "%s",
-                             bgp_evpn_route2str((struct prefix_evpn *)p, buf,
-                                                BUFSIZ));
+        if (!json)
+          len = vty_out (vty, "%s",
+                         bgp_evpn_route2str((struct prefix_evpn *)p,
+                                           buf, BUFSIZ));
+        else
+          bgp_evpn_route2json ( (struct prefix_evpn *) p, json);
 #else
                prefix2str(p, buf, PREFIX_STRLEN);
                len = vty_out(vty, "%s", buf);
 #endif
-       } else
+       } else {
                len = vty_out(vty, "%s/%d",
                              inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
                              p->prefixlen);
+       }
 
-       len = 17 - len;
-       if (len < 1)
-               vty_out(vty, "\n%*s", 20, " ");
-       else
-               vty_out(vty, "%*s", len, " ");
+       if (!json) {
+               len = 17 - len;
+               if (len < 1)
+                       vty_out(vty, "\n%*s", 20, " ");
+               else
+                       vty_out(vty, "%*s", len, " ");
+       }
 }
 
 enum bgp_display_type {
@@ -6370,9 +6377,11 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
        if (!json_paths) {
                /* print prefix and mask */
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, json_path);
                else
                        vty_out(vty, "%*s", 17, " ");
+       } else {
+               route_vty_out_route (p, vty, json_path);
        }
 
        /* Print attribute */
@@ -6668,7 +6677,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
                        json_net, "addrPrefix",
                        inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
        else
-               route_vty_out_route(p, vty);
+               route_vty_out_route(p, vty, NULL);
 
        /* Print attribute */
        if (attr) {
@@ -6801,7 +6810,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
        /* print prefix and mask */
        if (json == NULL) {
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, NULL);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -6916,7 +6925,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
 
        /* print prefix and mask */
        if (!display)
-               route_vty_out_route(p, vty);
+               route_vty_out_route(p, vty, NULL);
        else
                vty_out(vty, "%*s", 17, " ");
 
@@ -6985,7 +6994,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
        /* print prefix and mask */
        if (!use_json) {
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, NULL);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -7054,7 +7063,7 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p,
        /* print prefix and mask */
        if (!use_json) {
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, NULL);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -8336,6 +8345,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
 #if defined(HAVE_CUMULUS)
        char buf3[EVPN_ROUTE_STRLEN];
 #endif
+       char  prefix_str[BUFSIZ];
        int count = 0;
        int best = 0;
        int suppress = 0;
@@ -8357,10 +8367,9 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                if (has_valid_label)
                        json_object_int_add(json, "localLabel", label);
 
-               json_object_string_add(json, "prefix",
-                                      inet_ntop(p->family, &p->u.prefix, buf2,
-                                                INET6_ADDRSTRLEN));
-               json_object_int_add(json, "prefixlen", p->prefixlen);
+               json_object_string_add (json, "prefix",
+                                       prefix2str (p, prefix_str,
+                                                   sizeof (prefix_str)));
        } else {
 #if defined(HAVE_CUMULUS)
                if (safi == SAFI_EVPN)