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

#include <vnet/mfib/mfib_entry.h>
#include <vnet/mfib/mfib_entry_src.h>
#include <vnet/mfib/mfib_entry_cover.h>
#include <vnet/fib/fib_path_list.h>
#include <vnet/fib/fib_walk.h>

#include <vnet/dpo/drop_dpo.h>
#include <vnet/dpo/replicate_dpo.h>

/**
 * the logger
 */
vlib_log_class_t mfib_entry_logger;

/**
 * Pool of path extensions
 */
static mfib_path_ext_t *mfib_path_ext_pool;

/**
 * String names for each source
 */
static const char *mfib_source_names[] = MFIB_SOURCE_NAMES;

/*
 * Pool for all fib_entries
 */
mfib_entry_t *mfib_entry_pool;

static fib_node_t *
mfib_entry_get_node (fib_node_index_t index)
{
    return ((fib_node_t*)mfib_entry_get(index));
}

static fib_protocol_t
mfib_entry_get_proto (const mfib_entry_t * mfib_entry)
{
    return (mfib_entry->mfe_prefix.fp_proto);
}

fib_forward_chain_type_t
mfib_entry_get_default_chain_type (const mfib_entry_t *mfib_entry)
{
    switch (mfib_entry->mfe_prefix.fp_proto)
    {
    case FIB_PROTOCOL_IP4:
        return (FIB_FORW_CHAIN_TYPE_MCAST_IP4);
    case FIB_PROTOCOL_IP6:
        return (FIB_FORW_CHAIN_TYPE_MCAST_IP6);
    case FIB_PROTOCOL_MPLS:
        ASSERT(0);
        break;
    }
    return (FIB_FORW_CHAIN_TYPE_MCAST_IP4);
}

static u8 *
format_mfib_entry_dpo (u8 * s, va_list * args)
{
    index_t fei = va_arg(*args, index_t);
    CLIB_UNUSED(u32 indent) = va_arg(*args, u32);

    return (format(s, "%U",
                   format_mfib_entry, fei,
                   MFIB_ENTRY_FORMAT_BRIEF));
}

static inline mfib_path_ext_t *
mfib_entry_path_ext_get (index_t mi)
{
    return (pool_elt_at_index(mfib_path_ext_pool, mi));
}

static u8 *
format_mfib_entry_path_ext (u8 * s, va_list * args)
{
    mfib_path_ext_t *path_ext;
    index_t mpi = va_arg(*args, index_t);

    path_ext = mfib_entry_path_ext_get(mpi);
    return (format(s, "path:%d flags:%U",
                   path_ext->mfpe_path,
                   format_mfib_itf_flags, path_ext->mfpe_flags));
}

