]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd : backpressure - Handle BGP-Zebra(EPVN) Install evt Creation 15624/head
authorRajasekar Raja <rajasekarr@nvidia.com>
Thu, 15 Feb 2024 19:23:51 +0000 (11:23 -0800)
committerRajasekar Raja <rajasekarr@nvidia.com>
Mon, 8 Apr 2024 17:51:43 +0000 (10:51 -0700)
Current changes deals with EVPN routes installation to zebra.

In evpn_route_select_install() we invoke evpn_zebra_install/uninstall
which sends zclient_send_message().

This is a continuation of code changes (similar to
ccfe452763d16c432fa81fd20e805bec819b345e) but to handle evpn part
of the code.

Ticket: #3390099

Signed-off-by: Rajasekar Raja <rajasekarr@nvidia.com>
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_mh.c
bgpd/bgp_evpn_mh.h
bgpd/bgp_route.c
bgpd/bgp_table.h
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.h

index a846484f0e41efd5da49ab5a8546e54ada26bad6..e142ff6a347f9ab7b04c413a5b79a03d1fa42dc9 100644 (file)
@@ -892,11 +892,10 @@ struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn,
 /*
  * Add (update) or delete MACIP from zebra.
  */
-static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
-                                      const struct prefix_evpn *p,
-                                      const struct ethaddr *mac,
-                                      struct in_addr remote_vtep_ip, int add,
-                                      uint8_t flags, uint32_t seq, esi_t *esi)
+static enum zclient_send_status bgp_zebra_send_remote_macip(
+       struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p,
+       const struct ethaddr *mac, struct in_addr remote_vtep_ip, int add,
+       uint8_t flags, uint32_t seq, esi_t *esi)
 {
        struct stream *s;
        uint16_t ipa_len;
@@ -904,8 +903,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
        bool esi_valid;
 
        /* Check socket. */
-       if (!zclient || zclient->sock < 0)
-               return 0;
+       if (!zclient || zclient->sock < 0) {
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: No zclient or zclient->sock exists",
+                                  __func__);
+               return ZCLIENT_SEND_SUCCESS;
+       }
 
        /* Don't try to register if Zebra doesn't know of this instance. */
        if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
@@ -913,7 +916,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
                        zlog_debug(
                                "%s: No zebra instance to talk to, not installing remote macip",
                                __func__);
-               return 0;
+               return ZCLIENT_SEND_SUCCESS;
        }
 
        if (!esi)
@@ -979,24 +982,26 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
        frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip,
                 esi);
 
-        if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
-          return -1;
-
-        return 0;
+       return zclient_send_message(zclient);
 }
 
 /*
  * Add (update) or delete remote VTEP from zebra.
  */
-static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
-                                     const struct prefix_evpn *p,
-                                     int flood_control, int add)
+static enum zclient_send_status
+bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
+                          const struct prefix_evpn *p, int flood_control,
+                          int add)
 {
        struct stream *s;
 
        /* Check socket. */
-       if (!zclient || zclient->sock < 0)
-               return 0;
+       if (!zclient || zclient->sock < 0) {
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: No zclient or zclient->sock exists",
+                                  __func__);
+               return ZCLIENT_SEND_SUCCESS;
+       }
 
        /* Don't try to register if Zebra doesn't know of this instance. */
        if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
@@ -1004,7 +1009,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
                        zlog_debug(
                                "%s: No zebra instance to talk to, not installing remote vtep",
                                __func__);
-               return 0;
+               return ZCLIENT_SEND_SUCCESS;
        }
 
        s = zclient->obuf;
@@ -1021,7 +1026,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
                        EC_BGP_VTEP_INVALID,
                        "Bad remote IP when trying to %s remote VTEP for VNI %u",
                        add ? "ADD" : "DEL", (vpn ? vpn->vni : 0));
-               return -1;
+               return ZCLIENT_SEND_FAILURE;
        }
        stream_putl(s, flood_control);
 
@@ -1034,10 +1039,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
 
        frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p);
 
-        if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
-          return -1;
-
-        return 0;
+       return zclient_send_message(zclient);
 }
 
 /*
@@ -1263,14 +1265,14 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr)
 }
 
 /* Install EVPN route into zebra. */
