blob: 9b37406d561a4e2e1619b15901ca11be6a4e98ef [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "memory.h"
25#include "log.h"
26#include "command.h"
hasso508e53e2004-05-18 18:57:06 +000027#include "prefix.h"
28#include "table.h"
hasso049207c2004-08-04 20:02:13 +000029#include "vty.h"
paul718e3742002-12-13 20:15:29 +000030
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
paul718e3742002-12-13 20:15:29 +000033#include "ospf6_lsdb.h"
hasso049207c2004-08-04 20:02:13 +000034#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000035
paul718e3742002-12-13 20:15:29 +000036struct ospf6_lsdb *
hasso6452df02004-08-15 05:52:07 +000037ospf6_lsdb_create (void *data)
paul718e3742002-12-13 20:15:29 +000038{
39 struct ospf6_lsdb *lsdb;
40
41 lsdb = XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb));
42 if (lsdb == NULL)
43 {
44 zlog_warn ("Can't malloc lsdb");
45 return NULL;
46 }
47 memset (lsdb, 0, sizeof (struct ospf6_lsdb));
48
hasso6452df02004-08-15 05:52:07 +000049 lsdb->data = data;
paul718e3742002-12-13 20:15:29 +000050 lsdb->table = route_table_init ();
51 return lsdb;
52}
53
54void
55ospf6_lsdb_delete (struct ospf6_lsdb *lsdb)
56{
57 ospf6_lsdb_remove_all (lsdb);
58 route_table_finish (lsdb->table);
59 XFREE (MTYPE_OSPF6_LSDB, lsdb);
60}
61
62static void
hasso508e53e2004-05-18 18:57:06 +000063ospf6_lsdb_set_key (struct prefix_ipv6 *key, void *value, int len)
paul718e3742002-12-13 20:15:29 +000064{
hasso508e53e2004-05-18 18:57:06 +000065 assert (key->prefixlen % 8 == 0);
paul718e3742002-12-13 20:15:29 +000066
hasso508e53e2004-05-18 18:57:06 +000067 memcpy ((caddr_t) &key->prefix + key->prefixlen / 8,
68 (caddr_t) value, len);
paul718e3742002-12-13 20:15:29 +000069 key->family = AF_INET6;
hasso508e53e2004-05-18 18:57:06 +000070 key->prefixlen += len * 8;
paul718e3742002-12-13 20:15:29 +000071}
72
hasso508e53e2004-05-18 18:57:06 +000073#ifndef NDEBUG
74static void
75_lsdb_count_assert (struct ospf6_lsdb *lsdb)
76{
77 struct ospf6_lsa *debug;
78 int num = 0;
79 for (debug = ospf6_lsdb_head (lsdb); debug;
80 debug = ospf6_lsdb_next (debug))
81 num++;
82
83 if (num == lsdb->count)
84 return;
85
86 if (IS_OSPF6_DEBUG_LSA (DATABASE))
87 {
88 zlog_info ("PANIC !! lsdb[%p]->count = %d, real = %d",
89 lsdb, lsdb->count, num);
90 for (debug = ospf6_lsdb_head (lsdb); debug;
91 debug = ospf6_lsdb_next (debug))
92 zlog_info ("%p %p %s", debug->prev, debug->next, debug->name);
93 zlog_info ("DUMP END");
94 }
95 assert (num == lsdb->count);
96}
97#define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
98#else /*NDEBUG*/
99#define ospf6_lsdb_count_assert(t) ((void) 0)
100#endif /*NDEBUG*/
101
paul718e3742002-12-13 20:15:29 +0000102void
103ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
104{
paul718e3742002-12-13 20:15:29 +0000105 struct prefix_ipv6 key;
hasso508e53e2004-05-18 18:57:06 +0000106 struct route_node *current, *nextnode, *prevnode;
107 struct ospf6_lsa *next, *prev, *old = NULL;
paul718e3742002-12-13 20:15:29 +0000108
hasso508e53e2004-05-18 18:57:06 +0000109 memset (&key, 0, sizeof (key));
110 ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
111 ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
112 sizeof (lsa->header->adv_router));
113 ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
paul718e3742002-12-13 20:15:29 +0000114
hasso508e53e2004-05-18 18:57:06 +0000115 current = route_node_get (lsdb->table, (struct prefix *) &key);
116 old = current->info;
117 current->info = lsa;
paul718e3742002-12-13 20:15:29 +0000118 ospf6_lsa_lock (lsa);
119
120 if (old)
hasso508e53e2004-05-18 18:57:06 +0000121 {
122 if (old->prev)
123 old->prev->next = lsa;
124 if (old->next)
125 old->next->prev = lsa;
126 lsa->next = old->next;
127 lsa->prev = old->prev;
128 }
paul718e3742002-12-13 20:15:29 +0000129 else
hasso508e53e2004-05-18 18:57:06 +0000130 {
131 /* next link */
132 nextnode = current;
133 route_lock_node (nextnode);
134 do {
135 nextnode = route_next (nextnode);
136 } while (nextnode && nextnode->info == NULL);
137 if (nextnode == NULL)
138 lsa->next = NULL;
139 else
140 {
141 next = nextnode->info;
142 lsa->next = next;
143 next->prev = lsa;
144 route_unlock_node (nextnode);
145 }
146
147 /* prev link */
148 prevnode = current;
149 route_lock_node (prevnode);
150 do {
151 prevnode = route_prev (prevnode);
152 } while (prevnode && prevnode->info == NULL);
153 if (prevnode == NULL)
154 lsa->prev = NULL;
155 else
156 {
157 prev = prevnode->info;
158 lsa->prev = prev;
159 prev->next = lsa;
160 route_unlock_node (prevnode);
161 }
162
163 lsdb->count++;
164 }
165
166 if (old)
167 {
168 if (OSPF6_LSA_IS_CHANGED (old, lsa))
169 {
170 if (OSPF6_LSA_IS_MAXAGE (lsa))
171 {
172 if (lsdb->hook_remove)
173 {
174 (*lsdb->hook_remove) (old);
175 (*lsdb->hook_remove) (lsa);
176 }
177 }
178 else
179 {
180 if (lsdb->hook_remove)
181 (*lsdb->hook_remove) (old);
182 if (lsdb->hook_add)
183 (*lsdb->hook_add) (lsa);
184 }
185 }
186 }
187 else if (OSPF6_LSA_IS_MAXAGE (lsa))
188 {
189 if (lsdb->hook_remove)
190 (*lsdb->hook_remove) (lsa);
191 }
192 else
193 {
194 if (lsdb->hook_add)
195 (*lsdb->hook_add) (lsa);
196 }
197
198 if (old)
199 ospf6_lsa_unlock (old);
200
201 ospf6_lsdb_count_assert (lsdb);
paul718e3742002-12-13 20:15:29 +0000202}
203
204void
205ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
206{
hasso508e53e2004-05-18 18:57:06 +0000207 struct route_node *node;
paul718e3742002-12-13 20:15:29 +0000208 struct prefix_ipv6 key;
paul718e3742002-12-13 20:15:29 +0000209
hasso508e53e2004-05-18 18:57:06 +0000210 memset (&key, 0, sizeof (key));
211 ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
212 ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
213 sizeof (lsa->header->adv_router));
214 ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
paul718e3742002-12-13 20:15:29 +0000215
hasso508e53e2004-05-18 18:57:06 +0000216 node = route_node_lookup (lsdb->table, (struct prefix *) &key);
217 assert (node && node->info == lsa);
paul718e3742002-12-13 20:15:29 +0000218
hasso508e53e2004-05-18 18:57:06 +0000219 if (lsa->prev)
220 lsa->prev->next = lsa->next;
221 if (lsa->next)
222 lsa->next->prev = lsa->prev;
paul718e3742002-12-13 20:15:29 +0000223
hasso508e53e2004-05-18 18:57:06 +0000224 node->info = NULL;
paul718e3742002-12-13 20:15:29 +0000225 lsdb->count--;
paul718e3742002-12-13 20:15:29 +0000226
hasso508e53e2004-05-18 18:57:06 +0000227 if (lsdb->hook_remove)
228 (*lsdb->hook_remove) (lsa);
paul718e3742002-12-13 20:15:29 +0000229
hasso508e53e2004-05-18 18:57:06 +0000230 ospf6_lsa_unlock (lsa);
231 route_unlock_node (node);
hasso6452df02004-08-15 05:52:07 +0000232
hasso508e53e2004-05-18 18:57:06 +0000233 ospf6_lsdb_count_assert (lsdb);
paul718e3742002-12-13 20:15:29 +0000234}
235
236struct ospf6_lsa *
237ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
hasso508e53e2004-05-18 18:57:06 +0000238 struct ospf6_lsdb *lsdb)
paul718e3742002-12-13 20:15:29 +0000239{
hasso508e53e2004-05-18 18:57:06 +0000240 struct route_node *node;
241 struct prefix_ipv6 key;
paul718e3742002-12-13 20:15:29 +0000242
hasso508e53e2004-05-18 18:57:06 +0000243 if (lsdb == NULL)
244 return NULL;
paul718e3742002-12-13 20:15:29 +0000245
hasso508e53e2004-05-18 18:57:06 +0000246 memset (&key, 0, sizeof (key));
247 ospf6_lsdb_set_key (&key, &type, sizeof (type));
248 ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
249 ospf6_lsdb_set_key (&key, &id, sizeof (id));
paul718e3742002-12-13 20:15:29 +0000250
hasso508e53e2004-05-18 18:57:06 +0000251 node = route_node_lookup (lsdb->table, (struct prefix *) &key);
252 if (node == NULL || node->info == NULL)
253 return NULL;
254 return (struct ospf6_lsa *) node->info;
paul718e3742002-12-13 20:15:29 +0000255}
256
hasso508e53e2004-05-18 18:57:06 +0000257/* Iteration function */
258struct ospf6_lsa *
259ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
paul718e3742002-12-13 20:15:29 +0000260{
hasso508e53e2004-05-18 18:57:06 +0000261 struct route_node *node;
paul718e3742002-12-13 20:15:29 +0000262
hasso508e53e2004-05-18 18:57:06 +0000263 node = route_top (lsdb->table);
264 if (node == NULL)
265 return NULL;
paul718e3742002-12-13 20:15:29 +0000266
hasso508e53e2004-05-18 18:57:06 +0000267 /* skip to the existing lsdb entry */
268 while (node && node->info == NULL)
269 node = route_next (node);
270 if (node == NULL)
271 return NULL;
272
273 route_unlock_node (node);
274 if (node->info)
275 ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
276 return (struct ospf6_lsa *) node->info;
277}
278
279struct ospf6_lsa *
280ospf6_lsdb_next (struct ospf6_lsa *lsa)
281{
282 struct ospf6_lsa *next = lsa->next;
283
284 ospf6_lsa_unlock (lsa);
285 if (next)
286 ospf6_lsa_lock (next);
287
288 return next;
289}
290
291/* Macro version of check_bit (). */
292#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
293
294struct ospf6_lsa *
295ospf6_lsdb_type_router_head (u_int16_t type, u_int32_t adv_router,
296 struct ospf6_lsdb *lsdb)
297{
298 struct route_node *node;
299 struct prefix_ipv6 key;
300 struct ospf6_lsa *lsa;
301
302 memset (&key, 0, sizeof (key));
303 ospf6_lsdb_set_key (&key, &type, sizeof (type));
304 ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
305
306 node = lsdb->table->top;
307
308 /* Walk down tree. */
309 while (node && node->p.prefixlen <= key.prefixlen &&
310 prefix_match (&node->p, (struct prefix *) &key))
311 node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
312
313 if (node)
314 route_lock_node (node);
315 while (node && node->info == NULL)
316 node = route_next (node);
317
318 if (node == NULL)
319 return NULL;
320 else
321 route_unlock_node (node);
322
323 if (! prefix_match ((struct prefix *) &key, &node->p))
324 return NULL;
325
326 lsa = node->info;
327 ospf6_lsa_lock (lsa);
328
329 return lsa;
330}
331
332struct ospf6_lsa *
333ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
334 struct ospf6_lsa *lsa)
335{
336 struct ospf6_lsa *next = lsa->next;
337
338 if (next)
paul718e3742002-12-13 20:15:29 +0000339 {
hasso508e53e2004-05-18 18:57:06 +0000340 if (next->header->type != type ||
341 next->header->adv_router != adv_router)
342 next = NULL;
paul718e3742002-12-13 20:15:29 +0000343 }
344
hasso508e53e2004-05-18 18:57:06 +0000345 if (next)
346 ospf6_lsa_lock (next);
347 ospf6_lsa_unlock (lsa);
348 return next;
349}
paul718e3742002-12-13 20:15:29 +0000350
hasso508e53e2004-05-18 18:57:06 +0000351struct ospf6_lsa *
352ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
353{
354 struct route_node *node;
355 struct prefix_ipv6 key;
356 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000357
hasso508e53e2004-05-18 18:57:06 +0000358 memset (&key, 0, sizeof (key));
359 ospf6_lsdb_set_key (&key, &type, sizeof (type));
paul718e3742002-12-13 20:15:29 +0000360
hasso508e53e2004-05-18 18:57:06 +0000361 /* Walk down tree. */
362 node = lsdb->table->top;
363 while (node && node->p.prefixlen <= key.prefixlen &&
364 prefix_match (&node->p, (struct prefix *) &key))
365 node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
paul718e3742002-12-13 20:15:29 +0000366
hasso508e53e2004-05-18 18:57:06 +0000367 if (node)
368 route_lock_node (node);
369 while (node && node->info == NULL)
370 node = route_next (node);
paul718e3742002-12-13 20:15:29 +0000371
hasso508e53e2004-05-18 18:57:06 +0000372 if (node == NULL)
373 return NULL;
374 else
375 route_unlock_node (node);
paul718e3742002-12-13 20:15:29 +0000376
hasso508e53e2004-05-18 18:57:06 +0000377 if (! prefix_match ((struct prefix *) &key, &node->p))
378 return NULL;
379
380 lsa = node->info;
381 ospf6_lsa_lock (lsa);
382
383 return lsa;
384}
385
386struct ospf6_lsa *
387ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
388{
389 struct ospf6_lsa *next = lsa->next;
390
391 if (next)
392 {
393 if (next->header->type != type)
394 next = NULL;
395 }
396
397 if (next)
398 ospf6_lsa_lock (next);
399 ospf6_lsa_unlock (lsa);
400 return next;
paul718e3742002-12-13 20:15:29 +0000401}
402
403void
404ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
405{
paul718e3742002-12-13 20:15:29 +0000406 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000407 for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
408 ospf6_lsdb_remove (lsa, lsdb);
paul718e3742002-12-13 20:15:29 +0000409}
410
hasso049207c2004-08-04 20:02:13 +0000411void
412ospf6_lsdb_show (struct vty *vty, int level,
413 u_int16_t *type, u_int32_t *id, u_int32_t *adv_router,
414 struct ospf6_lsdb *lsdb)
415{
416 struct ospf6_lsa *lsa;
417 void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
418
419 if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
420 showfunc = ospf6_lsa_show_summary;
421 else if (level == OSPF6_LSDB_SHOW_LEVEL_DETAIL)
422 showfunc = ospf6_lsa_show;
423 else if (level == OSPF6_LSDB_SHOW_LEVEL_INTERNAL)
424 showfunc = ospf6_lsa_show_internal;
425 else if (level == OSPF6_LSDB_SHOW_LEVEL_DUMP)
426 showfunc = ospf6_lsa_show_dump;
427
428 if (type && id && adv_router)
429 {
430 lsa = ospf6_lsdb_lookup (*type, *id, *adv_router, lsdb);
431 if (lsa)
432 {
433 if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
434 ospf6_lsa_show (vty, lsa);
435 else
436 (*showfunc) (vty, lsa);
437 }
438 return;
439 }
440
441 if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
442 ospf6_lsa_show_summary_header (vty);
443
444 if (type && adv_router)
445 lsa = ospf6_lsdb_type_router_head (*type, *adv_router, lsdb);
446 else if (type)
447 lsa = ospf6_lsdb_type_head (*type, lsdb);
448 else
449 lsa = ospf6_lsdb_head (lsdb);
450 while (lsa)
451 {
452 if ((! adv_router || lsa->header->adv_router == *adv_router) &&
453 (! id || lsa->header->id == *id))
454 (*showfunc) (vty, lsa);
455
456 if (type && adv_router)
457 lsa = ospf6_lsdb_type_router_next (*type, *adv_router, lsa);
458 else if (type)
459 lsa = ospf6_lsdb_type_next (*type, lsa);
460 else
461 lsa = ospf6_lsdb_next (lsa);
462 }
463}
464
465/* Decide new Link State ID to originate.
466 note return value is network byte order */
467u_int32_t
468ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
469 struct ospf6_lsdb *lsdb)
470{
471 struct ospf6_lsa *lsa;
472 u_int32_t id = 1;
473
474 for (lsa = ospf6_lsdb_type_router_head (type, adv_router, lsdb); lsa;
475 lsa = ospf6_lsdb_type_router_next (type, adv_router, lsa))
476 {
477 if (ntohl (lsa->header->id) < id)
478 continue;
479 if (ntohl (lsa->header->id) > id)
hasso6452df02004-08-15 05:52:07 +0000480 break;
hasso049207c2004-08-04 20:02:13 +0000481 id++;
482 }
483
484 return ((u_int32_t) htonl (id));
485}
486
487/* Decide new LS sequence number to originate.
488 note return value is network byte order */
489u_int32_t
490ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router,
491 struct ospf6_lsdb *lsdb)
492{
493 struct ospf6_lsa *lsa;
494 signed long seqnum = 0;
495
496 /* if current database copy not found, return InitialSequenceNumber */
497 lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
498 if (lsa == NULL)
499 seqnum = INITIAL_SEQUENCE_NUMBER;
500 else
501 seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
502
503 return ((u_int32_t) htonl (seqnum));
504}
505
paul718e3742002-12-13 20:15:29 +0000506