mirror of https://github.com/torvalds/linux.git
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>
This commit is contained in:
parent
095928e7d8
commit
fe60065689
|
|
@ -9,6 +9,8 @@
|
||||||
#ifndef _NET_SEG6_HMAC_H
|
#ifndef _NET_SEG6_HMAC_H
|
||||||
#define _NET_SEG6_HMAC_H
|
#define _NET_SEG6_HMAC_H
|
||||||
|
|
||||||
|
#include <crypto/sha1.h>
|
||||||
|
#include <crypto/sha2.h>
|
||||||
#include <net/flow.h>
|
#include <net/flow.h>
|
||||||
#include <net/ip6_fib.h>
|
#include <net/ip6_fib.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
|
@ -26,9 +28,15 @@ struct seg6_hmac_info {
|
||||||
struct rcu_head rcu;
|
struct rcu_head rcu;
|
||||||
|
|
||||||
u32 hmackeyid;
|
u32 hmackeyid;
|
||||||
|
/* The raw key, kept only so it can be returned back to userspace */
|
||||||
char secret[SEG6_HMAC_SECRET_LEN];
|
char secret[SEG6_HMAC_SECRET_LEN];
|
||||||
u8 slen;
|
u8 slen;
|
||||||
u8 alg_id;
|
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,
|
extern int seg6_hmac_compute(struct seg6_hmac_info *hinfo,
|
||||||
|
|
|
||||||
|
|
@ -148,19 +148,18 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
|
||||||
|
|
||||||
switch (hinfo->alg_id) {
|
switch (hinfo->alg_id) {
|
||||||
case SEG6_HMAC_ALGO_SHA1:
|
case SEG6_HMAC_ALGO_SHA1:
|
||||||
hmac_sha1_usingrawkey(hinfo->secret, hinfo->slen, ring, plen,
|
hmac_sha1(&hinfo->key.sha1, ring, plen, output);
|
||||||
output);
|
|
||||||
static_assert(SEG6_HMAC_FIELD_LEN > SHA1_DIGEST_SIZE);
|
static_assert(SEG6_HMAC_FIELD_LEN > SHA1_DIGEST_SIZE);
|
||||||
memset(&output[SHA1_DIGEST_SIZE], 0,
|
memset(&output[SHA1_DIGEST_SIZE], 0,
|
||||||
SEG6_HMAC_FIELD_LEN - SHA1_DIGEST_SIZE);
|
SEG6_HMAC_FIELD_LEN - SHA1_DIGEST_SIZE);
|
||||||
break;
|
break;
|
||||||
case SEG6_HMAC_ALGO_SHA256:
|
case SEG6_HMAC_ALGO_SHA256:
|
||||||
hmac_sha256_usingrawkey(hinfo->secret, hinfo->slen, ring, plen,
|
hmac_sha256(&hinfo->key.sha256, ring, plen, output);
|
||||||
output);
|
|
||||||
static_assert(SEG6_HMAC_FIELD_LEN == SHA256_DIGEST_SIZE);
|
static_assert(SEG6_HMAC_FIELD_LEN == SHA256_DIGEST_SIZE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -ENOENT;
|
WARN_ON_ONCE(1);
|
||||||
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
local_unlock_nested_bh(&hmac_storage.bh_lock);
|
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) {
|
switch (hinfo->alg_id) {
|
||||||
case SEG6_HMAC_ALGO_SHA1:
|
case SEG6_HMAC_ALGO_SHA1:
|
||||||
|
hmac_sha1_preparekey(&hinfo->key.sha1,
|
||||||
|
hinfo->secret, hinfo->slen);
|
||||||
|
break;
|
||||||
case SEG6_HMAC_ALGO_SHA256:
|
case SEG6_HMAC_ALGO_SHA256:
|
||||||
|
hmac_sha256_preparekey(&hinfo->key.sha256,
|
||||||
|
hinfo->secret, hinfo->slen);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue