Skip to content

Commit

Permalink
bgpd: Add some vrf <-> vrf code comments
Browse files Browse the repository at this point in the history
Note that when we are importing vrf EVA into vrf DONNA
we must keep track of all the vrfs EVA is being
exported into and we must also keep track of all the vrf's
that DONNA is receiving data from as well.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
  • Loading branch information
donaldsharp committed Apr 25, 2018
1 parent 89d5934 commit 1d4e8b0
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 49 deletions.
111 changes: 65 additions & 46 deletions bgpd/bgp_mplsvpn.c
Expand Up @@ -1174,7 +1174,8 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
}

/*
* For VRF route-leaking, the source will be the originating VRF.
* For VRF-2-VRF route-leaking,
* the source will be the originating VRF.
*/
if (info_vpn->extra && info_vpn->extra->bgp_orig)
src_vrf = info_vpn->extra->bgp_orig;
Expand Down Expand Up @@ -1452,7 +1453,7 @@ void vpn_policy_routemap_event(const char *rmap_name)
vpn_policy_routemap_update(bgp, rmap_name);
}

void vrf_import_from_vrf(struct bgp *bgp, struct bgp *vrf_bgp,
void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi, safi_t safi)
{
const char *export_name;
Expand All @@ -1462,59 +1463,59 @@ void vrf_import_from_vrf(struct bgp *bgp, struct bgp *vrf_bgp,
struct ecommunity *ecom;
bool first_export = false;

export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
idir = BGP_VPN_POLICY_DIR_FROMVPN;
edir = BGP_VPN_POLICY_DIR_TOVPN;


/* Cross-ref both VRFs. Also, note if this is the first time
/*
* Cross-ref both VRFs. Also, note if this is the first time
* any VRF is importing from "import_vrf".
*/
vname = XSTRDUP(MTYPE_TMP, vrf_bgp->name);
listnode_add(bgp->vpn_policy[afi].import_vrf, vname);
vname = XSTRDUP(MTYPE_TMP, from_bgp->name);
listnode_add(to_bgp->vpn_policy[afi].import_vrf, vname);

if (!listcount(vrf_bgp->vpn_policy[afi].export_vrf))
if (!listcount(from_bgp->vpn_policy[afi].export_vrf))
first_export = true;
vname = XSTRDUP(MTYPE_TMP, export_name);
listnode_add(vrf_bgp->vpn_policy[afi].export_vrf, vname);
listnode_add(from_bgp->vpn_policy[afi].export_vrf, vname);

/* Update import RT for current VRF using export RT of the VRF we're
* importing from. First though, make sure "import_vrf" has that
* set.
*/
if (first_export) {
form_auto_rd(vrf_bgp->router_id, vrf_bgp->vrf_rd_id,
&vrf_bgp->vrf_prd_auto);
vrf_bgp->vpn_policy[afi].tovpn_rd = vrf_bgp->vrf_prd_auto;
SET_FLAG(vrf_bgp->vpn_policy[afi].flags,
form_auto_rd(from_bgp->router_id, from_bgp->vrf_rd_id,
&from_bgp->vrf_prd_auto);
from_bgp->vpn_policy[afi].tovpn_rd = from_bgp->vrf_prd_auto;
SET_FLAG(from_bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_RD_SET);
prefix_rd2str(&vrf_bgp->vpn_policy[afi].tovpn_rd,
prefix_rd2str(&from_bgp->vpn_policy[afi].tovpn_rd,
buf, sizeof(buf));
vrf_bgp->vpn_policy[afi].rtlist[edir] =
from_bgp->vpn_policy[afi].rtlist[edir] =
ecommunity_str2com(buf, ECOMMUNITY_ROUTE_TARGET, 0);
SET_FLAG(vrf_bgp->af_flags[afi][safi],
SET_FLAG(from_bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_EXPORT);
}
ecom = vrf_bgp->vpn_policy[afi].rtlist[edir];
if (bgp->vpn_policy[afi].rtlist[idir])
bgp->vpn_policy[afi].rtlist[idir] =
ecommunity_merge(bgp->vpn_policy[afi]
ecom = from_bgp->vpn_policy[afi].rtlist[edir];
if (to_bgp->vpn_policy[afi].rtlist[idir])
to_bgp->vpn_policy[afi].rtlist[idir] =
ecommunity_merge(to_bgp->vpn_policy[afi]
.rtlist[idir], ecom);
else
bgp->vpn_policy[afi].rtlist[idir] = ecommunity_dup(ecom);
SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT);
to_bgp->vpn_policy[afi].rtlist[idir] = ecommunity_dup(ecom);
SET_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT);

/* Does "import_vrf" first need to export its routes or that
* is already done and we just need to import those routes
* from the global table?
*/
if (first_export)
vpn_leak_postchange(edir, afi, bgp_get_default(), vrf_bgp);
vpn_leak_postchange(edir, afi, bgp_get_default(), from_bgp);
else
vpn_leak_postchange(idir, afi, bgp_get_default(), bgp);
vpn_leak_postchange(idir, afi, bgp_get_default(), to_bgp);
}

void vrf_unimport_from_vrf(struct bgp *bgp, struct bgp *vrf_bgp,
void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi, safi_t safi)
{
const char *export_name;
Expand All @@ -1523,38 +1524,46 @@ void vrf_unimport_from_vrf(struct bgp *bgp, struct bgp *vrf_bgp,
struct ecommunity *ecom;
struct listnode *node;

export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
idir = BGP_VPN_POLICY_DIR_FROMVPN;
edir = BGP_VPN_POLICY_DIR_TOVPN;

/* Were we importing from "import_vrf"? */
for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node,
vname)) {
if (strcmp(vname, vrf_bgp->name) == 0)
for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf, node,
vname)) {
if (strcmp(vname, from_bgp->name) == 0)
break;
}

/*
* We do not check in the cli if the passed in bgp
* instance is actually imported into us before
* we call this function. As such if we do not
* find this in the import_vrf list than
* we just need to return safely.
*/
if (!vname)
return;

/* Remove "import_vrf" from our import list. */
listnode_delete(bgp->vpn_policy[afi].import_vrf, vname);
listnode_delete(to_bgp->vpn_policy[afi].import_vrf, vname);
XFREE(MTYPE_TMP, vname);

/* Remove routes imported from "import_vrf". */
/* TODO: In the current logic, we have to first remove all
* imported routes and then (if needed) import back routes
*/
vpn_leak_prechange(idir, afi, bgp_get_default(), bgp);
vpn_leak_prechange(idir, afi, bgp_get_default(), to_bgp);

if (bgp->vpn_policy[afi].import_vrf->count == 0) {
UNSET_FLAG(bgp->af_flags[afi][safi],
if (to_bgp->vpn_policy[afi].import_vrf->count == 0) {
UNSET_FLAG(to_bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT);
ecommunity_free(&bgp->vpn_policy[afi].rtlist[idir]);
ecommunity_free(&to_bgp->vpn_policy[afi].rtlist[idir]);
} else {
ecom = vrf_bgp->vpn_policy[afi].rtlist[edir];
ecommunity_del_val(bgp->vpn_policy[afi].rtlist[idir],
ecom = from_bgp->vpn_policy[afi].rtlist[edir];
ecommunity_del_val(to_bgp->vpn_policy[afi].rtlist[idir],
(struct ecommunity_val *)ecom->val);
vpn_leak_postchange(idir, afi, bgp_get_default(), bgp);
vpn_leak_postchange(idir, afi, bgp_get_default(), to_bgp);
}

/*
Expand All @@ -1567,28 +1576,38 @@ void vrf_unimport_from_vrf(struct bgp *bgp, struct bgp *vrf_bgp,
* So make it happy, under protest, with liberty and justice
* for all.
*/
assert(vrf_bgp->vpn_policy[afi].export_vrf);
assert(from_bgp->vpn_policy[afi].export_vrf);

/* Remove us from "import_vrf's" export list. If no other VRF
* is importing from "import_vrf", cleanup appropriately.
*/
for (ALL_LIST_ELEMENTS_RO(vrf_bgp->vpn_policy[afi].export_vrf,
for (ALL_LIST_ELEMENTS_RO(from_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);
/*
* If we have gotten to this point then the vname must
* exist. If not, we are in a world of trouble and
* have slag sitting around.
*
* import_vrf and export_vrf must match in having
* the in/out names as appropriate.
*/
assert(vname);

listnode_delete(from_bgp->vpn_policy[afi].export_vrf, vname);
XFREE(MTYPE_TMP, vname);

if (!listcount(vrf_bgp->vpn_policy[afi].export_vrf)) {
vpn_leak_prechange(edir, afi, bgp_get_default(), vrf_bgp);
ecommunity_free(&vrf_bgp->vpn_policy[afi].rtlist[edir]);
UNSET_FLAG(vrf_bgp->af_flags[afi][safi],
if (!listcount(from_bgp->vpn_policy[afi].export_vrf)) {
vpn_leak_prechange(edir, afi, bgp_get_default(), from_bgp);
ecommunity_free(&from_bgp->vpn_policy[afi].rtlist[edir]);
UNSET_FLAG(from_bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_EXPORT);
memset(&vrf_bgp->vpn_policy[afi].tovpn_rd, 0,
memset(&from_bgp->vpn_policy[afi].tovpn_rd, 0,
sizeof(struct prefix_rd));
UNSET_FLAG(vrf_bgp->vpn_policy[afi].flags,
UNSET_FLAG(from_bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_RD_SET);
}
}
Expand Down
4 changes: 2 additions & 2 deletions bgpd/bgp_mplsvpn.h
Expand Up @@ -78,9 +78,9 @@ extern void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,
extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi);
extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
extern int vpn_leak_label_callback(mpls_label_t label, void *lblid, bool alloc);
extern void vrf_import_from_vrf(struct bgp *bgp, struct bgp *vrf_bgp,
extern void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi, safi_t safi);
void vrf_unimport_from_vrf(struct bgp *bgp, struct bgp *vrf_bgp,
void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi, safi_t safi);

static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
Expand Down
10 changes: 9 additions & 1 deletion bgpd/bgpd.h
Expand Up @@ -189,8 +189,16 @@ struct vpn_policy {
#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 */
/*
* If we are importing another vrf into us keep a list of
* vrf names that are being imported into us.
*/
struct list *import_vrf;

/*
* if we are being exported to another vrf keep a list of
* vrf names that we are being exported to.
*/
struct list *export_vrf;
};

Expand Down

0 comments on commit 1d4e8b0

Please sign in to comment.