]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_lsdb.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / ospf6d / ospf6_lsdb.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2003 Yasuhiro Ohara
4 */
5
6 #include <zebra.h>
7
8 #include "memory.h"
9 #include "log.h"
10 #include "command.h"
11 #include "prefix.h"
12 #include "table.h"
13 #include "vty.h"
14
15 #include "ospf6_proto.h"
16 #include "ospf6_lsa.h"
17 #include "ospf6_lsdb.h"
18 #include "ospf6_asbr.h"
19 #include "ospf6_route.h"
20 #include "ospf6d.h"
21 #include "bitfield.h"
22
23 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSDB, "OSPF6 LSA database");
24
25 struct ospf6_lsdb *ospf6_lsdb_create(void *data)
26 {
27 struct ospf6_lsdb *lsdb;
28
29 lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb));
30 memset(lsdb, 0, sizeof(struct ospf6_lsdb));
31
32 lsdb->data = data;
33 lsdb->table = route_table_init();
34 return lsdb;
35 }
36
37 void ospf6_lsdb_delete(struct ospf6_lsdb *lsdb)
38 {
39 if (lsdb != NULL) {
40 ospf6_lsdb_remove_all(lsdb);
41 route_table_finish(lsdb->table);
42 XFREE(MTYPE_OSPF6_LSDB, lsdb);
43 }
44 }
45
46 static void ospf6_lsdb_set_key(struct prefix_ipv6 *key, const void *value,
47 int len)
48 {
49 assert(key->prefixlen % 8 == 0);
50
51 memcpy((caddr_t)&key->prefix + key->prefixlen / 8, (caddr_t)value, len);
52 key->family = AF_INET6;
53 key->prefixlen += len * 8;
54 }
55
56 #ifdef DEBUG
57 static void _lsdb_count_assert(struct ospf6_lsdb *lsdb)
58 {
59 struct ospf6_lsa *debug, *debugnext;
60 unsigned int num = 0;
61 for (ALL_LSDB(lsdb, debug, debugnext))
62 num++;
63
64 if (num == lsdb->count)
65 return;
66
67 zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb,
68 lsdb->count, num);
69 for (ALL_LSDB(lsdb, debug, debugnext))
70 zlog_debug("%s lsdb[%p]", debug->name, debug->lsdb);
71 zlog_debug("DUMP END");
72
73 assert(num == lsdb->count);
74 }
75 #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
76 #else /*DEBUG*/
77 #define ospf6_lsdb_count_assert(t) ((void) 0)
78 #endif /*DEBUG*/
79
80 static inline void ospf6_lsdb_stats_update(struct ospf6_lsa *lsa,
81 struct ospf6_lsdb *lsdb, int count)
82 {
83 uint16_t stat = ntohs(lsa->header->type) & OSPF6_LSTYPE_FCODE_MASK;
84
85 if (stat >= OSPF6_LSTYPE_SIZE)
86 stat = OSPF6_LSTYPE_UNKNOWN;
87 lsdb->stats[stat] += count;
88 }
89
90 void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
91 {
92 struct prefix_ipv6 key;
93 struct route_node *current;
94 struct ospf6_lsa *old = NULL;
95
96 memset(&key, 0, sizeof(key));
97 ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
98 ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
99 sizeof(lsa->header->adv_router));
100 ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
101
102 current = route_node_get(lsdb->table, (struct prefix *)&key);
103 old = current->info;
104 current->info = lsa;
105 lsa->rn = current;
106 ospf6_lsa_lock(lsa);
107
108 if (!old) {
109 lsdb->count++;
110 ospf6_lsdb_stats_update(lsa, lsdb, 1);
111
112 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
113 if (lsdb->hook_remove)
114 (*lsdb->hook_remove)(lsa);
115 } else {
116 if (lsdb->hook_add)
117 (*lsdb->hook_add)(lsa);
118 }
119 } else {
120 lsa->retrans_count = old->retrans_count;
121
122 if (OSPF6_LSA_IS_CHANGED(old, lsa)) {
123 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
124 if (lsdb->hook_remove) {
125 (*lsdb->hook_remove)(old);
126 (*lsdb->hook_remove)(lsa);
127 }
128 } else if (OSPF6_LSA_IS_MAXAGE(old)) {
129 if (lsdb->hook_add)
130 (*lsdb->hook_add)(lsa);
131 } else {
132 if (lsdb->hook_remove)
133 (*lsdb->hook_remove)(old);
134 if (lsdb->hook_add)
135 (*lsdb->hook_add)(lsa);
136 }
137 }
138 /* to free the lookup lock in node get*/
139 route_unlock_node(current);
140 ospf6_lsa_unlock(old);
141 }
142
143 ospf6_lsdb_count_assert(lsdb);
144 }
145
146 void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
147 {
148 struct route_node *node;
149 struct prefix_ipv6 key;
150
151 memset(&key, 0, sizeof(key));
152 ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
153 ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
154 sizeof(lsa->header->adv_router));
155 ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
156
157 node = route_node_lookup(lsdb->table, (struct prefix *)&key);
158 assert(node && node->info == lsa);
159
160 node->info = NULL;
161 lsdb->count--;
162 ospf6_lsdb_stats_update(lsa, lsdb, -1);
163
164 if (lsdb->hook_remove)
165 (*lsdb->hook_remove)(lsa);
166
167 route_unlock_node(node); /* to free the lookup lock */
168 route_unlock_node(node); /* to free the original lock */
169 ospf6_lsa_unlock(lsa);
170
171 ospf6_lsdb_count_assert(lsdb);
172 }
173
174 struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id,
175 uint32_t adv_router,
176 struct ospf6_lsdb *lsdb)
177 {
178 struct route_node *node;
179 struct prefix_ipv6 key;
180
181 if (lsdb == NULL)
182 return NULL;
183
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));
188
189 node = route_node_lookup(lsdb->table, (struct prefix *)&key);
190 if (node == NULL || node->info == NULL)
191 return NULL;
192
193 route_unlock_node(node);
194 return (struct ospf6_lsa *)node->info;
195 }
196
197 struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p)
198 {
199 struct ospf6_route *match;
200 struct ospf6_lsa *lsa;
201 struct ospf6_external_info *info;
202
203 match = ospf6_route_lookup(p, ospf6->external_table);
204 if (match == NULL) {
205 if (IS_OSPF6_DEBUG_ASBR)
206 zlog_debug("No such route %pFX to withdraw", p);
207
208 return NULL;
209 }
210
211 info = match->route_option;
212 assert(info);
213
214 lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
215 htonl(info->id), ospf6->router_id, ospf6->lsdb);
216 return lsa;
217 }
218
219 struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
220 uint32_t adv_router,
221 struct ospf6_lsdb *lsdb)
222 {
223 struct route_node *node;
224 struct prefix_ipv6 key;
225
226 if (lsdb == NULL)
227 return NULL;
228
229 memset(&key, 0, sizeof(key));
230 ospf6_lsdb_set_key(&key, &type, sizeof(type));
231 ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router));
232 ospf6_lsdb_set_key(&key, &id, sizeof(id));
233
234 zlog_debug("lsdb_lookup_next: key: %pFX", &key);
235
236 node = route_table_get_next(lsdb->table, &key);
237
238 /* skip to real existing entry */
239 while (node && node->info == NULL)
240 node = route_next(node);
241
242 if (!node)
243 return NULL;
244
245 route_unlock_node(node);
246 if (!node->info)
247 return NULL;
248
249 return (struct ospf6_lsa *)node->info;
250 }
251
252 const struct route_node *ospf6_lsdb_head(struct ospf6_lsdb *lsdb, int argmode,
253 uint16_t type, uint32_t adv_router,
254 struct ospf6_lsa **lsa)
255 {
256 struct route_node *node, *end;
257
258 *lsa = NULL;
259
260 if (argmode > 0) {
261 struct prefix_ipv6 key = {.family = AF_INET6, .prefixlen = 0};
262
263 ospf6_lsdb_set_key(&key, &type, sizeof(type));
264 if (argmode > 1)
265 ospf6_lsdb_set_key(&key, &adv_router,
266 sizeof(adv_router));
267
268 node = route_table_get_next(lsdb->table, &key);
269 if (!node || !prefix_match((struct prefix *)&key, &node->p))
270 return NULL;
271
272 for (end = node; end && end->parent
273 && end->parent->p.prefixlen >= key.prefixlen;
274 end = end->parent)
275 ;
276 } else {
277 node = route_top(lsdb->table);
278 end = NULL;
279 }
280
281 while (node && !node->info)
282 node = route_next_until(node, end);
283
284 if (!node)
285 return NULL;
286 if (!node->info) {
287 route_unlock_node(node);
288 return NULL;
289 }
290
291 *lsa = node->info;
292 ospf6_lsa_lock(*lsa);
293
294 return end;
295 }
296
297 struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend,
298 struct ospf6_lsa *lsa)
299 {
300 struct route_node *node = lsa->rn;
301
302 ospf6_lsa_unlock(lsa);
303
304 do
305 node = route_next_until(node, iterend);
306 while (node && !node->info);
307
308 if (node && node->info) {
309 struct ospf6_lsa *next = node->info;
310 ospf6_lsa_lock(next);
311 return next;
312 }
313
314 if (node)
315 route_unlock_node(node);
316 return NULL;
317 }
318
319 void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb)
320 {
321 struct ospf6_lsa *lsa, *lsanext;
322
323 if (lsdb == NULL)
324 return;
325
326 for (ALL_LSDB(lsdb, lsa, lsanext))
327 ospf6_lsdb_remove(lsa, lsdb);
328 }
329
330 void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa)
331 {
332 if (lsa != NULL) {
333 if (lsa->rn != NULL)
334 route_unlock_node(lsa->rn);
335 ospf6_lsa_unlock(lsa);
336 }
337 }
338
339 int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb)
340 {
341 int reschedule = 0;
342 struct ospf6_lsa *lsa, *lsanext;
343
344 for (ALL_LSDB(lsdb, lsa, lsanext)) {
345 if (!OSPF6_LSA_IS_MAXAGE(lsa)) {
346 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
347 zlog_debug("Not MaxAge %s", lsa->name);
348 continue;
349 }
350
351 if (lsa->retrans_count != 0) {
352 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
353 zlog_debug("Remove MaxAge %s retrans_count %d",
354 lsa->name, lsa->retrans_count);
355
356 reschedule = 1;
357 continue;
358 }
359 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
360 zlog_debug("Remove MaxAge %s", lsa->name);
361
362 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) {
363 UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
364 /*
365 * lsa->header->age = 0;
366 */
367 lsa->header->seqnum =
368 htonl(OSPF_MAX_SEQUENCE_NUMBER + 1);
369 ospf6_lsa_checksum(lsa->header);
370
371 THREAD_OFF(lsa->refresh);
372 thread_execute(master, ospf6_lsa_refresh, lsa, 0);
373 } else {
374 zlog_debug("calling ospf6_lsdb_remove %s", lsa->name);
375 ospf6_lsdb_remove(lsa, lsdb);
376 }
377 }
378
379 return (reschedule);
380 }
381
382 uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router,
383 struct ospf6_lsdb *lsdb)
384 {
385 struct ospf6_lsa *lsa;
386 uint32_t id = 1, tmp_id;
387
388 /* This routine is curently invoked only for Inter-Prefix LSAs for
389 * non-summarized routes (no area/range).
390 */
391 for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) {
392 tmp_id = ntohl(lsa->header->id);
393 if (tmp_id < id)
394 continue;
395
396 if (tmp_id > id) {
397 ospf6_lsdb_lsa_unlock(lsa);
398 break;
399 }
400 id++;
401 }
402
403 return ((uint32_t)htonl(id));
404 }
405
406 /* Decide new LS sequence number to originate.
407 note return value is network byte order */
408 uint32_t ospf6_new_ls_seqnum(uint16_t type, uint32_t id, uint32_t adv_router,
409 struct ospf6_lsdb *lsdb)
410 {
411 struct ospf6_lsa *lsa;
412 signed long seqnum = 0;
413
414 /* if current database copy not found, return InitialSequenceNumber */
415 lsa = ospf6_lsdb_lookup(type, id, adv_router, lsdb);
416 if (lsa == NULL)
417 seqnum = OSPF_INITIAL_SEQUENCE_NUMBER;
418 else
419 seqnum = (signed long)ntohl(lsa->header->seqnum) + 1;
420
421 return ((uint32_t)htonl(seqnum));
422 }