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

    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,
                                            cpu_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* */
