/*
 * 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/fib/fib_entry_delegate.h>
#include <vnet/fib/fib_entry.h>
#include <vnet/fib/fib_table.h>
#include <vnet/fib/fib_walk.h>

static fib_bfd_state_t
fib_bfd_bfd_state_to_fib (bfd_state_e bstate)
{
    switch (bstate)
    {
    case BFD_STATE_up:
        return (FIB_BFD_STATE_UP);
    case BFD_STATE_down:
    case BFD_STATE_admin_down:
    case BFD_STATE_init:
        return (FIB_BFD_STATE_DOWN);
    }
    return (FIB_BFD_STATE_DOWN);
}

static void
fib_bfd_update_walk (fib_node_index_t fei)
{
    /*
     * initiate a backwalk of dependent children
     * to notify of the state change of this entry.
     */
    fib_node_back_walk_ctx_t ctx = {
        .fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE,
    };
    fib_walk_sync(FIB_NODE_TYPE_ENTRY, fei, &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
fib_bfd_notify (bfd_listen_event_e event,
                const bfd_session_t *session)
{
    fib_entry_delegate_t *fed;
    const bfd_udp_key_t *key;
    fib_node_index_t fei;

    if (BFD_HOP_TYPE_MULTI != 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;

    fib_prefix_t pfx = {
        .fp_addr = key->peer_addr,
        .fp_proto = (ip46_address_is_ip4 (&key->peer_addr) ?
                     FIB_PROTOCOL_IP4:
                     FIB_PROTOCOL_IP6),
        .fp_len = (ip46_address_is_ip4 (&key->peer_addr) ?
                   32:
                   128),
    };

    /*
     * get the FIB entry
     */
    fei = fib_table_lookup_exact_match(key->fib_index, &pfx);

    switch (event)
    {
    case BFD_LISTEN_EVENT_CREATE:
        /*
         * The creation of a new session
         */
        if ((FIB_NODE_INDEX_INVALID != fei) &&
            (fed = fib_entry_delegate_find(fib_entry_get(fei),
                                           FIB_ENTRY_DELEGATE_BFD)))
        {
            /*
             * already got state for this entry
             */
        }
        else
        {
            /*
             * source and lock the entry. add the delegate
             */
            fei = fib_table_entry_special_add(key->fib_index,
                                              &pfx,
                                              FIB_SOURCE_RR,
                                              FIB_ENTRY_FLAG_NONE);
            fib_entry_lock(fei);

            fed = fib_entry_delegate_find_or_add(fib_entry_get(fei),
                                                 FIB_ENTRY_DELEGATE_BFD);

            /*
             * pretend the session is up and skip the walk.
             * If we set it down then we get traffic loss on new children.
             * if we walk then we lose traffic for existing children. Wait
             * for the first BFD UP/DOWN before we let the session's state
             * influence forwarding.
             */
            fed->fd_bfd_state = FIB_BFD_STATE_UP;
        }
        break;

    case BFD_LISTEN_EVENT_UPDATE:
        /*
         * state change up/dowm and
         */
        ASSERT(FIB_NODE_INDEX_INVALID != fei);

        fed = fib_entry_delegate_find(fib_entry_get(fei),
                                      FIB_ENTRY_DELEGATE_BFD);

        if (NULL != fed)
        {
            fed->fd_bfd_state = fib_bfd_bfd_state_to_fib(session->local_state);
            fib_bfd_update_walk(fei);
        }
        /*
         * else
         *   no BFD state
         */
        break;

    case BFD_LISTEN_EVENT_DELETE:
        /*
         * session has been removed.
         */
        if (FIB_NODE_INDEX_INVALID == fei)
        {
            /*
             * no FIB entry
             */
        }
        else if (fib_entry_delegate_find(fib_entry_get(fei),
                                         FIB_ENTRY_DELEGATE_BFD))
        {
            /*
             * has an associated BFD tracking delegate
             * usource the entry and remove the BFD tracking delegate
             */
            fib_entry_delegate_remove(fib_entry_get(fei),
                                      FIB_ENTRY_DELEGATE_BFD);
            fib_bfd_update_walk(fei);

            fib_table_entry_special_remove(key->fib_index,
                                           &pfx,
                                           FIB_SOURCE_RR);
            fib_entry_unlock(fei);
        }
        /*
         * else
         * no BFD associated state
         */
        break;
    }
}

static clib_error_t *
fib_bfd_main_init (vlib_main_t * vm)
{
    bfd_register_listener(fib_bfd_notify);

    return (NULL);
}

VLIB_INIT_FUNCTION (fib_bfd_main_init) =
{
    .runs_after = VLIB_INITS("bfd_main_init"),
};
