]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_rnh.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / zebra / zebra_rnh.c
index a8389f2adf4bc36040396d307dfb9f6fa6e392a8..2d9c83becb7b6ee65926ca8f23d54fd321170cac 100644 (file)
@@ -50,6 +50,8 @@
 #include "zebra/zebra_memory.h"
 #include "zebra/zebra_errors.h"
 
+DEFINE_MTYPE_STATIC(ZEBRA, RNH, "Nexthop tracking object")
+
 static void free_state(vrf_id_t vrf_id, struct route_entry *re,
                       struct route_node *rn);
 static void copy_state(struct rnh *rnh, struct route_entry *re,
@@ -60,9 +62,6 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
 static void print_rnh(struct route_node *rn, struct vty *vty);
 static int zebra_client_cleanup_rnh(struct zserv *client);
 
-int zebra_rnh_ip_default_route = 0;
-int zebra_rnh_ipv6_default_route = 0;
-
 void zebra_rnh_init(void)
 {
        hook_register(zserv_client_close, zebra_client_cleanup_rnh);
@@ -160,14 +159,15 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
 
        if (IS_ZEBRA_DEBUG_NHT) {
                prefix2str(p, buf, sizeof(buf));
-               zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type);
+               zlog_debug("%u: Add RNH %s type %s", vrfid, buf,
+                          rnh_type2str(type));
        }
        table = get_rnh_table(vrfid, afi, type);
        if (!table) {
                prefix2str(p, buf, sizeof(buf));
                flog_warn(EC_ZEBRA_RNH_NO_TABLE,
-                         "%u: Add RNH %s type %d - table not found", vrfid,
-                         buf, type);
+                         "%u: Add RNH %s type %s - table not found", vrfid,
+                         buf, rnh_type2str(type));
                exists = false;
                return NULL;
        }
@@ -271,8 +271,8 @@ static void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
 
        if (IS_ZEBRA_DEBUG_NHT) {
                char buf[PREFIX2STR_BUFFER];
-               zlog_debug("%u: Del RNH %s type %d", rnh->vrf_id,
-                          rnh_str(rnh, buf, sizeof(buf)), type);
+               zlog_debug("%u: Del RNH %s type %s", rnh->vrf_id,
+                          rnh_str(rnh, buf, sizeof(buf)), rnh_type2str(type));
        }
 
        zebra_free_rnh(rnh);
@@ -293,9 +293,9 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
 {
        if (IS_ZEBRA_DEBUG_NHT) {
                char buf[PREFIX2STR_BUFFER];
-               zlog_debug("%u: Client %s registers for RNH %s type %d", vrf_id,
+               zlog_debug("%u: Client %s registers for RNH %s type %s", vrf_id,
                           zebra_route_string(client->proto),
-                          rnh_str(rnh, buf, sizeof(buf)), type);
+                          rnh_str(rnh, buf, sizeof(buf)), rnh_type2str(type));
        }
        if (!listnode_lookup(rnh->client_list, client))
                listnode_add(rnh->client_list, client);
@@ -312,9 +312,9 @@ void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
 {
        if (IS_ZEBRA_DEBUG_NHT) {
                char buf[PREFIX2STR_BUFFER];
-               zlog_debug("Client %s unregisters for RNH %s type %d",
+               zlog_debug("Client %s unregisters for RNH %s type %s",
                           zebra_route_string(client->proto),
-                          rnh_str(rnh, buf, sizeof(buf)), type);
+                          rnh_str(rnh, buf, sizeof(buf)), rnh_type2str(type));
        }
        listnode_delete(rnh->client_list, client);
        zebra_delete_rnh(rnh, type);
@@ -337,7 +337,7 @@ static void addr2hostprefix(int af, const union g_addr *addr,
                break;
        default:
                memset(prefix, 0, sizeof(*prefix));
-               zlog_debug("%s: unknown address family %d", __func__, af);
+               zlog_warn("%s: unknown address family %d", __func__, af);
                break;
        }
 }
@@ -384,7 +384,7 @@ static void zebra_rnh_clear_nexthop_rnh_filters(struct route_entry *re)
        struct nexthop *nexthop;
 
        if (re) {
-               for (nexthop = re->ng.nexthop; nexthop;
+               for (nexthop = re->nhe->nhg->nexthop; nexthop;
                     nexthop = nexthop->next) {
                        UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RNH_FILTERED);
                }
@@ -403,7 +403,7 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf,
        route_map_result_t ret;
 
        if (prn && re) {
-               for (nexthop = re->ng.nexthop; nexthop;
+               for (nexthop = re->nhe->nhg->nexthop; nexthop;
                     nexthop = nexthop->next) {
                        ret = zebra_nht_route_map_check(
                                afi, proto, &prn->p, zvrf, re, nexthop);
@@ -462,6 +462,7 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi,
        RNODE_FOREACH_RE (rn, re) {
                if (!CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)
                    && CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
+                   && !CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED)
                    && (re->type != ZEBRA_ROUTE_BGP))
                        break;
        }
@@ -592,54 +593,6 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi,
                zebra_rnh_clear_nexthop_rnh_filters(re);
 }
 
-static void zebra_rnh_process_pbr_tables(afi_t afi, struct route_node *nrn,
-                                        struct rnh *rnh,
-                                        struct route_node *prn,
-                                        struct route_entry *re)
-{
-       struct zebra_router_table *zrt;
-       struct route_entry *o_re;
-       struct route_node *o_rn;
-       struct listnode *node;
-       struct zserv *client;
-
-       /*
-        * We are only concerned about nexthops that change for
-        * anyone using PBR
-        */
-       for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
-               if (client->proto == ZEBRA_ROUTE_PBR)
-                       break;
-       }
-
-       if (!client)
-               return;
-
-       RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
-               if (afi != zrt->afi)
-                       continue;
-
-               for (o_rn = route_top(zrt->table); o_rn;
-                    o_rn = srcdest_route_next(o_rn)) {
-                       RNODE_FOREACH_RE (o_rn, o_re) {
-                               if (o_re->type == ZEBRA_ROUTE_PBR)
-                                       break;
-
-                       }
-
-                       /*
-                        * If we have a PBR route and a nexthop changes
-                        * just rethink it.  Yes this is a hammer, but
-                        * a small one
-                        */
-                       if (o_re) {
-                               SET_FLAG(o_re->status, ROUTE_ENTRY_CHANGED);
-                               rib_queue_add(o_rn);
-                       }
-               }
-       }
-}
-
 /*
  * Utility to determine whether a candidate nexthop is useable. We make this
  * check in a couple of places, so this is a single home for the logic we
@@ -700,7 +653,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
                 * match route to be exact if so specified
                 */
                if (is_default_prefix(&rn->p)
-                   && !rnh_resolve_via_default(rn->p.family)) {
+                   && !rnh_resolve_via_default(zvrf, rn->p.family)) {
                        if (IS_ZEBRA_DEBUG_NHT_DETAILED)
                                zlog_debug(
                                        "\tNot allowed to resolve through default prefix");
@@ -724,10 +677,18 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
                                continue;
                        }
 
+                       if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED)) {
+                               if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+                                       zlog_debug(
+                                               "\tRoute Entry %s queued",
+                                               zebra_route_string(re->type));
+                               continue;
+                       }
+
                        /* Just being SELECTED isn't quite enough - must
                         * have an installed nexthop to be useful.
                         */
-                       for (ALL_NEXTHOPS(re->ng, nexthop)) {
+                       for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
                                if (rnh_nexthop_valid(re, nexthop))
                                        break;
                        }
@@ -746,7 +707,8 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
                                        break;
                                if (re->type == ZEBRA_ROUTE_NHRP) {
 
-                                       for (nexthop = re->ng.nexthop; nexthop;
+                                       for (nexthop = re->nhe->nhg->nexthop;
+                                            nexthop;
                                             nexthop = nexthop->next)
                                                if (nexthop->type
                                                    == NEXTHOP_TYPE_IFINDEX)
@@ -804,7 +766,7 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
         * change.
         */
        zebra_rnh_remove_from_routing_table(rnh);
-       if (!prefix_same(&rnh->resolved_route, prn ? NULL : &prn->p)) {
+       if (!prefix_same(&rnh->resolved_route, prn ? &prn->p : NULL)) {
                if (prn)
                        prefix_copy(&rnh->resolved_route, &prn->p);
                else {
@@ -834,8 +796,6 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
                zebra_rnh_notify_protocol_clients(zvrf, afi, nrn, rnh, prn,
                                                  rnh->state);
 
-               zebra_rnh_process_pbr_tables(afi, nrn, rnh, prn, rnh->state);
-
                /* Process pseudowires attached to this nexthop */
                zebra_rnh_process_pseudowires(zvrf->vrf->vrf_id, rnh);
        }
@@ -853,8 +813,8 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
 
        if (IS_ZEBRA_DEBUG_NHT) {
                prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
-               zlog_debug("%u:%s: Evaluate RNH, type %d %s", zvrf->vrf->vrf_id,
-                          bufn, type, force ? "(force)" : "");
+               zlog_debug("%u:%s: Evaluate RNH, type %s %s", zvrf->vrf->vrf_id,
+                          bufn, rnh_type2str(type), force ? "(force)" : "");
        }
 
        rnh = nrn->info;
@@ -906,10 +866,8 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi,
                re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh,
                                                     &prn);
 
-       if (re) {
-               UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED);
+       if (re)
                UNSET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
-       }
 }
 
 /* Evaluate all tracked entries (nexthops or routes for import into BGP)
@@ -959,12 +917,13 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
 
        table = get_rnh_table(vrfid, afi, type);
        if (!table) {
-               zlog_debug("print_rnhs: rnh table not found");
+               if (IS_ZEBRA_DEBUG_NHT)
+                       zlog_debug("print_rnhs: rnh table not found");
                return;
        }
 
        for (rn = route_top(table); rn; rn = route_next(rn)) {
-               if (p && prefix_cmp(&rn->p, p) != 0)
+               if (p && !prefix_match(&rn->p, p))
                        continue;
 
                if (rn->info)
@@ -982,7 +941,7 @@ static void free_state(vrf_id_t vrf_id, struct route_entry *re,
                return;
 
        /* free RE and nexthops */
-       nexthops_free(re->ng.nexthop);
+       zebra_nhg_free(re->nhe);
        XFREE(MTYPE_RE, re);
 }
 
@@ -1006,13 +965,15 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
        state->vrf_id = re->vrf_id;
        state->status = re->status;
 
-       route_entry_copy_nexthops(state, re->ng.nexthop);
+       state->nhe = zebra_nhg_alloc();
+       state->nhe->nhg = nexthop_group_new();
+
+       nexthop_group_copy(state->nhe->nhg, re->nhe->nhg);
        rnh->state = state;
 }
 
 static int compare_state(struct route_entry *r1, struct route_entry *r2)
 {
-
        if (!r1 && !r2)
                return 0;
 
@@ -1025,11 +986,12 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
        if (r1->metric != r2->metric)
                return 1;
 
-       if (r1->nexthop_num != r2->nexthop_num)
+       if (nexthop_group_nexthop_num(r1->nhe->nhg)
+           != nexthop_group_nexthop_num(r2->nhe->nhg))
                return 1;
 
-       if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)
-           || CHECK_FLAG(r1->status, ROUTE_ENTRY_LABELS_CHANGED))
+       if (nexthop_group_hash(r1->nhe->nhg) !=
+           nexthop_group_hash(r2->nhe->nhg))
                return 1;
 
        return 0;
@@ -1072,6 +1034,8 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
                break;
        }
        if (re) {
+               struct zapi_nexthop znh;
+
                stream_putc(s, re->type);
                stream_putw(s, re->instance);
                stream_putc(s, re->distance);
@@ -1079,39 +1043,10 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
                num = 0;
                nump = stream_get_endp(s);
                stream_putc(s, 0);
-               for (ALL_NEXTHOPS(re->ng, nh))
+               for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nh))
                        if (rnh_nexthop_valid(re, nh)) {
-                               stream_putl(s, nh->vrf_id);
-                               stream_putc(s, nh->type);
-                               switch (nh->type) {
-                               case NEXTHOP_TYPE_IPV4:
-                               case NEXTHOP_TYPE_IPV4_IFINDEX:
-                                       stream_put_in_addr(s, &nh->gate.ipv4);
-                                       stream_putl(s, nh->ifindex);
-                                       break;
-                               case NEXTHOP_TYPE_IFINDEX:
-                                       stream_putl(s, nh->ifindex);
-                                       break;
-                               case NEXTHOP_TYPE_IPV6:
-                               case NEXTHOP_TYPE_IPV6_IFINDEX:
-                                       stream_put(s, &nh->gate.ipv6, 16);
-                                       stream_putl(s, nh->ifindex);
-                                       break;
-                               default:
-                                       /* do nothing */
-                                       break;
-                               }
-                               if (nh->nh_label) {
-                                       stream_putc(s,
-                                                   nh->nh_label->num_labels);
-                                       if (nh->nh_label->num_labels)
-                                               stream_put(
-                                                       s,
-                                                       &nh->nh_label->label[0],
-                                                       nh->nh_label->num_labels
-                                                               * sizeof(mpls_label_t));
-                               } else
-                                       stream_putc(s, 0);
+                               zapi_nexthop_from_nexthop(&znh, nh);
+                               zapi_nexthop_encode(s, &znh, 0 /* flags */);
                                num++;
                        }
                stream_putc_at(s, nump, num);
@@ -1179,7 +1114,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty)
        if (rnh->state) {
                vty_out(vty, " resolved via %s\n",
                        zebra_route_string(rnh->state->type));
-               for (nexthop = rnh->state->ng.nexthop; nexthop;
+               for (nexthop = rnh->state->nhe->nhg->nexthop; nexthop;
                     nexthop = nexthop->next)
                        print_nh(nexthop, vty);
        } else
@@ -1206,9 +1141,9 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
        struct rnh *rnh;
 
        if (IS_ZEBRA_DEBUG_NHT)
-               zlog_debug("%u: Client %s RNH cleanup for family %s type %d",
+               zlog_debug("%u: Client %s RNH cleanup for family %s type %s",
                           vrf_id, zebra_route_string(client->proto),
-                          afi2str(afi), type);
+                          afi2str(afi), rnh_type2str(type));
 
        ntable = get_rnh_table(vrf_id, afi, type);
        if (!ntable) {
@@ -1243,15 +1178,17 @@ static int zebra_client_cleanup_rnh(struct zserv *client)
                                                 RNH_IMPORT_CHECK_TYPE);
                        zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client,
                                                 RNH_IMPORT_CHECK_TYPE);
-                       if (client->proto == ZEBRA_ROUTE_LDP) {
-                               hash_iterate(zvrf->lsp_table,
-                                            mpls_ldp_lsp_uninstall_all,
-                                            zvrf->lsp_table);
-                               mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP);
-                               mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP6);
-                       }
                }
        }
 
        return 0;
 }
+
+int rnh_resolve_via_default(struct zebra_vrf *zvrf, int family)
+{
+       if (((family == AF_INET) && zvrf->zebra_rnh_ip_default_route)
+           || ((family == AF_INET6) && zvrf->zebra_rnh_ipv6_default_route))
+               return 1;
+       else
+               return 0;
+}