u8 *
format_mfib_entry (u8 * s, va_list * args)
{
    fib_node_index_t fei, mfi;
    mfib_entry_t *mfib_entry;
    mfib_entry_src_t *msrc;
    u32 sw_if_index;
    int level;

    fei = va_arg (*args, fib_node_index_t);
    level = va_arg (*args, int);
    mfib_entry = mfib_entry_get(fei);

    s = format (s, "%U", format_mfib_prefix, &mfib_entry->mfe_prefix);
    s = format (s, ": %U", format_mfib_entry_flags, mfib_entry->mfe_flags);

    if (level >= MFIB_ENTRY_FORMAT_DETAIL)
    {
        fib_node_index_t path_index, mpi;

        s = format (s, "\n");
        s = format (s, " fib:%d", mfib_entry->mfe_fib_index);
        s = format (s, " index:%d", mfib_entry_get_index(mfib_entry));
        s = format (s, " locks:%d\n", mfib_entry->mfe_node.fn_locks);
        vec_foreach(msrc, mfib_entry->mfe_srcs)
        {
            s = format (s, "  src:%s locks:%d:",
                        mfib_source_names[msrc->mfes_src],
                        msrc->mfes_ref_count);
            if (msrc->mfes_cover != FIB_NODE_INDEX_INVALID)
            {
                s = format (s, " cover:%d", msrc->mfes_cover);
            }
            s = format (s, " %U\n", format_mfib_entry_flags, msrc->mfes_flags);
            if (FIB_NODE_INDEX_INVALID != msrc->mfes_pl)
            {
                s = fib_path_list_format(msrc->mfes_pl, s);
            }
            s = format (s, "    Extensions:\n");
            hash_foreach(path_index, mpi, msrc->mfes_exts,
            ({
                s = format(s, "     %U\n", format_mfib_entry_path_ext, mpi);
            }));
            s = format (s, "    Interface-Forwarding:\n");
            hash_foreach(sw_if_index, mfi, msrc->mfes_itfs,
            ({
                s = format(s, "    %U\n", format_mfib_itf, mfi);
            }));
        }
    }

    s = format(s, "\n  Interfaces:");
    hash_foreach(sw_if_index, mfi, mfib_entry->mfe_itfs,
    ({
        s = format(s, "\n  %U", format_mfib_itf, mfi);
    }));
    if (MFIB_RPF_ID_NONE != mfib_entry->mfe_rpf_id)
    {
        s = format(s, "\n  RPF-ID:%d", mfib_entry->mfe_rpf_id);
    }
    s = format(s, "\n  %U-chain\n  %U",
               format_fib_forw_chain_type,
               mfib_entry_get_default_chain_type(mfib_entry),
               format_dpo_id,
               &mfib_entry->mfe_rep,
               2);
    s = format(s, "\n");

    if (level >= MFIB_ENTRY_FORMAT_DETAIL2)
    {
        s = format(s, "\nchildren:");
        s = fib_node_children_format(mfib_entry->mfe_node.fn_children, s);
    }

    return (s);
}

static mfib_entry_t*
mfib_entry_from_fib_node (fib_node_t *node)
{
    ASSERT(FIB_NODE_TYPE_MFIB_ENTRY == node->fn_type);
    return ((mfib_entry_t*)node);
}

static int
mfib_entry_src_cmp_for_sort (void * v1,
                             void * v2)
{
    mfib_entry_src_t *esrc1 = v1, *esrc2 = v2;

    return (esrc1->mfes_src - esrc2->mfes_src);
}

static void
mfib_entry_src_init (mfib_entry_t *mfib_entry,
                     mfib_source_t source)

{
    mfib_entry_src_t esrc = {
        .mfes_pl = FIB_NODE_INDEX_INVALID,
        .mfes_flags = MFIB_ENTRY_FLAG_NONE,
        .mfes_src = source,
        .mfes_cover = FIB_NODE_INDEX_INVALID,
        .mfes_sibling = FIB_NODE_INDEX_INVALID,
        .mfes_ref_count = 1,
    };

    vec_add1(mfib_entry->mfe_srcs, esrc);
    vec_sort_with_function(mfib_entry->mfe_srcs,
                           mfib_entry_src_cmp_for_sort);
}

static mfib_entry_src_t *
mfib_entry_src_find (const mfib_entry_t *mfib_entry,
                    mfib_source_t source,
                    u32 *index)

{
    mfib_entry_src_t *esrc;
    int ii;

    ii = 0;
    vec_foreach(esrc, mfib_entry->mfe_srcs)
    {
        if (esrc->mfes_src == source)
        {
            if (NULL != index)
            {
                *index = ii;
            }
            return (esrc);
        }
        else
        {
            ii++;
        }
    }

    return (NULL);
}

static mfib_entry_src_t *
mfib_entry_src_find_or_create (mfib_entry_t *mfib_entry,
                               mfib_source_t source)
{
    mfib_entry_src_t *msrc;

    msrc = mfib_entry_src_find(mfib_entry, source, NULL);

    if (NULL == msrc)
    {
        mfib_entry_src_init(mfib_entry, source);
        msrc = mfib_entry_src_find(mfib_entry, source, NULL);
    }

    return (msrc);
}

