summaryrefslogtreecommitdiffstats
path: root/src/plugins/acl/session_inlines.h
AgeCommit message (Expand)AuthorFilesLines
2018-10-19vppinfra: add atomic macros for __sync builtinsSirshak Das1-3/+3
2018-09-26acl-plugin: fix the stateful ICMP handling and add testcasesAndrew Yourtchenko1-39/+40
2018-09-25acl-plugin: optimize session idle timer checksAndrew Yourtchenko1-5/+5
2018-09-24Trivial: Clean up some typos.Paul Vinciguerra1-1/+1
2018-09-14acl-plugin: do not do clib_smp_atomic_add on per-worker countersAndrew Yourtchenko1-2/+2
2018-09-06acl-plugin: VPP-1400: fix crash when removing a session entryAndrew Yourtchenko1-0/+2
2018-07-23fix vector index range checksEyal Bari1-8/+3
2018-06-14acl-plugin: use 16_8 bihash for IPv4 sessions and 40_8 bihash for IPv6 sessionsAndrew Yourtchenko1-38/+81
2018-06-13acl-plugin: change the src/dst L3 info in 5tuple struct to be always contiguo...Andrew Yourtchenko1-7/+27
2018-06-02acl-plugin: multicore: session management fixesAndrew Yourtchenko1-33/+118
2018-05-27acl-plugin: use clib_bihash_search_inline_2_40_8 rather than clib_bihash_sear...Andrew Yourtchenko1-1/+1
2018-05-26acl-plugin: create forward and return sessions in lieu of making a special pe...Andrew Yourtchenko1-70/+104
2018-05-22acl-plugin: refactor to introduce multiarch dataplane functionsAndrew Yourtchenko1-0/+426
id='n290' href='#n290'>290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
/*
 * Copyright (c) 2016 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/lisp-gpe/lisp_gpe_tenant.h>

/**
 * The pool of all tenants
 */
static lisp_gpe_tenant_t *lisp_gpe_tenant_pool;

/**
 * The hash table of all tenants: key:{VNI}.
 */
uword *lisp_gpe_tenant_db;

static lisp_gpe_tenant_t *
lisp_gpe_tenant_find (u32 vni)
{
  uword *p;

  p = hash_get (lisp_gpe_tenant_db, vni);

  if (NULL == p)
    return (NULL);

  return (pool_elt_at_index (lisp_gpe_tenant_pool, p[0]));
}

static lisp_gpe_tenant_t *
lisp_gpe_tenant_find_or_create_i (u32 vni)
{
  lisp_gpe_tenant_t *lt;

  lt = lisp_gpe_tenant_find (vni);

  if (NULL == lt)
    {
      pool_get (lisp_gpe_tenant_pool, lt);
      clib_memset (lt, 0, sizeof (*lt));

      lt->lt_vni = vni;
      lt->lt_table_id = ~0;
      lt->lt_bd_id = ~0;

      hash_set (lisp_gpe_tenant_db, vni, lt - lisp_gpe_tenant_pool);
    }

  return (lt);
}

/**
 * @brief Find or create a tenant for the given VNI
 */
u32
lisp_gpe_tenant_find_or_create (u32 vni)
{
  lisp_gpe_tenant_t *lt;

  lt = lisp_gpe_tenant_find (vni);

  if (NULL == lt)
    {
      lt = lisp_gpe_tenant_find_or_create_i (vni);
    }

  return (lt - lisp_gpe_tenant_pool);
}

/**
 * @brief If there are no more locks/users of te tenant, then delete it
 */
static void
lisp_gpe_tenant_delete_if_empty (lisp_gpe_tenant_t * lt)
{
  int i;

  for (i = 0; i < LISP_GPE_TENANT_LOCK_NUM; i++)
    {
      if (lt->lt_locks[i])
	return;
    }

  hash_unset (lisp_gpe_tenant_db, lt->lt_vni);
  pool_put (lisp_gpe_tenant_pool, lt);
}

/**
 * @brief Add/create and lock a new or find and lock the existing L3
 * interface for the tenant
 *
 * @paran vni The tenant's VNI
 * @param table_id the Tenant's L3 table ID.
 * @param with_default_route Install default route for the interface
 *
 * @return the SW IF index of the L3 interface
 */
u32
lisp_gpe_tenant_l3_iface_add_or_lock (u32 vni, u32 table_id,
				      u8 with_default_route)
{
  lisp_gpe_tenant_t *lt;

  lt = lisp_gpe_tenant_find_or_create_i (vni);

  if (~0 == lt->lt_table_id)
    lt->lt_table_id = table_id;

  ASSERT (lt->lt_table_id == table_id);

  if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE])
    {
      /* create the l3 interface since there are currently no users of it */
      lt->lt_l3_sw_if_index =
	lisp_gpe_add_l3_iface (&lisp_gpe_main, vni, table_id,
			       with_default_route);
    }

  lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]++;

  return (lt->lt_l3_sw_if_index);
}

/**
 * @brief Release the lock held on the tenant's L3 interface
 */