-static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
-                             const struct prefix_evpn *p,
-                             struct bgp_path_info *pi)
+enum zclient_send_status evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
+                                           const struct prefix_evpn *p,
+                                           struct bgp_path_info *pi)
 {
-       int ret;
        uint8_t flags;
        int flood_control = VXLAN_FLOOD_DISABLED;
        uint32_t seq;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
                flags = 0;
@@ -1348,6 +1350,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
                        flood_control = VXLAN_FLOOD_DISABLED;
                        break;
                }
+
                ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, flood_control, 1);
        }
 
@@ -1355,11 +1358,13 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
 }
 
 /* Uninstall EVPN route from zebra. */
-static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
-                               const struct prefix_evpn *p,
-                               struct bgp_path_info *pi, bool is_sync)
+enum zclient_send_status evpn_zebra_uninstall(struct bgp *bgp,
+                                             struct bgpevpn *vpn,
+                                             const struct prefix_evpn *p,
+                                             struct bgp_path_info *pi,
+                                             bool is_sync)
 {
-       int ret;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
                ret = bgp_zebra_send_remote_macip(
@@ -1374,7 +1379,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
                ret = bgp_evpn_remote_es_evi_del(bgp, vpn, p);
        else
                ret = bgp_zebra_send_remote_vtep(bgp, vpn, p,
-                                       VXLAN_FLOOD_DISABLED, 0);
+                                                VXLAN_FLOOD_DISABLED, 0);
 
        return ret;
 }
@@ -1465,12 +1470,18 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
            && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
            && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
            && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
-               if (bgp_zebra_has_route_changed(old_select))
-                       ret = evpn_zebra_install(
-                               bgp, vpn,
-                               (const struct prefix_evpn *)bgp_dest_get_prefix(
-                                       dest),
-                               old_select);
+               if (bgp_zebra_has_route_changed(old_select)) {
+                       if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+                               evpn_zebra_install(bgp, vpn,
+                                                  (const struct prefix_evpn *)
+                                                          bgp_dest_get_prefix(
+                                                                  dest),
+                                                  old_select);
+                       else
+                               bgp_zebra_route_install(dest, old_select, bgp,
+                                                       true, vpn, false);
+               }
+
                UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
                UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
                bgp_zebra_clear_route_change_flags(dest);
@@ -1502,10 +1513,14 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
        if (new_select && new_select->type == ZEBRA_ROUTE_BGP
            && (new_select->sub_type == BGP_ROUTE_IMPORTED ||
                        bgp_evpn_attr_is_sync(new_select->attr))) {
-               ret = evpn_zebra_install(
-                       bgp, vpn,
-                       (struct prefix_evpn *)bgp_dest_get_prefix(dest),
-                       new_select);
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+                       evpn_zebra_install(bgp, vpn,
+                                          (const struct prefix_evpn *)
+                                                  bgp_dest_get_prefix(dest),
+                                          new_select);
+               else
+                       bgp_zebra_route_install(dest, new_select, bgp, true,
+                                               vpn, false);
 
                /* If an old best existed and it was a "local" route, the only
                 * reason
@@ -1522,13 +1537,19 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
                        evpn_delete_old_local_route(bgp, vpn, dest,
                                        old_select, new_select);
        } else {
-               if (old_select && old_select->type == ZEBRA_ROUTE_BGP
-                   && old_select->sub_type == BGP_ROUTE_IMPORTED)
-                       ret = evpn_zebra_uninstall(
-                               bgp, vpn,
-                               (const struct prefix_evpn *)bgp_dest_get_prefix(
-                                       dest),
-                               old_select, false);
+               if (old_select && old_select->type == ZEBRA_ROUTE_BGP &&
+                   old_select->sub_type == BGP_ROUTE_IMPORTED) {
+                       if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
+                           CHECK_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN))
+                               evpn_zebra_uninstall(bgp, vpn,
+                                                    (const struct prefix_evpn *)
+                                                            bgp_dest_get_prefix(
+                                                                    dest),
+                                                    old_select, false);
+                       else
+                               bgp_zebra_route_install(dest, old_select, bgp,
+                                                       false, vpn, false);
+               }
        }
 
        /* Clear any route change flags. */
@@ -2062,9 +2083,19 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
        if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP
                        && (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
                                bgp_evpn_attr_is_sync(curr_select->attr)))
-               evpn_zebra_install(bgp, vpn,
-                  (const struct prefix_evpn *)bgp_dest_get_prefix(dest),
-                  curr_select);
+               if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP &&
+                   (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
+                    bgp_evpn_attr_is_sync(curr_select->attr))) {
+                       if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+                               evpn_zebra_install(bgp, vpn,
+                                                  (const struct prefix_evpn *)
+                                                          bgp_dest_get_prefix(
+                                                                  dest),
+                                                  curr_select);
+                       else
+                               bgp_zebra_route_install(dest, curr_select, bgp,
+                                                       true, vpn, false);
+               }
 }
 
 /*
@@ -2245,8 +2276,16 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
                         * has been removed.
                         */
                        new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
-                       if (!new_is_sync && old_is_sync)
-                               evpn_zebra_uninstall(bgp, vpn, p, pi, true);
+                       if (!new_is_sync && old_is_sync) {
+                               if (CHECK_FLAG(bgp->flags,
+                                              BGP_FLAG_DELETE_IN_PROGRESS))
+                                       evpn_zebra_uninstall(bgp, vpn, p, pi,
+                                                            true);
+                               else
+                                       bgp_zebra_route_install(dest, pi, bgp,
+                                                               false, vpn,
+                                                               true);
+                       }
                }
        }
        bgp_path_info_unlock(pi);
@@ -2512,8 +2551,17 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
                         * has been removed.
                         */
                        new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
-                       if (!new_is_sync && old_is_sync)
-                               evpn_zebra_uninstall(bgp, vpn, &evp, pi, true);
+                       if (!new_is_sync && old_is_sync) {
+                               if (CHECK_FLAG(bgp->flags,
+                                              BGP_FLAG_DELETE_IN_PROGRESS))
+                                       (void)evpn_zebra_uninstall(bgp, vpn,
+                                                                  &evp, pi,
+                                                                  true);
+                               else
+                                       bgp_zebra_route_install(dest, pi, bgp,
+                                                               false, vpn,
+                                                               true);
+                       }
                }
        }
 
@@ -2795,7 +2843,22 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
        delete_all_type2_routes(bgp, vpn);
 
        build_evpn_type3_prefix(&p, vpn->originator_ip);
+
+       /*
+        * To handle the following scenario:
+        *  - Say, the new zebra announce fifo list has few vni Evpn prefixes yet
+        *    to be sent to zebra.
+        *  - At this point if we have triggers like "no advertise-all-vni" or
+        *    "networking restart", where a vni is going down.
+        *
+        * Perform the below
+        *    1) send withdraw routes to zebra immediately in case it is installed.
+        *    2) before we blow up the vni table, we need to walk the list and
+        *       pop all the dest whose za_vpn points to this vni.
+        */
+       SET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
        ret = delete_evpn_route(bgp, vpn, &p);
+       UNSET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
        if (ret)
                return ret;
 
@@ -6262,6 +6325,17 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
  */
 void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
 {
+       struct bgp_dest *dest = NULL;
+
+       while (zebra_announce_count(&bm->zebra_announce_head)) {
+               dest = zebra_announce_pop(&bm->zebra_announce_head);
+               if (dest->za_vpn == vpn) {
+                       bgp_path_info_unlock(dest->za_bgp_pi);
+                       bgp_dest_unlock_node(dest);
+               } else
+                       zebra_announce_add_tail(&bm->zebra_announce_head, dest);
+       }
+
        bgp_evpn_remote_ip_hash_destroy(vpn);
        bgp_evpn_vni_es_cleanup(vpn);
        bgpevpn_unlink_from_l3vni(vpn);
index c641a64f627a98dbf13a82be7167dc6cc7b8fc4d..11a6f45dd0901f2eeff00cca2005ef3371db1996 100644 (file)
@@ -186,4 +186,12 @@ extern bool is_route_injectable_into_evpn_non_supp(struct bgp_path_info *pi);
 extern void bgp_aggr_supp_withdraw_from_evpn(struct bgp *bgp, afi_t afi,
                                             safi_t safi);
 
+extern enum zclient_send_status evpn_zebra_install(struct bgp *bgp,
+                                                  struct bgpevpn *vpn,
+                                                  const struct prefix_evpn *p,
+                                                  struct bgp_path_info *pi);
+extern enum zclient_send_status
+evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
+                    const struct prefix_evpn *p, struct bgp_path_info *pi,
+                    bool is_sync);
 #endif /* _QUAGGA_BGP_EVPN_H */
