/*
 * 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/vnet.h>
#include <vnet/adj/adj_l2.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/ip/ip.h>

/**
 * @brief Trace data for a L2 Midchain
 */
typedef struct adj_l2_trace_t_ {
    /** Adjacency index taken. */
    u32 adj_index;
} adj_l2_trace_t;

static u8 *
format_adj_l2_trace (u8 * s, va_list * args)
{
    CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
    CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
    adj_l2_trace_t * t = va_arg (*args, adj_l2_trace_t *);

    s = format (s, "adj-idx %d : %U",
		t->adj_index,
		format_ip_adjacency, t->adj_index, FORMAT_IP_ADJACENCY_NONE);
    return s;
}

typedef enum adj_l2_rewrite_next_t_
{
    ADJ_L2_REWRITE_NEXT_DROP,
} adj_l2_rewrite_next_t;

always_inline uword
adj_l2_rewrite_inline (vlib_main_t * vm,
		       vlib_node_runtime_t * node,
		       vlib_frame_t * frame,
		       int is_midchain)
{
    u32 * from = vlib_frame_vector_args (frame);
    u32 n_left_from, n_left_to_next, * to_next, next_index;
    u32 thread_index = vlib_get_thread_index();
    ethernet_main_t * em = &ethernet_main;

    n_left_from = frame->n_vectors;
    next_index = node->cached_next_index;

    while (n_left_from > 0)
    {
	vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);

	while (n_left_from > 0 && n_left_to_next > 0)
	{
	    ip_adjacency_t * adj0;
	    vlib_buffer_t * p0;
	    char *h0;
	    u32 pi0, rw_len0, adj_index0, next0 = 0;
	    u32 tx_sw_if_index0;

	    pi0 = to_next[0] = from[0];
	    from += 1;
	    n_left_from -= 1;
	    to_next += 1;
	    n_left_to_next -= 1;

	    p0 = vlib_get_buffer (vm, pi0);
	    h0 = vlib_buffer_get_current (p0);

	    adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];

	    adj0 = adj_get (adj_index0);

	    /* Guess we are only writing on simple Ethernet header. */
	    vnet_rewrite_one_header (adj0[0], h0,
				     sizeof (ethernet_header_t));

	    /* Update packet buffer attributes/set output interface. */
	    rw_len0 = adj0[0].rewrite_header.data_bytes;
	    vnet_buffer(p0)->ip.save_rewrite_length = rw_len0;
            vnet_buffer(p0)->sw_if_index[VLIB_TX] = adj0->rewrite_header.sw_if_index;

	    vlib_increment_combined_counter(&adjacency_counters,
                                            thread_index,
                                            adj_index0,
                                            /* packet increment */ 0,
                                            /* byte increment */ rw_len0);

	    /* Check MTU of outgoing interface. */
	    if (PREDICT_TRUE((vlib_buffer_length_in_chain (vm, p0)  <=
			      adj0[0].rewrite_header.max_l3_packet_bytes)))
	    {
		/* Don't adjust the buffer for ttl issue; icmp-error node wants
		 * to see the IP headerr */
		p0->current_data -= rw_len0;
		p0->current_length += rw_len0;
		tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;

		if (is_midchain)
		{
		    adj0->sub_type.midchain.fixup_func(vm, adj0, p0);
		}

		vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;

		/*
		 * Follow the feature ARC. this will result eventually in
		 * the midchain-tx node
		 */
		vnet_feature_arc_start(em->output_feature_arc_index, tx_sw_if_index0, &next0, p0);
	    }
	    else
	    {
		/* can't fragment L2 */
		next0 = ADJ_L2_REWRITE_NEXT_DROP;
	    }

	    if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
	    {
		adj_l2_trace_t *tr = vlib_add_trace (vm, node,
						     p0, sizeof (*tr));
		tr->adj_index = vnet_buffer(p0)->ip.adj_index[VLIB_TX];
	    }

	    vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
					     to_next, n_left_to_next,
					     pi0, next0);
	}

	vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    }

    return frame->n_vectors;
}

static uword
adj_l2_rewrite (vlib_main_t * vm,
		vlib_node_runtime_t * node,
		vlib_frame_t * frame)
{
    return adj_l2_rewrite_inline (vm, node, frame, 0);
}

static uword
adj_l2_midchain (vlib_main_t * vm,
		 vlib_node_runtime_t * node,
		 vlib_frame_t * frame)
{
    return adj_l2_rewrite_inline (vm, node, frame, 1);
}

VLIB_REGISTER_NODE (adj_l2_rewrite_node) = {
    .function = adj_l2_rewrite,
    .name = "adj-l2-rewrite",
    .vector_size = sizeof (u32),

    .format_trace = format_adj_l2_trace,

    .n_next_nodes = 1,
    .next_nodes = {
	[ADJ_L2_REWRITE_NEXT_DROP] = "error-drop",
    },
};

VLIB_NODE_FUNCTION_MULTIARCH (adj_l2_rewrite_node, adj_l2_rewrite)

VLIB_REGISTER_NODE (adj_l2_midchain_node) = {
    .function = adj_l2_midchain,
    .name = "adj-l2-midchain",
    .vector_size = sizeof (u32),

    .format_trace = format_adj_l2_trace,

    .n_next_nodes = 1,
    .next_nodes = {
	[ADJ_L2_REWRITE_NEXT_DROP] = "error-drop",
    },
};

VLIB_NODE_FUNCTION_MULTIARCH (adj_l2_midchain_node, adj_l2_midchain)
