]>
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 | |
4d762f26 | 34 | struct ospf_lsdb *ospf_lsdb_new(void) |
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 | ||
266469eb | 145 | if (!lsdb || !lsa) |
d62a17ae | 146 | return; |
d62a17ae | 147 | |
148 | assert(lsa->data->type < OSPF_MAX_LSA); | |
149 | table = lsdb->type[lsa->data->type].db; | |
150 | ls_prefix_set(&lp, lsa); | |
151 | if ((rn = route_node_lookup(table, (struct prefix *)&lp))) { | |
152 | if (rn->info == lsa) | |
153 | ospf_lsdb_delete_entry(lsdb, rn); | |
154 | route_unlock_node(rn); /* route_node_lookup */ | |
155 | } | |
718e3744 | 156 | } |
157 | ||
d62a17ae | 158 | void ospf_lsdb_delete_all(struct ospf_lsdb *lsdb) |
718e3744 | 159 | { |
d62a17ae | 160 | struct route_table *table; |
161 | struct route_node *rn; | |
162 | int i; | |
163 | ||
164 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { | |
165 | table = lsdb->type[i].db; | |
166 | for (rn = route_top(table); rn; rn = route_next(rn)) | |
167 | if (rn->info != NULL) | |
168 | ospf_lsdb_delete_entry(lsdb, rn); | |
169 | } | |
718e3744 | 170 | } |
171 | ||
d62a17ae | 172 | struct ospf_lsa *ospf_lsdb_lookup(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) |
718e3744 | 173 | { |
d62a17ae | 174 | struct route_table *table; |
175 | struct prefix_ls lp; | |
176 | struct route_node *rn; | |
177 | struct ospf_lsa *find; | |
178 | ||
179 | table = lsdb->type[lsa->data->type].db; | |
180 | ls_prefix_set(&lp, lsa); | |
181 | rn = route_node_lookup(table, (struct prefix *)&lp); | |
182 | if (rn) { | |
183 | find = rn->info; | |
184 | route_unlock_node(rn); | |
185 | return find; | |
186 | } | |
187 | return NULL; | |
718e3744 | 188 | } |
189 | ||
d7c0a89a | 190 | struct ospf_lsa *ospf_lsdb_lookup_by_id(struct ospf_lsdb *lsdb, uint8_t type, |
d62a17ae | 191 | struct in_addr id, |
192 | struct in_addr adv_router) | |
718e3744 | 193 | { |
d62a17ae | 194 | struct route_table *table; |
195 | struct prefix_ls lp; | |
196 | struct route_node *rn; | |
197 | struct ospf_lsa *find; | |
198 | ||
199 | table = lsdb->type[type].db; | |
200 | ||
201 | memset(&lp, 0, sizeof(struct prefix_ls)); | |
202 | lp.family = 0; | |
203 | lp.prefixlen = 64; | |
204 | lp.id = id; | |
205 | lp.adv_router = adv_router; | |
206 | ||
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 | ||
d62a17ae | 216 | struct ospf_lsa *ospf_lsdb_lookup_by_id_next(struct ospf_lsdb *lsdb, |
d7c0a89a | 217 | uint8_t type, struct in_addr id, |
d62a17ae | 218 | struct in_addr adv_router, |
219 | int first) | |
718e3744 | 220 | { |
d62a17ae | 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 | if (first) | |
235 | rn = route_top(table); | |
236 | else { | |
237 | if ((rn = route_node_lookup(table, (struct prefix *)&lp)) | |
238 | == NULL) | |
239 | return NULL; | |
240 | rn = route_next(rn); | |
241 | } | |
242 | ||
243 | for (; rn; rn = route_next(rn)) | |
244 | if (rn->info) | |
245 | break; | |
246 | ||
247 | if (rn && rn->info) { | |
248 | find = rn->info; | |
249 | route_unlock_node(rn); | |
250 | return find; | |
251 | } | |
252 | return NULL; | |
718e3744 | 253 | } |
254 | ||
d62a17ae | 255 | unsigned long ospf_lsdb_count_all(struct ospf_lsdb *lsdb) |
718e3744 | 256 | { |
d62a17ae | 257 | return lsdb->total; |
718e3744 | 258 | } |
259 | ||
d62a17ae | 260 | unsigned long ospf_lsdb_count(struct ospf_lsdb *lsdb, int type) |
718e3744 | 261 | { |
d62a17ae | 262 | return lsdb->type[type].count; |
718e3744 | 263 | } |
264 | ||
d62a17ae | 265 | unsigned long ospf_lsdb_count_self(struct ospf_lsdb *lsdb, int type) |
718e3744 | 266 | { |
d62a17ae | 267 | return lsdb->type[type].count_self; |
718e3744 | 268 | } |
269 | ||
d62a17ae | 270 | unsigned int ospf_lsdb_checksum(struct ospf_lsdb *lsdb, int type) |
718e3744 | 271 | { |
d62a17ae | 272 | return lsdb->type[type].checksum; |
718e3744 | 273 | } |
274 | ||
d62a17ae | 275 | unsigned long ospf_lsdb_isempty(struct ospf_lsdb *lsdb) |
718e3744 | 276 | { |
d62a17ae | 277 | return (lsdb->total == 0); |
718e3744 | 278 | } |