xref: /dflybsd-src/sys/net/toeplitz.c (revision f8c589f353e45a43e2df3f5435bc3aeeb83f99bc)
1cc85a685SSepherosa Ziehau /*
2cc85a685SSepherosa Ziehau  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3cc85a685SSepherosa Ziehau  *
4cc85a685SSepherosa Ziehau  * This code is derived from software contributed to The DragonFly Project
5cc85a685SSepherosa Ziehau  * by Sepherosa Ziehau <sepherosa@gmail.com>
6cc85a685SSepherosa Ziehau  *
7cc85a685SSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
8cc85a685SSepherosa Ziehau  * modification, are permitted provided that the following conditions
9cc85a685SSepherosa Ziehau  * are met:
10cc85a685SSepherosa Ziehau  *
11cc85a685SSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
12cc85a685SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
13cc85a685SSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
14cc85a685SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in
15cc85a685SSepherosa Ziehau  *    the documentation and/or other materials provided with the
16cc85a685SSepherosa Ziehau  *    distribution.
17cc85a685SSepherosa Ziehau  * 3. Neither the name of The DragonFly Project nor the names of its
18cc85a685SSepherosa Ziehau  *    contributors may be used to endorse or promote products derived
19cc85a685SSepherosa Ziehau  *    from this software without specific, prior written permission.
20cc85a685SSepherosa Ziehau  *
21cc85a685SSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22cc85a685SSepherosa Ziehau  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23cc85a685SSepherosa Ziehau  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24cc85a685SSepherosa Ziehau  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25cc85a685SSepherosa Ziehau  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26cc85a685SSepherosa Ziehau  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27cc85a685SSepherosa Ziehau  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28cc85a685SSepherosa Ziehau  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29cc85a685SSepherosa Ziehau  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30cc85a685SSepherosa Ziehau  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31cc85a685SSepherosa Ziehau  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32cc85a685SSepherosa Ziehau  * SUCH DAMAGE.
33cc85a685SSepherosa Ziehau  */
34cc85a685SSepherosa Ziehau 
35cc85a685SSepherosa Ziehau /*
36cc85a685SSepherosa Ziehau  * Toeplitz hash function
37cc85a685SSepherosa Ziehau  *
38cc85a685SSepherosa Ziehau  * This function is used to support Receive Side Scaling:
39cc85a685SSepherosa Ziehau  * http://www.microsoft.com/whdc/device/network/ndis_rss.mspx
40cc85a685SSepherosa Ziehau  *
41cc85a685SSepherosa Ziehau  * Two things are changed from the above paper:
42cc85a685SSepherosa Ziehau  * o  Instead of creating random 40 bytes key string, we replicate
43cc85a685SSepherosa Ziehau  *    2 user defined bytes to form the 40 bytes key string.  So the
44cc85a685SSepherosa Ziehau  *    hash result of TCP segment is commutative.  '2' is chosen,
45cc85a685SSepherosa Ziehau  *    since the hash is calculated upon the binary string formed by
46cc85a685SSepherosa Ziehau  *    concatenating faddr,laddr,fport,lport; the smallest unit is
47cc85a685SSepherosa Ziehau  *    the size of the fport/lport, which is 2 bytes.
48cc85a685SSepherosa Ziehau  * o  Precalculated hash result cache is used to reduce the heavy
49cc85a685SSepherosa Ziehau  *    computation burden
50cc85a685SSepherosa Ziehau  *
51cc85a685SSepherosa Ziehau  * Thank Simon 'corecode' Schubert <corecode@fs.ei.tum.de> very much
52cc85a685SSepherosa Ziehau  * for various constructive suggestions.  Without him, this will not
53cc85a685SSepherosa Ziehau  * be possible.
54cc85a685SSepherosa Ziehau  */
55cc85a685SSepherosa Ziehau 
564d334cdbSSepherosa Ziehau #include "opt_rss.h"
574d334cdbSSepherosa Ziehau 
58cc85a685SSepherosa Ziehau #include <sys/param.h>
59cc85a685SSepherosa Ziehau #include <sys/kernel.h>
60cc85a685SSepherosa Ziehau #include <sys/systm.h>
61cc85a685SSepherosa Ziehau #include <sys/sysctl.h>
62cc85a685SSepherosa Ziehau 
63cc85a685SSepherosa Ziehau #include <net/toeplitz.h>
64cc85a685SSepherosa Ziehau #include <net/toeplitz2.h>
65cc85a685SSepherosa Ziehau 
66cc85a685SSepherosa Ziehau #define TOEPLITZ_KEYSEED0	0x6d
67cc85a685SSepherosa Ziehau #define TOEPLITZ_KEYSEED1	0x5a
68d9304583SSepherosa Ziehau #define TOEPLITZ_INIT_KEYLEN	(TOEPLITZ_KEYSEED_CNT + sizeof(uint32_t))
69cc85a685SSepherosa Ziehau 
70cc85a685SSepherosa Ziehau static uint32_t	toeplitz_keyseeds[TOEPLITZ_KEYSEED_CNT] =
71cc85a685SSepherosa Ziehau 	{ TOEPLITZ_KEYSEED0, TOEPLITZ_KEYSEED1 };
72cc85a685SSepherosa Ziehau 
73cc85a685SSepherosa Ziehau uint32_t	toeplitz_cache[TOEPLITZ_KEYSEED_CNT][256];
74cc85a685SSepherosa Ziehau 
75cc85a685SSepherosa Ziehau TUNABLE_INT("net.toeplitz.keyseed0", &toeplitz_keyseeds[0]);
76cc85a685SSepherosa Ziehau TUNABLE_INT("net.toeplitz.keyseed1", &toeplitz_keyseeds[1]);
77cc85a685SSepherosa Ziehau 
78cc85a685SSepherosa Ziehau SYSCTL_NODE(_net, OID_AUTO, toeplitz, CTLFLAG_RW, 0, "Toeplitz hash");
79cc85a685SSepherosa Ziehau SYSCTL_INT(_net_toeplitz, OID_AUTO, keyseed0, CTLFLAG_RD,
80cc85a685SSepherosa Ziehau 	   &toeplitz_keyseeds[0], 0, "Toeplitz hash key seed0");
81cc85a685SSepherosa Ziehau SYSCTL_INT(_net_toeplitz, OID_AUTO, keyseed1, CTLFLAG_RD,
82cc85a685SSepherosa Ziehau 	   &toeplitz_keyseeds[1], 0, "Toeplitz hash key seed1");
83cc85a685SSepherosa Ziehau 
84cc85a685SSepherosa Ziehau static void
toeplitz_cache_create(uint32_t cache[][256],int cache_len,const uint8_t key_str[],int key_strlen)85cc85a685SSepherosa Ziehau toeplitz_cache_create(uint32_t cache[][256], int cache_len,
86cc85a685SSepherosa Ziehau 		      const uint8_t key_str[], int key_strlen)
87cc85a685SSepherosa Ziehau {
88cc85a685SSepherosa Ziehau 	int i;
89cc85a685SSepherosa Ziehau 
90cc85a685SSepherosa Ziehau 	for (i = 0; i < cache_len; ++i) {
91cc85a685SSepherosa Ziehau 		uint32_t key[NBBY];
92cc85a685SSepherosa Ziehau 		int j, b, shift, val;
93cc85a685SSepherosa Ziehau 
94cc85a685SSepherosa Ziehau 		bzero(key, sizeof(key));
95cc85a685SSepherosa Ziehau 
96cc85a685SSepherosa Ziehau 		/*
97cc85a685SSepherosa Ziehau 		 * Calculate 32bit keys for one byte; one key for each bit.
98cc85a685SSepherosa Ziehau 		 */
99cc85a685SSepherosa Ziehau 		for (b = 0; b < NBBY; ++b) {
100cc85a685SSepherosa Ziehau 			for (j = 0; j < 32; ++j) {
101cc85a685SSepherosa Ziehau 				uint8_t k;
102cc85a685SSepherosa Ziehau 				int bit;
103cc85a685SSepherosa Ziehau 
104cc85a685SSepherosa Ziehau 				bit = (i * NBBY) + b + j;
105cc85a685SSepherosa Ziehau 
106cc85a685SSepherosa Ziehau 				k = key_str[bit / NBBY];
107cc85a685SSepherosa Ziehau 				shift = NBBY - (bit % NBBY) - 1;
108cc85a685SSepherosa Ziehau 				if (k & (1 << shift))
109cc85a685SSepherosa Ziehau 					key[b] |= 1 << (31 - j);
110cc85a685SSepherosa Ziehau 			}
111cc85a685SSepherosa Ziehau 		}
112cc85a685SSepherosa Ziehau 
113cc85a685SSepherosa Ziehau 		/*
114cc85a685SSepherosa Ziehau 		 * Cache the results of all possible bit combination of
115cc85a685SSepherosa Ziehau 		 * one byte.
116cc85a685SSepherosa Ziehau 		 */
117cc85a685SSepherosa Ziehau 		for (val = 0; val < 256; ++val) {
118cc85a685SSepherosa Ziehau 			uint32_t res = 0;
119cc85a685SSepherosa Ziehau 
120cc85a685SSepherosa Ziehau 			for (b = 0; b < NBBY; ++b) {
121cc85a685SSepherosa Ziehau 				shift = NBBY - b - 1;
122cc85a685SSepherosa Ziehau 				if (val & (1 << shift))
123cc85a685SSepherosa Ziehau 					res ^= key[b];
124cc85a685SSepherosa Ziehau 			}
125cc85a685SSepherosa Ziehau 			cache[i][val] = res;
126cc85a685SSepherosa Ziehau 		}
127cc85a685SSepherosa Ziehau 	}
128cc85a685SSepherosa Ziehau }
129cc85a685SSepherosa Ziehau 
1304d334cdbSSepherosa Ziehau #ifdef RSS_DEBUG
1314d334cdbSSepherosa Ziehau 
1324d334cdbSSepherosa Ziehau static void
toeplitz_verify(void)1334d334cdbSSepherosa Ziehau toeplitz_verify(void)
1344d334cdbSSepherosa Ziehau {
1354d334cdbSSepherosa Ziehau 	in_addr_t faddr, laddr;
1364d334cdbSSepherosa Ziehau 	in_port_t fport, lport;
1374d334cdbSSepherosa Ziehau 
1384d334cdbSSepherosa Ziehau 	/*
1394d334cdbSSepherosa Ziehau 	 * The first IPv4 example in the verification suite
1404d334cdbSSepherosa Ziehau 	 */
1414d334cdbSSepherosa Ziehau 
1424d334cdbSSepherosa Ziehau 	/* 66.9.149.187:2794 */
1434d334cdbSSepherosa Ziehau 	faddr = 0xbb950942;
1444d334cdbSSepherosa Ziehau 	fport = 0xea0a;
1454d334cdbSSepherosa Ziehau 
1464d334cdbSSepherosa Ziehau 	/* 161.142.100.80:1766 */
1474d334cdbSSepherosa Ziehau 	laddr = 0x50648ea1;
1484d334cdbSSepherosa Ziehau 	lport = 0xe606;
1494d334cdbSSepherosa Ziehau 
1504d334cdbSSepherosa Ziehau 	kprintf("toeplitz: verify addr/port 0x%08x, addr 0x%08x\n",
151b73d4152SSepherosa Ziehau 		toeplitz_rawhash_addrport(faddr, laddr, fport, lport),
152b73d4152SSepherosa Ziehau 		toeplitz_rawhash_addr(faddr, laddr));
1534d334cdbSSepherosa Ziehau }
1544d334cdbSSepherosa Ziehau 
1554d334cdbSSepherosa Ziehau #endif	/* RSS_DEBUG */
1564d334cdbSSepherosa Ziehau 
157cc85a685SSepherosa Ziehau static void
toeplitz_init(void * dummy __unused)158cc85a685SSepherosa Ziehau toeplitz_init(void *dummy __unused)
159cc85a685SSepherosa Ziehau {
160d9304583SSepherosa Ziehau 	uint8_t key[TOEPLITZ_INIT_KEYLEN];
161cc85a685SSepherosa Ziehau 	int i;
162cc85a685SSepherosa Ziehau 
163cc85a685SSepherosa Ziehau 	for (i = 0; i < TOEPLITZ_KEYSEED_CNT; ++i)
164cc85a685SSepherosa Ziehau 		toeplitz_keyseeds[i] &= 0xff;
165cc85a685SSepherosa Ziehau 
166d9304583SSepherosa Ziehau 	toeplitz_get_key(key, TOEPLITZ_INIT_KEYLEN);
167cc85a685SSepherosa Ziehau 
1684d334cdbSSepherosa Ziehau #ifdef RSS_DEBUG
1694d334cdbSSepherosa Ziehau 	kprintf("toeplitz: keystr ");
170d9304583SSepherosa Ziehau 	for (i = 0; i < TOEPLITZ_INIT_KEYLEN; ++i)
171d9304583SSepherosa Ziehau 		kprintf("%02x ", key[i]);
1724d334cdbSSepherosa Ziehau 	kprintf("\n");
1734d334cdbSSepherosa Ziehau #endif
1744d334cdbSSepherosa Ziehau 
175cc85a685SSepherosa Ziehau 	toeplitz_cache_create(toeplitz_cache, TOEPLITZ_KEYSEED_CNT,
176d9304583SSepherosa Ziehau 			      key, TOEPLITZ_INIT_KEYLEN);
1774d334cdbSSepherosa Ziehau 
1784d334cdbSSepherosa Ziehau #ifdef RSS_DEBUG
1794d334cdbSSepherosa Ziehau 	toeplitz_verify();
1804d334cdbSSepherosa Ziehau #endif
181cc85a685SSepherosa Ziehau }
182*f8c589f3SSepherosa Ziehau /* After netisr_init */
1833c5b1eb8SSepherosa Ziehau SYSINIT(toeplitz, SI_SUB_PRE_DRIVERS, SI_ORDER_SECOND, toeplitz_init, NULL);
184b263df52SSepherosa Ziehau 
185b263df52SSepherosa Ziehau void
toeplitz_get_key(uint8_t * key,int keylen)186b263df52SSepherosa Ziehau toeplitz_get_key(uint8_t *key, int keylen)
187b263df52SSepherosa Ziehau {
188b263df52SSepherosa Ziehau 	int i;
189b263df52SSepherosa Ziehau 
190b263df52SSepherosa Ziehau 	if (keylen > TOEPLITZ_KEYLEN_MAX)
191ed20d0e3SSascha Wildner 		panic("invalid key length %d", keylen);
192b263df52SSepherosa Ziehau 
193b263df52SSepherosa Ziehau 	/* Replicate key seeds to form key */
194b263df52SSepherosa Ziehau 	for (i = 0; i < keylen; ++i)
195b263df52SSepherosa Ziehau 		key[i] = toeplitz_keyseeds[i % TOEPLITZ_KEYSEED_CNT];
196b263df52SSepherosa Ziehau }
197