index d88c52d1f6d954dbc6c171aa76d1e8798f376336..601b8e91ba16d5f996534a6bde13afe2bb6b462b 100644 (file)
@@ -45,13 +45,14 @@ static void bgp_evpn_local_es_down(struct bgp *bgp,
                struct bgp_evpn_es *es);
 static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp,
                struct bgp_evpn_es *es);
-static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
+static struct bgp_evpn_es_vtep *
+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es,
+                    struct in_addr vtep_ip, bool esr, uint8_t df_alg,
+                    uint16_t df_pref, int *zret);
+static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp,
                                                     struct bgp_evpn_es *es,
                                                     struct in_addr vtep_ip,
-                                                    bool esr, uint8_t df_alg,
-                                                    uint16_t df_pref);
-static void bgp_evpn_es_vtep_del(struct bgp *bgp,
-               struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr);
+                                                    bool esr);
 static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es);
 static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es);
 static struct bgp_evpn_es_evi *
@@ -94,6 +95,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
                                            struct bgp_dest *dest)
 {
        int ret = 0;
+       int zret = 0;
        afi_t afi = AFI_L2VPN;
        safi_t safi = SAFI_EVPN;
        struct bgp_path_info *old_select; /* old best */
@@ -120,7 +122,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
                        bgp_evpn_es_vtep_add(bgp, es, old_select->attr->nexthop,
                                             true /*esr*/,
                                             old_select->attr->df_alg,
-                                            old_select->attr->df_pref);
+                                            old_select->attr->df_pref, &zret);
                }
                UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
                bgp_zebra_clear_route_change_flags(dest);
@@ -149,7 +151,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
                        && new_select->sub_type == BGP_ROUTE_IMPORTED) {
                bgp_evpn_es_vtep_add(bgp, es, new_select->attr->nexthop,
                                     true /*esr */, new_select->attr->df_alg,
-                                    new_select->attr->df_pref);
+                                    new_select->attr->df_pref, &zret);
        } else {
                if (old_select && old_select->type == ZEBRA_ROUTE_BGP
                                && old_select->sub_type == BGP_ROUTE_IMPORTED)
@@ -447,7 +449,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
                         attr->mp_nexthop_global_in);
        }
 
-       /* Return back the route entry. */
+       /* Return back th*e route entry. */
        *ri = tmp_pi;
        return 0;
 }
@@ -1371,23 +1373,28 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es,
 }
 
 /* Send the remote ES to zebra for NHG programming */
-static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
-               struct bgp_evpn_es_vtep *es_vtep, bool add)
+static enum zclient_send_status
+bgp_zebra_send_remote_es_vtep(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep,
+                             bool add)
 {
        struct bgp_evpn_es *es = es_vtep->es;
        struct stream *s;
        uint32_t flags = 0;
 
        /* Check socket. */
-       if (!zclient || zclient->sock < 0)
-               return 0;
+       if (!zclient || zclient->sock < 0) {
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: No zclient or zclient->sock exists",
+                                  __func__);
+               return ZCLIENT_SEND_SUCCESS;
+       }
 
        /* Don't try to register if Zebra doesn't know of this instance. */
        if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
                if (BGP_DEBUG(zebra, ZEBRA))
                        zlog_debug("No zebra instance, not installing remote es %s",
                                        es->esi_str);
-               return 0;
+               return ZCLIENT_SEND_SUCCESS;
        }
 
        if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
@@ -1418,12 +1425,12 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
        return zclient_send_message(zclient);
 }
 
-static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
-                                           struct bgp_evpn_es_vtep *es_vtep,
-                                           bool param_change)
+static enum zclient_send_status bgp_evpn_es_vtep_re_eval_active(
+       struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, bool param_change)
 {
        bool old_active;
        bool new_active;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        old_active = CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
        /* currently we need an active EVI reference to use the VTEP as
@@ -1445,7 +1452,7 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
                                   es_vtep->df_alg, es_vtep->df_pref);
 
                /* send remote ES to zebra */
-               bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
+               ret = bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
 
                /* The NHG is updated first for efficient failover handling.
                 * Note the NHG can be de-activated while there are bgp
@@ -1457,13 +1464,14 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
                /* queue up the es for background consistency checks */
                bgp_evpn_es_cons_checks_pend_add(es_vtep->es);
        }
+
+       return ret;
 }
 
-static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
-                                                    struct bgp_evpn_es *es,
-                                                    struct in_addr vtep_ip,
-                                                    bool esr, uint8_t df_alg,
-                                                    uint16_t df_pref)
+static struct bgp_evpn_es_vtep *
+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es,
+                    struct in_addr vtep_ip, bool esr, uint8_t df_alg,
+                    uint16_t df_pref, int *zret)
 {
        struct bgp_evpn_es_vtep *es_vtep;
        bool param_change = false;
@@ -1490,15 +1498,17 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
                ++es_vtep->evi_cnt;
        }
 
-       bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
+       *zret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
 
        return es_vtep;
 }
 
-static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
-               struct bgp_evpn_es_vtep *es_vtep, bool esr)
+static enum zclient_send_status
+bgp_evpn_es_vtep_do_del(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep,
+                       bool esr)
 {
        bool param_change = false;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
                zlog_debug("es %s vtep %pI4 del %s", es_vtep->es->esi_str,
@@ -1515,18 +1525,25 @@ static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
                        --es_vtep->evi_cnt;
        }
 
-       bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
+       ret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
        bgp_evpn_es_vtep_free(es_vtep);
+
+       return ret;
 }
 
-static void bgp_evpn_es_vtep_del(struct bgp *bgp,
-               struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr)
+static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp,
+                                                    struct bgp_evpn_es *es,
+                                                    struct in_addr vtep_ip,
+                                                    bool esr)
 {
        struct bgp_evpn_es_vtep *es_vtep;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip);
        if (es_vtep)
-               bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
+               ret = bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
+
+       return ret;
 }
 
 /********************** ES MAC-IP paths *************************************
@@ -3399,12 +3416,14 @@ static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find(
 /* A VTEP can be added as "active" attach to an ES if EAD-per-ES and
  * EAD-per-EVI routes are rxed from it.
  */
-static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
-               struct bgp_evpn_es_evi_vtep *evi_vtep)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
+                                   struct bgp_evpn_es_evi_vtep *evi_vtep)
 {
        bool old_active;
        bool new_active;
        uint32_t ead_activity_flags;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        old_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
 
@@ -3425,7 +3444,7 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
        new_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
 
        if (old_active == new_active)
-               return;
+               return ret;
 
        if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
                zlog_debug("es %s evi %u vtep %pI4 %s",
@@ -3434,24 +3453,27 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
                           new_active ? "active" : "inactive");
 
        /* add VTEP to parent es */
-       if (new_active)
-               evi_vtep->es_vtep = bgp_evpn_es_vtep_add(
-                       bgp, evi_vtep->es_evi->es, evi_vtep->vtep_ip,
-                       false /*esr*/, 0, 0);
-       else {
+       if (new_active) {
+               evi_vtep->es_vtep =
+                       bgp_evpn_es_vtep_add(bgp, evi_vtep->es_evi->es,
+                                            evi_vtep->vtep_ip, false /*esr*/,
+                                            0, 0, &ret);
+       } else {
                if (evi_vtep->es_vtep) {
-                       bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
-                                       false /*esr*/);
+                       ret = bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
+                                                     false /*esr*/);
                        evi_vtep->es_vtep = NULL;
                }
        }
        /* queue up the parent es for background consistency checks */
        bgp_evpn_es_cons_checks_pend_add(evi_vtep->es_evi->es);
+
+       return ret;
 }
 
-static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
-               struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
-               bool ead_es)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_add(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi,
+                        struct in_addr vtep_ip, bool ead_es)
 {
        struct bgp_evpn_es_evi_vtep *evi_vtep;
 
@@ -3475,18 +3497,19 @@ static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
        else
                SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
 
-       bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
+       return bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
 }
 
-static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
-               struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
-               bool ead_es)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_del(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi,
+                        struct in_addr vtep_ip, bool ead_es)
 {
        struct bgp_evpn_es_evi_vtep *evi_vtep;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip);
        if (!evi_vtep)
