frr icon indicating copy to clipboard operation
frr copied to clipboard

VPNv4 Routes failing to import into VRF in 8.0

Open jonlangemak opened this issue 4 years ago • 20 comments

Hi folks - I have a use case where I want to use FRR as a sort of IPv4 to VPNv4 route reflector. That is - I'd like to take in VPNv4 routes and then convert them into IPv4 routes to send to a Peer in a VRF (a typical PE model). I can't seem to get the VPNv4 routes to import into the VRF - they all show as inaccessible which makes sense since they likely can't resolve their next hop as Im not running LDP or anything to be able to resolve the underlying LSP.

I know in JunOS you can tell the router to resolve next hops from the inet.0 table rather than inet.3 to help with this kind of scenario, Is a similar configuration possible in FRR? I've tried disable connected checks etc but the routes stay stuck as inaccessible and never import into the VRF.

Thanks!

jonlangemak avatar Aug 01 '21 15:08 jonlangemak

Can you provide some output showing what you're referring to? It's not clear which address-family shows the next-hop is inaccessible, or what may be causing it. Would also probably be useful to see the output of show ip nht and show ip nht vrf <vrf name>.

What version of FRR are you running?

taspelund avatar Aug 02 '21 21:08 taspelund

@taspelund Many apologies for the delay, I got hit with a flu or something and was out of commission for a long time. In either case, I think I might have stumbled upon a bug here. It looks like this should just work but the problem seems to be that newly added VPNv4 routes are not being properly advertised to a VRF based IPv4 peer. I built a quick lab to demonstrate what I'm seeing...

Lab topology

VM1 (10.10.10.0) <------> (10.10.10.1) VM2 (10.10.10.2) <------> VM3(10.10.10.3)

The base premise of the lab is that VM2 is running FRR and acting as a PE. VM1 is acting an upstream VPNv4 peer and sending VM2 VPN routes. VM3 is a normal IPv4 peer is that is connected to VM2 inside of a VRF and has a normal IPv4 BGP peer configuration. Both VM1 and VM3 are running GOBGP. The configuration files for the three VMs are below....

VM1

global:
    config:
        as: 65000
        router-id: 10.10.10.0
neighbors:
    - config:
        neighbor-address: 10.10.10.1
        peer-as: 65000
      timers:
          config:
            connect-retry: 1
            hold-time: 3
            keepalive-interval: 1
      afi-safis:
        - config:
            afi-safi-name: l3vpn-ipv4-unicast

VM2

frr version 8.0
frr defaults traditional
hostname vm2
log syslog informational
no ip forwarding
no ipv6 forwarding
bgp no-rib
service integrated-vtysh-config
!
router bgp 65000
 bgp router-id 10.10.10.1
 no bgp ebgp-requires-policy
 bgp disable-ebgp-connected-route-check
 bgp bestpath compare-routerid
 no bgp network import-check
 neighbor 10.10.10.0 remote-as 65000
 neighbor 10.10.10.0 update-source 10.10.10.1
 !
 address-family ipv4 vpn
  neighbor 10.10.10.0 activate
  neighbor 10.10.10.0 attribute-unchanged next-hop
 exit-address-family
!
router bgp 65000 vrf vrf_1
 no bgp ebgp-requires-policy
 bgp disable-ebgp-connected-route-check
 bgp bestpath compare-routerid
 no bgp network import-check
 neighbor 10.10.10.3 remote-as 65123
 !
 address-family ipv4 unicast
  redistribute connected
  rd vpn export 65000:1
  rt vpn both 65000:1
  export vpn
  import vpn
 exit-address-family
!
line vty
!
end

VM3

global:
    config:
        as: 65123
        router-id: 10.10.10.3
neighbors:
    - config:
        neighbor-address: 10.10.10.2
        peer-as: 65000
      ebgp-multihop:
          config:
            enabled: true
            multihop-ttl: 255
      timers:
          config:
            connect-retry: 1
            hold-time: 3
            keepalive-interval: 1

If I start everything up - I immediately see that the route for the directly connected VRF interface is being sent to VM1 as a VPNv4 route...

root@vm1:~# ./gobgp global rib -a ipv4-l3vpn
   Network               Labels     Next Hop             AS_PATH              Age        Attrs
*> 65000:1:10.10.10.2/31 [3]        10.10.10.1                                01:09:48   [{Origin: ?} {Med: 0} {LocalPref: 100} {Extcomms: [65000:1]}]
root@vm1:~# 

