summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@kernel.org>2025-08-23 21:36:44 -0400
committerJakub Kicinski <kuba@kernel.org>2025-08-26 18:11:29 -0700
commitfe60065689048edf4df99fffdb180a2166f9a54d (patch)
treeeb6d86af91ea0b85b711cfad0a1fc96e0087b412
parent095928e7d80186c524013a5b5d54889fa2ec1eaa (diff)
ipv6: sr: Prepare HMAC key ahead of time
Prepare the HMAC key when it is added to the kernel, instead of preparing it implicitly for every packet. This significantly improves the performance of seg6_hmac_compute(). A microbenchmark on x86_64 shows seg6_hmac_compute() (with HMAC-SHA256) dropping from ~1978 cycles to ~1419 cycles, a 28% improvement. The size of 'struct seg6_hmac_info' increases by 128 bytes, but that should be fine, since there should not be a massive number of keys. Signed-off-by: Eric Biggers <ebiggers@kernel.org> Link: https://patch.msgid.link/20250824013644.71928-3-ebiggers@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--include/net/seg6_hmac.h8
-rw-r--r--net/ipv6/seg6_hmac.c14
2 files changed, 17 insertions, 5 deletions
diff --git a/include/net/seg6_hmac.h b/include/net/seg6_hmac.h
index 3fe4123dbbf0..e9f41725933e 100644
--- a/include/net/seg6_hmac.h
+++ b/include/net/seg6_hmac.h
@@ -9,6 +9,8 @@
#ifndef _NET_SEG6_HMAC_H
#define _NET_SEG6_HMAC_H
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
#include <net/flow.h>
#include <net/ip6_fib.h>
#include <net/sock.h>
@@ -26,9 +28,15 @@ struct seg6_hmac_info {
struct rcu_head rcu;
u32 hmackeyid;
+ /* The raw key, kept only so it can be returned back to userspace */
char secret[SEG6_HMAC_SECRET_LEN];
u8 slen;
u8 alg_id;
+ /* The prepared key, which the calculations actually use */
+ union {
+ struct hmac_sha1_key sha1;
+ struct hmac_sha256_key sha256;
+ } key;
};
extern int seg6_hmac_compute(struct seg6_hmac_info *hinfo,
diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c
index 61f6019df55b..ee6bac0160ac 100644
--- a/net/ipv6/seg6_hmac.c
+++ b/net/ipv6/seg6_hmac.c
@@ -148,19 +148,18 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
switch (hinfo->alg_id) {
case SEG6_HMAC_ALGO_SHA1:
- hmac_sha1_usingrawkey(hinfo->secret, hinfo->slen, ring, plen,
- output);
+ hmac_sha1(&hinfo->key.sha1, ring, plen, output);
static_assert(SEG6_HMAC_FIELD_LEN > SHA1_DIGEST_SIZE);
memset(&output[SHA1_DIGEST_SIZE], 0,
SEG6_HMAC_FIELD_LEN - SHA1_DIGEST_SIZE);
break;
case SEG6_HMAC_ALGO_SHA256:
- hmac_sha256_usingrawkey(hinfo->secret, hinfo->slen, ring, plen,
- output);
+ hmac_sha256(&hinfo->key.sha256, ring, plen, output);
static_assert(SEG6_HMAC_FIELD_LEN == SHA256_DIGEST_SIZE);
break;
default:
- ret = -ENOENT;
+ WARN_ON_ONCE(1);
+ ret = -EINVAL;
break;
}
local_unlock_nested_bh(&hmac_storage.bh_lock);
@@ -238,7 +237,12 @@ int seg6_hmac_info_add(struct net *net, u32 key, struct seg6_hmac_info *hinfo)
switch (hinfo->alg_id) {
case SEG6_HMAC_ALGO_SHA1:
+ hmac_sha1_preparekey(&hinfo->key.sha1,
+ hinfo->secret, hinfo->slen);
+ break;
case SEG6_HMAC_ALGO_SHA256:
+ hmac_sha256_preparekey(&hinfo->key.sha256,
+ hinfo->secret, hinfo->slen);
break;
default:
return -EINVAL;