* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "prefix.h"
#include "table.h"
#include "memory.h"
+#include "log.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
-\f
-struct ospf_lsdb *
-ospf_lsdb_new ()
+
+struct ospf_lsdb *ospf_lsdb_new()
{
- struct ospf_lsdb *new;
+ struct ospf_lsdb *new;
- new = XCALLOC (MTYPE_OSPF_LSDB, sizeof (struct ospf_lsdb));
- ospf_lsdb_init (new);
+ new = XCALLOC(MTYPE_OSPF_LSDB, sizeof(struct ospf_lsdb));
+ ospf_lsdb_init(new);
- return new;
+ return new;
}
-void
-ospf_lsdb_init (struct ospf_lsdb *lsdb)
+void ospf_lsdb_init(struct ospf_lsdb *lsdb)
{
- int i;
-
- for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
- lsdb->type[i].db = route_table_init ();
+ int i;
+
+ for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+ lsdb->type[i].db = route_table_init();
}
-void
-ospf_lsdb_free (struct ospf_lsdb *lsdb)
+void ospf_lsdb_free(struct ospf_lsdb *lsdb)
{
- ospf_lsdb_cleanup (lsdb);
- XFREE (MTYPE_OSPF_LSDB, lsdb);
+ ospf_lsdb_cleanup(lsdb);
+ XFREE(MTYPE_OSPF_LSDB, lsdb);
}
-void
-ospf_lsdb_cleanup (struct ospf_lsdb *lsdb)
+void ospf_lsdb_cleanup(struct ospf_lsdb *lsdb)
{
- int i;
- assert (lsdb);
- assert (lsdb->total == 0);
-
- ospf_lsdb_delete_all (lsdb);
-
- for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
- route_table_finish (lsdb->type[i].db);
+ int i;
+ assert(lsdb);
+ assert(lsdb->total == 0);
+
+ ospf_lsdb_delete_all(lsdb);
+
+ for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+ route_table_finish(lsdb->type[i].db);
}
-void
-lsdb_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa)
+void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa)
{
- memset (lp, 0, sizeof (struct prefix_ls));
- lp->family = 0;
- lp->prefixlen = 64;
- lp->id = lsa->data->id;
- lp->adv_router = lsa->data->adv_router;
+ if (lp && lsa && lsa->data) {
+ lp->family = 0;
+ lp->prefixlen = 64;
+ lp->id = lsa->data->id;
+ lp->adv_router = lsa->data->adv_router;
+ }
}
-/* Add new LSA to lsdb. */
-void
-ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
+static void ospf_lsdb_delete_entry(struct ospf_lsdb *lsdb,
+ struct route_node *rn)
{
- struct route_table *table;
- struct prefix_ls lp;
- struct route_node *rn;
-
- table = lsdb->type[lsa->data->type].db;
- lsdb_prefix_set (&lp, lsa);
- rn = route_node_get (table, (struct prefix *)&lp);
- if (!rn->info)
- {
- if (IS_LSA_SELF (lsa))
- lsdb->type[lsa->data->type].count_self++;
- lsdb->type[lsa->data->type].count++;
- lsdb->total++;
- }
- else
- {
- if (rn->info == lsa)
- return;
-
- ospf_lsa_unlock (rn->info);
- route_unlock_node (rn);
- }
+ struct ospf_lsa *lsa = rn->info;
-#ifdef MONITOR_LSDB_CHANGE
- if (lsdb->new_lsa_hook != NULL)
- (* lsdb->new_lsa_hook)(lsa);
-#endif /* MONITOR_LSDB_CHANGE */
- rn->info = ospf_lsa_lock (lsa);
-}
+ if (!lsa)
+ return;
-void
-ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
-{
- struct route_table *table;
- struct prefix_ls lp;
- struct route_node *rn;
-
- table = lsdb->type[lsa->data->type].db;
- lsdb_prefix_set (&lp, lsa);
- rn = route_node_lookup (table, (struct prefix *) &lp);
- if (rn)
- if (rn->info == lsa)
- {
- if (IS_LSA_SELF (lsa))
- lsdb->type[lsa->data->type].count_self--;
+ assert(rn->table == lsdb->type[lsa->data->type].db);
+
+ if (IS_LSA_SELF(lsa))
+ lsdb->type[lsa->data->type].count_self--;
lsdb->type[lsa->data->type].count--;
+ lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum);
lsdb->total--;
rn->info = NULL;
- route_unlock_node (rn);
- route_unlock_node (rn);
+ route_unlock_node(rn);
#ifdef MONITOR_LSDB_CHANGE
- if (lsdb->del_lsa_hook != NULL)
- (* lsdb->del_lsa_hook)(lsa);
-#endif /* MONITOR_LSDB_CHANGE */
- ospf_lsa_unlock (lsa);
+ if (lsdb->del_lsa_hook != NULL)
+ (*lsdb->del_lsa_hook)(lsa);
+#endif /* MONITOR_LSDB_CHANGE */
+ ospf_lsa_unlock(&lsa); /* lsdb */
return;
- }
}
-void
-ospf_lsdb_delete_all (struct ospf_lsdb *lsdb)
+/* Add new LSA to lsdb. */
+void ospf_lsdb_add(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
{
- struct route_table *table;
- struct route_node *rn;
- struct ospf_lsa *lsa;
- int i;
-
- for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
- {
- table = lsdb->type[i].db;
- for (rn = route_top (table); rn; rn = route_next (rn))
- if ((lsa = (rn->info)) != NULL)
- {
- if (IS_LSA_SELF (lsa))
- lsdb->type[i].count_self--;
- lsdb->type[i].count--;
- lsdb->total--;
- rn->info = NULL;
- route_unlock_node (rn);
+ struct route_table *table;
+ struct prefix_ls lp;
+ struct route_node *rn;
+
+ table = lsdb->type[lsa->data->type].db;
+ ls_prefix_set(&lp, lsa);
+ rn = route_node_get(table, (struct prefix *)&lp);
+
+ /* nothing to do? */
+ if (rn->info && rn->info == lsa) {
+ route_unlock_node(rn);
+ return;
+ }
+
+ /* purge old entry? */
+ if (rn->info)
+ ospf_lsdb_delete_entry(lsdb, rn);
+
+ if (IS_LSA_SELF(lsa))
+ lsdb->type[lsa->data->type].count_self++;
+ lsdb->type[lsa->data->type].count++;
+ lsdb->total++;
+
#ifdef MONITOR_LSDB_CHANGE
- if (lsdb->del_lsa_hook != NULL)
- (* lsdb->del_lsa_hook)(lsa);
+ if (lsdb->new_lsa_hook != NULL)
+ (*lsdb->new_lsa_hook)(lsa);
#endif /* MONITOR_LSDB_CHANGE */
- ospf_lsa_unlock (lsa);
- }
- }
+ lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum);
+ rn->info = ospf_lsa_lock(lsa); /* lsdb */
+}
+
+void ospf_lsdb_delete(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
+{
+ struct route_table *table;
+ struct prefix_ls lp;
+ struct route_node *rn;
+
+ if (!lsdb || !lsa)
+ return;
+
+ assert(lsa->data->type < OSPF_MAX_LSA);
+ table = lsdb->type[lsa->data->type].db;
+ ls_prefix_set(&lp, lsa);
+ if ((rn = route_node_lookup(table, (struct prefix *)&lp))) {
+ if (rn->info == lsa)
+ ospf_lsdb_delete_entry(lsdb, rn);
+ route_unlock_node(rn); /* route_node_lookup */
+ }
}
-struct ospf_lsa *
-ospf_lsdb_lookup (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
+void ospf_lsdb_delete_all(struct ospf_lsdb *lsdb)
{
- struct route_table *table;
- struct prefix_ls lp;
- struct route_node *rn;
- struct ospf_lsa *find;
-
- table = lsdb->type[lsa->data->type].db;
- lsdb_prefix_set (&lp, lsa);
- rn = route_node_lookup (table, (struct prefix *) &lp);
- if (rn)
- {
- find = rn->info;
- route_unlock_node (rn);
- return find;
- }
- return NULL;
+ struct route_table *table;
+ struct route_node *rn;
+ int i;
+
+ for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) {
+ table = lsdb->type[i].db;
+ for (rn = route_top(table); rn; rn = route_next(rn))
+ if (rn->info != NULL)
+ ospf_lsdb_delete_entry(lsdb, rn);
+ }
}
-struct ospf_lsa *
-ospf_lsdb_lookup_by_id (struct ospf_lsdb *lsdb, u_char type,
- struct in_addr id, struct in_addr adv_router)
+void ospf_lsdb_clean_stat(struct ospf_lsdb *lsdb)
{
- struct route_table *table;
- struct prefix_ls lp;
- struct route_node *rn;
- struct ospf_lsa *find;
-
- table = lsdb->type[type].db;
-
- memset (&lp, 0, sizeof (struct prefix_ls));
- lp.family = 0;
- lp.prefixlen = 64;
- lp.id = id;
- lp.adv_router = adv_router;
-
- rn = route_node_lookup (table, (struct prefix *) &lp);
- if (rn)
- {
- find = rn->info;
- route_unlock_node (rn);
- return find;
- }
- return NULL;
+ struct route_table *table;
+ struct route_node *rn;
+ struct ospf_lsa *lsa;
+ int i;
+
+ for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) {
+ table = lsdb->type[i].db;
+ for (rn = route_top(table); rn; rn = route_next(rn))
+ if ((lsa = (rn->info)) != NULL)
+ lsa->stat = LSA_SPF_NOT_EXPLORED;
+ }
}
-struct ospf_lsa *
-ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *lsdb, u_char type,
- struct in_addr id, struct in_addr adv_router,
- int first)
+struct ospf_lsa *ospf_lsdb_lookup(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
{
- struct route_table *table;
- struct prefix_ls lp;
- struct route_node *rn;
- struct ospf_lsa *find;
-
- table = lsdb->type[type].db;
-
- memset (&lp, 0, sizeof (struct prefix_ls));
- lp.family = 0;
- lp.prefixlen = 64;
- lp.id = id;
- lp.adv_router = adv_router;
-
- if (first)
- rn = route_top (table);
- else
- {
- rn = route_node_get (table, (struct prefix *) &lp);
- rn = route_next (rn);
- }
-
- for (; rn; rn = route_next (rn))
- if (rn->info)
- break;
-
- if (rn && rn->info)
- {
- find = rn->info;
- route_unlock_node (rn);
- return find;
- }
- return NULL;
+ struct route_table *table;
+ struct prefix_ls lp;
+ struct route_node *rn;
+ struct ospf_lsa *find;
+
+ table = lsdb->type[lsa->data->type].db;
+ ls_prefix_set(&lp, lsa);
+ rn = route_node_lookup(table, (struct prefix *)&lp);
+ if (rn) {
+ find = rn->info;
+ route_unlock_node(rn);
+ return find;
+ }
+ return NULL;
}
-unsigned long
-ospf_lsdb_count_all (struct ospf_lsdb *lsdb)
+struct ospf_lsa *ospf_lsdb_lookup_by_id(struct ospf_lsdb *lsdb, uint8_t type,
+ struct in_addr id,
+ struct in_addr adv_router)
{
- return lsdb->total;
+ struct route_table *table;
+ struct prefix_ls lp;
+ struct route_node *rn;
+ struct ospf_lsa *find;
+
+ table = lsdb->type[type].db;
+
+ memset(&lp, 0, sizeof(struct prefix_ls));
+ lp.family = 0;
+ lp.prefixlen = 64;
+ lp.id = id;
+ lp.adv_router = adv_router;
+
+ rn = route_node_lookup(table, (struct prefix *)&lp);
+ if (rn) {
+ find = rn->info;
+ route_unlock_node(rn);
+ return find;
+ }
+ return NULL;
}
-unsigned long
-ospf_lsdb_count (struct ospf_lsdb *lsdb, int type)
+struct ospf_lsa *ospf_lsdb_lookup_by_id_next(struct ospf_lsdb *lsdb,
+ uint8_t type, struct in_addr id,
+ struct in_addr adv_router,
+ int first)
{
- return lsdb->type[type].count;
+ struct route_table *table;
+ struct prefix_ls lp;
+ struct route_node *rn;
+ struct ospf_lsa *find;
+
+ table = lsdb->type[type].db;
+
+ memset(&lp, 0, sizeof(struct prefix_ls));
+ lp.family = 0;
+ lp.prefixlen = 64;
+ lp.id = id;
+ lp.adv_router = adv_router;
+
+ if (first)
+ rn = route_top(table);
+ else {
+ if ((rn = route_node_lookup(table, (struct prefix *)&lp))
+ == NULL)
+ return NULL;
+ rn = route_next(rn);
+ }
+
+ for (; rn; rn = route_next(rn))
+ if (rn->info)
+ break;
+
+ if (rn && rn->info) {
+ find = rn->info;
+ route_unlock_node(rn);
+ return find;
+ }
+ return NULL;
}
-unsigned long
-ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type)
+unsigned long ospf_lsdb_count_all(struct ospf_lsdb *lsdb)
{
- return lsdb->type[type].count_self;
+ return lsdb->total;
}
-unsigned long
-ospf_lsdb_isempty (struct ospf_lsdb *lsdb)
+unsigned long ospf_lsdb_count(struct ospf_lsdb *lsdb, int type)
{
- return (lsdb->total == 0);
+ return lsdb->type[type].count;
}
-struct ospf_lsa *
-foreach_lsa (struct route_table *table, void *p_arg, int int_arg,
- int (*callback) (struct ospf_lsa *, void *, int))
+unsigned long ospf_lsdb_count_self(struct ospf_lsdb *lsdb, int type)
{
- struct route_node *rn;
- struct ospf_lsa *lsa;
+ return lsdb->type[type].count_self;
+}
- for (rn = route_top (table); rn; rn = route_next (rn))
- if ((lsa = rn->info) != NULL)
- if (callback (lsa, p_arg, int_arg))
- return lsa;
+unsigned int ospf_lsdb_checksum(struct ospf_lsdb *lsdb, int type)
+{
+ return lsdb->type[type].checksum;
+}
- return NULL;
+unsigned long ospf_lsdb_isempty(struct ospf_lsdb *lsdb)
+{
+ return (lsdb->total == 0);
}