/*
 * Copyright (c) 2016 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @brief The IPv4 FIB
 *
 * FIBs are composed of two prefix data-bases (akak tables). The non-forwarding
 * table contains all the routes that the control plane has programmed, the
 * forwarding table contains the sub-set of those routes that can be used to
 * forward packets.
 * In the IPv4 FIB the non-forwarding table is an array of hash tables indexed
 * by mask length, the forwarding table is an mtrie
 *
 * This IPv4 FIB is used by the protocol independent FIB. So directly using
 * this APIs in client code is not encouraged. However, this IPv4 FIB can be
 * used if all the client wants is an IPv4 prefix data-base
 */

#ifndef __IP4_FIB_H__
#define __IP4_FIB_H__

#include <vlib/vlib.h>
#include <vnet/ip/ip.h>
#include <vnet/fib/fib_entry.h>
#include <vnet/fib/fib_table.h>
#include <vnet/ip/ip4_mtrie.h>

typedef struct ip4_fib_t_
{
  /** Required for pool_get_aligned */
  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);

  /**
   * Mtrie for fast lookups. Hash is used to maintain overlapping prefixes.
   * First member so it's in the first cacheline.
   */
  ip4_fib_mtrie_t mtrie;

  /* Hash table for each prefix length mapping. */
  uword *fib_entry_by_dst_address[33];

  /* Table ID (hash key) for this FIB. */
  u32 table_id;

  /* Index into FIB vector. */
  u32 index;
} ip4_fib_t;

extern fib_node_index_t ip4_fib_table_lookup(const ip4_fib_t *fib,
					     const ip4_address_t *addr,
					     u32 len);
extern fib_node_index_t ip4_fib_table_lookup_exact_match(const ip4_fib_t *fib,
							 const ip4_address_t *addr,
							 u32 len);

extern void ip4_fib_table_entry_remove(ip4_fib_t *fib,
				       const ip4_address_t *addr,
				       u32 len);

extern void ip4_fib_table_entry_insert(ip4_fib_t *fib,
				       const ip4_address_t *addr,
				       u32 len,
				       fib_node_index_t fib_entry_index);
extern void ip4_fib_table_destroy(u32 fib_index);

extern void ip4_fib_table_fwding_dpo_update(ip4_fib_t *fib,
					    const ip4_address_t *addr,
					    u32 len,
					    const dpo_id_t *dpo);

extern void ip4_fib_table_fwding_dpo_remove(ip4_fib_t *fib,
					    const ip4_address_t *addr,
					    u32 len,
					    const dpo_id_t *dpo,
                                            fib_node_index_t cover_index);
extern u32 ip4_fib_table_lookup_lb (ip4_fib_t *fib,
				    const ip4_address_t * dst);

/**
 * @brief Walk all entries in a FIB table
 * N.B: This is NOT safe to deletes. If you need to delete walk the whole
 * table and store elements in a vector, then delete the elements
 */
extern void ip4_fib_table_walk(ip4_fib_t *fib,
                               fib_table_walk_fn_t fn,
                               void *ctx);

/**
 * @brief Walk all entries in a sub-tree of the FIB table
 * N.B: This is NOT safe to deletes. If you need to delete walk the whole
 * table and store elements in a vector, then delete the elements
 */
extern void ip4_fib_table_sub_tree_walk(ip4_fib_t *fib,
                                        const fib_prefix_t *root,
                                        fib_table_walk_fn_t fn,
                                        void *ctx);

/**
 * @brief Get the FIB at the given index
 */
static inline ip4_fib_t *
ip4_fib_get (u32 index)
{
    return (pool_elt_at_index(ip4_main.v4_fibs, index));
}

always_inline u32
ip4_fib_lookup (ip4_main_t * im, u32 sw_if_index, ip4_address_t * dst)
{
    return (ip4_fib_table_lookup_lb(
		ip4_fib_get(vec_elt (im->fib_index_by_sw_if_index, sw_if_index)),
		dst));
}

/**
 * @brief Get or create an IPv4 fib.
 *
 * Get or create an IPv4 fib with the provided table ID.
 *
 * @param table_id
 *      When set to \c ~0, an arbitrary and unused fib ID is picked
 *      and can be retrieved with \c ret->table_id.
 *      Otherwise, the fib ID to be used to retrieve or create the desired fib.
 * @returns A pointer to the retrieved or created fib.
 *
 */
extern u32 ip4_fib_table_find_or_create_and_lock(u32 table_id,
                                                 fib_source_t src);
extern u32 ip4_fib_table_create_and_lock(fib_source_t src);

extern u8 *format_ip4_fib_table_memory(u8 * s, va_list * args);

static inline 
u32 ip4_fib_index_from_table_id (u32 table_id)
{
  ip4_main_t * im = &ip4_main;
  uword * p;

  p = hash_get (im->fib_index_by_table_id, table_id);
  if (!p)
    return ~0;

  return p[0];
}

extern u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index);

always_inline index_t
ip4_fib_forwarding_lookup (u32 fib_index,
                           const ip4_address_t * addr)
{
    ip4_fib_mtrie_leaf_t leaf;
    ip4_fib_mtrie_t * mtrie;

    mtrie = &ip4_fib_get(fib_index)->mtrie;

    leaf = ip4_fib_mtrie_lookup_step_one (mtrie, addr);
    leaf = ip4_fib_mtrie_lookup_step (mtrie, leaf, addr, 2);
    leaf = ip4_fib_mtrie_lookup_step (mtrie, leaf, addr, 3);

    return (ip4_fib_mtrie_leaf_get_adj_index(leaf));
}


#endif

