]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_lsdb.c
ospf6d: add write-multiplier configuration
[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
30043e4c
DL
37DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSDB, "OSPF6 LSA database");
38
d62a17ae 39struct 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 51void 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 60static 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 71static 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 94void 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 147void 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
174struct 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
197struct 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 230const 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 275struct 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 297void 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 308void 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 317int 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
360uint32_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
386uint32_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}