]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: new vpn-policy CLI
authorG. Paul Ziemba <paulz@labn.net>
Fri, 16 Mar 2018 18:11:37 +0000 (11:11 -0700)
committerG. Paul Ziemba <paulz@labn.net>
Tue, 20 Mar 2018 05:13:43 +0000 (22:13 -0700)
PR #1739 added code to leak routes between (default VRF) VPN safi and unicast RIBs in any VRF. That set of changes included temporary CLI including vpn-policy blocks to specify RD/RT/label/&c. After considerable discussion, we arrived at a consensus CLI shown below.

The code of this PR implements the vpn-specific parts of this syntax:

router bgp <as> [vrf <FOO>]
    address-family <afi> unicast
        rd (vpn|evpn) export (AS:NN | IP:nn)
        label (vpn|evpn) export (0..1048575)
        rt (vpn|evpn) (import|export|both) RTLIST...
        nexthop vpn (import|export) (A.B.C.D | X:X::X:X)
        route-map (vpn|evpn|vrf NAME) (import|export) MAP

        [no] import|export [vpn|evpn|evpn8]
        [no] import|export vrf NAME

User documentation of the vpn-specific parts of the above syntax is in PR #1937

Signed-off-by: G. Paul Ziemba <paulz@labn.net>
13 files changed:
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_vty.c
bgpd/bgp_vty.h
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
lib/command.c
lib/command.h
lib/log.c
lib/route_types.txt
vtysh/vtysh.c
zebra/zebra_rib.c

index d87f78a7830dae257675914d0a04229031de40ab..4916e95106d74ef05a2203d985ada6a1b2bbc75c 100644 (file)
@@ -28,8 +28,8 @@
 #include "queue.h"
 #include "filter.h"
 #include "mpls.h"
-#include "lib/json.h"
-#include "lib/zclient.h"
+#include "json.h"
+#include "zclient.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_debug.h"
@@ -824,7 +824,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf,       /* to */
        struct prefix *p = &info_vpn->net->p;
        afi_t afi = family2afi(p->family);
 
-       struct bgp_redist *red;
        struct attr static_attr = {0};
        struct attr *new_attr = NULL;
        struct bgp_node *bn;
@@ -836,7 +835,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf,       /* to */
 
        int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
 
-       if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg, &red)) {
+       if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg)) {
                if (debug)
                        zlog_debug("%s: skipping: %s", __func__, debugmsg);
                return;
@@ -893,28 +892,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf,       /* to */
 
        /*
         * route map handling
-        * For now, we apply two route maps: the "redist" route map and the
-        * vpn-policy route map. Once we finalize CLI syntax, one of these
-        * route maps will probably go away.
         */
-       if (red->rmap.map) {
-               struct bgp_info info;
-               route_map_result_t ret;
-
-               memset(&info, 0, sizeof(info));
-               info.peer = bgp_vrf->peer_self;
-               info.attr = &static_attr;
-               ret = route_map_apply(red->rmap.map, p, RMAP_BGP, &info);
-               if (RMAP_DENYMATCH == ret) {
-                       bgp_attr_flush(&static_attr); /* free any added parts */
-                       if (debug)
-                               zlog_debug(
-                                       "%s: vrf %s redist route map \"%s\" says DENY, skipping",
-                                       __func__, bgp_vrf->name,
-                                       red->rmap.name);
-                       return;
-               }
-       }
        if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
                struct bgp_info info;
                route_map_result_t ret;
@@ -994,7 +972,6 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,       /* from */
        safi_t safi = SAFI_UNICAST;
        struct bgp *bgp;
        struct listnode *mnode, *mnnode;
-       struct bgp_redist *red;
        struct bgp_node *bn;
        struct bgp_info *bi;
        const char *debugmsg;
@@ -1007,7 +984,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,       /* from */
 
        /* Loop over VRFs */
        for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
-               if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg, &red)) {
+               if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg)) {
                        if (debug)
                                zlog_debug("%s: skipping: %s", __func__,
                                           debugmsg);
@@ -1164,36 +1141,27 @@ static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name)
                                           __func__);
                }
 
-               /*
-                * vpn -> vrf leaking currently can have two route-maps:
-                * 1. the vpn-policy tovpn route-map
-                * 2. the (per-afi) redistribute vpn route-map
-                */
-               char *mapname_vpn_policy =
-                       bgp->vpn_policy[afi]
-                               .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN];
-               struct bgp_redist *red = NULL;
-
-               if (vpn_leak_from_vpn_active(bgp, afi, NULL, &red)
-                   && ((mapname_vpn_policy
-                        && !strcmp(rmap_name, mapname_vpn_policy))
-                       || (red && red->rmap.name
-                           && !strcmp(red->rmap.name, rmap_name)))) {
+               char *mapname = bgp->vpn_policy[afi]
+                       .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN];
 
-                       if (debug)
-                               zlog_debug(
-                                       "%s: rmap \"%s\" matches vrf-policy fromvpn"
-                                       " for as %d afi %s",
+               if (vpn_leak_from_vpn_active(bgp, afi, NULL) && 
+                       mapname &&
+                       !strcmp(rmap_name, mapname))  {
+
+                       if (debug) {
+                               zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
                                        __func__, rmap_name, bgp->as,
                                        afi2str(afi));
+                       }
 
                        vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
                                           bgp_get_default(), bgp);
 
-                       if (!rmap)
+                       if (!rmap) {
                                bgp->vpn_policy[afi]
                                        .rmap[BGP_VPN_POLICY_DIR_FROMVPN] =
                                        NULL;
+                       }
 
                        vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
                                            bgp_get_default(), bgp);
index d0ad8ac8462b7fb20573c1fb62c9590682fae18e..4d7a858becc46aeeed14727fb8a74d83e779b1ff 100644 (file)
@@ -107,11 +107,8 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
 }
 
 static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
-                                          const char **pmsg,
-                                          struct bgp_redist **pred)
+                                          const char **pmsg)
 {
-       struct bgp_redist *red;
-
        if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
            && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
 
@@ -120,14 +117,11 @@ static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
                return 0;
        }
 
-       /* Hijack zebra redist bits for this route type */
-       red = bgp_redist_lookup(bgp_vrf, afi, ZEBRA_ROUTE_BGP_VPN, 0);
-       if (red) {
-               if (pred)
-                       *pred = red;
-       } else {
+       /* Is vrf configured to import from vpn? */
+       if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+                       BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
                if (pmsg)
-                       *pmsg = "redist not set";
+                       *pmsg = "import not set";
                return 0;
        }
        if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
