/*
 * Copyright (c) 2017-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_udp_h__
#define __included_udp_h__

#include <vnet/vnet.h>
#include <vnet/udp/udp_inlines.h>
#include <vnet/udp/udp_local.h>
#include <vnet/udp/udp_packet.h>
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/format.h>

#include <vnet/ip/ip.h>
#include <vnet/session/transport.h>

typedef enum
{
#define udp_error(n,s) UDP_ERROR_##n,
#include <vnet/udp/udp_error.def>
#undef udp_error
  UDP_N_ERROR,
} udp_error_t;

#define foreach_udp_connection_flag					\
  _(CONNECTED, "CONNECTED")	/**< connected mode */			\
  _(OWNS_PORT, "OWNS_PORT")	/**< port belong to conn (UDPC) */	\
  _(CLOSING, "CLOSING")		/**< conn closed with data */		\
  _(LISTEN, "LISTEN")		/**< conn is listening */		\
  _(MIGRATED, "MIGRATED")	/**< cloned to another thread */	\

enum udp_conn_flags_bits
{
#define _(sym, str) UDP_CONN_F_BIT_##sym,
  foreach_udp_connection_flag
#undef _
  UDP_CONN_N_FLAGS
};

typedef enum udp_conn_flags_
{
#define _(sym, str) UDP_CONN_F_##sym = 1 << UDP_CONN_F_BIT_##sym,
  foreach_udp_connection_flag
#undef _
} udp_conn_flags_t;

typedef struct
{
  /** Required for pool_get_aligned */
  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
  transport_connection_t connection;	/**< must be first */
  clib_spinlock_t rx_lock;		/**< rx fifo lock */
  u8 flags;				/**< connection flags */
  u16 mss;				/**< connection mss */
} udp_connection_t;

typedef struct
{
  /* Name (a c string). */
  char *name;

  /* Port number in host byte order. */
  udp_dst_port_t dst_port;

  /* Node which handles this type. */
  u32 node_index;

  /* Next index for this type. */
  u32 next_index;

  /* UDP sessions refcount (not tunnels) */
  u32 n_connections;

  /* Parser for packet generator edits for this protocol */
  unformat_function_t *unformat_pg_edit;
} udp_dst_port_info_t;

typedef enum
{
  UDP_IP6 = 0,
  UDP_IP4,			/* the code is full of is_ip4... */
  N_UDP_AF,
} udp_af_t;

typedef struct
{
  udp_dst_port_info_t *dst_port_infos[N_UDP_AF];

  /* Hash tables mapping name/protocol to protocol info index. */
  uword *dst_port_info_by_name[N_UDP_AF];
  uword *dst_port_info_by_dst_port[N_UDP_AF];

  /* Sparse vector mapping udp dst_port in network byte order
     to next index. */
  u16 *next_by_dst_port4;
  u16 *next_by_dst_port6;
  u8 punt_unknown4;
  u8 punt_unknown6;

  /* Udp local to input arc index */
  u32 local_to_input_edge[N_UDP_AF];

  /*
   * Per-worker thread udp connection pools used with session layer
   */
  udp_connection_t **connections;
  u32 *connection_peekers;
  clib_spinlock_t *peekers_readers_locks;
  clib_spinlock_t *peekers_write_locks;
  udp_connection_t *listener_pool;

  u16 default_mtu;
} udp_main_t;

extern udp_main_t udp_main;
extern vlib_node_registration_t udp4_input_node;
extern vlib_node_registration_t udp6_input_node;
extern vlib_node_registration_t udp4_local_node;
extern vlib_node_registration_t udp6_local_node;

void udp_add_dst_port (udp_main_t * um, udp_dst_port_t dst_port,
		       char *dst_port_name, u8 is_ip4);