So that's working. And if I advertise an additional prefix from VM3 that also shows up so it appears that the IPv4 to VPNv4 prefix translation is working as expected...

root@vm3:~# ./gobgp global rib add 172.16.16.0/24
root@vm3:~# 
root@vm1:~# ./gobgp global rib -a ipv4-l3vpn
   Network                Labels     Next Hop             AS_PATH              Age        Attrs
*> 65000:1:10.10.10.2/31  [3]        10.10.10.1                                01:10:44   [{Origin: ?} {Med: 0} {LocalPref: 100} {Extcomms: [65000:1]}]
*> 65000:1:172.16.16.0/24 [3]        10.10.10.3           65123                00:00:11   [{Origin: ?} {LocalPref: 100} {Extcomms: [65000:1]}]
root@vm1:~# 

However - If I generate a VPNv4 prefix - its is not being translated to the IPv4 peer correctly despite having a matching RT....

root@vm1:~# ./gobgp global rib add -a vpnv4 10.0.0.0/24 label 10 rd 65000:1 rt 65000:1
root@vm1:~# 

The route shows up on the FRR instance - but it is marked as not valid....

vm2# show ip bgp vrf vrf_1 ipv4 
BGP table version is 6, local router ID is 10.10.10.2, vrf id 5
Default local pref 100, local AS 65000
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
   10.0.0.0/24      10.10.10.0@0<                 100      0 ?
*> 10.10.10.2/31    0.0.0.0                  0         32768 ?
*> 172.16.16.0/24   10.10.10.3                             0 65123 ?

Displayed  3 routes and 3 total paths
vm2# 

The actual prefix output...

vm2# show ip bgp vrf vrf_1 ipv4 10.0.0.0/24
BGP routing table entry for 10.0.0.0/24, version 0
Paths: (1 available, no best path)
  Not advertised to any peer
  Imported from 65000:1:10.0.0.0/24
  Local
    10.10.10.0 (inaccessible) from 0.0.0.0 (10.10.10.2) vrf default(0) announce-nh-self
      Origin incomplete, localpref 100, invalid, sourced, local
      Extended Community: RT:65000:1
      Remote label: 10
      Last update: Fri Aug 20 20:50:34 2021
vm2# 

Now what's curious here is that if I reapply the RT configuration on the FRR node - the route becomes valid...

vm2# config t
vm2(config)# router bgp 65000 vrf vrf_1
vm2(config-router)# address-family ipv4 unicast
vm2(config-router-af)# rt vpn both 65000:1
vm2(config-router-af)# 
vm2(config-router-af)# end
vm2# show ip bgp vrf vrf_1 ipv4 
BGP table version is 7, local router ID is 10.10.10.2, vrf id 5
Default local pref 100, local AS 65000
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
*> 10.0.0.0/24      10.10.10.0@0<                 100      0 ?
*> 10.10.10.2/31    0.0.0.0                  0         32768 ?
*> 172.16.16.0/24   10.10.10.3                             0 65123 ?

Displayed  3 routes and 3 total paths
vm2# 

And is then received on VM3...

root@vm3:~# ./gobgp global rib
   Network              Next Hop             AS_PATH              Age        Attrs
*> 10.0.0.0/24          10.10.10.2           65000                00:00:34   [{Origin: ?} {Extcomms: [65000:1]}]
*> 10.10.10.2/31        10.10.10.2           65000                01:11:40   [{Origin: ?} {Med: 0}]
*> 172.16.16.0/24       0.0.0.0                                   00:03:01   [{Origin: ?}]
root@vm3:~# 

So it's sort of like the translation from VPNv4 routes is only happening when you apply the RT configuration? Or am I doing something wrong here?

jonlangemak avatar Aug 20 '21 20:08 jonlangemak

I've confirmed that this is not an issue in the 7.5 code base. Possibly a regression in the 8.0 code train?

jonlangemak avatar Aug 24 '21 18:08 jonlangemak

Hi @jonlangemak , it looks like that imported route target is badly generated. that would explain why route from gobgp is not imported. there should be a command giving you ert/irt for the vrf

pguibert6WIND avatar Sep 15 '21 08:09 pguibert6WIND

@pguibert6WIND Thanks for the reply! Can you elaborate a little though? You believe that the RT coming from gobgp is malformed? Or that FRR is doing something to it on import that is malforming it?

