Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eric Biggers and committed by
Jakub Kicinski
fe600656 095928e7

+17 -5
+8
include/net/seg6_hmac.h
··· 9 9 #ifndef _NET_SEG6_HMAC_H 10 10 #define _NET_SEG6_HMAC_H 11 11 12 + #include <crypto/sha1.h> 13 + #include <crypto/sha2.h> 12 14 #include <net/flow.h> 13 15 #include <net/ip6_fib.h> 14 16 #include <net/sock.h> ··· 28 26 struct rcu_head rcu; 29 27 30 28 u32 hmackeyid; 29 + /* The raw key, kept only so it can be returned back to userspace */ 31 30 char secret[SEG6_HMAC_SECRET_LEN]; 32 31 u8 slen; 33 32 u8 alg_id; 33 + /* The prepared key, which the calculations actually use */ 34 + union { 35 + struct hmac_sha1_key sha1; 36 + struct hmac_sha256_key sha256; 37 + } key; 34 38 }; 35 39 36 40 extern int seg6_hmac_compute(struct seg6_hmac_info *hinfo,
+9 -5
net/ipv6/seg6_hmac.c
··· 148 148 149 149 switch (hinfo->alg_id) { 150 150 case SEG6_HMAC_ALGO_SHA1: 151 - hmac_sha1_usingrawkey(hinfo->secret, hinfo->slen, ring, plen, 152 - output); 151 + hmac_sha1(&hinfo->key.sha1, ring, plen, output); 153 152 static_assert(SEG6_HMAC_FIELD_LEN > SHA1_DIGEST_SIZE); 154 153 memset(&output[SHA1_DIGEST_SIZE], 0, 155 154 SEG6_HMAC_FIELD_LEN - SHA1_DIGEST_SIZE); 156 155 break; 157 156 case SEG6_HMAC_ALGO_SHA256: 158 - hmac_sha256_usingrawkey(hinfo->secret, hinfo->slen, ring, plen, 159 - output); 157 + hmac_sha256(&hinfo->key.sha256, ring, plen, output); 160 158 static_assert(SEG6_HMAC_FIELD_LEN == SHA256_DIGEST_SIZE); 161 159 break; 162 160 default: 163 - ret = -ENOENT; 161 + WARN_ON_ONCE(1); 162 + ret = -EINVAL; 164 163 break; 165 164 } 166 165 local_unlock_nested_bh(&hmac_storage.bh_lock); ··· 237 238 238 239 switch (hinfo->alg_id) { 239 240 case SEG6_HMAC_ALGO_SHA1: 241 + hmac_sha1_preparekey(&hinfo->key.sha1, 242 + hinfo->secret, hinfo->slen); 243 + break; 240 244 case SEG6_HMAC_ALGO_SHA256: 245 + hmac_sha256_preparekey(&hinfo->key.sha256, 246 + hinfo->secret, hinfo->slen); 241 247 break; 242 248 default: 243 249 return -EINVAL;