/*
 * 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/adj/adj_mcast.h>
#include <vnet/adj/adj_internal.h>
#include <vnet/fib/fib_walk.h>
#include <vnet/ip/ip.h>

/*
 * The 'DB' of all mcast adjs.
 * There is only one mcast per-interface per-protocol, so this is a per-interface
 * vector
 */
static adj_index_t *adj_mcasts[FIB_PROTOCOL_MAX];

static u32
adj_get_mcast_node (fib_protocol_t proto)
{
    switch (proto) {
    case FIB_PROTOCOL_IP4:
	return (ip4_rewrite_mcast_node.index);
    case FIB_PROTOCOL_IP6:
	return (ip6_rewrite_mcast_node.index);
    case FIB_PROTOCOL_MPLS:
	break;
    }
    ASSERT(0);
    return (0);
}

/*
 * adj_mcast_add_or_lock
 *
 * The next_hop address here is used for source address selection in the DP.
 * The mcast adj is added to an interface's connected prefix, the next-hop
 * passed here is the local prefix on the same interface.
 */
adj_index_t
adj_mcast_add_or_lock (fib_protocol_t proto,
                       vnet_link_t link_type,
		       u32 sw_if_index)
{
    ip_adjacency_t * adj;

    vec_validate_init_empty(adj_mcasts[proto], sw_if_index, ADJ_INDEX_INVALID);

    if (ADJ_INDEX_INVALID == adj_mcasts[proto][sw_if_index])
    {
        vnet_main_t *vnm;

        vnm = vnet_get_main();
	adj = adj_alloc(proto);

	adj->lookup_next_index = IP_LOOKUP_NEXT_MCAST;
	adj->ia_nh_proto = proto;
	adj->ia_link = link_type;
	adj_mcasts[proto][sw_if_index] = adj_get_index(adj);
        adj_lock(adj_get_index(adj));

	vnet_rewrite_init(vnm, sw_if_index, link_type,
			  adj_get_mcast_node(proto),
			  vnet_tx_node_index_for_sw_interface(vnm, sw_if_index),
			  &adj->rewrite_header);

	/*
	 * we need a rewrite where the destination IP address is converted
	 * to the appropriate link-layer address. This is interface specific.
	 * So ask the interface to do it.
	 */
	vnet_update_adjacency_for_sw_interface(vnm, sw_if_index,
                                               adj_get_index(adj));
    }
    else
    {
	adj = adj_get(adj_mcasts[proto][sw_if_index]);
        adj_lock(adj_get_index(adj));
    }

    return (adj_get_index(adj));
}

/**
 * adj_mcast_update_rewrite
 *
 * Update the adjacency's rewrite string. A NULL string implies the
 * rewrite is reset (i.e. when ARP/ND entry is gone).
 * NB: the adj being updated may be handling traffic in the DP.
 */
void
adj_mcast_update_rewrite (adj_index_t adj_index,
                          u8 *rewrite,
                          u8 offset)
{
    ip_adjacency_t *adj;

    ASSERT(ADJ_INDEX_INVALID != adj_index);

    adj = adj_get(adj_index);

    /*
     * update the adj's rewrite string and build the arc
     * from the rewrite node to the interface's TX node
     */
    adj_nbr_update_rewrite_internal(adj, IP_LOOKUP_NEXT_MCAST,
                                    adj_get_mcast_node(adj->ia_nh_proto),
                                    vnet_tx_node_index_for_sw_interface(
                                        vnet_get_main(),
                                        adj->rewrite_header.sw_if_index),
                                    rewrite);
    /*
     * set the offset corresponding to the mcast IP address rewrite
     */
    adj->rewrite_header.dst_mcast_offset = offset;
}

/**
 * adj_mcast_midchain_update_rewrite
 *
 * Update the adjacency's rewrite string. A NULL string implies the
 * rewrite is reset (i.e. when ARP/ND entry is gone).
 * NB: the adj being updated may be handling traffic in the DP.
 */
void
adj_mcast_midchain_update_rewrite (adj_index_t adj_index,
                                   adj_midchain_fixup_t fixup,
                                   const void *fixup_data,
                                   adj_flags_t flags,
                                   u8 *rewrite,
                                   u8 offset,
                                   u32 mask)
{
    ip_adjacency_t *adj;

    ASSERT(ADJ_INDEX_INVALID != adj_index);

    adj = adj_get(adj_index);

    /*
     * one time only update. since we don't support changing the tunnel
     * src,dst, this is all we need.
     */
    ASSERT(adj->lookup_next_index == IP_LOOKUP_NEXT_MCAST);
    /*
     * tunnels can always provide a rewrite.
     */
    ASSERT(NULL != rewrite);

    adj_midchain_setup(adj_index, fixup, fixup_data, flags);

    /*
     * update the adj's rewrite string and build the arc
     * from the rewrite node to the interface's TX node
     */
    adj_nbr_update_rewrite_internal(adj, IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
                                    adj_get_mcast_node(adj->ia_nh_proto),
                                    vnet_tx_node_index_for_sw_interface(
                                        vnet_get_main(),
                                        adj->rewrite_header.sw_if_index),
                                    rewrite);

    adj->rewrite_header.dst_mcast_offset = offset;
}

