/*
 * node.c: gre packet processing
 *
 * Copyright (c) 2012 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 <vlib/vlib.h>
#include <vnet/pg/pg.h>
#include <vnet/gre/gre.h>
#include <vnet/mpls/mpls.h>
#include <vppinfra/sparse_vec.h>

#define foreach_gre_input_next			\
_(PUNT, "error-punt")                           \
_(DROP, "error-drop")                           \
_(ETHERNET_INPUT, "ethernet-input")             \
_(IP4_INPUT, "ip4-input")                       \
_(IP6_INPUT, "ip6-input")			\
_(MPLS_INPUT, "mpls-input")

typedef enum
{
#define _(s,n) GRE_INPUT_NEXT_##s,
  foreach_gre_input_next
#undef _
    GRE_INPUT_N_NEXT,
} gre_input_next_t;

typedef struct
{
  u32 tunnel_id;
  u32 length;
  ip46_address_t src;
  ip46_address_t dst;
  u8 is_ipv6;
} gre_rx_trace_t;

u8 *
format_gre_rx_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 *);
  gre_rx_trace_t *t = va_arg (*args, gre_rx_trace_t *);

  s = format (s, "GRE: tunnel %d len %d src %U dst %U",
	      t->tunnel_id, clib_net_to_host_u16 (t->length),
	      format_ip46_address, &t->src, IP46_TYPE_ANY,
	      format_ip46_address, &t->dst, IP46_TYPE_ANY);
  return s;
}

typedef struct
{
  /* Sparse vector mapping gre protocol in network byte order
     to next index. */
  u16 *next_by_protocol;
} gre_input_runtime_t;

