]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: program mac-ip routes in matching vrfs
authormitesh <mitesh@cumulusnetworks.com>
Wed, 11 Oct 2017 08:32:54 +0000 (01:32 -0700)
committerMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>
Thu, 14 Dec 2017 18:57:05 +0000 (10:57 -0800)
Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
bgpd/bgp_evpn.c
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_zebra.c
lib/zebra.h
zebra/zebra_rib.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h
zebra/zserv.c

index 326748bb47bfda716fb61c39f5d131e794ffd60b..4ddbbceb5137f2bef674f1367e9707b6bc885f92 100644 (file)
@@ -782,6 +782,95 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
        bgp_info_delete(rn, old_local);
 }
 
+/*
+ * Calculate the best path for an EVPN route. Install/update best path in zebra,
+ * if appropriate.
+ */
+static int evpn_vrf_route_select_install(struct bgp *bgp_vrf,
+                                        struct bgp_node *rn,
+                                        struct prefix *p,
+                                        afi_t afi,
+                                        safi_t safi)
+{
+       struct bgp_info *old_select, *new_select;
+       struct bgp_info_pair old_and_new;
+       int ret = 0;
+
+       /* Compute the best path. */
+       bgp_best_selection(bgp_vrf, rn, &bgp_vrf->maxpaths[afi][safi],
+                          &old_and_new, afi, safi);
+       old_select = old_and_new.old;
+       new_select = old_and_new.new;
+
+       /* If the best path hasn't changed - see if there is still something to
+        * update
+        * to zebra RIB.
+        */
+       if (old_select && old_select == new_select
+           && old_select->type == ZEBRA_ROUTE_BGP
+           && old_select->sub_type == BGP_ROUTE_NORMAL
+           && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
+           && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
+           && !bgp_vrf->addpath_tx_used[afi][safi]) {
+               if (bgp_zebra_has_route_changed(rn, old_select))
+                       bgp_zebra_announce(rn, p, old_select, bgp_vrf,
+                                          afi, safi);
+               UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
+               bgp_zebra_clear_route_change_flags(rn);
+               return ret;
+       }
+
+       /* If the user did a "clear" this flag will be set */
+       UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
+
+       /* bestpath has changed; update relevant fields and install or uninstall
+        * into the zebra RIB.
+        */
+       if (old_select || new_select)
+               bgp_bump_version(rn);
+
+       if (old_select)
+               bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED);
+       if (new_select) {
+               bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED);
+               bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED);
+               UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG);
+       }
+
+       if (new_select && new_select->type == ZEBRA_ROUTE_BGP
+           && new_select->sub_type == BGP_ROUTE_NORMAL) {
+               bgp_zebra_announce(rn, p, new_select, bgp_vrf,
+                                  afi, safi);
+
+               /* If an old best existed and it was a "local" route, the only
+                * reason
+                * it would be supplanted is due to MAC mobility procedures. So,
+                * we
+                * need to do an implicit delete and withdraw that route from
+                * peers.
+                */
+               /*if (old_select && old_select->peer == bgp_vrf->peer_self
+                   && old_select->type == ZEBRA_ROUTE_BGP
+                   && old_select->sub_type == BGP_ROUTE_STATIC) {
+                       //evpn_delete_old_local_route(bgp, vpn, rn, old_select);
+               }*/ //TODO_MITESH: probably not needed for vrf routes, think!!
+       } else {
+               if (old_select && old_select->type == ZEBRA_ROUTE_BGP
+                   && old_select->sub_type == BGP_ROUTE_NORMAL) {
+                       bgp_zebra_withdraw(p, old_select, safi);
+               }
+       }
+
+       /* Clear any route change flags. */
+       bgp_zebra_clear_route_change_flags(rn);
+
+       /* Reap old select bgp_info, if it has been removed */
+       if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED))
+               bgp_info_reap(rn, old_select);
+
+       return ret;
+}
+
 /*
  * Calculate the best path for an EVPN route. Install/update best path in zebra,
  * if appropriate.
@@ -1418,6 +1507,88 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
        return update_routes_for_vni(bgp, vpn);
 }
 
+/*
+ * Install route entry into the VRF routing table and invoke route selection.
+ */
+static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
+                                          struct prefix_evpn *evp,
+                                          struct bgp_info *parent_ri)
+{
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       struct attr *attr_new;
+       int ret;
+       struct prefix p;
+       struct prefix *pp = &p;
+       afi_t afi = 0;
+       safi_t safi = 0;
+
+       memset(pp, 0, sizeof(struct prefix));
+       ip_prefix_from_type2_prefix(evp, pp);
+
+       /* Create (or fetch) route within the VRF. */
+       /* NOTE: There is no RD here. */
+       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+               afi = AFI_IP;
+               safi = SAFI_UNICAST;
+               rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
+       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+               afi = AFI_IP6;
+               safi = SAFI_UNICAST;
+               rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
+       } else
+               return 0;
+
+       /* Check if route entry is already present. */
+       for (ri = rn->info; ri; ri = ri->next)
+               if (ri->extra
+                   && (struct bgp_info *)ri->extra->parent == parent_ri)
+                       break;
+
+       if (!ri) {
+               /* Add (or update) attribute to hash. */
+               attr_new = bgp_attr_intern(parent_ri->attr);
+
+               /* Create new route with its attribute. */
+               ri = info_make(parent_ri->type, parent_ri->sub_type, 0,
+                              parent_ri->peer, attr_new, rn);
+               SET_FLAG(ri->flags, BGP_INFO_VALID);
+               bgp_info_extra_get(ri);
+               ri->extra->parent = parent_ri;
+               if (parent_ri->extra)
+                       memcpy(&ri->extra->label, &parent_ri->extra->label,
+                              BGP_LABEL_BYTES);
+               bgp_info_add(rn, ri);
+       } else {
+               if (attrhash_cmp(ri->attr, parent_ri->attr)
+                   && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
+                       bgp_unlock_node(rn);
+                       return 0;
+               }
+               /* The attribute has changed. */
+               /* Add (or update) attribute to hash. */
+               attr_new = bgp_attr_intern(parent_ri->attr);
+
+               /* Restore route, if needed. */
+               if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+                       bgp_info_restore(rn, ri);
+
+               /* Mark if nexthop has changed. */
+               if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop))
+                       SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED);
+
+               /* Unintern existing, set to new. */
+               bgp_attr_unintern(&ri->attr);
+               ri->attr = attr_new;
+               ri->uptime = bgp_clock();
+       }
+
+       /* Perform route selection and update zebra, if required. */
+       ret = evpn_vrf_route_select_install(bgp_vrf, rn, pp, afi, safi);
+
+       return ret;
+}
+
 /*
  * Install route entry into the VNI routing table and invoke route selection.
  */
