/*
 * 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_get(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_get(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_get(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)
{
    clib_error_t * error = NULL;

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

    bfd_register_listener(fib_bfd_notify);

    return (error);
}

VLIB_INIT_FUNCTION (fib_bfd_main_init);