always_inline uword
gre_input (vlib_main_t * vm,
	   vlib_node_runtime_t * node, vlib_frame_t * from_frame, u8 is_ipv6)
{
  gre_main_t *gm = &gre_main;
  __attribute__ ((unused)) u32 n_left_from, next_index, *from, *to_next;
  gre_tunnel_key_t cached_tunnel_key;

  u32 cached_tunnel_sw_if_index = ~0, tunnel_sw_if_index = ~0;

  u32 thread_index = vm->thread_index;
  u32 len;
  vnet_interface_main_t *im = &gm->vnet_main->interface_main;

  if (!is_ipv6)
    clib_memset (&cached_tunnel_key.gtk_v4, 0xff,
		 sizeof (cached_tunnel_key.gtk_v4));
  else
    clib_memset (&cached_tunnel_key.gtk_v6, 0xff,
		 sizeof (cached_tunnel_key.gtk_v6));

  from = vlib_frame_vector_args (from_frame);
  n_left_from = from_frame->n_vectors;

  next_index = node->cached_next_index;

  while (n_left_from > 0)
    {
      u32 n_left_to_next;

      vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);

      while (n_left_from >= 4 && n_left_to_next >= 2)
	{
	  u32 bi0, bi1;
	  vlib_buffer_t *b0, *b1;
	  gre_header_t *h0, *h1;
	  u16 version0, version1;
	  int verr0, verr1;
	  u32 i0, i1, next0, next1, protocol0, protocol1;
	  ip4_header_t *ip4_0, *ip4_1;
	  ip6_header_t *ip6_0, *ip6_1;
	  gre_tunnel_key_t key0, key1;

	  /* Prefetch next iteration. */
	  {
	    vlib_buffer_t *p2, *p3;

	    p2 = vlib_get_buffer (vm, from[2]);
	    p3 = vlib_get_buffer (vm, from[3]);

	    vlib_prefetch_buffer_header (p2, LOAD);
	    vlib_prefetch_buffer_header (p3, LOAD);

	    CLIB_PREFETCH (p2->data, sizeof (h0[0]), LOAD);
	    CLIB_PREFETCH (p3->data, sizeof (h1[0]), LOAD);
	  }

	  bi0 = from[0];
	  bi1 = from[1];
	  to_next[0] = bi0;
	  to_next[1] = bi1;
	  from += 2;
	  to_next += 2;
	  n_left_to_next -= 2;
	  n_left_from -= 2;

	  b0 = vlib_get_buffer (vm, bi0);
	  b1 = vlib_get_buffer (vm, bi1);

	  if (!is_ipv6)
	    {
	      /* ip4_local hands us the ip header, not the gre header */
	      ip4_0 = vlib_buffer_get_current (b0);
	      ip4_1 = vlib_buffer_get_current (b1);

	      vlib_buffer_advance (b0, sizeof (*ip4_0));
	      vlib_buffer_advance (b1, sizeof (*ip4_1));
	    }
	  else
	    {
	      /* ip6_local hands us the ip header, not the gre header */
	      ip6_0 = vlib_buffer_get_current (b0);
	      ip6_1 = vlib_buffer_get_current (b1);

	      vlib_buffer_advance (b0, sizeof (*ip6_0));
	      vlib_buffer_advance (b1, sizeof (*ip6_1));
	    }

	  h0 = vlib_buffer_get_current (b0);
	  h1 = vlib_buffer_get_current (b1);

	  /* Index sparse array with network byte order. */
	  protocol0 = h0->protocol;
	  protocol1 = h1->protocol;
	  sparse_vec_index2 (gm->next_by_protocol, protocol0, protocol1,
			     &i0, &i1);
	  next0 = vec_elt (gm->next_by_protocol, i0).next_index;
	  next1 = vec_elt (gm->next_by_protocol, i1).next_index;
	  u8 ttype0 = vec_elt (gm->next_by_protocol, i0).tunnel_type;
	  u8 ttype1 = vec_elt (gm->next_by_protocol, i1).tunnel_type;

	  b0->error =
	    node->errors[i0 ==
			 SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL
			 : GRE_ERROR_NONE];
	  b1->error =
	    node->errors[i1 ==
			 SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL
			 : GRE_ERROR_NONE];

	  version0 = clib_net_to_host_u16 (h0->flags_and_version);
	  verr0 = version0 & GRE_VERSION_MASK;
	  version1 = clib_net_to_host_u16 (h1->flags_and_version);
	  verr1 = version1 & GRE_VERSION_MASK;

	  b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
	    : b0->error;
	  next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
	  b1->error = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
	    : b1->error;
	  next1 = verr1 ? GRE_INPUT_NEXT_DROP : next1;


	  /* RPF check for ip4/ip6 input */
	  if (PREDICT_TRUE (next0 > GRE_INPUT_NEXT_DROP))
	    {
	      if (is_ipv6)
		{
		  gre_mk_key6 (&ip6_0->dst_address,
			       &ip6_0->src_address,
			       vnet_buffer (b0)->ip.fib_index,
			       ttype0, 0, &key0.gtk_v6);
		}
	      else
		{
		  gre_mk_key4 (ip4_0->dst_address,
			       ip4_0->src_address,
			       vnet_buffer (b0)->ip.fib_index,
			       ttype0, 0, &key0.gtk_v4);
		}

	      if ((!is_ipv6 && !gre_match_key4 (&cached_tunnel_key.gtk_v4,
						&key0.gtk_v4)) ||
		  (is_ipv6 && !gre_match_key6 (&cached_tunnel_key.gtk_v6,
					       &key0.gtk_v6)))
		{
		  gre_tunnel_t *t;
		  uword *p;

		  if (!is_ipv6)
		    {
		      p = hash_get_mem (gm->tunnel_by_key4, &key0.gtk_v4);
		    }
		  else
		    {
		      p = hash_get_mem (gm->tunnel_by_key6, &key0.gtk_v6);
		    }
		  if (!p)
		    {
		      next0 = GRE_INPUT_NEXT_DROP;
		      b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
		      goto drop0;
		    }
		  t = pool_elt_at_index (gm->tunnels, p[0]);
		  tunnel_sw_if_index = t->sw_if_index;

		  cached_tunnel_sw_if_index = tunnel_sw_if_index;
		  if (!is_ipv6)
		    {
		      cached_tunnel_key.gtk_v4 = key0.gtk_v4;
		    }
		  else
		    {
		      cached_tunnel_key.gtk_v6 = key0.gtk_v6;
		    }
		}
	      else
		{
		  tunnel_sw_if_index = cached_tunnel_sw_if_index;
		}
	    }
	  else
	    {
	      next0 = GRE_INPUT_NEXT_DROP;
	      goto drop0;
	    }
	  len = vlib_buffer_length_in_chain (vm, b0);
	  vlib_increment_combined_counter (im->combined_sw_if_counters
					   + VNET_INTERFACE_COUNTER_RX,
					   thread_index,
					   tunnel_sw_if_index,
					   1 /* packets */ ,
					   len /* bytes */ );

	  vnet_buffer (b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;

	drop0:
	  if (PREDICT_TRUE (next1 > GRE_INPUT_NEXT_DROP))
	    {
	      if (is_ipv6)
		{
		  gre_mk_key6 (&ip6_1->dst_address,
			       &ip6_1->src_address,
			       vnet_buffer (b1)->ip.fib_index,
			       ttype1, 0, &key1.gtk_v6);
		}
	      else
		{
		  gre_mk_key4 (ip4_1->dst_address,
			       ip4_1->src_address,
			       vnet_buffer (b1)->ip.fib_index,
			       ttype1, 0, &key1.gtk_v4);
		}

	      if ((!is_ipv6 && !gre_match_key4 (&cached_tunnel_key.gtk_v4,
						&key1.gtk_v4)) ||
		  (is_ipv6 && !gre_match_key6 (&cached_tunnel_key.gtk_v6,
					       &key1.gtk_v6)))
		{
		  gre_tunnel_t *t;
		  uword *p;

		  if (!is_ipv6)
		    {
		      p = hash_get_mem (gm->tunnel_by_key4, &key1.gtk_v4);
		    }
		  else
		    {
		      p = hash_get_mem (gm->tunnel_by_key6, &key1.gtk_v6);
		    }
		  if (!p)
		    {
		      next1 = GRE_INPUT_NEXT_DROP;
		      b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
		      goto drop1;
		    }
		  t = pool_elt_at_index (gm->tunnels, p[0]);
		  tunnel_sw_if_index = t->sw_if_index;

		  cached_tunnel_sw_if_index = tunnel_sw_if_index;
		  if (!is_ipv6)
		    {
		      cached_tunnel_key.gtk_v4 = key1.gtk_v4;
		    }
		  else
		    {
		      cached_tunnel_key.gtk_v6 = key1.gtk_v6;
		    }
		}
	      else
		{
		  tunnel_sw_if_index = cached_tunnel_sw_if_index;
		}
	    }
	  else
	    {
	      next1 = GRE_INPUT_NEXT_DROP;
	      goto drop1;
	    }
	  len = vlib_buffer_length_in_chain (vm, b1);
	  vlib_increment_combined_counter (im->combined_sw_if_counters
					   + VNET_INTERFACE_COUNTER_RX,
					   thread_index,
					   tunnel_sw_if_index,
					   1 /* packets */ ,
					   len /* bytes */ );

	  vnet_buffer (b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;

	drop1:
	  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
	    {
	      gre_rx_trace_t *tr = vlib_add_trace (vm, node,
						   b0, sizeof (*tr));
	      tr->tunnel_id = tunnel_sw_if_index;
	      if (!is_ipv6)
		{
		  tr->length = ip4_0->length;
		  tr->src.ip4.as_u32 = ip4_0->src_address.as_u32;
		  tr->dst.ip4.as_u32 = ip4_0->dst_address.as_u32;
		}
	      else
		{
		  tr->length = ip6_0->payload_length;
		  tr->src.ip6.as_u64[0] = ip6_0->src_address.as_u64[0];
		  tr->src.ip6.as_u64[1] = ip6_0->src_address.as_u64[1];
		  tr->dst.ip6.as_u64[0] = ip6_0->dst_address.as_u64[0];
		  tr->dst.ip6.as_u64[1] = ip6_0->dst_address.as_u64[1];
		}
	    }

	  if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
	    {
	      gre_rx_trace_t *tr = vlib_add_trace (vm, node,
						   b1, sizeof (*tr));
	      tr->tunnel_id = tunnel_sw_if_index;
	      if (!is_ipv6)
		{
		  tr->length = ip4_1->length;
		  tr->src.ip4.as_u32 = ip4_1->src_address.as_u32;
		  tr->dst.ip4.as_u32 = ip4_1->dst_address.as_u32;
		}
	      else
		{
		  tr->length = ip6_1->payload_length;
		  tr->src.ip6.as_u64[0] = ip6_1->src_address.as_u64[0];
		  tr->src.ip6.as_u64[1] = ip6_1->src_address.as_u64[1];
		  tr->dst.ip6.as_u64[0] = ip6_1->dst_address.as_u64[0];
		  tr->dst.ip6.as_u64[1] = ip6_1->dst_address.as_u64[1];
		}
	    }

	  vlib_buffer_advance (b0, sizeof (*h0));
	  vlib_buffer_advance (b1, sizeof (*h1));

	  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
					   to_next, n_left_to_next,
					   bi0, bi1, next0, next1);
	}

      while (n_left_from > 0 && n_left_to_next > 0)
	{
	  u32 bi0;
	  vlib_buffer_t *b0;
	  gre_header_t *h0;
	  ip4_header_t *ip4_0;
	  ip6_header_t *ip6_0;
	  u16 version0;
	  int verr0;
	  u32 i0, next0;
	  gre_tunnel_key_t key0;

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

	  b0 = vlib_get_buffer (vm, bi0);
	  ip4_0 = vlib_buffer_get_current (b0);
	  ip6_0 = (void *) ip4_0;

	  if (!is_ipv6)
	    {
	      vlib_buffer_advance (b0, sizeof (*ip4_0));
	    }
	  else
	    {
	      vlib_buffer_advance (b0, sizeof (*ip6_0));
	    }

	  h0 = vlib_buffer_get_current (b0);

	  i0 = sparse_vec_index (gm->next_by_protocol, h0->protocol);
	  next0 = vec_elt (gm->next_by_protocol, i0).next_index;
	  u8 ttype0 = vec_elt (gm->next_by_protocol, i0).tunnel_type;

	  b0->error =
	    node->errors[i0 == SPARSE_VEC_INVALID_INDEX
			 ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];

	  version0 = clib_net_to_host_u16 (h0->flags_and_version);
	  verr0 = version0 & GRE_VERSION_MASK;
	  b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
	    : b0->error;
	  next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;


	  /* For IP payload we need to find source interface
	     so we can increase counters and help forward node to
	     pick right FIB */
	  /* RPF check for ip4/ip6 input */
	  if (PREDICT_TRUE (next0 > GRE_INPUT_NEXT_DROP))
	    {
	      if (is_ipv6)
		{
		  gre_mk_key6 (&ip6_0->dst_address,
			       &ip6_0->src_address,
			       vnet_buffer (b0)->ip.fib_index,
			       ttype0, 0, &key0.gtk_v6);
		}
	      else
		{
		  gre_mk_key4 (ip4_0->dst_address,
			       ip4_0->src_address,
			       vnet_buffer (b0)->ip.fib_index,
			       ttype0, 0, &key0.gtk_v4);
		}

	      if ((!is_ipv6 && !gre_match_key4 (&cached_tunnel_key.gtk_v4,
						&key0.gtk_v4)) ||
		  (is_ipv6 && !gre_match_key6 (&cached_tunnel_key.gtk_v6,
					       &key0.gtk_v6)))
		{
		  gre_tunnel_t *t;
		  uword *p;

		  if (!is_ipv6)
		    {
		      p = hash_get_mem (gm->tunnel_by_key4, &key0.gtk_v4);
		    }
		  else
		    {
		      p = hash_get_mem (gm->tunnel_by_key6, &key0.gtk_v6);
		    }
		  if (!p)
		    {
		      next0 = GRE_INPUT_NEXT_DROP;
		      b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
		      goto drop;
		    }
		  t = pool_elt_at_index (gm->tunnels, p[0]);
		  tunnel_sw_if_index = t->sw_if_index;

		  cached_tunnel_sw_if_index = tunnel_sw_if_index;
		  if (!is_ipv6)
		    {
		      cached_tunnel_key.gtk_v4 = key0.gtk_v4;
		    }
		  else
		    {
		      cached_tunnel_key.gtk_v6 = key0.gtk_v6;
		    }
		}
	      else
		{
		  tunnel_sw_if_index = cached_tunnel_sw_if_index;
		}
	    }
	  else
	    {
	      next0 = GRE_INPUT_NEXT_DROP;
	      goto drop;
	    }
	  len = vlib_buffer_length_in_chain (vm, b0);
	  vlib_increment_combined_counter (im->combined_sw_if_counters
					   + VNET_INTERFACE_COUNTER_RX,
					   thread_index,
					   tunnel_sw_if_index,
					   1 /* packets */ ,
					   len /* bytes */ );

	  vnet_buffer (b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;

	drop:
	  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
	    {
	      gre_rx_trace_t *tr = vlib_add_trace (vm, node,
						   b0, sizeof (*tr));
	      tr->tunnel_id = tunnel_sw_if_index;
	      if (!is_ipv6)
		{
		  tr->length = ip4_0->length;
		  tr->src.ip4.as_u32 = ip4_0->src_address.as_u32;
		  tr->dst.ip4.as_u32 = ip4_0->dst_address.as_u32;
		}
	      else
		{
		  tr->length = ip6_0->payload_length;
		  tr->src.ip6.as_u64[0] = ip6_0->src_address.as_u64[0];
		  tr->src.ip6.as_u64[1] = ip6_0->src_address.as_u64[1];
		  tr->dst.ip6.as_u64[0] = ip6_0->dst_address.as_u64[0];
		  tr->dst.ip6.as_u64[1] = ip6_0->dst_address.as_u64[1];
		}
	    }

	  vlib_buffer_advance (b0, sizeof (*h0));

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

      vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    }
  vlib_node_increment_counter (vm,
			       !is_ipv6 ? gre4_input_node.index :
			       gre6_input_node.index, GRE_ERROR_PKTS_DECAP,
			       from_frame->n_vectors);
  return from_frame->n_vectors;
}

static uword
gre4_input (vlib_main_t * vm,
	    vlib_node_runtime_t * node, vlib_frame_t * from_frame)
{
  return gre_input (vm, node, from_frame, /* is_ip6 */ 0);
}

static uword
gre6_input (vlib_main_t * vm,
	    vlib_node_runtime_t * node, vlib_frame_t * from_frame)
{
  return gre_input (vm, node, from_frame, /* is_ip6 */ 1);
}

static char *gre_error_strings[] = {
#define gre_error(n,s) s,
#include "error.def"
#undef gre_error
};

/* *INDENT-OFF* */
VLIB_REGISTER_NODE (gre4_input_node) = {
  .function = gre4_input,
  .name = "gre4-input",
  /* Takes a vector of packets. */
  .vector_size = sizeof (u32),

  .n_errors = GRE_N_ERROR,
  .error_strings = gre_error_strings,

  .n_next_nodes = GRE_INPUT_N_NEXT,
  .next_nodes = {
#define _(s,n) [GRE_INPUT_NEXT_##s] = n,
    foreach_gre_input_next
#undef _
  },

  .format_buffer = format_gre_header_with_length,
  .format_trace = format_gre_rx_trace,
  .unformat_buffer = unformat_gre_header,
};

VLIB_REGISTER_NODE (gre6_input_node) = {
  .function = gre6_input,
  .name = "gre6-input",
  /* Takes a vector of packets. */
  .vector_size = sizeof (u32),

  .runtime_data_bytes = sizeof (gre_input_runtime_t),

  .n_errors = GRE_N_ERROR,
  .error_strings = gre_error_strings,

  .n_next_nodes = GRE_INPUT_N_NEXT,
  .next_nodes = {
#define _(s,n) [GRE_INPUT_NEXT_##s] = n,
    foreach_gre_input_next
#undef _
  },

  .format_buffer = format_gre_header_with_length,
  .format_trace = format_gre_rx_trace,
  .unformat_buffer = unformat_gre_header,
};

VLIB_NODE_FUNCTION_MULTIARCH (gre4_input_node, gre4_input)
VLIB_NODE_FUNCTION_MULTIARCH (gre6_input_node, gre6_input)
/* *INDENT-ON* */

void
gre_register_input_protocol (vlib_main_t * vm,
			     gre_protocol_t protocol, u32 node_index,
			     gre_tunnel_type_t tunnel_type)
{
  gre_main_t *em = &gre_main;
  gre_protocol_info_t *pi;
  next_info_t *n;
  u32 i;

  {
    clib_error_t *error = vlib_call_init_function (vm, gre_input_init);
    if (error)
      clib_error_report (error);
  }

  pi = gre_get_protocol_info (em, protocol);
  pi->node_index = node_index;
  pi->tunnel_type = tunnel_type;
  pi->next_index = vlib_node_add_next (vm, gre4_input_node.index, node_index);
  i = vlib_node_add_next (vm, gre6_input_node.index, node_index);
  ASSERT (i == pi->next_index);

  /* Setup gre protocol -> next index sparse vector mapping. */
  n = sparse_vec_validate (em->next_by_protocol,
			   clib_host_to_net_u16 (protocol));
  n->next_index = pi->next_index;
  n->tunnel_type = tunnel_type;
}

static void
gre_setup_node (vlib_main_t * vm, u32 node_index)
{
  vlib_node_t *n = vlib_get_node (vm, node_index);
  pg_node_t *pn = pg_get_node (node_index);

  n->format_buffer = format_gre_header_with_length;
  n->unformat_buffer = unformat_gre_header;
  pn->unformat_edit = unformat_pg_gre_header;
}

static clib_error_t *
gre_input_init (vlib_main_t * vm)
{
  gre_main_t *gm = &gre_main;
  vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input;

  {
    clib_error_t *error;
    error = vlib_call_init_function (vm, gre_init);
    if (error)
      clib_error_report (error);
  }

  gre_setup_node (vm, gre4_input_node.index);
  gre_setup_node (vm, gre6_input_node.index);

  gm->next_by_protocol = sparse_vec_new
    ( /* elt bytes */ sizeof (gm->next_by_protocol[0]),
     /* bits in index */ BITS (((gre_header_t *) 0)->protocol));

  /* These could be moved to the supported protocol input node defn's */
  ethernet_input = vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
  ASSERT (ethernet_input);
  ip4_input = vlib_get_node_by_name (vm, (u8 *) "ip4-input");
  ASSERT (ip4_input);
  ip6_input = vlib_get_node_by_name (vm, (u8 *) "ip6-input");
  ASSERT (ip6_input);
  mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *) "mpls-input");
  ASSERT (mpls_unicast_input);

  gre_register_input_protocol (vm, GRE_PROTOCOL_teb,
			       ethernet_input->index, GRE_TUNNEL_TYPE_TEB);

  gre_register_input_protocol (vm, GRE_PROTOCOL_ip4,
			       ip4_input->index, GRE_TUNNEL_TYPE_L3);

  gre_register_input_protocol (vm, GRE_PROTOCOL_ip6,
			       ip6_input->index, GRE_TUNNEL_TYPE_L3);

  gre_register_input_protocol (vm, GRE_PROTOCOL_mpls_unicast,
			       mpls_unicast_input->index, GRE_TUNNEL_TYPE_L3);

  ip4_register_protocol (IP_PROTOCOL_GRE, gre4_input_node.index);
  ip6_register_protocol (IP_PROTOCOL_GRE, gre6_input_node.index);

  return 0;
}

VLIB_INIT_FUNCTION (gre_input_init);

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
