]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
718e3744 | 2 | /* |
3 | * OSPF LSDB support. | |
4 | * Copyright (C) 1999, 2000 Alex Zinin, Kunihiro Ishiguro, Toshiaki Takada | |
718e3744 | 5 | */ |
6 | ||
7 | #include <zebra.h> | |
8 | ||
9 | #include "prefix.h" | |
10 | #include "table.h" | |
11 | #include "memory.h" | |
3fc1eca9 | 12 | #include "log.h" |
718e3744 | 13 | |
14 | #include "ospfd/ospfd.h" | |
15 | #include "ospfd/ospf_asbr.h" | |
16 | #include "ospfd/ospf_lsa.h" | |
17 | #include "ospfd/ospf_lsdb.h" | |
6b0655a2 | 18 | |
4d762f26 | 19 | struct ospf_lsdb *ospf_lsdb_new(void) |
718e3744 | 20 | { |
d62a17ae | 21 | struct ospf_lsdb *new; |
718e3744 | 22 | |
d62a17ae | 23 | new = XCALLOC(MTYPE_OSPF_LSDB, sizeof(struct ospf_lsdb)); |
24 | ospf_lsdb_init(new); | |
718e3744 | 25 | |
d62a17ae | 26 | return new; |
718e3744 | 27 | } |
28 | ||
d62a17ae | 29 | void ospf_lsdb_init(struct ospf_lsdb *lsdb) |
718e3744 | 30 | { |
d62a17ae | 31 | int i; |
32 | ||
33 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) | |
34 | lsdb->type[i].db = route_table_init(); | |
718e3744 | 35 | } |
36 | ||
d62a17ae | 37 | void ospf_lsdb_free(struct ospf_lsdb *lsdb) |
718e3744 | 38 | { |
d62a17ae | 39 | ospf_lsdb_cleanup(lsdb); |
40 | XFREE(MTYPE_OSPF_LSDB, lsdb); | |
718e3744 | 41 | } |
42 | ||
d62a17ae | 43 | void ospf_lsdb_cleanup(struct ospf_lsdb *lsdb) |
718e3744 | 44 | { |
d62a17ae | 45 | int i; |
46 | assert(lsdb); | |
47 | assert(lsdb->total == 0); | |
48 | ||
49 | ospf_lsdb_delete_all(lsdb); | |
50 | ||
51 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) | |
52 | route_table_finish(lsdb->type[i].db); | |
718e3744 | 53 | } |
54 | ||
d62a17ae | 55 | void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa) |
718e3744 | 56 | { |
d62a17ae | 57 | if (lp && lsa && lsa->data) { |
abb1bf8d | 58 | lp->family = AF_UNSPEC; |
d62a17ae | 59 | lp->prefixlen = 64; |
60 | lp->id = lsa->data->id; | |
61 | lp->adv_router = lsa->data->adv_router; | |
62 | } | |
718e3744 | 63 | } |
64 | ||
d62a17ae | 65 | static void ospf_lsdb_delete_entry(struct ospf_lsdb *lsdb, |
66 | struct route_node *rn) | |
ba122e77 | 67 | { |
d62a17ae | 68 | struct ospf_lsa *lsa = rn->info; |
69 | ||
70 | if (!lsa) | |
71 | return; | |
72 | ||
73 | assert(rn->table == lsdb->type[lsa->data->type].db); | |
74 | ||
75 | if (IS_LSA_SELF(lsa)) | |
76 | lsdb->type[lsa->data->type].count_self--; | |
77 | lsdb->type[lsa->data->type].count--; | |
78 | lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum); | |
79 | lsdb->total--; | |
516c4c66 MN |
80 | |
81 | /* Decrement number of router LSAs received with DC bit set */ | |
82 | if (lsa->area && (lsa->area->lsdb == lsdb) && !IS_LSA_SELF(lsa) && | |
83 | (lsa->data->type == OSPF_ROUTER_LSA) && | |
84 | CHECK_FLAG(lsa->data->options, OSPF_OPTION_DC)) | |
85 | lsa->area->fr_info.router_lsas_recv_dc_bit--; | |
86 | ||
87 | /* | |
88 | * If the LSA being deleted is indication LSA, then set the | |
89 | * pointer to NULL. | |
90 | */ | |
91 | if (lsa->area && lsa->area->fr_info.indication_lsa_self && | |
92 | (lsa->area->fr_info.indication_lsa_self == lsa)) | |
93 | lsa->area->fr_info.indication_lsa_self = NULL; | |
94 | ||
d62a17ae | 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 | |
516c4c66 MN |
131 | /* Increment number of router LSAs received with DC bit set */ |
132 | if (lsa->area && (lsa->area->lsdb == lsdb) && !IS_LSA_SELF(lsa) && | |
133 | (lsa->data->type == OSPF_ROUTER_LSA) && | |
134 | CHECK_FLAG(lsa->data->options, OSPF_OPTION_DC)) | |
135 | lsa->area->fr_info.router_lsas_recv_dc_bit++; | |
136 | ||
718e3744 | 137 | #ifdef MONITOR_LSDB_CHANGE |
d62a17ae | 138 | if (lsdb->new_lsa_hook != NULL) |
139 | (*lsdb->new_lsa_hook)(lsa); | |
718e3744 | 140 | #endif /* MONITOR_LSDB_CHANGE */ |
d62a17ae | 141 | lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum); |
142 | rn->info = ospf_lsa_lock(lsa); /* lsdb */ | |
718e3744 | 143 | } |
144 | ||
d62a17ae | 145 | void ospf_lsdb_delete(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) |
718e3744 | 146 | { |
d62a17ae | 147 | struct route_table *table; |
148 | struct prefix_ls lp; | |
149 | struct route_node *rn; | |
150 | ||
266469eb | 151 | if (!lsdb || !lsa) |
d62a17ae | 152 | return; |
d62a17ae | 153 | |
154 | assert(lsa->data->type < OSPF_MAX_LSA); | |
155 | table = lsdb->type[lsa->data->type].db; | |
156 | ls_prefix_set(&lp, lsa); | |
157 | if ((rn = route_node_lookup(table, (struct prefix *)&lp))) { | |
158 | if (rn->info == lsa) | |
159 | ospf_lsdb_delete_entry(lsdb, rn); | |
160 | route_unlock_node(rn); /* route_node_lookup */ | |
161 | } | |
718e3744 | 162 | } |
163 | ||
d62a17ae | 164 | void ospf_lsdb_delete_all(struct ospf_lsdb *lsdb) |
718e3744 | 165 | { |
d62a17ae | 166 | struct route_table *table; |
167 | struct route_node *rn; | |
168 | int i; | |
169 | ||
170 | for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { | |
171 | table = lsdb->type[i].db; | |
172 | for (rn = route_top(table); rn; rn = route_next(rn)) | |
173 | if (rn->info != NULL) | |
174 | ospf_lsdb_delete_entry(lsdb, rn); | |
175 | } | |
718e3744 | 176 | } |
177 | ||
d62a17ae | 178 | struct ospf_lsa *ospf_lsdb_lookup(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) |
718e3744 | 179 | { |
d62a17ae | 180 | struct route_table *table; |
181 | struct prefix_ls lp; | |
182 | struct route_node *rn; | |
183 | struct ospf_lsa *find; | |
184 | ||
185 | table = lsdb->type[lsa->data->type].db; | |
186 | ls_prefix_set(&lp, lsa); | |
187 | rn = route_node_lookup(table, (struct prefix *)&lp); | |
188 | if (rn) { | |
189 | find = rn->info; | |
190 | route_unlock_node(rn); | |
191 | return find; | |
192 | } | |
193 | return NULL; | |
718e3744 | 194 | } |
195 | ||
d7c0a89a | 196 | struct ospf_lsa *ospf_lsdb_lookup_by_id(struct ospf_lsdb *lsdb, uint8_t type, |
d62a17ae | 197 | struct in_addr id, |
198 | struct in_addr adv_router) | |
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[type].db; | |
206 | ||
6006b807 | 207 | memset(&lp, 0, sizeof(lp)); |
abb1bf8d | 208 | lp.family = AF_UNSPEC; |
d62a17ae | 209 | lp.prefixlen = 64; |
210 | lp.id = id; | |
211 | lp.adv_router = adv_router; | |
212 | ||
213 | rn = route_node_lookup(table, (struct prefix *)&lp); | |
214 | if (rn) { | |
215 | find = rn->info; | |
216 | route_unlock_node(rn); | |
217 | return find; | |
218 | } | |
219 | return NULL; | |
718e3744 | 220 | } |
221 | ||
d62a17ae | 222 | struct ospf_lsa *ospf_lsdb_lookup_by_id_next(struct ospf_lsdb *lsdb, |
d7c0a89a | 223 | uint8_t type, struct in_addr id, |
d62a17ae | 224 | struct in_addr adv_router, |
225 | int first) | |
718e3744 | 226 | { |
d62a17ae | 227 | struct route_table *table; |
228 | struct prefix_ls lp; | |
229 | struct route_node *rn; | |
230 | struct ospf_lsa *find; | |
231 | ||
232 | table = lsdb->type[type].db; | |
233 | ||
6006b807 | 234 | memset(&lp, 0, sizeof(lp)); |
abb1bf8d | 235 | lp.family = AF_UNSPEC; |
d62a17ae | 236 | lp.prefixlen = 64; |
237 | lp.id = id; | |
238 | lp.adv_router = adv_router; | |
239 | ||
240 | if (first) | |
241 | rn = route_top(table); | |
242 | else { | |
243 | if ((rn = route_node_lookup(table, (struct prefix *)&lp)) | |
244 | == NULL) | |
245 | return NULL; | |
246 | rn = route_next(rn); | |
247 | } | |
248 | ||
249 | for (; rn; rn = route_next(rn)) | |
250 | if (rn->info) | |
251 | break; | |
252 | ||
253 | if (rn && rn->info) { | |
254 | find = rn->info; | |
255 | route_unlock_node(rn); | |
256 | return find; | |
257 | } | |
258 | return NULL; | |
718e3744 | 259 | } |
260 | ||
d62a17ae | 261 | unsigned long ospf_lsdb_count_all(struct ospf_lsdb *lsdb) |
718e3744 | 262 | { |
d62a17ae | 263 | return lsdb->total; |
718e3744 | 264 | } |
265 | ||
d62a17ae | 266 | unsigned long ospf_lsdb_count(struct ospf_lsdb *lsdb, int type) |
718e3744 | 267 | { |
d62a17ae | 268 | return lsdb->type[type].count; |
718e3744 | 269 | } |
270 | ||
d62a17ae | 271 | unsigned long ospf_lsdb_count_self(struct ospf_lsdb *lsdb, int type) |
718e3744 | 272 | { |
d62a17ae | 273 | return lsdb->type[type].count_self; |
718e3744 | 274 | } |
275 | ||
d62a17ae | 276 | unsigned int ospf_lsdb_checksum(struct ospf_lsdb *lsdb, int type) |
718e3744 | 277 | { |
d62a17ae | 278 | return lsdb->type[type].checksum; |
718e3744 | 279 | } |
280 | ||
d62a17ae | 281 | unsigned long ospf_lsdb_isempty(struct ospf_lsdb *lsdb) |
718e3744 | 282 | { |
d62a17ae | 283 | return (lsdb->total == 0); |
718e3744 | 284 | } |