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 lsa
->retrans_count
= old
->retrans_count
;
137 if (OSPF6_LSA_IS_CHANGED(old
, lsa
)) {
138 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
139 if (lsdb
->hook_remove
) {
140 (*lsdb
->hook_remove
)(old
);
141 (*lsdb
->hook_remove
)(lsa
);
143 } else if (OSPF6_LSA_IS_MAXAGE(old
)) {
145 (*lsdb
->hook_add
)(lsa
);
147 if (lsdb
->hook_remove
)
148 (*lsdb
->hook_remove
)(old
);
150 (*lsdb
->hook_add
)(lsa
);
153 /* to free the lookup lock in node get*/
154 route_unlock_node(current
);
155 ospf6_lsa_unlock(old
);
158 ospf6_lsdb_count_assert(lsdb
);
161 void ospf6_lsdb_remove(struct ospf6_lsa
*lsa
, struct ospf6_lsdb
*lsdb
)
163 struct route_node
*node
;
164 struct prefix_ipv6 key
;
166 memset(&key
, 0, sizeof(key
));
167 ospf6_lsdb_set_key(&key
, &lsa
->header
->type
, sizeof(lsa
->header
->type
));
168 ospf6_lsdb_set_key(&key
, &lsa
->header
->adv_router
,
169 sizeof(lsa
->header
->adv_router
));
170 ospf6_lsdb_set_key(&key
, &lsa
->header
->id
, sizeof(lsa
->header
->id
));
172 node
= route_node_lookup(lsdb
->table
, (struct prefix
*)&key
);
173 assert(node
&& node
->info
== lsa
);
177 ospf6_lsdb_stats_update(lsa
, lsdb
, -1);
179 if (lsdb
->hook_remove
)
180 (*lsdb
->hook_remove
)(lsa
);
182 route_unlock_node(node
); /* to free the lookup lock */
183 route_unlock_node(node
); /* to free the original lock */
184 ospf6_lsa_unlock(lsa
);
186 ospf6_lsdb_count_assert(lsdb
);
189 struct ospf6_lsa
*ospf6_lsdb_lookup(uint16_t type
, uint32_t id
,
191 struct ospf6_lsdb
*lsdb
)
193 struct route_node
*node
;
194 struct prefix_ipv6 key
;
199 memset(&key
, 0, sizeof(key
));
200 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
201 ospf6_lsdb_set_key(&key
, &adv_router
, sizeof(adv_router
));
202 ospf6_lsdb_set_key(&key
, &id
, sizeof(id
));
204 node
= route_node_lookup(lsdb
->table
, (struct prefix
*)&key
);
205 if (node
== NULL
|| node
->info
== NULL
)
208 route_unlock_node(node
);
209 return (struct ospf6_lsa
*)node
->info
;
212 struct ospf6_lsa
*ospf6_find_external_lsa(struct ospf6
*ospf6
, struct prefix
*p
)
214 struct ospf6_route
*match
;
215 struct ospf6_lsa
*lsa
;
216 struct ospf6_external_info
*info
;
218 match
= ospf6_route_lookup(p
, ospf6
->external_table
);
220 if (IS_OSPF6_DEBUG_ASBR
)
221 zlog_debug("No such route %pFX to withdraw", p
);
226 info
= match
->route_option
;
229 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
230 htonl(info
->id
), ospf6
->router_id
, ospf6
->lsdb
);
234 struct ospf6_lsa
*ospf6_lsdb_lookup_next(uint16_t type
, uint32_t id
,
236 struct ospf6_lsdb
*lsdb
)
238 struct route_node
*node
;
239 struct prefix_ipv6 key
;
244 memset(&key
, 0, sizeof(key
));
245 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
246 ospf6_lsdb_set_key(&key
, &adv_router
, sizeof(adv_router
));
247 ospf6_lsdb_set_key(&key
, &id
, sizeof(id
));
249 zlog_debug("lsdb_lookup_next: key: %pFX", &key
);
251 node
= route_table_get_next(lsdb
->table
, &key
);
253 /* skip to real existing entry */
254 while (node
&& node
->info
== NULL
)
255 node
= route_next(node
);
260 route_unlock_node(node
);
264 return (struct ospf6_lsa
*)node
->info
;
267 const struct route_node
*ospf6_lsdb_head(struct ospf6_lsdb
*lsdb
, int argmode
,
268 uint16_t type
, uint32_t adv_router
,
269 struct ospf6_lsa
**lsa
)
271 struct route_node
*node
, *end
;
276 struct prefix_ipv6 key
= {.family
= AF_INET6
, .prefixlen
= 0};
278 ospf6_lsdb_set_key(&key
, &type
, sizeof(type
));
280 ospf6_lsdb_set_key(&key
, &adv_router
,
283 node
= route_table_get_next(lsdb
->table
, &key
);
284 if (!node
|| !prefix_match((struct prefix
*)&key
, &node
->p
))
287 for (end
= node
; end
&& end
->parent
288 && end
->parent
->p
.prefixlen
>= key
.prefixlen
;
292 node
= route_top(lsdb
->table
);
296 while (node
&& !node
->info
)
297 node
= route_next_until(node
, end
);
302 route_unlock_node(node
);
307 ospf6_lsa_lock(*lsa
);
312 struct ospf6_lsa
*ospf6_lsdb_next(const struct route_node
*iterend
,
313 struct ospf6_lsa
*lsa
)
315 struct route_node
*node
= lsa
->rn
;
317 ospf6_lsa_unlock(lsa
);
320 node
= route_next_until(node
, iterend
);
321 while (node
&& !node
->info
);
323 if (node
&& node
->info
) {
324 struct ospf6_lsa
*next
= node
->info
;
325 ospf6_lsa_lock(next
);
330 route_unlock_node(node
);
334 void ospf6_lsdb_remove_all(struct ospf6_lsdb
*lsdb
)
336 struct ospf6_lsa
*lsa
, *lsanext
;
341 for (ALL_LSDB(lsdb
, lsa
, lsanext
))
342 ospf6_lsdb_remove(lsa
, lsdb
);
345 void ospf6_lsdb_lsa_unlock(struct ospf6_lsa
*lsa
)
349 route_unlock_node(lsa
->rn
);
350 ospf6_lsa_unlock(lsa
);
354 int ospf6_lsdb_maxage_remover(struct ospf6_lsdb
*lsdb
)
357 struct ospf6_lsa
*lsa
, *lsanext
;
359 for (ALL_LSDB(lsdb
, lsa
, lsanext
)) {
360 if (!OSPF6_LSA_IS_MAXAGE(lsa
)) {
361 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
362 zlog_debug("Not MaxAge %s", lsa
->name
);
366 if (lsa
->retrans_count
!= 0) {
367 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
368 zlog_debug("Remove MaxAge %s retrans_count %d",
369 lsa
->name
, lsa
->retrans_count
);
374 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
375 zlog_debug("Remove MaxAge %s", lsa
->name
);
377 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
)) {
378 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_SEQWRAPPED
);
380 * lsa->header->age = 0;
382 lsa
->header
->seqnum
=
383 htonl(OSPF_MAX_SEQUENCE_NUMBER
+ 1);
384 ospf6_lsa_checksum(lsa
->header
);
386 THREAD_OFF(lsa
->refresh
);
387 thread_execute(master
, ospf6_lsa_refresh
, lsa
, 0);
389 zlog_debug("calling ospf6_lsdb_remove %s", lsa
->name
);
390 ospf6_lsdb_remove(lsa
, lsdb
);
397 uint32_t ospf6_new_ls_id(uint16_t type
, uint32_t adv_router
,
398 struct ospf6_lsdb
*lsdb
)
400 struct ospf6_lsa
*lsa
;
401 uint32_t id
= 1, tmp_id
;
403 /* This routine is curently invoked only for Inter-Prefix LSAs for
404 * non-summarized routes (no area/range).
406 for (ALL_LSDB_TYPED_ADVRTR(lsdb
, type
, adv_router
, lsa
)) {
407 tmp_id
= ntohl(lsa
->header
->id
);
412 ospf6_lsdb_lsa_unlock(lsa
);
418 return ((uint32_t)htonl(id
));
421 /* Decide new LS sequence number to originate.
422 note return value is network byte order */
423 uint32_t ospf6_new_ls_seqnum(uint16_t type
, uint32_t id
, uint32_t adv_router
,
424 struct ospf6_lsdb
*lsdb
)
426 struct ospf6_lsa
*lsa
;
427 signed long seqnum
= 0;
429 /* if current database copy not found, return InitialSequenceNumber */
430 lsa
= ospf6_lsdb_lookup(type
, id
, adv_router
, lsdb
);
432 seqnum
= OSPF_INITIAL_SEQUENCE_NUMBER
;
434 seqnum
= (signed long)ntohl(lsa
->header
->seqnum
) + 1;
436 return ((uint32_t)htonl(seqnum
));