blob: aad979a742ec1e1f6691f913a5d446b3d34725d6 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * OSPF LSDB support.
3 * Copyright (C) 1999, 2000 Alex Zinin, Kunihiro Ishiguro, Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "prefix.h"
26#include "table.h"
27#include "memory.h"
Tomasz Pala3fc1eca2009-06-24 21:48:22 +010028#include "log.h"
paul718e3742002-12-13 20:15:29 +000029
30#include "ospfd/ospfd.h"
31#include "ospfd/ospf_asbr.h"
32#include "ospfd/ospf_lsa.h"
33#include "ospfd/ospf_lsdb.h"
34
35struct ospf_lsdb *
36ospf_lsdb_new ()
37{
38 struct ospf_lsdb *new;
39
40 new = XCALLOC (MTYPE_OSPF_LSDB, sizeof (struct ospf_lsdb));
41 ospf_lsdb_init (new);
42
43 return new;
44}
45
46void
47ospf_lsdb_init (struct ospf_lsdb *lsdb)
48{
49 int i;
50
51 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
52 lsdb->type[i].db = route_table_init ();
53}
54
55void
56ospf_lsdb_free (struct ospf_lsdb *lsdb)
57{
58 ospf_lsdb_cleanup (lsdb);
59 XFREE (MTYPE_OSPF_LSDB, lsdb);
60}
61
62void
63ospf_lsdb_cleanup (struct ospf_lsdb *lsdb)
64{
65 int i;
66 assert (lsdb);
67 assert (lsdb->total == 0);
68
69 ospf_lsdb_delete_all (lsdb);
70
71 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
72 route_table_finish (lsdb->type[i].db);
73}
74
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -080075void
76ls_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa)
paul718e3742002-12-13 20:15:29 +000077{
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -080078 if (lp && lsa && lsa->data)
79 {
80 lp->family = 0;
81 lp->prefixlen = 64;
82 lp->id = lsa->data->id;
83 lp->adv_router = lsa->data->adv_router;
84 }
paul718e3742002-12-13 20:15:29 +000085}
86
Paul Jakmaba122e72006-08-27 06:24:34 +000087static void
88ospf_lsdb_delete_entry (struct ospf_lsdb *lsdb, struct route_node *rn)
89{
90 struct ospf_lsa *lsa = rn->info;
91
92 if (!lsa)
93 return;
94
95 assert (rn->table == lsdb->type[lsa->data->type].db);
96
97 if (IS_LSA_SELF (lsa))
98 lsdb->type[lsa->data->type].count_self--;
99 lsdb->type[lsa->data->type].count--;
100 lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum);
101 lsdb->total--;
102 rn->info = NULL;
103 route_unlock_node (rn);
104#ifdef MONITOR_LSDB_CHANGE
105 if (lsdb->del_lsa_hook != NULL)
106 (* lsdb->del_lsa_hook)(lsa);
107#endif /* MONITOR_LSDB_CHANGE */
108 ospf_lsa_unlock (&lsa); /* lsdb */
109 return;
110}
111
paul718e3742002-12-13 20:15:29 +0000112/* Add new LSA to lsdb. */
113void
114ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
115{
116 struct route_table *table;
117 struct prefix_ls lp;
118 struct route_node *rn;
119
120 table = lsdb->type[lsa->data->type].db;
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800121 ls_prefix_set (&lp, lsa);
paul718e3742002-12-13 20:15:29 +0000122 rn = route_node_get (table, (struct prefix *)&lp);
Paul Jakmaba122e72006-08-27 06:24:34 +0000123
124 /* nothing to do? */
125 if (rn->info && rn->info == lsa)
Paul Jakmae8f22262010-04-13 22:43:34 +0100126 {
127 route_unlock_node (rn);
128 return;
129 }
Paul Jakmaba122e72006-08-27 06:24:34 +0000130
131 /* purge old entry? */
132 if (rn->info)
133 ospf_lsdb_delete_entry (lsdb, rn);
hasso082253f2005-02-11 08:31:54 +0000134
Paul Jakmaba122e72006-08-27 06:24:34 +0000135 if (IS_LSA_SELF (lsa))
136 lsdb->type[lsa->data->type].count_self++;
137 lsdb->type[lsa->data->type].count++;
138 lsdb->total++;
paul718e3742002-12-13 20:15:29 +0000139
140#ifdef MONITOR_LSDB_CHANGE
141 if (lsdb->new_lsa_hook != NULL)
142 (* lsdb->new_lsa_hook)(lsa);
143#endif /* MONITOR_LSDB_CHANGE */
hasso082253f2005-02-11 08:31:54 +0000144 lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum);
Paul Jakmaba122e72006-08-27 06:24:34 +0000145 rn->info = ospf_lsa_lock (lsa); /* lsdb */
paul718e3742002-12-13 20:15:29 +0000146}
147
148void
149ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
150{
151 struct route_table *table;
152 struct prefix_ls lp;
153 struct route_node *rn;
154
Paul Jakmaac904de2006-06-15 12:04:57 +0000155 if (!lsdb)
156 {
157 zlog_warn ("%s: Called with NULL LSDB", __func__);
158 if (lsa)
159 zlog_warn ("LSA[Type%d:%s]: LSA %p, lsa->lsdb %p",
160 lsa->data->type, inet_ntoa (lsa->data->id),
161 lsa, lsa->lsdb);
162 return;
163 }
164
165 if (!lsa)
166 {
167 zlog_warn ("%s: Called with NULL LSA", __func__);
168 return;
169 }
170
Paul Jakmae8f22262010-04-13 22:43:34 +0100171 assert (lsa->data->type < OSPF_MAX_LSA);
paul718e3742002-12-13 20:15:29 +0000172 table = lsdb->type[lsa->data->type].db;
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800173 ls_prefix_set (&lp, lsa);
Paul Jakmae8f22262010-04-13 22:43:34 +0100174 if ((rn = route_node_lookup (table, (struct prefix *) &lp)))
Paul Jakmaba122e72006-08-27 06:24:34 +0000175 {
Paul Jakmae8f22262010-04-13 22:43:34 +0100176 if (rn->info == lsa)
177 ospf_lsdb_delete_entry (lsdb, rn);
Paul Jakmaba122e72006-08-27 06:24:34 +0000178 route_unlock_node (rn); /* route_node_lookup */
179 }
paul718e3742002-12-13 20:15:29 +0000180}
181
182void
183ospf_lsdb_delete_all (struct ospf_lsdb *lsdb)
184{
185 struct route_table *table;
186 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000187 int i;
188
189 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
190 {
191 table = lsdb->type[i].db;
192 for (rn = route_top (table); rn; rn = route_next (rn))
Paul Jakmaba122e72006-08-27 06:24:34 +0000193 if (rn->info != NULL)
194 ospf_lsdb_delete_entry (lsdb, rn);
paul718e3742002-12-13 20:15:29 +0000195 }
196}
197
hasso462f20d2005-02-23 11:29:02 +0000198void
199ospf_lsdb_clean_stat (struct ospf_lsdb *lsdb)
200{
201 struct route_table *table;
202 struct route_node *rn;
203 struct ospf_lsa *lsa;
204 int i;
205
206 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
207 {
208 table = lsdb->type[i].db;
209 for (rn = route_top (table); rn; rn = route_next (rn))
210 if ((lsa = (rn->info)) != NULL)
211 lsa->stat = LSA_SPF_NOT_EXPLORED;
212 }
213}
214
paul718e3742002-12-13 20:15:29 +0000215struct ospf_lsa *
216ospf_lsdb_lookup (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
217{
218 struct route_table *table;
219 struct prefix_ls lp;
220 struct route_node *rn;
221 struct ospf_lsa *find;
222
223 table = lsdb->type[lsa->data->type].db;
Dinesh Dutt91e6a0e2012-12-04 10:46:37 -0800224 ls_prefix_set (&lp, lsa);
paul718e3742002-12-13 20:15:29 +0000225 rn = route_node_lookup (table, (struct prefix *) &lp);
226 if (rn)
227 {
228 find = rn->info;
229 route_unlock_node (rn);
230 return find;
231 }
232 return NULL;
233}
234
235struct ospf_lsa *
236ospf_lsdb_lookup_by_id (struct ospf_lsdb *lsdb, u_char type,
237 struct in_addr id, struct in_addr adv_router)
238{
239 struct route_table *table;
240 struct prefix_ls lp;
241 struct route_node *rn;
242 struct ospf_lsa *find;
243
244 table = lsdb->type[type].db;
245
246 memset (&lp, 0, sizeof (struct prefix_ls));
247 lp.family = 0;
248 lp.prefixlen = 64;
249 lp.id = id;
250 lp.adv_router = adv_router;
251
252 rn = route_node_lookup (table, (struct prefix *) &lp);
253 if (rn)
254 {
255 find = rn->info;
256 route_unlock_node (rn);
257 return find;
258 }
259 return NULL;
260}
261
262struct ospf_lsa *
263ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *lsdb, u_char type,
264 struct in_addr id, struct in_addr adv_router,
265 int first)
266{
267 struct route_table *table;
268 struct prefix_ls lp;
269 struct route_node *rn;
270 struct ospf_lsa *find;
271
272 table = lsdb->type[type].db;
273
274 memset (&lp, 0, sizeof (struct prefix_ls));
275 lp.family = 0;
276 lp.prefixlen = 64;
277 lp.id = id;
278 lp.adv_router = adv_router;
279
280 if (first)
281 rn = route_top (table);
282 else
283 {
Paul Jakmae8f22262010-04-13 22:43:34 +0100284 if ((rn = route_node_lookup (table, (struct prefix *) &lp)) == NULL)
285 return NULL;
paul718e3742002-12-13 20:15:29 +0000286 rn = route_next (rn);
287 }
288
289 for (; rn; rn = route_next (rn))
290 if (rn->info)
291 break;
292
293 if (rn && rn->info)
294 {
295 find = rn->info;
296 route_unlock_node (rn);
297 return find;
298 }
299 return NULL;
300}
301
302unsigned long
303ospf_lsdb_count_all (struct ospf_lsdb *lsdb)
304{
305 return lsdb->total;
306}
307
308unsigned long
309ospf_lsdb_count (struct ospf_lsdb *lsdb, int type)
310{
311 return lsdb->type[type].count;
312}
313
314unsigned long
315ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type)
316{
317 return lsdb->type[type].count_self;
318}
319
hassofe71a972004-12-22 16:16:02 +0000320unsigned int
321ospf_lsdb_checksum (struct ospf_lsdb *lsdb, int type)
322{
323 return lsdb->type[type].checksum;
324}
325
paul718e3742002-12-13 20:15:29 +0000326unsigned long
327ospf_lsdb_isempty (struct ospf_lsdb *lsdb)
328{
329 return (lsdb->total == 0);
330}