/*
 * OSPF LSDB support.
 * Copyright (C) 1999, 2000 Alex Zinin, Kunihiro Ishiguro, Toshiaki Takada
 *
 * This file is part of GNU Zebra.
 *
 * GNU Zebra is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * GNU Zebra is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * 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.
 */

#include <zebra.h>

#include "prefix.h"
#include "table.h"
#include "memory.h"

#include "ospfd/ospfd.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"

struct ospf_lsdb *
ospf_lsdb_new ()
{
  struct ospf_lsdb *new;

  new = XCALLOC (MTYPE_OSPF_LSDB, sizeof (struct ospf_lsdb));
  ospf_lsdb_init (new);

  return new;
}

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 ();
}

void
ospf_lsdb_free (struct ospf_lsdb *lsdb)
{
  ospf_lsdb_cleanup (lsdb);
  XFREE (MTYPE_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);
}

static void
lsdb_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;
}

/* Add new LSA to lsdb. */
void
ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
{
  struct route_table *table;
  struct prefix_ls lp;
  struct route_node *rn;
  struct ospf_lsa *old;

  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;
      
      old = rn->info;
      lsdb->type[old->data->type].checksum -= ntohs(old->data->checksum);

      ospf_lsa_unlock (rn->info);
      route_unlock_node (rn);
    }

#ifdef MONITOR_LSDB_CHANGE
  if (lsdb->new_lsa_hook != NULL)
    (* lsdb->new_lsa_hook)(lsa);
#endif /* MONITOR_LSDB_CHANGE */
  lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum);
  rn->info = ospf_lsa_lock (lsa);
}

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)
    {
      zlog_warn ("%s: Called with NULL LSDB", __func__);
      if (lsa)
        zlog_warn ("LSA[Type%d:%s]: LSA %p, lsa->lsdb %p",
                   lsa->data->type, inet_ntoa (lsa->data->id),
                   lsa, lsa->lsdb);
      return;
    }
  
  if (!lsa)
    {
      zlog_warn ("%s: Called with NULL LSA", __func__);
      return;
    }
  
  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--;
	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);
#ifdef MONITOR_LSDB_CHANGE
        if (lsdb->del_lsa_hook != NULL)
          (* lsdb->del_lsa_hook)(lsa);
#endif /* MONITOR_LSDB_CHANGE */
	ospf_lsa_unlock (lsa);
	return;
      }
}

void
ospf_lsdb_delete_all (struct ospf_lsdb *lsdb)
{
  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->type[i].checksum -= ntohs(lsa->data->checksum);
	    lsdb->total--;
	    rn->info = NULL;
	    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);
	  }
    }
}

void
ospf_lsdb_clean_stat (struct ospf_lsdb *lsdb)
{
  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 (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[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 ospf_lsa *
ospf_lsdb_lookup_by_id (struct ospf_lsdb *lsdb, u_char type,
		       struct in_addr id, struct in_addr adv_router)
{
  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 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 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;
}

unsigned long
ospf_lsdb_count_all (struct ospf_lsdb *lsdb)
{
  return lsdb->total;
}

unsigned long
ospf_lsdb_count (struct ospf_lsdb *lsdb, int type)
{
  return lsdb->type[type].count;
}

unsigned long
ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type)
{
  return lsdb->type[type].count_self;
}

unsigned int
ospf_lsdb_checksum (struct ospf_lsdb *lsdb, int type)
{
  return lsdb->type[type].checksum;
}

unsigned long
ospf_lsdb_isempty (struct ospf_lsdb *lsdb)
{
  return (lsdb->total == 0);
}
