From c49ce6d11b59461b5b424e01443847f8e0803741 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Tue, 24 Jun 2014 18:28:08 -0700 Subject: [PATCH] datapath: Rehash 16-bit skbuff hashes into 32 bits. Currently, if the network stack provides skb->rxhash then we use it, otherwise we compute our own. However, on at least some versions of RHEL/CentOS, the stack provides a hash that is 16 bits rather than 32 bits. In cases where we use the uppermost bits of the hash this is particularly bad because we detect that a hash is present and we use it rather than computing our own but the result is always zero. This is particularly noticible with tunnel ports that use the hash to generate a source port, such as VXLAN. On these kernels the tunnel source port is always the minimum value. To solve this problem while still taking advantage of the precomputed hash, this rehashes the hash so that the entropy is spread throughout 32 bits. Signed-off-by: Jesse Gross Acked-by: Thomas Graf --- acinclude.m4 | 2 ++ datapath/linux/compat/include/linux/skbuff.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/acinclude.m4 b/acinclude.m4 index 5ed02d21a..cd0434690 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -273,6 +273,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [[[^@]]proto_data_valid], [OVS_DEFINE([HAVE_PROTO_DATA_VALID])]) OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [rxhash]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [u16.*rxhash], + [OVS_DEFINE([HAVE_U16_RXHASH])]) OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_dst(], [OVS_DEFINE([HAVE_SKB_DST_ACCESSOR_FUNCS])]) OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index b011396ef..9abd58224 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -3,6 +3,7 @@ #include_next +#include #include #ifndef HAVE_SKB_COPY_FROM_LINEAR_DATA_OFFSET @@ -260,7 +261,11 @@ static inline __u32 skb_get_hash(struct sk_buff *skb) { #ifdef HAVE_RXHASH if (skb->rxhash) +#ifndef HAVE_U16_RXHASH return skb->rxhash; +#else + return jhash_1word(skb->rxhash, 0); +#endif #endif return __skb_get_hash(skb); } -- 2.20.1