-               return;
+               return ret;
 
        if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
                zlog_debug("del es %s evi %u vtep %pI4 %s",
@@ -3503,8 +3526,10 @@ static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
        else
                UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
 
-       bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
+       ret = bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
        bgp_evpn_es_evi_vtep_free(evi_vtep);
+
+       return ret;
 }
 
 /* compare ES-IDs for the ES-EVI RB tree maintained per-VNI */
@@ -3780,18 +3805,20 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
 /* Add remote ES-EVI entry. This is actually the remote VTEP add and the
  * ES-EVI is implicity created on first VTEP's reference.
  */
-int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
-               const struct prefix_evpn *p)
+enum zclient_send_status bgp_evpn_remote_es_evi_add(struct bgp *bgp,
+                                                   struct bgpevpn *vpn,
+                                                   const struct prefix_evpn *p)
 {
        char buf[ESI_STR_LEN];
        struct bgp_evpn_es *es;
        struct bgp_evpn_es_evi *es_evi;
        bool ead_es;
        const esi_t *esi = &p->prefix.ead_addr.esi;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        if (!vpn)
                /* local EAD-ES need not be sent back to zebra */
-               return 0;
+               return ret;
 
        if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
                zlog_debug("add remote %s es %s evi %u vtep %pI4",
@@ -3808,27 +3835,29 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
                es_evi = bgp_evpn_es_evi_new(es, vpn);
 
        ead_es = !!p->prefix.ead_addr.eth_tag;
-       bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
-                       ead_es);
+       ret = bgp_evpn_es_evi_vtep_add(bgp, es_evi,
+                                      p->prefix.ead_addr.ip.ipaddr_v4, ead_es);
 
        bgp_evpn_es_evi_remote_info_re_eval(es_evi);
-       return 0;
+       return ret;
 }
 
 /* A remote VTEP has withdrawn. The es-evi-vtep will be deleted and the
  * parent es-evi freed up implicitly in last VTEP's deref.
  */
-int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
-               const struct prefix_evpn *p)
+enum zclient_send_status bgp_evpn_remote_es_evi_del(struct bgp *bgp,
+                                                   struct bgpevpn *vpn,
+                                                   const struct prefix_evpn *p)
 {
        char buf[ESI_STR_LEN];
        struct bgp_evpn_es *es;
        struct bgp_evpn_es_evi *es_evi;
        bool ead_es;
+       enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
 
        if (!vpn)
                /* local EAD-ES need not be sent back to zebra */
-               return 0;
+               return ret;
 
        if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
                zlog_debug(
@@ -3847,7 +3876,7 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
                                esi_to_str(&p->prefix.ead_addr.esi, buf,
                                           sizeof(buf)),
                                vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4);
-               return 0;
+               return ret;
        }
        es_evi = bgp_evpn_es_evi_find(es, vpn);
        if (!es_evi) {
@@ -3860,14 +3889,15 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
                                           sizeof(buf)),
                                vpn->vni,
                                &p->prefix.ead_addr.ip.ipaddr_v4);
-               return 0;
+               return ret;
        }
 
        ead_es = !!p->prefix.ead_addr.eth_tag;
-       bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
-                       ead_es);
+       ret = bgp_evpn_es_evi_vtep_del(bgp, es_evi,
+                                      p->prefix.ead_addr.ip.ipaddr_v4, ead_es);
        bgp_evpn_es_evi_remote_info_re_eval(es_evi);
-       return 0;
+
+       return ret;
 }
 
 /* If a VNI is being deleted we need to force del all remote VTEPs */
index cebabb9fd05114a6020afd4e1a55e740959d8330..5d393c37a20df72899cbe1dd7c7dadb53cece7e0 100644 (file)
@@ -418,10 +418,12 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
 extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi);
 extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni);
 extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni);
-extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
-               const struct prefix_evpn *p);
-extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
-               const struct prefix_evpn *p);
+extern enum zclient_send_status
+bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
+                          const struct prefix_evpn *p);
+extern enum zclient_send_status
+bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
+                          const struct prefix_evpn *p);
 extern void bgp_evpn_mh_init(void);
 extern void bgp_evpn_mh_finish(void);
 void bgp_evpn_vni_es_init(struct bgpevpn *vpn);
