Skip to content

Commit 64be3db

Browse files
Add Jenkins hash to supported hash algorithms. (#2233)
Add the option to configure the hash algorithm to the lower or upper 16 bits of a Jenkins hash algorithm (https://en.wikipedia.org/wiki/Jenkins_hash_function). This provides a stronger alternative to the CRC-based algorithms where supported. Signed-off-by: Mike Beresford <mberes@google.com>
1 parent 7693545 commit 64be3db

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# [SAI] Jenkins Hash Algorithm
2+
3+
--------------------------------------------------------------------------------
4+
5+
Title | Jenkins Hash Algorithm
6+
----------- | ---------------------------------------
7+
Authors | Mike Beresford, Abhishek Verma (Google)
8+
Status | In-Review
9+
Type | Standards track
10+
Created | 2026-02-05
11+
SAI-Version | 1.18
12+
13+
--------------------------------------------------------------------------------
14+
15+
## 1. Introduction
16+
17+
ECMP or Next hop groups (NHG) and LAG use load balancing techniques to spread
18+
the traffic across the various members. The most common load balancing technique
19+
is to use hash-based member selection. In this technique, flows are identified
20+
by performing a hash on a set of packet fields like the 5-tuple, and then
21+
selecting the group member based on the computed hash value.
22+
23+
This proposal introduces the addition of Jenkins hash algorithm to
24+
_sai_hash_algorithm_t.
25+
26+
## 2. Motivation
27+
28+
Limitation of CRC/XOR: Traditional CRC and XOR algorithms are susceptible to
29+
polarization when traffic passes through multiple next hops.
30+
31+
Jenkins hash function is a non-cryptographic hash function that offers better
32+
avalanche properties compared to CRC and XOR. This results in a more uniform
33+
distribution of flows across members, especially in multi-stage networks (e.g.,
34+
CLOS topologies) where polarization is a concern.
35+
36+
## 3. Behavior
37+
38+
The Jenkins algorithm (specifically `lookup3`) produces a 32-bit hash value for
39+
a given input (e.g., packet 5-tuple). Switching ASICs generally rely on a 16-bit
40+
hash value for load balancing. To accommodate this, the 32-bit Jenkins hash is
41+
split into two 16-bit segments.
42+
43+
Two new enums are introduced to allow selecting either the lower 16 bits
44+
(`_LO`) or the upper 16 bits (`_HI`) of the computed hash. This provides
45+
flexibility, for example allowing different hash values for ECMP and LAG even
46+
if the same flow keys are used.
47+
48+
## 4. SAI Enhancement
49+
50+
New enums added to the `sai_hash_algorithm_t`.
51+
52+
Enum defining the Jenkins hash algorithm:
53+
54+
```c
55+
/**
56+
* @brief Attribute data for #SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM
57+
* and #SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_ALGORITHM
58+
*/
59+
typedef enum _sai_hash_algorithm_t
60+
{
61+
...
62+
63+
/** Round-robin based hash algorithm (per-packet round-robin spraying) */
64+
SAI_HASH_ALGORITHM_ROUND_ROBIN = 8,
65+
66+
/** Lower 16 bits of Jenkins hash algorithm */
67+
SAI_HASH_ALGORITHM_JENKINS_LO = 9,
68+
69+
/** Upper 16 bits of Jenkins hash algorithm */
70+
SAI_HASH_ALGORITHM_JENKINS_HI = 10,
71+
72+
} sai_hash_algorithm_t;
73+
74+
```
75+
76+
## 5. API Example(s)
77+
78+
### Query supported hashing algorithms
79+
80+
```c
81+
sai_s32_list_t enum_values_capability;
82+
enum_values_capability.count = 0;
83+
enum_values_capability.list = nullptr;
84+
85+
// Fetch the number of supported hash algorithms, then allocate a buffer and
86+
// fetch the actual list.
87+
sai_status_t status = sai->queryAttributeEnumValuesCapability(
88+
switchid,
89+
SAI_OBJECT_TYPE_SWITCH,
90+
SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM,
91+
&enum_values_capability);
92+
93+
std::vector<int32_t> list;
94+
list.resize(enum_values_capability.count);
95+
enum_values_capability.list = list.data();
96+
sai_status_t status = sai->queryAttributeEnumValuesCapability(
97+
switchid,
98+
SAI_OBJECT_TYPE_SWITCH,
99+
SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM,
100+
&enum_values_capability);
101+
102+
ASSERT_EQ(status, SAI_STATUS_SUCCESS);
103+
104+
bool jenkins_hash_lo_supported = false;
105+
for (uint32_t i = 0; i < enum_values_capability.count; ++i)
106+
{
107+
if (enum_values_capability.list[i] == SAI_HASH_ALGORITHM_JENKINS_LO)
108+
{
109+
jenkins_hash_lo_supported = true;
110+
}
111+
}
112+
```
113+
114+
### Set Jenkins algorithm as the default hash algorithm
115+
116+
```c
117+
sai_attribute_t attr;
118+
attr.id = SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM;
119+
attr.value.s32 = SAI_HASH_ALGORITHM_JENKINS_LO;
120+
status = sai->set(SAI_OBJECT_TYPE_SWITCH, switchid, &attr);
121+
ASSERT_EQ(status, SAI_STATUS_SUCCESS);
122+
```
123+
124+
## 6. References
125+
126+
https://burtleburtle.net/bob/c/lookup3.c
127+

inc/saiswitch.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ typedef enum _sai_hash_algorithm_t
214214
/** Round-robin based hash algorithm (per-packet round-robin spraying) */
215215
SAI_HASH_ALGORITHM_ROUND_ROBIN = 8,
216216

217+
/** Lower 16 bits of Jenkins hash algorithm */
218+
SAI_HASH_ALGORITHM_JENKINS_LO = 9,
219+
220+
/** Upper 16 bits of Jenkins hash algorithm */
221+
SAI_HASH_ALGORITHM_JENKINS_HI = 10,
222+
217223
} sai_hash_algorithm_t;
218224

219225
/**

0 commit comments

Comments
 (0)