FD.io VPP  v16.06
Vector Packet Processing
hash.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  Copyright (c) 2001-2005 Eliot Dresselhaus
17 
18  Permission is hereby granted, free of charge, to any person obtaining
19  a copy of this software and associated documentation files (the
20  "Software"), to deal in the Software without restriction, including
21  without limitation the rights to use, copy, modify, merge, publish,
22  distribute, sublicense, and/or sell copies of the Software, and to
23  permit persons to whom the Software is furnished to do so, subject to
24  the following conditions:
25 
26  The above copyright notice and this permission notice shall be
27  included in all copies or substantial portions of the Software.
28 
29  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37 
38 #include <vppinfra/hash.h>
39 #include <vppinfra/error.h>
40 #include <vppinfra/mem.h>
41 #include <vppinfra/byte_order.h> /* for clib_arch_is_big_endian */
42 
44 { memset (p, 0, hash_pair_bytes (h)); }
45 
47 { memset (p->value, ~0, hash_value_bytes (h)); }
48 
50 get_pair (void * v, uword i)
51 {
52  hash_t * h = hash_header (v);
53  hash_pair_t * p;
54  ASSERT (i < vec_len (v));
55  p = v;
56  p += i << h->log2_pair_size;
57  return (hash_pair_union_t *) p;
58 }
59 
60 always_inline void set_is_user (void * v, uword i, uword is_user)
61 {
62  hash_t * h = hash_header (v);
63  uword i0 = i / BITS(h->is_user[0]);
64  uword i1 = (uword) 1 << (i % BITS(h->is_user[0]));
65  if (is_user)
66  h->is_user[i0] |= i1;
67  else
68  h->is_user[i0] &= ~i1;
69 }
70 
71 static u8 * hash_format_pair_default (u8 * s, va_list * args);
72 
73 #if uword_bits == 64
74 
75 static inline u64 zap64 (u64 x, word n)
76 {
77 #define _(n) (((u64) 1 << (u64) (8*(n))) - (u64) 1)
78  static u64 masks_little_endian[] = {
79  0, _(1), _(2), _(3), _(4), _(5), _(6), _(7),
80  };
81  static u64 masks_big_endian[] = {
82  0, ~_(7), ~_(6), ~_(5), ~_(4), ~_(3), ~_(2), ~_(1),
83  };
84 #undef _
86  return x & masks_big_endian[n];
87  else
88  return x & masks_little_endian[n];
89 }
90 
91 static inline u64 hash_memory64 (void * p, word n_bytes, u64 state)
92 {
93  u64 * q = p;
94  u64 a, b, c, n;
95 
96  a = b = 0x9e3779b97f4a7c13LL;
97  c = state;
98  n = n_bytes;
99 
100  while (n >= 3 * sizeof(u64))
101  {
102  a += clib_mem_unaligned (q + 0, u64);
103  b += clib_mem_unaligned (q + 1, u64);
104  c += clib_mem_unaligned (q + 2, u64);
105  hash_mix64 (a, b, c);
106  n -= 3*sizeof(u64);
107  q += 3;
108  }
109 
110  c += n_bytes;
111  switch (n / sizeof (u64))
112  {
113  case 2:
114  a += clib_mem_unaligned (q + 0, u64);
115  b += clib_mem_unaligned (q + 1, u64);
116  if (n % sizeof (u64))
117  c += zap64 (clib_mem_unaligned (q + 2, u64),
118  n % sizeof (u64)) << 8;
119  break;
120 
121  case 1:
122  a += clib_mem_unaligned (q + 0, u64);
123  if (n % sizeof (u64))
124  b += zap64 (clib_mem_unaligned (q + 1, u64),
125  n % sizeof (u64));
126  break;
127 
128  case 0:
129  if (n % sizeof (u64))
130  a += zap64 (clib_mem_unaligned (q + 0, u64),
131  n % sizeof (u64));
132  break;
133  }
134 
135  hash_mix64 (a, b, c);
136 
137  return c;
138 }
139 
140 #else /* if uword_bits == 64 */
141 
142 static inline u32 zap32 (u32 x, word n)
143 {
144 #define _(n) (((u32) 1 << (u32) (8*(n))) - (u32) 1)
145  static u32 masks_little_endian[] = {
146  0, _(1), _(2), _(3),
147  };
148  static u32 masks_big_endian[] = {
149  0, ~_(3), ~_(2), ~_(1),
150  };
151 #undef _
153  return x & masks_big_endian[n];
154  else
155  return x & masks_little_endian[n];
156 }
157 
158 static inline u32 hash_memory32 (void * p, word n_bytes, u32 state)
159 {
160  u32 * q = p;
161  u32 a, b, c, n;
162 
163  a = b = 0x9e3779b9;
164  c = state;
165  n = n_bytes;
166 
167  while (n >= 3 * sizeof(u32))
168  {
169  a += clib_mem_unaligned (q + 0, u32);
170  b += clib_mem_unaligned (q + 1, u32);
171  c += clib_mem_unaligned (q + 2, u32);
172  hash_mix32 (a, b, c);
173  n -= 3*sizeof(u32);
174  q += 3;
175  }
176 
177  c += n_bytes;
178  switch (n / sizeof (u32))
179  {
180  case 2:
181  a += clib_mem_unaligned (q + 0, u32);
182  b += clib_mem_unaligned (q + 1, u32);
183  if (n % sizeof (u32))
184  c += zap32 (clib_mem_unaligned (q + 2, u32),
185  n % sizeof (u32)) << 8;
186  break;
187 
188  case 1:
189  a += clib_mem_unaligned (q + 0, u32);
190  if (n % sizeof (u32))
191  b += zap32 (clib_mem_unaligned (q + 1, u32),
192  n % sizeof (u32));
193  break;
194 
195  case 0:
196  if (n % sizeof (u32))
197  a += zap32 (clib_mem_unaligned (q + 0, u32),
198  n % sizeof (u32));
199  break;
200  }
201 
202  hash_mix32 (a, b, c);
203 
204  return c;
205 }
206 #endif
207 
208 uword hash_memory (void * p, word n_bytes, uword state)
209 {
210  uword * q = p;
211 
212 #if uword_bits == 64
213  return hash_memory64 (q, n_bytes, state);
214 #else
215  return hash_memory32 (q, n_bytes, state);
216 #endif
217 }
218 
219 #if uword_bits == 64
221 {
222  u64 a, b, c;
223 
224  a = b = 0x9e3779b97f4a7c13LL;
225  c = 0;
226  a += x;
227  hash_mix64 (a, b, c);
228  return c;
229 }
230 #else
232 {
233  u32 a, b, c;
234 
235  a = b = 0x9e3779b9;
236  c = 0;
237  a += x;
238  hash_mix32 (a, b, c);
239  return c;
240 }
241 #endif
242 
243 /* Call sum function. Hash code will be sum function value
244  modulo the prime length of the hash table. */
246 {
247  uword sum;
248  switch (pointer_to_uword ((void *) h->key_sum))
249  {
250  case KEY_FUNC_NONE:
251  sum = hash_uword (key);
252  break;
253 
255  sum = hash_uword (* uword_to_pointer (key, uword *));
256  break;
257 
259  sum = hash_uword (* uword_to_pointer (key, u32 *));
260  break;
261 
262  case KEY_FUNC_STRING:
263  sum = string_key_sum (h, key);
264  break;
265 
266  default:
267  sum = h->key_sum (h, key);
268  break;
269  }
270 
271  return sum;
272 }
273 
275 {
276  switch (pointer_to_uword ((void *) h->key_equal))
277  {
278  case KEY_FUNC_NONE:
279  break;
280 
282  e = * uword_to_pointer (key1, uword *) == * uword_to_pointer (key2, uword *);
283  break;
284 
286  e = * uword_to_pointer (key1, u32 *) == * uword_to_pointer (key2, u32 *);
287  break;
288 
289  case KEY_FUNC_STRING:
290  e = string_key_equal (h, key1, key2);
291  break;
292 
293  default:
294  e = h->key_equal (h, key1, key2);
295  break;
296  }
297  return e;
298 }
299 
300 /* Compares two keys: returns 1 if equal, 0 if not. */
302 {
303  uword e = key1 == key2;
304  if (CLIB_DEBUG > 0 && key1 == key2)
305  ASSERT (key_equal1 (h, key1, key2, e));
306  if (! e)
307  e = key_equal1 (h, key1, key2, e);
308  return e;
309 }
310 
311 static hash_pair_union_t *
313 {
314  hash_t * h = hash_header (v);
315  hash_pair_t * p0, * p1;
316 
317  p0 = p1 = pi->pairs;
318  if (h->log2_pair_size > 0)
319  p1 = hash_forward (h, p0, indirect_pair_get_len (pi));
320  else
321  p1 += vec_len (p0);
322 
323  while (p0 < p1)
324  {
325  if (key_equal (h, p0->key, key))
326  return (hash_pair_union_t *) p0;
327  p0 = hash_forward1 (h, p0);
328  }
329 
330  return (hash_pair_union_t *) 0;
331 }
332 
333 static hash_pair_union_t *
335  uword i,
336  hash_pair_union_t * p,
337  uword key)
338 {
339  hash_t * h = hash_header (v);
340  hash_pair_t * q;
341  hash_pair_indirect_t * pi = &p->indirect;
342  uword log2_bytes = 0;
343 
344  if (h->log2_pair_size == 0)
345  q = vec_new (hash_pair_t, 2);
346  else
347  {
348  log2_bytes = 1 + hash_pair_log2_bytes (h);
349  q = clib_mem_alloc (1 << log2_bytes);
350  }
351  clib_memcpy (q, &p->direct, hash_pair_bytes (h));
352 
353  pi->pairs = q;
354  if (h->log2_pair_size > 0)
355  indirect_pair_set (pi, log2_bytes, 2);
356 
357  set_is_user (v, i, 0);
358 
359  /* First element is used by existing pair, second will be used by caller. */
360  q = hash_forward1 (h, q);
361  q->key = key;
362  init_pair (h, q);
363  return (hash_pair_union_t *) q;
364 }
365 
366 static hash_pair_union_t *
368  uword * found_key)
369 {
370  hash_t * h = hash_header (v);
371  hash_pair_t * new_pair;
372  hash_pair_union_t * q;
373 
374  q = get_indirect (v, pi, key);
375  if (q)
376  {
377  *found_key = 1;
378  return q;
379  }
380 
381  if (h->log2_pair_size == 0)
382  vec_add2 (pi->pairs, new_pair, 1);
383  else
384  {
385  uword len, new_len, log2_bytes;
386 
387  len = indirect_pair_get_len (pi);
388  log2_bytes = indirect_pair_get_log2_bytes (pi);
389 
390  new_len = len + 1;
391  if (new_len * hash_pair_bytes (h) > (1 << log2_bytes))
392  {
393  pi->pairs = clib_mem_realloc (pi->pairs,
394  1 << (log2_bytes + 1),
395  1 << log2_bytes);
396  log2_bytes++;
397  }
398 
399  indirect_pair_set (pi, log2_bytes, new_len);
400  new_pair = pi->pairs + (len << h->log2_pair_size);
401  }
402  new_pair->key = key;
403  init_pair (h, new_pair);
404  *found_key = 0;
405  return (hash_pair_union_t *) new_pair;
406 }
407 
408 static void unset_indirect (void * v, uword i, hash_pair_t * q)
409 {
410  hash_t * h = hash_header (v);
411  hash_pair_union_t * p = get_pair (v, i);
412  hash_pair_t * e;
413  hash_pair_indirect_t * pi = &p->indirect;
414  uword len, is_vec;
415 
416  is_vec = h->log2_pair_size == 0;
417 
418  ASSERT (! hash_is_user (v, i));
419  len = is_vec ? vec_len (pi->pairs) : indirect_pair_get_len (pi);
420  e = hash_forward (h, pi->pairs, len - 1);
421  ASSERT (q >= pi->pairs && q <= e);
422 
423  /* We have two or fewer pairs and we are delete one pair.
424  Make indirect pointer direct and free indirect memory. */
425  if (len <= 2)
426  {
427  hash_pair_t * r = pi->pairs;
428 
429  if (len == 2)
430  {
431  clib_memcpy (p, q == r ? hash_forward1 (h, r) : r, hash_pair_bytes (h));
432  set_is_user (v, i, 1);
433  }
434  else
435  zero_pair (h, &p->direct);
436 
437  if (is_vec)
438  vec_free (r);
439  else if (r)
440  clib_mem_free (r);
441  }
442  else
443  {
444  /* If deleting a pair we need to keep non-null pairs together. */
445  if (q < e)
446  clib_memcpy (q, e, hash_pair_bytes (h));
447  else
448  zero_pair (h, q);
449  if (is_vec)
450  _vec_len (pi->pairs) -= 1;
451  else
452  indirect_pair_set (pi,
454  len - 1);
455  }
456 }
457 
459  GET = 1,
460  SET = 2,
461  UNSET = 3,
462 };
463 
464 static hash_pair_t * lookup (void * v, uword key, enum lookup_opcode op,
465  void * new_value, void * old_value)
466 {
467  hash_t * h = hash_header (v);
468  hash_pair_union_t * p = 0;
469  uword found_key = 0;
470  uword i;
471 
472  if (! v)
473  return 0;
474 
475  i = key_sum (h, key) & (_vec_len (v) - 1);
476  p = get_pair (v, i);
477 
478  if (hash_is_user (v, i))
479  {
480  found_key = key_equal (h, p->direct.key, key);
481  if (found_key)
482  {
483  if (op == UNSET)
484  {
485  set_is_user (v, i, 0);
486  if (old_value)
487  clib_memcpy (old_value, p->direct.value, hash_value_bytes (h));
488  zero_pair (h, &p->direct);
489  }
490  }
491  else
492  {
493  if (op == SET)
494  p = set_indirect_is_user (v, i, p, key);
495  else
496  p = 0;
497  }
498  }
499  else
500  {
501  hash_pair_indirect_t * pi = &p->indirect;
502 
503  if (op == SET)
504  {
505  if (! pi->pairs)
506  {
507  p->direct.key = key;
508  set_is_user (v, i, 1);
509  }
510  else
511  p = set_indirect (v, pi, key, &found_key);
512  }
513  else
514  {
515  p = get_indirect (v, pi, key);
516  found_key = p != 0;
517  if (found_key && op == UNSET)
518  {
519  if (old_value)
520  clib_memcpy (old_value, &p->direct.value, hash_value_bytes (h));
521 
522  unset_indirect (v, i, &p->direct);
523 
524  /* Nullify p (since it's just been deleted).
525  Otherwise we might be tempted to play with it. */
526  p = 0;
527  }
528  }
529  }
530 
531  if (op == SET && p != 0)
532  {
533  /* Save away old value for caller. */
534  if (old_value && found_key)
535  clib_memcpy (old_value, &p->direct.value, hash_value_bytes (h));
536  clib_memcpy (&p->direct.value, new_value, hash_value_bytes (h));
537  }
538 
539  if (op == SET)
540  h->elts += !found_key;
541  if (op == UNSET)
542  h->elts -= found_key;
543 
544  return &p->direct;
545 }
546 
547 /* Fetch value of key. */
548 uword * _hash_get (void * v, uword key)
549 {
550  hash_t * h = hash_header (v);
551  hash_pair_t * p;
552 
553  /* Don't even search table if its empty. */
554  if (! v || h->elts == 0)
555  return 0;
556 
557  p = lookup (v, key, GET, 0, 0);
558  if (! p)
559  return 0;
560  if (h->log2_pair_size == 0)
561  return &p->key;
562  else
563  return &p->value[0];
564 }
565 
566 hash_pair_t * _hash_get_pair (void * v, uword key)
567 { return lookup (v, key, GET, 0, 0); }
568 
570 {
571  hash_t * h = hash_header (v);
572  hash_pair_t * p;
573 
574  while (1)
575  {
576  if (hn->i == 0 && hn->j == 0)
577  {
578  /* Save flags. */
579  hn->f = h->flags;
580 
581  /* Prevent others from re-sizing hash table. */
582  h->flags |=
586  }
587  else if (hn->i >= hash_capacity (v))
588  {
589  /* Restore flags. */
590  h->flags = hn->f;
591  memset (hn, 0, sizeof (hn[0]));
592  return 0;
593  }
594 
595  p = hash_forward (h, v, hn->i);
596  if (hash_is_user (v, hn->i))
597  {
598  hn->i++;
599  return p;
600  }
601  else
602  {
603  hash_pair_indirect_t * pi = (void *) p;
604  uword n;
605 
606  if (h->log2_pair_size > 0)
607  n = indirect_pair_get_len (pi);
608  else
609  n = vec_len (pi->pairs);
610 
611  if (hn->j >= n)
612  {
613  hn->i++;
614  hn->j = 0;
615  }
616  else
617  return hash_forward (h, pi->pairs, hn->j++);
618  }
619  }
620 }
621 
622 /* Remove key from table. */
623 void * _hash_unset (void * v, uword key, void * old_value)
624 {
625  hash_t * h;
626 
627  if (! v)
628  return v;
629 
630  (void) lookup (v, key, UNSET, 0, old_value);
631 
632  h = hash_header (v);
633  if (! (h->flags & HASH_FLAG_NO_AUTO_SHRINK))
634  {
635  /* Resize when 1/4 full. */
636  if (h->elts > 32 && 4 * (h->elts + 1) < vec_len (v))
637  v = hash_resize (v, vec_len (v) / 2);
638  }
639 
640  return v;
641 }
642 
643 void * _hash_create (uword elts, hash_t * h_user)
644 {
645  hash_t * h;
646  uword log2_pair_size;
647  void * v;
648 
649  /* Size of hash is power of 2 >= ELTS and larger than
650  number of bits in is_user bitmap elements. */
651  elts = clib_max (elts, BITS (h->is_user[0]));
652  elts = 1 << max_log2 (elts);
653 
654  log2_pair_size = 1;
655  if (h_user)
656  log2_pair_size = h_user->log2_pair_size;
657 
658  v = _vec_resize (0,
659  /* vec len: */ elts,
660  /* data bytes: */ (elts << log2_pair_size) * sizeof (hash_pair_t),
661  /* header bytes: */ sizeof (h[0]) + (elts / BITS (h->is_user[0])) * sizeof (h->is_user[0]),
662  /* alignment */ sizeof (hash_pair_t));
663  h = hash_header (v);
664 
665  if (h_user)
666  h[0] = h_user[0];
667 
668  h->log2_pair_size = log2_pair_size;
669  h->elts = 0;
670 
671  /* Default flags to never shrinking hash tables.
672  Shrinking tables can cause "jackpot" cases. */
673  if (! h_user)
675 
676  if (! h->format_pair)
677  {
679  h->format_pair_arg = 0;
680  }
681 
682  return v;
683 }
684 
685 void * _hash_free (void * v)
686 {
687  hash_t * h = hash_header (v);
688  hash_pair_union_t * p;
689  uword i;
690 
691  if (! v)
692  return v;
693 
694  /* We zero all freed memory in case user would be tempted to use it. */
695  for (i = 0; i < hash_capacity (v); i++)
696  {
697  if (hash_is_user (v, i))
698  continue;
699  p = get_pair (v, i);
700  if (h->log2_pair_size == 0)
701  vec_free (p->indirect.pairs);
702  else if (p->indirect.pairs)
704  }
705 
706  vec_free_header (h);
707 
708  return 0;
709 }
710 
711 static void * hash_resize_internal (void * old, uword new_size, uword free_old)
712 {
713  void * new;
714  hash_pair_t * p;
715 
716  new = 0;
717  if (new_size > 0)
718  {
719  hash_t * h = old ? hash_header (old) : 0;
720  new = _hash_create (new_size, h);
721  hash_foreach_pair (p, old, {
722  new = _hash_set3 (new, p->key, &p->value[0], 0);
723  });
724  }
725 
726  if (free_old)
727  hash_free (old);
728  return new;
729 }
730 
731 void * hash_resize (void * old, uword new_size)
732 { return hash_resize_internal (old, new_size, 1); }
733 
734 void * hash_dup (void * old)
735 { return hash_resize_internal (old, vec_len (old), 0); }
736 
737 void * _hash_set3 (void * v, uword key, void * value, void * old_value)
738 {
739  hash_t * h;
740 
741  if (! v)
742  v = hash_create (0, sizeof (uword));
743 
744  h = hash_header (v);
745  (void) lookup (v, key, SET, value, old_value);
746 
747  if (! (h->flags & HASH_FLAG_NO_AUTO_GROW))
748  {
749  /* Resize when 3/4 full. */
750  if (4 * (h->elts + 1) > 3 * vec_len (v))
751  v = hash_resize (v, 2 * vec_len (v));
752  }
753 
754  return v;
755 }
756 
758 {
759  void * v = uword_to_pointer (key, void *);
760  return hash_memory (v, vec_len (v) * h->user, 0);
761 }
762 
764 {
765  void * v1 = uword_to_pointer (key1, void *);
766  void * v2 = uword_to_pointer (key2, void *);
767  uword l1 = vec_len (v1);
768  uword l2 = vec_len (v2);
769  return l1 == l2 && 0 == memcmp (v1, v2, l1 * h->user);
770 }
771 
772 u8 * vec_key_format_pair (u8 * s, va_list * args)
773 {
774  void * CLIB_UNUSED (user_arg) = va_arg (*args, void *);
775  void * v = va_arg (*args, void *);
776  hash_pair_t * p = va_arg (*args, hash_pair_t *);
777  hash_t * h = hash_header (v);
778  void * u = uword_to_pointer (p->key, void *);
779  int i;
780 
781  switch (h->user) {
782  case 1:
783  s = format (s, "%v", u);
784  break;
785 
786  case 2:
787  {
788  u16 * w = u;
789  for (i = 0; i < vec_len (w); i++)
790  s = format (s, "0x%x, ", w[i]);
791  break;
792  }
793 
794  case 4:
795  {
796  u32 * w = u;
797  for (i = 0; i < vec_len (w); i++)
798  s = format (s, "0x%x, ", w[i]);
799  break;
800  }
801 
802  case 8:
803  {
804  u64 * w = u;
805  for (i = 0; i < vec_len (w); i++)
806  s = format (s, "0x%Lx, ", w[i]);
807  break;
808  }
809 
810  default:
811  s = format (s, "0x%U", format_hex_bytes, u, vec_len (u) * h->user);
812  break;
813  }
814 
815  if (hash_value_bytes (h) > 0)
816  s = format (s, " -> 0x%wx", p->value[0]);
817 
818  return s;
819 }
820 
822 {
823  uword * v = uword_to_pointer (key, void *);
824  return hash_memory (v, h->user, 0);
825 }
826 
828 {
829  void * v1 = uword_to_pointer (key1, void *);
830  void * v2 = uword_to_pointer (key2, void *);
831  return v1 && v2 && 0 == memcmp (v1, v2, h->user);
832 }
833 
835 {
836  char * v = uword_to_pointer (key, char *);
837  return hash_memory (v, strlen (v), 0);
838 }
839 
841 {
842  void * v1 = uword_to_pointer (key1, void *);
843  void * v2 = uword_to_pointer (key2, void *);
844  return v1 && v2 && 0 == strcmp (v1, v2);
845 }
846 
847 u8 * string_key_format_pair (u8 * s, va_list * args)
848 {
849  void * CLIB_UNUSED (user_arg) = va_arg (*args, void *);
850  void * v = va_arg (*args, void *);
851  hash_pair_t * p = va_arg (*args, hash_pair_t *);
852  hash_t * h = hash_header (v);
853  void * u = uword_to_pointer (p->key, void *);
854 
855  s = format (s, "%s", u);
856 
857  if (hash_value_bytes (h) > 0)
858  s = format (s, " -> 0x%8U", format_hex_bytes, &p->value[0], hash_value_bytes (h));
859 
860  return s;
861 }
862 
863 static u8 * hash_format_pair_default (u8 * s, va_list * args)
864 {
865  void * CLIB_UNUSED (user_arg) = va_arg (*args, void *);
866  void * v = va_arg (*args, void *);
867  hash_pair_t * p = va_arg (*args, hash_pair_t *);
868  hash_t * h = hash_header (v);
869 
870  s = format (s, "0x%08x", p->key);
871  if (hash_value_bytes (h) > 0)
872  s = format (s, " -> 0x%8U", format_hex_bytes, &p->value[0], hash_value_bytes (h));
873  return s;
874 }
875 
876 uword hash_bytes (void * v)
877 {
878  uword i, bytes;
879  hash_t * h = hash_header (v);
880 
881  if (! v)
882  return 0;
883 
884  bytes = vec_capacity (v, hash_header_bytes (v));
885 
886  for (i = 0; i < hash_capacity (v); i++)
887  {
888  if (! hash_is_user (v, i))
889  {
890  hash_pair_union_t * p = get_pair (v, i);
891  if (h->log2_pair_size > 0)
892  bytes += 1<< indirect_pair_get_log2_bytes (&p->indirect);
893  else
894  bytes += vec_capacity (p->indirect.pairs, 0);
895  }
896  }
897  return bytes;
898 }
899 
900 u8 * format_hash (u8 * s, va_list * va)
901 {
902  void * v = va_arg (*va, void *);
903  int verbose = va_arg (*va, int);
904  hash_pair_t * p;
905  hash_t * h = hash_header (v);
906  uword i;
907 
908  s = format (s, "hash %p, %wd elts, capacity %wd, %wd bytes used,\n",
909  v, hash_elts (v), hash_capacity (v),
910  hash_bytes (v));
911 
912  {
913  uword * occupancy = 0;
914 
915  /* Count number of buckets with each occupancy. */
916  for (i = 0; i < hash_capacity (v); i++)
917  {
918  uword j;
919 
920  if (hash_is_user (v, i))
921  {
922  j = 1;
923  }
924  else
925  {
926  hash_pair_union_t * p = get_pair (v, i);
927  if (h->log2_pair_size > 0)
929  else
930  j = vec_len (p->indirect.pairs);
931  }
932 
933  vec_validate (occupancy, j);
934  occupancy[j]++;
935  }
936 
937  s = format (s, " profile ");
938  for (i = 0; i < vec_len (occupancy); i++)
939  s = format (s, "%wd%c", occupancy[i],
940  i + 1 == vec_len (occupancy) ? '\n' : ' ');
941 
942  s = format (s, " lookup # of compares: ");
943  for (i = 1; i < vec_len (occupancy); i++)
944  s = format (s, "%wd: .%03d%c", i,
945  (1000 * i * occupancy[i]) / hash_elts (v),
946  i + 1 == vec_len (occupancy) ? '\n' : ' ');
947 
948  vec_free (occupancy);
949  }
950 
951  if (verbose)
952  {
953  hash_foreach_pair (p, v, {
954  s = format (s, " %U\n", h->format_pair, h->format_pair_arg, v, p);
955  });
956  }
957 
958  return s;
959 }
960 
961 static uword
963  va_list * va,
964  int is_vec)
965 {
966  uword * hash = va_arg (*va, uword *);
967  int * result = va_arg (*va, int *);
968  u8 * string = 0;
969  uword * p;
970 
971  if (! unformat (input, is_vec ? "%v%_" : "%s%_", &string))
972  return 0;
973 
974  p = hash_get_mem (hash, string);
975  if (p)
976  *result = *p;
977 
978  vec_free (string);
979  return p ? 1 : 0;
980 }
981 
982 uword
984 { return unformat_hash_string_internal (input, va, /* is_vec */ 1); }
985 
986 uword
987 unformat_hash_string (unformat_input_t * input, va_list * va)
988 { return unformat_hash_string_internal (input, va, /* is_vec */ 0); }
989 
991 {
992  hash_t * h = hash_header (v);
993  uword i, j;
994  uword * keys = 0;
995  clib_error_t * error = 0;
996 
997 #define CHECK(x) if ((error = ERROR_ASSERT (x))) goto done;
998 
999  for (i = 0; i < hash_capacity (v); i++)
1000  {
1001  hash_pair_union_t * pu = get_pair (v, i);
1002 
1003  if (hash_is_user (v, i))
1004  {
1005  CHECK (pu->direct.key != 0);
1006  vec_add1 (keys, pu->direct.key);
1007  }
1008  else
1009  {
1010  hash_pair_t * p;
1011  hash_pair_indirect_t * pi = &pu->indirect;
1012  uword n;
1013 
1014  n = h->log2_pair_size > 0
1015  ? indirect_pair_get_len (pi)
1016  : vec_len (pi->pairs);
1017 
1018  for (p = pi->pairs; n-- > 0; p = hash_forward1 (h, p))
1019  {
1020  /* Assert key uniqueness. */
1021  for (j = 0; j < vec_len (keys); j++)
1022  CHECK (keys[j] != p->key);
1023  vec_add1 (keys, p->key);
1024  }
1025  }
1026  }
1027 
1028  CHECK (vec_len (keys) == h->elts);
1029 
1030  vec_free (keys);
1031  done:
1032  return error;
1033 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
lookup_opcode
Definition: hash.c:458
any user
Definition: hash.h:85
#define KEY_FUNC_NONE
Definition: hash.h:76
u8 * string_key_format_pair(u8 *s, va_list *args)
Definition: hash.c:847
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
always_inline void set_is_user(void *v, uword i, uword is_user)
Definition: hash.c:60
static void unset_indirect(void *v, uword i, hash_pair_t *q)
Definition: hash.c:408
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword mem_key_equal(hash_t *h, uword key1, uword key2)
Definition: hash.c:827
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
void * format_pair_arg
Definition: hash.h:91
void * hash_resize(void *old, uword new_size)
Definition: hash.c:731
a
Definition: bitmap.h:393
static void(BVT(clib_bihash)*h, BVT(clib_bihash_value)*v)
#define KEY_FUNC_STRING
Definition: hash.h:79
always_inline void clib_mem_free(void *p)
Definition: mem.h:149
#define KEY_FUNC_POINTER_UWORD
Definition: hash.h:77
always_inline void indirect_pair_set(hash_pair_indirect_t *p, uword log2_alloc, uword len)
Definition: hash.h:193
hash_pair_t * pairs
Definition: hash.h:161
always_inline hash_t * hash_header(void *v)
Definition: hash.h:107
#define HASH_FLAG_NO_AUTO_GROW
Definition: hash.h:62
#define vec_free_header(h)
Free vector user header (syntactic sugar)
Definition: vec.h:304
always_inline uword key_sum(hash_t *h, uword key)
Definition: hash.c:245
static hash_pair_union_t * get_indirect(void *v, hash_pair_indirect_t *pi, uword key)
Definition: hash.c:312
always_inline uword hash_header_bytes(void *v)
Definition: hash.h:99
always_inline void zero_pair(hash_t *h, hash_pair_t *p)
Definition: hash.c:43
uword j
Definition: hash.h:415
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
always_inline uword max_log2(uword x)
Definition: clib.h:216
always_inline void * clib_mem_realloc(void *p, uword new_size, uword old_size)
Definition: mem.h:163
always_inline uword hash_uword(uword x)
Definition: hash.c:231
always_inline void * hash_forward(hash_t *h, void *v, uword n)
Definition: hash.h:302
uword value[0]
Definition: hash.h:151
uword elts
Definition: hash.h:56
u32 log2_pair_size
Definition: hash.h:68
always_inline uword hash_capacity(void *v)
Definition: hash.h:118
static u32 zap32(u32 x, word n)
Definition: hash.c:142
always_inline uword hash_is_user(void *v, uword i)
Definition: hash.h:122
#define KEY_FUNC_POINTER_U32
Definition: hash.h:78
#define always_inline
Definition: clib.h:84
#define vec_new(T, N)
Create new vector of given type and length (unspecified alignment, no header).
Definition: vec.h:268
hash_key_equal_function_t * key_equal
Definition: hash.h:82
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:79
unsigned long u64
Definition: types.h:89
uword vec_key_sum(hash_t *h, uword key)
Definition: hash.c:757
u8 * format_hash(u8 *s, va_list *va)
Definition: hash.c:900
uword f
Definition: hash.h:415
static uword pointer_to_uword(const void *p)
Definition: types.h:131
u8 * vec_key_format_pair(u8 *s, va_list *args)
Definition: hash.c:772
static hash_pair_union_t * set_indirect(void *v, hash_pair_indirect_t *pi, uword key, uword *found_key)
Definition: hash.c:367
clib_error_t * hash_validate(void *v)
Definition: hash.c:990
always_inline void init_pair(hash_t *h, hash_pair_t *p)
Definition: hash.c:46
static u8 * hash_format_pair_default(u8 *s, va_list *args)
Definition: hash.c:863
uword hash_bytes(void *v)
Definition: hash.c:876
#define hash_free(h)
Definition: hash.h:269
u32 flags
Definition: hash.h:59
always_inline uword hash_pair_log2_bytes(hash_t *h)
Definition: hash.h:281
Definition: hash.c:459
#define uword_to_pointer(u, type)
Definition: types.h:134
format_function_t * format_pair
Definition: hash.h:88
hash_pair_t * hash_next(void *v, hash_next_t *hn)
Definition: hash.c:569
static void * hash_resize_internal(void *old, uword new_size, uword free_old)
Definition: hash.c:711
static hash_pair_t * lookup(void *v, uword key, enum lookup_opcode op, void *new_value, void *old_value)
Definition: hash.c:464
hash_pair_indirect_t indirect
Definition: hash.h:171
#define clib_arch_is_big_endian
Definition: byte_order.h:53
#define hash_mix64(a0, b0, c0)
Definition: hash.h:466
always_inline void * clib_mem_alloc(uword size)
Definition: mem.h:109
#define CHECK(x)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
always_inline uword hash_pair_bytes(hash_t *h)
Definition: hash.h:294
#define clib_memcpy(a, b, c)
Definition: string.h:63
#define hash_mix32(a0, b0, c0)
Definition: hash.h:474
#define HASH_FLAG_HASH_NEXT_IN_PROGRESS
Definition: hash.h:66
Definition: hash.c:460
#define vec_capacity(v, b)
Total number of bytes that can fit in vector with current allocation.
always_inline uword hash_elts(void *v)
Definition: hash.h:111
always_inline uword indirect_pair_get_len(hash_pair_indirect_t *p)
Definition: hash.h:183
static uword unformat_hash_string_internal(unformat_input_t *input, va_list *va, int is_vec)
Definition: hash.c:962
void * hash_dup(void *old)
Definition: hash.c:734
always_inline hash_pair_union_t * get_pair(void *v, uword i)
Definition: hash.c:50
#define hash_create(elts, value_bytes)
Definition: hash.h:615
static hash_pair_union_t * set_indirect_is_user(void *v, uword i, hash_pair_union_t *p, uword key)
Definition: hash.c:334
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
uword string_key_sum(hash_t *h, uword key)
Definition: hash.c:834
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
uword hash_memory(void *p, word n_bytes, uword state)
Definition: hash.c:208
always_inline uword indirect_pair_get_log2_bytes(hash_pair_indirect_t *p)
Definition: hash.h:178
vhost_vring_state_t state
Definition: vhost-user.h:77
uword i
Definition: hash.h:415
uword unformat_hash_string(unformat_input_t *input, va_list *va)
Definition: hash.c:987
#define clib_max(x, y)
Definition: clib.h:288
u64 uword
Definition: types.h:112
always_inline uword key_equal(hash_t *h, uword key1, uword key2)
Definition: hash.c:301
unsigned short u16
Definition: types.h:57
hash_pair_t direct
Definition: hash.h:170
i64 word
Definition: types.h:111
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define hash_foreach_pair(p, v, body)
Definition: hash.h:311
Definition: hash.c:461
always_inline void * hash_forward1(hash_t *h, void *v)
Definition: hash.h:298
always_inline uword hash_value_bytes(hash_t *h)
Definition: hash.h:274
#define clib_mem_unaligned(pointer, type)
Definition: types.h:153
#define hash_get_mem(h, key)
Definition: hash.h:251
uword string_key_equal(hash_t *h, uword key1, uword key2)
Definition: hash.c:840
uword unformat_hash_vec_string(unformat_input_t *input, va_list *va)
Definition: hash.c:983
always_inline uword key_equal1(hash_t *h, uword key1, uword key2, uword e)
Definition: hash.c:274
struct _unformat_input_t unformat_input_t
uword mem_key_sum(hash_t *h, uword key)
Definition: hash.c:821
#define HASH_FLAG_NO_AUTO_SHRINK
Definition: hash.h:64
#define BITS(x)
Definition: clib.h:58
uword is_user[0]
Definition: hash.h:95
uword vec_key_equal(hash_t *h, uword key1, uword key2)
Definition: hash.c:763
hash_key_sum_function_t * key_sum
Definition: hash.h:73
uword key
Definition: hash.h:148
static u32 hash_memory32(void *p, word n_bytes, u32 state)
Definition: hash.c:158