From 067fbab4e41d540b3f00f9a5c6c5e44e0728416c Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Mon, 25 Apr 2022 15:14:49 +0200 Subject: [PATCH] bgpd: fix interface on leaks from network statement Leaked routes from prefixes defined with 'network ' are inactive because they have no valid nexthop interface. > vrf r1-cust1 > ip route 172.16.29.0/24 192.168.1.2 > router bgp 5227 vrf r1-cust1 > no bgp network import-check > address-family ipv4 unicast > network 172.16.29.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 192.0.2/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>* 172.16.29.0/24 [1/0] via 192.168.1.2, r1-eth4, weight 1, 00:47:53 > > VRF r1-cust4: > B 172.16.29.0/24 [20/0] is directly connected, unknown (vrf r1-cust1) inactive, weight 1, 00:03:40 Routes imported through the "network" command, as opposed to those redistributed from the routing table, do not associate with any specific interface. When leaking prefix from other VRFs, if the route was imported from the network statement (ie. static sub-type), set nh_ifindex to the index of the VRF master interface of the incoming BGP instance. The result is: > VRF r1-cust4: > B>* 172.16.29.0/24 [20/0] is directly connected, r1-cust1 (vrf r1-cust1), weight 1, 00:00:08 Signed-off-by: Louis Scalbert --- bgpd/bgp_mplsvpn.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 32436861f4..0982a4dee1 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -2209,12 +2209,21 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ /* If the path has accept-own community and the source VRF * is valid, reset next-hop to self, to allow importing own * routes between different VRFs on the same node. - * Set the nh ifindex to VRF's interface, not the real interface. + */ + + if (src_bgp) + subgroup_announce_reset_nhop(nhfamily, &static_attr); + + bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn); + + /* The nh ifindex may not be defined (when the route is + * imported from the network statement => BGP_ROUTE_STATIC) + * or to the real interface. + * Rewrite the nh ifindex to VRF's interface. * Let the kernel to decide with double lookup the real next-hop * interface when installing the route. */ - if (src_bgp) { - subgroup_announce_reset_nhop(nhfamily, &static_attr); + if (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC) { ifp = if_get_vrf_loopback(src_vrf->vrf_id); if (ifp) static_attr.nh_ifindex = ifp->ifindex; @@ -2300,9 +2309,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ */ if (!CHECK_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT)) { - /* work back to original route */ - bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn); - /* * if original route was unicast, * then it did not arrive over vpn -- 2.39.5