@@ -1484,6 +1655,61 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
        return ret;
 }
 
+/*
+ * Uninstall route entry from the VRF routing table and send message
+ * to zebra, if appropriate.
+ */
+static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
+                                            struct prefix_evpn *evp,
+                                            struct bgp_info *parent_ri)
+{
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       int ret;
+       struct prefix p;
+       struct prefix *pp = &p;
+       afi_t afi = 0;
+       safi_t safi = 0;
+
+       memset(pp, 0, sizeof(struct prefix));
+       ip_prefix_from_type2_prefix(evp, pp);
+
+       /* Locate route within the VRF. */
+       /* NOTE: There is no RD here. */
+       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+               afi = AFI_IP;
+               safi = SAFI_UNICAST;
+               rn = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
+       } else {
+               afi = AFI_IP6;
+               safi = SAFI_UNICAST;
+               rn = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
+       }
+
+       if (!rn)
+               return 0;
+
+       /* Find matching route entry. */
+       for (ri = rn->info; ri; ri = ri->next)
+               if (ri->extra
+                   && (struct bgp_info *)ri->extra->parent == parent_ri)
+                       break;
+
+       if (!ri)
+               return 0;
+
+       /* Mark entry for deletion */
+       bgp_info_delete(rn, ri);
+
+       /* Perform route selection and update zebra, if required. */
+       ret = evpn_vrf_route_select_install(bgp_vrf, rn, pp, afi, safi);
+
+       /* Unlock route node. */
+       bgp_unlock_node(rn);
+
+       return ret;
+}
+
 /*
  * Uninstall route entry from the VNI routing table and send message
  * to zebra, if appropriate.
@@ -1706,6 +1932,45 @@ static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
                                                0);
 }
 
+/*
+ * Install or uninstall route in matching VRFs (list).
+ */
+static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi,
+                                          safi_t safi, struct prefix_evpn *evp,
+                                          struct bgp_info *ri,
+                                          struct list *vrfs, int install)
+{
+       char buf[PREFIX2STR_BUFFER];
+       struct bgp *bgp_vrf;
+       struct listnode *node, *nnode;
+
+       /* Only type-2 routes go into a VRF */
+       if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE))
+               return 0;
+
+       for (ALL_LIST_ELEMENTS(vrfs, node, nnode, bgp_vrf)) {
+               int ret;
+
+               if (install)
+                       ret = install_evpn_route_entry_in_vrf(bgp_vrf,
+                                                             evp, ri);
+               else
+                       ret = uninstall_evpn_route_entry_in_vrf(bgp_vrf,
+                                                               evp, ri);
+
+               if (ret) {
+                       zlog_err("%u: Failed to %s prefix %s in VRF %s",
+                                bgp_def->vrf_id,
+                                install ? "install" : "uninstall",
+                                prefix2str(evp, buf, sizeof(buf)),
+                                vrf_id_to_name(bgp_vrf->vrf_id));
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Install or uninstall route in matching VNIs (list).
  */
@@ -1777,7 +2042,8 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
                u_char type, sub_type;
                struct ecommunity_val *eval;
                struct ecommunity_val eval_tmp;
-               struct irt_node *irt;
+               struct irt_node *irt; /* import rt for l2vni */
+               struct vrf_irt_node *vrf_irt; /* import rt for l3vni */
 
                /* Only deal with RTs */
                pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
@@ -1788,12 +2054,18 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
                if (sub_type != ECOMMUNITY_ROUTE_TARGET)
                        continue;
 
-               /* Are we interested in this RT? */
+               /* Import route into matching l2-vnis */
                irt = lookup_import_rt(bgp, eval);
                if (irt && irt->vnis)
                        install_uninstall_route_in_vnis(bgp, afi, safi, evp, ri,
                                                        irt->vnis, import);
 
+               /* Import route into matching l3-vnis (vrfs) */
+               vrf_irt = lookup_vrf_import_rt(eval);
+               if (vrf_irt && vrf_irt->vrfs)
+                       install_uninstall_route_in_vrfs(bgp, afi, safi, evp, ri,
+                                                       vrf_irt->vrfs, import);
+
                /* Also check for non-exact match. In this, we mask out the AS
                 * and
                 * only check on the local-admin sub-field. This is to
@@ -1801,16 +2073,22 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
                 * VNI as the RT for EBGP peering too.
                 */
                irt = NULL;
+               vrf_irt = NULL;
                if (type == ECOMMUNITY_ENCODE_AS
                    || type == ECOMMUNITY_ENCODE_AS4
                    || type == ECOMMUNITY_ENCODE_IP) {
                        memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE);
                        mask_ecom_global_admin(&eval_tmp, eval);
                        irt = lookup_import_rt(bgp, &eval_tmp);
+                       vrf_irt = lookup_vrf_import_rt(&eval_tmp);
                }
                if (irt && irt->vnis)
                        install_uninstall_route_in_vnis(bgp, afi, safi, evp, ri,
                                                        irt->vnis, import);
+               if (vrf_irt && vrf_irt->vrfs)
+                       install_uninstall_route_in_vrfs(bgp, afi, safi, evp,
+                                                       ri, vrf_irt->vrfs,
+                                                       import);
        }
 
        return 0;
