In attempt to test a "seamless MPLS" scenario using bgp-lu I came across the following issue.
I'm wondering whether a) that's indeed an issue (i.e. it's not due to a mis-configuration or a misunderstanding), and b) what would be needed to address this.
Topology:
+-----------------------------------------------+
| |
| |
| |
| +-----+ |
| +--------------+ 2 +---------------+ |
| | | | | |
| | +-----+ | |
| | ASN 7777 | |
| | RR | |
CE | | | | CE
+-----+ VRF-a +-----+ | +---+-+ +-----+ +--+--+ | VRF-a +-----+
| 8 +----------+ 7 +-----------+ 1 +------------+ 3 +------------+ 5 +------------+ 6 |
| | eBGP | | BGP-LU | | | | | | | | OSPF as | |
+-----+ +-----+ | +---+-+ +--+--+ +-----+ | PE-CE +-----+
ASN 888 ASN 7777 | | | ASN 7777 |
RR-client | | | RR-client |
| | | |
| | | |
| | +--+--+ OSPF backbone |
| +--------------+ 4 | LDP/MPLS |
| | | |
| +-----+ |
| ASN 7777 |
| RR-client |
| |
+-----------------------------------------------+
* Node i has a loopback with IP address 7.0.0.i/32
* Nodes i and j (with i < j) are connected by subnet ij.0.0.0/24 (e.g. node 1 and 3 are on 13.0.0.0/24)
* The host is set to the node number of the neighbor, e.g. node 1 connects to 3 using port 3 with address 13.0.0.3
* Node 2 acts as a route reflector for node 4,5,7
* Node 7 learns routes to node 2 and node 5 through the bgp-lu session with node 1
The issue:
Routes get installed correctly but pings between CEs 8 and 6 do not work. On a closer inspection, one can see that node 1 is advertising prefixes to node 7 with implicit-null labels. From node 7:
# show ip route vrf all
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
F - PBR, f - OpenFabric,
> - selected route, * - FIB route, q - queued route, r - rejected route
B>* 7.0.0.2/32 [200/0] via 17.0.0.1, 7-xge1.0, label implicit-null, 00:05:34
B>* 7.0.0.5/32 [200/0] via 17.0.0.1, 7-xge1.0, label implicit-null, 00:05:34
C>* 7.0.0.7/32 is directly connected, lo, 00:05:37
C>* 17.0.0.0/24 is directly connected, 7-xge1.0, 00:05:37
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
F - PBR, f - OpenFabric,
> - selected route, * - FIB route, q - queued route, r - rejected route
VRF vrf-a:
B> 7.0.0.6/32 [200/10] via 7.0.0.5(vrf default) (recursive), label 16, 00:04:54
* via 17.0.0.1, 7-xge1.0(vrf default), label implicit-null, 00:04:54
B>* 7.0.0.8/32 [20/0] via 78.0.0.8, 7-xge8.0, 00:05:28
C>* 7.0.7.1/32 is directly connected, vrf-a, 00:05:37
B> 55.0.55.1/32 [200/0] via 7.0.0.5(vrf default) (recursive), label 16, 00:04:54
* via 17.0.0.1, 7-xge1.0(vrf default), label implicit-null, 00:04:54
B> 56.0.0.4/30 [200/0] via 7.0.0.5(vrf default) (recursive), label 16, 00:04:54
* via 17.0.0.1, 7-xge1.0(vrf default), label implicit-null, 00:04:54
C>* 78.0.0.0/24 is directly connected, 7-xge8.0, 00:05:37
B>* 88.88.88.0/24 [20/0] via 78.0.0.8, 7-xge8.0, 00:05:28
# show ip bgp 7.0.0.5
BGP routing table entry for 7.0.0.5/32
Local label: 18
Paths: (1 available, best #1, table default)
Not advertised to any peer
Local
17.0.0.1 from 17.0.0.1 (7.0.0.1)
Origin IGP, metric 0, localpref 100, valid, internal, best (First path received)
Remote label: 3
Last update: Mon Aug 12 14:56:33 2019
Here 16 is the VPN label, and implicit-null is the label advertised through bgp-lu by 1. This is confirmed by a tcpdump on the link between 7 and 1. Once a packet from node 8 gets to 1 it gets discarded as node 1 doesn't know what to do with the VPN label.
In Cisco/Juniper there is a way to enforce the sending of labels (and the installation of the related LFIB entry), e.g. in Cisco either using send-label or allocate-label all. In FRR to the best of my knowledge there is no such thing; additionally, the code specifically enforces PHP behavior for local, aggregated and redistributed routes:
if (bgp->allocate_mpls_labels[afi][safi]) {
if (new_select) {
if (!old_select
|| bgp_label_index_differs(new_select, old_select)
|| new_select->sub_type != old_select->sub_type
|| !bgp_is_valid_label(&rn->local_label)) {
/* Enforced penultimate hop popping:
* implicit-null for local routes, aggregate
* and redistributed routes
*/
if (new_select->sub_type == BGP_ROUTE_STATIC
|| new_select->sub_type
== BGP_ROUTE_AGGREGATE
|| new_select->sub_type
== BGP_ROUTE_REDISTRIBUTE) {
if (CHECK_FLAG(
rn->flags,
BGP_NODE_REGISTERED_FOR_LABEL))
bgp_unregister_for_label(rn);
label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
&rn->local_label);
bgp_set_valid_label(&rn->local_label);
} else
bgp_register_for_label(rn, new_select);
}
} else if (CHECK_FLAG(rn->flags,
BGP_NODE_REGISTERED_FOR_LABEL)) {
bgp_unregister_for_label(rn);
}
} else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
bgp_unregister_for_label(rn);
}
There doesn't seem to be a way to tweak this, and even removing the code doesn't solve the issue as the corresponding LFIB entry is not installed (zebra checks that it's not a bgp-lu route and silently returns).
Note that by using a Cisco in place of node 1 and adding the configuration mentioned above, we are able to make this work.
Relevant configuration
node 1:
interface 1-xge2.0
ip address 12.0.0.1/24
!
interface 1-xge3.0
ip address 13.0.0.1/24
!
interface 1-xge4.0
ip address 14.0.0.1/24
!
interface 1-xge7.0
ip address 17.0.0.1/24
!
interface lo
ip address 7.0.0.1/32
!
router bgp 7777
neighbor 17.0.0.7 remote-as 7777
neighbor 17.0.0.7 update-source 17.0.0.1
!
address-family ipv4 unicast
network 7.0.0.2/32
network 7.0.0.5/32
no neighbor 17.0.0.7 activate
neighbor 17.0.0.7 next-hop-self force
exit-address-family
!
address-family ipv4 labeled-unicast
neighbor 17.0.0.7 activate
neighbor 17.0.0.7 route-reflector-client
exit-address-family
!
router ospf
ospf router-id 7.0.0.1
network 7.0.0.1/32 area 0.0.0.0
network 12.0.0.0/24 area 0.0.0.0
network 13.0.0.0/24 area 0.0.0.0
network 14.0.0.0/24 area 0.0.0.0
network 17.0.0.0/24 area 0
!
mpls ldp
router-id 7.0.0.1
!
address-family ipv4
discovery transport-address 7.0.0.1
!
interface 1-xge2.0
!
interface 1-xge3.0
!
interface 1-xge4.0
!
exit-address-family
!
!
Having the same issue. I have an environment in which some devices don't support LDP for IPv6 thus one of the possible options would be to use 6PE. It would be great having 6PE working.
In attempt to test a "seamless MPLS" scenario using bgp-lu I came across the following issue. I'm wondering whether a) that's indeed an issue (i.e. it's not due to a mis-configuration or a misunderstanding), and b) what would be needed to address this.
Topology:
The issue:
Routes get installed correctly but pings between CEs 8 and 6 do not work. On a closer inspection, one can see that node 1 is advertising prefixes to node 7 with implicit-null labels. From node 7:
Here 16 is the VPN label, and implicit-null is the label advertised through bgp-lu by 1. This is confirmed by a tcpdump on the link between 7 and 1. Once a packet from node 8 gets to 1 it gets discarded as node 1 doesn't know what to do with the VPN label.
In Cisco/Juniper there is a way to enforce the sending of labels (and the installation of the related LFIB entry), e.g. in Cisco either using
send-label
orallocate-label all
. In FRR to the best of my knowledge there is no such thing; additionally, the code specifically enforces PHP behavior for local, aggregated and redistributed routes:There doesn't seem to be a way to tweak this, and even removing the code doesn't solve the issue as the corresponding LFIB entry is not installed (zebra checks that it's not a bgp-lu route and silently returns).
Note that by using a Cisco in place of node 1 and adding the configuration mentioned above, we are able to make this work.
Relevant configuration
node 1:
node 7: