2 * IS-IS Rout(e)ing protocol - isis_spf_private.h
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
7 * Copyright (C) 2017 Christian Franke <chris@opensourcerouting.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along
20 * with this program; see the file COPYING; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #ifndef ISIS_SPF_PRIVATE_H
24 #define ISIS_SPF_PRIVATE_H
29 #include "lib_errors.h"
35 VTYPE_NONPSEUDO_TE_IS
,
37 VTYPE_IPREACH_INTERNAL
,
38 VTYPE_IPREACH_EXTERNAL
,
40 VTYPE_IP6REACH_INTERNAL
,
41 VTYPE_IP6REACH_EXTERNAL
44 #define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS)
45 #define VTYPE_ES(t) ((t) == VTYPE_ES)
46 #define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
50 struct prefix_ipv6 src
;
54 * Triple <N, d(N), {Adj(N)}>
57 uint8_t id
[ISIS_SYS_ID_LEN
+ 1];
58 struct prefix_pair ip
;
63 uint32_t d_N
; /* d(N) Distance from this IS */
64 uint16_t depth
; /* The depth in the imaginary tree */
65 struct list
*Adj_N
; /* {Adj(N)} next hop or neighbor list */
66 struct list
*parents
; /* list of parents for ECMP */
67 struct hash
*firsthops
; /* first two hops to neighbor */
68 uint64_t insert_counter
;
71 /* Vertex Queue and associated functions */
73 struct isis_vertex_queue
{
75 struct skiplist
*slist
;
79 uint64_t insert_counter
;
82 __attribute__((__unused__
))
83 static unsigned isis_vertex_queue_hash_key(void *vp
)
85 struct isis_vertex
*vertex
= vp
;
87 if (VTYPE_IP(vertex
->type
)) {
90 key
= prefix_hash_key(&vertex
->N
.ip
.dest
);
91 key
= jhash_1word(prefix_hash_key(&vertex
->N
.ip
.src
), key
);
95 return jhash(vertex
->N
.id
, ISIS_SYS_ID_LEN
+ 1, 0x55aa5a5a);
98 __attribute__((__unused__
))
99 static int isis_vertex_queue_hash_cmp(const void *a
, const void *b
)
101 const struct isis_vertex
*va
= a
, *vb
= b
;
103 if (va
->type
!= vb
->type
)
106 if (VTYPE_IP(va
->type
)) {
107 if (prefix_cmp(&va
->N
.ip
.dest
, &vb
->N
.ip
.dest
))
110 return prefix_cmp((struct prefix
*)&va
->N
.ip
.src
,
111 (struct prefix
*)&vb
->N
.ip
.src
) == 0;
114 return memcmp(va
->N
.id
, vb
->N
.id
, ISIS_SYS_ID_LEN
+ 1) == 0;
118 * Compares vertizes for sorting in the TENT list. Returns true
119 * if candidate should be considered before current, false otherwise.
121 __attribute__((__unused__
))
122 static int isis_vertex_queue_tent_cmp(void *a
, void *b
)
124 struct isis_vertex
*va
= a
;
125 struct isis_vertex
*vb
= b
;
127 if (va
->d_N
< vb
->d_N
)
130 if (va
->d_N
> vb
->d_N
)
133 if (va
->type
< vb
->type
)
136 if (va
->type
> vb
->type
)
139 if (va
->insert_counter
< vb
->insert_counter
)
142 if (va
->insert_counter
> vb
->insert_counter
)
148 __attribute__((__unused__
))
149 static struct skiplist
*isis_vertex_queue_skiplist(void)
151 return skiplist_new(0, isis_vertex_queue_tent_cmp
, NULL
);
154 __attribute__((__unused__
))
155 static void isis_vertex_queue_init(struct isis_vertex_queue
*queue
,
156 const char *name
, bool ordered
)
159 queue
->insert_counter
= 1;
160 queue
->l
.slist
= isis_vertex_queue_skiplist();
162 queue
->insert_counter
= 0;
163 queue
->l
.list
= list_new();
165 queue
->hash
= hash_create(isis_vertex_queue_hash_key
,
166 isis_vertex_queue_hash_cmp
, name
);
169 __attribute__((__unused__
))
170 static void isis_vertex_del(struct isis_vertex
*vertex
)
172 list_delete_and_null(&vertex
->Adj_N
);
173 list_delete_and_null(&vertex
->parents
);
174 if (vertex
->firsthops
) {
175 hash_clean(vertex
->firsthops
, NULL
);
176 hash_free(vertex
->firsthops
);
177 vertex
->firsthops
= NULL
;
180 memset(vertex
, 0, sizeof(struct isis_vertex
));
181 XFREE(MTYPE_ISIS_VERTEX
, vertex
);
184 __attribute__((__unused__
))
185 static void isis_vertex_queue_clear(struct isis_vertex_queue
*queue
)
187 hash_clean(queue
->hash
, NULL
);
189 if (queue
->insert_counter
) {
190 struct isis_vertex
*vertex
;
191 while (0 == skiplist_first(queue
->l
.slist
, NULL
,
193 isis_vertex_del(vertex
);
194 skiplist_delete_first(queue
->l
.slist
);
196 queue
->insert_counter
= 1;
198 queue
->l
.list
->del
= (void (*)(void *))isis_vertex_del
;
199 list_delete_all_node(queue
->l
.list
);
200 queue
->l
.list
->del
= NULL
;
204 __attribute__((__unused__
))
205 static void isis_vertex_queue_free(struct isis_vertex_queue
*queue
)
207 isis_vertex_queue_clear(queue
);
209 hash_free(queue
->hash
);
212 if (queue
->insert_counter
) {
213 skiplist_free(queue
->l
.slist
);
214 queue
->l
.slist
= NULL
;
216 list_delete_and_null(&queue
->l
.list
);
219 __attribute__((__unused__
))
220 static unsigned int isis_vertex_queue_count(struct isis_vertex_queue
*queue
)
222 return hashcount(queue
->hash
);
225 __attribute__((__unused__
))
226 static void isis_vertex_queue_append(struct isis_vertex_queue
*queue
,
227 struct isis_vertex
*vertex
)
229 assert(!queue
->insert_counter
);
231 listnode_add(queue
->l
.list
, vertex
);
233 struct isis_vertex
*inserted
;
235 inserted
= hash_get(queue
->hash
, vertex
, hash_alloc_intern
);
236 assert(inserted
== vertex
);
239 __attribute__((__unused__
))
240 static struct isis_vertex
*isis_vertex_queue_last(struct isis_vertex_queue
*queue
)
242 assert(!queue
->insert_counter
);
244 return listgetdata(listtail(queue
->l
.list
));
247 __attribute__((__unused__
))
248 static void isis_vertex_queue_insert(struct isis_vertex_queue
*queue
,
249 struct isis_vertex
*vertex
)
251 assert(queue
->insert_counter
);
252 vertex
->insert_counter
= queue
->insert_counter
++;
253 assert(queue
->insert_counter
!= (uint64_t)-1);
255 skiplist_insert(queue
->l
.slist
, vertex
, vertex
);
257 struct isis_vertex
*inserted
;
258 inserted
= hash_get(queue
->hash
, vertex
, hash_alloc_intern
);
259 assert(inserted
== vertex
);
262 __attribute__((__unused__
))
263 static struct isis_vertex
*
264 isis_vertex_queue_pop(struct isis_vertex_queue
*queue
)
266 assert(queue
->insert_counter
);
268 struct isis_vertex
*rv
;
270 if (skiplist_first(queue
->l
.slist
, NULL
, (void **)&rv
))
273 skiplist_delete_first(queue
->l
.slist
);
274 hash_release(queue
->hash
, rv
);
279 __attribute__((__unused__
))
280 static void isis_vertex_queue_delete(struct isis_vertex_queue
*queue
,
281 struct isis_vertex
*vertex
)
283 assert(queue
->insert_counter
);
285 skiplist_delete(queue
->l
.slist
, vertex
, vertex
);
286 hash_release(queue
->hash
, vertex
);
289 #define ALL_QUEUE_ELEMENTS_RO(queue, node, data) \
290 ALL_LIST_ELEMENTS_RO((queue)->l.list, node, data)
292 /* End of vertex queue definitions */
294 struct isis_spftree
{
295 struct isis_vertex_queue paths
; /* the SPT */
296 struct isis_vertex_queue tents
; /* TENT */
297 struct route_table
*route_table
;
298 struct isis_area
*area
; /* back pointer to area */
299 unsigned int runcount
; /* number of runs since uptime */
300 time_t last_run_timestamp
; /* last run timestamp as wall time for display */
301 time_t last_run_monotime
; /* last run as monotime for scheduling */
302 time_t last_run_duration
; /* last run duration in msec */
307 enum spf_tree_id tree_id
;
308 bool hopcount_metric
;
311 __attribute__((__unused__
))
312 static void isis_vertex_id_init(struct isis_vertex
*vertex
, const union isis_N
*n
,
313 enum vertextype vtype
)
315 vertex
->type
= vtype
;
317 if (VTYPE_IS(vtype
) || VTYPE_ES(vtype
)) {
318 memcpy(vertex
->N
.id
, n
->id
, ISIS_SYS_ID_LEN
+ 1);
319 } else if (VTYPE_IP(vtype
)) {
320 memcpy(&vertex
->N
.ip
, &n
->ip
, sizeof(n
->ip
));
322 flog_err(LIB_ERR_DEVELOPMENT
, "Unknown Vertex Type");
326 __attribute__((__unused__
))
327 static struct isis_vertex
*isis_find_vertex(struct isis_vertex_queue
*queue
,
329 enum vertextype vtype
)
331 struct isis_vertex querier
;
333 isis_vertex_id_init(&querier
, n
, vtype
);
334 return hash_lookup(queue
->hash
, &querier
);
337 __attribute__((__unused__
))
338 static struct isis_lsp
*lsp_for_vertex(struct isis_spftree
*spftree
,
339 struct isis_vertex
*vertex
)
341 uint8_t lsp_id
[ISIS_SYS_ID_LEN
+ 2];
343 assert(VTYPE_IS(vertex
->type
));
345 memcpy(lsp_id
, vertex
->N
.id
, ISIS_SYS_ID_LEN
+ 1);
346 LSP_FRAGMENT(lsp_id
) = 0;
348 dict_t
*lspdb
= spftree
->area
->lspdb
[spftree
->level
- 1];
349 struct isis_lsp
*lsp
= lsp_search(lsp_id
, lspdb
);
351 if (lsp
&& lsp
->hdr
.rem_lifetime
!= 0)