/*
 * 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 cpu_index = os_get_cpu_number();
    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];

	    /* We should never rewrite a pkt using the MISS adjacency */
	    ASSERT(adj_index0);

	    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;

	    vlib_increment_combined_counter
		(&adjacency_counters,
		 cpu_index, adj_index0,
		 /* packet increment */ 0,
		 /* byte increment */ rw_len0-sizeof(ethernet_header_t));

	    /* 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)
