/*
 * 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.
 */

#include <vnet/bfd/bfd_main.h>

#include <vnet/adj/adj_delegate.h>
#include <vnet/adj/adj_nbr.h>
#include <vnet/fib/fib_walk.h>

/**
 * Distillation of the BFD session states into a go/no-go for using
 * the associated tracked adjacency
 */
typedef enum adj_bfd_state_t_
{
    ADJ_BFD_STATE_DOWN,
    ADJ_BFD_STATE_UP,
} adj_bfd_state_t;

#define ADJ_BFD_STATES {                        \
    [ADJ_BFD_STATE_DOWN] = "down",              \
    [ADJ_BFD_STATE_UP]   = "up",                \
}

static const char *adj_bfd_state_names[] = ADJ_BFD_STATES;

/**
 * BFD delegate daa
 */
typedef struct adj_bfd_delegate_t_
{
    /**
     * BFD session state
     */
    adj_bfd_state_t abd_state;

    /**
     * BFD session index
     */
    u32 abd_index;
} adj_bfd_delegate_t;

/**
 * Pool of delegates
*/
static adj_bfd_delegate_t *abd_pool;

static inline adj_bfd_delegate_t*
adj_bfd_from_base (adj_delegate_t *ad)
{
    if (NULL != ad)
    {
        return (pool_elt_at_index(abd_pool, ad->ad_index));
    }
    return (NULL);
}

static inline const adj_bfd_delegate_t*
adj_bfd_from_const_base (const adj_delegate_t *ad)
{
    if (NULL != ad)
    {
        return (pool_elt_at_index(abd_pool, ad->ad_index));
    }
    return (NULL);
}

static adj_bfd_state_t
adj_bfd_bfd_state_to_fib (bfd_state_e bstate)
{
    switch (bstate)
    {
    case BFD_STATE_up:
        return (ADJ_BFD_STATE_UP);
    case BFD_STATE_down:
    case BFD_STATE_admin_down:
    case BFD_STATE_init:
        return (ADJ_BFD_STATE_DOWN);
    }
    return (ADJ_BFD_STATE_DOWN);
}

static void
adj_bfd_update_walk (adj_index_t ai)
{
    /*
     * initiate a backwalk of dependent children
     * to notify of the state change of this adj.
     */
    fib_node_back_walk_ctx_t ctx = {
        .fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE,
    };
    fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &ctx);
}

/**
 * @brief Callback function registered with BFD module to receive notifications
 * of the CRUD of BFD sessions
 * would be static but for the fact it's called from the unit-tests
 */
void
adj_bfd_notify (bfd_listen_event_e event,
                const bfd_session_t *session)
{
    const bfd_udp_key_t *key;
    adj_bfd_delegate_t *abd;
    fib_protocol_t fproto;
    adj_delegate_t *aed;
    adj_index_t ai;

    if (BFD_HOP_TYPE_SINGLE != session->hop_type)
    {
        /*
         * multi-hop BFD sessions attach directly to the FIB entry
         * single-hop adj to the associate adjacency.
         */
        return;
    }

    key = &session->udp.key;

    fproto = (ip46_address_is_ip4 (&key->peer_addr) ?
              FIB_PROTOCOL_IP4:
              FIB_PROTOCOL_IP6);

    /*
     * find the adj that corresponds to the BFD session.
     */
    ai = adj_nbr_add_or_lock(fproto,
                             fib_proto_to_link(fproto),
                             &key->peer_addr,
                             key->sw_if_index);

    switch (event)
    {
    case BFD_LISTEN_EVENT_CREATE:
        /*
         * The creation of a new session
         */
        if ((ADJ_INDEX_INVALID != ai) &&
            (aed = adj_delegate_get(adj_get(ai),
                                    ADJ_DELEGATE_BFD)))
        {
            /*
             * already got state for this adj
             */
        }
        else
        {
            /*
             * lock the adj. add the delegate.
             * Locking the adj prevents it being removed and thus maintains
             * the BFD derived states
             */
            adj_lock(ai);

            /*
             * allocate and init a new delegate struct
             */
            pool_get(abd_pool, abd);

            /*
             * it would be best here if we could ignore this create and just
             * wait for the first update, but this is not possible because
             * BFD sessions are created in the down state, and can remain this
             * way without transitioning to another state if the peer is
             * unresponsive. So we have to assume down and wait for up.
             */
            abd->abd_state = ADJ_BFD_STATE_DOWN;
            abd->abd_index = session->bs_idx;

            adj_delegate_add(adj_get(ai), ADJ_DELEGATE_BFD, abd - abd_pool);
            adj_bfd_update_walk(ai);
        }
        break;

    case BFD_LISTEN_EVENT_UPDATE:
        /*
         * state change up/down and
         */
        abd = adj_bfd_from_base(adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD));

        if (NULL != abd)
        {
            abd->abd_state = adj_bfd_bfd_state_to_fib(session->local_state);
            adj_bfd_update_walk(ai);
        }
        /*
         * else
         *   not an adj with BFD state
         */
        break;

    case BFD_LISTEN_EVENT_DELETE:
        /*
         * session has been removed.
         */
        abd = adj_bfd_from_base(adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD));

        if (NULL != abd)
        {
            /*
             * has an associated BFD tracking delegate
             * remove the BFD tracking delegate, update children, then
             * unlock the adj
             */
            adj_delegate_remove(ai, ADJ_DELEGATE_BFD);
            pool_put(abd_pool, abd);

            adj_bfd_update_walk(ai);
            adj_unlock(ai);
        }
        /*
         * else
         *  no BFD associated state
         */
        break;
    }

    /*
     * unlock match of the add-or-lock at the start
     */
    adj_unlock(ai);
}

int
adj_bfd_is_up (adj_index_t ai)
{
    const adj_bfd_delegate_t *abd;

    abd = adj_bfd_from_base(adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD));

    if (NULL == abd)
    {
        /*
         * no BFD tracking - resolved
         */
        return (!0);
    }
    else
    {
        /*
         * defer to the state of the BFD tracking
         */
        return (ADJ_BFD_STATE_UP == abd->abd_state);
    }
}

/**
 * Print a delegate that represents BFD tracking
 */
static u8 *
adj_delegate_fmt_bfd (const adj_delegate_t *aed, u8 *s)
{
    const adj_bfd_delegate_t *abd = adj_bfd_from_const_base(aed);

    s = format(s, "BFD:[state:%s index:%d]",
               adj_bfd_state_names[abd->abd_state],
               abd->abd_index);

    return (s);
}

const static adj_delegate_vft_t adj_delegate_vft = {
  .adv_format = adj_delegate_fmt_bfd,
};

static clib_error_t *
adj_bfd_main_init (vlib_main_t * vm)
{
    clib_error_t * error = NULL;

    if ((error = vlib_call_init_function (vm, bfd_main_init)))
        return (error);

    bfd_register_listener(adj_bfd_notify);

    adj_delegate_register_type (ADJ_DELEGATE_BFD, &adj_delegate_vft);

    return (error);
}

VLIB_INIT_FUNCTION (adj_bfd_main_init);
