diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index cebd576365..efbd078a52 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -42,6 +42,7 @@ #include "zebra/zebra_fpm_private.h" #include "zebra/zebra_vxlan_private.h" +#include "zebra/interface.h" /* * af_addr_size @@ -164,7 +165,10 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri, { struct netlink_nh_info nhi; union g_addr *src; - zebra_l3vni_t *zl3vni = NULL; + struct zebra_vrf *zvrf = NULL; + struct interface *ifp = NULL, *link_if = NULL; + struct zebra_if *zif = NULL; + vni_t vni = 0; memset(&nhi, 0, sizeof(nhi)); src = NULL; @@ -199,12 +203,29 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri, if (re && CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) { nhi.encap_info.encap_type = FPM_NH_ENCAP_VXLAN; - zl3vni = zl3vni_from_vrf(nexthop->vrf_id); - if (zl3vni && is_l3vni_oper_up(zl3vni)) { - - /* Add VNI to VxLAN encap info */ - nhi.encap_info.vxlan_encap.vni = zl3vni->vni; + /* Extract VNI id for the nexthop SVI interface */ + zvrf = zebra_vrf_lookup_by_id(nexthop->vrf_id); + if (zvrf) { + ifp = if_lookup_by_index_per_ns(zvrf->zns, + nexthop->ifindex); + if (ifp) { + zif = (struct zebra_if *)ifp->info; + if (zif) { + if (IS_ZEBRA_IF_BRIDGE(ifp)) + link_if = ifp; + else if (IS_ZEBRA_IF_VLAN(ifp)) + link_if = + if_lookup_by_index_per_ns( + zvrf->zns, + zif->link_ifindex); + if (link_if) + vni = vni_id_from_svi(ifp, + link_if); + } + } } + + nhi.encap_info.vxlan_encap.vni = vni; } /* diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 99df49a46b..2f3ea7475a 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1842,6 +1842,27 @@ static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp, return zl3vni; } +vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if) +{ + vni_t vni = 0; + zebra_evpn_t *zevpn = NULL; + zebra_l3vni_t *zl3vni = NULL; + + /* Check if an L3VNI belongs to this SVI interface. + * If not, check if an L2VNI belongs to this SVI interface. + */ + zl3vni = zl3vni_from_svi(ifp, br_if); + if (zl3vni) + vni = zl3vni->vni; + else { + zevpn = zebra_evpn_from_svi(ifp, br_if); + if (zevpn) + vni = zevpn->vni; + } + + return vni; +} + static inline void zl3vni_get_vrr_rmac(zebra_l3vni_t *zl3vni, struct ethaddr *rmac) { diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index 0556c4adce..84ac76b3b9 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -224,6 +224,7 @@ extern struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni); extern struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni); extern struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni); extern zebra_l3vni_t *zl3vni_lookup(vni_t vni); +extern vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if); DECLARE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni, bool delete, const char *reason), (rmac, zl3vni, delete, reason));