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

#include <vnet/vnet.h>
#include <vnet/adj/adj_nsh.h>
#include <vnet/ip/ip.h>

nsh_main_dummy_t nsh_main_dummy;

/**
 * @brief Trace data for a NSH Midchain
 */
typedef struct adj_nsh_trace_t_ {
    /** Adjacency index taken. */
    u32 adj_index;
} adj_nsh_trace_t;

static u8 *
format_adj_nsh_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_nsh_trace_t * t = va_arg (*args, adj_nsh_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_nsh_rewrite_next_t_
{
    ADJ_NSH_REWRITE_NEXT_DROP,
} adj_gpe_rewrite_next_t;

always_inline uword
adj_nsh_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();

    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 IP4 header. */
            vnet_rewrite_one_header(adj0[0], h0, sizeof(ip4_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,
                                            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 (nsh_main_dummy.output_feature_arc_index,
                                        tx_sw_if_index0, &next0, p0);
            }
            else
            {
                /* can't fragment NSH */
                next0 = ADJ_NSH_REWRITE_NEXT_DROP;
            }

            if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
            {
                adj_nsh_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_nsh_rewrite (vlib_main_t * vm,
                vlib_node_runtime_t * node,
                vlib_frame_t * frame)
{
    return adj_nsh_rewrite_inline (vm, node, frame, 0);
}

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

VLIB_REGISTER_NODE (adj_nsh_rewrite_node) = {
    .function = adj_nsh_rewrite,
    .name = "adj-nsh-rewrite",
    .vector_size = sizeof (u32),

    .format_trace = format_adj_nsh_trace,

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

VLIB_NODE_FUNCTION_MULTIARCH (adj_nsh_rewrite_node, adj_nsh_rewrite)

VLIB_REGISTER_NODE (adj_nsh_midchain_node) = {
    .function = adj_nsh_midchain,
    .name = "adj-nsh-midchain",
    .vector_size = sizeof (u32),

    .format_trace = format_adj_nsh_trace,

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

VLIB_NODE_FUNCTION_MULTIARCH (adj_nsh_midchain_node, adj_nsh_midchain)

/* Built-in ip4 tx feature path definition */
/* *INDENT-OFF* */
VNET_FEATURE_ARC_INIT (nsh_output, static) =
{
  .arc_name  = "nsh-output",
  .start_nodes = VNET_FEATURES ("adj-nsh-midchain"),
  .arc_index_ptr = &nsh_main_dummy.output_feature_arc_index,
};

VNET_FEATURE_INIT (nsh_tx_drop, static) =
{
  .arc_name = "nsh-output",
  .node_name = "error-drop",
  .runs_before = 0,     /* not before any other features */
};
/* *INDENT-ON* */
