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

typedef CLIB_PACKED
(struct {
  union {
    struct {
      ip4_address_t addr;
      u32 fib_index;
    };
    u64 as_u64;
  };
}) vtep4_key_t;

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

typedef CLIB_PACKED
(struct {
  ip6_address_t addr;
  u32 fib_index;
}) vtep6_key_t;

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;

#ifdef CLIB_HAVE_VEC512
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;

  u64x8 k4_u64x8 = u64x8_splat (k4.as_u64);
  u64x8 cache = u64x8_load_unaligned (vtep4_u512->vtep4_cache);
  u8 result = u64x8_is_equal_mask (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;
    }

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

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

  last_k4->as_u64 = k4.as_u64;

  return VTEP_CHECK_PASS;
}
#endif

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