index 4a5633c94d07f706c0dcee53fef08d324690614c..3aa8ceedafc31c47dc71b8991a18d21d53ee1fd4 100644 (file)
@@ -6112,74 +6112,63 @@ ALIAS_HIDDEN(no_neighbor_addpath_tx_bestpath_per_as,
             NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
             "Use addpath to advertise the bestpath per each neighboring AS\n")
 
-
-DEFUN_NOSH (vpn_policy_afi,
-       vpn_policy_afi_cmd,
-       "vpn-policy <ipv4|ipv6>",
-       "Enter vpn-policy command mode\n"
-       BGP_AFI_HELP_STR)
+static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
+                        struct ecommunity **list)
 {
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF
-           && bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+       struct ecommunity *ecom = NULL;
+       struct ecommunity *ecomadd;
 
-               vty_out(vty,
-                       "vpn-policy supported only in core or vrf instances.\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
+       for (; argc; --argc, ++argv) {
 
-       afi_t afi;
-       int idx = 0;
+               ecomadd = ecommunity_str2com(argv[0]->arg,
+                                            ECOMMUNITY_ROUTE_TARGET, 0);
+               if (!ecomadd) {
+                       vty_out(vty, "Malformed community-list value\n");
+                       if (ecom)
+                               ecommunity_free(&ecom);
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
 
-       if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
-               if (afi == AFI_IP)
-                       vty->node = BGP_VPNPOLICY_IPV4_NODE;
-               else
-                       vty->node = BGP_VPNPOLICY_IPV6_NODE;
-               return CMD_SUCCESS;
+               if (ecom) {
+                       ecommunity_merge(ecom, ecomadd);
+                       ecommunity_free(&ecomadd);
+               } else {
+                       ecom = ecomadd;
+               }
+       }
+
+       if (*list) {
+               ecommunity_free(&*list);
        }
-       return CMD_WARNING_CONFIG_FAILED;
+       *list = ecom;
+
+       return CMD_SUCCESS;
 }
 
-static int vpn_policy_afis(struct vty *vty, int *doafi)
+static int vpn_policy_getafi(struct vty *vty, int *doafi)
 {
        switch (vty->node) {
-       case BGP_VPNPOLICY_IPV4_NODE:
+       case BGP_IPV4_NODE:
                doafi[AFI_IP] = 1;
                break;
-       case BGP_VPNPOLICY_IPV6_NODE:
+       case BGP_IPV6_NODE:
                doafi[AFI_IP6] = 1;
                break;
        default:
                vty_out(vty,
-                       "%% context error: valid only in vpn-policy block\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       return CMD_SUCCESS;
-}
-
-static int argv_find_and_parse_vpn_policy_dirs(struct vty *vty,
-                                              struct cmd_token **argv,
-                                              int argc, int *idx, int *dodir)
-{
-       if (argv_find(argv, argc, "fromvpn", idx)) {
-               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
-       } else if (argv_find(argv, argc, "tovpn", idx)) {
-               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
-       } else if (argv_find(argv, argc, "both", idx)) {
-               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
-               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
-       } else {
-               vty_out(vty, "%% direction parse error\n");
+                       "%% context error: valid only in address-family <ipv4|ipv6> unicast block\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_rd,
-       vpn_policy_rd_cmd,
-       "rd ASN:NN_OR_IP-ADDRESS:NN",
+DEFPY (af_rd_vpn_export,
+       af_rd_vpn_export_cmd,
+       "[no] rd vpn export ASN:NN_OR_IP-ADDRESS:NN$rd_str",
+       NO_STR
        "Specify route distinguisher\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n"
        "Route Distinguisher (<as-number>:<number> | <ip-address>:<number>)\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
@@ -6187,14 +6176,21 @@ DEFUN (vpn_policy_rd,
        int ret;
        int doafi[AFI_MAX] = {0};
        afi_t afi;
+       int idx = 0;
+       int yes = 1;
 
-       ret = str2prefix_rd(argv[1]->arg, &prd);
-       if (!ret) {
-               vty_out(vty, "%% Malformed rd\n");
-               return CMD_WARNING_CONFIG_FAILED;
+       if (argv_find(argv, argc, "no", &idx))
+           yes = 0;
+
+       if (yes) {
+               ret = str2prefix_rd(rd_str, &prd);
+               if (!ret) {
+                       vty_out(vty, "%% Malformed rd\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
        }
 
-       ret = vpn_policy_afis(vty, doafi);
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6208,9 +6204,14 @@ DEFUN (vpn_policy_rd,
                vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
                                   bgp_get_default(), bgp);
 
-               bgp->vpn_policy[afi].tovpn_rd = prd;
-               SET_FLAG(bgp->vpn_policy[afi].flags,
-                        BGP_VPN_POLICY_TOVPN_RD_SET);
+               if (yes) {
+                       bgp->vpn_policy[afi].tovpn_rd = prd;
+                       SET_FLAG(bgp->vpn_policy[afi].flags,
+                                BGP_VPN_POLICY_TOVPN_RD_SET);
+               } else {
+                       UNSET_FLAG(bgp->vpn_policy[afi].flags,
+                                  BGP_VPN_POLICY_TOVPN_RD_SET);
+               }
 
                /* post-change: re-export vpn routes */
                vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
@@ -6220,57 +6221,38 @@ DEFUN (vpn_policy_rd,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_rd,
-       vpn_policy_no_rd_cmd,
-       "no rd",
+ALIAS (af_rd_vpn_export,
+       af_no_rd_vpn_export_cmd,
+       "no rd vpn export",
        NO_STR
-       "Specify route distinguisher\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
-       int doafi[AFI_MAX] = {0};
-       afi_t afi;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
-                */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-
-               UNSET_FLAG(bgp->vpn_policy[afi].flags,
-                          BGP_VPN_POLICY_TOVPN_RD_SET);
-
-               /* post-change: re-export vpn routes */
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-
-       return CMD_SUCCESS;
-}
+       "Specify route distinguisher\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n")
 
-DEFUN (vpn_policy_label,
-       vpn_policy_label_cmd,
-       "label (0-1048575)",
+DEFPY (af_label_vpn_export,
+       af_label_vpn_export_cmd,
+       "[no] label vpn export (0-1048575)$label_val",
+       NO_STR
        "label value for VRF\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n"
        "Label Value <0-1048575>\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
-       mpls_label_t label;
+       mpls_label_t label = MPLS_LABEL_NONE;
        int doafi[AFI_MAX] = {0};
        afi_t afi;
        int ret;
+       int idx = 0;
+       int yes = 1;
+
+       if (argv_find(argv, argc, "no", &idx))
+           yes = 0;
 
-       label = strtoul(argv[1]->arg, NULL, 10);
+       if (yes)
+               label = label_val; /* rely on parser to force unsigned */
 
-       ret = vpn_policy_afis(vty, doafi);
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6278,7 +6260,8 @@ DEFUN (vpn_policy_label,
                if (!doafi[afi])
                        continue;
 
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
+               /*
+                * pre-change: un-export vpn routes (vpn->vrf routes unaffected)
                 */
                vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
                                   bgp_get_default(), bgp);
@@ -6293,44 +6276,21 @@ DEFUN (vpn_policy_label,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_label,
-       vpn_policy_no_label_cmd,
-       "no label",
-       "Negate a command or set its defaults\n"
-       "label value for VRF\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int doafi[AFI_MAX] = {0};
-       afi_t afi;
-       int ret;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
-                */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-
-               bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
-
-               /* post-change: re-export vpn routes */
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-
-       return CMD_SUCCESS;
-}
+ALIAS (af_label_vpn_export,
+       af_no_label_vpn_export_cmd,
+       "no label vpn export",
+       NO_STR
+       "label value for VRF\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n")
 
-DEFPY (vpn_policy_nexthop,
-       vpn_policy_nexthop_cmd,
-       "nexthop <A.B.C.D|X:X::X:X>$nexthop",
+DEFPY (af_nexthop_vpn_export,
+       af_nexthop_vpn_export_cmd,
+       "[no] nexthop vpn export <A.B.C.D|X:X::X:X>$nexthop_str",
+       NO_STR
        "Specify next hop to use for VRF advertised prefixes\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n"
        "IPv4 prefix\n"
        "IPv6 prefix\n")
 {
@@ -6339,11 +6299,18 @@ DEFPY (vpn_policy_nexthop,
        afi_t afi;
        int ret;
        struct prefix p;
+       int idx = 0;
+       int yes = 1;
 
-       if (!sockunion2hostprefix(nexthop, &p))
-               return CMD_WARNING_CONFIG_FAILED;
+       if (argv_find(argv, argc, "no", &idx))
+           yes = 0;
+
+       if (yes) {
+               if (!sockunion2hostprefix(nexthop_str, &p))
+                       return CMD_WARNING_CONFIG_FAILED;
+       }
 
-       ret = vpn_policy_afis(vty, doafi);
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6357,9 +6324,14 @@ DEFPY (vpn_policy_nexthop,
                vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
                                   bgp_get_default(), bgp);
 
-               bgp->vpn_policy[afi].tovpn_nexthop = p;
-               SET_FLAG(bgp->vpn_policy[afi].flags,
-                        BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+               if (yes) {
+                       bgp->vpn_policy[afi].tovpn_nexthop = p;
+                       SET_FLAG(bgp->vpn_policy[afi].flags,
+                                BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+               } else {
+                       UNSET_FLAG(bgp->vpn_policy[afi].flags,
+                                  BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+               }
 
                /* post-change: re-export vpn routes */
                vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
@@ -6369,81 +6341,40 @@ DEFPY (vpn_policy_nexthop,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_nexthop,
-       vpn_policy_no_nexthop_cmd,
-       "no nexthop",
+ALIAS (af_nexthop_vpn_export,
+       af_no_nexthop_vpn_export_cmd,
+       "no nexthop vpn export",
        NO_STR
-       "Specify next hop to use for VRF advertised prefixes\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int doafi[AFI_MAX] = {0};
-       afi_t afi;
-       int ret;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-
-               /* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
-                */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-
-               UNSET_FLAG(bgp->vpn_policy[afi].flags,
-                          BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
-
-               /* post-change: re-export vpn routes */
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-
-       return CMD_SUCCESS;
-}
+       "Specify next hop to use for VRF advertised prefixes\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from current address-family to vpn\n")
 
-static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
-                        struct ecommunity **list)
+static int vpn_policy_getdirs(struct vty *vty, const char *dstr, int *dodir)
 {
-       struct ecommunity *ecom = NULL;
-       struct ecommunity *ecomadd;
-
-       for (; argc; --argc, ++argv) {
-
-               ecomadd = ecommunity_str2com(argv[0]->arg,
-                                            ECOMMUNITY_ROUTE_TARGET, 0);
-               if (!ecomadd) {
-                       vty_out(vty, "Malformed community-list value\n");
-                       if (ecom)
-                               ecommunity_free(&ecom);
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               if (ecom) {
-                       ecommunity_merge(ecom, ecomadd);
-                       ecommunity_free(&ecomadd);
-               } else {
-                       ecom = ecomadd;
-               }
-       }
-
-       if (*list) {
-               ecommunity_free(&*list);
+       if (!strcmp(dstr, "import")) {
+               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
+       } else if (!strcmp(dstr, "export")) {
+               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
+       } else if (!strcmp(dstr, "both")) {
+               dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
+               dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
+       } else {
+               vty_out(vty, "%% direction parse error\n");
+               return CMD_WARNING_CONFIG_FAILED;
        }
-       *list = ecom;
-
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_rt,
-       vpn_policy_rt_cmd,
-       "rt <fromvpn|tovpn|both> RTLIST...",
+DEFPY (af_rt_vpn_imexport,
+       af_rt_vpn_imexport_cmd,
+       "[no] <rt|route-target> vpn <import|export|both>$direction_str RTLIST...",
+       NO_STR
+       "Specify route target list\n"
        "Specify route target list\n"
-       "fromvpn: match any\n"
-       "tovpn: set\n"
-       "both fromvpn: match any and tovpn: set\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family: match any\n"
+       "For routes leaked from current address-family to vpn: set\n"
+       "both import: match any and export: set\n"
        "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
@@ -6454,18 +6385,28 @@ DEFUN (vpn_policy_rt,
        vpn_policy_direction_t dir;
        afi_t afi;
        int idx = 0;
+       int yes = 1;
 
-       ret = vpn_policy_afis(vty, doafi);
+       if (argv_find(argv, argc, "no", &idx))
+           yes = 0;
+
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
+       ret = vpn_policy_getdirs(vty, direction_str, dodir);
        if (ret != CMD_SUCCESS)
                return ret;
 
-       ret = set_ecom_list(vty, argc - 2, argv + 2, &ecom);
-       if (ret != CMD_SUCCESS) {
-               return ret;
+       if (yes) {
+               if (!argv_find(argv, argc, "RTLIST", &idx)) {
+                       vty_out(vty, "%% Missing RTLIST\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+               ret = set_ecom_list(vty, argc - idx, argv + idx, &ecom);
+               if (ret != CMD_SUCCESS) {
+                       return ret;
+               }
        }
 
        for (afi = 0; afi < AFI_MAX; ++afi) {
@@ -6477,10 +6418,18 @@ DEFUN (vpn_policy_rt,
 
                        vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
 
-                       if (bgp->vpn_policy[afi].rtlist[dir])
-                               ecommunity_free(
-                                       &bgp->vpn_policy[afi].rtlist[dir]);
-                       bgp->vpn_policy[afi].rtlist[dir] = ecommunity_dup(ecom);
+                       if (yes) {
+                               if (bgp->vpn_policy[afi].rtlist[dir])
+                                       ecommunity_free(
+                                           &bgp->vpn_policy[afi].rtlist[dir]);
+                               bgp->vpn_policy[afi].rtlist[dir] =
+                                       ecommunity_dup(ecom);
+                       } else {
+                               if (bgp->vpn_policy[afi].rtlist[dir])
+                                       ecommunity_free(
+                                           &bgp->vpn_policy[afi].rtlist[dir]);
+                               bgp->vpn_policy[afi].rtlist[dir] = NULL;
+                       }
 
                        vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
                }
@@ -6490,58 +6439,26 @@ DEFUN (vpn_policy_rt,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_rt,
-       vpn_policy_no_rt_cmd,
-       "no rt <fromvpn|tovpn|both>",
+ALIAS (af_rt_vpn_imexport,
+       af_no_rt_vpn_imexport_cmd,
+       "no <rt|route-target> vpn <import|export|both>$direction_str",
        NO_STR
        "Specify route target list\n"
-       "fromvpn: match any\n"
-       "tovpn: set\n"
-       "both fromvpn: match any and tovpn: set\n")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
-       int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
-       int doafi[AFI_MAX] = {0};
-       vpn_policy_direction_t dir;
-       afi_t afi;
-       int idx = 0;
-
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
-       if (ret != CMD_SUCCESS)
-               return ret;
-
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-               for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
-                       if (!dodir[dir])
-                               continue;
-
-                       vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
-
-                       if (bgp->vpn_policy[afi].rtlist[dir])
-                               ecommunity_free(
-                                       &bgp->vpn_policy[afi].rtlist[dir]);
-                       bgp->vpn_policy[afi].rtlist[dir] = NULL;
-
-                       vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
-               }
-       }
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (vpn_policy_route_map,
-       vpn_policy_route_map_cmd,
-       "route-map <fromvpn|tovpn> WORD",
+       "Specify route target list\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family\n"
+       "For routes leaked from current address-family to vpn\n"
+       "both import and export\n")
+
+DEFPY (af_route_map_vpn_imexport,
+       af_route_map_vpn_imexport_cmd,
+/* future: "route-map <vpn|evpn|vrf NAME> <import|export> RMAP" */
+       "[no] route-map vpn <import|export>$direction_str RMAP$rmap_str",
+       NO_STR
        "Specify route map\n"
-       "fromvpn: core vpn -> this vrf\n"
-       "tovpn: this vrf -> core vpn\n"
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family\n"
+       "For routes leaked from current address-family to vpn\n"
        "name of route-map\n")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
@@ -6550,14 +6467,17 @@ DEFUN (vpn_policy_route_map,
        int doafi[AFI_MAX] = {0};
        vpn_policy_direction_t dir;
        afi_t afi;
-       int map_name_arg = 2;
        int idx = 0;
+       int yes = 1;
 
-       ret = vpn_policy_afis(vty, doafi);
+       if (argv_find(argv, argc, "no", &idx))
+           yes = 0;
+
+       ret = vpn_policy_getafi(vty, doafi);
        if (ret != CMD_SUCCESS)
                return ret;
 
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
+       ret = vpn_policy_getdirs(vty, direction_str, dodir);
        if (ret != CMD_SUCCESS)
                return ret;
 
@@ -6570,14 +6490,21 @@ DEFUN (vpn_policy_route_map,
 
                        vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
 
-                       if (bgp->vpn_policy[afi].rmap_name[dir])
-                               XFREE(MTYPE_ROUTE_MAP_NAME,
-                                     bgp->vpn_policy[afi].rmap_name[dir]);
-                       bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP(
-                               MTYPE_ROUTE_MAP_NAME, argv[map_name_arg]->arg);
-                       bgp->vpn_policy[afi].rmap[dir] =
-                               route_map_lookup_by_name(
-                                       argv[map_name_arg]->arg);
+                       if (yes) {
+                               if (bgp->vpn_policy[afi].rmap_name[dir])
+                                       XFREE(MTYPE_ROUTE_MAP_NAME,
+                                       bgp->vpn_policy[afi].rmap_name[dir]);
+                               bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP(
+                                       MTYPE_ROUTE_MAP_NAME, rmap_str);
+                               bgp->vpn_policy[afi].rmap[dir] =
+                                       route_map_lookup_by_name(rmap_str);
+                       } else {
+                               if (bgp->vpn_policy[afi].rmap_name[dir])
+                                       XFREE(MTYPE_ROUTE_MAP_NAME,
+                                       bgp->vpn_policy[afi].rmap_name[dir]);
+                               bgp->vpn_policy[afi].rmap_name[dir] = NULL;
+                               bgp->vpn_policy[afi].rmap[dir] = NULL;
+                       }
 
                        vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
                }
@@ -6586,47 +6513,73 @@ DEFUN (vpn_policy_route_map,
        return CMD_SUCCESS;
 }
 
-DEFUN (vpn_policy_no_route_map,
-       vpn_policy_no_route_map_cmd,
-       "no route-map <fromvpn|tovpn>",
+ALIAS (af_route_map_vpn_imexport,
+       af_no_route_map_vpn_imexport_cmd,
+       "no route-map vpn <import|export>$direction_str",
        NO_STR
        "Specify route map\n"
-       "fromvpn: core vpn -> this vrf\n"
-       "tovpn: this vrf -> core vpn\n")
+       "Between current address-family and vpn\n"
+       "For routes leaked from vpn to current address-family\n"
+       "For routes leaked from current address-family to vpn\n")
+
+/* This command is valid only in a bgp vrf instance or the default instance */
+DEFPY (bgp_imexport_vpn,
+       bgp_imexport_vpn_cmd,
+       "[no] <import|export>$direction_str vpn",
+       "Export routes to another routing protocol\n"
+       "to VPN RIB per vpn-policy")
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int ret;
-       int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
-       int doafi[AFI_MAX] = {0};
-       vpn_policy_direction_t dir;
+       int previous_state;
        afi_t afi;
+       safi_t safi;
        int idx = 0;
+       int yes = 1;
+       int flag;
+       vpn_policy_direction_t dir;
 
-       ret = vpn_policy_afis(vty, doafi);
-       if (ret != CMD_SUCCESS)
-               return ret;
+       if (argv_find(argv, argc, "no", &idx))
+           yes = 0;
 
-       ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
-       if (ret != CMD_SUCCESS)
-               return ret;
+       if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type &&
+               BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
 
-       for (afi = 0; afi < AFI_MAX; ++afi) {
-               if (!doafi[afi])
-                       continue;
-               for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
-                       if (!dodir[dir])
-                               continue;
+               vty_out(vty, "%% import|export vpn valid only for bgp vrf or default instance\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
-                       vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+       afi = bgp_node_afi(vty);
+       safi = bgp_node_safi(vty);
+       if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
+               vty_out(vty, "%% import|export vpn valid only for unicast ipv4|ipv6\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
-                       if (bgp->vpn_policy[afi].rmap_name[dir])
-                               XFREE(MTYPE_ROUTE_MAP_NAME,
-                                     bgp->vpn_policy[afi].rmap_name[dir]);
-                       bgp->vpn_policy[afi].rmap_name[dir] = NULL;
-                       bgp->vpn_policy[afi].rmap[dir] = NULL;
+       if (!strcmp(direction_str, "import")) {
+               flag = BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT;
+               dir = BGP_VPN_POLICY_DIR_FROMVPN;
+       } else if (!strcmp(direction_str, "export")) {
+               flag = BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT;
+               dir = BGP_VPN_POLICY_DIR_TOVPN;
+       } else {
+               vty_out(vty, "%% unknown direction %s\n", direction_str);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       previous_state = CHECK_FLAG(bgp->af_flags[afi][safi], flag);
 
+       if (yes) {
+               SET_FLAG(bgp->af_flags[afi][safi], flag);
+               if (!previous_state) {
+                       /* trigger export current vrf */
                        vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
                }
+       } else {
+               if (previous_state) {
+                       /* trigger un-export current vrf */
+                       vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+               }
+               UNSET_FLAG(bgp->af_flags[afi][safi], flag);
        }
 
        return CMD_SUCCESS;
@@ -11659,99 +11612,20 @@ void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
        }
 }
 
-/* This command is valid only in a bgp vrf instance or the default instance */
-DEFUN (bgp_export_vpn,
-       bgp_export_vpn_cmd,
-       "export vpn",
-       "Export routes to another routing protocol\n"
-       "to VPN RIB per vpn-policy")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int was_off = 0;
-       afi_t afi;
-       safi_t safi;
-
-       if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type
-           && BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
-               vty_out(vty,
-                       "%% export vpn valid only for bgp vrf or default instance\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       afi = bgp_node_afi(vty);
-       safi = bgp_node_safi(vty);
-       if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
-               vty_out(vty,
-                       "%% export vpn valid only for unicast ipv4|ipv6\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (!CHECK_FLAG(bgp->af_flags[afi][safi],
-                       BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
-               was_off = 1;
-       }
-       SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT);
-       if (was_off) {
-               /* trigger export current vrf */
-               zlog_debug("%s: calling postchange", __func__);
-               vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                   bgp_get_default(), bgp);
-       }
-       return CMD_SUCCESS;
-}
-
-DEFUN (bgp_no_export_vpn,
-       bgp_no_export_vpn_cmd,
-       "no export vpn",
-       NO_STR
-       "Export routes to another routing protocol\n"
-       "to VPN RIB per vpn-policy")
-{
-       VTY_DECLVAR_CONTEXT(bgp, bgp);
-       int was_on = 0;
-       afi_t afi;
-       safi_t safi;
-
-       if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type
-           && BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
-               vty_out(vty,
-                       "%% export vpn valid only for bgp vrf or default instance\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       afi = bgp_node_afi(vty);
-       safi = bgp_node_safi(vty);
-       if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
-               vty_out(vty,
-                       "%% export vpn valid only for unicast ipv4|ipv6\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (CHECK_FLAG(bgp->af_flags[afi][safi],
-                      BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
-               was_on = 1;
-       }
-       if (was_on) {
-               /* trigger un-export current vrf */
-               zlog_debug("%s: calling postchange", __func__);
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
-                                  bgp_get_default(), bgp);
-       }
-       UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT);
-       return CMD_SUCCESS;
-}
-
-static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
+/* This is part of the address-family block (unicast only) */
+void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                                            afi_t afi)
 {
-       vty_frame(vty, " vpn-policy ipv%d\n", ((afi == AFI_IP) ? 4 : 6));
+       int indent = 2;
 
        if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
-               vty_out(vty, "    label %u\n",
+               vty_out(vty, "%*slabel vpn export %u\n", indent, "",
                        bgp->vpn_policy[afi].tovpn_label);
        }
        if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
                       BGP_VPN_POLICY_TOVPN_RD_SET)) {
                char buf[RD_ADDRSTRLEN];
-               vty_out(vty, "    rd %s\n",
+               vty_out(vty, "%*srd vpn export %s\n", indent, "",
                        prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
                                      sizeof(buf)));
        }
@@ -11763,7 +11637,8 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                              &bgp->vpn_policy[afi].tovpn_nexthop.u.prefix, buf,
                              sizeof(buf))) {
 
-                       vty_out(vty, "    nexthop %s\n", buf);
+                       vty_out(vty, "%*snexthop vpn export %s\n",
+                               indent, "", buf);
                }
        }
        if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]
@@ -11775,7 +11650,7 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                char *b = ecommunity_ecom2str(
                        bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN],
                        ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
-               vty_out(vty, "    rt both %s\n", b);
+               vty_out(vty, "%*srt vpn both %s\n", indent, "", b);
                XFREE(MTYPE_ECOMMUNITY_STR, b);
        } else {
                if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
@@ -11784,7 +11659,7 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                                        .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
                                ECOMMUNITY_FORMAT_ROUTE_MAP,
                                ECOMMUNITY_ROUTE_TARGET);
-                       vty_out(vty, "    rt fromvpn %s\n", b);
+                       vty_out(vty, "%*srt vpn import %s\n", indent, "", b);
                        XFREE(MTYPE_ECOMMUNITY_STR, b);
                }
                if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
@@ -11793,28 +11668,21 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                                        .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
                                ECOMMUNITY_FORMAT_ROUTE_MAP,
                                ECOMMUNITY_ROUTE_TARGET);
-                       vty_out(vty, "    rt tovpn %s\n", b);
+                       vty_out(vty, "%*srt vpn export %s\n", indent, "", b);
                        XFREE(MTYPE_ECOMMUNITY_STR, b);
                }
        }
        if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]) {
-               vty_out(vty, "    route-map fromvpn %s\n",
+               vty_out(vty, "%*sroute-map vpn import %s\n", indent, "",
                        bgp->vpn_policy[afi]
                                .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]);
        }
        if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN]) {
-               vty_out(vty, "    route-map tovpn %s\n",
+               vty_out(vty, "%*sroute-map vpn export %s\n", indent, "",
                        bgp->vpn_policy[afi]
                                .rmap_name[BGP_VPN_POLICY_DIR_TOVPN]);
        }
 
-       vty_endframe(vty, " exit\n");
-}
-
-void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp)
-{
-       bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP);
-       bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP6);
 }
 
 
@@ -11859,12 +11727,6 @@ static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE,
 static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE,
                                            "%s(config-router-af-vni)# ", 1};
 
-static struct cmd_node bgp_vpn_policy_ipv4_node = {
-       BGP_VPNPOLICY_IPV4_NODE, "%s(config-router-vpn-policy-ipv4)# ", 1};
-
-static struct cmd_node bgp_vpn_policy_ipv6_node = {
-       BGP_VPNPOLICY_IPV6_NODE, "%s(config-router-vpn-policy-ipv6)# ", 1};
-
 static void community_list_vty(void);
 
 static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
@@ -11925,8 +11787,6 @@ void bgp_vty_init(void)
        install_node(&bgp_vpnv6_node, NULL);
        install_node(&bgp_evpn_node, NULL);
        install_node(&bgp_evpn_vni_node, NULL);
-       install_node(&bgp_vpn_policy_ipv4_node, NULL);
-       install_node(&bgp_vpn_policy_ipv6_node, NULL);
 
        /* Install default VTY commands to new nodes.  */
        install_default(BGP_NODE);
@@ -11940,8 +11800,6 @@ void bgp_vty_init(void)
        install_default(BGP_VPNV6_NODE);
        install_default(BGP_EVPN_NODE);
        install_default(BGP_EVPN_VNI_NODE);
-       install_default(BGP_VPNPOLICY_IPV4_NODE);
-       install_default(BGP_VPNPOLICY_IPV6_NODE);
 
        /* "bgp multiple-instance" commands. */
        install_element(CONFIG_NODE, &bgp_multiple_instance_cmd);
@@ -13001,11 +12859,9 @@ void bgp_vty_init(void)
        install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
        install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
 
-       /* export vpn [route-map WORD] */
-       install_element(BGP_IPV4_NODE, &bgp_export_vpn_cmd);
-       install_element(BGP_IPV6_NODE, &bgp_export_vpn_cmd);
-       install_element(BGP_IPV4_NODE, &bgp_no_export_vpn_cmd);
-       install_element(BGP_IPV6_NODE, &bgp_no_export_vpn_cmd);
+       /* import|export vpn [route-map WORD] */
+       install_element(BGP_IPV4_NODE, &bgp_imexport_vpn_cmd);
+       install_element(BGP_IPV6_NODE, &bgp_imexport_vpn_cmd);
 
        /* ttl_security commands */
        install_element(BGP_NODE, &neighbor_ttl_security_cmd);
@@ -13027,28 +12883,27 @@ void bgp_vty_init(void)
        community_list_vty();
 
        /* vpn-policy commands */
-       install_element(BGP_NODE, &vpn_policy_afi_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_route_map_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_route_map_cmd);
-
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_label_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_nexthop_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rt_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_route_map_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_route_map_cmd);
+       install_element(BGP_IPV4_NODE, &af_rd_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_rd_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_label_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_label_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV4_NODE, &af_route_map_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_route_map_vpn_imexport_cmd);
+
+       install_element(BGP_IPV4_NODE, &af_no_rd_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_rd_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_label_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_label_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_nexthop_vpn_export_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_rt_vpn_imexport_cmd);
+       install_element(BGP_IPV4_NODE, &af_no_route_map_vpn_imexport_cmd);
+       install_element(BGP_IPV6_NODE, &af_no_route_map_vpn_imexport_cmd);
 }
 
 #include "memory.h"
index 459c4ffcc3a293d26102eb85062fc5baa5b0f310..f77ebb610e3fec0f35d8a54ee593792e2d1d7ebe 100644 (file)
@@ -71,5 +71,6 @@ extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
                                               safi_t *safi, struct bgp **bgp);
 extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
                                safi_t safi, u_char use_json);
-extern void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp);
+extern void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
+                                           afi_t afi);
 #endif /* _QUAGGA_BGP_VTY_H */
index 22284fd28d9bd294930c10988008ee93574982be..97b4c916d739f998f41d57fba138bc6539d9f95b 100644 (file)
@@ -1451,27 +1451,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, u_short instance)
                }
 #endif
 
