bgpd: bugfix vpn->vrf leak: unicast-originated routes are local non-LSP

In general, routes leaked from the vpn rib to a vrf include any
labels that might have been attached to the vpn route. VRF routes
that have labels attached require a label-switched path and therefore
require nexthops with labels in order to be marked valid by the
nexthop-tracking logic.

However, some routes in the vpn RIB originated in vrfs local to this
router. Even though they may have labels, we must omit the labels
when leaking to a vrf because traffic using those resulting routes
will be carried by this router via IP routing and not label switching.
The nexthops of these routes do not need to indicate a label-switched
path, and thus the routes should be marked valid even when their nexthops
do not have labels.

This changeset omits labels from vpn->vrf leaked routes when the ultimate
source of the vpn route was a local vrf.

Signed-off-by: G. Paul Ziemba <paulz@labn.net>
This commit is contained in:
G. Paul Ziemba 2018-04-11 10:58:03 -07:00
parent 08097fedd0
commit 513bf8d6c9

View File

@ -891,6 +891,8 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
mpls_label_t *pLabels = NULL;
int num_labels = 0;
int nexthop_self_flag = 1;
struct bgp_info *bi_ultimate = NULL;
int origin_local = 0;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@ -982,13 +984,40 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
/*
* ensure labels are copied
*
* However, there is a special case: if the route originated in
* another local VRF (as opposed to arriving via VPN), then the
* nexthop is reached by hairpinning through this router (me)
* using IP forwarding only (no LSP). Therefore, the route
* imported to the VRF should not have labels attached. Note
* that nexthop tracking is also involved: eliminating the
* labels for these routes enables the non-labeled nexthops
* from the originating VRF to be considered valid for this route.
*/
if (info_vpn->extra && info_vpn->extra->num_labels) {
/* 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;
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;
}
if (debug) {
char buf_prefix[PREFIX_STRLEN];
prefix2str(p, buf_prefix, sizeof(buf_prefix));