/*
 * 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/ip/ip.h>
#include <vnet/fib/fib_table.h>

u32 ip_flow_hash_router_id;

ethernet_type_t
ip_address_family_to_ether_type (ip_address_family_t af)
{
  switch (af)
    {
    case AF_IP4:
      return (ETHERNET_TYPE_IP4);
    case AF_IP6:
      return (ETHERNET_TYPE_IP6);
    }
  ASSERT (0);
  return (ETHERNET_TYPE_IP4);
}

u8
ip_is_zero (ip46_address_t * ip46_address, u8 is_ip4)
{
  if (is_ip4)
    return (ip46_address->ip4.as_u32 == 0);
  else
    return (ip46_address->as_u64[0] == 0 && ip46_address->as_u64[1] == 0);
}

u8
ip_is_local_host (ip46_address_t * ip46_address, u8 is_ip4)
{
  if (is_ip4)
    return (ip46_address->ip4.as_u8[0] == 127);
  else
    return (ip46_address->as_u64[0] == 0 &&
	    clib_net_to_host_u64 (ip46_address->as_u64[1]) == 1);
}

u8
ip4_is_local_host (ip4_address_t * ip4_address)
{
  return (ip4_address->as_u8[0] == 127);
}

u8
ip6_is_local_host (ip6_address_t * ip6_address)
{
  return (ip6_address->as_u64[0] == 0 &&
	  clib_net_to_host_u64 (ip6_address->as_u64[1]) == 1);
}

/**
 * Checks that an ip is local to the requested fib
 */
u8
ip_is_local (u32 fib_index, ip46_address_t * ip46_address, u8 is_ip4)
{
  fib_node_index_t fei;
  fib_entry_flag_t flags;
  fib_prefix_t prefix;

  /* Check if requester is local */
  if (is_ip4)
    {
      prefix.fp_len = 32;
      prefix.fp_proto = FIB_PROTOCOL_IP4;
    }
  else
    {
      prefix.fp_len = 128;
      prefix.fp_proto = FIB_PROTOCOL_IP6;
    }

  clib_memcpy_fast (&prefix.fp_addr, ip46_address, sizeof (ip46_address_t));
  fei = fib_table_lookup (fib_index, &prefix);
  flags = fib_entry_get_flags (fei);

  return (flags & FIB_ENTRY_FLAG_LOCAL);
}

void
ip_copy (ip46_address_t * dst, ip46_address_t * src, u8 is_ip4)
{
  if (is_ip4)
    {
      ip46_address_mask_ip4 (dst);
      dst->ip4.as_u32 = src->ip4.as_u32;
    }
  else
    clib_memcpy_fast (&dst->ip6, &src->ip6, sizeof (ip6_address_t));
}

void
ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
{
  if (is_ip4)
    {
      ip46_address_mask_ip4 (dst);
      dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
    }
  else
    clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
		      sizeof (ip6_address_t));
}

static const char *ip_arc_names[N_IP_FEATURE_LOCATIONS][N_AF][N_SAFI] = {
  [IP_FEATURE_INPUT] = {
    [AF_IP4] = {
      [SAFI_UNICAST] = "ip4-unicast",
      [SAFI_MULTICAST] = "ip4-multicast",
    },
    [AF_IP6] = {
      [SAFI_UNICAST] = "ip6-unicast",
      [SAFI_MULTICAST] = "ip6-multicast",
    },
  },
  [IP_FEATURE_OUTPUT] = {
    [AF_IP4] = {
      [SAFI_UNICAST] = "ip4-output",
      [SAFI_MULTICAST] = "ip4-output",
    },
    [AF_IP6] = {
      [SAFI_UNICAST] = "ip6-output",
      [SAFI_MULTICAST] = "ip6-output",
    },
  },
  [IP_FEATURE_LOCAL] = {
    [AF_IP4] = {
      [SAFI_UNICAST] = "ip4-local",
      [SAFI_MULTICAST] = "ip4-local",
    },
    [AF_IP6] = {
      [SAFI_UNICAST] = "ip6-local",
      [SAFI_MULTICAST] = "ip6-local",
    },
  },
  [IP_FEATURE_PUNT] = {
    [AF_IP4] = {
      [SAFI_UNICAST] = "ip4-punt",
      [SAFI_MULTICAST] = "ip4-punt",
    },
    [AF_IP6] = {
      [SAFI_UNICAST] = "ip6-punt",
      [SAFI_MULTICAST] = "ip6-punt",
    },
  },
  [IP_FEATURE_DROP] = {
    [AF_IP4] = {
      [SAFI_UNICAST] = "ip4-drop",
      [SAFI_MULTICAST] = "ip4-drop",
    },
    [AF_IP6] = {
      [SAFI_UNICAST] = "ip6-drop",
      [SAFI_MULTICAST] = "ip6-drop",
    },
  },
};

