From 14aabc01565a918c223b7811572fae0316810422 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Mon, 25 Apr 2022 15:14:49 +0200 Subject: [PATCH] bgpd: fix invalid nexthop interface on leaked routes There is two cases where the nexthop interface is incorrect: - Case 1: leaked routes from prefixes stated in 'network ' are inactive because they have no nexthop IP address or interface. - Case 2: leaked routes from 'redistribute connected' contains the original nexthop interface. ====== Case 1 ====== > router bgp 5227 vrf r1-cust1 > bgp router-id 192.168.1.1 > no bgp network import-check > ! > address-family ipv4 unicast > network 10.2.3.4/32 > network 192.168.1.0/24 > rd vpn export 10:1 > rt vpn import 52:100 > rt vpn export 52:101 > export vpn > import vpn > exit-address-family > exit > ! > router bgp 5227 vrf r1-cust4 > bgp router-id 192.168.1.1 > ! > address-family ipv4 unicast > network 29.0.0.0/24 > rd vpn export 10:1 > rt vpn import 52:101 > rt vpn export 52:100 > export vpn > import vpn > exit-address-family > exit Extract from the routing table: > VRF r1-cust1: > S>* 192.0.0.0/24 [1/0] via 192.168.1.2, r1-eth4, weight 1, 00:47:53 > C>* 192.168.1.0/24 is directly connected, r1-eth4, 00:44:15 > B>* 29.0.0.0/24 [20/0] is directly connected, unknown (vrf r1-cust4), inactive, weight 1, 00:00:02 > > VRF r1-cust4: > B 10.2.3.4/32 [20/0] is directly connected, unknown (vrf r1-cust1) inactive, weight 1, 00:00:02 > C>* 29.0.0.0/24 is directly connected, r1-cust5, 00:27:40 > B 192.0.0.0/24 [20/0] is directly connected, unknown (vrf r1-cust1) inactive, weight 1, 00:03:40 > B 192.168.1.0/24 [20/0] is directly connected, unknown (vrf r1-cust1) inactive, weight 1, 00:00:02 ====== Case 2 ====== The previous is modified with the following settings: > router bgp 5227 vrf r1-cust1 > address-family ipv4 unicast > no network 192.168.1.0/24 > redistribute connected > ! > vrf r1-cust1 > ip route 29.0.0.0/24 r1-cust5 nexthop-vrf r1-cust5 Extract from the routing table: > VRF r1-cust1: > S>* 192.0.0.0/24 [1/0] via 192.168.1.2, r1-eth4, weight 1, 00:47:53 > C>* 192.168.1.0/24 is directly connected, r1-eth4, 00:44:15 > S>* 29.0.0.0/24 [1/0] is directly connected, r1-cust5 (vrf r1-cust5), weight 1, 00:00:30 > > VRF r1-cust4: > B 10.2.3.4/32 [20/0] is directly connected, unknown (vrf r1-cust1) inactive, weight 1, 00:00:02 > C>* 29.0.0.0/24 is directly connected, r1-cust5, 00:27:40 > B 192.0.0.0/24 [20/0] is directly connected, unknown (vrf r1-cust1) inactive, weight 1, 00:03:40 > B>* 192.168.1.0/24 [20/0] is directly connected, r1-eth4 (vrf r1-cust1), weight 1, 00:00:02 The nexthop interface is r1-eth4. It causes issue to traffic leaving r1-cust4. The following ping to r1-eth4 local address 192.168.1.1 from r1-cust5 local add does not respond. > # tcpdump -lnni r1-cust1 'icmp' & > # ip vrf exec r1-cust4 ping -c1 192.168.1.1 -I 29.0.0.1 > PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. PING 192.168.1.1 (192.168.1.1) from 29.0.0.1 : 56(84) bytes of data. 18:49:20.635638 IP 29.0.0.1 > 192.168.1.1: ICMP echo request, id 15897, seq 1, length 64 18:49:27.113827 IP 29.0.0.1 > 29.0.0.1: ICMP host 192.168.1.1 unreachable, length 92 Fix description: When leaking prefix from other VRFs, if the nexthop IP address is not set in the bgp path info attribures, reset nh_ifindex to the index of master interface of the incoming BGP instance. The result is for case 1 and 2: > VRF r1-cust1: > S>* 192.0.0.0/24 [1/0] via 192.168.1.2, r1-eth4, weight 1, 00:47:53 > C>* 192.168.1.0/24 is directly connected, r1-eth4, 00:44:15 > B>* 29.0.0.0/24 [20/0] is directly connected, r1-cust4 (vrf r1-cust4), weight 1, 00:00:08 > > VRF r1-cust4: > B>* 10.2.3.4/32 [20/0] is directly connected, r1-cust1 (vrf r1-cust1), weight 1, 00:00:08 > C>* 29.0.0.0/24 is directly connected, r1-cust5, 00:27:40 > B>* 192.0.0.0/24 [20/0] is directly connected, r1-cust1 (vrf r1-cust1), weight 1, 00:00:08 > B>* 192.168.1.0/24 [20/0] is directly connected, r1-cust1 (vrf r1-cust1), weight 1, 00:00:08 > # tcpdump -lnni r1-cust1 'icmp' & > # ping -c1 192.168.1.1 -I 29.0.0.1 > PING 192.168.1.1 (192.168.1.1) from 29.0.0.1 : 56(84) bytes of data. > 18:48:32.506281 IP 29.0.0.1 > 192.168.1.1: ICMP echo request, id 15870, seq 1, length 64 > 64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.050 ms > 18:48:32.506304 IP 192.168.1.1 > 29.0.0.1: ICMP echo reply, id 15870, seq 1, length 64 Signed-off-by: Louis Scalbert 1, 00:47:53 4:15 vrf r1-cust4), inactive, weight 1, 00:00:02 vrf r1-cust1) inactive, weight 1, 00:00:02 40 (vrf r1-cust1) inactive, weight 1, 00:03:40 n (vrf r1-cust1) inactive, weight 1, 00:00:02 dress is not the index of 1, 00:47:53 4:15 (vrf r1-cust4), weight 1, 00:00:08 (vrf r1-cust1), weight 1, 00:00:08 40 (vrf r1-cust1), weight 1, 00:00:08 t1 (vrf r1-cust1), weight 1, 00:00:08 --- bgpd/bgp_mplsvpn.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 42ae3562c2..bf6df88d2e 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1881,6 +1881,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ struct bgp_path_info *bpi; int origin_local = 0; struct bgp *src_vrf; + struct interface *ifp; int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); @@ -2015,6 +2016,13 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ break; } + if (static_attr.nexthop.s_addr == INADDR_ANY && + IN6_IS_ADDR_UNSPECIFIED(&static_attr.mp_nexthop_global)) { + ifp = if_get_vrf_loopback(src_vrf->vrf_id); + if (ifp) + static_attr.nh_ifindex = ifp->ifindex; + } + /* * route map handling */ -- 2.39.5