1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
@media (prefers-color-scheme: light) {
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /*/*
Copyright (c) 2013 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.
*/
#ifndef included_clib_pfhash_h
#define included_clib_pfhash_h
#include <vppinfra/clib.h>
#include <vppinfra/hash.h>
#include <vppinfra/pool.h>
#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__)
typedef struct
{
/* 3 x 16 = 48 key bytes */
union
{
u32x4 k_u32x4[3];
u64 k_u64[6];
} kb;
/* 3 x 4 = 12 value bytes */
u32 values[3];
u32 pad;
} pfhash_kv_16_t;
typedef struct
{
/* 5 x 8 = 40 key bytes */
union
{
u64 k_u64[5];
} kb;
/* 5 x 4 = 20 value bytes */
u32 values[5];
u32 pad;
} pfhash_kv_8_t;
typedef struct
{
/* 4 x 8 = 32 key bytes */
union
{
u64 k_u64[4];
} kb;
/* 4 x 8 = 32 value bytes */
u64 values[4];
} pfhash_kv_8v8_t;
typedef struct
{
/* 8 x 4 = 32 key bytes */
union
{
u32x4 k_u32x4[2];
u32 kb[8];
} kb;
/* 8 x 4 = 32 value bytes */
u32 values[8];
} pfhash_kv_4_t;
typedef union
{
pfhash_kv_16_t kv16;
pfhash_kv_8_t kv8;
pfhash_kv_8v8_t kv8v8;
pfhash_kv_4_t kv4;
} pfhash_kv_t;
typedef struct
{
/* Bucket vector */
u32 *buckets;
#define PFHASH_BUCKET_OVERFLOW (u32)~0
/* Pool of key/value pairs */
pfhash_kv_t *kvp;
/* overflow plain-o-hash */
uword *overflow_hash;
/* Pretty-print name */
u8 *name;
u32 key_size;
u32 value_size;
u32 overflow_count;
u32 nitems;
u32 nitems_in_overflow;
} pfhash_t;
void pfhash_init (pfhash_t * p, char *name, u32 key_size, u32 value_size,
u32 nbuckets);
void pfhash_free (pfhash_t * p);
u64 pfhash_get (pfhash_t * p, u32 bucket, void *key);
void pfhash_set (pfhash_t * p, u32 bucket, void *key, void *value);
void pfhash_unset (pfhash_t * p, u32 bucket, void *key);
format_function_t format_pfhash;
static inline void
pfhash_prefetch_bucket (pfhash_t * p, u32 bucket)
{
CLIB_PREFETCH (&p->buckets[bucket], CLIB_CACHE_LINE_BYTES, LOAD);
}
static inline u32
pfhash_read_bucket_prefetch_kv (pfhash_t * p, u32 bucket)
{
u32 bucket_contents = p->buckets[bucket];
if (PREDICT_TRUE ((bucket_contents & PFHASH_BUCKET_OVERFLOW) == 0))
CLIB_PREFETCH (&p->kvp[bucket_contents], CLIB_CACHE_LINE_BYTES, LOAD);
return bucket_contents;
}
/*
* pfhash_search_kv_16
* See if the supplied 16-byte key matches one of three 16-byte (key,value) pairs.
* Return the indicated value, or ~0 if no match
*
* Note: including the overflow test, the fast path is 35 instrs
* on x86_64. Elves will steal your keyboard in the middle of the night if
* you "improve" it without checking the generated code!
*/
static inline u32
pfhash_search_kv_16 (pfhash_t * p, u32 bucket_contents, u32x4 * key)
{
u32x4 diff0, diff1, diff2;
u32 is_equal0, is_equal1, is_equal2;
u32 no_match;
pfhash_kv_16_t *kv;
u32 rv;
if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
{
uword *hp;
hp = hash_get_mem (p->overflow_hash, key);
if (hp)
return hp[0];
return (u32) ~ 0;
}
kv = &p->kvp[bucket_contents].kv16;
diff0 = u32x4_sub (kv->kb.k_u32x4[0], key[0]);
diff1 = u32x4_sub (kv->kb.k_u32x4[1], key[0]);
diff2 = u32x4_sub (kv->kb.k_u32x4[2], key[0]);
no_match = is_equal0 = (i16) u32x4_zero_byte_mask (diff0);
is_equal1 = (i16) u32x4_zero_byte_mask (diff1);
no_match |= is_equal1;
is_equal2 = (i16) u32x4_zero_byte_mask (diff2);
no_match |= is_equal2;
/* If any of the three items matched, no_match will be zero after this line */
no_match = ~no_match;
rv = (is_equal0 & kv->values[0])
| (is_equal1 & kv->values[1]) | (is_equal2 & kv->values[2]) | no_match;
return rv;
}
static inline u32
pfhash_search_kv_8 (pfhash_t * p, u32 bucket_contents, u64 * key)
{
pfhash_kv_8_t *kv;
u32 rv = (u32) ~ 0;
if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
{
uword *hp;
hp = hash_get_mem (p->overflow_hash, key);
if (hp)
return hp[0];
return (u32) ~ 0;
}
kv = &p->kvp[bucket_contents].kv8;
rv = (kv->kb.k_u64[0] == key[0]) ? kv->values[0] : rv;
rv = (kv->kb.k_u64[1] == key[0]) ? kv->values[1] : rv;
rv = (kv->kb.k_u64[2] == key[0]) ? kv->values[2] : rv;
rv = (kv->kb.k_u64[3] == key[0]) ? kv->values[3] : rv;
rv = (kv->kb.k_u64[4] == key[0]) ? kv->values[4] : rv;
return rv;
}
static inline u64
pfhash_search_kv_8v8 (pfhash_t * p, u32 bucket_contents, u64 * key)
{
pfhash_kv_8v8_t *kv;
u64 rv = (u64) ~ 0;
if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
{
uword *hp;
hp = hash_get_mem (p->overflow_hash, key);
if (hp)
return hp[0];
return (u64) ~ 0;
}
kv = &p->kvp[bucket_contents].kv8v8;
rv = (kv->kb.k_u64[0] == key[0]) ? kv->values[0] : rv;
rv = (kv->kb.k_u64[1] == key[0]) ? kv->values[1] : rv;
rv = (kv->kb.k_u64[2] == key[0]) ? kv->values[2] : rv;
rv = (kv->kb.k_u64[3] == key[0]) ? kv->values[3] : rv;
return rv;
}
static inline u32
pfhash_search_kv_4 (pfhash_t * p, u32 bucket_contents, u32 * key)
{
u32x4 vector_key;
u32x4 is_equal[2];
u32 zbm[2], winner_index;
pfhash_kv_4_t *kv;
if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
{
uword *hp;
hp = hash_get_mem (p->overflow_hash, key);
if (hp)
return hp[0];
return (u32) ~ 0;
}
kv = &p->kvp[bucket_contents].kv4;
vector_key = u32x4_splat (key[0]);
is_equal[0] = (kv->kb.k_u32x4[0] == vector_key);
is_equal[1] = (kv->kb.k_u32x4[1] == vector_key);
zbm[0] = ~u32x4_zero_byte_mask (is_equal[0]) & 0xFFFF;
zbm[1] = ~u32x4_zero_byte_mask (is_equal[1]) & 0xFFFF;
if (PREDICT_FALSE ((zbm[0] == 0) && (zbm[1] == 0)))
return (u32) ~ 0;
winner_index = min_log2 (zbm[0]) >> 2;
winner_index = zbm[1] ? (4 + (min_log2 (zbm[1]) >> 2)) : winner_index;
return kv->values[winner_index];
}
#endif /* CLIB_HAVE_VEC128 */
#endif /* included_clib_pfhash_h */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
|