index f8594394ef28239095723e3b3e50807d21b295c7..1b7e4d719ec4a0efa0c34df3f072d9d926e72243 100644 (file)
@@ -258,6 +258,25 @@ static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq,
        eval->val[7] = seq & 0xff;
 }
 
+static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
+                                              struct prefix *ip)
+{
+       memset(ip, 0, sizeof(struct prefix));
+       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+               ip->family = AF_INET;
+               ip->prefixlen = IPV4_MAX_BITLEN;
+               memcpy(&(ip->u.prefix4),
+                      &(evp->prefix.ip.ip),
+                      IPV4_MAX_BYTELEN);
+       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+               ip->family = AF_INET6;
+               ip->prefixlen = IPV6_MAX_BITLEN;
+               memcpy(&(ip->u.prefix6),
+                      &(evp->prefix.ip.ip),
+                      IPV6_MAX_BYTELEN);
+       }
+}
+
 static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
                                           struct ethaddr *mac,
                                           struct ipaddr *ip)
index 86b50db581214b65e3f3e4dbe7263050a60a32d0..c3f77aba27cbe69c78a40da4d87ccab7e0087832 100644 (file)
@@ -411,6 +411,52 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
                json_object_object_add(json, "exportRts", json_export_rtl);
 }
 
+static void evpn_show_vrf_routes(struct vty *vty,
+                                struct bgp *bgp_vrf)
+{
+       struct bgp *bgp_def = NULL;
+       struct bgp_node *rn;
+       struct bgp_info *ri;
+       int header = 1;
+       u_int32_t prefix_cnt, path_cnt;
+
+       prefix_cnt = path_cnt = 0;
+       bgp_def = bgp_get_default();
+       if (!bgp_def)
+               return;
+
+       for (rn = bgp_table_top(bgp_vrf->rib[AFI_L2VPN][SAFI_EVPN]); rn;
+            rn = bgp_route_next(rn)) {
+               char prefix_str[BUFSIZ];
+
+               bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
+                                  sizeof(prefix_str));
+
+               if (rn->info) {
+                       /* Overall header/legend displayed once. */
+                       if (header) {
+                               bgp_evpn_show_route_header(vty, bgp_def, NULL);
+                               header = 0;
+                       }
+                       prefix_cnt++;
+               }
+
+               /* For EVPN, the prefix is displayed for each path (to fit in
+                * with code that already exists).
+                */
+               for (ri = rn->info; ri; ri = ri->next) {
+                       route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, NULL);
+                       path_cnt++;
+               }
+       }
+
+       if (prefix_cnt == 0)
+               vty_out(vty, "No EVPN prefixes exist for this VRF");
+       else
+               vty_out(vty, "\nDisplayed %u prefixes (%u paths)",
+                       prefix_cnt, path_cnt);
+}
+
 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
                            struct vty *vty, struct in_addr vtep_ip,
                            json_object *json)
