]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
508e53e2 | 2 | * Copyright (C) 2003 Yasuhiro Ohara |
718e3744 | 3 | * |
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 | * | |
896014f4 DL |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; see the file COPYING; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 19 | */ |
20 | ||
21 | #include <zebra.h> | |
22 | ||
23 | #include "memory.h" | |
24 | #include "log.h" | |
25 | #include "command.h" | |
508e53e2 | 26 | #include "prefix.h" |
27 | #include "table.h" | |
049207c3 | 28 | #include "vty.h" |
718e3744 | 29 | |
508e53e2 | 30 | #include "ospf6_proto.h" |
31 | #include "ospf6_lsa.h" | |
718e3744 | 32 | #include "ospf6_lsdb.h" |
c3c0ac83 | 33 | #include "ospf6_route.h" |
049207c3 | 34 | #include "ospf6d.h" |
c3c0ac83 | 35 | #include "bitfield.h" |
718e3744 | 36 | |
d62a17ae | 37 | struct ospf6_lsdb *ospf6_lsdb_create(void *data) |
718e3744 | 38 | { |
d62a17ae | 39 | struct ospf6_lsdb *lsdb; |
40 | ||
41 | lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb)); | |
d62a17ae | 42 | memset(lsdb, 0, sizeof(struct ospf6_lsdb)); |
43 | ||
44 | lsdb->data = data; | |
45 | lsdb->table = route_table_init(); | |
46 | return lsdb; | |
718e3744 | 47 | } |
48 | ||
d62a17ae | 49 | void ospf6_lsdb_delete(struct ospf6_lsdb *lsdb) |
718e3744 | 50 | { |
d62a17ae | 51 | if (lsdb != NULL) { |
52 | ospf6_lsdb_remove_all(lsdb); | |
53 | route_table_finish(lsdb->table); | |
54 | XFREE(MTYPE_OSPF6_LSDB, lsdb); | |
55 | } | |
718e3744 | 56 | } |
57 | ||
d62a17ae | 58 | static void ospf6_lsdb_set_key(struct prefix_ipv6 *key, const void *value, |
59 | int len) | |
718e3744 | 60 | { |
d62a17ae | 61 | assert(key->prefixlen % 8 == 0); |
718e3744 | 62 | |
d62a17ae | 63 | memcpy((caddr_t)&key->prefix + key->prefixlen / 8, (caddr_t)value, len); |
64 | key->family = AF_INET6; | |
65 | key->prefixlen += len * 8; | |
508e53e2 | 66 | } |
718e3744 | 67 | |
e39d0538 | 68 | #ifdef DEBUG |
d62a17ae | 69 | static void _lsdb_count_assert(struct ospf6_lsdb *lsdb) |
508e53e2 | 70 | { |
d62a17ae | 71 | struct ospf6_lsa *debug; |
72 | unsigned int num = 0; | |
73 | for (ALL_LSDB(lsdb, debug)) | |
74 | num++; | |
75 | ||
76 | if (num == lsdb->count) | |
77 | return; | |
78 | ||
79 | zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb, | |
80 | lsdb->count, num); | |
81 | for (ALL_LSDB(lsdb, debug)) | |
c811f101 | 82 | zlog_debug("%s lsdb[%p]", debug->name, debug->lsdb); |
d62a17ae | 83 | zlog_debug("DUMP END"); |
84 | ||
85 | assert(num == lsdb->count); | |
718e3744 | 86 | } |
508e53e2 | 87 | #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t)) |
d62a17ae | 88 | #else /*DEBUG*/ |
508e53e2 | 89 | #define ospf6_lsdb_count_assert(t) ((void) 0) |
e39d0538 | 90 | #endif /*DEBUG*/ |
718e3744 | 91 | |
d62a17ae | 92 | void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) |
718e3744 | 93 | { |
d62a17ae | 94 | struct prefix_ipv6 key; |
95 | struct route_node *current; | |
96 | struct ospf6_lsa *old = NULL; | |
97 | ||
98 | memset(&key, 0, sizeof(key)); | |
99 | ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type)); | |
100 | ospf6_lsdb_set_key(&key, &lsa->header->adv_router, | |
101 | sizeof(lsa->header->adv_router)); | |
102 | ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id)); | |
103 | ||
104 | current = route_node_get(lsdb->table, (struct prefix *)&key); | |
105 | old = current->info; | |
106 | current->info = lsa; | |
107 | lsa->rn = current; | |
108 | ospf6_lsa_lock(lsa); | |
109 | ||
110 | if (!old) { | |
111 | lsdb->count++; | |
112 | ||
113 | if (OSPF6_LSA_IS_MAXAGE(lsa)) { | |
114 | if (lsdb->hook_remove) | |
115 | (*lsdb->hook_remove)(lsa); | |
116 | } else { | |
117 | if (lsdb->hook_add) | |
118 | (*lsdb->hook_add)(lsa); | |
119 | } | |
120 | } else { | |
121 | if (OSPF6_LSA_IS_CHANGED(old, lsa)) { | |
122 | if (OSPF6_LSA_IS_MAXAGE(lsa)) { | |
123 | if (lsdb->hook_remove) { | |
124 | (*lsdb->hook_remove)(old); | |
125 | (*lsdb->hook_remove)(lsa); | |
126 | } | |
127 | } else if (OSPF6_LSA_IS_MAXAGE(old)) { | |
128 | if (lsdb->hook_add) | |
129 | (*lsdb->hook_add)(lsa); | |
130 | } else { | |
131 | if (lsdb->hook_remove) | |
132 | (*lsdb->hook_remove)(old); | |
133 | if (lsdb->hook_add) | |
134 | (*lsdb->hook_add)(lsa); | |
135 | } | |
136 | } | |
d107621d CS |
137 | /* to free the lookup lock in node get*/ |
138 | route_unlock_node(current); | |
d62a17ae | 139 | ospf6_lsa_unlock(old); |
a765eb93 | 140 | } |
d62a17ae | 141 | |
142 | ospf6_lsdb_count_assert(lsdb); | |
718e3744 | 143 | } |
144 | ||
d62a17ae | 145 | void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) |
718e3744 | 146 | { |
d62a17ae | 147 | struct route_node *node; |
148 | struct prefix_ipv6 key; | |
718e3744 | 149 | |
d62a17ae | 150 | memset(&key, 0, sizeof(key)); |
151 | ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type)); | |
152 | ospf6_lsdb_set_key(&key, &lsa->header->adv_router, | |
153 | sizeof(lsa->header->adv_router)); | |
154 | ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id)); | |
718e3744 | 155 | |
d62a17ae | 156 | node = route_node_lookup(lsdb->table, (struct prefix *)&key); |
157 | assert(node && node->info == lsa); | |
718e3744 | 158 | |
d62a17ae | 159 | node->info = NULL; |
160 | lsdb->count--; | |
718e3744 | 161 | |
d62a17ae | 162 | if (lsdb->hook_remove) |
163 | (*lsdb->hook_remove)(lsa); | |
718e3744 | 164 | |
d62a17ae | 165 | route_unlock_node(node); /* to free the lookup lock */ |
166 | route_unlock_node(node); /* to free the original lock */ | |
167 | ospf6_lsa_unlock(lsa); | |
6452df09 | 168 | |
d62a17ae | 169 | ospf6_lsdb_count_assert(lsdb); |
718e3744 | 170 | } |
171 | ||
d7c0a89a QY |
172 | struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id, |
173 | uint32_t adv_router, | |
d62a17ae | 174 | struct ospf6_lsdb *lsdb) |
718e3744 | 175 | { |
d62a17ae | 176 | struct route_node *node; |
177 | struct prefix_ipv6 key; | |
718e3744 | 178 | |
d62a17ae | 179 | if (lsdb == NULL) |
180 | return NULL; | |
718e3744 | 181 | |
d62a17ae | 182 | memset(&key, 0, sizeof(key)); |
183 | ospf6_lsdb_set_key(&key, &type, sizeof(type)); | |
184 | ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router)); | |
185 | ospf6_lsdb_set_key(&key, &id, sizeof(id)); | |
718e3744 | 186 | |
d62a17ae | 187 | node = route_node_lookup(lsdb->table, (struct prefix *)&key); |
188 | if (node == NULL || node->info == NULL) | |
189 | return NULL; | |
a765eb93 | 190 | |
d62a17ae | 191 | route_unlock_node(node); |
192 | return (struct ospf6_lsa *)node->info; | |
718e3744 | 193 | } |
194 | ||
d7c0a89a QY |
195 | struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id, |
196 | uint32_t adv_router, | |
d62a17ae | 197 | struct ospf6_lsdb *lsdb) |
2680aa2b | 198 | { |
d62a17ae | 199 | struct route_node *node; |
200 | struct prefix_ipv6 key; | |
2680aa2b | 201 | |
d62a17ae | 202 | if (lsdb == NULL) |
203 | return NULL; | |
2680aa2b | 204 | |
d62a17ae | 205 | memset(&key, 0, sizeof(key)); |
206 | ospf6_lsdb_set_key(&key, &type, sizeof(type)); | |
207 | ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router)); | |
208 | ospf6_lsdb_set_key(&key, &id, sizeof(id)); | |
2680aa2b | 209 | |
d62a17ae | 210 | { |
211 | char buf[PREFIX2STR_BUFFER]; | |
212 | prefix2str(&key, buf, sizeof(buf)); | |
213 | zlog_debug("lsdb_lookup_next: key: %s", buf); | |
214 | } | |
2680aa2b | 215 | |
d62a17ae | 216 | node = route_table_get_next(lsdb->table, &key); |
2680aa2b | 217 | |
d62a17ae | 218 | /* skip to real existing entry */ |
219 | while (node && node->info == NULL) | |
220 | node = route_next(node); | |
2680aa2b | 221 | |
d62a17ae | 222 | if (!node) |
223 | return NULL; | |
2680aa2b | 224 | |
d62a17ae | 225 | route_unlock_node(node); |
226 | if (!node->info) | |
227 | return NULL; | |
2680aa2b | 228 | |
d62a17ae | 229 | return (struct ospf6_lsa *)node->info; |
2680aa2b | 230 | } |
231 | ||
d62a17ae | 232 | const struct route_node *ospf6_lsdb_head(struct ospf6_lsdb *lsdb, int argmode, |
233 | uint16_t type, uint32_t adv_router, | |
234 | struct ospf6_lsa **lsa) | |
718e3744 | 235 | { |
d62a17ae | 236 | struct route_node *node, *end; |
237 | ||
238 | *lsa = NULL; | |
239 | ||
240 | if (argmode > 0) { | |
241 | struct prefix_ipv6 key = {.family = AF_INET6, .prefixlen = 0}; | |
242 | ||
243 | ospf6_lsdb_set_key(&key, &type, sizeof(type)); | |
244 | if (argmode > 1) | |
245 | ospf6_lsdb_set_key(&key, &adv_router, | |
246 | sizeof(adv_router)); | |
247 | ||
248 | node = route_table_get_next(lsdb->table, &key); | |
249 | if (!node || !prefix_match((struct prefix *)&key, &node->p)) | |
250 | return NULL; | |
251 | ||
252 | for (end = node; end && end->parent | |
253 | && end->parent->p.prefixlen >= key.prefixlen; | |
254 | end = end->parent) | |
255 | ; | |
256 | } else { | |
257 | node = route_top(lsdb->table); | |
258 | end = NULL; | |
259 | } | |
260 | ||
261 | while (node && !node->info) | |
262 | node = route_next_until(node, end); | |
263 | ||
264 | if (!node) | |
265 | return NULL; | |
266 | if (!node->info) { | |
267 | route_unlock_node(node); | |
268 | return NULL; | |
269 | } | |
270 | ||
271 | *lsa = node->info; | |
272 | ospf6_lsa_lock(*lsa); | |
273 | ||
274 | return end; | |
718e3744 | 275 | } |
276 | ||
d62a17ae | 277 | struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend, |
278 | struct ospf6_lsa *lsa) | |
718e3744 | 279 | { |
d62a17ae | 280 | struct route_node *node = lsa->rn; |
718e3744 | 281 | |
d62a17ae | 282 | ospf6_lsa_unlock(lsa); |
718e3744 | 283 | |
d62a17ae | 284 | do |
285 | node = route_next_until(node, iterend); | |
286 | while (node && !node->info); | |
718e3744 | 287 | |
d62a17ae | 288 | if (node && node->info) { |
289 | struct ospf6_lsa *next = node->info; | |
290 | ospf6_lsa_lock(next); | |
291 | return next; | |
292 | } | |
718e3744 | 293 | |
d62a17ae | 294 | if (node) |
295 | route_unlock_node(node); | |
296 | return NULL; | |
718e3744 | 297 | } |
298 | ||
d62a17ae | 299 | void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb) |
718e3744 | 300 | { |
d62a17ae | 301 | struct ospf6_lsa *lsa; |
a765eb93 | 302 | |
d62a17ae | 303 | if (lsdb == NULL) |
304 | return; | |
a765eb93 | 305 | |
d62a17ae | 306 | for (ALL_LSDB(lsdb, lsa)) |
307 | ospf6_lsdb_remove(lsa, lsdb); | |
718e3744 | 308 | } |
309 | ||
d62a17ae | 310 | void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa) |
a765eb93 | 311 | { |
d62a17ae | 312 | if (lsa != NULL) { |
313 | if (lsa->rn != NULL) | |
314 | route_unlock_node(lsa->rn); | |
315 | ospf6_lsa_unlock(lsa); | |
316 | } | |
a765eb93 DD |
317 | } |
318 | ||
d62a17ae | 319 | int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb) |
2449fcd6 | 320 | { |
d62a17ae | 321 | int reschedule = 0; |
322 | struct ospf6_lsa *lsa; | |
323 | ||
324 | for (ALL_LSDB(lsdb, lsa)) { | |
325 | if (!OSPF6_LSA_IS_MAXAGE(lsa)) | |
326 | continue; | |
327 | if (lsa->retrans_count != 0) { | |
328 | reschedule = 1; | |
329 | continue; | |
330 | } | |
331 | if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) | |
332 | zlog_debug("Remove MaxAge %s", lsa->name); | |
76249532 | 333 | |
d62a17ae | 334 | if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) { |
335 | UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); | |
336 | /* | |
337 | * lsa->header->age = 0; | |
338 | */ | |
339 | lsa->header->seqnum = | |
340 | htonl(OSPF_MAX_SEQUENCE_NUMBER + 1); | |
341 | ospf6_lsa_checksum(lsa->header); | |
342 | ||
343 | THREAD_OFF(lsa->refresh); | |
344 | thread_execute(master, ospf6_lsa_refresh, lsa, 0); | |
345 | } else { | |
346 | ospf6_lsdb_remove(lsa, lsdb); | |
347 | } | |
2449fcd6 | 348 | } |
d62a17ae | 349 | |
350 | return (reschedule); | |
2449fcd6 DD |
351 | } |
352 | ||
d62a17ae | 353 | void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level, |
d7c0a89a | 354 | uint16_t *type, uint32_t *id, uint32_t *adv_router, |
d62a17ae | 355 | struct ospf6_lsdb *lsdb) |
049207c3 | 356 | { |
d62a17ae | 357 | struct ospf6_lsa *lsa; |
358 | const struct route_node *end = NULL; | |
359 | void (*showfunc)(struct vty *, struct ospf6_lsa *) = NULL; | |
360 | ||
361 | switch (level) { | |
362 | case OSPF6_LSDB_SHOW_LEVEL_DETAIL: | |
363 | showfunc = ospf6_lsa_show; | |
364 | break; | |
365 | case OSPF6_LSDB_SHOW_LEVEL_INTERNAL: | |
366 | showfunc = ospf6_lsa_show_internal; | |
367 | break; | |
368 | case OSPF6_LSDB_SHOW_LEVEL_DUMP: | |
369 | showfunc = ospf6_lsa_show_dump; | |
370 | break; | |
371 | case OSPF6_LSDB_SHOW_LEVEL_NORMAL: | |
372 | default: | |
373 | showfunc = ospf6_lsa_show_summary; | |
374 | } | |
375 | ||
376 | if (type && id && adv_router) { | |
377 | lsa = ospf6_lsdb_lookup(*type, *id, *adv_router, lsdb); | |
378 | if (lsa) { | |
379 | if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) | |
380 | ospf6_lsa_show(vty, lsa); | |
381 | else | |
382 | (*showfunc)(vty, lsa); | |
383 | } | |
384 | return; | |
385 | } | |
386 | ||
387 | if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) | |
388 | ospf6_lsa_show_summary_header(vty); | |
389 | ||
62d86b87 | 390 | end = ospf6_lsdb_head(lsdb, !!type + !!(type && adv_router), |
996c9314 | 391 | type ? *type : 0, adv_router ? *adv_router : 0, |
62d86b87 | 392 | &lsa); |
d62a17ae | 393 | while (lsa) { |
394 | if ((!adv_router || lsa->header->adv_router == *adv_router) | |
395 | && (!id || lsa->header->id == *id)) | |
396 | (*showfunc)(vty, lsa); | |
397 | ||
398 | lsa = ospf6_lsdb_next(end, lsa); | |
399 | } | |
049207c3 | 400 | } |
401 | ||
d7c0a89a QY |
402 | uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router, |
403 | struct ospf6_lsdb *lsdb) | |
049207c3 | 404 | { |
d62a17ae | 405 | struct ospf6_lsa *lsa; |
d7c0a89a | 406 | uint32_t id = 1, tmp_id; |
d62a17ae | 407 | |
408 | /* This routine is curently invoked only for Inter-Prefix LSAs for | |
409 | * non-summarized routes (no area/range). | |
410 | */ | |
411 | for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) { | |
412 | tmp_id = ntohl(lsa->header->id); | |
413 | if (tmp_id < id) | |
414 | continue; | |
415 | ||
416 | if (tmp_id > id) { | |
417 | ospf6_lsdb_lsa_unlock(lsa); | |
418 | break; | |
419 | } | |
420 | id++; | |
421 | } | |
422 | ||
d7c0a89a | 423 | return ((uint32_t)htonl(id)); |
049207c3 | 424 | } |
425 | ||
426 | /* Decide new LS sequence number to originate. | |
427 | note return value is network byte order */ | |
d7c0a89a QY |
428 | uint32_t ospf6_new_ls_seqnum(uint16_t type, uint32_t id, uint32_t adv_router, |
429 | struct ospf6_lsdb *lsdb) | |
049207c3 | 430 | { |
d62a17ae | 431 | struct ospf6_lsa *lsa; |
432 | signed long seqnum = 0; | |
049207c3 | 433 | |
d62a17ae | 434 | /* if current database copy not found, return InitialSequenceNumber */ |
435 | lsa = ospf6_lsdb_lookup(type, id, adv_router, lsdb); | |
436 | if (lsa == NULL) | |
437 | seqnum = OSPF_INITIAL_SEQUENCE_NUMBER; | |
438 | else | |
439 | seqnum = (signed long)ntohl(lsa->header->seqnum) + 1; | |
049207c3 | 440 | |
d7c0a89a | 441 | return ((uint32_t)htonl(seqnum)); |
049207c3 | 442 | } |