/*
 * Copyright (c) 2020 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.
 */

#ifndef included_ip_vtep_h
#define included_ip_vtep_h

#include <vppinfra/hash.h>
#include <vnet/ip/ip.h>
#include <vnet/ip/ip46_address.h>

/**
 * @brief Tunnel endpoint key (IPv4)
 *
 * Tunnel modules maintain a set of vtep4_key_t-s to track local IP
 * addresses that have tunnels established.  Bypass node consults the
 * corresponding set to decide whether a packet should bypass normal
 * processing and go directly to the tunnel protocol handler node.
 */

/* *INDENT-OFF* */
typedef CLIB_PACKED
(struct {
  union {
    struct {
      ip4_address_t addr;
      u32 fib_index;
    };
    u64 as_u64;
  };
}) vtep4_key_t;
/* *INDENT-ON* */

/**
 * @brief Tunnel endpoint key (IPv6)
 *
 * Tunnel modules maintain a set of vtep6_key_t-s to track local IP
 * addresses that have tunnels established.  Bypass node consults the
 * corresponding set to decide whether a packet should bypass normal
 * processing and go directly to the tunnel protocol handler node.
 */

/* *INDENT-OFF* */
typedef CLIB_PACKED
(struct {
  ip6_address_t addr;
  u32 fib_index;
}) vtep6_key_t;
/* *INDENT-ON* */

typedef struct
{
  uword *vtep4;			/* local ip4 VTEPs keyed on their ip4 addr + fib_index */
  uword *vtep6;			/* local ip6 VTEPs keyed on their ip6 addr + fib_index */
} vtep_table_t;

always_inline vtep_table_t
vtep_table_create ()
{
  vtep_table_t t = { };
  t.vtep6 = hash_create_mem (0, sizeof (vtep6_key_t), sizeof (uword));
  return t;
}

uword vtep_addr_ref (vtep_table_t * t, u32 fib_index, ip46_address_t * ip);
uword vtep_addr_unref (vtep_table_t * t, u32 fib_index, ip46_address_t * ip);

always_inline void
vtep4_key_init (vtep4_key_t * k4)
{
  k4->as_u64 = ~((u64) 0);
}

always_inline void
vtep6_key_init (vtep6_key_t * k6)
{
  ip6_address_set_zero (&k6->addr);
  k6->fib_index = (u32) ~ 0;
}

enum
{
  VTEP_CHECK_FAIL = 0,
  VTEP_CHECK_PASS = 1,
  VTEP_CHECK_PASS_UNCHANGED = 2
};

always_inline u8
vtep4_check (vtep_table_t * t, vlib_buffer_t * b0, ip4_header_t * ip40,
	     vtep4_key_t * last_k4)
{
  vtep4_key_t k4;
  k4.addr.as_u32 = ip40->dst_address.as_u32;
  k4.fib_index = vlib_buffer_get_ip4_fib_index (b0);
  if (PREDICT_TRUE (k4.as_u64 == last_k4->as_u64))
    return VTEP_CHECK_PASS_UNCHANGED;
  if (PREDICT_FALSE (!hash_get (t->vtep4, k4.as_u64)))
    return VTEP_CHECK_FAIL;
  last_k4->as_u64 = k4.as_u64;
  return VTEP_CHECK_PASS;
}

typedef struct
{
  vtep4_key_t vtep4_cache[8];
  int idx;
} vtep4_cache_t;

always_inline u8
vtep4_check_vector (vtep_table_t * t, vlib_buffer_t * b0, ip4_header_t * ip40,
		    vtep4_key_t * last_k4, vtep4_cache_t * vtep4_u512)
{
  vtep4_key_t k4;
  k4.addr.as_u32 = ip40->dst_address.as_u32;
  k4.fib_index = vlib_buffer_get_ip4_fib_index (b0);

  if (PREDICT_TRUE (k4.as_u64 == last_k4->as_u64))
    return VTEP_CHECK_PASS_UNCHANGED;

#ifdef CLIB_HAVE_VEC512
  u64x8 k4_u64x8 = u64x8_splat (k4.as_u64);
  u64x8 cache = u64x8_load_unaligned (vtep4_u512->vtep4_cache);
  u8 result = u64x8_mask_is_equal (cache, k4_u64x8);
  if (PREDICT_TRUE (result != 0))
    {
      last_k4->as_u64 =
	vtep4_u512->vtep4_cache[count_trailing_zeros (result)].as_u64;
      return VTEP_CHECK_PASS_UNCHANGED;
    }
#endif

  if (PREDICT_FALSE (!hash_get (t->vtep4, k4.as_u64)))
    return VTEP_CHECK_FAIL;

  last_k4->as_u64 = k4.as_u64;

#ifdef CLIB_HAVE_VEC512
  vtep4_u512->vtep4_cache[vtep4_u512->idx].as_u64 = k4.as_u64;
  vtep4_u512->idx = (vtep4_u512->idx + 1) & 0x7;
#endif

  return VTEP_CHECK_PASS;
}

always_inline u8
vtep6_check (vtep_table_t * t, vlib_buffer_t * b0, ip6_header_t * ip60,
	     vtep6_key_t * last_k6)
{
  vtep6_key_t k6;
  k6.fib_index = vlib_buffer_get_ip6_fib_index (b0);
  if (PREDICT_TRUE (k6.fib_index == last_k6->fib_index
		    && ip60->dst_address.as_u64[0] == last_k6->addr.as_u64[0]
		    && ip60->dst_address.as_u64[1] ==
		    last_k6->addr.as_u64[1]))
    {
      return VTEP_CHECK_PASS_UNCHANGED;
    }
  k6.addr = ip60->dst_address;
  if (PREDICT_FALSE (!hash_get_mem (t->vtep6, &k6)))
    return VTEP_CHECK_FAIL;
  *last_k6 = k6;
  return VTEP_CHECK_PASS;
}
#endif /* included_ip_vtep_h */

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