blob: 97a278e9d0f33679e926b97c82255fac5e37b7cd [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"
paul718e3742002-12-13 20:15:29 +000029
hasso508e53e2004-05-18 18:57:06 +000030#include "ospf6d.h"
31#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
paul718e3742002-12-13 20:15:29 +000033#include "ospf6_lsdb.h"
34
paul718e3742002-12-13 20:15:29 +000035struct ospf6_lsdb *
36ospf6_lsdb_create ()
37{
38 struct ospf6_lsdb *lsdb;
39
40 lsdb = XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb));
41 if (lsdb == NULL)
42 {
43 zlog_warn ("Can't malloc lsdb");
44 return NULL;
45 }
46 memset (lsdb, 0, sizeof (struct ospf6_lsdb));
47
48 lsdb->table = route_table_init ();
49 return lsdb;
50}
51
52void
53ospf6_lsdb_delete (struct ospf6_lsdb *lsdb)
54{
55 ospf6_lsdb_remove_all (lsdb);
56 route_table_finish (lsdb->table);
57 XFREE (MTYPE_OSPF6_LSDB, lsdb);
58}
59
60static void
hasso508e53e2004-05-18 18:57:06 +000061ospf6_lsdb_set_key (struct prefix_ipv6 *key, void *value, int len)
paul718e3742002-12-13 20:15:29 +000062{
hasso508e53e2004-05-18 18:57:06 +000063 assert (key->prefixlen % 8 == 0);
paul718e3742002-12-13 20:15:29 +000064
hasso508e53e2004-05-18 18:57:06 +000065 memcpy ((caddr_t) &key->prefix + key->prefixlen / 8,
66 (caddr_t) value, len);
paul718e3742002-12-13 20:15:29 +000067 key->family = AF_INET6;
hasso508e53e2004-05-18 18:57:06 +000068 key->prefixlen += len * 8;
paul718e3742002-12-13 20:15:29 +000069}
70
hasso508e53e2004-05-18 18:57:06 +000071#ifndef NDEBUG
72static void
73_lsdb_count_assert (struct ospf6_lsdb *lsdb)
74{
75 struct ospf6_lsa *debug;
76 int num = 0;
77 for (debug = ospf6_lsdb_head (lsdb); debug;
78 debug = ospf6_lsdb_next (debug))
79 num++;
80
81 if (num == lsdb->count)
82 return;
83
84 if (IS_OSPF6_DEBUG_LSA (DATABASE))
85 {
86 zlog_info ("PANIC !! lsdb[%p]->count = %d, real = %d",
87 lsdb, lsdb->count, num);
88 for (debug = ospf6_lsdb_head (lsdb); debug;
89 debug = ospf6_lsdb_next (debug))
90 zlog_info ("%p %p %s", debug->prev, debug->next, debug->name);
91 zlog_info ("DUMP END");
92 }
93 assert (num == lsdb->count);
94}
95#define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
96#else /*NDEBUG*/
97#define ospf6_lsdb_count_assert(t) ((void) 0)
98#endif /*NDEBUG*/
99
paul718e3742002-12-13 20:15:29 +0000100void
101ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
102{
paul718e3742002-12-13 20:15:29 +0000103 struct prefix_ipv6 key;
hasso508e53e2004-05-18 18:57:06 +0000104 struct route_node *current, *nextnode, *prevnode;
105 struct ospf6_lsa *next, *prev, *old = NULL;
paul718e3742002-12-13 20:15:29 +0000106
hasso508e53e2004-05-18 18:57:06 +0000107 memset (&key, 0, sizeof (key));
108 ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
109 ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
110 sizeof (lsa->header->adv_router));
111 ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
paul718e3742002-12-13 20:15:29 +0000112
hasso508e53e2004-05-18 18:57:06 +0000113 current = route_node_get (lsdb->table, (struct prefix *) &key);
114 old = current->info;
115 current->info = lsa;
paul718e3742002-12-13 20:15:29 +0000116 ospf6_lsa_lock (lsa);
117
118 if (old)
hasso508e53e2004-05-18 18:57:06 +0000119 {
120 if (old->prev)
121 old->prev->next = lsa;
122 if (old->next)
123 old->next->prev = lsa;
124 lsa->next = old->next;
125 lsa->prev = old->prev;
126 }
paul718e3742002-12-13 20:15:29 +0000127 else
hasso508e53e2004-05-18 18:57:06 +0000128 {
129 /* next link */
130 nextnode = current;
131 route_lock_node (nextnode);
132 do {
133 nextnode = route_next (nextnode);
134 } while (nextnode && nextnode->info == NULL);
135 if (nextnode == NULL)
136 lsa->next = NULL;
137 else
138 {
139 next = nextnode->info;
140 lsa->next = next;
141 next->prev = lsa;
142 route_unlock_node (nextnode);
143 }
144
145 /* prev link */
146 prevnode = current;
147 route_lock_node (prevnode);
148 do {
149 prevnode = route_prev (prevnode);
150 } while (prevnode && prevnode->info == NULL);
151 if (prevnode == NULL)
152 lsa->prev = NULL;
153 else
154 {
155 prev = prevnode->info;
156 lsa->prev = prev;
157 prev->next = lsa;
158 route_unlock_node (prevnode);
159 }
160
161 lsdb->count++;
162 }
163
164 if (old)
165 {
166 if (OSPF6_LSA_IS_CHANGED (old, lsa))
167 {
168 if (OSPF6_LSA_IS_MAXAGE (lsa))
169 {
170 if (lsdb->hook_remove)
171 {
172 (*lsdb->hook_remove) (old);
173 (*lsdb->hook_remove) (lsa);
174 }
175 }
176 else
177 {
178 if (lsdb->hook_remove)
179 (*lsdb->hook_remove) (old);
180 if (lsdb->hook_add)
181 (*lsdb->hook_add) (lsa);
182 }
183 }
184 }
185 else if (OSPF6_LSA_IS_MAXAGE (lsa))
186 {
187 if (lsdb->hook_remove)
188 (*lsdb->hook_remove) (lsa);
189 }
190 else
191 {
192 if (lsdb->hook_add)
193 (*lsdb->hook_add) (lsa);
194 }
195
196 if (old)
197 ospf6_lsa_unlock (old);
198
199 ospf6_lsdb_count_assert (lsdb);
paul718e3742002-12-13 20:15:29 +0000200}
201
202void
203ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
204{
hasso508e53e2004-05-18 18:57:06 +0000205 struct route_node *node;
paul718e3742002-12-13 20:15:29 +0000206 struct prefix_ipv6 key;
paul718e3742002-12-13 20:15:29 +0000207
hasso508e53e2004-05-18 18:57:06 +0000208 memset (&key, 0, sizeof (key));
209 ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
210 ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
211 sizeof (lsa->header->adv_router));
212 ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
paul718e3742002-12-13 20:15:29 +0000213
hasso508e53e2004-05-18 18:57:06 +0000214 node = route_node_lookup (lsdb->table, (struct prefix *) &key);
215 assert (node && node->info == lsa);
paul718e3742002-12-13 20:15:29 +0000216
hasso508e53e2004-05-18 18:57:06 +0000217 if (lsa->prev)
218 lsa->prev->next = lsa->next;
219 if (lsa->next)
220 lsa->next->prev = lsa->prev;
paul718e3742002-12-13 20:15:29 +0000221
hasso508e53e2004-05-18 18:57:06 +0000222 node->info = NULL;
paul718e3742002-12-13 20:15:29 +0000223 lsdb->count--;
paul718e3742002-12-13 20:15:29 +0000224
hasso508e53e2004-05-18 18:57:06 +0000225 if (lsdb->hook_remove)
226 (*lsdb->hook_remove) (lsa);
paul718e3742002-12-13 20:15:29 +0000227
hasso508e53e2004-05-18 18:57:06 +0000228 ospf6_lsa_unlock (lsa);
229 route_unlock_node (node);
230 ospf6_lsdb_count_assert (lsdb);
paul718e3742002-12-13 20:15:29 +0000231}
232
233struct ospf6_lsa *
234ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
hasso508e53e2004-05-18 18:57:06 +0000235 struct ospf6_lsdb *lsdb)
paul718e3742002-12-13 20:15:29 +0000236{
hasso508e53e2004-05-18 18:57:06 +0000237 struct route_node *node;
238 struct prefix_ipv6 key;
paul718e3742002-12-13 20:15:29 +0000239
hasso508e53e2004-05-18 18:57:06 +0000240 if (lsdb == NULL)
241 return NULL;
paul718e3742002-12-13 20:15:29 +0000242
hasso508e53e2004-05-18 18:57:06 +0000243 memset (&key, 0, sizeof (key));
244 ospf6_lsdb_set_key (&key, &type, sizeof (type));
245 ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
246 ospf6_lsdb_set_key (&key, &id, sizeof (id));
paul718e3742002-12-13 20:15:29 +0000247
hasso508e53e2004-05-18 18:57:06 +0000248 node = route_node_lookup (lsdb->table, (struct prefix *) &key);
249 if (node == NULL || node->info == NULL)
250 return NULL;
251 return (struct ospf6_lsa *) node->info;
paul718e3742002-12-13 20:15:29 +0000252}
253
hasso508e53e2004-05-18 18:57:06 +0000254/* Iteration function */
255struct ospf6_lsa *
256ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
paul718e3742002-12-13 20:15:29 +0000257{
hasso508e53e2004-05-18 18:57:06 +0000258 struct route_node *node;
paul718e3742002-12-13 20:15:29 +0000259
hasso508e53e2004-05-18 18:57:06 +0000260 node = route_top (lsdb->table);
261 if (node == NULL)
262 return NULL;
paul718e3742002-12-13 20:15:29 +0000263
hasso508e53e2004-05-18 18:57:06 +0000264 /* skip to the existing lsdb entry */
265 while (node && node->info == NULL)
266 node = route_next (node);
267 if (node == NULL)
268 return NULL;
269
270 route_unlock_node (node);
271 if (node->info)
272 ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
273 return (struct ospf6_lsa *) node->info;
274}
275
276struct ospf6_lsa *
277ospf6_lsdb_next (struct ospf6_lsa *lsa)
278{
279 struct ospf6_lsa *next = lsa->next;
280
281 ospf6_lsa_unlock (lsa);
282 if (next)
283 ospf6_lsa_lock (next);
284
285 return next;
286}
287
288/* Macro version of check_bit (). */
289#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
290
291struct ospf6_lsa *
292ospf6_lsdb_type_router_head (u_int16_t type, u_int32_t adv_router,
293 struct ospf6_lsdb *lsdb)
294{
295 struct route_node *node;
296 struct prefix_ipv6 key;
297 struct ospf6_lsa *lsa;
298
299 memset (&key, 0, sizeof (key));
300 ospf6_lsdb_set_key (&key, &type, sizeof (type));
301 ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
302
303 node = lsdb->table->top;
304
305 /* Walk down tree. */
306 while (node && node->p.prefixlen <= key.prefixlen &&
307 prefix_match (&node->p, (struct prefix *) &key))
308 node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
309
310 if (node)
311 route_lock_node (node);
312 while (node && node->info == NULL)
313 node = route_next (node);
314
315 if (node == NULL)
316 return NULL;
317 else
318 route_unlock_node (node);
319
320 if (! prefix_match ((struct prefix *) &key, &node->p))
321 return NULL;
322
323 lsa = node->info;
324 ospf6_lsa_lock (lsa);
325
326 return lsa;
327}
328
329struct ospf6_lsa *
330ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
331 struct ospf6_lsa *lsa)
332{
333 struct ospf6_lsa *next = lsa->next;
334
335 if (next)
paul718e3742002-12-13 20:15:29 +0000336 {
hasso508e53e2004-05-18 18:57:06 +0000337 if (next->header->type != type ||
338 next->header->adv_router != adv_router)
339 next = NULL;
paul718e3742002-12-13 20:15:29 +0000340 }
341
hasso508e53e2004-05-18 18:57:06 +0000342 if (next)
343 ospf6_lsa_lock (next);
344 ospf6_lsa_unlock (lsa);
345 return next;
346}
paul718e3742002-12-13 20:15:29 +0000347
hasso508e53e2004-05-18 18:57:06 +0000348struct ospf6_lsa *
349ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
350{
351 struct route_node *node;
352 struct prefix_ipv6 key;
353 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000354
hasso508e53e2004-05-18 18:57:06 +0000355 memset (&key, 0, sizeof (key));
356 ospf6_lsdb_set_key (&key, &type, sizeof (type));
paul718e3742002-12-13 20:15:29 +0000357
hasso508e53e2004-05-18 18:57:06 +0000358 /* Walk down tree. */
359 node = lsdb->table->top;
360 while (node && node->p.prefixlen <= key.prefixlen &&
361 prefix_match (&node->p, (struct prefix *) &key))
362 node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
paul718e3742002-12-13 20:15:29 +0000363
hasso508e53e2004-05-18 18:57:06 +0000364 if (node)
365 route_lock_node (node);
366 while (node && node->info == NULL)
367 node = route_next (node);
paul718e3742002-12-13 20:15:29 +0000368
hasso508e53e2004-05-18 18:57:06 +0000369 if (node == NULL)
370 return NULL;
371 else
372 route_unlock_node (node);
paul718e3742002-12-13 20:15:29 +0000373
hasso508e53e2004-05-18 18:57:06 +0000374 if (! prefix_match ((struct prefix *) &key, &node->p))
375 return NULL;
376
377 lsa = node->info;
378 ospf6_lsa_lock (lsa);
379
380 return lsa;
381}
382
383struct ospf6_lsa *
384ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
385{
386 struct ospf6_lsa *next = lsa->next;
387
388 if (next)
389 {
390 if (next->header->type != type)
391 next = NULL;
392 }
393
394 if (next)
395 ospf6_lsa_lock (next);
396 ospf6_lsa_unlock (lsa);
397 return next;
paul718e3742002-12-13 20:15:29 +0000398}
399
400void
401ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
402{
paul718e3742002-12-13 20:15:29 +0000403 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000404 for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
405 ospf6_lsdb_remove (lsa, lsdb);
paul718e3742002-12-13 20:15:29 +0000406}
407
408