index 88baa535100d290612c8df9fd134cb3b9b0927e3..1f26736b552be2acfc691324effd548a4dd5b149 100644 (file)
@@ -3402,9 +3402,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
                                    && (new_select->sub_type == BGP_ROUTE_NORMAL
                                        || new_select->sub_type
                                                   == BGP_ROUTE_IMPORTED))
-
                                        bgp_zebra_route_install(dest, old_select,
-                                                               bgp, true);
+                                                               bgp, true, NULL,
+                                                               false);
                        }
                }
 
@@ -3522,9 +3522,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
                        if (old_select &&
                            is_route_parent_evpn(old_select))
                                bgp_zebra_route_install(dest, old_select, bgp,
-                                                       false);
+                                                       false, NULL, false);
 
-                       bgp_zebra_route_install(dest, new_select, bgp, true);
+                       bgp_zebra_route_install(dest, new_select, bgp, true,
+                                               NULL, false);
                } else {
                        /* Withdraw the route from the kernel. */
                        if (old_select && old_select->type == ZEBRA_ROUTE_BGP
@@ -3533,7 +3534,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
                                || old_select->sub_type == BGP_ROUTE_IMPORTED))
 
                                bgp_zebra_route_install(dest, old_select, bgp,
-                                                       false);
+                                                       false, NULL, false);
                }
        }
 
@@ -4430,7 +4431,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
        if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
                if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
                        /* remove from RIB previous entry */
-                       bgp_zebra_route_install(dest, pi, bgp, false);
+                       bgp_zebra_route_install(dest, pi, bgp, false, NULL,
+                                               false);
        }
 
        if (peer->sort == BGP_PEER_EBGP) {
index 95705d24707d233c33edef5a860de930c818000d..130f5ca749e5e35f11ea8670688ab537fd6022be 100644 (file)
@@ -78,6 +78,8 @@ struct bgp_dest {
 
        struct zebra_announce_item zai;
        struct bgp_path_info *za_bgp_pi;
+       struct bgpevpn *za_vpn;
+       bool za_is_sync;
 
        uint64_t version;
 
index 04d520a9233e359392974d94f7c187a7607713d9..95c89869a282e5568f23771bb9cbc14f7a1e7946 100644 (file)
@@ -1687,12 +1687,11 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
        for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
                for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
                        if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
-
                            (pi->type == ZEBRA_ROUTE_BGP
                             && (pi->sub_type == BGP_ROUTE_NORMAL
                                 || pi->sub_type == BGP_ROUTE_IMPORTED)))
-
-                               bgp_zebra_route_install(dest, pi, bgp, true);
+                               bgp_zebra_route_install(dest, pi, bgp, true,
+                                                       NULL, false);
 }
 
 /* Announce routes of any bgp subtype of a table to zebra */
@@ -1714,7 +1713,8 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
                for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
                        if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
                            pi->type == ZEBRA_ROUTE_BGP)
-                               bgp_zebra_route_install(dest, pi, bgp, true);
+                               bgp_zebra_route_install(dest, pi, bgp, true,
+                                                       NULL, false);
 }
 
 enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
@@ -1767,6 +1767,7 @@ enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
 #define ZEBRA_ANNOUNCEMENTS_LIMIT 1000
 static void bgp_handle_route_announcements_to_zebra(struct event *e)
 {
+       bool is_evpn = false;
        uint32_t count = 0;
        struct bgp_dest *dest = NULL;
        struct bgp_table *table = NULL;
@@ -1781,6 +1782,8 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e)
 
                table = bgp_dest_table(dest);
                install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+               if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+                       is_evpn = true;
 
                if (BGP_DEBUG(zebra, ZEBRA))
                        zlog_debug("BGP %s route %pBD(%s) with dest %p and flags 0x%x to zebra",
@@ -1788,17 +1791,38 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e)
                                   table->bgp->name_pretty, dest, dest->flags);
 
                if (install) {
-                       status = bgp_zebra_announce_actual(dest, dest->za_bgp_pi,
-                                                          table->bgp);
+                       if (is_evpn)
+                               status =
+                                       evpn_zebra_install(table->bgp,
+                                                          dest->za_vpn,
+                                                          (const struct prefix_evpn
+                                                                   *)
+                                                                  bgp_dest_get_prefix(
+                                                                          dest),
+                                                          dest->za_bgp_pi);
+                       else
+                               status = bgp_zebra_announce_actual(dest,
+                                                                  dest->za_bgp_pi,
+                                                                  table->bgp);
                        UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
                } else {
-                       status = bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi,
-                                                          table->bgp);
+                       if (is_evpn)
+                               status = evpn_zebra_uninstall(
+                                       table->bgp, dest->za_vpn,
+                                       (const struct prefix_evpn *)
+                                               bgp_dest_get_prefix(dest),
+                                       dest->za_bgp_pi, false);
+                       else
+                               status = bgp_zebra_withdraw_actual(dest,
+                                                                  dest->za_bgp_pi,
+                                                                  table->bgp);
+
                        UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
                }
 
                bgp_path_info_unlock(dest->za_bgp_pi);
                dest->za_bgp_pi = NULL;
