]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_evpn_vty.c
fix coding style
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
index 4850a8f13a8986b12c35d3d0cb43e039474ace26..e8e986d1fcd93aaa370844032b9e479e3646c84a 100644 (file)
 #include "bgpd/bgp_vpn.h"
 #include "bgpd/bgp_evpn_vty.h"
 #include "bgpd/bgp_evpn.h"
+#include "bgpd/bgp_evpn_private.h"
+#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_vty.h"
 
 #define SHOW_DISPLAY_STANDARD 0
 #define SHOW_DISPLAY_TAGS 1
 #define SHOW_DISPLAY_OVERLAY 2
+#define VNI_STR_LEN          32
 
-static int
-bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
-                     enum bgp_show_type type, void *output_arg, int option,
-                     u_char use_json)
+/*
+ * Context for VNI hash walk - used by callbacks.
+ */
+struct vni_walk_ctx {
+       struct bgp *bgp;
+       struct vty *vty;
+       struct in_addr vtep_ip;
+       json_object *json;
+};
+
+struct evpn_config_write {
+       int write;
+       struct vty *vty;
+};
+
+#if defined(HAVE_CUMULUS)
+static void display_import_rt(struct vty *vty, struct irt_node *irt,
+                             json_object *json)
+{
+       u_char *pnt;
+       u_char type, sub_type;
+       struct ecommunity_as {
+               as_t as;
+               u_int32_t val;
+       } eas;
+       struct ecommunity_ip {
+               struct in_addr ip;
+               u_int16_t val;
+       } 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 */
+
+       pnt = (u_char *)&irt->rt.val;
+       type = *pnt++;
+       sub_type = *pnt++;
+       if (sub_type != ECOMMUNITY_ROUTE_TARGET)
+               return;
+
+       switch (type) {
+       case ECOMMUNITY_ENCODE_AS:
+               eas.as = (*pnt++ << 8);
+               eas.as |= (*pnt++);
+
+               eas.val = (*pnt++ << 24);
+               eas.val |= (*pnt++ << 16);
+               eas.val |= (*pnt++ << 8);
+               eas.val |= (*pnt++);
+
+               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:
+               memcpy(&eip.ip, pnt, 4);
+               pnt += 4;
+               eip.val = (*pnt++ << 8);
+               eip.val |= (*pnt++);
+
+               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:
+               eas.as = (*pnt++ << 24);
+               eas.as |= (*pnt++ << 16);
+               eas.as |= (*pnt++ << 8);
+               eas.as |= (*pnt++);
+
+               eas.val = (*pnt++ << 8);
+               eas.val |= (*pnt++);
+
+               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;
+       }
+
+       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);
+       }
+
+}
+
+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, json);
+
+       return;
+}
+
+static void bgp_evpn_show_route_rd_header(struct vty *vty,
+                                         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);
+               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);
+               snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
+                        rd_ip.val);
+               break;
+
+       default:
+               snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
+               break;
+       }
+
+       vty_out(vty, "%s\n", rd_str);
+}
+
+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,
+               "Status codes: s suppressed, d damped, h history, "
+               "* valid, > best, i - internal\n");
+       vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
+       vty_out(vty,
+               "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
+       vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n");
+       vty_out(vty, "%s", ri_header);
+}
+
+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, "  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");
+
+       for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
+               ecom_str = ecommunity_ecom2str(ecom,
+                                              ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+
+               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);
+       }
+
+       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);
+
+               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,
+                           json_object *json)
+{
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       int header = 1;
+       u_int32_t prefix_cnt, path_cnt;
+
+       prefix_cnt = path_cnt = 0;
+
+       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, 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++;
+                       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 (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)
+{
+       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);
+
+       if (json)
+               json_object_object_add(json, vni_str, json_vni);
+}
+
+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];
+       char rt_buf[25];
+       char *ecom_str;
+       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, "*");
+
+       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 (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);
+
+               /* 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 (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);
+
+               /* 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");
+       }
+}
+#endif /* HAVE_CUMULUS */
+
+static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
+                                enum bgp_show_type type, void *output_arg,
+                                int option, u_char use_json)
 {
        afi_t afi = AFI_L2VPN;
        struct bgp *bgp;
@@ -49,12 +543,6 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
        struct bgp_info *ri;
        int rd_header;
        int header = 1;
-       char v4_header[] =
-           "   Network          Next Hop            Metric LocPrf Weight Path%s";
-       char v4_header_tag[] =
-           "   Network          Next Hop      In tag/Out tag%s";
-       char v4_header_overlay[] =
-           "   Network          Next Hop      EthTag    Overlay Index   RouterMac%s";
 
        unsigned long output_count = 0;
        unsigned long total_count = 0;
@@ -67,8 +555,9 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
        bgp = bgp_get_default();
        if (bgp == NULL) {
                if (!use_json)
-                       vty_out(vty, "No BGP process is configured%s",
-                               VTY_NEWLINE);
+                       vty_out(vty, "No BGP process is configured\n");
+               else
+                       vty_out(vty, "{}\n");
                return CMD_WARNING;
        }
 
@@ -93,7 +582,7 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
        for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
             rn = bgp_route_next(rn)) {
                if (use_json)
-                       continue;       /* XXX json TODO */
+                       continue; /* XXX json TODO */
 
                if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
                        continue;
@@ -107,66 +596,57 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                        total_count++;
                                        if (type == bgp_show_type_neighbor) {
                                                union sockunion *su =
-                                                   output_arg;
+                                                       output_arg;
 
                                                if (ri->peer->su_remote == NULL
-                                                   || !sockunion_same(ri->
-                                                                      peer->
-                                                                      su_remote,
-                                                                      su))
+                                                   || !sockunion_same(
+                                                              ri->peer->su_remote,
+                                                              su))
                                                        continue;
                                        }
                                        if (header == 0) {
                                                if (use_json) {
-                                                       if (option ==
-                                                           SHOW_DISPLAY_TAGS) {
-                                                               json_object_int_add
-                                                                   (json,
-                                                                    "bgpTableVersion",
-                                                                    0);
-                                                               json_object_string_add
-                                                                   (json,
-                                                                    "bgpLocalRouterId",
-                                                                    inet_ntoa
-                                                                    (bgp->
-                                                                     router_id));
-                                                               json_object_object_add
-                                                                   (json,
-                                                                    "bgpStatusCodes",
-                                                                    json_scode);
-                                                               json_object_object_add
-                                                                   (json,
-                                                                    "bgpOriginCodes",
-                                                                    json_ocode);
+                                                       if (option
+                                                           == SHOW_DISPLAY_TAGS) {
+                                                               json_object_int_add(
+                                                                       json,
+                                                                       "bgpTableVersion",
+                                                                       0);
+                                                               json_object_string_add(
+                                                                       json,
+                                                                       "bgpLocalRouterId",
+                                                                       inet_ntoa(
+                                                                               bgp->router_id));
+                                                               json_object_object_add(
+                                                                       json,
+                                                                       "bgpStatusCodes",
+                                                                       json_scode);
+                                                               json_object_object_add(
+                                                                       json,
+                                                                       "bgpOriginCodes",
+                                                                       json_ocode);
                                                        }
                                                } else {
-                                                       if (option ==
-                                                           SHOW_DISPLAY_TAGS)
+                                                       if (option
+                                                           == SHOW_DISPLAY_TAGS)
                                                                vty_out(vty,
-                                                                       v4_header_tag,
-                                                                       VTY_NEWLINE);
-                                                       else if (option ==
-                                                                SHOW_DISPLAY_OVERLAY)
+                                                                       V4_HEADER_TAG);
+                                                       else if (
+                                                               option
+                                                               == SHOW_DISPLAY_OVERLAY)
                                                                vty_out(vty,
-                                                                       v4_header_overlay,
-                                                                       VTY_NEWLINE);
+                                                                       V4_HEADER_OVERLAY);
                                                        else {
                                                                vty_out(vty,
-                                                                       "BGP table version is 0, local router ID is %s%s",
-                                                                       inet_ntoa
-                                                                       (bgp->
-                                                                        router_id),
-                                                                       VTY_NEWLINE);
+                                                                       "BGP table version is 0, local router ID is %s\n",
+                                                                       inet_ntoa(
+                                                                               bgp->router_id));
                                                                vty_out(vty,
-                                                                       "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
-                                                                       VTY_NEWLINE);
+                                                                       "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
                                                                vty_out(vty,
-                                                                       "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
-                                                                       VTY_NEWLINE,
-                                                                       VTY_NEWLINE);
+                                                                       "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
                                                                vty_out(vty,
-                                                                       v4_header,
-                                                                       VTY_NEWLINE);
+                                                                       V4_HEADER);
                                                        }
                                                }
                                                header = 0;
