dpdk 0.0.1

A wrapper around DPDK
// This file is part of dpdk. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/dpdk/master/COPYRIGHT. No part of dpdk, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
// Copyright © 2016-2017 The developers of dpdk. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/dpdk/master/COPYRIGHT.


// NOTE: The hash function is Toeplitz's

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ReceiveSideScalingHashFunctionKeyData
{
	EthernetDeviceDefault,
	Forty(Array40<u8>),
	FiftyTwo(Array52<u8>),
	
	// NOTE: DPDK and TLDK example programs define RSS_HASH_KEY_LENGTH as 64 for key data arrays
	// ie, implying that the upper power-of-two aligned maximum hash key data size they expect any ethernet port to have is 64 bytes
}

impl ReceiveSideScalingHashFunctionKeyData
{
	// NOTE: The default often isn't a good key
	pub const EthernetDeviceDefaultKeyData: ReceiveSideScalingHashFunctionKeyData = ReceiveSideScalingHashFunctionKeyData::EthernetDeviceDefault;
	
	// This key should not be used as it has a lot of hash collisions
	// Key should be used with the Toeplitz hash function
	// Original Microsoft key, source was http://www.ran-lifshitz.com/2014/08/28/symmetric-rss-receive-side-scaling/
	pub const MicrosoftKeyData: ReceiveSideScalingHashFunctionKeyData = ReceiveSideScalingHashFunctionKeyData::Forty
	(
		Array40
		([
			0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
			0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
			0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
			0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
			0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
		])
	);
	
	// This key should result in good scaling across multiple cores
	// Key should be used with the Toeplitz hash function
	// https://galsagie.github.io/2015/02/26/dpdk-tips-1/
	// http://www.ran-lifshitz.com/2014/08/28/symmetric-rss-receive-side-scaling/
	pub const SymmetricFortyKeyData: ReceiveSideScalingHashFunctionKeyData = ReceiveSideScalingHashFunctionKeyData::Forty
	(
		Array40
		([
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
		])
	);
	
	// This is a GUESS based on the above
	pub const SymmetricFiftyTwoKeyData: ReceiveSideScalingHashFunctionKeyData = ReceiveSideScalingHashFunctionKeyData::FiftyTwo
	(
		Array52
		([
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
			0x6D, 0x5A, 0x6D, 0x5A,
		])
	);

	pub const DefaultMellanoxKeyData: ReceiveSideScalingHashFunctionKeyData = ReceiveSideScalingHashFunctionKeyData::Forty
	(
		Array40
		([
			0xD1, 0x81, 0xC6, 0x2C, 0xF7, 0xF4, 0xDB, 0x5B,
			0x19, 0x83, 0xA2, 0xFC, 0x94, 0x3E, 0x1A, 0xDB,
			0xD9, 0x38, 0x9E, 0x6B, 0xD1, 0x03, 0x9C, 0x2C,
			0xA7, 0x44, 0x99, 0xAD, 0x59, 0x3D, 0x56, 0xD9,
			0xF3, 0x25, 0x3C, 0x06, 0x2A, 0xDC, 0x1F, 0xFC,
		])
	);

	pub const DefaultIntelI40eKeyData: ReceiveSideScalingHashFunctionKeyData = ReceiveSideScalingHashFunctionKeyData::FiftyTwo
	(
		Array52
		([
			0x44, 0x39, 0x79, 0x6B, 0xB5, 0x4C, 0x50, 0x23,
			0xB6, 0x75, 0xEA, 0x5B, 0x12, 0x4F, 0x9F, 0x30,
			0xB8, 0xA2, 0xC0, 0x3D, 0xDF, 0xDC, 0x4D, 0x02,
			0xA0, 0x8C, 0x9B, 0x33, 0x4A, 0xF6, 0x4A, 0x4C,
			0x05, 0xC6, 0xFA, 0x34, 0x39, 0x58, 0xD8, 0x55,
			0x7D, 0x99, 0x58, 0x3A, 0xE1, 0x38, 0xC9, 0x2E,
			0x81, 0x15, 0x03, 0x66,
		])
	);
	
	#[inline(always)]
	pub fn length(&self) -> u8
	{
		match *self
		{
			ReceiveSideScalingHashFunctionKeyData::EthernetDeviceDefaultKeyData => 0,
			ReceiveSideScalingHashFunctionKeyData::Forty(_) => 40,
			ReceiveSideScalingHashFunctionKeyData::FiftyTwo(_) => 52,
		}
	}
	
	#[inline(always)]
	pub fn as_ref(&self) -> Option<&[u8]>
	{
		match *self
		{
			ReceiveSideScalingHashFunctionKeyData::EthernetDeviceDefaultKeyData => None,
			ReceiveSideScalingHashFunctionKeyData::Forty(ref data) => Some(&data.0),
			ReceiveSideScalingHashFunctionKeyData::FiftyTwo(ref data) => Some(&data.0),
		}
	}
	
	#[inline(always)]
	pub const fn receiveSideScalingHashFunctionConfiguration(self, hashFunctionFlowApplicability: ReceiveSideScalingOffloadFlowTypeSet) -> ReceiveSideScalingHashFunctionConfiguration
	{
		ReceiveSideScalingHashFunctionConfiguration
		{
			key: self,
			hashFunctionFlowApplicability: hashFunctionFlowApplicability
		}
	}
	
	pub fn tldkRssKeyData(numberOfReceiveQueues: u16, receiveSideScalingHashKeySize: ReceiveSideScalingHashKeySize) -> ReceiveSideScalingHashFunctionKeyData
	{
		let n = numberOfReceiveQueues.next_power_of_two() as u8;
		
		match receiveSideScalingHashKeySize
		{
			ReceiveSideScalingHashKeySize::Forty => ReceiveSideScalingHashFunctionKeyData::Forty
			(
				Array40
				([
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, n,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, n,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				])
			),
			ReceiveSideScalingHashKeySize::FiftyTwo => ReceiveSideScalingHashFunctionKeyData::FiftyTwo
			(
				Array52
				([
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, n,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, n,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00,
				])
			)
		}
	}
}