]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_lsdb.c
sharpd: Allow sharpd to accept nexthop group as part of route install
[mirror_frr.git] / ospf6d / ospf6_lsdb.c
CommitLineData
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 37struct 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 53void 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 62static 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 73static 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 96void 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 149void 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
176struct 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
199struct 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 236const 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 281struct 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 303void 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 314void 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 323int 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 357void 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
406uint32_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
432uint32_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}