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