]> git.proxmox.com Git - mirror_frr.git/blobdiff - isisd/isis_spf.c
Merge pull request #5625 from qlyoung/fix-zapi-ipset-name-nullterm
[mirror_frr.git] / isisd / isis_spf.c
index 79b3103237de6237c6205564706cde22392dd749..a28220eb260395d3b1c5013f1f14f72e6964c6b1 100644 (file)
@@ -39,7 +39,6 @@
 #include "isis_constants.h"
 #include "isis_common.h"
 #include "isis_flags.h"
-#include "dict.h"
 #include "isisd.h"
 #include "isis_misc.h"
 #include "isis_adjacency.h"
@@ -162,8 +161,7 @@ static const char *vtype2string(enum vertextype vtype)
        return NULL; /* Not reached */
 }
 
-#define VID2STR_BUFFER SRCDEST2STR_BUFFER
-static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
+const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
 {
        if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) {
                return print_sys_hostname(vertex->N.id);
@@ -179,18 +177,25 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
        return "UNKNOWN";
 }
 
-static struct isis_vertex *isis_vertex_new(union isis_N *n,
+static struct isis_vertex *isis_vertex_new(struct isis_spftree *spftree,
+                                          void *id,
                                           enum vertextype vtype)
 {
        struct isis_vertex *vertex;
 
        vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex));
 
-       isis_vertex_id_init(vertex, n, vtype);
+       isis_vertex_id_init(vertex, id, vtype);
 
        vertex->Adj_N = list_new();
        vertex->parents = list_new();
 
+       if (spftree->hopcount_metric) {
+               vertex->firsthops = hash_create(isis_vertex_queue_hash_key,
+                                               isis_vertex_queue_hash_cmp,
+                                               NULL);
+       }
+
        return vertex;
 }
 
@@ -307,7 +312,7 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level,
        memcpy(lspid, sysid, ISIS_SYS_ID_LEN);
        LSP_PSEUDO_ID(lspid) = 0;
        LSP_FRAGMENT(lspid) = 0;
-       lsp = lsp_search(lspid, area->lspdb[level - 1]);
+       lsp = lsp_search(&area->lspdb[level - 1], lspid);
        if (lsp && lsp->hdr.rem_lifetime != 0)
                return lsp;
        return NULL;
@@ -324,17 +329,13 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
 #ifdef EXTREME_DEBUG
        char buff[VID2STR_BUFFER];
 #endif /* EXTREME_DEBUG */
-       union isis_N n;
-
-       memcpy(n.id, sysid, ISIS_SYS_ID_LEN);
-       LSP_PSEUDO_ID(n.id) = 0;
 
        lsp = isis_root_system_lsp(spftree->area, spftree->level, sysid);
        if (lsp == NULL)
                zlog_warn("ISIS-Spf: could not find own l%d LSP!",
                          spftree->level);
 
-       vertex = isis_vertex_new(&n,
+       vertex = isis_vertex_new(spftree, sysid,
                                 spftree->area->oldmetric
                                         ? VTYPE_NONPSEUDO_IS
                                         : VTYPE_NONPSEUDO_TE_IS);
@@ -350,6 +351,26 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
        return vertex;
 }
 
+static void vertex_add_parent_firsthop(struct hash_bucket *bucket, void *arg)
+{
+       struct isis_vertex *vertex = arg;
+       struct isis_vertex *hop = bucket->data;
+
+       hash_get(vertex->firsthops, hop, hash_alloc_intern);
+}
+
+static void vertex_update_firsthops(struct isis_vertex *vertex,
+                                   struct isis_vertex *parent)
+{
+       if (vertex->d_N <= 2)
+               hash_get(vertex->firsthops, vertex, hash_alloc_intern);
+
+       if (vertex->d_N < 2 || !parent)
+               return;
+
+       hash_iterate(parent->firsthops, vertex_add_parent_firsthop, vertex);
+}
+
 /*
  * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
  */
@@ -368,7 +389,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
 
        assert(isis_find_vertex(&spftree->paths, id, vtype) == NULL);
        assert(isis_find_vertex(&spftree->tents, id, vtype) == NULL);
-       vertex = isis_vertex_new(id, vtype);
+       vertex = isis_vertex_new(spftree, id, vtype);
        vertex->d_N = cost;
        vertex->depth = depth;
 
@@ -376,6 +397,9 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
                listnode_add(vertex->parents, parent);
        }
 
+       if (spftree->hopcount_metric)
+               vertex_update_firsthops(vertex, parent);
+
        if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) {
                for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_adj))
                        listnode_add(vertex->Adj_N, parent_adj);
@@ -497,6 +521,8 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
                                if (listnode_lookup(vertex->Adj_N, parent_adj)
                                    == NULL)
                                        listnode_add(vertex->Adj_N, parent_adj);
+                       if (spftree->hopcount_metric)
+                               vertex_update_firsthops(vertex, parent);
                        /*      2) */
                        if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
                                remove_excess_adjs(vertex->Adj_N);
@@ -576,6 +602,9 @@ lspfragloop:
                        for (r = (struct isis_oldstyle_reach *)
                                         lsp->tlvs->oldstyle_reach.head;
                             r; r = r->next) {
+                               if (fabricd)
+                                       continue;
+
                                /* C.2.6 a) */
                                /* Two way connectivity */
                                if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN))
@@ -620,7 +649,7 @@ lspfragloop:
                }
        }
 
-       if (!pseudo_lsp && spftree->family == AF_INET
+       if (!fabricd && !pseudo_lsp && spftree->family == AF_INET
            && spftree->mtid == ISIS_MT_IPV4_UNICAST) {
                struct isis_item_list *reachs[] = {
                        &lsp->tlvs->oldstyle_ip_reach,
@@ -794,7 +823,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                        adjdb = circuit->u.bc.adjdb[spftree->level - 1];
                        isis_adj_build_up_list(adjdb, adj_list);
                        if (listcount(adj_list) == 0) {
-                               list_delete_and_null(&adj_list);
+                               list_delete(&adj_list);
                                if (isis->debugs & DEBUG_SPF_EVENTS)
                                        zlog_debug(
                                                "ISIS-Spf: no L%d adjacencies on circuit %s",
@@ -840,10 +869,8 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                                        [spftree->level - 1],
                                                parent);
                                        lsp = lsp_search(
-                                               lsp_id,
-                                               spftree->area
-                                                       ->lspdb[spftree->level
-                                                               - 1]);
+                                               &spftree->area->lspdb[spftree->level- 1],
+                                               lsp_id);
                                        if (lsp == NULL
                                            || lsp->hdr.rem_lifetime == 0)
                                                zlog_warn(
@@ -857,10 +884,10 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                case ISIS_SYSTYPE_UNKNOWN:
                                default:
                                        zlog_warn(
-                                               "isis_spf_preload_tent unknow adj type");
+                                               "isis_spf_preload_tent unknown adj type");
                                }
                        }
-                       list_delete_and_null(&adj_list);
+                       list_delete(&adj_list);
                        /*
                         * Add the pseudonode
                         */
@@ -893,8 +920,8 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                continue;
                        }
                        lsp = lsp_search(
-                               lsp_id,
-                               spftree->area->lspdb[spftree->level - 1]);
+                               &spftree->area->lspdb[spftree->level - 1],
+                               lsp_id);
                        if (lsp == NULL || lsp->hdr.rem_lifetime == 0) {
                                zlog_warn(
                                        "ISIS-Spf: No lsp (%p) found from root "
@@ -1038,7 +1065,8 @@ static void isis_spf_loop(struct isis_spftree *spftree,
                lsp = lsp_for_vertex(spftree, vertex);
                if (!lsp) {
                        zlog_warn("ISIS-Spf: No LSP found for %s",
-                                 rawlspid_print(vertex->N.id)); /* FIXME */
+                                 isis_format_id(vertex->N.id,
+                                                sizeof(vertex->N.id)));
                        continue;
                }
 
@@ -1062,7 +1090,8 @@ struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
                isis_spf_preload_tent(spftree, sysid, root);
        } else {
                isis_vertex_queue_insert(&spftree->tents, isis_vertex_new(
-                                        sysid, VTYPE_NONPSEUDO_TE_IS));
+                                        spftree, sysid,
+                                        VTYPE_NONPSEUDO_TE_IS));
        }
 
        isis_spf_loop(spftree, sysid);
@@ -1216,7 +1245,8 @@ static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level)
        return run;
 }
 
-int isis_spf_schedule(struct isis_area *area, int level)
+int _isis_spf_schedule(struct isis_area *area, int level,
+                      const char *func, const char *file, int line)
 {
        struct isis_spftree *spftree = area->spftree[SPFTREE_IPV4][level - 1];
        time_t now = monotime(NULL);
@@ -1225,10 +1255,12 @@ int isis_spf_schedule(struct isis_area *area, int level)
        assert(diff >= 0);
        assert(area->is_type & level);
 
-       if (isis->debugs & DEBUG_SPF_EVENTS)
+       if (isis->debugs & DEBUG_SPF_EVENTS) {
                zlog_debug(
-                       "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago",
-                       area->area_tag, level, diff);
+                       "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago"
+                       " Caller: %s %s:%d",
+                       area->area_tag, level, diff, func, file, line);
+       }
 
        if (area->spf_delay_ietf[level - 1]) {
                /* Need to call schedule function also if spf delay is running
@@ -1436,7 +1468,7 @@ DEFUN (show_isis_topology,
        return CMD_SUCCESS;
 }
 
-void isis_spf_cmds_init()
+void isis_spf_cmds_init(void)
 {
        install_element(VIEW_NODE, &show_isis_topology_cmd);
 }