FRRouting / frr

The FRRouting Protocol Suite
https://frrouting.org/
Other
3.27k stars 1.24k forks source link

bgp labeled-unicast: missing option to force label allocation for neighbor #4824

Closed edipascale closed 6 months ago

edipascale commented 5 years ago

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
 !
!

node 7:

interface 7-xge1.0
 ip address 17.0.0.7/24
!
interface lo
 ip address 7.0.0.7/32
!
interface 7-xge8.0 vrf vrf-a
 ip address 78.0.0.7/24
!
interface vrf-a vrf vrf-a
 ip address 7.0.7.1/32
!
router bgp 7777
 bgp router-id 7.0.0.7
 neighbor 7.0.0.2 remote-as 7777
 neighbor 7.0.0.2 update-source 17.0.0.7
 neighbor 17.0.0.1 remote-as 7777
 neighbor 17.0.0.1 solo
 neighbor 17.0.0.1 update-source 17.0.0.7
 !
 address-family ipv4 unicast
  no neighbor 7.0.0.2 activate
  no neighbor 17.0.0.1 activate
 exit-address-family
 !
 address-family ipv4 labeled-unicast
  neighbor 17.0.0.1 activate
  neighbor 17.0.0.1 soft-reconfiguration inbound
 exit-address-family
 !
 address-family ipv4 vpn
  neighbor 7.0.0.2 activate
  neighbor 7.0.0.2 soft-reconfiguration inbound
 exit-address-family
!
router bgp 7777 vrf vrf-a
 bgp router-id 7.0.0.7
 neighbor 78.0.0.8 remote-as 888
 !
 address-family ipv4 unicast
  redistribute connected
  label vpn export auto
  rd vpn export 65500:777
  rt vpn both 65500:1
  export vpn
  import vpn
 exit-address-family
ronaldobf commented 1 year ago

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.

ton31337 commented 6 months ago

You can control this now via https://docs.frrouting.org/en/stable-9.1/bgp.html#clicmd-bgp-labeled-unicast-explicit-null-ipv4-explicit-null-ipv6-explicit-null.