LCOV - code coverage report
Current view: top level - root/contrail/vrouter/include - vr_hash.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 37 37 100.0 %
Date: 2026-11-09 02:10:49 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_hash.h
       3             :  *
       4             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       5             :  * Copyright Contributors to the OpenSDN project
       6             :  */
       7             : 
       8             : #ifndef _VR_HASH_H
       9             : #define _VR_HASH_H
      10             : 
      11             : #include "vr_os.h"
      12             : 
      13             : /* vr_hash.h: Jenkins hash support.
      14             :  *
      15             :  * License: Public Domain
      16             :  * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
      17             :  *
      18             :  * http://burtleburtle.net/bob/hash/
      19             :  *
      20             :  * These are the credits from Bob's sources:
      21             :  *
      22             :  * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
      23             :  *
      24             :  * These are functions for producing 32-bit hashes for hash table lookup.
      25             :  * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
      26             :  * are externally useful functions.  Routines to test the hash are included
      27             :  * if SELF_TEST is defined.  You can use this free for any purpose.  It's in
      28             :  * the public domain.  It has no warranty.
      29             :  *
      30             :  * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
      31             :  *
      32             :  * I've modified Bob's hash to be useful in the Linux kernel, and
      33             :  * any bugs present are my fault.
      34             :  * Jozsef
      35             :  */
      36             : 
      37             : /* Best hash sizes are of power of two */
      38             : #define vr_hash_size(n)   ((uint32_t)1<<(n))
      39             : /* Mask the hash value, i.e (value & vr_hash_mask(n)) instead of (value % n) */
      40             : #define vr_hash_mask(n)   (vr_hash_size(n)-1)
      41             : 
      42             : #define rolword(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
      43             : 
      44             : /* __vr_hash_mix -- mix 3 32-bit values reversibly. */
      45             : #define __vr_hash_mix(a, b, c)              \
      46             : {                                           \
      47             :     a -= c;  a ^= rolword(c, 4);  c += b;   \
      48             :     b -= a;  b ^= rolword(a, 6);  a += c;   \
      49             :     c -= b;  c ^= rolword(b, 8);  b += a;   \
      50             :     a -= c;  a ^= rolword(c, 16); c += b;   \
      51             :     b -= a;  b ^= rolword(a, 19); a += c;   \
      52             :     c -= b;  c ^= rolword(b, 4);  b += a;   \
      53             : }
      54             : 
      55             : /* __vr_hash_final - final mixing of 3 32-bit values (a,b,c) into c */
      56             : #define __vr_hash_final(a, b, c)            \
      57             : {                                           \
      58             :     c ^= b; c -= rolword(b, 14);            \
      59             :     a ^= c; a -= rolword(c, 11);            \
      60             :     b ^= a; b -= rolword(a, 25);            \
      61             :     c ^= b; c -= rolword(b, 16);            \
      62             :     a ^= c; a -= rolword(c, 4);             \
      63             :     b ^= a; b -= rolword(a, 14);            \
      64             :     c ^= b; c -= rolword(b, 24);            \
      65             : }
      66             : 
      67             : /* An arbitrary initial parameter */
      68             : #define VR_HASH_INITVAL     0xdeadbeef
      69             : 
      70             : __attribute__packed__open__
      71             : struct __unaligned_u32 {
      72             :     uint32_t x;
      73             : } __attribute__packed__close__;
      74             : 
      75        2487 : static inline uint32_t __get_unaligned_word(const void *p)
      76             : {
      77             :     union {
      78             :         uint8_t bytes[sizeof(uint32_t)];
      79             :         struct __unaligned_u32 u32;
      80             :     } word;
      81             : 
      82             :     size_t i;
      83       12435 :     for (i = 0; i < sizeof(struct __unaligned_u32); i++) {
      84        9948 :         word.bytes[i] = ((uint8_t *) p)[i];
      85             :     }
      86        2487 :     return word.u32.x;
      87             : }
      88             : 
      89             : 
      90             : /* vr_hash - hash an arbitrary key
      91             :  * @k: sequence of bytes as key
      92             :  * @length: the length of the key
      93             :  * @initval: the previous hash, or an arbitray value
      94             :  *
      95             :  * The generic version, hashes an arbitrary sequence of bytes.
      96             :  * No alignment or length assumptions are made about the input key.
      97             :  *
      98             :  * Returns the hash value of the key. The result depends on endianness.
      99             :  */
     100         984 : static inline uint32_t vr_hash(const void *key, uint32_t length, uint32_t initval)
     101             : {
     102             :     uint32_t a, b, c;
     103         984 :     const uint8_t *k = key;
     104             : 
     105             :     /* Set up the internal state */
     106         984 :     a = b = c = VR_HASH_INITVAL + length + initval;
     107             : 
     108             :     /* All but the last block: affect some 32 bits of (a,b,c) */
     109        1813 :     while (length > 12) {
     110         829 :         a += __get_unaligned_word(k);
     111         829 :         b += __get_unaligned_word(k + 4);
     112         829 :         c += __get_unaligned_word(k + 8);
     113         829 :         __vr_hash_mix(a, b, c);
     114         829 :         length -= 12;
     115         829 :         k += 12;
     116             :     }
     117             :     /* Last block: affect all 32 bits of (c) */
     118         984 :     if (length == 12) c += (uint32_t)k[11]<<24;
     119         984 :     if (length >= 11) c += (uint32_t)k[10]<<16;
     120         984 :     if (length >= 10) c += (uint32_t)k[9]<<8;
     121         984 :     if (length >= 9) c += k[8];
     122         984 :     if (length >= 8) b += (uint32_t)k[7]<<24;
     123         984 :     if (length >= 7) b += (uint32_t)k[6]<<16;
     124         984 :     if (length >= 6) b += (uint32_t)k[5]<<8;
     125         984 :     if (length >= 5) b += k[4];
     126         984 :     if (length >= 4) a += (uint32_t)k[3]<<24;
     127         984 :     if (length >= 3) a += (uint32_t)k[2]<<16;
     128         984 :     if (length >= 2) a += (uint32_t)k[1]<<8;
     129         984 :     if (length >= 1) {
     130         984 :         a += k[0];
     131         984 :         __vr_hash_final(a, b, c);
     132             :     }
     133             : 
     134         984 :     return c;
     135             : }
     136             : 
     137             : /* vr_hash2 - hash an array of u32's
     138             :  * @k: the key which must be an array of u32's
     139             :  * @length: the number of u32's in the key
     140             :  * @initval: the previous hash, or an arbitray value
     141             :  *
     142             :  * Returns the hash value of the key.
     143             :  */
     144             : static inline uint32_t vr_hash2(const uint32_t *k, uint32_t length, uint32_t initval)
     145             : {
     146             :     uint32_t a, b, c;
     147             : 
     148             :     /* Set up the internal state */
     149             :     a = b = c = VR_HASH_INITVAL + (length<<2) + initval;
     150             : 
     151             :     /* Handle most of the key */
     152             :     while (length > 3) {
     153             :         a += k[0];
     154             :         b += k[1];
     155             :         c += k[2];
     156             :         __vr_hash_mix(a, b, c);
     157             :         length -= 3;
     158             :         k += 3;
     159             :     }
     160             : 
     161             :     /* Handle the last 3 u32's: all the case statements fall through */
     162             :     switch (length) {
     163             :     case 3: c += k[2];
     164             :     case 2: b += k[1];
     165             :     case 1: a += k[0];
     166             :         __vr_hash_final(a, b, c);
     167             :     case 0:    /* Nothing left to add */
     168             :         break;
     169             :     }
     170             : 
     171             :     return c;
     172             : }
     173             : 
     174             : 
     175             : /* vr_hash_3words - hash exactly 3, 2 or 1 word(s) */
     176           2 : static inline uint32_t vr_hash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
     177             : {
     178           2 :     a += VR_HASH_INITVAL;
     179           2 :     b += VR_HASH_INITVAL;
     180           2 :     c += initval;
     181             : 
     182           2 :     __vr_hash_final(a, b, c);
     183             : 
     184           2 :     return c;
     185             : }
     186             : 
     187           2 : static inline uint32_t vr_hash_2words(uint32_t a, uint32_t b, uint32_t initval)
     188             : {
     189           2 :     return vr_hash_3words(a, b, 0, initval);
     190             : }
     191             : 
     192             : static inline uint32_t vr_hash_1word(uint32_t a, uint32_t initval)
     193             : {
     194             :     return vr_hash_3words(a, 0, 0, initval);
     195             : }
     196             : 
     197             : #endif /* _VR_HASH_H */

Generated by: LCOV version 1.14