From db7cf73a33e2a15286063f1609be7f1554ed736c Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Thu, 19 Jan 2023 17:46:14 +0100 Subject: [PATCH] bgpd: fix interface on leaks from redistribute connected In the target VRF's Routing Information Base (RIB), routes that are leaked and originate from the 'redistribute connected' command have their next-hop interface set as the interface from the source VRF. This prevents the IP address of the connected interface from being reachable from the target VRF. > router bgp 5227 vrf r1-cust1 > address-family ipv4 unicast > redistribute connected > 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 > address-family ipv4 unicast > network 192.0.2.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 > ! > vrf r1-cust1 > ip route 192.0.2.0/24 r1-cust4 nexthop-vrf r1-cust4 Extract from the routing table: > VRF r1-cust1: > C>* 172.16.29.0/24 is directly connected, r1-eth4, 00:44:15 > S>* 192.0.2.0/24 [1/0] is directly connected, r1-cust4 (vrf r1-cust4), weight 1, 00:00:30 > > VRF r1-cust4: > B>* 172.16.29.0/24 [20/0] is directly connected, r1-eth4 (vrf r1-cust1), weight 1, 00:00:02 In r1-cust4 VRF, the nexthop interface of 172.16.29.0/24 is r1-eth4, which is unknown in the context. The following ping does not work: > # tcpdump -lnni r1-cust1 'icmp' & > # ip vrf exec r1-cust4 ping -c1 -I 192.0.2.1 172.16.29.1 > PING 172.16.29.1 (172.16.29.1) 56(84) bytes of data. PING 172.16.29.1 (172.16.29.1) from 192.0.2.1 : 56(84) bytes of data. 18:49:20.635638 IP 192.0.2.1 > 172.16.29.1: ICMP echo request, id 15897, seq 1, length 64 18:49:27.113827 IP 192.0.2.1 > 192.0.2.1: ICMP host 172.16.29.1 unreachable, length 92 Fix the issue by setting nh_ifindex to the index of the VRF master interface of the incoming BGP instance. The result is: > VRF r1-cust4: > C>* 192.0.2.0/24 is directly connected, r1-cust5, 00:27:40 > B>* 172.16.29.0/24 [20/0] is directly connected, r1-cust1 (vrf r1-cust1), weight 1, 00:00:08 > # tcpdump -lnni r1-cust1 'icmp' & > # ping -c1 172.16.29.1 -I 192.0.2.1 > PING 172.16.29.1 (172.16.29.1) from 192.0.2.1 : 56(84) bytes of data. > 18:48:32.506281 IP 192.0.2.1 > 172.16.29.1: ICMP echo request, id 15870, seq 1, length 64 > 64 bytes from 172.16.29.1: icmp_seq=1 ttl=64 time=0.050 ms > 18:48:32.506304 IP 172.16.29.1 > 192.0.2.1: ICMP echo reply, id 15870, seq 1, length 64 Signed-off-by: Louis Scalbert --- bgpd/bgp_mplsvpn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 0982a4dee1..cd5cf5be54 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -2223,7 +2223,8 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ * Let the kernel to decide with double lookup the real next-hop * interface when installing the route. */ - if (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC) { + if (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC || + bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) { ifp = if_get_vrf_loopback(src_vrf->vrf_id); if (ifp) static_attr.nh_ifindex = ifp->ifindex;