1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2003 Yasuhiro Ohara
15 #include "ospf6_proto.h"
16 #include "ospf6_area.h"
17 #include "ospf6_lsa.h"
18 #include "ospf6_lsdb.h"
19 #include "ospf6_abr.h"
20 #include "ospf6_asbr.h"
21 #include "ospf6_route.h"
25 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSDB
, "OSPF6 LSA database");
27 struct ospf6_lsdb
*ospf6_lsdb_create(void *data
)
29 struct ospf6_lsdb
*lsdb
;
31 lsdb
= XCALLOC(MTYPE_OSPF6_LSDB
, sizeof(struct ospf6_lsdb
));
32 memset(lsdb
, 0, sizeof(struct ospf6_lsdb
));
35 lsdb
->table
= route_table_init();
39 void ospf6_lsdb_delete(struct ospf6_lsdb
*lsdb
)
42 ospf6_lsdb_remove_all(lsdb
);
43 route_table_finish(lsdb
->table
);
44 XFREE(MTYPE_OSPF6_LSDB
, lsdb
);
48 static void ospf6_lsdb_set_key(struct prefix_ipv6
*key
, const void *value
,
51 assert(key
->prefixlen
% 8 == 0);
53 memcpy((caddr_t
)&key
->prefix
+ key
->prefixlen
/ 8, (caddr_t
)value
, len
);
54 key
->family
= AF_INET6
;
55 key
->prefixlen
+= len
* 8;
59 static void _lsdb_count_assert(struct ospf6_lsdb
*lsdb
)
61 struct ospf6_lsa
*debug
, *debugnext
;
63 for (ALL_LSDB(lsdb
, debug
, debugnext
))
66 if (num
== lsdb
->count
)
69 zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb
,
71 for (ALL_LSDB(lsdb
, debug
, debugnext
))
72 zlog_debug("%s lsdb[%p]", debug
->name
, debug
->lsdb
);
73 zlog_debug("DUMP END");
75 assert(num
== lsdb
->count
);
77 #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
79 #define ospf6_lsdb_count_assert(t) ((void) 0)
82 static inline void ospf6_lsdb_stats_update(struct ospf6_lsa
*lsa
,
83 struct ospf6_lsdb
*lsdb
, int count
)
85 uint16_t stat
= ntohs(lsa
->header
->type
) & OSPF6_LSTYPE_FCODE_MASK
;
87 if (stat
>= OSPF6_LSTYPE_SIZE
)
88 stat
= OSPF6_LSTYPE_UNKNOWN
;
89 lsdb
->stats
[stat
] += count
;
92 void ospf6_lsdb_add(struct ospf6_lsa
*lsa
, struct ospf6_lsdb
*lsdb
)
94 struct prefix_ipv6 key
;
95 struct route_node
*current
;
96 struct ospf6_lsa
*old
= NULL
;
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
));
104 current
= route_node_get(lsdb
->table
, (struct prefix
*)&key
);
112 ospf6_lsdb_stats_update(lsa
, lsdb
, 1);
114 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
115 if (lsdb
->hook_remove
)
116 (*lsdb
->hook_remove
)(lsa
);
119 (*lsdb
->hook_add
)(lsa
);
122 lsa
->retrans_count
= old
->retrans_count
;
124 if (OSPF6_LSA_IS_CHANGED(old
, lsa
)) {
125 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
126 if (lsdb
->hook_remove
) {
127 (*lsdb
->hook_remove
)(old
);
128 (*lsdb
->hook_remove
)(lsa
);
130 } else if (OSPF6_LSA_IS_MAXAGE(old
)) {
132 (*lsdb
->hook_add
)(lsa
);
134 if (lsdb
->hook_remove
)
135 (*lsdb
->hook_remove
)(old
);
137 (*lsdb
->hook_add
)(lsa
);
140 /* to free the lookup lock in node get*/
141 route_unlock_node(current
);
142 ospf6_lsa_unlock(old
);
145 ospf6_lsdb_count_assert(lsdb
);
148 void ospf6_lsdb_remove(struct ospf6_lsa
*lsa
, struct ospf6_lsdb
*lsdb
)
150 struct route_node
*node
;
151 struct prefix_ipv6 key
;
153 memset(&key
, 0, sizeof(key
));
154 ospf6_lsdb_set_key(&key
, &lsa
->header
->type
, sizeof(lsa
->header
->type
));
155 ospf6_lsdb_set_key(&key
, &lsa
->header
->adv_router
,
156 sizeof(lsa
->header
->adv_router
));
157 ospf6_lsdb_set_key(&key
, &lsa
->header
->id
, sizeof(lsa
->header
->id
));
159 node
= route_node_lookup(lsdb
->table
, (struct prefix
*)&key
);
160 assert(node
&& node
->info
== lsa
);
164 ospf6_lsdb_stats_update(lsa
, lsdb
, -1);
166 if (lsdb
->hook_remove
)
167 (*lsdb
->hook_remove
)(lsa
);
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
);
173 ospf6_lsdb_count_assert(lsdb
);
176 struct ospf6_lsa
*ospf6_lsdb_lookup(uint16_t type
, uint32_t id
,
178 struct ospf6_lsdb
*lsdb
)
180 struct route_node
*node
;
181 struct prefix_ipv6 key
;
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
));
191 node
= route_node_lookup(lsdb
->table
, (struct prefix
*)&key
);
192 if (node
== NULL
|| node
->info
== NULL
)
195 route_unlock_node(node
);
196 return (struct ospf6_lsa
*)node
->info
;
199 struct ospf6_lsa
*ospf6_find_external_lsa(struct ospf6
*ospf6
, struct prefix
*p
)
201 struct ospf6_route
*match
;
202 struct ospf6_lsa
*lsa
;
203 struct ospf6_external_info
*info
;
205 match
= ospf6_route_lookup(p
, ospf6
->external_table
);
207 if (IS_OSPF6_DEBUG_ASBR
)
208 zlog_debug("No such route %pFX to withdraw", p
);
213 info
= match
->route_option
;
216 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
217 htonl(info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
221 struct ospf6_lsa
*ospf6_find_inter_prefix_lsa(struct ospf6
*ospf6
,
222 struct ospf6_area
*area
,
225 struct ospf6_lsa
*lsa
;
226 uint16_t type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
228 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
, lsa
)) {
229 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
230 struct prefix prefix
;
233 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
235 prefix
.family
= AF_INET6
;
236 prefix
.prefixlen
= prefix_lsa
->prefix
.prefix_length
;
237 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, prefix_lsa
,
238 &prefix_lsa
->prefix
);
239 if (prefix_same(p
, &prefix
))
246 struct ospf6_lsa
*ospf6_lsdb_lookup_next(uint16_t type
, uint32_t id
,
248 struct ospf6_lsdb
*lsdb
)
250 struct route_node
*node
;
251 struct prefix_ipv6 key
;
256 memset(&key
, 0, sizeof(key
));
257 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
258 ospf6_lsdb_set_key(&key
, &adv_router
, sizeof(adv_router
));
259 ospf6_lsdb_set_key(&key
, &id
, sizeof(id
));
261 zlog_debug("lsdb_lookup_next: key: %pFX", &key
);
263 node
= route_table_get_next(lsdb
->table
, &key
);
265 /* skip to real existing entry */
266 while (node
&& node
->info
== NULL
)
267 node
= route_next(node
);
272 route_unlock_node(node
);
276 return (struct ospf6_lsa
*)node
->info
;
279 const struct route_node
*ospf6_lsdb_head(struct ospf6_lsdb
*lsdb
, int argmode
,
280 uint16_t type
, uint32_t adv_router
,
281 struct ospf6_lsa
**lsa
)
283 struct route_node
*node
, *end
;
288 struct prefix_ipv6 key
= {.family
= AF_INET6
, .prefixlen
= 0};
290 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
292 ospf6_lsdb_set_key(&key
, &adv_router
,
295 node
= route_table_get_next(lsdb
->table
, &key
);
296 if (!node
|| !prefix_match((struct prefix
*)&key
, &node
->p
))
299 for (end
= node
; end
&& end
->parent
300 && end
->parent
->p
.prefixlen
>= key
.prefixlen
;
304 node
= route_top(lsdb
->table
);
308 while (node
&& !node
->info
)
309 node
= route_next_until(node
, end
);
314 route_unlock_node(node
);
319 ospf6_lsa_lock(*lsa
);
324 struct ospf6_lsa
*ospf6_lsdb_next(const struct route_node
*iterend
,
325 struct ospf6_lsa
*lsa
)
327 struct route_node
*node
= lsa
->rn
;
329 ospf6_lsa_unlock(lsa
);
332 node
= route_next_until(node
, iterend
);
333 while (node
&& !node
->info
);
335 if (node
&& node
->info
) {
336 struct ospf6_lsa
*next
= node
->info
;
337 ospf6_lsa_lock(next
);
342 route_unlock_node(node
);
346 void ospf6_lsdb_remove_all(struct ospf6_lsdb
*lsdb
)
348 struct ospf6_lsa
*lsa
, *lsanext
;
353 for (ALL_LSDB(lsdb
, lsa
, lsanext
))
354 ospf6_lsdb_remove(lsa
, lsdb
);
357 void ospf6_lsdb_lsa_unlock(struct ospf6_lsa
*lsa
)
361 route_unlock_node(lsa
->rn
);
362 ospf6_lsa_unlock(lsa
);
366 int ospf6_lsdb_maxage_remover(struct ospf6_lsdb
*lsdb
)
369 struct ospf6_lsa
*lsa
, *lsanext
;
371 for (ALL_LSDB(lsdb
, lsa
, lsanext
)) {
372 if (!OSPF6_LSA_IS_MAXAGE(lsa
)) {
373 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
374 zlog_debug("Not MaxAge %s", lsa
->name
);
378 if (lsa
->retrans_count
!= 0) {
379 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
380 zlog_debug("Remove MaxAge %s retrans_count %d",
381 lsa
->name
, lsa
->retrans_count
);
386 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
387 zlog_debug("Remove MaxAge %s", lsa
->name
);
389 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
)) {
390 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
);
392 * lsa->header->age = 0;
394 lsa
->header
->seqnum
=
395 htonl(OSPF_MAX_SEQUENCE_NUMBER
+ 1);
396 ospf6_lsa_checksum(lsa
->header
);
398 THREAD_OFF(lsa
->refresh
);
399 thread_execute(master
, ospf6_lsa_refresh
, lsa
, 0);
401 zlog_debug("calling ospf6_lsdb_remove %s", lsa
->name
);
402 ospf6_lsdb_remove(lsa
, lsdb
);
409 uint32_t ospf6_new_ls_id(uint16_t type
, uint32_t adv_router
,
410 struct ospf6_lsdb
*lsdb
)
412 struct ospf6_lsa
*lsa
;
413 uint32_t id
= 1, tmp_id
;
415 /* This routine is curently invoked only for Inter-Prefix LSAs for
416 * non-summarized routes (no area/range).
418 for (ALL_LSDB_TYPED_ADVRTR(lsdb
, type
, adv_router
, lsa
)) {
419 tmp_id
= ntohl(lsa
->header
->id
);
424 ospf6_lsdb_lsa_unlock(lsa
);
430 return ((uint32_t)htonl(id
));
433 /* Decide new LS sequence number to originate.
434 note return value is network byte order */
435 uint32_t ospf6_new_ls_seqnum(uint16_t type
, uint32_t id
, uint32_t adv_router
,
436 struct ospf6_lsdb
*lsdb
)
438 struct ospf6_lsa
*lsa
;
439 signed long seqnum
= 0;
441 /* if current database copy not found, return InitialSequenceNumber */
442 lsa
= ospf6_lsdb_lookup(type
, id
, adv_router
, lsdb
);
444 seqnum
= OSPF_INITIAL_SEQUENCE_NUMBER
;
446 seqnum
= (signed long)ntohl(lsa
->header
->seqnum
) + 1;
448 return ((uint32_t)htonl(seqnum
));