]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_lsdb.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / ospfd / ospf_lsdb.c
CommitLineData
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 19struct 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 29void 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 37void 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 43void 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 55void 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 65static 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 106void 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 145void 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 164void 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 178struct 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 196struct 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 222struct 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 261unsigned long ospf_lsdb_count_all(struct ospf_lsdb *lsdb)
718e3744 262{
d62a17ae 263 return lsdb->total;
718e3744 264}
265
d62a17ae 266unsigned long ospf_lsdb_count(struct ospf_lsdb *lsdb, int type)
718e3744 267{
d62a17ae 268 return lsdb->type[type].count;
718e3744 269}
270
d62a17ae 271unsigned 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 276unsigned int ospf_lsdb_checksum(struct ospf_lsdb *lsdb, int type)
718e3744 277{
d62a17ae 278 return lsdb->type[type].checksum;
718e3744 279}
280
d62a17ae 281unsigned long ospf_lsdb_isempty(struct ospf_lsdb *lsdb)
718e3744 282{
d62a17ae 283 return (lsdb->total == 0);
718e3744 284}