@@ -2640,6 +2686,33 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
        return CMD_SUCCESS;
 }
 
+/*
+ * Display per-VRF EVPN routing table.
+ */
+DEFUN(show_bgp_l2vpn_evpn_route_vrf, show_bgp_l2vpn_evpn_route_vrf_cmd,
+      "show bgp l2vpn evpn route vrf VRFNAME",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VRF\n"
+      "VRF Name\n")
+{
+       int vrf_idx = 6;
+       char *vrf_name = NULL;
+       struct bgp *bgp_vrf = NULL;
+
+       vrf_name = argv[vrf_idx]->arg;
+       bgp_vrf = bgp_lookup_by_name(vrf_name);
+       if (!bgp_vrf)
+               return CMD_WARNING;
+
+       evpn_show_vrf_routes(vty, bgp_vrf);
+
+       return CMD_SUCCESS;
+}
+
 /*
  * Display per-VNI EVPN routing table.
  */
@@ -3697,6 +3770,7 @@ void bgp_ethernetvpn_init(void)
        install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
        install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
        install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
+       install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vrf_cmd);
        install_element(VIEW_NODE,
                        &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
        install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
index a660139a242f34d17871a7d5fd8d2282e51f71a1..78defa85dc4643bce117e1cdcdfa75f34b6d0311 100644 (file)
@@ -1015,6 +1015,12 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
        if (info->sub_type == BGP_ROUTE_AGGREGATE)
                zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
 
+       /* If it is an EVPN route mark as such.
+        * Currently presence of rmac in attr denotes
+        * this is an EVPN type-2 route */
+       if (!is_zero_mac(&(info->attr->rmac)))
+               SET_FLAG(api.flags, ZEBRA_FLAG_EVPN_TYPE2_ROUTE);
+
        if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
            || info->sub_type == BGP_ROUTE_AGGREGATE) {
                SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
@@ -1072,7 +1078,13 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
 
                        api_nh = &api.nexthops[valid_nh_count];
                        api_nh->gate.ipv4 = *nexthop;
-                       api_nh->type = NEXTHOP_TYPE_IPV4;
+
+                       /* EVPN type-2 routes are
+                          programmed as onlink on l3-vni SVI */
+                       if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_TYPE2_ROUTE))
+                               api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+                       else
+                               api_nh->type = NEXTHOP_TYPE_IPV4;
                } else {
                        ifindex_t ifindex;
                        struct in6_addr *nexthop;
index fa5fa89f776116c2b1aff76c9241017a63222a5e..73b5f7058ef8911464d0b0d6369bbbad66b71363 100644 (file)
@@ -409,6 +409,7 @@ extern const char *zserv_command_string(unsigned int command);
 #define ZEBRA_FLAG_STATIC             0x40
 #define ZEBRA_FLAG_SCOPE_LINK         0x100
 #define ZEBRA_FLAG_FIB_OVERRIDE       0x200
+#define ZEBRA_FLAG_EVPN_TYPE2_ROUTE   0x400
 /* ZEBRA_FLAG_BLACKHOLE was 0x04 */
 /* ZEBRA_FLAG_REJECT was 0x80 */
 
index 58b69659955cf2328e05592c225963376685af0d..82f087cebf0b3e76f09d34d11b9d8891a204a98d 100644 (file)
@@ -259,7 +259,8 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
        /*Pending: need to think if null ifp here is ok during bootup?
          There was a crash because ifp here was coming to be NULL */
        if (ifp)
-               if (connected_is_unnumbered(ifp)) {
+               if (connected_is_unnumbered(ifp) ||
+                   CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_TYPE2_ROUTE)) {
                        SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
                }
 
index 962e66068dd4b9dd313daabde8f57ec270c020be..03e9fd318572c22ab9fb98ad1627ae09aa2165ed 100644 (file)
@@ -6084,3 +6084,15 @@ void zebra_vxlan_ns_disable(struct zebra_ns *zns)
 {
        hash_free(zns->l3vni_table);
 }
+
+/* get the l3vni svi ifindex */
+ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
+{
+       zebra_l3vni_t *zl3vni = NULL;
+
+       zl3vni = zl3vni_from_vrf(vrf_id);
+       if (!zl3vni || !is_l3vni_oper_up(zl3vni))
+               return 0;
+
+       return zl3vni->svi_if->ifindex;
+}
index 33e962c4849d6b500417511c34e8cd2eff73bfcd..9e1ca746a562cdf519ea8f77f43b779375f0b35c 100644 (file)
@@ -51,6 +51,7 @@ is_evpn_enabled()
 
 #define VNI_STR_LEN 32
 
+extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
 extern int zebra_vxlan_vrf_delete(struct zebra_vrf *);
 extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
                                       vni_t vni, u_char use_json);