void
lisp_gpe_tenant_l3_iface_unlock (u32 vni)
{
  lisp_gpe_tenant_t *lt;

  lt = lisp_gpe_tenant_find (vni);

  if (NULL == lt)
    {
      clib_warning ("No tenant for VNI %d", vni);
      return;
    }

  if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE])
    {
      clib_warning ("No L3 interface for tenant VNI %d", vni);
      return;
    }

  lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]--;

  if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE])
    {
      /* the last user has gone, so delete the l3 interface */
      lisp_gpe_del_l3_iface (&lisp_gpe_main, vni, lt->lt_table_id);
    }

  /*
   * If there are no more locks on any tenant managed resource, then
   * this tenant is toast.
   */
  lisp_gpe_tenant_delete_if_empty (lt);
}

/**
 * @brief Add/create and lock a new or find and lock the existing L2
 * interface for the tenant
 *
 * @paran vni The tenant's VNI
 * @param table_id the Tenant's L2 Bridge Domain ID.
 *
 * @return the SW IF index of the L2 interface
 */
u32
lisp_gpe_tenant_l2_iface_add_or_lock (u32 vni, u32 bd_id)
{
  lisp_gpe_tenant_t *lt;

  lt = lisp_gpe_tenant_find_or_create_i (vni);

  if (NULL == lt)
    {
      clib_warning ("No tenant for VNI %d", vni);
      return ~0;
    }

  if (~0 == lt->lt_bd_id)
    lt->lt_bd_id = bd_id;

  ASSERT (lt->lt_bd_id == bd_id);

  if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE])
    {
      /* create the l2 interface since there are currently no users of it */
      lt->lt_l2_sw_if_index =
	lisp_gpe_add_l2_iface (&lisp_gpe_main, vni, bd_id);
    }

  lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]++;

  return (lt->lt_l2_sw_if_index);
}

/**
 * @brief Release the lock held on the tenant's L3 interface
 */
void
lisp_gpe_tenant_l2_iface_unlock (u32 vni)
{
  lisp_gpe_tenant_t *lt;

  lt = lisp_gpe_tenant_find (vni);

  if (NULL == lt)
    {
      clib_warning ("No tenant for VNI %d", vni);
      return;
    }

  if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE])
    {
      clib_warning ("No L2 interface for tenant VNI %d", vni);
      return;
    }

  lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]--;

  if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE])
    {
      /* the last user has gone, so delete the l2 interface */
      lisp_gpe_del_l2_iface (&lisp_gpe_main, vni, lt->lt_bd_id);
    }

  /*
   * If there are no more locks on any tenant managed resource, then
   * this tenant is toast.
   */
  lisp_gpe_tenant_delete_if_empty (lt);
}

/**
 * @brief get a const pointer to the tenant object
 */
const lisp_gpe_tenant_t *
lisp_gpe_tenant_get (u32 index)
{
  return (pool_elt_at_index (lisp_gpe_tenant_pool, index));
}

/**
 * @brief Flush/delete ALL the tenants
 */
void
lisp_gpe_tenant_flush (void)
{
  lisp_gpe_tenant_t *lt;

  /* *INDENT-OFF* */
  pool_foreach(lt, lisp_gpe_tenant_pool,
  ({
    lisp_gpe_tenant_l2_iface_unlock(lt->lt_vni);
    lisp_gpe_tenant_l3_iface_unlock(lt->lt_vni);
  }));
  /* *INDENT-ON* */
}

/**
 * @brif Show/display one tenant
 */
static u8 *
format_lisp_gpe_tenant (u8 * s, va_list * ap)
{
  const lisp_gpe_tenant_t *lt = va_arg (*ap, lisp_gpe_tenant_t *);

  s = format (s, "VNI:%d ", lt->lt_vni);

  if (lt->lt_table_id != ~0)
    {
      s = format (s, "VRF:%d ", lt->lt_table_id);
      s = format (s, "L3-SW-IF:%d ", lt->lt_l3_sw_if_index);
    }

  if (lt->lt_bd_id != ~0)
    {
      s = format (s, "BD-ID:%d ", lt->lt_bd_id);
      s = format (s, "L2-SW-IF:%d ", lt->lt_l2_sw_if_index);
    }

  return (s);
}

/**
 * @brief CLI command to show LISP-GPE tenant.
 */
static clib_error_t *
lisp_gpe_tenant_show (vlib_main_t * vm,
		      unformat_input_t * input, vlib_cli_command_t * cmd)
{
  lisp_gpe_tenant_t *lt;

  /* *INDENT-OFF* */
  pool_foreach (lt, lisp_gpe_tenant_pool,
  ({
    vlib_cli_output (vm, "%U", format_lisp_gpe_tenant, lt);
  }));
  /* *INDENT-ON* */

  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (lisp_gpe_tenant_command) = {
  .path = "show gpe tenant",
  .short_help = "show gpe tenant",
  .function = lisp_gpe_tenant_show,
};
/* *INDENT-ON* */


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