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