]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_nht.c
Merge pull request #12646 from pguibert6WIND/mpls_alloc_per_nh
[mirror_frr.git] / bgpd / bgp_nht.c
index d7707a8c0c057aa29fffa31036f639bc216d409d..bda163d7a50943d9260973a18fb86868437d6ed2 100644 (file)
@@ -1,27 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /* BGP Nexthop tracking
  * Copyright (C) 2013 Cumulus Networks, Inc.
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
 
 #include "command.h"
-#include "thread.h"
+#include "frrevent.h"
 #include "prefix.h"
 #include "zclient.h"
 #include "stream.h"
@@ -53,7 +38,7 @@ extern struct zclient *zclient;
 static void register_zebra_rnh(struct bgp_nexthop_cache *bnc);
 static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc);
 static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p);
-static void bgp_nht_ifp_initial(struct thread *thread);
+static void bgp_nht_ifp_initial(struct event *thread);
 
 static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
 {
@@ -165,6 +150,8 @@ void bgp_unlink_nexthop(struct bgp_path_info *path)
 {
        struct bgp_nexthop_cache *bnc = path->nexthop;
 
+       bgp_mplsvpn_path_nh_label_unlink(path);
+
        if (!bnc)
                return;
 
@@ -340,7 +327,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                 * Gather the ifindex for if up/down events to be
                 * tagged into this fun
                 */
