summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_mplsvpn.c63
-rw-r--r--bgpd/bgp_mplsvpn.h42
-rw-r--r--bgpd/bgp_vty.c730
-rw-r--r--bgpd/bgp_vty.h3
-rw-r--r--bgpd/bgp_zebra.c29
-rw-r--r--bgpd/bgpd.c16
-rw-r--r--bgpd/bgpd.h3
7 files changed, 348 insertions, 538 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 56676e62c..5ed43e4bd 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -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"
@@ -732,7 +732,6 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
safi_t safi = SAFI_MPLS_VPN;
/*
- * Walk vpn table, delete bi with parent == bgp_vrf
* Walk vpn table, delete bi with bgp_orig == bgp_vrf
*/
for (prn = bgp_table_top(bgp_vpn->rib[afi][safi]); prn;
@@ -818,7 +817,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;
@@ -830,7 +828,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;
@@ -887,28 +885,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;
@@ -988,7 +965,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;
@@ -1001,7 +977,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);
@@ -1158,36 +1134,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);
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index d0ad8ac84..d35568b83 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -81,6 +81,14 @@ extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
const char **pmsg)
{
+ if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
+ && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+
+ if (pmsg)
+ *pmsg = "source bgp instance neither vrf nor default";
+ return 0;
+ }
+
/* Is vrf configured to export to vpn? */
if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
@@ -107,27 +115,21 @@ 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) {
+ && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
if (pmsg)
*pmsg = "destination bgp instance neither vrf nor default";
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]) {
@@ -142,10 +144,16 @@ static inline void vpn_leak_prechange(vpn_policy_direction_t direction,
afi_t afi, struct bgp *bgp_vpn,
struct bgp *bgp_vrf)
{
- if (direction == BGP_VPN_POLICY_DIR_FROMVPN)
+ if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) &&
+ vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) {
+
vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi);
- if (direction == BGP_VPN_POLICY_DIR_TOVPN)
+ }
+ if ((direction == BGP_VPN_POLICY_DIR_TOVPN) &&
+ vpn_leak_to_vpn_active(bgp_vrf, afi, NULL)) {
+
vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi);
+ }
}
static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
@@ -156,16 +164,14 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
- if (bgp_vrf->vpn_policy[afi].tovpn_label
- != bgp_vrf->vpn_policy[afi]
+ if (bgp_vrf->vpn_policy[afi].tovpn_label !=
+ bgp_vrf->vpn_policy[afi]
.tovpn_zebra_vrf_label_last_sent) {
vpn_leak_zebra_vrf_label_update(bgp_vrf, afi);
}
vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
}
- if (direction == BGP_VPN_POLICY_DIR_TOVPN)
- vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
}
extern void vpn_policy_routemap_event(const char *rmap_name);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 4a5633c94..ad6f1a558 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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");
+ "%% context error: valid only in address-family <ipv4|ipv6> unicast 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");
- 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;
- label = strtoul(argv[1]->arg, NULL, 10);
+ if (argv_find(argv, argc, "no", &idx))
+ yes = 0;
- ret = vpn_policy_afis(vty, doafi);
+ if (yes)
+ label = label_val; /* rely on parser to force unsigned */
+
+ 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"
- "fromvpn: match any\n"
- "tovpn: set\n"
- "both fromvpn: match any and tovpn: set\n"
+ "Specify route target list\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;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = 0;
- ret = vpn_policy_afis(vty, doafi);
+ 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,71 +6418,48 @@ 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);
}
}
- ecommunity_free(&ecom);
+ if (ecom)
+ ecommunity_free(&ecom);
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 +6468,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;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = 0;
- ret = vpn_policy_afis(vty, doafi);
+ 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 +6491,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 +6514,75 @@ 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",
+ NO_STR
+ "Import routes to this address-family\n"
+ "Export routes from this address-family\n"
+ "to/from default instance VPN RIB\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;
+ 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 (!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;
+ }
- 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;
+ 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 +11615,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 +11640,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 +11653,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 +11662,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 +11671,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 +11730,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 +11790,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 +11803,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 +12862,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 +12886,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"
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index 459c4ffcc..f77ebb610 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -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 */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index cba3811e1..486ea3937 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1445,27 +1445,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);
- }
}
/*
@@ -1619,15 +1599,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)
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 2eae2e5e9..c178727b5 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 664f8c9da..79fe8c8c3 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -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