index 4352b78e83ae484caa6bb9b9b91f02766affb1fc..d82ccb93d77c705b51461471b81103faa675e5c1 100644 (file)
@@ -1149,6 +1149,7 @@ static int zread_route_add(struct zserv *client, u_short length,
        if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
                for (i = 0; i < api.nexthop_num; i++) {
                        api_nh = &api.nexthops[i];
+                       ifindex_t ifindex = 0;
 
                        switch (api_nh->type) {
                        case NEXTHOP_TYPE_IFINDEX:
@@ -1160,9 +1161,16 @@ static int zread_route_add(struct zserv *client, u_short length,
                                        re, &api_nh->gate.ipv4, NULL);
                                break;
                        case NEXTHOP_TYPE_IPV4_IFINDEX:
+                               if (CHECK_FLAG(api.flags,
+                                              ZEBRA_FLAG_EVPN_TYPE2_ROUTE)) {
+                                       ifindex =
+                                               get_l3vni_svi_ifindex(zvrf_id(zvrf));
+                               } else {
+                                       ifindex = api_nh->ifindex;
+                               }
                                nexthop = route_entry_nexthop_ipv4_ifindex_add(
                                        re, &api_nh->gate.ipv4, NULL,
-                                       api_nh->ifindex);
+                                       ifindex);
                                break;
                        case NEXTHOP_TYPE_IPV6:
                                nexthop = route_entry_nexthop_ipv6_add(