Merge tag 'upstream/1.2.4'
[quagga-debian.git] / ospfd / ospf_lsdb.c
1 /*
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"
28 #include "log.h"
29
30 #include "ospfd/ospfd.h"
31 #include "ospfd/ospf_asbr.h"
32 #include "ospfd/ospf_lsa.h"
33 #include "ospfd/ospf_lsdb.h"
34
35 struct ospf_lsdb *
36 ospf_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
46 void
47 ospf_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
55 void
56 ospf_lsdb_free (struct ospf_lsdb *lsdb)
57 {
58   ospf_lsdb_cleanup (lsdb);
59   XFREE (MTYPE_OSPF_LSDB, lsdb);
60 }
61
62 void
63 ospf_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
75 void
76 ls_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa)
77 {
78   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     }
85 }
86
87 static void
88 ospf_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
112 /* Add new LSA to lsdb. */
113 void
114 ospf_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;
121   ls_prefix_set (&lp, lsa);
122   rn = route_node_get (table, (struct prefix *)&lp);
123   
124   /* nothing to do? */
125   if (rn->info && rn->info == lsa)
126     {
127       route_unlock_node (rn);
128       return;
129     }
130   
131   /* purge old entry? */
132   if (rn->info)
133     ospf_lsdb_delete_entry (lsdb, rn);
134
135   if (IS_LSA_SELF (lsa))
136     lsdb->type[lsa->data->type].count_self++;
137   lsdb->type[lsa->data->type].count++;
138   lsdb->total++;
139
140 #ifdef MONITOR_LSDB_CHANGE
141   if (lsdb->new_lsa_hook != NULL)
142     (* lsdb->new_lsa_hook)(lsa);
143 #endif /* MONITOR_LSDB_CHANGE */
144   lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum);
145   rn->info = ospf_lsa_lock (lsa); /* lsdb */
146 }
147
148 void
149 ospf_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
155   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                    (void *)lsa, (void *)lsa->lsdb);
162       return;
163     }
164   
165   if (!lsa)
166     {
167       zlog_warn ("%s: Called with NULL LSA", __func__);
168       return;
169     }
170   
171   assert (lsa->data->type < OSPF_MAX_LSA);
172   table = lsdb->type[lsa->data->type].db;
173   ls_prefix_set (&lp, lsa);
174   if ((rn = route_node_lookup (table, (struct prefix *) &lp)))
175     {
176       if (rn->info == lsa)
177         ospf_lsdb_delete_entry (lsdb, rn);
178       route_unlock_node (rn); /* route_node_lookup */
179     }
180 }
181
182 void
183 ospf_lsdb_delete_all (struct ospf_lsdb *lsdb)
184 {
185   struct route_table *table;
186   struct route_node *rn;
187   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))
193         if (rn->info != NULL)
194           ospf_lsdb_delete_entry (lsdb, rn);
195     }
196 }
197
198 void
199 ospf_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
215 struct ospf_lsa *
216 ospf_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;
224   ls_prefix_set (&lp, lsa);
225   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
235 struct ospf_lsa *
236 ospf_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
262 struct ospf_lsa *
263 ospf_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     {
284       if ((rn = route_node_lookup (table, (struct prefix *) &lp)) == NULL)
285         return NULL;
286       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
302 unsigned long
303 ospf_lsdb_count_all (struct ospf_lsdb *lsdb)
304 {
305   return lsdb->total;
306 }
307
308 unsigned long
309 ospf_lsdb_count (struct ospf_lsdb *lsdb, int type)
310 {
311   return lsdb->type[type].count;
312 }
313
314 unsigned long
315 ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type)
316 {
317   return lsdb->type[type].count_self;
318 }
319
320 unsigned int
321 ospf_lsdb_checksum (struct ospf_lsdb *lsdb, int type)
322 {
323   return lsdb->type[type].checksum;
324 }
325
326 unsigned long
327 ospf_lsdb_isempty (struct ospf_lsdb *lsdb)
328 {
329   return (lsdb->total == 0);
330 }