char *s = ecommunity_ecom2str(info_vrf->attr->ecommunity,
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
- zlog_debug("%s: info_vrf->type=%d, EC{%s}", __func__,
- info_vrf->type, s);
+ zlog_debug("%s: %s info_vrf->type=%d, EC{%s}", __func__,
+ bgp_vrf->name, info_vrf->type, s);
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
if (!vpn_leak_to_vpn_active(bgp_vrf, afi, &debugmsg)) {
if (debug)
- zlog_debug("%s: skipping: %s", __func__, debugmsg);
+ zlog_debug("%s: %s skipping: %s", __func__,
+ bgp_vrf->name, debugmsg);
return;
}
/* if policy nexthop not set, use 0 */
if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
-
struct prefix *nexthop =
&bgp_vrf->vpn_policy[afi].tovpn_nexthop;
+
switch (nexthop->family) {
case AF_INET:
/* prevent mp_nexthop_global_in <- self in bgp_route.c
assert(0);
}
} else {
- if (afi == AFI_IP) {
- /* For ipv4, copy to multiprotocol nexthop field */
- static_attr.mp_nexthop_global_in = static_attr.nexthop;
- static_attr.mp_nexthop_len = 4;
- /* XXX Leave static_attr.nexthop intact for NHT */
- static_attr.flag &= ~ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
+ if (afi == AFI_IP) {
+ /* For ipv4, copy to multiprotocol nexthop field */
+ static_attr.mp_nexthop_global_in = static_attr.nexthop;
+ static_attr.mp_nexthop_len = 4;
+ /* XXX Leave static_attr.nexthop intact for NHT */
+ static_attr.flag &= ~ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ }
+ } else {
+ switch (afi) {
+ case AFI_IP:
+ static_attr.mp_nexthop_global_in.s_addr =
+ static_attr.nexthop.s_addr;
+ static_attr.mp_nexthop_len = 4;
+ static_attr.flag |=
+ ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ break;
+ case AFI_IP6:
+ break;
+ case AFI_L2VPN:
+ case AFI_MAX:
+ assert(!"Unexpected AFI to process");
+ break;
+ }
}
nexthop_self_flag = 1;
}
nexthop_orig.family = nhfamily;
switch (nhfamily) {
-
case AF_INET:
/* save */
nexthop_orig.u.prefix4 = info_vpn->attr->mp_nexthop_global_in;
nexthop_orig.prefixlen = 32;
+
+ if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ static_attr.nexthop.s_addr =
+ nexthop_orig.u.prefix4.s_addr;
+
+ static_attr.mp_nexthop_global_in =
+ info_vpn->attr->mp_nexthop_global_in;
+ static_attr.mp_nexthop_len =
+ info_vpn->attr->mp_nexthop_len;
+ }
static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
break;
-
case AF_INET6:
/* save */
nexthop_orig.u.prefix6 = info_vpn->attr->mp_nexthop_global;
nexthop_orig.prefixlen = 128;
+
+ if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ static_attr.mp_nexthop_global = nexthop_orig.u.prefix6;
+ static_attr.mp_nexthop_len = 16;
+ }
break;
}
-
/*
* route map handling
*/
* labels for these routes enables the non-labeled nexthops
* from the originating VRF to be considered valid for this route.
*/
+ if (!CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ /* work back to original route */
+ for (bi_ultimate = info_vpn;
+ bi_ultimate->extra && bi_ultimate->extra->parent;
+ bi_ultimate = bi_ultimate->extra->parent)
+ ;
- /* work back to original route */
- for (bi_ultimate = info_vpn;
- bi_ultimate->extra && bi_ultimate->extra->parent;
- bi_ultimate = bi_ultimate->extra->parent)
- ;
-
- /* if original route was unicast, then it did not arrive over vpn */
- if (bi_ultimate->net) {
- struct bgp_table *table;
+ /*
+ * if original route was unicast,
+ * then it did not arrive over vpn
+ */
+ if (bi_ultimate->net) {
+ struct bgp_table *table;
- table = bgp_node_table(bi_ultimate->net);
- if (table && (table->safi == SAFI_UNICAST))
- origin_local = 1;
- }
+ table = bgp_node_table(bi_ultimate->net);
+ if (table && (table->safi == SAFI_UNICAST))
+ origin_local = 1;
+ }
- /* copy labels */
- if (!origin_local && info_vpn->extra && info_vpn->extra->num_labels) {
- num_labels = info_vpn->extra->num_labels;
- if (num_labels > BGP_MAX_LABELS)
- num_labels = BGP_MAX_LABELS;
- pLabels = info_vpn->extra->label;
+ /* copy labels */
+ if (!origin_local &&
+ info_vpn->extra && info_vpn->extra->num_labels) {
+ num_labels = info_vpn->extra->num_labels;
+ if (num_labels > BGP_MAX_LABELS)
+ num_labels = BGP_MAX_LABELS;
+ pLabels = info_vpn->extra->label;
+ }
}
if (debug) {
/* Is vrf configured to export to vpn? */
if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
- BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
+ && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
if (pmsg)
*pmsg = "export not set";
return 0;
/* Is vrf configured to import from vpn? */
if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
- BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)
+ && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
if (pmsg)
*pmsg = "import not set";
return 0;
"For routes leaked from vpn to current address-family\n"
"For routes leaked from current address-family to vpn\n")
+DEFPY (bgp_imexport_vrf,
+ bgp_imexport_vrf_cmd,
+ "[no] import vrf NAME$import_name",
+ NO_STR
+ "Import routes from another VRF\n"
+ "VRF to import from\n"
+ "The name of the VRF\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct listnode *node;
+ struct bgp *vrf_bgp;
+ bool remove = false;
+ int32_t idx = 0;
+ char *vname;
+ const char *export_name;
+ safi_t safi;
+ afi_t afi;
+
+ if (argv_find(argv, argc, "no", &idx))
+ remove = true;
+
+ afi = bgp_node_afi(vty);
+ safi = bgp_node_safi(vty);
+
+ vrf_bgp = bgp_lookup_by_name(import_name);
+ if (!vrf_bgp) {
+ vty_out(vty, "VRF %s is not configured as a bgp instance\n",
+ import_name);
+ return CMD_WARNING;
+ }
+
+ export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
+
+ if (remove) {
+ for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node,
+ vname)) {
+ if (strcmp(vname, import_name) == 0)
+ break;
+ }
+
+ if (!vname) {
+ vty_out(vty,
+ "Specified VRF %s was not imported, ignoring",
+ import_name);
+ return CMD_WARNING;
+ }
+
+ listnode_delete(bgp->vpn_policy[afi].import_vrf, vname);
+ XFREE(MTYPE_TMP, vname);
+
+ if (bgp->vpn_policy[afi].import_vrf->count == 0) {
+ UNSET_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT);
+
+ ecommunity_free(
+ &bgp->vpn_policy[afi]
+ .rtlist[BGP_VPN_POLICY_DIR_FROMVPN]);
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(vrf_bgp->vpn_policy[afi].export_vrf,
+ node, vname)) {
+ if (strcmp(vname, export_name) == 0)
+ break;
+ }
+
+ listnode_delete(vrf_bgp->vpn_policy[afi].export_vrf, vname);
+ XFREE(MTYPE_TMP, vname);
+
+ UNSET_FLAG(vrf_bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT);
+ UNSET_FLAG(vrf_bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET);
+
+ ecommunity_free(&vrf_bgp->vpn_policy[afi]
+ .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp, vrf_bgp);
+ } else {
+ char buf[1000];
+
+ for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node,
+ vname)) {
+ if (strcmp(vname, import_name) == 0)
+ return CMD_WARNING;
+ }
+
+ vname = XSTRDUP(MTYPE_TMP, import_name);
+ listnode_add(bgp->vpn_policy[afi].import_vrf, vname);
+
+ vname = XSTRDUP(MTYPE_TMP, export_name);
+ listnode_add(vrf_bgp->vpn_policy[afi].export_vrf, vname);
+
+ prefix_rd2str(&vrf_bgp->vrf_prd, buf, sizeof(buf));
+ vrf_bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN] =
+ ecommunity_str2com(buf, ECOMMUNITY_ROUTE_TARGET, 0);
+ bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN] =
+ ecommunity_str2com(buf, ECOMMUNITY_ROUTE_TARGET, 0);
+
+ SET_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT);
+ SET_FLAG(vrf_bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT);
+ SET_FLAG(vrf_bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET);
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp,
+ vrf_bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
/* This command is valid only in a bgp vrf instance or the default instance */
DEFPY (bgp_imexport_vpn,
bgp_imexport_vpn_cmd,
{
int indent = 2;
+ if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)
+ || CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT))
+ return;
+
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
install_element(BGP_IPV4_NODE, &bgp_imexport_vpn_cmd);
install_element(BGP_IPV6_NODE, &bgp_imexport_vpn_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_imexport_vrf_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_imexport_vrf_cmd);
+
/* ttl_security commands */
install_element(BGP_NODE, &neighbor_ttl_security_cmd);
install_element(BGP_NODE, &no_neighbor_ttl_security_cmd);
bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
MPLS_LABEL_NONE;
+
+ bgp->vpn_policy[afi].import_vrf = list_new();
+ bgp->vpn_policy[afi].export_vrf = list_new();
}
if (name) {
bgp->name = XSTRDUP(MTYPE_BGP, name);
vty_out(vty, " import vpn\n");
}
+ if (CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ struct listnode *node;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(
+ bgp->vpn_policy[afi].import_vrf, node,
+ name))
+ vty_out(vty, " import vrf %s\n", name);
+ }
}
vty_endframe(vty, " exit-address-family\n");
#define BGP_VPN_POLICY_TOVPN_LABEL_AUTO (1 << 0)
#define BGP_VPN_POLICY_TOVPN_RD_SET (1 << 1)
#define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET (1 << 2)
+
+ /* If we are importing a vrf -> vrf keep a list of vrf names */
+ struct list *import_vrf;
+ struct list *export_vrf;
};
/*
#define BGP_CONFIG_DAMPENING (1 << 0)
#define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT (1 << 1)
#define BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT (1 << 2)
+#define BGP_CONFIG_VRF_TO_VRF_IMPORT (1 << 3)
+#define BGP_CONFIG_VRF_TO_VRF_EXPORT (1 << 4)
/* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */
#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 1)