/* *------------------------------------------------------------------ * ipsec_api.c - ipsec api * * 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 #include #include #include #include #include #include #include #include #include #if WITH_LIBSSL > 0 #include #include #endif /* IPSEC */ #define vl_typedefs /* define message structures */ #include #undef vl_typedefs #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include #undef vl_printfun #include #define foreach_vpe_api_msg \ _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del) \ _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd) \ _(IPSEC_SPD_ENTRY_ADD_DEL, ipsec_spd_entry_add_del) \ _(IPSEC_SAD_ENTRY_ADD_DEL, ipsec_sad_entry_add_del) \ _(IPSEC_SA_DUMP, ipsec_sa_dump) \ _(IPSEC_SPDS_DUMP, ipsec_spds_dump) \ _(IPSEC_SPD_DUMP, ipsec_spd_dump) \ _(IPSEC_SPD_INTERFACE_DUMP, ipsec_spd_interface_dump) \ _(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del) \ _(IPSEC_TUNNEL_IF_SET_SA, ipsec_tunnel_if_set_sa) \ _(IPSEC_SELECT_BACKEND, ipsec_select_backend) \ _(IPSEC_BACKEND_DUMP, ipsec_backend_dump) \ _(IPSEC_TUNNEL_PROTECT_UPDATE, ipsec_tunnel_protect_update) \ _(IPSEC_TUNNEL_PROTECT_DEL, ipsec_tunnel_protect_del) \ _(IPSEC_TUNNEL_PROTECT_DUMP, ipsec_tunnel_protect_dump) static void vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp) { #if WITH_LIBSSL == 0 clib_warning ("unimplemented"); #else vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_spd_add_del_reply_t *rmp; int rv; rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add); REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY); #endif } static void vl_api_ipsec_interface_add_del_spd_t_handler (vl_api_ipsec_interface_add_del_spd_t * mp) { vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_interface_add_del_spd_reply_t *rmp; int rv; u32 sw_if_index __attribute__ ((unused)); u32 spd_id __attribute__ ((unused)); sw_if_index = ntohl (mp->sw_if_index); spd_id = ntohl (mp->spd_id); VALIDATE_SW_IF_INDEX (mp); #if WITH_LIBSSL > 0 rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add); #else rv = VNET_API_ERROR_UNIMPLEMENTED; #endif BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY); } static void vl_api_ipsec_tunnel_protect_update_t_handler (vl_api_ipsec_tunnel_protect_update_t * mp) { vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_tunnel_protect_update_reply_t *rmp; u32 sw_if_index, ii, *sa_ins = NULL; ip_address_t nh; int rv; sw_if_index = ntohl (mp->tunnel.sw_if_index); VALIDATE_SW_IF_INDEX (&(mp->tunnel)); #if WITH_LIBSSL > 0 for (ii = 0; ii < mp->tunnel.n_sa_in; ii++) vec_add1 (sa_ins, ntohl (mp->tunnel.sa_in[ii])); ip_address_decode2 (&mp->tunnel.nh, &nh); rv = ipsec_tun_protect_update (sw_if_index, &nh, ntohl (mp->tunnel.sa_out), sa_ins); #else rv = VNET_API_ERROR_UNIMPLEMENTED; #endif BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_UPDATE_REPLY); } static void vl_api_ipsec_tunnel_protect_del_t_handler (vl_api_ipsec_tunnel_protect_del_t * mp) { vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_tunnel_protect_del_reply_t *rmp; ip_address_t nh; u32 sw_if_index; int rv; sw_if_index = ntohl (mp->sw_if_index); VALIDATE_SW_IF_INDEX (mp); #if WITH_LIBSSL > 0 ip_address_decode2 (&mp->nh, &nh); rv = ipsec_tun_protect_del (sw_if_index, &nh); #else rv = VNET_API_ERROR_UNIMPLEMENTED; #endif BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_DEL_REPLY); } typedef struct ipsec_dump_walk_ctx_t_ { vl_api_registration_t *reg; u32 context; } ipsec_dump_walk_ctx_t; static walk_rc_t send_ipsec_tunnel_protect_details (index_t itpi, void *arg) { ipsec_dump_walk_ctx_t *ctx = arg; vl_api_ipsec_tunnel_protect_details_t *mp; ipsec_tun_protect_t *itp; u32 ii = 0; ipsec_sa_t *sa; itp = ipsec_tun_protect_get (itpi); mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (u32) * itp->itp_n_sa_in)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IPSEC_TUNNEL_PROTECT_DETAILS); mp->context = ctx->context; mp->tun.sw_if_index = htonl (itp->itp_sw_if_index); ip_address_encode2 (itp->itp_key, &mp->tun.nh); sa = ipsec_sa_get (itp->itp_out_sa); mp->tun.sa_out = htonl (sa->id); mp->tun.n_sa_in = itp->itp_n_sa_in; /* *INDENT-OFF* */ FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa, ({ mp->tun.sa_in[ii++] = htonl (sa->id); })); /* *INDENT-ON* */ vl_api_send_msg (ctx->reg, (u8 *) mp); return (WALK_CONTINUE); } static void vl_api_ipsec_tunnel_protect_dump_t_handler (vl_api_ipsec_tunnel_protect_dump_t * mp) { vl_api_registration_t *reg; u32 sw_if_index; #if WITH_LIBSSL > 0 reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; ipsec_dump_walk_ctx_t ctx = { .reg = reg, .context = mp->context, }; sw_if_index = ntohl (mp->sw_if_index); if (~0 == sw_if_index) { ipsec_tun_protect_walk (send_ipsec_tunnel_protect_details, &ctx); } else { ipsec_tun_protect_walk_itf (sw_if_index, send_ipsec_tunnel_protect_details, &ctx); } #else clib_warning ("unimplemented"); #endif } static int ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in, ipsec_policy_action_t * out) { in = clib_net_to_host_u32 (in); switch (in) { #define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \ *out = IPSEC_POLICY_ACTION_##f; \ return (0); foreach_ipsec_policy_action #undef _ } return (VNET_API_ERROR_UNIMPLEMENTED); } static void vl_api_ipsec_spd_entry_add_del_t_handler (vl_api_ipsec_spd_entry_add_del_t * mp) { vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_spd_entry_add_del_reply_t *rmp; ip46_type_t itype; u32 stat_index; int rv; stat_index = ~0; #if WITH_LIBSSL > 0 ipsec_policy_t p; clib_memset (&p, 0, sizeof (p)); p.id = ntohl (mp->entry.spd_id); p.priority = ntohl (mp->entry.priority); itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start); ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop); ip_address_decode (&mp->entry.local_address_start, &p.laddr.start); ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop); p.is_ipv6 = (itype == IP46_TYPE_IP6); p.protocol = mp->entry.protocol; p.rport.start = ntohs (mp->entry.remote_port_start); p.rport.
/*
 * 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.
 */