+               dest->za_vpn = NULL;
                bgp_dest_unlock_node(dest);
 
                if (status == ZCLIENT_SEND_BUFFERED)
@@ -1852,8 +1876,16 @@ static void bgp_zebra_buffer_write_ready(void)
  *                                     withdrawn.
  */
 void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
-                            struct bgp *bgp, bool install)
+                            struct bgp *bgp, bool install, struct bgpevpn *vpn,
+                            bool is_sync)
 {
+       bool is_evpn = false;
+       struct bgp_table *table = NULL;
+
+       table = bgp_dest_table(dest);
+       if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+               is_evpn = true;
+
        /*
         * BGP is installing this route and bgp has been configured
         * to suppress announcements until the route has been installed
@@ -1863,7 +1895,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
                if (BGP_SUPPRESS_FIB_ENABLED(bgp))
                        SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
 
-               if (bgp->main_zebra_update_hold)
+               if (bgp->main_zebra_update_hold && !is_evpn)
                        return;
        } else {
                UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
@@ -1873,7 +1905,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
         * Don't try to install if we're not connected to Zebra or Zebra doesn't
         * know of this instance.
         */
-       if (!bgp_install_info_to_zebra(bgp))
+       if (!bgp_install_info_to_zebra(bgp) && !is_evpn)
                return;
 
        if (!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL) &&
@@ -1893,7 +1925,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
                dest->za_bgp_pi = info;
        } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
                assert(dest->za_bgp_pi);
-               if (install)
+               if (install & !is_evpn)
                        bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi, bgp);
 
                bgp_path_info_unlock(dest->za_bgp_pi);
@@ -1901,6 +1933,11 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
                dest->za_bgp_pi = info;
        }
 
+       if (is_evpn) {
+               dest->za_vpn = vpn;
+               dest->za_is_sync = is_sync;
+       }
+
        if (install) {
                UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
                SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
@@ -1931,7 +1968,8 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa
                for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
                        if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
                            && (pi->type == ZEBRA_ROUTE_BGP))
-                               bgp_zebra_route_install(dest, pi, bgp, false);
+                               bgp_zebra_route_install(dest, pi, bgp, false,
+                                                       NULL, false);
                }
        }
 }
index 9c033197f7db573457db99c1bc7e381fb4eb51d1..ef296b963c57a2f3ca96aa2c1c20ecbd9faa9702 100644 (file)
@@ -30,7 +30,8 @@ extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,
 extern int bgp_if_update_all(void);
 extern void bgp_zebra_route_install(struct bgp_dest *dest,
                                    struct bgp_path_info *path, struct bgp *bgp,
-                                   bool install);
+                                   bool install, struct bgpevpn *vpn,
+                                   bool is_sync);
 extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi);
 
 /* Announce routes of any bgp subtype of a table to zebra */
index c0fefd53baa7b227f4c0b3feeafc56acf28e8a8d..e882a181b50ceac91eae152d98be9ac347974dd2 100644 (file)
@@ -530,6 +530,7 @@ struct bgp {
 #define BGP_FLAG_SOFT_VERSION_CAPABILITY (1ULL << 35)
 #define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)
 #define BGP_FLAG_DYNAMIC_CAPABILITY (1ULL << 37)
+#define BGP_FLAG_VNI_DOWN               (1ULL << 38)
 
        /* BGP default address-families.
         * New peers inherit enabled afi/safis from bgp instance.