/*
 * Copyright (c) 2017 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.
 */
/**
 * bier_imposition : The BIER imposition object
 *
 * A BIER imposition object is present in the IP mcast output list
 * and represents the imposition of a BIER bitmask. After BIER header
 * imposition the packet is forward within the appropriate/specified
 * BIER table
 */

#include <vnet/bier/bier_imp.h>
#include <vnet/bier/bier_table.h>
#include <vnet/bier/bier_hdr_inlines.h>
#include <vnet/fib/fib_node.h>
#include <vnet/mpls/mpls_types.h>

/**
 * The memory pool of all imp objects
 */
bier_imp_t *bier_imp_pool;

/**
 * When constructing the BIER imp ID from an index and BSL, shift
 * the BSL this far
 */
#define BIER_IMP_ID_HLEN_SHIFT 24

static void
bier_imp_lock_i (bier_imp_t *bi)
{
    bi->bi_locks++;
}

void
bier_imp_lock (index_t bii)
{
    bier_imp_lock_i(bier_imp_get(bii));
}

static index_t
bier_imp_get_index(bier_imp_t *bi)
{
    return (bi - bier_imp_pool);
}

index_t
bier_imp_add_or_lock (const bier_table_id_t *bti,
                      bier_bp_t sender,
                      const bier_bit_string_t *bs)
{
    bier_imp_t *bi = NULL;
    fib_protocol_t fproto;
    index_t btii;

    pool_get_aligned(bier_imp_pool, bi, CLIB_CACHE_LINE_BYTES);

    bi->bi_tbl = *bti;
    btii = bier_table_lock(bti);

    /*
     * init the BIER header we will paint on in the data plane
     */
    bier_hdr_init(&bi->bi_hdr,
                  BIER_HDR_VERSION_1,
                  BIER_HDR_PROTO_INVALID, // filled in later
                  bti->bti_hdr_len,
                  0, // entropy
                  sender);
    bier_hdr_hton(&bi->bi_hdr);
    clib_memcpy_fast(&bi->bi_bits, bs->bbs_buckets, bs->bbs_len);

    bier_imp_lock_i(bi);

    /*
     * get and stack on the forwarding info from the table
     */
    FOR_EACH_FIB_IP_PROTOCOL(fproto)
    {
        /*
         * initialise to invalid first, lest we pick up garbage
         * from the pool alloc
         */
        dpo_id_t dpo = DPO_INVALID;
        bi->bi_dpo[fproto] = dpo;

        bier_table_contribute_forwarding(btii, &dpo);
        dpo_stack(DPO_BIER_IMP, fib_proto_to_dpo(fproto),
                  &bi->bi_dpo[fproto],
                  &dpo);
        dpo_reset(&dpo);
    }

    return (bier_imp_get_index(bi));
}

void
bier_imp_unlock (index_t bii)
{
    fib_protocol_t fproto;
    bier_imp_t *bi;

    if (INDEX_INVALID == bii)
    {
        return;
    }

    bi = bier_imp_get(bii);

    bi->bi_locks--;

    if (0 == bi->bi_locks)
    {
        bier_table_unlock(&bi->bi_tbl);

        FOR_EACH_FIB_IP_PROTOCOL(fproto)
        {
            dpo_reset(&bi->bi_dpo[fproto]);
        }
        pool_put(bier_imp_pool, bi);
    }
}