void
ip_feature_enable_disable (ip_address_family_t af,
			   ip_sub_address_family_t safi,
			   ip_feature_location_t loc,
			   const char *feature_name,
			   u32 sw_if_index, int enable,
			   void *feature_config, u32 n_feature_config_bytes)
{
  if (IP_FEATURE_INPUT == loc)
    {
      if (N_SAFI == safi)
	FOR_EACH_IP_ADDRESS_SUB_FAMILY (safi)
	  vnet_feature_enable_disable (ip_arc_names[loc][af][safi],
				       feature_name, sw_if_index,
				       enable, feature_config,
				       n_feature_config_bytes);
      else
	vnet_feature_enable_disable (ip_arc_names[loc][af][safi],
				     feature_name, sw_if_index,
				     enable, feature_config,
				     n_feature_config_bytes);
    }
  else
    vnet_feature_enable_disable (ip_arc_names[loc][af][SAFI_UNICAST],
				 feature_name, sw_if_index,
				 enable, feature_config,
				 n_feature_config_bytes);
}

int
ip_flow_hash_set (ip_address_family_t af, u32 table_id, u32 flow_hash_config)
{
  fib_protocol_t fproto;
  u32 fib_index;

  fproto = ip_address_family_to_fib_proto (af);
  fib_index = fib_table_find (fproto, table_id);

  if (~0 == fib_index)
    return VNET_API_ERROR_NO_SUCH_FIB;

  fib_table_set_flow_hash_config (fib_index, fproto, flow_hash_config);

  return 0;
}

void
ip_flow_hash_router_id_set (u32 router_id)
{
  ip_flow_hash_router_id = router_id;
}

u8 *
format_ip_address_family (u8 * s, va_list * args)
{
  ip_address_family_t af = va_arg (*args, int);	// int promo ip_address_family_t);

  switch (af)
    {
    case AF_IP4:
      return (format (s, "ip4"));
    case AF_IP6:
      return (format (s, "ip6"));
    }

  return (format (s, "unknown"));
}

uword
unformat_ip_address_family (unformat_input_t * input, va_list * args)
{
  ip_address_family_t *af = va_arg (*args, ip_address_family_t *);

  if (unformat (input, "ip4") || unformat (input, "ipv4") ||
      unformat (input, "IP4") || unformat (input, "IPv4"))
    {
      *af = AF_IP4;
      return (1);
    }
  else if (unformat (input, "ip6") || unformat (input, "ipv6") ||
	   unformat (input, "IP6") || unformat (input, "IPv6"))
    {
      *af = AF_IP6;
      return (1);
    }
  return (0);
}

u8 *
format_ip_sub_address_family (u8 * s, va_list * args)
{
  ip_sub_address_family_t safi = va_arg (*args, int);	// int promo ip_sub_address_family_t);

  switch (safi)
    {
    case SAFI_UNICAST:
      return (format (s, "unicast"));
    case SAFI_MULTICAST:
      return (format (s, "multicast"));
    }

  return (format (s, "unknown"));
}

uword
unformat_ip_sub_address_family (unformat_input_t * input, va_list * args)
{
  ip_sub_address_family_t *safi = va_arg (*args, ip_sub_address_family_t *);

  if (unformat (input, "unicast") || unformat (input, "uni"))
    {
      *safi = SAFI_UNICAST;
      return (1);
    }
  else if (unformat (input, "multicast") || unformat (input, "multi"))
    {
      *safi = SAFI_MULTICAST;
      return (1);
    }
  return (0);
}

u8 *
format_ip_dscp (u8 * s, va_list * va)
{
  ip_dscp_t dscp = va_arg (*va, u32);	// int promotion of u8

  switch (dscp)
    {
#define _(n,v)                                                  \
    case IP_DSCP_##v:                                           \
      return (format (s, "%s", #v));
      foreach_ip_dscp
#undef _
    }

  return (format (s, "unknown"));
}

uword
unformat_ip_dscp (unformat_input_t * input, va_list * args)
{
  ip_dscp_t *dscp = va_arg (*args, ip_dscp_t *);

  if (0)
    ;
#define _(n,v)                                                  \
  else if (unformat (input, #v))                                \
    *dscp = IP_DSCP_##v;
  foreach_ip_dscp
#undef _
    else
    return 0;

  return 1;
}

u8 *
format_ip_ecn (u8 * s, va_list * va)
{
  ip_ecn_t ecn = va_arg (*va, u32);	// int promotion of u8

  switch (ecn)
    {
#define _(n,v)                                                  \
    case IP_ECN_##v:                                           \
      return (format (s, "%s", #v));
      foreach_ip_ecn
#undef _
    }

  return (format (s, "unknown"));
}

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