1/* $OpenBSD: toeplitz.h,v 1.11 2023/05/17 10:22:17 dlg Exp $ */
2
3/*
4 * Copyright (c) 2019 David Gwynne <dlg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#ifndef _SYS_NET_TOEPLITZ_H_
20#define _SYS_NET_TOEPLITZ_H_
21
22#include <sys/endian.h>
23
24/*
25 * symmetric toeplitz
26 */
27
28typedef uint16_t stoeplitz_key;
29
30struct stoeplitz_cache {
31 uint16_t bytes[256];
32};
33
34static __unused inline uint16_t
35stoeplitz_cache_entry(const struct stoeplitz_cache *scache, uint8_t byte)
36{
37 return (scache->bytes[byte]);
38}
39
40void stoeplitz_cache_init(struct stoeplitz_cache *, stoeplitz_key);
41
42uint16_t stoeplitz_hash_ip4(const struct stoeplitz_cache *,
43 uint32_t, uint32_t);
44uint16_t stoeplitz_hash_ip4port(const struct stoeplitz_cache *,
45 uint32_t, uint32_t, uint16_t, uint16_t);
46
47#ifdef INET6
48struct in6_addr;
49uint16_t stoeplitz_hash_ip6(const struct stoeplitz_cache *,
50 const struct in6_addr *, const struct in6_addr *);
51uint16_t stoeplitz_hash_ip6port(const struct stoeplitz_cache *,
52 const struct in6_addr *, const struct in6_addr *,
53 uint16_t, uint16_t);
54#endif
55
56uint16_t stoeplitz_hash_eaddr(const struct stoeplitz_cache *,
57 const uint8_t *);
58
59/* hash a uint16_t in network byte order */
60static __unused inline uint16_t
61stoeplitz_hash_n16(const struct stoeplitz_cache *scache, uint16_t n16)
62{
63 uint16_t hi, lo;
64
65 hi = stoeplitz_cache_entry(scache, n16 >> 8);
66 lo = stoeplitz_cache_entry(scache, n16);
67
68 return (hi ^ swap16(lo));
69}
70
71/* hash a uint32_t in network byte order */
72static __unused inline uint16_t
73stoeplitz_hash_n32(const struct stoeplitz_cache *scache, uint32_t n32)
74{
75 return (stoeplitz_hash_n16(scache, n32 ^ (n32 >> 16)));
76}
77
78/* hash a uint16_t in host byte order */
79static __unused inline uint16_t
80stoeplitz_hash_h16(const struct stoeplitz_cache *scache, uint16_t h16)
81{
82 uint16_t lo, hi;
83
84 lo = stoeplitz_cache_entry(scache, h16);
85 hi = stoeplitz_cache_entry(scache, h16 >> 8);
86
87#if _BYTE_ORDER == _BIG_ENDIAN
88 return (hi ^ swap16(lo));
89#else
90 return (swap16(hi) ^ lo);
91#endif
92}
93
94static __unused inline uint16_t
95stoeplitz_hash_h32(const struct stoeplitz_cache *scache, uint32_t h32)
96{
97 return (stoeplitz_hash_h16(scache, h32 ^ (h32 >> 16)));
98}
99
100static __unused inline uint16_t
101stoeplitz_hash_h64(const struct stoeplitz_cache *scache, uint64_t h64)
102{
103 return (stoeplitz_hash_h32(scache, h64 ^ (h64 >> 32)));
104}
105
106/*
107 * system provided symmetric toeplitz
108 */
109
110#define STOEPLITZ_KEYSEED 0x6d5a
111
112void stoeplitz_init(void);
113
114void stoeplitz_to_key(void *, size_t)
115 __bounded((__buffer__, 1, 2));
116
117extern const struct stoeplitz_cache *const stoeplitz_cache;
118
119#define stoeplitz_n16(_n16) \
120 stoeplitz_hash_n16(stoeplitz_cache, (_n16))
121#define stoeplitz_n32(_n32) \
122 stoeplitz_hash_n32(stoeplitz_cache, (_n32))
123#define stoeplitz_h16(_h16) \
124 stoeplitz_hash_h16(stoeplitz_cache, (_h16))
125#define stoeplitz_h32(_h32) \
126 stoeplitz_hash_h32(stoeplitz_cache, (_h32))
127#define stoeplitz_h64(_h64) \
128 stoeplitz_hash_h64(stoeplitz_cache, (_h64))
129#define stoeplitz_port(_p) stoeplitz_n16((_p))
130#define stoeplitz_ip4(_sa4, _da4) \
131 stoeplitz_hash_ip4(stoeplitz_cache, (_sa4), (_da4))
132#define stoeplitz_ip4port(_sa4, _da4, _sp, _dp) \
133 stoeplitz_hash_ip4port(stoeplitz_cache, (_sa4), (_da4), (_sp), (_dp))
134#ifdef INET6
135#define stoeplitz_ip6(_sa6, _da6) \
136 stoeplitz_hash_ip6(stoeplitz_cache, (_sa6), (_da6))
137#define stoeplitz_ip6port(_sa6, _da6, _sp, _dp) \
138 stoeplitz_hash_ip6port(stoeplitz_cache, (_sa6), (_da6), (_sp), (_dp))
139#endif
140#define stoeplitz_eaddr(_ea) \
141 stoeplitz_hash_eaddr(stoeplitz_cache, (_ea))
142
143#endif /* _SYS_NET_TOEPLITZ_H_ */