]>
git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_lsdb.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 1999, 2000 Alex Zinin, Kunihiro Ishiguro, Toshiaki Takada
14 #include "ospfd/ospfd.h"
15 #include "ospfd/ospf_asbr.h"
16 #include "ospfd/ospf_lsa.h"
17 #include "ospfd/ospf_lsdb.h"
19 struct ospf_lsdb
*ospf_lsdb_new(void)
21 struct ospf_lsdb
*new;
23 new = XCALLOC(MTYPE_OSPF_LSDB
, sizeof(struct ospf_lsdb
));
29 void ospf_lsdb_init(struct ospf_lsdb
*lsdb
)
33 for (i
= OSPF_MIN_LSA
; i
< OSPF_MAX_LSA
; i
++)
34 lsdb
->type
[i
].db
= route_table_init();
37 void ospf_lsdb_free(struct ospf_lsdb
*lsdb
)
39 ospf_lsdb_cleanup(lsdb
);
40 XFREE(MTYPE_OSPF_LSDB
, lsdb
);
43 void ospf_lsdb_cleanup(struct ospf_lsdb
*lsdb
)
47 assert(lsdb
->total
== 0);
49 ospf_lsdb_delete_all(lsdb
);
51 for (i
= OSPF_MIN_LSA
; i
< OSPF_MAX_LSA
; i
++)
52 route_table_finish(lsdb
->type
[i
].db
);
55 void ls_prefix_set(struct prefix_ls
*lp
, struct ospf_lsa
*lsa
)
57 if (lp
&& lsa
&& lsa
->data
) {
58 lp
->family
= AF_UNSPEC
;
60 lp
->id
= lsa
->data
->id
;
61 lp
->adv_router
= lsa
->data
->adv_router
;
65 static void ospf_lsdb_delete_entry(struct ospf_lsdb
*lsdb
,
66 struct route_node
*rn
)
68 struct ospf_lsa
*lsa
= rn
->info
;
73 assert(rn
->table
== lsdb
->type
[lsa
->data
->type
].db
);
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
);
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
--;
88 * If the LSA being deleted is indication LSA, then set the
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
;
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 */
105 /* Add new LSA to lsdb. */
106 void ospf_lsdb_add(struct ospf_lsdb
*lsdb
, struct ospf_lsa
*lsa
)
108 struct route_table
*table
;
110 struct route_node
*rn
;
112 table
= lsdb
->type
[lsa
->data
->type
].db
;
113 ls_prefix_set(&lp
, lsa
);
114 rn
= route_node_get(table
, (struct prefix
*)&lp
);
117 if (rn
->info
&& rn
->info
== lsa
) {
118 route_unlock_node(rn
);
122 /* purge old entry? */
124 ospf_lsdb_delete_entry(lsdb
, rn
);
126 if (IS_LSA_SELF(lsa
))
127 lsdb
->type
[lsa
->data
->type
].count_self
++;
128 lsdb
->type
[lsa
->data
->type
].count
++;
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
++;
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 */
145 void ospf_lsdb_delete(struct ospf_lsdb
*lsdb
, struct ospf_lsa
*lsa
)
147 struct route_table
*table
;
149 struct route_node
*rn
;
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
))) {
159 ospf_lsdb_delete_entry(lsdb
, rn
);
160 route_unlock_node(rn
); /* route_node_lookup */
164 void ospf_lsdb_delete_all(struct ospf_lsdb
*lsdb
)
166 struct route_table
*table
;
167 struct route_node
*rn
;
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
);
178 struct ospf_lsa
*ospf_lsdb_lookup(struct ospf_lsdb
*lsdb
, struct ospf_lsa
*lsa
)
180 struct route_table
*table
;
182 struct route_node
*rn
;
183 struct ospf_lsa
*find
;
185 table
= lsdb
->type
[lsa
->data
->type
].db
;
186 ls_prefix_set(&lp
, lsa
);
187 rn
= route_node_lookup(table
, (struct prefix
*)&lp
);
190 route_unlock_node(rn
);
196 struct ospf_lsa
*ospf_lsdb_lookup_by_id(struct ospf_lsdb
*lsdb
, uint8_t type
,
198 struct in_addr adv_router
)
200 struct route_table
*table
;
202 struct route_node
*rn
;
203 struct ospf_lsa
*find
;
205 table
= lsdb
->type
[type
].db
;
207 memset(&lp
, 0, sizeof(lp
));
208 lp
.family
= AF_UNSPEC
;
211 lp
.adv_router
= adv_router
;
213 rn
= route_node_lookup(table
, (struct prefix
*)&lp
);
216 route_unlock_node(rn
);
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
,
227 struct route_table
*table
;
229 struct route_node
*rn
;
230 struct ospf_lsa
*find
;
232 table
= lsdb
->type
[type
].db
;
234 memset(&lp
, 0, sizeof(lp
));
235 lp
.family
= AF_UNSPEC
;
238 lp
.adv_router
= adv_router
;
241 rn
= route_top(table
);
243 if ((rn
= route_node_lookup(table
, (struct prefix
*)&lp
))
249 for (; rn
; rn
= route_next(rn
))
253 if (rn
&& rn
->info
) {
255 route_unlock_node(rn
);
261 unsigned long ospf_lsdb_count_all(struct ospf_lsdb
*lsdb
)
266 unsigned long ospf_lsdb_count(struct ospf_lsdb
*lsdb
, int type
)
268 return lsdb
->type
[type
].count
;
271 unsigned long ospf_lsdb_count_self(struct ospf_lsdb
*lsdb
, int type
)
273 return lsdb
->type
[type
].count_self
;
276 unsigned int ospf_lsdb_checksum(struct ospf_lsdb
*lsdb
, int type
)
278 return lsdb
->type
[type
].checksum
;
281 unsigned long ospf_lsdb_isempty(struct ospf_lsdb
*lsdb
)
283 return (lsdb
->total
== 0);