static mfib_entry_src_t *
mfib_entry_src_update (mfib_entry_t *mfib_entry,
                       mfib_source_t source,
                       fib_rpf_id_t rpf_id,
                       mfib_entry_flags_t entry_flags)
{
    mfib_entry_src_t *msrc;

    msrc = mfib_entry_src_find_or_create(mfib_entry, source);

    msrc->mfes_flags = entry_flags;
    msrc->mfes_rpf_id = rpf_id;

    return (msrc);
}

static mfib_entry_src_t *
mfib_entry_src_update_and_lock (mfib_entry_t *mfib_entry,
                                mfib_source_t source,
                                fib_rpf_id_t rpf_id,
                                mfib_entry_flags_t entry_flags)
{
    mfib_entry_src_t *msrc;

    msrc = mfib_entry_src_update(mfib_entry, source, rpf_id, entry_flags);

    msrc->mfes_ref_count++;

    return (msrc);
}

mfib_entry_src_t*
mfib_entry_get_best_src (const mfib_entry_t *mfib_entry)
{
    mfib_entry_src_t *bsrc;

    /*
     * the enum of sources is deliberately arranged in priority order
     */
    if (0 == vec_len(mfib_entry->mfe_srcs))
    {
        bsrc = NULL;
    }
    else
    {
        bsrc = vec_elt_at_index(mfib_entry->mfe_srcs, 0);
    }

    return (bsrc);
}

static mfib_source_t
mfib_entry_get_best_source (const mfib_entry_t *mfib_entry)
{
    mfib_entry_src_t *bsrc;

    bsrc = mfib_entry_get_best_src(mfib_entry);

    return (bsrc->mfes_src);
}

int
mfib_entry_is_sourced (fib_node_index_t mfib_entry_index,
                       mfib_source_t source)
{
    mfib_entry_t *mfib_entry;

    mfib_entry = mfib_entry_get(mfib_entry_index);

    return (NULL != mfib_entry_src_find(mfib_entry, source, NULL));
}

int
mfib_entry_is_host (fib_node_index_t mfib_entry_index)
{
    return (mfib_prefix_is_host(mfib_entry_get_prefix(mfib_entry_index)));
}


static void
mfib_entry_src_flush (mfib_entry_src_t *msrc)
{
    u32 sw_if_index;
    index_t mfii;

    hash_foreach(sw_if_index, mfii, msrc->mfes_itfs,
    ({
        mfib_itf_delete(mfib_itf_get(mfii));
    }));
    hash_free(msrc->mfes_itfs);
    msrc->mfes_itfs = NULL;
    fib_path_list_unlock(msrc->mfes_pl);
}

static void
mfib_entry_src_remove (mfib_entry_t *mfib_entry,
                       mfib_source_t source)

