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 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Zebra; see the file COPYING. If not, write to the Free 19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 */ 22 23#include <zebra.h> 24 25#include "prefix.h" 26#include "table.h" 27#include "memory.h" 28 29#include "ospfd/ospfd.h" 30#include "ospfd/ospf_asbr.h" 31#include "ospfd/ospf_lsa.h" 32#include "ospfd/ospf_lsdb.h" 33 34struct ospf_lsdb * 35ospf_lsdb_new () 36{ 37 struct ospf_lsdb *new; 38 39 new = XCALLOC (MTYPE_OSPF_LSDB, sizeof (struct ospf_lsdb)); 40 ospf_lsdb_init (new); 41 42 return new; 43} 44 45void 46ospf_lsdb_init (struct ospf_lsdb *lsdb) 47{ 48 int i; 49 50 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) 51 lsdb->type[i].db = route_table_init (); 52} 53 54void 55ospf_lsdb_free (struct ospf_lsdb *lsdb) 56{ 57 ospf_lsdb_cleanup (lsdb); 58 XFREE (MTYPE_OSPF_LSDB, lsdb); 59} 60 61void 62ospf_lsdb_cleanup (struct ospf_lsdb *lsdb) 63{ 64 int i; 65 assert (lsdb); 66 assert (lsdb->total == 0); 67 68 ospf_lsdb_delete_all (lsdb); 69 70 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) 71 route_table_finish (lsdb->type[i].db); 72} 73 74void 75lsdb_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa) 76{ 77 memset (lp, 0, sizeof (struct prefix_ls)); 78 lp->family = 0; 79 lp->prefixlen = 64; 80 lp->id = lsa->data->id; 81 lp->adv_router = lsa->data->adv_router; 82} 83 84/* Add new LSA to lsdb. */ 85void 86ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) 87{ 88 struct route_table *table; 89 struct prefix_ls lp; 90 struct route_node *rn; 91 92 table = lsdb->type[lsa->data->type].db; 93 lsdb_prefix_set (&lp, lsa); 94 rn = route_node_get (table, (struct prefix *)&lp); 95 if (!rn->info) 96 { 97 if (IS_LSA_SELF (lsa)) 98 lsdb->type[lsa->data->type].count_self++; 99 lsdb->type[lsa->data->type].count++; 100 lsdb->total++; 101 } 102 else 103 { 104 if (rn->info == lsa) 105 return; 106 107 ospf_lsa_unlock (rn->info); 108 route_unlock_node (rn); 109 } 110 111#ifdef MONITOR_LSDB_CHANGE 112 if (lsdb->new_lsa_hook != NULL) 113 (* lsdb->new_lsa_hook)(lsa); 114#endif /* MONITOR_LSDB_CHANGE */ 115 rn->info = ospf_lsa_lock (lsa); 116} 117 118void 119ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) 120{ 121 struct route_table *table; 122 struct prefix_ls lp; 123 struct route_node *rn; 124 125 table = lsdb->type[lsa->data->type].db; 126 lsdb_prefix_set (&lp, lsa); 127 rn = route_node_lookup (table, (struct prefix *) &lp); 128 if (rn) 129 if (rn->info == lsa) 130 { 131 if (IS_LSA_SELF (lsa)) 132 lsdb->type[lsa->data->type].count_self--; 133 lsdb->type[lsa->data->type].count--; 134 lsdb->total--; 135 rn->info = NULL; 136 route_unlock_node (rn); 137 route_unlock_node (rn); 138#ifdef MONITOR_LSDB_CHANGE 139 if (lsdb->del_lsa_hook != NULL) 140 (* lsdb->del_lsa_hook)(lsa); 141#endif /* MONITOR_LSDB_CHANGE */ 142 ospf_lsa_unlock (lsa); 143 return; 144 } 145} 146 147void 148ospf_lsdb_delete_all (struct ospf_lsdb *lsdb) 149{ 150 struct route_table *table; 151 struct route_node *rn; 152 struct ospf_lsa *lsa; 153 int i; 154 155 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) 156 { 157 table = lsdb->type[i].db; 158 for (rn = route_top (table); rn; rn = route_next (rn)) 159 if ((lsa = (rn->info)) != NULL) 160 { 161 if (IS_LSA_SELF (lsa)) 162 lsdb->type[i].count_self--; 163 lsdb->type[i].count--; 164 lsdb->total--; 165 rn->info = NULL; 166 route_unlock_node (rn); 167#ifdef MONITOR_LSDB_CHANGE 168 if (lsdb->del_lsa_hook != NULL) 169 (* lsdb->del_lsa_hook)(lsa); 170#endif /* MONITOR_LSDB_CHANGE */ 171 ospf_lsa_unlock (lsa); 172 } 173 } 174} 175 176struct ospf_lsa * 177ospf_lsdb_lookup (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) 178{ 179 struct route_table *table; 180 struct prefix_ls lp; 181 struct route_node *rn; 182 struct ospf_lsa *find; 183 184 table = lsdb->type[lsa->data->type].db; 185 lsdb_prefix_set (&lp, lsa); 186 rn = route_node_lookup (table, (struct prefix *) &lp); 187 if (rn) 188 { 189 find = rn->info; 190 route_unlock_node (rn); 191 return find; 192 } 193 return NULL; 194} 195 196struct ospf_lsa * 197ospf_lsdb_lookup_by_id (struct ospf_lsdb *lsdb, u_char type, 198 struct in_addr id, 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 (struct prefix_ls)); 208 lp.family = 0; 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 { 216 find = rn->info; 217 route_unlock_node (rn); 218 return find; 219 } 220 return NULL; 221} 222 223struct ospf_lsa * 224ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *lsdb, u_char type, 225 struct in_addr id, struct in_addr adv_router, 226 int first) 227{ 228 struct route_table *table; 229 struct prefix_ls lp; 230 struct route_node *rn; 231 struct ospf_lsa *find; 232 233 table = lsdb->type[type].db; 234 235 memset (&lp, 0, sizeof (struct prefix_ls)); 236 lp.family = 0; 237 lp.prefixlen = 64; 238 lp.id = id; 239 lp.adv_router = adv_router; 240 241 if (first) 242 rn = route_top (table); 243 else 244 { 245 rn = route_node_get (table, (struct prefix *) &lp); 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 { 255 find = rn->info; 256 route_unlock_node (rn); 257 return find; 258 } 259 return NULL; 260} 261 262unsigned long 263ospf_lsdb_count_all (struct ospf_lsdb *lsdb) 264{ 265 return lsdb->total; 266} 267 268unsigned long 269ospf_lsdb_count (struct ospf_lsdb *lsdb, int type) 270{ 271 return lsdb->type[type].count; 272} 273 274unsigned long 275ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type) 276{ 277 return lsdb->type[type].count_self; 278} 279 280unsigned long 281ospf_lsdb_isempty (struct ospf_lsdb *lsdb) 282{ 283 return (lsdb->total == 0); 284} 285 286struct ospf_lsa * 287foreach_lsa (struct route_table *table, void *p_arg, int int_arg, 288 int (*callback) (struct ospf_lsa *, void *, int)) 289{ 290 struct route_node *rn; 291 struct ospf_lsa *lsa; 292 293 for (rn = route_top (table); rn; rn = route_next (rn)) 294 if ((lsa = rn->info) != NULL) 295 if (callback (lsa, p_arg, int_arg)) 296 return lsa; 297 298 return NULL; 299} 300