jonlangemak avatar Sep 15 '21 14:09 jonlangemak

@pguibert6WIND Thanks for the reply! Can you elaborate a little though? You believe that the RT coming from gobgp is malformed? Or that FRR is doing something to it on import that is malforming it?

frr. Just to be sure, when you modify on the fly l3vpn bgp config , there may be bad rt generation. I would request you to do two things:

  • populate router-id at second bgp instance
  • write config, then restart frr (because loading config from startup is safer on your case)
  • do you observe same pb ?

pguibert6WIND avatar Sep 15 '21 14:09 pguibert6WIND

Hello folks,

I'm facing almost the same problem, when the frr starts all VPNv4 routes aren't installed as "inaccessible". Config is saved and the issue is reproducible every time. But when I enter the same RT in the runtime - everything is fine. For instance, I restarted frr and then:

ubuntuguest# show bgp vrf testvrf 5013:100::/64
BGP routing table entry for 5013:100::/64, version 0
Paths: (2 available, no best path)
  Not advertised to any peer
  Imported from 121:1:5013:100::/64
  65012 65013
    2003:100::2 (inaccessible) from :: (3.3.3.3) vrf default(0) announce-nh-self
      Origin incomplete, invalid, sourced, local
      Extended Community: RT:121:1
      Remote label: 51
      Last update: Mon Oct 18 12:28:32 2021
  Imported from 121:1:5013:100::/64
  65013
    5003:100::2 (inaccessible) from :: (3.3.3.3) vrf default(0) announce-nh-self
      Origin incomplete, invalid, sourced, local
      Extended Community: RT:121:1
      Remote label: 47
      Last update: Mon Oct 18 12:28:32 2021
ubuntuguest# conf t
ubuntuguest(config)# router bgp 65011 vrf testvrf
ubuntuguest(config-router)#  address-family ipv6 unicast
ubuntuguest(config-router-af)#   rt vpn both 121:1
ubuntuguest(config-router-af)#   end
ubuntuguest# show bgp vrf testvrf 5013:100::/64
BGP routing table entry for 5013:100::/64, version 0
Paths: (2 available, no best path)
  Not advertised to any peer
  Imported from 121:1:5013:100::/64
  65012 65013
    2003:100::2 from :: (3.3.3.3) vrf default(0) announce-nh-self
      Origin incomplete, valid, sourced, local
      Extended Community: RT:121:1
      Remote label: 51
      Last update: Mon Oct 18 12:28:37 2021
  Imported from 121:1:5013:100::/64
  65013
    5003:100::2 from :: (3.3.3.3) vrf default(0) announce-nh-self
      Origin incomplete, valid, sourced, local
      Extended Community: RT:121:1
      Remote label: 47
      Last update: Mon Oct 18 12:28:37 2021
ubuntuguest#

The configuration is pretty simple:

router bgp 65011 vrf testvrf
 bgp router-id 3.3.3.3
 !
 address-family ipv6 unicast
  redistribute kernel
  redistribute connected
  redistribute static
  label vpn export 38
  rd vpn export 121:1
  rt vpn both 121:1
  export vpn
  import vpn
exit-address-family

Any thoughts?

zstas avatar Oct 18 '21 13:10 zstas

I've noticed that here we have a couple of issue:

  • The main thing why I get nexthops unaccessible - there is a check when leaking routes from vpn to vrf: bgp_isvalid_labeled_nexthop. But in my case I have a regular nexthops without any labels:
# show bgp nexthop 
Current BGP nexthop cache:
 2003:100::2 valid [IGP metric 0], #paths 9, peer 2003:100::2
  if eth2
  Last update: Wed Oct 20 11:27:13 2021
...

My main question: where it should be updated to become labeled?

  • Another issue, is different logic inside vpn_leak_from_vrf_update (when I update vrf's RT for example). That's why I get all the routes with accessible nexthop in that case.

zstas avatar Oct 20 '21 11:10 zstas

@zstas Anything I can do to help move this along from a testing perspective?

jonlangemak avatar Nov 18 '21 20:11 jonlangemak

@jonlangemak

I hoped we will get some comments from FRR maintainers. There's almost no presence of life in frr-dev mailing list, so seems like it's the main place to ask question. I can prepare a patch, but I don't know what behaviour is expected. For my purposes, I prepared a simple patch with checking whether the nextop is BGP_NEXTHOP_LABELED_VALID or at least BGP_NEXTHOP_VALID.

diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 8f381e9ff..d6f665e95 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -67,7 +67,7 @@ static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
 static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc)
 {
        return (bgp_zebra_num_connects() == 0
-               || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
+               || (bnc && ((CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)) || (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)))
                    && bnc->nexthop_num > 0));
 }