-               /* vpn -> vrf (happens within bgp but we hijack redist bits */
-               if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-                    || bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-                   && type == ZEBRA_ROUTE_BGP_VPN) {
-
-                       /* leak update all */
-                       vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
-                                          bgp_get_default(), bgp);
-               }
-
                vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id);
-
-               /* vpn -> vrf (happens within bgp but we hijack redist bits */
-               if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-                    || bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-                   && type == ZEBRA_ROUTE_BGP_VPN) {
-
-                       /* leak update all */
-                       vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
-                                           bgp_get_default(), bgp);
-               }
        }
 
        /*
@@ -1625,15 +1605,6 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
                vnc_export_bgp_disable(bgp, afi);
        }
 #endif
-       /* vpn -> vrf (happend within bgp but we hijack redist bits */
-       if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-            || bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-           && type == ZEBRA_ROUTE_BGP_VPN) {
-
-               /* leak withdraw all */
-               vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
-                                  bgp_get_default(), bgp);
-       }
 
        red = bgp_redist_lookup(bgp, afi, type, instance);
        if (!red)
index 2eae2e5e9e333cde76e5e95c828b0a9a2a3d88a7..c178727b548270be0fa20f84730717c23b5ab489 100644 (file)
@@ -7132,10 +7132,18 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
        if (safi == SAFI_EVPN)
                bgp_config_write_evpn_info(vty, bgp, afi, safi);
 