@@ -194,74 +674,60 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                                if (use_json) {
                                                        char buffer[BUFSIZ];
                                                        if (type == RD_TYPE_AS
-                                                           || type ==
-                                                           RD_TYPE_AS4)
+                                                           || type == RD_TYPE_AS4)
                                                                sprintf(buffer,
                                                                        "%u:%d",
-                                                                       rd_as.
-                                                                       as,
-                                                                       rd_as.
-                                                                       val);
-                                                       else if (type ==
-                                                                RD_TYPE_IP)
+                                                                       rd_as.as,
+                                                                       rd_as.val);
+                                                       else if (type
+                                                                == RD_TYPE_IP)
                                                                sprintf(buffer,
                                                                        "%s:%d",
-                                                                       inet_ntoa
-                                                                       (rd_ip.
-                                                                        ip),
-                                                                       rd_ip.
-                                                                       val);
-                                                       json_object_string_add
-                                                           (json_nroute,
-                                                            "routeDistinguisher",
-                                                            buffer);
+                                                                       inet_ntoa(
+                                                                               rd_ip.ip),
+                                                                       rd_ip.val);
+                                                       json_object_string_add(
+                                                               json_nroute,
+                                                               "routeDistinguisher",
+                                                               buffer);
                                                } else {
                                                        vty_out(vty,
                                                                "Route Distinguisher: ");
                                                        if (type == RD_TYPE_AS)
                                                                vty_out(vty,
                                                                        "as2 %u:%d",
-                                                                       rd_as.
-                                                                       as,
-                                                                       rd_as.
-                                                                       val);
-                                                       else if (type ==
-                                                                RD_TYPE_AS4)
+                                                                       rd_as.as,
+                                                                       rd_as.val);
+                                                       else if (type
+                                                                == RD_TYPE_AS4)
                                                                vty_out(vty,
                                                                        "as4 %u:%d",
-                                                                       rd_as.
-                                                                       as,
-                                                                       rd_as.
-                                                                       val);
-                                                       else if (type ==
-                                                                RD_TYPE_IP)
+                                                                       rd_as.as,
+                                                                       rd_as.val);
+                                                       else if (type
+                                                                == RD_TYPE_IP)
                                                                vty_out(vty,
                                                                        "ip %s:%d",
-                                                                       inet_ntoa
-                                                                       (rd_ip.
-                                                                        ip),
-                                                                       rd_ip.
-                                                                       val);
-                                                       vty_out(vty, "%s",
-                                                               VTY_NEWLINE);
+                                                                       inet_ntoa(
+                                                                               rd_ip.ip),
+                                                                       rd_ip.val);
+                                                       vty_out(vty, "\n\n");
                                                }
                                                rd_header = 0;
                                        }
                                        if (use_json)
                                                json_array =
-                                                   json_object_new_array();
+                                                       json_object_new_array();
                                        else
                                                json_array = NULL;
                                        if (option == SHOW_DISPLAY_TAGS)
-                                               route_vty_out_tag(vty, &rm->p,
-                                                                 ri, 0,
-                                                                 SAFI_EVPN,
-                                                                 json_array);
+                                               route_vty_out_tag(
+                                                       vty, &rm->p, ri, 0,
+                                                       SAFI_EVPN, json_array);
                                        else if (option == SHOW_DISPLAY_OVERLAY)
-                                               route_vty_out_overlay(vty,
-                                                                     &rm->p,
-                                                                     ri, 0,
-                                                                     json_array);
+                                               route_vty_out_overlay(
+                                                       vty, &rm->p, ri, 0,
+                                                       json_array);
                                        else
                                                route_vty_out(vty, &rm->p, ri,
                                                              0, SAFI_EVPN,
@@ -272,11 +738,10 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                }
        }
        if (output_count == 0)
-               vty_out(vty, "No prefixes displayed, %ld exist%s", total_count,
-                       VTY_NEWLINE);
+               vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
        else
-               vty_out(vty, "%sDisplayed %ld out of %ld total prefixes%s",
-                       VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
+               vty_out(vty, "\nDisplayed %ld out of %ld total prefixes\n",
+                       output_count, total_count);
        return CMD_SUCCESS;
 }
 
@@ -304,11 +769,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd,
        int ret;
        struct prefix_rd prd;
 
-       argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+       argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
 
        ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
        if (!ret) {
-               vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+               vty_out(vty, "%% Malformed Route Distinguisher\n");
                return CMD_WARNING;
        }
        return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
@@ -345,11 +810,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
        int ret;
        struct prefix_rd prd;
 
-       argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+       argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
 
        ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
        if (!ret) {
-               vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+               vty_out(vty, "%% Malformed Route Distinguisher\n");
                return CMD_WARNING;
        }
        return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
@@ -375,7 +840,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
        int ret;
        u_char uj = use_json(argc, argv);
 
-       argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+       argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
 
        ret = str2sockunion(argv[idx_ipv4]->arg, &su);
        if (ret < 0) {
@@ -384,13 +849,12 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
                        json_no = json_object_new_object();
                        json_object_string_add(json_no, "warning",
                                               "Malformed address");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "Malformed address: %s%s",
-                               argv[idx_ipv4]->arg, VTY_NEWLINE);
+                       vty_out(vty, "Malformed address: %s\n",
+                               argv[idx_ipv4]->arg);
                return CMD_WARNING;
        }
 