u8*
format_bier_imp (u8* s, va_list *args)
{
    index_t bii = va_arg (*args, index_t);
    u32 indent = va_arg(*args, u32);
    bier_show_flags_t flags = va_arg(*args, bier_show_flags_t);
    bier_imp_t *bi;

    bi = bier_imp_get(bii);

    s = format(s, "bier-imp:[%d]: tbl:[%U] hdr:[%U]",
               bier_imp_get_index(bi),
               format_bier_table_id, &bi->bi_tbl,
               format_bier_hdr, &bi->bi_hdr);

    if (BIER_SHOW_DETAIL & flags)
    {
        bier_bit_string_t bbs;
        bier_hdr_t copy;

        copy = bi->bi_hdr;
        bier_hdr_ntoh(&copy);
        bier_bit_string_init(&bbs,
                             bier_hdr_get_len_id(&copy),
                             bi->bi_bits);

        s = format(s, "\n%U%U",
                   format_white_space, indent,
                   format_bier_bit_string, &bbs);
        s = format(s, "\n%U%U",
                   format_white_space, indent,
                   format_dpo_id, &bi->bi_dpo, indent+2);
    }

    return (s);
}

void
bier_imp_contribute_forwarding (index_t bii,
                                dpo_proto_t proto,
                                dpo_id_t *dpo)
{
    dpo_set(dpo, DPO_BIER_IMP, proto, bii);
}

const static char* const bier_imp_ip4_nodes[] =
{
    "bier-imp-ip4",
    NULL,
};
const static char* const bier_imp_ip6_nodes[] =
{
    "bier-imp-ip6",
    NULL,
};

const static char* const * const bier_imp_nodes[DPO_PROTO_NUM] =
{
    [DPO_PROTO_IP4]  = bier_imp_ip4_nodes,
    [DPO_PROTO_IP6]  = bier_imp_ip6_nodes,
};

static void
bier_imp_dpo_lock (dpo_id_t *dpo)
{
    bier_imp_lock(dpo->dpoi_index);
}

static void
bier_imp_dpo_unlock (dpo_id_t *dpo)
{
    bier_imp_unlock(dpo->dpoi_index);
}

static void
bier_imp_dpo_mem_show (void)
{
    fib_show_memory_usage("BIER imposition",
                          pool_elts(bier_imp_pool),
                          pool_len(bier_imp_pool),
                          sizeof(bier_imp_t));
}

static u8*
format_bier_imp_dpo (u8* s, va_list *ap)
{
    index_t index = va_arg(*ap, index_t);
    u32 indent = va_arg(*ap, u32);

    s = format(s, "%U", format_bier_imp, index, indent, BIER_SHOW_DETAIL);

    return (s);
}

const static dpo_vft_t bier_imp_vft = {
    .dv_lock = bier_imp_dpo_lock,
    .dv_unlock = bier_imp_dpo_unlock,
    .dv_format = format_bier_imp_dpo,
    .dv_mem_show = bier_imp_dpo_mem_show,
};

clib_error_t *
bier_imp_db_module_init (vlib_main_t *vm)
{
    dpo_register(DPO_BIER_IMP, &bier_imp_vft, bier_imp_nodes);

    return (NULL);
}

VLIB_INIT_FUNCTION (bier_imp_db_module_init);

static clib_error_t *
show_bier_imp (vlib_main_t * vm,
               unformat_input_t * input,
               vlib_cli_command_t * cmd)
{
    bier_imp_t *bi;
    index_t bii;

    bii = INDEX_INVALID;

    while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
        if (unformat (input, "%d", &bii))
            ;
        else
        {
            break;
        }
    }

    if (INDEX_INVALID == bii)
    {
        pool_foreach (bi, bier_imp_pool)
         {
            vlib_cli_output(vm, "%U", format_bier_imp,
                            bier_imp_get_index(bi),
                            1,
                            BIER_SHOW_BRIEF);
        }
    }
    else
    {
        if (pool_is_free_index(bier_imp_pool, bii))
        {
            vlib_cli_output(vm, "No such BIER imposition: %d", bii);
        }
        else
        {
            vlib_cli_output(vm, "%U", format_bier_imp, bii, 1,
                            BIER_SHOW_DETAIL);
        }
    }
    return (NULL);
}

VLIB_CLI_COMMAND (show_bier_imp_node, static) = {
    .path = "show bier imp",
    .short_help = "show bier imp [index]",
    .function = show_bier_imp,
};
