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

#include <vnet/ip/ip.h>

/**
 * @file
 * @brief IP prefix management on interfaces
 */

u32
ip_interface_address_find (ip_lookup_main_t * lm,
			   void *addr_fib, u32 address_length)
{
  uword *p = mhash_get (&lm->address_to_if_address_index, addr_fib);

  if (p)
    return (p[0]);

  return (~0);
}

clib_error_t *
ip_interface_address_add (ip_lookup_main_t * lm,
			  u32 sw_if_index,
			  void *addr_fib,
			  u32 address_length, u32 * result_if_address_index)
{
  vnet_main_t *vnm = vnet_get_main ();
  ip_interface_address_t *a, *prev;
  u32 pi;			/* previous index */
  u32 ai;
  u32 hi;			/* head index */

  /* Verify given length. */
  if ((address_length == 0) ||
      (lm->is_ip6 && address_length > 128) ||
      (!lm->is_ip6 && address_length > 32))
    {
      vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
      return clib_error_create
	("%U wrong length for interface %U",
	 lm->format_address_and_length, addr_fib,
	 address_length, format_vnet_sw_if_index_name, vnm, sw_if_index);
    }

  vec_validate_init_empty (lm->if_address_pool_index_by_sw_if_index,
			   sw_if_index, ~0);

  pool_get_zero (lm->if_address_pool, a);

  ai = a - lm->if_address_pool;
  hi = pi = lm->if_address_pool_index_by_sw_if_index[sw_if_index];

  prev = 0;
  while (pi != (u32) ~ 0)
    {
      prev = pool_elt_at_index (lm->if_address_pool, pi);
      pi = prev->next_this_sw_interface;
    }
  pi = prev ? prev - lm->if_address_pool : (u32) ~ 0;

  a->address_key = mhash_set (&lm->address_to_if_address_index,
			      addr_fib, ai, /* old_value */ 0);
  a->address_length = address_length;
  a->sw_if_index = sw_if_index;
  a->flags = 0;
  a->prev_this_sw_interface = pi;
  a->next_this_sw_interface = ~0;
  if (prev)
    prev->next_this_sw_interface = ai;

  lm->if_address_pool_index_by_sw_if_index[sw_if_index] =
    (hi != ~0) ? hi : ai;

  *result_if_address_index = ai;

  return (NULL);
}

clib_error_t *
ip_interface_address_del (ip_lookup_main_t * lm,
			  vnet_main_t * vnm,
			  u32 address_index, void *addr_fib,
			  u32 address_length, u32 sw_if_index)
{
  ip_interface_address_t *a, *prev, *next;

  a = pool_elt_at_index (lm->if_address_pool, address_index);

  if (a->sw_if_index != sw_if_index)
    {
      vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
      return clib_error_create ("%U not found for interface %U",
				lm->format_address_and_length,
				addr_fib, address_length,
				format_vnet_sw_if_index_name,
				vnet_get_main (), sw_if_index);
    }

  if (a->prev_this_sw_interface != ~0)
    {
      prev = pool_elt_at_index (lm->if_address_pool,
				a->prev_this_sw_interface);
      prev->next_this_sw_interface = a->next_this_sw_interface;
    }
  if (a->next_this_sw_interface != ~0)
    {
      next = pool_elt_at_index (lm->if_address_pool,
				a->next_this_sw_interface);
      next->prev_this_sw_interface = a->prev_this_sw_interface;

      if (a->prev_this_sw_interface == ~0)
	lm->if_address_pool_index_by_sw_if_index[a->sw_if_index] =
	  a->next_this_sw_interface;
    }

  if ((a->next_this_sw_interface == ~0) && (a->prev_this_sw_interface == ~0))
    lm->if_address_pool_index_by_sw_if_index[a->sw_if_index] = ~0;

  mhash_unset (&lm->address_to_if_address_index, addr_fib,
	       /* old_value */ 0);
  pool_put (lm->if_address_pool, a);
  return NULL;
}