@@ -399,15 +863,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
                if (uj) {
                        json_object *json_no = NULL;
                        json_no = json_object_new_object();
-                       json_object_string_add(json_no, "warning",
-                                              "No such neighbor or address family");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       json_object_string_add(
+                               json_no, "warning",
+                               "No such neighbor or address family");
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "%% No such neighbor or address family%s",
-                               VTY_NEWLINE);
+                       vty_out(vty, "%% No such neighbor or address family\n");
                return CMD_WARNING;
        }
 
@@ -437,8 +900,8 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
        struct prefix_rd prd;
        u_char uj = use_json(argc, argv);
 
-       argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
-       argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+       argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+       argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
 
        ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
        if (!ret) {
@@ -447,13 +910,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
                        json_no = json_object_new_object();
                        json_object_string_add(json_no, "warning",
                                               "Malformed Route Distinguisher");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "%% Malformed Route Distinguisher%s",
-                               VTY_NEWLINE);
+                       vty_out(vty, "%% Malformed Route Distinguisher\n");
                return CMD_WARNING;
        }
 
@@ -464,13 +925,12 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
                        json_no = json_object_new_object();
                        json_object_string_add(json_no, "warning",
                                               "Malformed address");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "Malformed address: %s%s",
-                               argv[idx_ext_community]->arg, VTY_NEWLINE);
+                       vty_out(vty, "Malformed address: %s\n",
+                               argv[idx_ext_community]->arg);
                return CMD_WARNING;
        }
 
@@ -479,15 +939,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
                if (uj) {
                        json_object *json_no = NULL;
                        json_no = json_object_new_object();
-                       json_object_string_add(json_no, "warning",
-                                              "No such neighbor or address family");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       json_object_string_add(
+                               json_no, "warning",
+                               "No such neighbor or address family");
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "%% No such neighbor or address family%s",
-                               VTY_NEWLINE);
+                       vty_out(vty, "%% No such neighbor or address family\n");
                return CMD_WARNING;
        }
 
@@ -514,7 +973,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
        union sockunion su;
        u_char uj = use_json(argc, argv);
 
-       argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+       argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
 
        ret = str2sockunion(argv[idx_ipv4]->arg, &su);
        if (ret < 0) {
@@ -523,13 +982,12 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
                        json_no = json_object_new_object();
                        json_object_string_add(json_no, "warning",
                                               "Malformed address");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "Malformed address: %s%s",
-                               argv[idx_ipv4]->arg, VTY_NEWLINE);
+                       vty_out(vty, "Malformed address: %s\n",
+                               argv[idx_ipv4]->arg);
                return CMD_WARNING;
        }
        peer = peer_lookup(NULL, &su);
@@ -537,15 +995,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
                if (uj) {
                        json_object *json_no = NULL;
                        json_no = json_object_new_object();
-                       json_object_string_add(json_no, "warning",
-                                              "No such neighbor or address family");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       json_object_string_add(
+                               json_no, "warning",
+                               "No such neighbor or address family");
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "%% No such neighbor or address family%s",
-                               VTY_NEWLINE);
+                       vty_out(vty, "%% No such neighbor or address family\n");
                return CMD_WARNING;
        }
 
@@ -574,8 +1031,8 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
        union sockunion su;
        u_char uj = use_json(argc, argv);
 
-       argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
-       argv_find (argv, argc, "A.B.C.D", &idx_ipv4);
+       argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+       argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
 
        ret = str2sockunion(argv[idx_ipv4]->arg, &su);
        if (ret < 0) {
@@ -584,13 +1041,12 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
                        json_no = json_object_new_object();
                        json_object_string_add(json_no, "warning",
                                               "Malformed address");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "Malformed address: %s%s",
-                               argv[idx_ext_community]->arg, VTY_NEWLINE);
+                       vty_out(vty, "Malformed address: %s\n",
+                               argv[idx_ext_community]->arg);
                return CMD_WARNING;
        }
        peer = peer_lookup(NULL, &su);
@@ -598,15 +1054,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
                if (uj) {
                        json_object *json_no = NULL;
                        json_no = json_object_new_object();
-                       json_object_string_add(json_no, "warning",
-                                              "No such neighbor or address family");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       json_object_string_add(
+                               json_no, "warning",
+                               "No such neighbor or address family");
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "%% No such neighbor or address family%s",
-                               VTY_NEWLINE);
+                       vty_out(vty, "%% No such neighbor or address family\n");
                return CMD_WARNING;
        }
 
@@ -617,13 +1072,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
                        json_no = json_object_new_object();
                        json_object_string_add(json_no, "warning",
                                               "Malformed Route Distinguisher");
-                       vty_out(vty, "%s%s",
-                               json_object_to_json_string(json_no),
-                               VTY_NEWLINE);
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string(json_no));
                        json_object_free(json_no);
                } else
-                       vty_out(vty, "%% Malformed Route Distinguisher%s",
-                               VTY_NEWLINE);
+                       vty_out(vty, "%% Malformed Route Distinguisher\n");
                return CMD_WARNING;
        }
 
@@ -642,8 +1095,8 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
       "Display BGP Overlay Information for prefixes\n")
 {
        return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
-                                    SHOW_DISPLAY_OVERLAY, use_json(argc,
-                                                                   argv));
+                                    SHOW_DISPLAY_OVERLAY,
+                                    use_json(argc, argv));
 }
 
 DEFUN(show_ip_bgp_evpn_rd_overlay,
@@ -662,16 +1115,16 @@ DEFUN(show_ip_bgp_evpn_rd_overlay,
        int ret;
        struct prefix_rd prd;
 
-       argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
+       argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
 
        ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
        if (!ret) {
-               vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+               vty_out(vty, "%% Malformed Route Distinguisher\n");
                return CMD_WARNING;
        }
        return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
-                                    SHOW_DISPLAY_OVERLAY, use_json(argc,
-                                                                   argv));
+                                    SHOW_DISPLAY_OVERLAY,
+                                    use_json(argc, argv));
 }
 
 /* For testing purpose, static route of MPLS-VPN. */
@@ -705,14 +1158,13 @@ DEFUN(evpnrt5_network,
        int idx_ethtag = 5;
        int idx_routermac = 13;
        int idx_rmap = 15;
-       return bgp_static_set_safi(SAFI_EVPN, vty,
-                                  argv[idx_ipv4_prefixlen]->arg,
-                                  argv[idx_ext_community]->arg,
-                                  argv[idx_word]->arg,
-                                  argv[idx_rmap] ? argv[idx_gwip]->arg : NULL,
-                                  EVPN_IP_PREFIX, argv[idx_esi]->arg,
-                                  argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
-                                  argv[idx_routermac]->arg);
+       return bgp_static_set_safi(
+               AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
+               argv[idx_ext_community]->arg, argv[idx_word]->arg,
+               argv[idx_rmap] ? argv[idx_gwip]->arg : NULL,
+               BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
+               argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
+               argv[idx_routermac]->arg);
 }
 
 /* For testing purpose, static route of MPLS-VPN. */