{
    mfib_entry_src_t *msrc;
    u32 index = ~0;

    msrc = mfib_entry_src_find(mfib_entry, source, &index);

    if (NULL != msrc)
    {
        ASSERT(0 != msrc->mfes_ref_count);
        msrc->mfes_ref<style>.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="cm">/*</span>
<span class="cm">  Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus</span>

<span class="cm">  Permission is hereby granted, free of charge, to any person obtaining</span>
<span class="cm">  a copy of this software and associated documentation files (the</span>
<span class="cm">  &quot;Software&quot;), to deal in the Software without restriction, including</span>
<span class="cm">  without limitation the rights to use, copy, modify, merge, publish,</span>
<span class="cm">  distribute, sublicense, and/or sell copies of the Software, and to</span>
<span class="cm">  permit persons to whom the Software is furnished to do so, subject to</span>
<span class="cm">  the following conditions:</span>

<span class="cm">  The above copyright notice and this permission notice shall be</span>
<span class="cm">  included in all copies or substantial portions of the Software.</span>

<span class="cm">  THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,</span>
<span class="cm">  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF</span>
<span class="cm">  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND</span>
<span class="cm">  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE</span>
<span class="cm">  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION</span>
<span class="cm">  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION</span>
<span class="cm">  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>
<span class="cm">*/</span>

<span class="n">_</span> <span class="p">(</span><span class="n">EPERM</span><span class="p">,</span> <span class="s">&quot;Operation not permitted&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOENT</span><span class="p">,</span> <span class="s">&quot;No such file or directory&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ESRCH</span><span class="p">,</span> <span class="s">&quot;No such process&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EINTR</span><span class="p">,</span> <span class="s">&quot;Interrupted system call&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EIO</span><span class="p">,</span> <span class="s">&quot;I/O error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENXIO</span><span class="p">,</span> <span class="s">&quot;No such device or address&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">E2BIG</span><span class="p">,</span> <span class="s">&quot;Arg list too long&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOEXEC</span><span class="p">,</span> <span class="s">&quot;Exec format error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBADF</span><span class="p">,</span> <span class="s">&quot;Bad file number&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ECHILD</span><span class="p">,</span> <span class="s">&quot;No child processes&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOMEM</span><span class="p">,</span> <span class="s">&quot;Out of memory&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EACCES</span><span class="p">,</span> <span class="s">&quot;Permission denied&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EFAULT</span><span class="p">,</span> <span class="s">&quot;Bad address&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTBLK</span><span class="p">,</span> <span class="s">&quot;Block device required&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBUSY</span><span class="p">,</span> <span class="s">&quot;Device or resource busy&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EEXIST</span><span class="p">,</span> <span class="s">&quot;File exists&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EXDEV</span><span class="p">,</span> <span class="s">&quot;Cross-device link&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENODEV</span><span class="p">,</span> <span class="s">&quot;No such device&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTDIR</span><span class="p">,</span> <span class="s">&quot;Not a directory&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EISDIR</span><span class="p">,</span> <span class="s">&quot;Is a directory&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EINVAL</span><span class="p">,</span> <span class="s">&quot;Invalid argument&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENFILE</span><span class="p">,</span> <span class="s">&quot;File table overflow&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EMFILE</span><span class="p">,</span> <span class="s">&quot;Too many open files&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTTY</span><span class="p">,</span> <span class="s">&quot;Not a typewriter&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ETXTBSY</span><span class="p">,</span> <span class="s">&quot;Text file busy&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EFBIG</span><span class="p">,</span> <span class="s">&quot;File too large&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOSPC</span><span class="p">,</span> <span class="s">&quot;No space left on device&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ESPIPE</span><span class="p">,</span> <span class="s">&quot;Illegal seek&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EROFS</span><span class="p">,</span> <span class="s">&quot;Read-only file system&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EMLINK</span><span class="p">,</span> <span class="s">&quot;Too many links&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EPIPE</span><span class="p">,</span> <span class="s">&quot;Broken pipe&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EDOM</span><span class="p">,</span> <span class="s">&quot;Math argument out of domain of func&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ERANGE</span><span class="p">,</span> <span class="s">&quot;Math result not representable&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EDEADLK</span><span class="p">,</span> <span class="s">&quot;Resource deadlock would occur&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENAMETOOLONG</span><span class="p">,</span> <span class="s">&quot;File name too long&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOLCK</span><span class="p">,</span> <span class="s">&quot;No record locks available&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOSYS</span><span class="p">,</span> <span class="s">&quot;Function not implemented&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTEMPTY</span><span class="p">,</span> <span class="s">&quot;Directory not empty&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ELOOP</span><span class="p">,</span> <span class="s">&quot;Too many symbolic links encountered&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EWOULDBLOCK</span><span class="p">,</span> <span class="s">&quot;Operation would block&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOMSG</span><span class="p">,</span> <span class="s">&quot;No message of desired type&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EIDRM</span><span class="p">,</span> <span class="s">&quot;Identifier removed&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ECHRNG</span><span class="p">,</span> <span class="s">&quot;Channel number out of range&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EL2NSYNC</span><span class="p">,</span> <span class="s">&quot;Level 2 not synchronized&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EL3HLT</span><span class="p">,</span> <span class="s">&quot;Level 3 halted&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EL3RST</span><span class="p">,</span> <span class="s">&quot;Level 3 reset&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ELNRNG</span><span class="p">,</span> <span class="s">&quot;Link number out of range&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EUNATCH</span><span class="p">,</span> <span class="s">&quot;Protocol driver not attached&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOCSI</span><span class="p">,</span> <span class="s">&quot;No CSI structure available&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EL2HLT</span><span class="p">,</span> <span class="s">&quot;Level 2 halted&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBADE</span><span class="p">,</span> <span class="s">&quot;Invalid exchange&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBADR</span><span class="p">,</span> <span class="s">&quot;Invalid request descriptor&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EXFULL</span><span class="p">,</span> <span class="s">&quot;Exchange full&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOANO</span><span class="p">,</span> <span class="s">&quot;No anode&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBADRQC</span><span class="p">,</span> <span class="s">&quot;Invalid request code&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBADSLT</span><span class="p">,</span> <span class="s">&quot;Invalid slot&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBFONT</span><span class="p">,</span> <span class="s">&quot;Bad font file format&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOSTR</span><span class="p">,</span> <span class="s">&quot;Device not a stream&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENODATA</span><span class="p">,</span> <span class="s">&quot;No data available&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ETIME</span><span class="p">,</span> <span class="s">&quot;Timer expired&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOSR</span><span class="p">,</span> <span class="s">&quot;Out of streams resources&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENONET</span><span class="p">,</span> <span class="s">&quot;Machine is not on the network&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOPKG</span><span class="p">,</span> <span class="s">&quot;Package not installed&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EREMOTE</span><span class="p">,</span> <span class="s">&quot;Object is remote&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOLINK</span><span class="p">,</span> <span class="s">&quot;Link has been severed&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EADV</span><span class="p">,</span> <span class="s">&quot;Advertise error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ESRMNT</span><span class="p">,</span> <span class="s">&quot;Srmount error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ECOMM</span><span class="p">,</span> <span class="s">&quot;Communication error on send&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EPROTO</span><span class="p">,</span> <span class="s">&quot;Protocol error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EMULTIHOP</span><span class="p">,</span> <span class="s">&quot;Multihop attempted&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EDOTDOT</span><span class="p">,</span> <span class="s">&quot;RFS specific error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBADMSG</span><span class="p">,</span> <span class="s">&quot;Not a data message&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EOVERFLOW</span><span class="p">,</span> <span class="s">&quot;Value too large for defined data type&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTUNIQ</span><span class="p">,</span> <span class="s">&quot;Name not unique on network&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EBADFD</span><span class="p">,</span> <span class="s">&quot;File descriptor in bad state&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EREMCHG</span><span class="p">,</span> <span class="s">&quot;Remote address changed&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ELIBACC</span><span class="p">,</span> <span class="s">&quot;Can not access a needed shared library&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ELIBBAD</span><span class="p">,</span> <span class="s">&quot;Accessing a corrupted shared library&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ELIBSCN</span><span class="p">,</span> <span class="s">&quot;lib section in a.out corrupted&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ELIBMAX</span><span class="p">,</span> <span class="s">&quot;Attempting to link in too many shared libraries&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ELIBEXEC</span><span class="p">,</span> <span class="s">&quot;Cannot exec a shared library directly&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EILSEQ</span><span class="p">,</span> <span class="s">&quot;Illegal byte sequence&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ERESTART</span><span class="p">,</span> <span class="s">&quot;Interrupted system call should be restarted&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ESTRPIPE</span><span class="p">,</span> <span class="s">&quot;Streams pipe error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EUSERS</span><span class="p">,</span> <span class="s">&quot;Too many users&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTSOCK</span><span class="p">,</span> <span class="s">&quot;Socket operation on non-socket&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EDESTADDRREQ</span><span class="p">,</span> <span class="s">&quot;Destination address required&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EMSGSIZE</span><span class="p">,</span> <span class="s">&quot;Message too long&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EPROTOTYPE</span><span class="p">,</span> <span class="s">&quot;Protocol wrong type for socket&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOPROTOOPT</span><span class="p">,</span> <span class="s">&quot;Protocol not available&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EPROTONOSUPPORT</span><span class="p">,</span> <span class="s">&quot;Protocol not supported&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ESOCKTNOSUPPORT</span><span class="p">,</span> <span class="s">&quot;Socket type not supported&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EOPNOTSUPP</span><span class="p">,</span> <span class="s">&quot;Operation not supported on transport endpoint&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EPFNOSUPPORT</span><span class="p">,</span> <span class="s">&quot;Protocol family not supported&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EAFNOSUPPORT</span><span class="p">,</span> <span class="s">&quot;Address family not supported by protocol&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EADDRINUSE</span><span class="p">,</span> <span class="s">&quot;Address already in use&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EADDRNOTAVAIL</span><span class="p">,</span> <span class="s">&quot;Cannot assign requested address&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENETDOWN</span><span class="p">,</span> <span class="s">&quot;Network is down&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENETUNREACH</span><span class="p">,</span> <span class="s">&quot;Network is unreachable&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENETRESET</span><span class="p">,</span> <span class="s">&quot;Network dropped connection because of reset&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ECONNABORTED</span><span class="p">,</span> <span class="s">&quot;Software caused connection abort&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ECONNRESET</span><span class="p">,</span> <span class="s">&quot;Connection reset by peer&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOBUFS</span><span class="p">,</span> <span class="s">&quot;No buffer space available&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EISCONN</span><span class="p">,</span> <span class="s">&quot;Transport endpoint is already connected&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTCONN</span><span class="p">,</span> <span class="s">&quot;Transport endpoint is not connected&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ESHUTDOWN</span><span class="p">,</span> <span class="s">&quot;Cannot send after transport endpoint shutdown&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ETOOMANYREFS</span><span class="p">,</span> <span class="s">&quot;Too many references: cannot splice&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ETIMEDOUT</span><span class="p">,</span> <span class="s">&quot;Connection timed out&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ECONNREFUSED</span><span class="p">,</span> <span class="s">&quot;Connection refused&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EHOSTDOWN</span><span class="p">,</span> <span class="s">&quot;Host is down&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EHOSTUNREACH</span><span class="p">,</span> <span class="s">&quot;No route to host&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EALREADY</span><span class="p">,</span> <span class="s">&quot;Operation already in progress&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EINPROGRESS</span><span class="p">,</span> <span class="s">&quot;Operation now in progress&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ESTALE</span><span class="p">,</span> <span class="s">&quot;Stale NFS file handle&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EUCLEAN</span><span class="p">,</span> <span class="s">&quot;Structure needs cleaning&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOTNAM</span><span class="p">,</span> <span class="s">&quot;Not a XENIX named type file&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENAVAIL</span><span class="p">,</span> <span class="s">&quot;No XENIX semaphores available&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EISNAM</span><span class="p">,</span> <span class="s">&quot;Is a named type file&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EREMOTEIO</span><span class="p">,</span> <span class="s">&quot;Remote I/O error&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EDQUOT</span><span class="p">,</span> <span class="s">&quot;Quota exceeded&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">ENOMEDIUM</span><span class="p">,</span> <span class="s">&quot;No medium found&quot;</span><span class="p">)</span>
<span class="n">_</span> <span class="p">(</span><span class="n">EMEDIUMTYPE</span><span class="p">,</span> <span class="s">&quot;Wrong medium type&quot;</span><span class="p">)</span>
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div id="lfcollabprojects-footer">
  <div class="gray-diagonal">
    <div class="footer-inner">
      <p>
        &copy; 2016 <a href="https://www.fd.io/">FD.io</a> a Linux Foundation
        Collaborative Project. All Rights Reserved.
      </p>
      <p>
        Linux Foundation is a registered trademark of The Linux Foundation.
        Linux is a registered
        <a
          href="http://www.linuxfoundation.org/programs/legal/trademark"
          title="Linux Mark Institute"
          >trademark</a
        >
        of Linus Torvalds.
      </p>
      <p>
        Please see our
        <a href="http://www.linuxfoundation.org/privacy">privacy policy</a> and
        <a href="http://www.linuxfoundation.org/terms">terms of use</a>
      </p>
    </div>
  </div>
</div>
</div> <!-- id=cgit -->
</body>
</html>
*mfib_entry;
    mfib_entry_src_t *msrc;
    mfib_src_res_t res;

    mfib_entry = mfib_entry_get(mfib_entry_index);
    msrc = mfib_entry_get_best_src(mfib_entry);

    res = mfib_entry_src_cover_change(mfib_entry, msrc);

    if (MFIB_SRC_REEVALUATE == res)
    {
        mfib_entry_recalculate_forwarding(mfib_entry, msrc->mfes_src);
    }
    MFIB_ENTRY_DBG(mfib_entry, "cover-changed");
}

/*
 * mfib_entry_cover_updated
 *
 * this entry is tracking its cover and that cover has been updated
 * (i.e. its forwarding information has changed).
 */
void
mfib_entry_cover_updated (fib_node_index_t mfib_entry_index)
{
    mfib_entry_t *mfib_entry;
    mfib_entry_src_t *msrc;
    mfib_src_res_t res;

    mfib_entry = mfib_entry_get(mfib_entry_index);
    msrc = mfib_entry_get_best_src(mfib_entry);

    res = mfib_entry_src_cover_update(mfib_entry, msrc);

    if (MFIB_SRC_REEVALUATE == res)
    {
        mfib_entry_recalculate_forwarding(mfib_entry, msrc->mfes_src);
    }
    MFIB_ENTRY_DBG(mfib_entry, "cover-updated");
}

u32
mfib_entry_pool_size (void)
{
    return (pool_elts(mfib_entry_pool));
}

static clib_error_t *
show_mfib_entry_command (vlib_main_t * vm,
                        unformat_input_t * input,
                        vlib_cli_command_t * cmd)
{
    fib_node_index_t fei;

    if (unformat (input, "%d", &fei))
    {
        /*
         * show one in detail
         */
        if (!pool_is_free_index(mfib_entry_pool, fei))
        {
            vlib_cli_output (vm, "%d@%U",
                             fei,
                             format_mfib_entry, fei,
                             MFIB_ENTRY_FORMAT_DETAIL2);
        }
        else
        {
            vlib_cli_output (vm, "entry %d invalid", fei);
        }
    }
    else
    {
        /*
         * show all
         */
        vlib_cli_output (vm, "FIB Entries:");
        pool_foreach_index(fei, mfib_entry_pool,
        ({
            vlib_cli_output (vm, "%d@%U",
                             fei,
                             format_mfib_entry, fei,
                             MFIB_ENTRY_FORMAT_BRIEF);
        }));
    }

    return (NULL);
}

/*?
 * This commnad displays an entry, or all entries, in the mfib tables indexed by their unique
 * numerical indentifier.
 ?*/
VLIB_CLI_COMMAND (show_mfib_entry, static) = {
  .path = "show mfib entry",
  .function = show_mfib_entry_command,
  .short_help = "show mfib entry",
};
