]>
Commit | Line | Data |
---|---|---|
718e3744 | 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 | * | |
896014f4 DL |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; see the file COPYING; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 20 | */ |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "prefix.h" | |
25 | #include "table.h" | |
26 | #include "memory.h" | |
3fc1eca9 | 27 | #include "log.h" |
718e3744 | 28 | |
29 | #include "ospfd/ospfd.h" | |
30 | #include "ospfd/ospf_asbr.h" | |
31 | #include "ospfd/ospf_lsa.h" | |
32 | #include "ospfd/ospf_lsdb.h" | |
6b0655a2 | 33 | |
718e3744 | 34 | struct ospf_lsdb * |
35 | ospf_lsdb_new () | |
36 | { | |
37 | struct ospf_lsdb *new; | |
38 | ||
39 | new = XCALLOC (MTYPE_OSPF_LSDB, sizeof (struct ospf_lsdb)); | |
40 | ospf_lsdb_init (new); | |
41 | ||
42 | return new; | |
43 | } | |
44 | ||
45 | void | |
46 | ospf_lsdb_init (struct ospf_lsdb *lsdb) | |
47 | { | |
48 | int i; | |
49 | ||
50 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) | |
51 | lsdb->type[i].db = route_table_init (); | |
52 | } | |
53 | ||
54 | void | |
55 | ospf_lsdb_free (struct ospf_lsdb *lsdb) | |
56 | { | |
57 | ospf_lsdb_cleanup (lsdb); | |
58 | XFREE (MTYPE_OSPF_LSDB, lsdb); | |
59 | } | |
60 | ||
61 | void | |
62 | ospf_lsdb_cleanup (struct ospf_lsdb *lsdb) | |
63 | { | |
64 | int i; | |
65 | assert (lsdb); | |
66 | assert (lsdb->total == 0); | |
67 | ||
68 | ospf_lsdb_delete_all (lsdb); | |
69 | ||
70 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) | |
71 | route_table_finish (lsdb->type[i].db); | |
72 | } | |
73 | ||
91e6a0e5 DD |
74 | void |
75 | ls_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa) | |
718e3744 | 76 | { |
91e6a0e5 DD |
77 | if (lp && lsa && lsa->data) |
78 | { | |
79 | lp->family = 0; | |
80 | lp->prefixlen = 64; | |
81 | lp->id = lsa->data->id; | |
82 | lp->adv_router = lsa->data->adv_router; | |
83 | } | |
718e3744 | 84 | } |
85 | ||
ba122e77 PJ |
86 | static void |
87 | ospf_lsdb_delete_entry (struct ospf_lsdb *lsdb, struct route_node *rn) | |
88 | { | |
89 | struct ospf_lsa *lsa = rn->info; | |
90 | ||
91 | if (!lsa) | |
92 | return; | |
93 | ||
94 | assert (rn->table == lsdb->type[lsa->data->type].db); | |
95 | ||
96 | if (IS_LSA_SELF (lsa)) | |
97 | lsdb->type[lsa->data->type].count_self--; | |
98 | lsdb->type[lsa->data->type].count--; | |
99 | lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum); | |
100 | lsdb->total--; | |
101 | rn->info = NULL; | |
102 | route_unlock_node (rn); | |
103 | #ifdef MONITOR_LSDB_CHANGE | |
104 | if (lsdb->del_lsa_hook != NULL) | |
105 | (* lsdb->del_lsa_hook)(lsa); | |
106 | #endif /* MONITOR_LSDB_CHANGE */ | |
107 | ospf_lsa_unlock (&lsa); /* lsdb */ | |
108 | return; | |
109 | } | |
110 | ||
718e3744 | 111 | /* Add new LSA to lsdb. */ |
112 | void | |
113 | ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) | |
114 | { | |
115 | struct route_table *table; | |
116 | struct prefix_ls lp; | |
117 | struct route_node *rn; | |
118 | ||
119 | table = lsdb->type[lsa->data->type].db; | |
91e6a0e5 | 120 | ls_prefix_set (&lp, lsa); |
718e3744 | 121 | rn = route_node_get (table, (struct prefix *)&lp); |
ba122e77 PJ |
122 | |
123 | /* nothing to do? */ | |
124 | if (rn->info && rn->info == lsa) | |
e8f22261 PJ |
125 | { |
126 | route_unlock_node (rn); | |
127 | return; | |
128 | } | |
ba122e77 PJ |
129 | |
130 | /* purge old entry? */ | |
131 | if (rn->info) | |
132 | ospf_lsdb_delete_entry (lsdb, rn); | |
133 | ||
134 | if (IS_LSA_SELF (lsa)) | |
135 | lsdb->type[lsa->data->type].count_self++; | |
136 | lsdb->type[lsa->data->type].count++; | |
137 | lsdb->total++; | |
718e3744 | 138 | |
139 | #ifdef MONITOR_LSDB_CHANGE | |
140 | if (lsdb->new_lsa_hook != NULL) | |
141 | (* lsdb->new_lsa_hook)(lsa); | |
142 | #endif /* MONITOR_LSDB_CHANGE */ | |
082253f5 | 143 | lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum); |
ba122e77 | 144 | rn->info = ospf_lsa_lock (lsa); /* lsdb */ |
718e3744 | 145 | } |
146 | ||
147 | void | |
148 | ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) | |
149 | { | |
150 | struct route_table *table; | |
151 | struct prefix_ls lp; | |
152 | struct route_node *rn; | |
153 | ||
ac904dec PJ |
154 | if (!lsdb) |
155 | { | |
156 | zlog_warn ("%s: Called with NULL LSDB", __func__); | |
157 | if (lsa) | |
158 | zlog_warn ("LSA[Type%d:%s]: LSA %p, lsa->lsdb %p", | |
159 | lsa->data->type, inet_ntoa (lsa->data->id), | |
6c4f4e6e | 160 | (void *)lsa, (void *)lsa->lsdb); |
ac904dec PJ |
161 | return; |
162 | } | |
163 | ||
164 | if (!lsa) | |
165 | { | |
166 | zlog_warn ("%s: Called with NULL LSA", __func__); | |
167 | return; | |
168 | } | |
169 | ||
e8f22261 | 170 | assert (lsa->data->type < OSPF_MAX_LSA); |
718e3744 | 171 | table = lsdb->type[lsa->data->type].db; |
91e6a0e5 | 172 | ls_prefix_set (&lp, lsa); |
e8f22261 | 173 | if ((rn = route_node_lookup (table, (struct prefix *) &lp))) |
ba122e77 | 174 | { |
e8f22261 PJ |
175 | if (rn->info == lsa) |
176 | ospf_lsdb_delete_entry (lsdb, rn); | |
ba122e77 PJ |
177 | route_unlock_node (rn); /* route_node_lookup */ |
178 | } | |
718e3744 | 179 | } |
180 | ||
181 | void | |
182 | ospf_lsdb_delete_all (struct ospf_lsdb *lsdb) | |
183 | { | |
184 | struct route_table *table; | |
185 | struct route_node *rn; | |
718e3744 | 186 | int i; |
187 | ||
188 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) | |
189 | { | |
190 | table = lsdb->type[i].db; | |
191 | for (rn = route_top (table); rn; rn = route_next (rn)) | |
ba122e77 PJ |
192 | if (rn->info != NULL) |
193 | ospf_lsdb_delete_entry (lsdb, rn); | |
718e3744 | 194 | } |
195 | } | |
196 | ||
462f20d5 | 197 | void |
198 | ospf_lsdb_clean_stat (struct ospf_lsdb *lsdb) | |
199 | { | |
200 | struct route_table *table; | |
201 | struct route_node *rn; | |
202 | struct ospf_lsa *lsa; | |
203 | int i; | |
204 | ||
205 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) | |
206 | { | |
207 | table = lsdb->type[i].db; | |
208 | for (rn = route_top (table); rn; rn = route_next (rn)) | |
209 | if ((lsa = (rn->info)) != NULL) | |
210 | lsa->stat = LSA_SPF_NOT_EXPLORED; | |
211 | } | |
212 | } | |
213 | ||
718e3744 | 214 | struct ospf_lsa * |
215 | ospf_lsdb_lookup (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) | |
216 | { | |
217 | struct route_table *table; | |
218 | struct prefix_ls lp; | |
219 | struct route_node *rn; | |
220 | struct ospf_lsa *find; | |
221 | ||
222 | table = lsdb->type[lsa->data->type].db; | |
91e6a0e5 | 223 | ls_prefix_set (&lp, lsa); |
718e3744 | 224 | rn = route_node_lookup (table, (struct prefix *) &lp); |
225 | if (rn) | |
226 | { | |
227 | find = rn->info; | |
228 | route_unlock_node (rn); | |
229 | return find; | |
230 | } | |
231 | return NULL; | |
232 | } | |
233 | ||
234 | struct ospf_lsa * | |
235 | ospf_lsdb_lookup_by_id (struct ospf_lsdb *lsdb, u_char type, | |
236 | struct in_addr id, struct in_addr adv_router) | |
237 | { | |
238 | struct route_table *table; | |
239 | struct prefix_ls lp; | |
240 | struct route_node *rn; | |
241 | struct ospf_lsa *find; | |
242 | ||
243 | table = lsdb->type[type].db; | |
244 | ||
245 | memset (&lp, 0, sizeof (struct prefix_ls)); | |
246 | lp.family = 0; | |
247 | lp.prefixlen = 64; | |
248 | lp.id = id; | |
249 | lp.adv_router = adv_router; | |
250 | ||
251 | rn = route_node_lookup (table, (struct prefix *) &lp); | |
252 | if (rn) | |
253 | { | |
254 | find = rn->info; | |
255 | route_unlock_node (rn); | |
256 | return find; | |
257 | } | |
258 | return NULL; | |
259 | } | |
260 | ||
261 | struct ospf_lsa * | |
262 | ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *lsdb, u_char type, | |
263 | struct in_addr id, struct in_addr adv_router, | |
264 | int first) | |
265 | { | |
266 | struct route_table *table; | |
267 | struct prefix_ls lp; | |
268 | struct route_node *rn; | |
269 | struct ospf_lsa *find; | |
270 | ||
271 | table = lsdb->type[type].db; | |
272 | ||
273 | memset (&lp, 0, sizeof (struct prefix_ls)); | |
274 | lp.family = 0; | |
275 | lp.prefixlen = 64; | |
276 | lp.id = id; | |
277 | lp.adv_router = adv_router; | |
278 | ||
279 | if (first) | |
280 | rn = route_top (table); | |
281 | else | |
282 | { | |
e8f22261 PJ |
283 | if ((rn = route_node_lookup (table, (struct prefix *) &lp)) == NULL) |
284 | return NULL; | |
718e3744 | 285 | rn = route_next (rn); |
286 | } | |
287 | ||
288 | for (; rn; rn = route_next (rn)) | |
289 | if (rn->info) | |
290 | break; | |
291 | ||
292 | if (rn && rn->info) | |
293 | { | |
294 | find = rn->info; | |
295 | route_unlock_node (rn); | |
296 | return find; | |
297 | } | |
298 | return NULL; | |
299 | } | |
300 | ||
301 | unsigned long | |
302 | ospf_lsdb_count_all (struct ospf_lsdb *lsdb) | |
303 | { | |
304 | return lsdb->total; | |
305 | } | |
306 | ||
307 | unsigned long | |
308 | ospf_lsdb_count (struct ospf_lsdb *lsdb, int type) | |
309 | { | |
310 | return lsdb->type[type].count; | |
311 | } | |
312 | ||
313 | unsigned long | |
314 | ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type) | |
315 | { | |
316 | return lsdb->type[type].count_self; | |
317 | } | |
318 | ||
fe71a97d | 319 | unsigned int |
320 | ospf_lsdb_checksum (struct ospf_lsdb *lsdb, int type) | |
718e3744 | 321 | { |
fe71a97d | 322 | return lsdb->type[type].checksum; |
718e3744 | 323 | } |
324 | ||
fe71a97d | 325 | unsigned long |
326 | ospf_lsdb_isempty (struct ospf_lsdb *lsdb) | |
718e3744 | 327 | { |
fe71a97d | 328 | return (lsdb->total == 0); |
718e3744 | 329 | } |