@@ -739,30 +1191,2229 @@ DEFUN(no_evpnrt5_network,
        int idx_ethtag = 6;
        int idx_esi = 10;
        int idx_gwip = 12;
-       return bgp_static_unset_safi(SAFI_EVPN, vty,
-                                    argv[idx_ipv4_prefixlen]->arg,
-                                    argv[idx_ext_community]->arg,
-                                    argv[idx_label]->arg, EVPN_IP_PREFIX,
-                                    argv[idx_esi]->arg, argv[idx_gwip]->arg,
-                                    argv[idx_ethtag]->arg);
+       return bgp_static_unset_safi(
+               AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
+               argv[idx_ext_community]->arg, argv[idx_label]->arg,
+               BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
+               argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
 }
 
-void bgp_ethernetvpn_init(void)
+#if defined(HAVE_CUMULUS)
+static void evpn_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn,
+                               struct list *rtl)
 {
-       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
-       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
-       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
-       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
-       install_element(VIEW_NODE,
-                       &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
-       install_element(VIEW_NODE,
-                       &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
-       install_element(VIEW_NODE,
-                       &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
-       install_element(VIEW_NODE,
-                       &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
-       install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
-       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
-       install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
-       install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
+       struct listnode *node, *nnode, *node_to_del;
+       struct ecommunity *ecom, *ecom_auto;
+       struct ecommunity_val eval;
+
+       encode_route_target_as((bgp->as & 0xFFFF), vpn->vni, &eval);
+
+       ecom_auto = ecommunity_new();
+       ecommunity_add_val(ecom_auto, &eval);
+       node_to_del = NULL;
+
+       for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
+               if (ecommunity_match(ecom, ecom_auto)) {
+                       ecommunity_free(&ecom);
+                       node_to_del = node;
+               }
+       }
+
+       if (node_to_del)
+               list_delete_node(rtl, node_to_del);
+
+       ecommunity_free(&ecom_auto);
+}
+
+static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
+{
+       evpn_rt_delete_auto(bgp, vpn, vpn->import_rtl);
+}
+
+static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
+{
+       evpn_rt_delete_auto(bgp, vpn, vpn->export_rtl);
+}
+
+/*
+ * Configure the Import RTs for a VNI (vty handler). Caller expected to
+ * check that this is a change.
+ */
+static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
+                                    struct ecommunity *ecomadd)
+{
+       /* If the VNI is "live", we need to uninstall routes using the current
+        * import RT(s) first before we update the import RT, and subsequently
+        * install routes.
+        */
+       if (is_vni_live(vpn))
+               bgp_evpn_uninstall_routes(bgp, vpn);
+
+       /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
+       bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
+
+       /* If the auto route-target is in use we must remove it */
+       evpn_import_rt_delete_auto(bgp, vpn);
+
+       /* Add new RT and rebuild the RT to VNI mapping */
+       listnode_add_sort(vpn->import_rtl, ecomadd);
+
+       SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
+       bgp_evpn_map_vni_to_its_rts(bgp, vpn);
+
+       /* Install routes that match new import RT */
+       if (is_vni_live(vpn))
+               bgp_evpn_install_routes(bgp, vpn);
+}
+
+/*
+ * Unconfigure Import RT(s) for a VNI (vty handler).
+ */
+static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
+                                      struct ecommunity *ecomdel)
+{
+       struct listnode *node, *nnode, *node_to_del;
+       struct ecommunity *ecom;
+
+       /* Along the lines of "configure" except we have to reset to the
+        * automatic value.
+        */
+       if (is_vni_live(vpn))
+               bgp_evpn_uninstall_routes(bgp, vpn);
+
+       /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
+       bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
+
+       /* Delete all import RTs */
+       if (ecomdel == NULL) {
+               for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom))
+                       ecommunity_free(&ecom);
+
+               list_delete_all_node(vpn->import_rtl);
+       }
+
+       /* Delete a specific import RT */
+       else {
+               node_to_del = NULL;
+
+               for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
+                       if (ecommunity_match(ecom, ecomdel)) {
+                               ecommunity_free(&ecom);
+                               node_to_del = node;
+                               break;
+                       }
+               }
+
+               if (node_to_del)
+                       list_delete_node(vpn->import_rtl, node_to_del);
+       }
+
+       /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
+       if (list_isempty(vpn->import_rtl)) {
+               UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
+               bgp_evpn_derive_auto_rt_import(bgp, vpn);
+       }
+       /* Rebuild the RT to VNI mapping */
+       else
+               bgp_evpn_map_vni_to_its_rts(bgp, vpn);
+
+       /* Install routes that match new import RT */
+       if (is_vni_live(vpn))
+               bgp_evpn_install_routes(bgp, vpn);
+}
+
+/*
+ * Configure the Export RT for a VNI (vty handler). Caller expected to
+ * check that this is a change. Note that only a single export RT is
+ * allowed for a VNI and any change to configuration is implemented as
+ * a "replace" (similar to other configuration).
+ */
+static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
+                                    struct ecommunity *ecomadd)
+{
+       /* If the auto route-target is in use we must remove it */
+       evpn_export_rt_delete_auto(bgp, vpn);
+
+       listnode_add_sort(vpn->export_rtl, ecomadd);
+       SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
+
+       if (is_vni_live(vpn))
+               bgp_evpn_handle_export_rt_change(bgp, vpn);
+}
+
+/*
+ * Unconfigure the Export RT for a VNI (vty handler)
+ */
+static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
+                                      struct ecommunity *ecomdel)
+{
+       struct listnode *node, *nnode, *node_to_del;
+       struct ecommunity *ecom;
+
+       /* Delete all export RTs */
+       if (ecomdel == NULL) {
+               /* Reset to default and process all routes. */
+               for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom))
+                       ecommunity_free(&ecom);
+
+               list_delete_all_node(vpn->export_rtl);
+       }
+
+       /* Delete a specific export RT */
+       else {
+               node_to_del = NULL;
+
+               for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
+                       if (ecommunity_match(ecom, ecomdel)) {
+                               ecommunity_free(&ecom);
+                               node_to_del = node;
+                               break;
+                       }
+               }
+
+               if (node_to_del)
+                       list_delete_node(vpn->export_rtl, node_to_del);
+       }
+
+       if (list_isempty(vpn->export_rtl)) {
+               UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
+               bgp_evpn_derive_auto_rt_export(bgp, vpn);
+       }
+
+       if (is_vni_live(vpn))
+               bgp_evpn_handle_export_rt_change(bgp, vpn);
+}
+
+/*
+ * Configure RD for a VNI (vty handler)
+ */
+static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
+                             struct prefix_rd *rd)
+{
+       /* 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,
+        * need to re-advertise.
+        */
+       if (is_vni_live(vpn))
+               bgp_evpn_handle_rd_change(bgp, vpn, 1);
+
+       /* update RD */
+       memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
+       SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
+
+       if (is_vni_live(vpn))
+               bgp_evpn_handle_rd_change(bgp, vpn, 0);
+}
+
+/*
+ * Unconfigure RD for a VNI (vty handler)
+ */
+static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
+{
+       /* If the VNI is "live", we need to delete and withdraw this VNI's
+        * local routes with the prior RD first. Then, after resetting RD
+        * to automatic value, need to re-advertise.
+        */
+       if (is_vni_live(vpn))
+               bgp_evpn_handle_rd_change(bgp, vpn, 1);
+
+       /* reset RD to default */
+       bgp_evpn_derive_auto_rd(bgp, vpn);
+
+       if (is_vni_live(vpn))
+               bgp_evpn_handle_rd_change(bgp, vpn, 0);
+}
+
+/*
+ * Create VNI, if not already present (VTY handler). Mark as configured.
+ */
+static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
+{
+       struct bgpevpn *vpn;
+
+       if (!bgp->vnihash)
+               return NULL;
+
+       vpn = bgp_evpn_lookup_vni(bgp, vni);
+       if (!vpn) {
+               vpn = bgp_evpn_new(bgp, vni, bgp->router_id);
+               if (!vpn) {
+                       zlog_err(
+                               "%u: Failed to allocate VNI entry for VNI %u - at Config",
+                               bgp->vrf_id, vni);
+                       return NULL;
+               }
+       }
+
+       /* Mark as configured. */
+       SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
+       return vpn;
+}
+
+/*
+ * Delete VNI. If VNI does not exist in the system (i.e., just
+ * configuration), all that is needed is to free it. Otherwise,
+ * any parameters configured for the VNI need to be reset (with
+ * appropriate action) and the VNI marked as unconfigured; the
+ * VNI will continue to exist, purely as a "learnt" entity.
+ */
+static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
+{
+       assert(bgp->vnihash);
+
+       if (!is_vni_live(vpn)) {
+               bgp_evpn_free(bgp, vpn);
+               return 0;
+       }
+
+       /* We need to take the unconfigure action for each parameter of this VNI
+        * that is configured. Some optimization is possible, but not worth the
+        * additional code for an operation that should be pretty rare.
+        */
+       UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
+
+       /* First, deal with the export side - RD and export RT changes. */
+       if (is_rd_configured(vpn))
+               evpn_unconfigure_rd(bgp, vpn);
+       if (is_export_rt_configured(vpn))
+               evpn_unconfigure_export_rt(bgp, vpn, NULL);
+
+       /* Next, deal with the import side. */
+       if (is_import_rt_configured(vpn))
+               evpn_unconfigure_import_rt(bgp, vpn, NULL);
+
+       return 0;
+}
+
+/*
+ * Display import RT mapping to VNIs (vty handler)
+ */
+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,
+               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,
+                                    json_object *json)
+{
+       u_int32_t num_vnis;
+       struct vni_walk_ctx wctx;
+
+       num_vnis = hashcount(bgp->vnihash);
+       if (!num_vnis)
+               return;
+       memset(&wctx, 0, sizeof(struct vni_walk_ctx));
+       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);
+}
+
+/*
+ * 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,
+                                         json_object *json)
+{
+       struct bgpevpn *vpn;
+       struct prefix_evpn p;
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       u_int32_t path_cnt = 0;
+       afi_t afi;
+       safi_t safi;
+       json_object *json_paths = NULL;
+
+       afi = AFI_L2VPN;
+       safi = SAFI_EVPN;
+
+       /* Locate VNI. */
+       vpn = bgp_evpn_lookup_vni(bgp, vni);
+       if (!vpn) {
+               vty_out(vty, "VNI not found\n");
+               return;
+       }
+
+       /* See if route exists. */
+       build_evpn_type3_prefix(&p, orig_ip);
+       rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+       if (!rn || !rn->info) {
+               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, json);
+
+       /* 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,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
+               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);
+       }
+}
+
+/*
+ * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
+ * By definition, only matching type-2 route will be displayed.
+ */
+static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
+                                     vni_t vni, struct ethaddr *mac,
+                                     struct ipaddr *ip, json_object *json)
+{
+       struct bgpevpn *vpn;
+       struct prefix_evpn p;
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       u_int32_t path_cnt = 0;
+       afi_t afi;
+       safi_t safi;
+       json_object *json_paths = NULL;
+
+       afi = AFI_L2VPN;
+       safi = SAFI_EVPN;
+
+       /* Locate VNI. */
+       vpn = bgp_evpn_lookup_vni(bgp, vni);
+       if (!vpn) {
+               if (!json)
+                       vty_out(vty, "VNI not found\n");
+               return;
+       }
+
+       /* See if route exists. Look for both non-sticky and sticky. */
+       build_evpn_type2_prefix(&p, mac, ip);
+       rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+       if (!rn || !rn->info) {
+               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, json);
+
+       /* 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,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
+               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);
+       }
+}
+
+/*
+ * Display EVPN routes for a VNI - vty handler.
+ * If 'type' is non-zero, only routes matching that type are shown.
+ * 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,
+                                json_object *json)
+{
+       struct bgpevpn *vpn;
+
+       /* Locate VNI. */
+       vpn = bgp_evpn_lookup_vni(bgp, vni);
+       if (!vpn) {
+               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, json);
+}
+
+/*
+ * Display BGP EVPN routing table -- for specific RD and MAC and/or
+ * IP (vty handler). By definition, only matching type-2 route will be
+ * displayed.
+ */
+static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
+                                    struct prefix_rd *prd, struct ethaddr *mac,
+                                    struct ipaddr *ip, json_object *json)
+{
+       struct prefix_evpn p;
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       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;
+
+       /* See if route exists. Look for both non-sticky and sticky. */
+       build_evpn_type2_prefix(&p, mac, ip);
+       rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
+                                (struct prefix *)&p, prd);
+       if (!rn || !rn->info) {
+               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, json);
+
+       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,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
+               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);
+       }
+}
+
+/*
+ * Display BGP EVPN routing table -- for specific RD (vty handler)
+ * 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,
+                              json_object *json)
+{
+       struct bgp_node *rd_rn;
+       struct bgp_table *table;
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       int rd_header = 1;
+       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 && !json) {
+                               vty_out(vty,
+                                       "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
+                                       "[MAC]\n");
+                               vty_out(vty,
+                                       "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
+                                       "[OrigIP]\n\n");
+                               rd_header = 0;
+                       }
+
+                       /* Prefix and num paths displayed once per prefix. */
+                       route_vty_out_detail_header(vty, bgp, rn, prd, afi,
+                                                   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,
+                                            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 (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,
+                                json_object *json)
+{
+       struct bgp_node *rd_rn;
+       struct bgp_table *table;
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       int header = 1;
+       int rd_header;
+       afi_t afi;
+       safi_t safi;
+       u_int32_t prefix_cnt, path_cnt;
+
+       afi = AFI_L2VPN;
+       safi = SAFI_EVPN;
+       prefix_cnt = path_cnt = 0;
+
+       /* EVPN routing table is a 2-level table with the first level being
+        * the RD.
+        */
+       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;
+
+                       if (rn->info) {
+                               /* Overall header/legend displayed once. */
+                               if (header) {
+                                       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, 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,
+                                             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 (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,
+                         json_object *json)
+{
+       struct bgpevpn *vpn;
+
+       vpn = bgp_evpn_lookup_vni(bgp, vni);
+       if (!vpn) {
+               if (json) {
+                       vty_out(vty, "{}\n");
+               } else {
+                       vty_out(vty, "VNI not found\n");
+                       return;
+               }
+       }
+
+       display_vni(vty, vpn, json);
+}
+
+/*
+ * Display a VNI (upon user query).
+ */
+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;
+
+       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,
+                    args);
+}
+
+/*
+ * evpn - enable advertisement of default g/w
+ */
+static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
+{
+       if (!vpn) {
+               if (bgp->advertise_gw_macip)
+                       return;
+
+               bgp->advertise_gw_macip = 1;
+               bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
+       } else {
+               if (vpn->advertise_gw_macip)
+                       return;
+
+               vpn->advertise_gw_macip = 1;
+               bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
+                                            vpn->vni);
+       }
+       return;
+}
+
+/*
+ * evpn - disable advertisement of default g/w
+ */
+static void evpn_unset_advertise_default_gw(struct bgp *bgp,
+                                           struct bgpevpn *vpn)
+{
+       if (!vpn) {
+               if (!bgp->advertise_gw_macip)
+                       return;
+
+               bgp->advertise_gw_macip = 0;
+               bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
+       } else {
+               if (!vpn->advertise_gw_macip)
+                       return;
+
+               vpn->advertise_gw_macip = 0;
+               bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
+                                            vpn->vni);
+       }
+       return;
+}
+
+/*
+ * EVPN (VNI advertisement) enabled. Register with zebra.
+ */
+static void evpn_set_advertise_all_vni(struct bgp *bgp)
+{
+       bgp->advertise_all_vni = 1;
+       bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
+}
+
+/*
+ * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
+ * cache, EVPN routes (delete and withdraw from peers).
+ */
+static void evpn_unset_advertise_all_vni(struct bgp *bgp)
+{
+       bgp->advertise_all_vni = 0;
+       bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
+       bgp_evpn_cleanup_on_disable(bgp);
+}
+#endif /* HAVE_CUMULUS */
+
+static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
+{
+       char buf1[INET6_ADDRSTRLEN];
+       afi_t afi = AFI_L2VPN;
+       safi_t safi = SAFI_EVPN;
+       char *ecom_str;
+       struct listnode *node, *nnode;
+       struct ecommunity *ecom;
+
+       if (is_vni_configured(vpn)) {
+               bgp_config_write_family_header(vty, afi, safi, write);
+               vty_out(vty, "  vni %d\n", vpn->vni);
+               if (is_rd_configured(vpn))
+                       vty_out(vty, "   rd %s\n",
+                               prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
+
+               if (is_import_rt_configured(vpn)) {
+                       for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
+                                              ecom)) {
+                               ecom_str = ecommunity_ecom2str(
+                                       ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+                               vty_out(vty, "   route-target import %s\n",
+                                       ecom_str);
+                               XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+                       }
+               }
+
+               if (is_export_rt_configured(vpn)) {
+                       for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
+                                              ecom)) {
+                               ecom_str = ecommunity_ecom2str(
+                                       ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+                               vty_out(vty, "   route-target export %s\n",
+                                       ecom_str);
+                               XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+                       }
+               }
+
+               if (vpn->advertise_gw_macip)
+                       vty_out(vty, "   advertise-default-gw\n");
+
+               vty_out(vty, "  exit-vni\n");
+       }
+}
+
+static void write_vni_config_for_entry(struct hash_backet *backet,
+                                      struct evpn_config_write *cfg)
+{
+       struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
+       write_vni_config(cfg->vty, vpn, &cfg->write);
+}
+
+#if defined(HAVE_CUMULUS)
+DEFUN (bgp_evpn_advertise_default_gw_vni,
+       bgp_evpn_advertise_default_gw_vni_cmd,
+       "advertise-default-gw",
+       "Advertise defualt g/w mac-ip routes in EVPN for a VNI\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       if (!vpn)
+               return CMD_WARNING;
+
+       evpn_set_advertise_default_gw(bgp, vpn);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_advertise_default_vni_gw,
+       no_bgp_evpn_advertise_default_gw_vni_cmd,
+       "no advertise-default-gw",
+       NO_STR
+       "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       if (!vpn)
+               return CMD_WARNING;
+
+       evpn_unset_advertise_default_gw(bgp, vpn);
+
+       return CMD_SUCCESS;
+}
+
+
+DEFUN (bgp_evpn_advertise_default_gw,
+       bgp_evpn_advertise_default_gw_cmd,
+       "advertise-default-gw",
+       "Advertise All defualt g/w mac-ip routes in EVPN\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       evpn_set_advertise_default_gw(bgp, NULL);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_advertise_default_gw,
+       no_bgp_evpn_advertise_default_gw_cmd,
+       "no advertise-default-gw",
+       NO_STR
+       "Withdraw All default g/w mac-ip routes from EVPN\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       evpn_unset_advertise_default_gw(bgp, NULL);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (bgp_evpn_advertise_all_vni,
+       bgp_evpn_advertise_all_vni_cmd,
+       "advertise-all-vni",
+       "Advertise All local VNIs\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+
+       if (!bgp)
+               return CMD_WARNING;
+       evpn_set_advertise_all_vni(bgp);
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_advertise_all_vni,
+       no_bgp_evpn_advertise_all_vni_cmd,
+       "no advertise-all-vni",
+       NO_STR
+       "Advertise All local VNIs\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+
+       if (!bgp)
+               return CMD_WARNING;
+       evpn_unset_advertise_all_vni(bgp);
+       return CMD_SUCCESS;
+}
+
+/*
+ * 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)] [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)
+               return CMD_WARNING;
+
+       if (!argv_find(argv, argc, "evpn", &idx))
+               return CMD_WARNING;
+
+       if (uj)
+               json = json_object_new_object();
+
+       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[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;
+}
+
+/*
+ * 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)
+{
+       u_char uj = use_json(argc, argv);
+       return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
+}
+
+/*
+ * 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>] [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 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 (uj)
+               json = json_object_new_object();
+
+       /* get the type */
+       if (argv_find(argv, argc, "type", &type_idx)) {
+               /* Specific type is requested */
+               if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
+                       type = BGP_EVPN_MAC_IP_ROUTE;
+               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, 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>] [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 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;
+
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
+       /* 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;
+               }
+       }
+
+       /* get the type */
+       if (argv_find(argv, argc, "type", &type_idx)) {
+               /* Specific type is requested */
+               if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
+                       type = BGP_EVPN_MAC_IP_ROUTE;
+               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, 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] [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;
+
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
+       /* 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;
+               }
+       }
+
+       /* 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;
+               }
+       }
+
+       /* 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, 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>] [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;
+
+       vtep_ip.s_addr = 0;
+
+       vni = strtoul(argv[idx + 3]->arg, NULL, 10);
+
+       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;
+                       else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
+                               type = BGP_EVPN_IMET_ROUTE;
+                       else
+                               return CMD_WARNING;
+               } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
+                       if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
+                               vty_out(vty, "%% Malformed VTEP IP address\n");
+                               return CMD_WARNING;
+                       }
+               } else
+                       return CMD_WARNING;
+       }
+
+       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] [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 ((!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, 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 [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, 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] [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 ((!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, 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 [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;
+
+       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;
+}
+
+#if defined(HAVE_CUMULUS)
+ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
+            "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
+            "Show VNI\n"
+            "VNI number\n")
+
+ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
+            "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
+            "Summary of BGP neighbor status\n"
+            JSON_STR)
+
+ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
+            "show bgp evpn route [type <macip|multicast>]",
+            SHOW_STR BGP_STR EVPN_HELP_STR
+            "EVPN route information\n"
+            "Specify Route type\n"
+            "MAC-IP (Type-2) route\n"
+            "Multicast (Type-3) route\n")
+
+ALIAS_HIDDEN(
+       show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
+       "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
+       SHOW_STR BGP_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")
+
+ALIAS_HIDDEN(
+       show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
+       "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
+       SHOW_STR BGP_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")
+
+ALIAS_HIDDEN(
+       show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
+       "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
+       SHOW_STR BGP_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")
+
+ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
+            show_bgp_evpn_route_vni_macip_cmd,
+            "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
+            SHOW_STR BGP_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")
+
+ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
+            show_bgp_evpn_route_vni_multicast_cmd,
+            "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
+            SHOW_STR BGP_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")
+
+ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
+            "show bgp evpn route vni all [vtep A.B.C.D]",
+            SHOW_STR BGP_STR EVPN_HELP_STR
+            "EVPN route information\n"
+            "VXLAN Network Identifier\n"
+            "All VNIs\n"
+            "Remote VTEP\n"
+            "Remote VTEP IP address\n")
+
+ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
+            "show bgp evpn import-rt",
+            SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
+#endif
+
+DEFUN_NOSH (bgp_evpn_vni,
+            bgp_evpn_vni_cmd,
+            "vni (1-16777215)",
+            "VXLAN Network Identifier\n"
+            "VNI number\n")
+{
+       vni_t vni;
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       struct bgpevpn *vpn;
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       vni = strtoul(argv[1]->arg, NULL, 10);
+
+       /* Create VNI, or mark as configured. */
+       vpn = evpn_create_update_vni(bgp, vni);
+       if (!vpn) {
+               vty_out(vty, "%% Failed to create VNI \n");
+               return CMD_WARNING;
+       }
+
+       VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_vni,
+       no_bgp_evpn_vni_cmd,
+       "no vni (1-16777215)",
+       NO_STR
+       "VXLAN Network Identifier\n"
+       "VNI number\n")
+{
+       vni_t vni;
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       struct bgpevpn *vpn;
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       vni = strtoul(argv[2]->arg, NULL, 10);
+
+       /* Check if we should disallow. */
+       vpn = bgp_evpn_lookup_vni(bgp, vni);
+       if (!vpn) {
+               vty_out(vty, "%% Specified VNI does not exist\n");
+               return CMD_WARNING;
+       }
+       if (!is_vni_configured(vpn)) {
+               vty_out(vty, "%% Specified VNI is not configured\n");
+               return CMD_WARNING;
+       }
+
+       evpn_delete_vni(bgp, vpn);
+       return CMD_SUCCESS;
+}
+
+DEFUN_NOSH (exit_vni,
+            exit_vni_cmd,
+            "exit-vni",
+            "Exit from VNI mode\n")
+{
+       if (vty->node == BGP_EVPN_VNI_NODE)
+               vty->node = BGP_EVPN_NODE;
+       return CMD_SUCCESS;
+}
+
+DEFUN (bgp_evpn_vni_rd,
+       bgp_evpn_vni_rd_cmd,
+       "rd ASN:nn_or_IP-address:nn",
+       "Route Distinguisher\n"
+       "ASN:XX or A.B.C.D:XX\n")
+{
+       struct prefix_rd prd;
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+       int ret;
+
+       if (!bgp || !vpn)
+               return CMD_WARNING;
+
+       ret = str2prefix_rd(argv[1]->arg, &prd);
+       if (!ret) {
+               vty_out(vty, "%% Malformed Route Distinguisher\n");
+               return CMD_WARNING;
+       }
+
+       /* If same as existing value, there is nothing more to do. */
+       if (bgp_evpn_rd_matches_existing(vpn, &prd))
+               return CMD_SUCCESS;
+
+       /* Configure or update the RD. */
+       evpn_configure_rd(bgp, vpn, &prd);
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_vni_rd,
+       no_bgp_evpn_vni_rd_cmd,
+       "no rd ASN:nn_or_IP-address:nn",
+       NO_STR
+       "Route Distinguisher\n"
+       "ASN:XX or A.B.C.D:XX\n")
+{
+       struct prefix_rd prd;
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+       int ret;
+
+       if (!bgp || !vpn)
+               return CMD_WARNING;
+
+       ret = str2prefix_rd(argv[2]->arg, &prd);
+       if (!ret) {
+               vty_out(vty, "%% Malformed Route Distinguisher\n");
+               return CMD_WARNING;
+       }
+
+       /* Check if we should disallow. */
+       if (!is_rd_configured(vpn)) {
+               vty_out(vty, "%% RD is not configured for this VNI\n");
+               return CMD_WARNING;
+       }
+
+       if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
+               vty_out(vty,
+                       "%% RD specified does not match configuration for this VNI\n");
+               return CMD_WARNING;
+       }
+
+       evpn_unconfigure_rd(bgp, vpn);
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_vni_rd_without_val,
+       no_bgp_evpn_vni_rd_without_val_cmd,
+       "no rd",
+       NO_STR
+       "Route Distinguisher\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+
+       if (!bgp || !vpn)
+               return CMD_WARNING;
+
+       /* Check if we should disallow. */
+       if (!is_rd_configured(vpn)) {
+               vty_out(vty, "%% RD is not configured for this VNI\n");
+               return CMD_WARNING;
+       }
+
+       evpn_unconfigure_rd(bgp, vpn);
+       return CMD_SUCCESS;
+}
+
+/*
+ * Loop over all extended-communities in the route-target list rtl and
+ * return 1 if we find ecomtarget
+ */
+static int bgp_evpn_rt_matches_existing(struct list *rtl,
+                                       struct ecommunity *ecomtarget)
+{
+       struct listnode *node, *nnode;
+       struct ecommunity *ecom;
+
+       for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
+               if (ecommunity_match(ecom, ecomtarget))
+                       return 1;
+       }
+
+       return 0;
+}
+
+
+DEFUN (bgp_evpn_vni_rt,
+       bgp_evpn_vni_rt_cmd,
+       "route-target <both|import|export> RT",
+       "Route Target\n"
+       "import and export\n"
+       "import\n"
+       "export\n"
+       "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+       int rt_type;
+       struct ecommunity *ecomadd = NULL;
+
+       if (!bgp || !vpn)
+               return CMD_WARNING;
+
+       if (!strcmp(argv[1]->arg, "import"))
+               rt_type = RT_TYPE_IMPORT;
+       else if (!strcmp(argv[1]->arg, "export"))
+               rt_type = RT_TYPE_EXPORT;
+       else if (!strcmp(argv[1]->arg, "both"))
+               rt_type = RT_TYPE_BOTH;
+       else {
+               vty_out(vty, "%% Invalid Route Target type\n");
+               return CMD_WARNING;
+       }
+
+       /* Add/update the import route-target */
+       if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
+               ecomadd = ecommunity_str2com(argv[2]->arg,
+                                            ECOMMUNITY_ROUTE_TARGET, 0);
+               if (!ecomadd) {
+                       vty_out(vty, "%% Malformed Route Target list\n");
+                       return CMD_WARNING;
+               }
+               ecommunity_str(ecomadd);
+
+               /* Do nothing if we already have this import route-target */
+               if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
+                       evpn_configure_import_rt(bgp, vpn, ecomadd);
+       }
+
+       /* Add/update the export route-target */
+       if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
+               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);
+       }
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_vni_rt,
+       no_bgp_evpn_vni_rt_cmd,
+       "no route-target <both|import|export> RT",
+       NO_STR
+       "Route Target\n"
+       "import and export\n"
+       "import\n"
+       "export\n"
+       "ASN:XX or A.B.C.D:XX\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+       int rt_type, found_ecomdel;
+       struct ecommunity *ecomdel = NULL;
+
+       if (!bgp || !vpn)
+               return CMD_WARNING;
+
+       if (!strcmp(argv[2]->arg, "import"))
+               rt_type = RT_TYPE_IMPORT;
+       else if (!strcmp(argv[2]->arg, "export"))
+               rt_type = RT_TYPE_EXPORT;
+       else if (!strcmp(argv[2]->arg, "both"))
+               rt_type = RT_TYPE_BOTH;
+       else {
+               vty_out(vty, "%% Invalid Route Target type\n");
+               return CMD_WARNING;
+       }
+
+       /* The user did "no route-target import", check to see if there are any
+        * import route-targets configured. */
+       if (rt_type == RT_TYPE_IMPORT) {
+               if (!is_import_rt_configured(vpn)) {
+                       vty_out(vty,
+                               "%% Import RT is not configured for this VNI\n");
+                       return CMD_WARNING;
+               }
+       } else if (rt_type == RT_TYPE_EXPORT) {
+               if (!is_export_rt_configured(vpn)) {
+                       vty_out(vty,
+                               "%% Export RT is not configured for this VNI\n");
+                       return CMD_WARNING;
+               }
+       } else if (rt_type == RT_TYPE_BOTH) {
+               if (!is_import_rt_configured(vpn)
+                   && !is_export_rt_configured(vpn)) {
+                       vty_out(vty,
+                               "%% Import/Export RT is not configured for this VNI\n");
+                       return CMD_WARNING;
+               }
+       }
+
+       ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
+       if (!ecomdel) {
+               vty_out(vty, "%% Malformed Route Target list\n");
+               return CMD_WARNING;
+       }
+       ecommunity_str(ecomdel);
+
+       if (rt_type == RT_TYPE_IMPORT) {
+               if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
+                       vty_out(vty,
+                               "%% RT specified does not match configuration for this VNI\n");
+                       return CMD_WARNING;
+               }
+               evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
+       } else if (rt_type == RT_TYPE_EXPORT) {
+               if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
+                       vty_out(vty,
+                               "%% RT specified does not match configuration for this VNI\n");
+                       return CMD_WARNING;
+               }
+               evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
+       } else if (rt_type == RT_TYPE_BOTH) {
+               found_ecomdel = 0;
+
+               if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
+                       evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
+                       found_ecomdel = 1;
+               }
+
+               if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
+                       evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
+                       found_ecomdel = 1;
+               }
+
+               if (!found_ecomdel) {
+                       vty_out(vty,
+                               "%% RT specified does not match configuration for this VNI\n");
+                       return CMD_WARNING;
+               }
+       }
+
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_evpn_vni_rt_without_val,
+       no_bgp_evpn_vni_rt_without_val_cmd,
+       "no route-target <import|export>",
+       NO_STR
+       "Route Target\n"
+       "import\n"
+       "export\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+       int rt_type;
+
+       if (!bgp || !vpn)
+               return CMD_WARNING;
+
+       if (!strcmp(argv[2]->arg, "import")) {
+               rt_type = RT_TYPE_IMPORT;
+       } else if (!strcmp(argv[2]->arg, "export")) {
+               rt_type = RT_TYPE_EXPORT;
+       } else {
+               vty_out(vty, "%% Invalid Route Target type\n");
+               return CMD_WARNING;
+       }
+
+       /* Check if we should disallow. */
+       if (rt_type == RT_TYPE_IMPORT) {
+               if (!is_import_rt_configured(vpn)) {
+                       vty_out(vty,
+                               "%% Import RT is not configured for this VNI\n");
+                       return CMD_WARNING;
+               }
+       } else {
+               if (!is_export_rt_configured(vpn)) {
+                       vty_out(vty,
+                               "%% Export RT is not configured for this VNI\n");
+                       return CMD_WARNING;
+               }
+       }
+
+       /* Unconfigure the RT. */
+       if (rt_type == RT_TYPE_IMPORT)
+               evpn_unconfigure_import_rt(bgp, vpn, NULL);
+       else
+               evpn_unconfigure_export_rt(bgp, vpn, NULL);
+       return CMD_SUCCESS;
+}
+#endif
+/*
+ * Output EVPN configuration information.
+ */
+void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
+                               safi_t safi, int *write)
+{
+       struct evpn_config_write cfg;
+
+       if (bgp->vnihash) {
+               cfg.write = *write;
+               cfg.vty = vty;
+               hash_iterate(bgp->vnihash,
+                            (void (*)(struct hash_backet *,
+                                      void *))write_vni_config_for_entry,
+                            &cfg);
+               *write = cfg.write;
+       }
+
+       if (bgp->advertise_all_vni) {
+               bgp_config_write_family_header(vty, afi, safi, write);
+               vty_out(vty, "  advertise-all-vni\n");
+       }
+
+       if (bgp->advertise_gw_macip) {
+               bgp_config_write_family_header(vty, afi, safi, write);
+               vty_out(vty, "  advertise-default-gw\n");
+       }
+}
+
+void bgp_ethernetvpn_init(void)
+{
+       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
+       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
+       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
+       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
+       install_element(VIEW_NODE,
+                       &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
+       install_element(VIEW_NODE,
+                       &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
+       install_element(
+               VIEW_NODE,
+               &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
+       install_element(
+               VIEW_NODE,
+               &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
+       install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
+       install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
+       install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
+       install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
+#if defined(HAVE_CUMULUS)
+       install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
+       install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
+       install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
+       install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
+
+       /* "show bgp l2vpn evpn" commands. */
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
+       install_element(VIEW_NODE,
+                       &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
+
+       /* "show bgp evpn" commands. */
+       install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
+       install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
+
+       install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
+       install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
+       install_element(BGP_EVPN_VNI_NODE,
+                       &bgp_evpn_advertise_default_gw_vni_cmd);
+       install_element(BGP_EVPN_VNI_NODE,
+                       &no_bgp_evpn_advertise_default_gw_vni_cmd);
+#endif
 }