-       if (CHECK_FLAG(bgp->af_flags[afi][safi],
-                      BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
+       if (safi == SAFI_UNICAST) {
+               bgp_vpn_policy_config_write_afi(vty, bgp, afi);
+               if (CHECK_FLAG(bgp->af_flags[afi][safi],
+                              BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
 
-               vty_out(vty, "  export vpn\n");
+                       vty_out(vty, "  export vpn\n");
+               }
+               if (CHECK_FLAG(bgp->af_flags[afi][safi],
+                              BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
+
+                       vty_out(vty, "  import vpn\n");
+               }
        }
 
        vty_endframe(vty, " exit-address-family\n");
@@ -7404,8 +7412,6 @@ int bgp_config_write(struct vty *vty)
                if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
                        vty_out(vty, " no auto-summary\n");
 
-               bgp_vpn_policy_config_write(vty, bgp);
-
                /* IPv4 unicast configuration.  */
                bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
 
index 664f8c9da4a82c812ee7eb52429956274c666cb7..79fe8c8c3bab69da98f9f17d43917a4f0ab1af98 100644 (file)
@@ -318,6 +318,7 @@ struct bgp {
        u_int16_t af_flags[AFI_MAX][SAFI_MAX];
 #define BGP_CONFIG_DAMPENING              (1 << 0)
 #define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT  (1 << 1)
+#define BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT  (1 << 2)
 
 /* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */
 #define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST      (1 << 1)
@@ -471,7 +472,7 @@ struct bgp {
                uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */
                uint32_t tovpn_zebra_vrf_label_last_sent;
                struct prefix_rd tovpn_rd;
-               struct prefix tovpn_nexthop; /* unset => set to router id */
+               struct prefix tovpn_nexthop; /* unset => set to 0 */
                uint32_t flags;
 #define BGP_VPN_POLICY_TOVPN_RD_SET            0x00000004
 #define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET       0x00000008
index b289cdd7a3cba562760fb138728833ec00153f0b..5697c1d812b01d6baff6b181c8cafab7c9d4489a 100644 (file)
@@ -87,8 +87,6 @@ const char *node_names[] = {
        "bgp vnc l2",               // BGP_VNC_L2_GROUP_NODE,
        "rfp defaults",             // RFP_DEFAULTS_NODE,
        "bgp evpn",                 // BGP_EVPN_NODE,
-       "bgp vpn policy ipv4",      // BGP_VPNPOLICY_IPV4_NODE
-       "bgp vpn policy ipv6",      // BGP_VPNPOLICY_IPV6_NODE
        "ospf",                     // OSPF_NODE,
        "ospf6",                    // OSPF6_NODE,
        "ldp",                      // LDP_NODE,
@@ -951,8 +949,6 @@ enum node_type node_parent(enum node_type node)
        case BGP_VPNV4_NODE:
        case BGP_VPNV6_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
        case BGP_VNC_L2_GROUP_NODE:
@@ -1323,8 +1319,6 @@ void cmd_exit(struct vty *vty)
        case BGP_VPNV4_NODE:
        case BGP_VPNV6_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
        case BGP_VNC_L2_GROUP_NODE:
@@ -1395,8 +1389,6 @@ DEFUN (config_end,
        case BABEL_NODE:
        case BGP_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
        case BGP_VNC_L2_GROUP_NODE:
index 1e700aaa8f8c7bea013c9819d30863a2a07d65a4..95d8ee99dfa1cc1e9a7b7c4f6b561352fe60eee6 100644 (file)
@@ -110,8 +110,6 @@ enum node_type {
        BGP_VNC_L2_GROUP_NODE,   /* BGP VNC L2 group */
        RFP_DEFAULTS_NODE,       /* RFP defaults node */
        BGP_EVPN_NODE,           /* BGP EVPN node. */
-       BGP_VPNPOLICY_IPV4_NODE, /* BGP VPN IPv6 policy */
-       BGP_VPNPOLICY_IPV6_NODE, /* BGP VPN IPv6 policy */
        OSPF_NODE,               /* OSPF protocol mode */
        OSPF6_NODE,              /* OSPF protocol for IPv6 mode */
        LDP_NODE,                /* LDP protocol mode */
index a8e7462baac123992a49a50dfaa3ee621ce62096..74e7be7c7d76821705d9e923261f0a8bef707a9b 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -1055,8 +1055,6 @@ int proto_redistnum(int afi, const char *s)
                        return ZEBRA_ROUTE_BABEL;
                else if (strmatch(s, "sharp"))
                        return ZEBRA_ROUTE_SHARP;
-               else if (strmatch(s, "vpn"))
-                       return ZEBRA_ROUTE_BGP_VPN;
        }
        if (afi == AFI_IP6) {
                if (strmatch(s, "kernel"))
@@ -1085,8 +1083,6 @@ int proto_redistnum(int afi, const char *s)
                        return ZEBRA_ROUTE_BABEL;
                else if (strmatch(s, "sharp"))
                        return ZEBRA_ROUTE_SHARP;
-               else if (strmatch(s, "vpn"))
-                       return ZEBRA_ROUTE_BGP_VPN;
        }
        return -1;
 }
index 98cada8f89887ecdf7fa035de51434a8761e9b86..310a993c38654e551871b981ad07543dd84b58ce 100644 (file)
@@ -76,7 +76,6 @@ ZEBRA_ROUTE_VNC_DIRECT_RH, vnc-rn, NULL,   'V', 0, 0, "VNC-RN"
 ZEBRA_ROUTE_BGP_DIRECT, bgp-direct, NULL,  'b', 0, 0, "BGP-Direct"
 #  bgp unicast -> vnc 
 ZEBRA_ROUTE_BGP_DIRECT_EXT, bgp-direct-to-nve-groups, NULL, 'e', 0, 0, "BGP2VNC"
-ZEBRA_ROUTE_BGP_VPN,    vpn,       NULL,   'c', 1, 1, "VPN", bgpd
 ZEBRA_ROUTE_BABEL,      babel,     babeld, 'A', 1, 1, "Babel"
 ZEBRA_ROUTE_SHARP,    sharp,     sharpd, 'D', 1, 1, "SHARP"
 ZEBRA_ROUTE_ALL,        wildcard,  none,   '-', 0, 0, "-"
@@ -102,6 +101,5 @@ ZEBRA_ROUTE_OLSR,   "Optimised Link State Routing (OLSR)"
 ZEBRA_ROUTE_TABLE,  "Non-main Kernel Routing Table"
 ZEBRA_ROUTE_LDP,    "Label Distribution Protocol (LDP)"
 ZEBRA_ROUTE_VNC_DIRECT,    "VNC direct (not via zebra) routes"
-ZEBRA_ROUTE_BGP_VPN, "BGP VPN routes"
 ZEBRA_ROUTE_BABEL,  "Babel routing protocol (Babel)"
 ZEBRA_ROUTE_SHARP, "Super Happy Advanced Routing Protocol (sharpd)"
index 556ce272291887e952d083c62752dc70b9075ff1..efef106d978ac0e87f9bcc4ad185b8b001256e80 100644 (file)
@@ -360,9 +360,7 @@ static int vtysh_execute_func(const char *line, int pager)
                } else if ((saved_node == KEYCHAIN_KEY_NODE
                            || saved_node == LDP_PSEUDOWIRE_NODE
                            || saved_node == LDP_IPV4_IFACE_NODE
-                           || saved_node == LDP_IPV6_IFACE_NODE
-                           || saved_node == BGP_VPNPOLICY_IPV4_NODE
-                           || saved_node == BGP_VPNPOLICY_IPV6_NODE)
+                           || saved_node == LDP_IPV6_IFACE_NODE)
                           && (tried == 1)) {
                        vtysh_execute("exit");
                } else if (tried) {
@@ -634,9 +632,7 @@ int vtysh_mark_file(const char *filename)
                        } else if ((prev_node == BGP_EVPN_VNI_NODE)
                                   && (tried == 1)) {
                                fprintf(outputfile, "exit-vni\n");
-                       } else if ((prev_node == KEYCHAIN_KEY_NODE
-                                   || prev_node == BGP_VPNPOLICY_IPV4_NODE
-                                   || prev_node == BGP_VPNPOLICY_IPV6_NODE)
+                       } else if ((prev_node == KEYCHAIN_KEY_NODE)
                                   && (tried == 1)) {
                                fprintf(outputfile, "exit\n");
                        } else if (tried) {
@@ -1017,12 +1013,6 @@ static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE,
 static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE,
                                            "%s(config-router-af-vni)# "};
 
-static struct cmd_node bgp_vpn_policy_ipv4_node = {
-       BGP_VPNPOLICY_IPV4_NODE, "%s(config-router-vpn-policy-ipv4)# ", 1};
-
-static struct cmd_node bgp_vpn_policy_ipv6_node = {
-       BGP_VPNPOLICY_IPV6_NODE, "%s(config-router-vpn-policy-ipv6)# ", 1};
-
 static struct cmd_node bgp_ipv6l_node = {BGP_IPV6L_NODE,
                                         "%s(config-router-af)# "};
 
@@ -1274,20 +1264,6 @@ DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni (1-16777215)",
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_BGPD, vpn_policy_afi, vpn_policy_afi_cmd, "vpn-policy <ipv4|ipv6>",
-       "Configure a VPN policy\n"
-       BGP_AFI_HELP_STR)
-{
-       int idx = 1;
-
-       if (argv_find(argv, argc, "ipv4", &idx))
-               vty->node = BGP_VPNPOLICY_IPV4_NODE;
-       else
-               vty->node = BGP_VPNPOLICY_IPV6_NODE;
-       return CMD_SUCCESS;
-}
-
-
 #if defined(ENABLE_BGP_VNC)
 DEFUNSH(VTYSH_BGPD, vnc_defaults, vnc_defaults_cmd, "vnc defaults",
        "VNC/RFP related configuration\n"
@@ -1562,8 +1538,6 @@ static int vtysh_exit(struct vty *vty)
        case BGP_IPV6M_NODE:
        case BGP_IPV6L_NODE:
        case BGP_VRF_POLICY_NODE:
-       case BGP_VPNPOLICY_IPV4_NODE:
-       case BGP_VPNPOLICY_IPV6_NODE:
        case BGP_EVPN_NODE:
        case BGP_VNC_DEFAULTS_NODE:
        case BGP_VNC_NVE_GROUP_NODE:
@@ -3112,8 +3086,6 @@ void vtysh_init_vty(void)
        install_node(&bgp_vrf_policy_node, NULL);
        install_node(&bgp_evpn_node, NULL);
        install_node(&bgp_evpn_vni_node, NULL);
-       install_node(&bgp_vpn_policy_ipv4_node, NULL);
-       install_node(&bgp_vpn_policy_ipv6_node, NULL);
        install_node(&bgp_vnc_defaults_node, NULL);
        install_node(&bgp_vnc_nve_group_node, NULL);
        install_node(&bgp_vnc_l2_group_node, NULL);
@@ -3206,10 +3178,6 @@ void vtysh_init_vty(void)
        install_element(BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd);
        install_element(BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd);
        install_element(BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vtysh_exit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vtysh_quit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vtysh_exit_bgpd_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vtysh_quit_bgpd_cmd);
 #if defined(ENABLE_BGP_VNC)
        install_element(BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd);
        install_element(BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd);
@@ -3262,8 +3230,6 @@ void vtysh_init_vty(void)
        install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd);
        install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd);
        install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
-       install_element(BGP_VPNPOLICY_IPV4_NODE, &vtysh_end_all_cmd);
-       install_element(BGP_VPNPOLICY_IPV6_NODE, &vtysh_end_all_cmd);
        install_element(ISIS_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
@@ -3313,7 +3279,6 @@ void vtysh_init_vty(void)
        install_element(CONFIG_NODE, &router_bgp_cmd);
        install_element(BGP_NODE, &address_family_vpnv4_cmd);
        install_element(BGP_NODE, &address_family_vpnv6_cmd);
-       install_element(BGP_NODE, &vpn_policy_afi_cmd);
 #if defined(ENABLE_BGP_VNC)
        install_element(BGP_NODE, &vnc_vrf_policy_cmd);
        install_element(BGP_NODE, &vnc_defaults_cmd);
index 26dd48733e6d3180ea13974a228e6ee9c249db54..d654579b1cb46931eb5132f8dd97e8f490e9a040 100644 (file)
@@ -1865,7 +1865,6 @@ static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
                [ZEBRA_ROUTE_VNC_DIRECT_RH] = 3,
                [ZEBRA_ROUTE_BGP_DIRECT] = 3,
                [ZEBRA_ROUTE_BGP_DIRECT_EXT] = 3,
-               [ZEBRA_ROUTE_BGP_VPN] = 3,
                [ZEBRA_ROUTE_BABEL] = 2,
                [ZEBRA_ROUTE_ALL] = 4, // Shouldn't happen but for safety
 };