]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_lsdb.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / ospfd / ospf_lsdb.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * OSPF LSDB support.
4 * Copyright (C) 1999, 2000 Alex Zinin, Kunihiro Ishiguro, Toshiaki Takada
5 */
6
7 #include <zebra.h>
8
9 #include "prefix.h"
10 #include "table.h"
11 #include "memory.h"
12 #include "log.h"
13
14 #include "ospfd/ospfd.h"
15 #include "ospfd/ospf_asbr.h"
16 #include "ospfd/ospf_lsa.h"
17 #include "ospfd/ospf_lsdb.h"
18
19 struct ospf_lsdb *ospf_lsdb_new(void)
20 {
21 struct ospf_lsdb *new;
22
23 new = XCALLOC(MTYPE_OSPF_LSDB, sizeof(struct ospf_lsdb));
24 ospf_lsdb_init(new);
25
26 return new;
27 }
28
29 void ospf_lsdb_init(struct ospf_lsdb *lsdb)
30 {
31 int i;
32
33 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
34 lsdb->type[i].db = route_table_init();
35 }
36
37 void ospf_lsdb_free(struct ospf_lsdb *lsdb)
38 {
39 ospf_lsdb_cleanup(lsdb);
40 XFREE(MTYPE_OSPF_LSDB, lsdb);
41 }
42
43 void ospf_lsdb_cleanup(struct ospf_lsdb *lsdb)
44 {
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);
53 }
54
55 void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa)
56 {
57 if (lp && lsa && lsa->data) {
58 lp->family = AF_UNSPEC;
59 lp->prefixlen = 64;
60 lp->id = lsa->data->id;
61 lp->adv_router = lsa->data->adv_router;
62 }
63 }
64
65 static void ospf_lsdb_delete_entry(struct ospf_lsdb *lsdb,
66 struct route_node *rn)
67 {
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--;
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
95 rn->info = NULL;
96 route_unlock_node(rn);
97 #ifdef MONITOR_LSDB_CHANGE
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;
103 }
104
105 /* Add new LSA to lsdb. */
106 void ospf_lsdb_add(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
107 {
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++;
130
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
137 #ifdef MONITOR_LSDB_CHANGE
138 if (lsdb->new_lsa_hook != NULL)
139 (*lsdb->new_lsa_hook)(lsa);
140 #endif /* MONITOR_LSDB_CHANGE */
141 lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum);
142 rn->info = ospf_lsa_lock(lsa); /* lsdb */
143 }
144
145 void ospf_lsdb_delete(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
146 {
147 struct route_table *table;
148 struct prefix_ls lp;
149 struct route_node *rn;
150
151 if (!lsdb || !lsa)
152 return;
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 }
162 }
163
164 void ospf_lsdb_delete_all(struct ospf_lsdb *lsdb)
165 {
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 }
176 }
177
178 struct ospf_lsa *ospf_lsdb_lookup(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
179 {
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;
194 }
195
196 struct ospf_lsa *ospf_lsdb_lookup_by_id(struct ospf_lsdb *lsdb, uint8_t type,
197 struct in_addr id,
198 struct in_addr adv_router)
199 {
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
207 memset(&lp, 0, sizeof(lp));
208 lp.family = AF_UNSPEC;
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;
220 }
221
222 struct ospf_lsa *ospf_lsdb_lookup_by_id_next(struct ospf_lsdb *lsdb,
223 uint8_t type, struct in_addr id,
224 struct in_addr adv_router,
225 int first)
226 {
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
234 memset(&lp, 0, sizeof(lp));
235 lp.family = AF_UNSPEC;
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;
259 }
260
261 unsigned long ospf_lsdb_count_all(struct ospf_lsdb *lsdb)
262 {
263 return lsdb->total;
264 }
265
266 unsigned long ospf_lsdb_count(struct ospf_lsdb *lsdb, int type)
267 {
268 return lsdb->type[type].count;
269 }
270
271 unsigned long ospf_lsdb_count_self(struct ospf_lsdb *lsdb, int type)
272 {
273 return lsdb->type[type].count_self;
274 }
275
276 unsigned int ospf_lsdb_checksum(struct ospf_lsdb *lsdb, int type)
277 {
278 return lsdb->type[type].checksum;
279 }
280
281 unsigned long ospf_lsdb_isempty(struct ospf_lsdb *lsdb)
282 {
283 return (lsdb->total == 0);
284 }