void
adj_mcast_remove (fib_protocol_t proto,
		  u32 sw_if_index)
{
    ASSERT(sw_if_index < vec_len(adj_mcasts[proto]));

    adj_mcasts[proto][sw_if_index] = ADJ_INDEX_INVALID;
}

static clib_error_t *
adj_mcast_interface_state_change (vnet_main_t * vnm,
				  u32 sw_if_index,
				  u32 flags)
{
    /*
     * for each mcast on the interface trigger a walk back to the children
     */
    fib_protocol_t proto;
    ip_adjacency_t *adj;


    for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
    {
	if (sw_if_index >= vec_len(adj_mcasts[proto]) ||
	    ADJ_INDEX_INVALID == adj_mcasts[proto][sw_if_index])
	    continue;

	adj = adj_get(adj_mcasts[proto][sw_if_index]);

	fib_node_back_walk_ctx_t bw_ctx = {
	    .fnbw_reason = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP ?
			    FIB_NODE_BW_REASON_FLAG_INTERFACE_UP :
			    FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN),
	};

	fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx);
    }

    return (NULL);
}

VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_mcast_interface_state_change);

/**
 * @brief Invoked on each SW interface of a HW interface when the
 * HW interface state changes
 */
static walk_rc_t
adj_mcast_hw_sw_interface_state_change (vnet_main_t * vnm,
                                        u32 sw_if_index,
                                        void *arg)
{
    adj_mcast_interface_state_change(vnm, sw_if_index, (uword) arg);

    return (WALK_CONTINUE);
}

/**
 * @brief Registered callback for HW interface state changes
 */
static clib_error_t *
adj_mcast_hw_interface_state_change (vnet_main_t * vnm,
                                     u32 hw_if_index,
                                     u32 flags)
{
    /*
     * walk SW interfaces on the HW
     */
    uword sw_flags;

    sw_flags = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
                VNET_SW_INTERFACE_FLAG_ADMIN_UP :
                0);

    vnet_hw_interface_walk_sw(vnm, hw_if_index,
                              adj_mcast_hw_sw_interface_state_change,
                              (void*) sw_flags);

    return (NULL);
}

VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(
    adj_mcast_hw_interface_state_change);

static clib_error_t *
adj_mcast_interface_delete (vnet_main_t * vnm,
			    u32 sw_if_index,
			    u32 is_add)
{
    /*
     * for each mcast on the interface trigger a walk back to the children
     */
    fib_protocol_t proto;
    ip_adjacency_t *adj;

    if (is_add)
    {
	/*
	 * not interested in interface additions. we will not back walk
	 * to resolve paths through newly added interfaces. Why? The control
	 * plane should have the brains to add interfaces first, then routes.
	 * So the case where there are paths with a interface that matches
	 * one just created is the case where the path resolved through an
	 * interface that was deleted, and still has not been removed. The
	 * new interface added, is NO GUARANTEE that the interface being
	 * added now, even though it may have the same sw_if_index, is the
	 * same interface that the path needs. So tough!
	 * If the control plane wants these routes to resolve it needs to
	 * remove and add them again.
	 */
	return (NULL);
    }

    for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
    {
	if (sw_if_index >= vec_len(adj_mcasts[proto]) ||
	    ADJ_INDEX_INVALID == adj_mcasts[proto][sw_if_index])
	    continue;

	adj = adj_get(adj_mcasts[proto][sw_if_index]);

	fib_node_back_walk_ctx_t bw_ctx = {
	    .fnbw_reason =  FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE,
	};

	fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx);
    }

    return (NULL);
}

VNET_SW_INTERFACE_ADD_DEL_FUNCTION(adj_mcast_interface_delete);

/**
 * @brief Walk the multicast Adjacencies on a given interface
 */
void
adj_mcast_walk (u32 sw_if_index,
                fib_protocol_t proto,
                adj_walk_cb_t cb,
                void *ctx)
{
    if (vec_len(adj_mcasts[proto]) > sw_if_index)
    {
        if (ADJ_INDEX_INVALID != adj_mcasts[proto][sw_if_index])
        {
            cb(adj_mcasts[proto][sw_if_index], ctx);
        }
    }
}

