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