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