-               if (afi == AFI_IP6 &&
+               if (afi == AFI_IP6 && peer->conf_if &&
                    IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) {
                        ifindex = peer->su.sin6.sin6_scope_id;
                        if (ifindex == 0) {
@@ -772,10 +759,10 @@ void bgp_nht_ifp_down(struct interface *ifp)
        bgp_nht_ifp_handle(ifp, false);
 }
 
-static void bgp_nht_ifp_initial(struct thread *thread)
+static void bgp_nht_ifp_initial(struct event *thread)
 {
-       ifindex_t ifindex = THREAD_VAL(thread);
-       struct bgp *bgp = THREAD_ARG(thread);
+       ifindex_t ifindex = EVENT_VAL(thread);
+       struct bgp *bgp = EVENT_ARG(thread);
        struct interface *ifp = if_lookup_by_index(ifindex, bgp->vrf_id);
 
        if (!ifp)
@@ -827,21 +814,18 @@ void bgp_nht_interface_events(struct peer *peer)
                return;
 
        if (bnc->ifindex)
-               thread_add_event(bm->master, bgp_nht_ifp_initial, bnc->bgp,
-                                bnc->ifindex, NULL);
+               event_add_event(bm->master, bgp_nht_ifp_initial, bnc->bgp,
+                               bnc->ifindex, NULL);
 }
 
 void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
 {
        struct bgp_nexthop_cache_head *tree = NULL;
        struct bgp_nexthop_cache *bnc_nhc, *bnc_import;
-       struct bgp_path_info *pi;
-       struct bgp_dest *dest;
        struct bgp *bgp;
        struct prefix match;
        struct zapi_route nhr;
        afi_t afi;
-       safi_t safi;
 
        bgp = bgp_lookup_by_vrf_id(vrf_id);
        if (!bgp) {
@@ -862,37 +846,25 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
        tree = &bgp->nexthop_cache_table[afi];
 
        bnc_nhc = bnc_find(tree, &match, nhr.srte_color, 0);
-       if (bnc_nhc)
+       if (!bnc_nhc) {
+               if (BGP_DEBUG(nht, NHT))
+                       zlog_debug(
+                               "parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache",
+                               &nhr.prefix, nhr.srte_color, bgp->name_pretty);
+       } else
                bgp_process_nexthop_update(bnc_nhc, &nhr, false);
-       else if (BGP_DEBUG(nht, NHT))
-               zlog_debug(
-                       "parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache",
-                       &nhr.prefix, nhr.srte_color, bgp->name_pretty);
 
        tree = &bgp->import_check_table[afi];
 
        bnc_import = bnc_find(tree, &match, nhr.srte_color, 0);
-       if (bnc_import) {
+       if (!bnc_import) {
+               if (BGP_DEBUG(nht, NHT))
+                       zlog_debug(
+                               "parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check",
+                               &nhr.prefix, nhr.srte_color, bgp->name_pretty);
+       } else
                bgp_process_nexthop_update(bnc_import, &nhr, true);
 
-               safi = nhr.safi;
-               if (bgp->rib[afi][safi]) {
-                       dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
-                                               &match, NULL);
-
-                       for (pi = bgp_dest_get_bgp_path_info(dest); pi;
-                            pi = pi->next)
-                               if (pi->peer == bgp->peer_self &&
-                                   pi->type == ZEBRA_ROUTE_BGP &&
-                                   pi->sub_type == BGP_ROUTE_STATIC)
-                                       vpn_leak_from_vrf_update(
-                                               bgp_get_default(), bgp, pi);
-               }
-       } else if (BGP_DEBUG(nht, NHT))
-               zlog_debug(
-                       "parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check",
-                       &nhr.prefix, nhr.srte_color, bgp->name_pretty);
-
        /*
         * HACK: if any BGP route is dependant on an SR-policy that doesn't
         * exist, zebra will never send NH updates relative to that policy. In
@@ -1165,10 +1137,21 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
        }
 
        LIST_FOREACH (path, &(bnc->paths), nh_thread) {
-               if (!(path->type == ZEBRA_ROUTE_BGP
-                     && ((path->sub_type == BGP_ROUTE_NORMAL)
-                         || (path->sub_type == BGP_ROUTE_STATIC)
-                         || (path->sub_type == BGP_ROUTE_IMPORTED))))
+               if (path->type == ZEBRA_ROUTE_BGP &&
+                   (path->sub_type == BGP_ROUTE_NORMAL ||
+                    path->sub_type == BGP_ROUTE_STATIC ||
+                    path->sub_type == BGP_ROUTE_IMPORTED))
+                       /* evaluate the path */
+                       ;
+               else if (path->sub_type == BGP_ROUTE_REDISTRIBUTE) {
+                       /* evaluate the path for redistributed routes
+                        * except those from VNC
+                        */
+                       if ((path->type == ZEBRA_ROUTE_VNC) ||
+                           (path->type == ZEBRA_ROUTE_VNC_DIRECT))
+                               continue;
+               } else
+                       /* don't evaluate the path */
                        continue;
 
                dest = path->net;
@@ -1221,14 +1204,20 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
                }
 
                if (BGP_DEBUG(nht, NHT)) {
-                       if (dest->pdest)
-                               zlog_debug(
-                                       "... eval path %d/%d %pBD RD %pRD %s flags 0x%x",
-                                       afi, safi, dest,
+
+                       if (dest->pdest) {
+                               char rd_buf[RD_ADDRSTRLEN];
+
+                               prefix_rd2str(
                                        (struct prefix_rd *)bgp_dest_get_prefix(
                                                dest->pdest),
+                                       rd_buf, sizeof(rd_buf),
+                                       bgp_get_asnotation(bnc->bgp));
+                               zlog_debug(
+                                       "... eval path %d/%d %pBD RD %s %s flags 0x%x",
+                                       afi, safi, dest, rd_buf,
                                        bgp_path->name_pretty, path->flags);
-                       else
+                       else
                                zlog_debug(
                                        "... eval path %d/%d %pBD %s flags 0x%x",
                                        afi, safi, dest, bgp_path->name_pretty,
@@ -1255,7 +1244,26 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
                        SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED);
 
                path_valid = CHECK_FLAG(path->flags, BGP_PATH_VALID);
-               if (path_valid != bnc_is_valid_nexthop) {
+               if (path->type == ZEBRA_ROUTE_BGP &&
+                   path->sub_type == BGP_ROUTE_STATIC &&
+                   !CHECK_FLAG(bgp_path->flags, BGP_FLAG_IMPORT_CHECK))
+                       /* static routes with 'no bgp network import-check' are
+                        * always valid. if nht is called with static routes,
+                        * the vpn exportation needs to be triggered
+                        */
+                       vpn_leak_from_vrf_update(bgp_get_default(), bgp_path,
+                                                path);
+               else if (path->sub_type == BGP_ROUTE_REDISTRIBUTE &&
+                        safi == SAFI_UNICAST &&
+                        (bgp_path->inst_type == BGP_INSTANCE_TYPE_VRF ||
+                         bgp_path->inst_type == BGP_INSTANCE_TYPE_DEFAULT))
+                       /* redistribute routes are always valid
+                        * if nht is called with redistribute routes, the vpn
+                        * exportation needs to be triggered
+                        */
+                       vpn_leak_from_vrf_update(bgp_get_default(), bgp_path,
+                                                path);
+               else if (path_valid != bnc_is_valid_nexthop) {
                        if (path_valid) {
                                /* No longer valid, clear flag; also for EVPN
                                 * routes, unimport from VRFs if needed.
@@ -1268,6 +1276,12 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
                                    bgp_evpn_is_prefix_nht_supported(bgp_dest_get_prefix(dest)))
                                        bgp_evpn_unimport_route(bgp_path,
                                                afi, safi, bgp_dest_get_prefix(dest), path);
+                               if (safi == SAFI_UNICAST &&
+                                   (bgp_path->inst_type !=
+                                    BGP_INSTANCE_TYPE_VIEW))
+                                       vpn_leak_from_vrf_withdraw(
+                                               bgp_get_default(), bgp_path,
+                                               path);
                        } else {
                                /* Path becomes valid, set flag; also for EVPN
                                 * routes, import from VRFs if needed.
@@ -1280,6 +1294,12 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
                                    bgp_evpn_is_prefix_nht_supported(bgp_dest_get_prefix(dest)))
                                        bgp_evpn_import_route(bgp_path,
                                                afi, safi, bgp_dest_get_prefix(dest), path);
+                               if (safi == SAFI_UNICAST &&
+                                   (bgp_path->inst_type !=
+                                    BGP_INSTANCE_TYPE_VIEW))
+                                       vpn_leak_from_vrf_update(
+                                               bgp_get_default(), bgp_path,
+                                               path);
                        }
                }