#undef BIHASH_TYPE
#undef BIHASH_KVP_CACHE_SIZE
#undef BIHASH_KVP_PER_PAGE

#define BIHASH_TYPE _40_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_CACHE_SIZE 2

#ifndef __included_bihash_40_8_h__
#define __included_bihash_40_8_h__

#include <vppinfra/crc32.h>
#include <vppinfra/heap.h>
#include <vppinfra/format.h>
#include <vppinfra/pool.h>
#include <vppinfra/xxhash.h>

typedef struct
{
  u64 key[5];
  u64 value;
} clib_bihash_kv_40_8_t;

static inline int
clib_bihash_is_free_40_8 (const clib_bihash_kv_40_8_t * v)
{
  /* Free values are memset to 0xff, check a bit... */
  if (v->key[0] == ~0ULL && v->value == ~0ULL)
    return 1;
  return 0;
}

static inline u64
clib_bihash_hash_40_8 (const clib_bihash_kv_40_8_t * v)
{
#ifdef clib_crc32c_uses_intrinsics
  return clib_crc32c ((u8 *) v->key, 40);
#else
  u64 tmp = v->key[0] ^ v->key[1] ^ v->key[2] ^ v->key[3] ^ v->key[4];
  return clib_xxhash (tmp);
#endif
}

static inline u8 *
format_bihash_kvp_40_8 (u8 * s, va_list * args)
{
  clib_bihash_kv_40_8_t *v = va_arg (*args, clib_bihash_kv_40_8_t *);

  s = format (s, "key %llu %llu %llu %llu %llu value %llu", v->key[0],
	      v->key[1], v->key[2], v->key[3], v->key[4], v->value);
  return s;
}

static inline int
clib_bihash_key_compare_40_8 (u64 * a, u64 * b)
{
#if defined (CLIB_HAVE_VEC512)
  u64x8 v;
  v = u64x8_load_unaligned (a) ^ u64x8_load_unaligned (b);
  return (u64x8_is_zero_mask (v) & 0x1f) == 0;
#elif defined (CLIB_HAVE_VEC256)
  u64x4 v;
  v = u64x4_load_unaligned (a) ^ u64x4_load_unaligned (b);
  v |= u64x4_load_unaligned (a + 1) ^ u64x4_load_unaligned (b + 1);
  return u64x4_is_all_zero (v);
#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
  u64x2 v;
  v = u64x2_load_unaligned (a) ^ u64x2_load_unaligned (b);
  v |= u64x2_load_unaligne