zstas avatar Nov 21 '21 12:11 zstas

every place we call isvalid_labeled_nexthop we have already checked that the Path info has labels. So I am a bit confused how we shouldn't be checking for a valid labels.

donaldsharp avatar Nov 22 '21 19:11 donaldsharp

I understand that usually, we have labeled next-hop (igp+ldp or labeled unicast). But there's one case when we have only the regular next-hop - it's Inter-AS option B. In this case, we have an eBGP session with vpnv4/vpnv6, and the only label is the label of the VRF (or per-prefix in the VRF). So, it won't be a "labeled" next-hop in this case but rather a regular one. Please correct me if I'm wrong.

zstas avatar Nov 22 '21 21:11 zstas

if we have a prefix with pi->extra->num_labels set then the prefix should have that label. In this case we should not set the pi->extra->num_labels for the case you just described. That would be the better fix imo

donaldsharp avatar Nov 22 '21 22:11 donaldsharp

@zstas Forgot to mention if there's a patch fix available Im happy to test it locally to see if it resolves the issue. I'll be out on holiday here for a few days but when I get back I'd be happy to help with testing.

jonlangemak avatar Nov 23 '21 02:11 jonlangemak

@jonlangemak Hi guys, sorry, was busy with holidays.

Could you please test it out with the following patch? [1]

1 - https://github.com/FRRouting/frr/pull/10319

zstas avatar Jan 11 '22 15:01 zstas

@zstas I'd be happy to test this out. I was able to pull down your commit into a local branch on my test box but Im a little lost on how to do the FRR build. Which flags do I need to pass into configure etc? If you could provide an example of how to run the build I'll give it a test on my end.

Thanks!

jonlangemak avatar Jan 14 '22 20:01 jonlangemak

My main question: where it should be updated to become labeled?

You should have LDP daemon or BGP LU configured with your EBGP peer. if not, you will not have a label.

* Another issue, is different logic inside vpn_leak_from_vrf_update (when I update vrf's RT for example). That's why I get all the routes with accessible nexthop in that case.

that looks like as if some callback did not refresh automatically BGP. By answering the first question, we may understand better what is wrong.

I tend do think that BGP nexthop tracking does not refresh because zebra nexthop tracking does not refresh When you get the problem, please type : `show IP route <your IP nexthop>' to check for any label available.

pguibert6WIND avatar Jan 15 '22 13:01 pguibert6WIND

Just to comment - my use case is for FRR to act more as a VPNv4 to IPv4 route reflector. So I'd be doing something like asking FRR to advertise routes that it can't resolve through the MPLS table (or inet.3 in Juniper parlance). This is working in the config posted above - just wanted to reiterate the use case since we're talking about next hop resolution.

@zstas - Just to reiterate - Im happy to test if you can give me some info on doing the build. Thanks!

jonlangemak avatar Jan 22 '22 15:01 jonlangemak

@jonlangemak you can give it a try with compiling my branch [1] with this instruction [2]. But maintainers said a clear "no" to this patch. let's wait until they decide how to proceed with this issue. if you post your use-case in the PR [3] - it might be helpful also.

[1] - https://github.com/zstas/frr [2] - http://docs.frrouting.org/projects/dev-guide/en/latest/building-frr-for-ubuntu2004.html [3] - https://github.com/FRRouting/frr/pull/10319

zstas avatar Jan 24 '22 14:01 zstas

For what it is worth - I can confirm that 7.5.1 does not have the bug, and that those couple of changes in the small patch appear to work in git. Thank you to zstas for the work around and to everybody who commented on this thread and, of course, a huge thanks to those who work on this project.

helpdeskdan avatar Aug 05 '22 22:08 helpdeskdan

This issue is stale because it has been open 180 days with no activity. Comment or remove the autoclose label in order to avoid having this issue closed.

github-actions[bot] avatar Feb 02 '23 01:02 github-actions[bot]

This issue will be automatically closed in the specified period unless there is further activity.

frrbot[bot] avatar Feb 02 '23 01:02 frrbot[bot]