u8
ip_interface_has_address (u32 sw_if_index, ip46_address_t * ip, u8 is_ip4)
{
  ip_interface_address_t *ia = 0;

  if (is_ip4)
    {
      ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
      ip4_address_t *ip4;
      foreach_ip_interface_address (lm4, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        ip4 = ip_interface_address_get_address (lm4, ia);
        if (ip4_address_compare (ip4, &ip->ip4) == 0)
          return 1;
      }));
    }
  else
    {
      ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
      ip6_address_t *ip6;
      foreach_ip_interface_address (lm6, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        ip6 = ip_interface_address_get_address (lm6, ia);
        if (ip6_address_compare (ip6, &ip->ip6) == 0)
          return 1;
      }));
    }
  return 0;
}

void *
ip_interface_get_first_ip (u32 sw_if_index, u8 is_ip4)
{
  ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
  ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
  ip_interface_address_t *ia = 0;

  if (is_ip4)
    {
      foreach_ip_interface_address (lm4, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        return ip_interface_address_get_address (lm4, ia);
      }));
    }
  else
    {
      foreach_ip_interface_address (lm6, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        ip6_address_t *rv;
        rv = ip_interface_address_get_address (lm6, ia);
        /* Trying to use a link-local ip6 src address is a fool's errand */
        if (!ip6_address_is_link_local_unicast (rv))
          return rv;
      }));
    }

  return 0;
}

walk_rc_t
ip_interface_address_mark_one_interface (vnet_main_t *vnm,
					 vnet_sw_interface_t *si, void *ctx)
{
  ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
  ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
  ip_interface_address_t *ia = 0;

  foreach_ip_interface_address (lm4, ia, si->sw_if_index, 1 /* unnumbered */ ,
  ({
    ia->flags |= IP_INTERFACE_ADDRESS_FLAG_STALE;
  }));
  foreach_ip_interface_address (lm6, ia, si->sw_if_index, 1 /* unnumbered */ ,
  ({
    ia->flags |= IP_INTERFACE_ADDRESS_FLAG_STALE;
  }));

  return (WALK_CONTINUE);
}

void
ip_interface_address_mark (void)
{
  vnet_sw_interface_walk (vnet_get_main (),
			  ip_interface_address_mark_one_interface, NULL);
}

static walk_rc_t
ip_interface_address_sweep_one_interface (vnet_main_t * vnm,
					  vnet_sw_interface_t * si, void *ctx)
{
  vlib_main_t *vm = vlib_get_main ();
  ip4_address_t *ip4_addrs = 0;
  ip6_address_t *ip6_addrs = 0;
  ip4_main_t *im4 = &ip4_main;
  ip6_main_t *im6 = &ip6_main;
  ip_interface_address_t *ia;
  u32 *ip6_masks = 0;
  u32 *ip4_masks = 0;
  int i;

  foreach_ip_interface_address (&im4->lookup_main, ia, si->sw_if_index, 1,
  ({
    if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
      {
        ip4_address_t * x = (ip4_address_t *)
          ip_interface_address_get_address (&im4->lookup_main, ia);
        vec_add1 (ip4_addrs, x[0]);
        vec_add1 (ip4_masks, ia->address_length);
      }
  }));

  foreach_ip_interface_address (&im6->lookup_main, ia, si->sw_if_index, 1,
  ({
    if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
      {
        ip6_address_t * x = (ip6_address_t *)
          ip_interface_address_get_address (&im6->lookup_main, ia);
        vec_add1 (ip6_addrs, x[0]);
        vec_add1 (ip6_masks, ia->address_length);
      }
  }));

  for (i = 0; i < vec_len (ip4_addrs); i++)
    ip4_add_del_interface_address (vm, si->sw_if_index, &ip4_addrs[i],
				   ip4_masks[i], 1 /* is_del */ );
  for (i = 0; i < vec_len (ip6_addrs); i++)
    ip6_add_del_interface_address (vm, si->sw_if_index, &ip6_addrs[i],
				   ip6_masks[i], 1 /* is_del */ );

  vec_free (ip4_addrs);
  vec_free (ip4_masks);
  vec_free (ip6_addrs);
  vec_free (ip6_masks);

  return (WALK_CONTINUE);
}

void
ip_interface_address_sweep (void)
{
  vnet_sw_interface_walk (vnet_get_main (),
			  ip_interface_address_sweep_one_interface, NULL);
}

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