always_inline udp_connection_t *
udp_connection_get (u32 conn_index, u32 thread_index)
{
  if (pool_is_free_index (udp_main.connections[thread_index], conn_index))
    return 0;
  return pool_elt_at_index (udp_main.connections[thread_index], conn_index);
}

always_inline udp_connection_t *
udp_listener_get (u32 conn_index)
{
  return pool_elt_at_index (udp_main.listener_pool, conn_index);
}

always_inline udp_main_t *
vnet_get_udp_main ()
{
  return &udp_main;
}

always_inline udp_connection_t *
udp_connection_from_transport (transport_connection_t * tc)
{
  return ((udp_connection_t *) tc);
}

always_inline u32
udp_connection_index (udp_connection_t * uc)
{
  return (uc - udp_main.connections[uc->c_thread_index]);
}

void udp_connection_free (udp_connection_t * uc);
udp_connection_t *udp_connection_alloc (u32 thread_index);

/**
 * Acquires a lock that blocks a connection pool from expanding.
 */
always_inline void
udp_pool_add_peeker (u32 thread_index)
{
  if (thread_index != vlib_get_thread_index ())
    return;
  clib_spinlock_lock_if_init (&udp_main.peekers_readers_locks[thread_index]);
  udp_main.connection_peekers[thread_index] += 1;
  if (udp_main.connection_peekers[thread_index] == 1)
    clib_spinlock_lock_if_init (&udp_main.peekers_write_locks[thread_index]);
  clib_spinlock_unlock_if_init (&udp_main.peekers_readers_locks
				[thread_index]);
}

always_inline void
udp_pool_remove_peeker (u32 thread_index)
{
  if (thread_index != vlib_get_thread_index ())
    return;
  ASSERT (udp_main.connection_peekers[thread_index] > 0);
  clib_spinlock_lock_if_init (&udp_main.peekers_readers_locks[thread_index]);
  udp_main.connection_peekers[thread_index] -= 1;
  if (udp_main.connection_peekers[thread_index] == 0)
    clib_spinlock_unlock_if_init (&udp_main.peekers_write_locks
				  [thread_index]);
  clib_spinlock_unlock_if_init (&udp_main.peekers_readers_locks
				[thread_index]);
}

always_inline udp_connection_t *
udp_connection_clone_safe (u32 connection_index, u32 thread_index)
{
  udp_connection_t *old_c, *new_c;
  u32 current_thread_index = vlib_get_thread_index ();
  new_c = udp_connection_alloc (current_thread_index);

  /* If during the memcpy pool is reallocated AND the memory allocator
   * decides to give the old chunk of memory to somebody in a hurry to
   * scribble something on it, we have a problem. So add this thread as
   * a session pool peeker.
   */
  udp_pool_add_peeker (thread_index);
  old_c = udp_main.connections[thread_index] + connection_index;
  clib_memcpy_fast (new_c, old_c, sizeof (*new_c));
  old_c->flags |= UDP_CONN_F_MIGRATED;
  udp_pool_remove_peeker (thread_index);
  new_c->c_thread_index = current_thread_index;
  new_c->c_c_index = udp_connection_index (new_c);
  new_c->c_fib_index = old_c->c_fib_index;
  /* Assume cloned sessions don't need lock */
  new_c->rx_lock = 0;
  return new_c;
}

always_inline udp_dst_port_info_t *
udp_get_dst_port_info (udp_main_t * um, udp_dst_port_t dst_port, u8 is_ip4)
{
  uword *p = hash_get (um->dst_port_info_by_dst_port[is_ip4], dst_port);
  return p ? vec_elt_at_index (um->dst_port_infos[is_ip4], p[0]) : 0;
}

format_function_t format_udp_header;
format_function_t format_udp_rx_trace;
format_function_t format_udp_connection;
unformat_function_t unformat_udp_header;
unformat_function_t unformat_udp_port;

void udp_connection_share_port (u16 lcl_port, u8 is_ip4);

void udp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);

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

#endif /* __included_udp_h__ */
