Files
vpp/src/vppinfra/bihash_vec8_8.h
Dave Barach b9c8c57e98 vppinfra: fix corner-cases in bihash lookup
In a case where one pounds on a single kvp in a KVP_AT_BUCKET_LEVEL
table, the code would sporadically return a transitional value (junk)
from a half-deleted kvp. At most, 64-bits worth of the kvp will be
written atomically, so using memset(...) to smear 0xFF's across a kvp
to free it left a lot to be desired.

Performance impact: very mild positive, thanks to FC for doing a
multi-thread host stack perf/scale test.

Added an ASSERT to catch attempts to add a (key,value) pair which
contains the magic "free kvp" value.

Type: fix

Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: I6a1aa8a2c30bc70bec4b696ce7b17c2839927065
2023-03-18 18:35:46 +00:00

136 lines
3.3 KiB
C

/*
* 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.
*/
#undef BIHASH_TYPE
#undef BIHASH_KVP_PER_PAGE
#undef BIHASH_32_64_SVM
#undef BIHASH_ENABLE_STATS
#undef BIHASH_KVP_AT_BUCKET_LEVEL
#undef BIHASH_LAZY_INSTANTIATE
#undef BIHASH_BUCKET_PREFETCH_CACHE_LINES
#define BIHASH_TYPE _vec8_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_AT_BUCKET_LEVEL 0
#define BIHASH_LAZY_INSTANTIATE 1
#define BIHASH_BUCKET_PREFETCH_CACHE_LINES 1
#ifndef __included_bihash_vec8_8_h__
#define __included_bihash_vec8_8_h__
#include <vppinfra/heap.h>
#include <vppinfra/format.h>
#include <vppinfra/pool.h>
#include <vppinfra/xxhash.h>
#include <vppinfra/crc32.h>
/** 8 octet key, 8 octet key value pair */
typedef struct
{
u64 key; /**< the key */
u64 value; /**< the value */
} clib_bihash_kv_vec8_8_t;
static inline void
clib_bihash_mark_free_vec8_8 (clib_bihash_kv_vec8_8_t *v)
{
v->value = 0xFEEDFACE8BADF00DULL;
}
/** Decide if a clib_bihash_kv_vec8_8_t instance is free
@param v- pointer to the (key,value) pair
*/
static inline int
clib_bihash_is_free_vec8_8 (clib_bihash_kv_vec8_8_t * v)
{
if (v->value == 0xFEEDFACE8BADF00DULL)
return 1;
return 0;
}
/** Hash a clib_bihash_kv_vec8_8_t instance
@param v - pointer to the (key,value) pair, hash the key (only)
*/
static inline u64
clib_bihash_hash_vec8_8 (clib_bihash_kv_vec8_8_t * v)
{
u8 *keyp = (u8 *) (v->key);
/* Note: to torture-test linear scan, make this fn return a constant */
#ifdef clib_crc32c_uses_intrinsics
return clib_crc32c (keyp, vec_len (keyp));
#else
{
int i, j;
u64 sum = 0;
for (i = 0, j = 0; i < vec_len (keyp); i++)
{
sum ^= keyp[i] << (j * 8);
j++;
if (j == 4)
j = 0;
}
return clib_xxhash (sum);
}
#endif
}
/** Format a clib_bihash_kv_vec8_8_t instance
@param s - u8 * vector under construction
@param args (vararg) - the (key,value) pair to format
@return s - the u8 * vector under construction
*/
static inline u8 *
format_bihash_kvp_vec8_8 (u8 * s, va_list * args)
{
clib_bihash_kv_vec8_8_t *v = va_arg (*args, clib_bihash_kv_vec8_8_t *);
s = format (s, "key %U value %llu",
format_hex_bytes, v->key, vec_len ((u8 *) (v->key)), v->value);
return s;
}
/** Compare two clib_bihash_kv_vec8_8_t instances
@param a - first key
@param b - second key
*/
static inline int
clib_bihash_key_compare_vec8_8 (u64 a_arg, u64 b_arg)
{
u8 *a = (u8 *) a_arg;
u8 *b = (u8 *) b_arg;
if (a_arg == ~0ULL || b_arg == ~0ULL)
return 0;
if (vec_len (a) != vec_len (b))
return 0;
return memcmp (a, b, vec_len (a)) == 0;
}
#undef __included_bihash_template_h__
#include <vppinfra/bihash_template.h>
#endif /* __included_bihash_vec8_8_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/