2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
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
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.
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
30 #include "ospf6_proto.h"
31 #include "ospf6_lsa.h"
32 #include "ospf6_lsdb.h"
33 #include "ospf6_asbr.h"
34 #include "ospf6_route.h"
38 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSDB
, "OSPF6 LSA database");
40 struct ospf6_lsdb
*ospf6_lsdb_create(void *data
)
42 struct ospf6_lsdb
*lsdb
;
44 lsdb
= XCALLOC(MTYPE_OSPF6_LSDB
, sizeof(struct ospf6_lsdb
));
45 memset(lsdb
, 0, sizeof(struct ospf6_lsdb
));
48 lsdb
->table
= route_table_init();
52 void ospf6_lsdb_delete(struct ospf6_lsdb
*lsdb
)
55 ospf6_lsdb_remove_all(lsdb
);
56 route_table_finish(lsdb
->table
);
57 XFREE(MTYPE_OSPF6_LSDB
, lsdb
);
61 static void ospf6_lsdb_set_key(struct prefix_ipv6
*key
, const void *value
,
64 assert(key
->prefixlen
% 8 == 0);
66 memcpy((caddr_t
)&key
->prefix
+ key
->prefixlen
/ 8, (caddr_t
)value
, len
);
67 key
->family
= AF_INET6
;
68 key
->prefixlen
+= len
* 8;
72 static void _lsdb_count_assert(struct ospf6_lsdb
*lsdb
)
74 struct ospf6_lsa
*debug
, *debugnext
;
76 for (ALL_LSDB(lsdb
, debug
, debugnext
))
79 if (num
== lsdb
->count
)
82 zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb
,
84 for (ALL_LSDB(lsdb
, debug
, debugnext
))
85 zlog_debug("%s lsdb[%p]", debug
->name
, debug
->lsdb
);
86 zlog_debug("DUMP END");
88 assert(num
== lsdb
->count
);
90 #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
92 #define ospf6_lsdb_count_assert(t) ((void) 0)
95 static inline void ospf6_lsdb_stats_update(struct ospf6_lsa
*lsa
,
96 struct ospf6_lsdb
*lsdb
, int count
)
98 uint16_t stat
= ntohs(lsa
->header
->type
) & OSPF6_LSTYPE_FCODE_MASK
;
100 if (stat
>= OSPF6_LSTYPE_SIZE
)
101 stat
= OSPF6_LSTYPE_UNKNOWN
;
102 lsdb
->stats
[stat
] += count
;
105 void ospf6_lsdb_add(struct ospf6_lsa
*lsa
, struct ospf6_lsdb
*lsdb
)
107 struct prefix_ipv6 key
;
108 struct route_node
*current
;
109 struct ospf6_lsa
*old
= NULL
;
111 memset(&key
, 0, sizeof(key
));
112 ospf6_lsdb_set_key(&key
, &lsa
->header
->type
, sizeof(lsa
->header
->type
));
113 ospf6_lsdb_set_key(&key
, &lsa
->header
->adv_router
,
114 sizeof(lsa
->header
->adv_router
));
115 ospf6_lsdb_set_key(&key
, &lsa
->header
->id
, sizeof(lsa
->header
->id
));
117 current
= route_node_get(lsdb
->table
, (struct prefix
*)&key
);
125 ospf6_lsdb_stats_update(lsa
, lsdb
, 1);
127 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
128 if (lsdb
->hook_remove
)
129 (*lsdb
->hook_remove
)(lsa
);
132 (*lsdb
->hook_add
)(lsa
);
135 if (OSPF6_LSA_IS_CHANGED(old
, lsa
)) {
136 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
137 if (lsdb
->hook_remove
) {
138 (*lsdb
->hook_remove
)(old
);
139 (*lsdb
->hook_remove
)(lsa
);
141 } else if (OSPF6_LSA_IS_MAXAGE(old
)) {
143 (*lsdb
->hook_add
)(lsa
);
145 if (lsdb
->hook_remove
)
146 (*lsdb
->hook_remove
)(old
);
148 (*lsdb
->hook_add
)(lsa
);
151 /* to free the lookup lock in node get*/
152 route_unlock_node(current
);
153 ospf6_lsa_unlock(old
);
156 ospf6_lsdb_count_assert(lsdb
);
159 void ospf6_lsdb_remove(struct ospf6_lsa
*lsa
, struct ospf6_lsdb
*lsdb
)
161 struct route_node
*node
;
162 struct prefix_ipv6 key
;
164 memset(&key
, 0, sizeof(key
));
165 ospf6_lsdb_set_key(&key
, &lsa
->header
->type
, sizeof(lsa
->header
->type
));
166 ospf6_lsdb_set_key(&key
, &lsa
->header
->adv_router
,
167 sizeof(lsa
->header
->adv_router
));
168 ospf6_lsdb_set_key(&key
, &lsa
->header
->id
, sizeof(lsa
->header
->id
));
170 node
= route_node_lookup(lsdb
->table
, (struct prefix
*)&key
);
171 assert(node
&& node
->info
== lsa
);
175 ospf6_lsdb_stats_update(lsa
, lsdb
, -1);
177 if (lsdb
->hook_remove
)
178 (*lsdb
->hook_remove
)(lsa
);
180 route_unlock_node(node
); /* to free the lookup lock */
181 route_unlock_node(node
); /* to free the original lock */
182 ospf6_lsa_unlock(lsa
);
184 ospf6_lsdb_count_assert(lsdb
);
187 struct ospf6_lsa
*ospf6_lsdb_lookup(uint16_t type
, uint32_t id
,
189 struct ospf6_lsdb
*lsdb
)
191 struct route_node
*node
;
192 struct prefix_ipv6 key
;
197 memset(&key
, 0, sizeof(key
));
198 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
199 ospf6_lsdb_set_key(&key
, &adv_router
, sizeof(adv_router
));
200 ospf6_lsdb_set_key(&key
, &id
, sizeof(id
));
202 node
= route_node_lookup(lsdb
->table
, (struct prefix
*)&key
);
203 if (node
== NULL
|| node
->info
== NULL
)
206 route_unlock_node(node
);
207 return (struct ospf6_lsa
*)node
->info
;
210 struct ospf6_lsa
*ospf6_find_external_lsa(struct ospf6
*ospf6
, struct prefix
*p
)
212 struct ospf6_route
*match
;
213 struct ospf6_lsa
*lsa
;
214 struct ospf6_external_info
*info
;
216 match
= ospf6_route_lookup(p
, ospf6
->external_table
);
218 if (IS_OSPF6_DEBUG_ASBR
)
219 zlog_debug("No such route %pFX to withdraw", p
);
224 info
= match
->route_option
;
227 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
228 htonl(info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
232 struct ospf6_lsa
*ospf6_lsdb_lookup_next(uint16_t type
, uint32_t id
,
234 struct ospf6_lsdb
*lsdb
)
236 struct route_node
*node
;
237 struct prefix_ipv6 key
;
242 memset(&key
, 0, sizeof(key
));
243 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
244 ospf6_lsdb_set_key(&key
, &adv_router
, sizeof(adv_router
));
245 ospf6_lsdb_set_key(&key
, &id
, sizeof(id
));
247 zlog_debug("lsdb_lookup_next: key: %pFX", &key
);
249 node
= route_table_get_next(lsdb
->table
, &key
);
251 /* skip to real existing entry */
252 while (node
&& node
->info
== NULL
)
253 node
= route_next(node
);
258 route_unlock_node(node
);
262 return (struct ospf6_lsa
*)node
->info
;
265 const struct route_node
*ospf6_lsdb_head(struct ospf6_lsdb
*lsdb
, int argmode
,
266 uint16_t type
, uint32_t adv_router
,
267 struct ospf6_lsa
**lsa
)
269 struct route_node
*node
, *end
;
274 struct prefix_ipv6 key
= {.family
= AF_INET6
, .prefixlen
= 0};
276 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
278 ospf6_lsdb_set_key(&key
, &adv_router
,
281 node
= route_table_get_next(lsdb
->table
, &key
);
282 if (!node
|| !prefix_match((struct prefix
*)&key
, &node
->p
))
285 for (end
= node
; end
&& end
->parent
286 && end
->parent
->p
.prefixlen
>= key
.prefixlen
;
290 node
= route_top(lsdb
->table
);
294 while (node
&& !node
->info
)
295 node
= route_next_until(node
, end
);
300 route_unlock_node(node
);
305 ospf6_lsa_lock(*lsa
);
310 struct ospf6_lsa
*ospf6_lsdb_next(const struct route_node
*iterend
,
311 struct ospf6_lsa
*lsa
)
313 struct route_node
*node
= lsa
->rn
;
315 ospf6_lsa_unlock(lsa
);
318 node
= route_next_until(node
, iterend
);
319 while (node
&& !node
->info
);
321 if (node
&& node
->info
) {
322 struct ospf6_lsa
*next
= node
->info
;
323 ospf6_lsa_lock(next
);
328 route_unlock_node(node
);
332 void ospf6_lsdb_remove_all(struct ospf6_lsdb
*lsdb
)
334 struct ospf6_lsa
*lsa
, *lsanext
;
339 for (ALL_LSDB(lsdb
, lsa
, lsanext
))
340 ospf6_lsdb_remove(lsa
, lsdb
);
343 void ospf6_lsdb_lsa_unlock(struct ospf6_lsa
*lsa
)
347 route_unlock_node(lsa
->rn
);
348 ospf6_lsa_unlock(lsa
);
352 int ospf6_lsdb_maxage_remover(struct ospf6_lsdb
*lsdb
)
355 struct ospf6_lsa
*lsa
, *lsanext
;
357 for (ALL_LSDB(lsdb
, lsa
, lsanext
)) {
358 if (!OSPF6_LSA_IS_MAXAGE(lsa
)) {
359 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
360 zlog_debug("Not MaxAge %s", lsa
->name
);
364 if (lsa
->retrans_count
!= 0) {
365 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
366 zlog_debug("Remove MaxAge %s retrans_count %d",
367 lsa
->name
, lsa
->retrans_count
);
372 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
373 zlog_debug("Remove MaxAge %s", lsa
->name
);
375 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
)) {
376 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
);
378 * lsa->header->age = 0;
380 lsa
->header
->seqnum
=
381 htonl(OSPF_MAX_SEQUENCE_NUMBER
+ 1);
382 ospf6_lsa_checksum(lsa
->header
);
384 THREAD_OFF(lsa
->refresh
);
385 thread_execute(master
, ospf6_lsa_refresh
, lsa
, 0);
387 zlog_debug("calling ospf6_lsdb_remove %s", lsa
->name
);
388 ospf6_lsdb_remove(lsa
, lsdb
);
395 uint32_t ospf6_new_ls_id(uint16_t type
, uint32_t adv_router
,
396 struct ospf6_lsdb
*lsdb
)
398 struct ospf6_lsa
*lsa
;
399 uint32_t id
= 1, tmp_id
;
401 /* This routine is curently invoked only for Inter-Prefix LSAs for
402 * non-summarized routes (no area/range).
404 for (ALL_LSDB_TYPED_ADVRTR(lsdb
, type
, adv_router
, lsa
)) {
405 tmp_id
= ntohl(lsa
->header
->id
);
410 ospf6_lsdb_lsa_unlock(lsa
);
416 return ((uint32_t)htonl(id
));
419 /* Decide new LS sequence number to originate.
420 note return value is network byte order */
421 uint32_t ospf6_new_ls_seqnum(uint16_t type
, uint32_t id
, uint32_t adv_router
,
422 struct ospf6_lsdb
*lsdb
)
424 struct ospf6_lsa
*lsa
;
425 signed long seqnum
= 0;
427 /* if current database copy not found, return InitialSequenceNumber */
428 lsa
= ospf6_lsdb_lookup(type
, id
, adv_router
, lsdb
);
430 seqnum
= OSPF_INITIAL_SEQUENCE_NUMBER
;
432 seqnum
= (signed long)ntohl(lsa
->header
->seqnum
) + 1;
434 return ((uint32_t)htonl(seqnum
));