/*
* Copyright (c) 2008-2016 Solarflare Communications Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the FreeBSD Project.
*/
#include <sys/int_limits.h>
#include <sys/byteorder.h>
#include "sfxge.h"
#include "efx.h"
/*
* The largest amount of the data which the hash may be calculated over
* is a 4-tuple of source/destination IPv6 addresses (2 x 16 bytes)
* and source/destination TCP port numbers (2 x 2 bytes), adding up to 40 bytes
*/
#define SFXGE_TOEPLITZ_IN_MAX \
static uint32_t
{
}
return (hash);
}
{
unsigned pos = 0;
}
return (hash);
}
/*
* The algorithm to calculate RSS Toeplitz hash is essentially as follows:
* - Regard a Toeplitz key and an input as bit strings, with the
* most significant bit of the first byte being the first bit
* - Let's have a 32-bit window sliding over the Toeplitz key bit by bit
* - Let the initial value of the hash be zero
* - Then for every bit in the input that is set to 1, XOR the value of the
* window at a given bit position into the resulting hash
*
* First we note that since XOR is commutative and associative, the
* resulting hash is just a XOR of subhashes for every input bit:
* H = H_0 XOR H_1 XOR ... XOR H_n (1)
* Then we note that every H_i is only dependent on the value of i and
* the value of i'th bit of input, but not on any preceding or following
* input bits.
* Then we note that (1) holds also for any bit sequences,
* e.g. for bytes of input:
* H = H_0_7 XOR H_8_15 XOR ... XOR H_(n-7)_n (2)
* and every
* H_i_j = H_i XOR H_(i+1) ... XOR H_j. (3)
*
* It naturally follows than H_i_(i+7) only depends on the value of the byte
* and the position of the byte in the input.
* Therefore we may pre-calculate the value of each byte sub-hash H_i_(i+7)
* for each possible byte value and each possible byte input position, and
* then just assemble the hash of the packet byte-by-byte instead of
* bit-by-bit.
*
* The amount of memory required for such a cache is not prohibitive:
* - we have at most 36 bytes of input, each holding 256 possible values
* - and the hash is 32-bit wide
* - hence, we need only 36 * 256 * 4 = 36kBytes of cache.
*
* The performance gain, at least on synthetic benchmarks, is significant:
* cache lookup is about 15 times faster than direct hash calculation
*/
const uint32_t *
{
unsigned i;
for (i = 0; i < SFXGE_TOEPLITZ_IN_MAX; i++, key++) {
unsigned j;
unsigned mask;
unsigned byte;
#if defined(BE_IN32)
#else
#endif
key_bits[j] |= 1;
}
j < NBBY;
j++, mask >>= 1) {
}
}
}
return (cache);
}
int
{
int rc;
return (rc);
sizeof (toeplitz_key))) != 0)
return (rc);
return (0);
}
void
{
}
}