]>
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 | { |
0f9f74ba DS |
301 | struct ospf6_lsa *lsa, *lsa_next; |
302 | const struct route_node *iterend; | |
a765eb93 | 303 | |
d62a17ae | 304 | if (lsdb == NULL) |
305 | return; | |
a765eb93 | 306 | |
0f9f74ba DS |
307 | for (iterend = ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); lsa; |
308 | lsa = lsa_next) { | |
309 | lsa_next = ospf6_lsdb_next(iterend, lsa); | |
d62a17ae | 310 | ospf6_lsdb_remove(lsa, lsdb); |
0f9f74ba | 311 | } |
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; |
0f9f74ba DS |
326 | struct ospf6_lsa *lsa, *lsa_next; |
327 | const struct route_node *iterend; | |
d62a17ae | 328 | |
0f9f74ba DS |
329 | for (iterend = ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); lsa; |
330 | lsa = lsa_next) { | |
331 | lsa_next = ospf6_lsdb_next(iterend, lsa); | |
d62a17ae | 332 | if (!OSPF6_LSA_IS_MAXAGE(lsa)) |
333 | continue; | |
334 | if (lsa->retrans_count != 0) { | |
335 | reschedule = 1; | |
336 | continue; | |
337 | } | |
338 | if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) | |
339 | zlog_debug("Remove MaxAge %s", lsa->name); | |
76249532 | 340 | |
d62a17ae | 341 | if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) { |
342 | UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); | |
343 | /* | |
344 | * lsa->header->age = 0; | |
345 | */ | |
346 | lsa->header->seqnum = | |
347 | htonl(OSPF_MAX_SEQUENCE_NUMBER + 1); | |
348 | ospf6_lsa_checksum(lsa->header); | |
349 | ||
350 | THREAD_OFF(lsa->refresh); | |
351 | thread_execute(master, ospf6_lsa_refresh, lsa, 0); | |
352 | } else { | |
353 | ospf6_lsdb_remove(lsa, lsdb); | |
354 | } | |
2449fcd6 | 355 | } |
d62a17ae | 356 | |
357 | return (reschedule); | |
2449fcd6 DD |
358 | } |
359 | ||
d62a17ae | 360 | void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level, |
d7c0a89a | 361 | uint16_t *type, uint32_t *id, uint32_t *adv_router, |
d62a17ae | 362 | struct ospf6_lsdb *lsdb) |
049207c3 | 363 | { |
d62a17ae | 364 | struct ospf6_lsa *lsa; |
365 | const struct route_node *end = NULL; | |
366 | void (*showfunc)(struct vty *, struct ospf6_lsa *) = NULL; | |
367 | ||
368 | switch (level) { | |
369 | case OSPF6_LSDB_SHOW_LEVEL_DETAIL: | |
370 | showfunc = ospf6_lsa_show; | |
371 | break; | |
372 | case OSPF6_LSDB_SHOW_LEVEL_INTERNAL: | |
373 | showfunc = ospf6_lsa_show_internal; | |
374 | break; | |
375 | case OSPF6_LSDB_SHOW_LEVEL_DUMP: | |
376 | showfunc = ospf6_lsa_show_dump; | |
377 | break; | |
378 | case OSPF6_LSDB_SHOW_LEVEL_NORMAL: | |
379 | default: | |
380 | showfunc = ospf6_lsa_show_summary; | |
381 | } | |
382 | ||
383 | if (type && id && adv_router) { | |
384 | lsa = ospf6_lsdb_lookup(*type, *id, *adv_router, lsdb); | |
385 | if (lsa) { | |
386 | if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) | |
387 | ospf6_lsa_show(vty, lsa); | |
388 | else | |
389 | (*showfunc)(vty, lsa); | |
390 | } | |
391 | return; | |
392 | } | |
393 | ||
394 | if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) | |
395 | ospf6_lsa_show_summary_header(vty); | |
396 | ||
62d86b87 | 397 | end = ospf6_lsdb_head(lsdb, !!type + !!(type && adv_router), |
996c9314 | 398 | type ? *type : 0, adv_router ? *adv_router : 0, |
62d86b87 | 399 | &lsa); |
d62a17ae | 400 | while (lsa) { |
401 | if ((!adv_router || lsa->header->adv_router == *adv_router) | |
402 | && (!id || lsa->header->id == *id)) | |
403 | (*showfunc)(vty, lsa); | |
404 | ||
405 | lsa = ospf6_lsdb_next(end, lsa); | |
406 | } | |
049207c3 | 407 | } |
408 | ||
d7c0a89a QY |
409 | uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router, |
410 | struct ospf6_lsdb *lsdb) | |
049207c3 | 411 | { |
d62a17ae | 412 | struct ospf6_lsa *lsa; |
d7c0a89a | 413 | uint32_t id = 1, tmp_id; |
d62a17ae | 414 | |
415 | /* This routine is curently invoked only for Inter-Prefix LSAs for | |
416 | * non-summarized routes (no area/range). | |
417 | */ | |
418 | for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) { | |
419 | tmp_id = ntohl(lsa->header->id); | |
420 | if (tmp_id < id) | |
421 | continue; | |
422 | ||
423 | if (tmp_id > id) { | |
424 | ospf6_lsdb_lsa_unlock(lsa); | |
425 | break; | |
426 | } | |
427 | id++; | |
428 | } | |
429 | ||
d7c0a89a | 430 | return ((uint32_t)htonl(id)); |
049207c3 | 431 | } |
432 | ||
433 | /* Decide new LS sequence number to originate. | |
434 | note return value is network byte order */ | |
d7c0a89a QY |
435 | uint32_t ospf6_new_ls_seqnum(uint16_t type, uint32_t id, uint32_t adv_router, |
436 | struct ospf6_lsdb *lsdb) | |
049207c3 | 437 | { |
d62a17ae | 438 | struct ospf6_lsa *lsa; |
439 | signed long seqnum = 0; | |
049207c3 | 440 | |
d62a17ae | 441 | /* if current database copy not found, return InitialSequenceNumber */ |
442 | lsa = ospf6_lsdb_lookup(type, id, adv_router, lsdb); | |
443 | if (lsa == NULL) | |
444 | seqnum = OSPF_INITIAL_SEQUENCE_NUMBER; | |
445 | else | |
446 | seqnum = (signed long)ntohl(lsa->header->seqnum) + 1; | |
049207c3 | 447 | |
d7c0a89a | 448 | return ((uint32_t)htonl(seqnum)); |
049207c3 | 449 | } |