summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.c8
-rw-r--r--bgpd/rfapi/rfapi_private.h1
-rw-r--r--bgpd/rfapi/rfapi_vty.c4
-rw-r--r--bgpd/rfapi/vnc_export_bgp.c357
4 files changed, 220 insertions, 150 deletions
diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c
index 9fc3a8af87..c96e869f1c 100644
--- a/bgpd/rfapi/bgp_rfapi_cfg.c
+++ b/bgpd/rfapi/bgp_rfapi_cfg.c
@@ -1459,6 +1459,14 @@ DEFUN (vnc_export_nvegroup,
rfg_new = bgp_rfapi_cfg_match_byname(bgp, argv[5]->arg,
RFAPI_GROUP_CFG_NVE);
+ if (rfg_new == NULL)
+ rfg_new = bgp_rfapi_cfg_match_byname(bgp, argv[5]->arg,
+ RFAPI_GROUP_CFG_VRF);
+
+ if (rfg_new == NULL) {
+ vty_out(vty, "Can't group named \"%s\".\n", argv[5]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
if (argv[2]->arg[0] == 'b') {
diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h
index 73c9312a64..cef319b43f 100644
--- a/bgpd/rfapi/rfapi_private.h
+++ b/bgpd/rfapi/rfapi_private.h
@@ -345,6 +345,7 @@ extern void rfapi_un_options_free(struct rfapi_un_option *goner);
extern void rfapi_vn_options_free(struct rfapi_vn_option *goner);
+extern void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg);
/*------------------------------------------
* rfapi_extract_l2o
*
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index f678e78825..5b080ae1e6 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -4632,6 +4632,8 @@ notcfg:
* add [vrf <vrf-name>] prefix <prefix>
* [rd <value>] [label <value>] [local-preference <0-4294967295>]
************************************************************************/
+
+/* NOTE: this functions parallels vnc_direct_add_rn_group_rd */
static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf,
const char *arg_prefix,
const char *arg_rd, /* optional */
@@ -4847,7 +4849,7 @@ static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg)
return count;
}
-static void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg)
+void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg)
{
struct rfapi_descriptor *rfd = rfg->rfd;
afi_t afi;
diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c
index 75347a7eea..7092218663 100644
--- a/bgpd/rfapi/vnc_export_bgp.c
+++ b/bgpd/rfapi/vnc_export_bgp.c
@@ -50,6 +50,14 @@
#include "bgpd/rfapi/rfapi_vty.h"
#include "bgpd/rfapi/vnc_debug.h"
+
+static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
+ struct rfapi_nve_group_cfg *rfg,
+ struct route_node *rn,
+ struct attr *attr,
+ afi_t afi,
+ struct rfapi_descriptor *irfd);
+
/***********************************************************************
* Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
***********************************************************************/
@@ -754,7 +762,7 @@ void vnc_direct_bgp_add_prefix(struct bgp *bgp,
/*
* if no NVEs currently associated with this group, skip it
*/
- if (!rfgn->rfg->nves)
+ if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
continue;
/*
@@ -768,6 +776,11 @@ void vnc_direct_bgp_add_prefix(struct bgp *bgp,
continue;
}
+ if (rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
+ vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
+ afi, rfgn->rfg->rfd);
+ continue; /* yuck! - but consistent with rest of function */
+ }
/*
* For each NVE that is assigned to the export nve group,
* generate
@@ -775,70 +788,8 @@ void vnc_direct_bgp_add_prefix(struct bgp *bgp,
*/
for (ln = listhead(rfgn->rfg->nves); ln;
ln = listnextnode(ln)) {
-
- struct prefix nhp;
- struct rfapi_descriptor *irfd;
- struct bgp_info info;
- struct attr hattr;
- struct attr *iattr;
-
- irfd = listgetdata(ln);
-
- if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
- continue;
-
- /*
- * Construct new attribute set with NVE's VN addr as
- * nexthop and without Tunnel Encap attr
- */
- if (encap_attr_export(&hattr, &attr, &nhp, rn))
- continue;
-
- if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
- vnc_zlog_debug_any("%s: attr follows",
- __func__);
- rfapiPrintAttrPtrs(NULL, &attr);
- vnc_zlog_debug_any("%s: hattr follows",
- __func__);
- rfapiPrintAttrPtrs(NULL, &hattr);
- }
-
- if (rfgn->rfg->routemap_export_bgp) {
- route_map_result_t ret;
- info.peer = irfd->peer;
- info.attr = &hattr;
- ret = route_map_apply(
- rfgn->rfg->routemap_export_bgp, &rn->p,
- RMAP_BGP, &info);
- if (ret == RMAP_DENYMATCH) {
- bgp_attr_flush(&hattr);
- vnc_zlog_debug_verbose(
- "%s: route map says DENY, so not calling bgp_update",
- __func__);
- continue;
- }
- }
-
- if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
- vnc_zlog_debug_any(
- "%s: hattr after route_map_apply:",
- __func__);
- rfapiPrintAttrPtrs(NULL, &hattr);
- }
-
- iattr = bgp_attr_intern(&hattr);
- bgp_attr_flush(&hattr);
-
- bgp_update(irfd->peer, &rn->p, /* prefix */
- 0, /* addpath_id */
- iattr, /* bgp_update copies it */
- afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
- BGP_ROUTE_REDISTRIBUTE,
- NULL, /* RD not used for unicast */
- NULL, /* tag not used for unicast */
- 0, NULL); /* EVPN not used */
-
- bgp_attr_unintern(&iattr);
+ vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
+ afi, listgetdata(ln));
}
}
@@ -903,7 +854,7 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
/*
* if no NVEs currently associated with this group, skip it
*/
- if (!rfgn->rfg->nves)
+ if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
continue;
/*
@@ -913,6 +864,24 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
if (import_table != rfgn->rfg->rfapi_import_table)
continue;
+ if (rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
+ struct prefix nhp;
+ struct rfapi_descriptor *irfd;
+
+ irfd = rfgn->rfg->rfd;
+
+ if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
+ continue;
+
+ bgp_withdraw(irfd->peer, &rn->p, /* prefix */
+ 0, /* addpath_id */
+ NULL, /* attr, ignored */
+ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
+ BGP_ROUTE_REDISTRIBUTE,
+ NULL, /* RD not used for unicast */
+ NULL, NULL); /* tag not used for unicast */
+ continue; /* yuck! - but consistent with rest of function */
+ }
/*
* For each NVE that is assigned to the export nve group,
* generate
@@ -1177,6 +1146,121 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
}
}
+static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
+ struct rfapi_nve_group_cfg *rfg,
+ struct route_node *rn,
+ struct attr *attr,
+ afi_t afi,
+ struct rfapi_descriptor *irfd)
+{
+ struct prefix nhp;
+ struct bgp_info info;
+ struct attr hattr;
+ struct attr *iattr;
+
+ if (irfd == NULL && rfg->type != RFAPI_GROUP_CFG_VRF) {
+ /* need new rfapi_handle, for peer strcture
+ * -- based on vnc_add_vrf_prefi */
+ assert (rfg->rfd == NULL);
+
+ if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
+ vnc_zlog_debug_verbose("%s: VRF \"%s\" is missing RT import/export configuration.\n",
+ __func__, rfg->name);
+ return;
+ }
+ if (!rfg->rd.prefixlen) {
+ vnc_zlog_debug_verbose("%s: VRF \"%s\" is missing RD configuration.\n",
+ __func__, rfg->name);
+ return;
+ }
+ if (rfg->label > MPLS_LABEL_MAX) {
+ vnc_zlog_debug_verbose("%s: VRF \"%s\" is missing defaul label configuration.\n",
+ __func__, rfg->name);
+ return;
+ }
+
+ irfd = XCALLOC(MTYPE_RFAPI_DESC,
+ sizeof(struct rfapi_descriptor));
+ irfd->bgp = bgp;
+ rfg->rfd = irfd;
+ /* leave most fields empty as will get from (dynamic) config
+ * when needed */
+ irfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
+ irfd->cookie = rfg;
+ if (rfg->vn_prefix.family
+ && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
+ rfapiQprefix2Raddr(&rfg->vn_prefix, &irfd->vn_addr);
+ } else {
+ memset(&irfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
+ irfd->vn_addr.addr_family = AF_INET;
+ irfd->vn_addr.addr.v4 = bgp->router_id;
+ }
+ irfd->un_addr = irfd->vn_addr; /* sigh, need something in UN for
+ lookups */
+ vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
+ rfg->name);
+ rfapi_init_and_open(bgp, irfd, rfg);
+ }
+
+ if (irfd == NULL || rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
+ return;
+
+ /*
+ * Construct new attribute set with NVE's VN
+ * addr as
+ * nexthop and without Tunnel Encap attr
+ */
+ if (encap_attr_export(&hattr, attr, &nhp, rn))
+ return;
+
+ if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
+ vnc_zlog_debug_any("%s: attr follows",
+ __func__);
+ rfapiPrintAttrPtrs(NULL, attr);
+ vnc_zlog_debug_any("%s: hattr follows",
+ __func__);
+ rfapiPrintAttrPtrs(NULL, &hattr);
+ }
+
+ if (rfg->routemap_export_bgp) {
+ route_map_result_t ret;
+ info.peer = irfd->peer;
+ info.attr = &hattr;
+ ret = route_map_apply(
+ rfg->routemap_export_bgp,
+ &rn->p, RMAP_BGP, &info);
+ if (ret == RMAP_DENYMATCH) {
+ bgp_attr_flush(&hattr);
+ vnc_zlog_debug_verbose(
+ "%s: route map says DENY, so not calling bgp_update",
+ __func__);
+ return;
+ }
+ }
+
+ if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
+ vnc_zlog_debug_any(
+ "%s: hattr after route_map_apply:",
+ __func__);
+ rfapiPrintAttrPtrs(NULL, &hattr);
+ }
+ iattr = bgp_attr_intern(&hattr);
+ bgp_attr_flush(&hattr);
+
+ bgp_update(irfd->peer, &rn->p, /* prefix */
+ 0, /* addpath_id */
+ iattr, /* bgp_update copies it */
+ afi, SAFI_UNICAST,
+ ZEBRA_ROUTE_VNC_DIRECT,
+ BGP_ROUTE_REDISTRIBUTE,
+ NULL, /* RD not used for unicast */
+ NULL, /* tag not used for unicast */
+ 0, NULL); /* EVPN not used */
+
+ bgp_attr_unintern(&iattr);
+
+ return;
+}
/*
* Caller is responsible for ensuring that the specified nve-group
@@ -1207,8 +1291,7 @@ static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
return;
}
- if (!rfg->nves) {
- /* avoid segfault below if list doesn't exist */
+ if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
return;
}
@@ -1235,7 +1318,11 @@ static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
continue;
}
-
+ if (rfg->type == RFAPI_GROUP_CFG_VRF) {
+ vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
+ afi, rfg->rfd);
+ continue; /* yuck! - but consistent with rest of function */
+ }
/*
* For each NVE that is assigned to the export nve
* group, generate
@@ -1243,53 +1330,8 @@ static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
*/
for (ln = listhead(rfg->nves); ln;
ln = listnextnode(ln)) {
-
- struct prefix nhp;
- struct rfapi_descriptor *irfd;
- struct bgp_info info;
- struct attr hattr;
- struct attr *iattr;
-
- irfd = listgetdata(ln);
-
- if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
- continue;
-
- /*
- * Construct new attribute set with NVE's VN
- * addr as
- * nexthop and without Tunnel Encap attr
- */
- if (encap_attr_export(&hattr, &attr, &nhp, rn))
- continue;
-
- if (rfg->routemap_export_bgp) {
- route_map_result_t ret;
- info.peer = irfd->peer;
- info.attr = &hattr;
- ret = route_map_apply(
- rfg->routemap_export_bgp,
- &rn->p, RMAP_BGP, &info);
- if (ret == RMAP_DENYMATCH) {
- bgp_attr_flush(&hattr);
- continue;
- }
- }
-
- iattr = bgp_attr_intern(&hattr);
- bgp_attr_flush(&hattr);
-
- bgp_update(irfd->peer, &rn->p, /* prefix */
- 0, /* addpath_id */
- iattr, /* bgp_update copies it */
- afi, SAFI_UNICAST,
- ZEBRA_ROUTE_VNC_DIRECT,
- BGP_ROUTE_REDISTRIBUTE,
- NULL, /* RD not used for unicast */
- NULL, /* tag not used for unicast */
- 0, NULL); /* EVPN not used */
-
- bgp_attr_unintern(&iattr);
+ vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
+ afi, listgetdata(ln));
}
}
}
@@ -1308,6 +1350,28 @@ void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP6);
}
+static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
+ struct rfapi_nve_group_cfg *rfg,
+ struct route_node *rn,
+ afi_t afi,
+ struct rfapi_descriptor *irfd)
+{
+ if (irfd == NULL)
+ return;
+ bgp_withdraw(irfd->peer, &rn->p, /* prefix */
+ 0, /* addpath_id */
+ NULL, /* attr, ignored */
+ afi, SAFI_UNICAST,
+ ZEBRA_ROUTE_VNC_DIRECT,
+ BGP_ROUTE_REDISTRIBUTE,
+ NULL, /* RD not used for unicast */
+ NULL,
+ NULL); /* tag not used for unicast */
+ if (rfg->type == RFAPI_GROUP_CFG_VRF) {
+ clear_vnc_vrf_closer(rfg);
+ }
+ return;
+}
/*
* Caller is responsible for ensuring that the specified nve-group
@@ -1333,8 +1397,7 @@ static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
assert(afi == AFI_IP || afi == AFI_IP6);
rt = import_table->imported_vpn[afi];
- if (!rfg->nves) {
- /* avoid segfault below if list does not exist */
+ if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
return;
}
@@ -1342,37 +1405,25 @@ static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
/*
* Walk the NVE-Group's VNC Import table
*/
- for (rn = route_top(rt); rn; rn = route_next(rn)) {
-
+ for (rn = route_top(rt); rn; rn = route_next(rn))
if (rn->info) {
+ if (rfg->type == RFAPI_GROUP_CFG_VRF)
+ vnc_direct_del_rn_group_rd(bgp, rfg, rn,
+ afi, rfg->rfd);
+ else {
+ struct listnode *ln;
- struct listnode *ln;
-
- /*
- * For each NVE that is assigned to the export nve
- * group, generate
- * a route with that NVE as its next hop
- */
- for (ln = listhead(rfg->nves); ln;
- ln = listnextnode(ln)) {
-
- struct rfapi_descriptor *irfd;
-
- irfd = listgetdata(ln);
-
- bgp_withdraw(
- irfd->peer, &rn->p, /* prefix */
- 0, /* addpath_id */
- NULL, /* attr, ignored */
- afi, SAFI_UNICAST,
- ZEBRA_ROUTE_VNC_DIRECT,
- BGP_ROUTE_REDISTRIBUTE,
- NULL, /* RD not used for unicast */
- NULL,
- NULL); /* tag not used for unicast */
+ /*
+ * For each NVE that is assigned to the export nve
+ * group, generate
+ * a route with that NVE as its next hop
+ */
+ for (ln = listhead(rfg->nves); ln;
+ ln = listnextnode(ln))
+ vnc_direct_del_rn_group_rd(bgp, rfg, rn,
+ afi, listgetdata(ln));
}
}
- }
}
@@ -1472,10 +1523,15 @@ static void import_table_to_nve_list_direct_bgp(struct bgp *bgp,
/*
* If this NVE-Group's import table matches the current one
*/
- if (rfgn->rfg && rfgn->rfg->nves
- && rfgn->rfg->rfapi_import_table == it) {
-
- nve_group_to_nve_list(rfgn->rfg, nves, family);
+ if (rfgn->rfg && rfgn->rfg->rfapi_import_table == it) {
+ if (rfgn->rfg->nves)
+ nve_group_to_nve_list(rfgn->rfg, nves, family);
+ else if (rfgn->rfg->rfd &&
+ rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
+ if (!*nves)
+ *nves = list_new();
+ listnode_add(*nves, rfgn->rfg->rfd);
+ }
}
}
}
@@ -1780,6 +1836,9 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
/* This is the per-RD table of prefixes */
table = prn->info;
+ if (!table)
+ continue;
+
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/*