u8*
format_adj_mcast (u8* s, va_list *ap)
{
    index_t index = va_arg(*ap, index_t);
    CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
    ip_adjacency_t * adj = adj_get(index);

    s = format(s, "%U-mcast: ",
               format_fib_protocol, adj->ia_nh_proto);
    if (adj->rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)
        s = format(s, "[features] ");
    s = format (s, "%U",
		format_vnet_rewrite,
                &adj->rewrite_header, sizeof (adj->rewrite_data), 0);

    return (s);
}

u8*
format_adj_mcast_midchain (u8* s, va_list *ap)
{
    index_t index = va_arg(*ap, index_t);
    CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
    ip_adjacency_t * adj = adj_get(index);

    s = format(s, "%U-mcast-midchain: ",
               format_fib_protocol, adj->ia_nh_proto);
    s = format (s, "%U",
		format_vnet_rewrite,
		&adj->rewrite_header,
                sizeof (adj->rewrite_data), 0);
    s = format (s, "\n%Ustacked-on:\n%U%U",
		format_white_space, indent,
		format_white_space, indent+2,
		format_dpo_id, &adj->sub_type.midchain.next_dpo, indent+2);

    return (s);
}


static void
adj_dpo_lock (dpo_id_t *dpo)
{
    adj_lock(dpo->dpoi_index);
}
static void
adj_dpo_unlock (dpo_id_t *dpo)
{
    adj_unlock(dpo->dpoi_index);
}

const static dpo_vft_t adj_mcast_dpo_vft = {
    .dv_lock = adj_dpo_lock,
    .dv_unlock = adj_dpo_unlock,
    .dv_format = format_adj_mcast,
    .dv_get_urpf = adj_dpo_get_urpf,
};
const static dpo_vft_t adj_mcast_midchain_dpo_vft = {
    .dv_lock = adj_dpo_lock,
    .dv_unlock = adj_dpo_unlock,
    .dv_format = format_adj_mcast_midchain,
    .dv_get_urpf = adj_dpo_get_urpf,
};

/**
 * @brief The per-protocol VLIB graph nodes that are assigned to a mcast
 *        object.
 *
 * this means that these graph nodes are ones from which a mcast is the
 * parent object in the DPO-graph.
 */
const static char* const adj_mcast_ip4_nodes[] =
{
    "ip4-rewrite-mcast",
    NULL,
};
const static char* const adj_mcast_ip6_nodes[] =
{
    "ip6-rewrite-mcast",
    NULL,
};

const static char* const * const adj_mcast_nodes[DPO_PROTO_NUM] =
{
    [DPO_PROTO_IP4]  = adj_mcast_ip4_nodes,
    [DPO_PROTO_IP6]  = adj_mcast_ip6_nodes,
    [DPO_PROTO_MPLS] = NULL,
};

/**
 * @brief The per-protocol VLIB graph nodes that are assigned to a mcast
 *        object.
 *
 * this means that these graph nodes are ones from which a mcast is the
 * parent object in the DPO-graph.
 */
const static char* const adj_mcast_midchain_ip4_nodes[] =
{
    "ip4-mcast-midchain",
    NULL,
};
const static char* const adj_mcast_midchain_ip6_nodes[] =
{
    "ip6-mcast-midchain",
    NULL,
};

const static char* const * const adj_mcast_midchain_nodes[DPO_PROTO_NUM] =
{
    [DPO_PROTO_IP4]  = adj_mcast_midchain_ip4_nodes,
    [DPO_PROTO_IP6]  = adj_mcast_midchain_ip6_nodes,
    [DPO_PROTO_MPLS] = NULL,
};

/**
 * @brief Return the size of the adj DB.
 * This is only for testing purposes so an efficient implementation is not needed
 */
u32
adj_mcast_db_size (void)
{
    u32 n_adjs, sw_if_index;
    fib_protocol_t proto;

    n_adjs = 0;
    for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
    {
        for (sw_if_index = 0;
             sw_if_index < vec_len(adj_mcasts[proto]);
             sw_if_index++)
        {
            if (ADJ_INDEX_INVALID != adj_mcasts[proto][sw_if_index])
            {
                n_adjs++;
            }
        }
    }
    
    return (n_adjs);
}

void
adj_mcast_module_init (void)
{
    dpo_register(DPO_ADJACENCY_MCAST,
                 &adj_mcast_dpo_vft,
                 adj_mcast_nodes);
    dpo_register(DPO_ADJACENCY_MCAST_MIDCHAIN,
                 &adj_mcast_midchain_dpo_vft,
                 adj_mcast_midchain_nodes);
}
