Blob Blame History Raw
From 7fcfc0e4d6949ff32df3ed749bad8eb419cebbda Mon Sep 17 00:00:00 2001
Message-Id: <7fcfc0e4d6949ff32df3ed749bad8eb419cebbda.1628790091.git.aclaudi@redhat.com>
In-Reply-To: <650694eb0120722499207078f965442ef7343bb1.1628790091.git.aclaudi@redhat.com>
References: <650694eb0120722499207078f965442ef7343bb1.1628790091.git.aclaudi@redhat.com>
From: Andrea Claudi <aclaudi@redhat.com>
Date: Wed, 11 Aug 2021 14:49:33 +0200
Subject: [PATCH] tc: u32: Fix key folding in sample option

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979425
Upstream Status: iproute2.git commit 9b7ea92b

commit 9b7ea92b9e3feff2876f772ace01148b7406839c
Author: Phil Sutter <phil@nwl.cc>
Date:   Wed Aug 4 11:18:28 2021 +0200

    tc: u32: Fix key folding in sample option

    In between Linux kernel 2.4 and 2.6, key folding for hash tables changed
    in kernel space. When iproute2 dropped support for the older algorithm,
    the wrong code was removed and kernel 2.4 folding method remained in
    place. To get things functional for recent kernels again, restoring the
    old code alone was not sufficient - additional byteorder fixes were
    needed.

    While being at it, make use of ffs() and thereby align the code with how
    kernel determines the shift width.

    Fixes: 267480f55383c ("Backout the 2.4 utsname hash patch.")
    Signed-off-by: Phil Sutter <phil@nwl.cc>
    Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
---
 tc/f_u32.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/tc/f_u32.c b/tc/f_u32.c
index 2ed5254a..a5747f67 100644
--- a/tc/f_u32.c
+++ b/tc/f_u32.c
@@ -978,6 +978,13 @@ show_k:
 	goto show_k;
 }
 
+static __u32 u32_hash_fold(struct tc_u32_key *key)
+{
+	__u8 fshift = key->mask ? ffs(ntohl(key->mask)) - 1 : 0;
+
+	return ntohl(key->val & key->mask) >> fshift;
+}
+
 static int u32_parse_opt(struct filter_util *qu, char *handle,
 			 int argc, char **argv, struct nlmsghdr *n)
 {
@@ -1110,9 +1117,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle,
 				}
 				NEXT_ARG();
 			}
-			hash = sel2.keys[0].val & sel2.keys[0].mask;
-			hash ^= hash >> 16;
-			hash ^= hash >> 8;
+			hash = u32_hash_fold(&sel2.keys[0]);
 			htid = ((hash % divisor) << 12) | (htid & 0xFFF00000);
 			sample_ok = 1;
 			continue;
-- 
2.31.1