lkml.org 
[lkml]   [2022]   [Aug]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [PATCH 6/6] net/ipv6: sr: Switch to using crypto_pool
From
Date
On 2022/7/27 4:16, Dmitry Safonov Wrote:
> The conversion to use crypto_pool has the following upsides:
> - now SR uses asynchronous API which may potentially free CPU cycles and
> improve performance for of CPU crypto algorithm providers;
Is there any specific test data for this performance improvement?
How much has the memory increased?
How much has the performance improved?
Thanks
Longfang.
> - hash descriptors now don't have to be allocated on boot, but only at
> the moment SR starts using HMAC and until the last HMAC secret is
> deleted;
> - potentially reuse ahash_request(s) for different users
> - allocate only one per-CPU scratch buffer rather than a new one for
> each user
> - have a common API for net/ users that need ahash on RX/TX fast path
>
> Signed-off-by: Dmitry Safonov <dima@arista.com>
> ---
> include/net/seg6_hmac.h | 7 --
> net/ipv6/Kconfig | 2 +-
> net/ipv6/seg6.c | 3 -
> net/ipv6/seg6_hmac.c | 204 ++++++++++++++++------------------------
> 4 files changed, 80 insertions(+), 136 deletions(-)
>
> diff --git a/include/net/seg6_hmac.h b/include/net/seg6_hmac.h
> index 2b5d2ee5613e..d6b7820ecda2 100644
> --- a/include/net/seg6_hmac.h
> +++ b/include/net/seg6_hmac.h
> @@ -32,13 +32,6 @@ struct seg6_hmac_info {
> u8 alg_id;
> };
>
> -struct seg6_hmac_algo {
> - u8 alg_id;
> - char name[64];
> - struct crypto_shash * __percpu *tfms;
> - struct shash_desc * __percpu *shashs;
> -};
> -
> extern int seg6_hmac_compute(struct seg6_hmac_info *hinfo,
> struct ipv6_sr_hdr *hdr, struct in6_addr *saddr,
> u8 *output);
> diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
> index 658bfed1df8b..5be1dab0f178 100644
> --- a/net/ipv6/Kconfig
> +++ b/net/ipv6/Kconfig
> @@ -304,7 +304,7 @@ config IPV6_SEG6_LWTUNNEL
> config IPV6_SEG6_HMAC
> bool "IPv6: Segment Routing HMAC support"
> depends on IPV6
> - select CRYPTO
> + select CRYPTO_POOL
> select CRYPTO_HMAC
> select CRYPTO_SHA1
> select CRYPTO_SHA256
> diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
> index 73aaabf0e966..96b80e1d04c1 100644
> --- a/net/ipv6/seg6.c
> +++ b/net/ipv6/seg6.c
> @@ -552,9 +552,6 @@ int __init seg6_init(void)
>
> void seg6_exit(void)
> {
> -#ifdef CONFIG_IPV6_SEG6_HMAC
> - seg6_hmac_exit();
> -#endif
> #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
> seg6_iptunnel_exit();
> #endif
> diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c
> index d43c50a7310d..3732dd993925 100644
> --- a/net/ipv6/seg6_hmac.c
> +++ b/net/ipv6/seg6_hmac.c
> @@ -35,6 +35,7 @@
> #include <net/xfrm.h>
>
> #include <crypto/hash.h>
> +#include <crypto/pool.h>
> #include <net/seg6.h>
> #include <net/genetlink.h>
> #include <net/seg6_hmac.h>
> @@ -70,6 +71,12 @@ static const struct rhashtable_params rht_params = {
> .obj_cmpfn = seg6_hmac_cmpfn,
> };
>
> +struct seg6_hmac_algo {
> + u8 alg_id;
> + char name[64];
> + int crypto_pool_id;
> +};
> +
> static struct seg6_hmac_algo hmac_algos[] = {
> {
> .alg_id = SEG6_HMAC_ALGO_SHA1,
> @@ -115,55 +122,17 @@ static struct seg6_hmac_algo *__hmac_get_algo(u8 alg_id)
> return NULL;
> }
>
> -static int __do_hmac(struct seg6_hmac_info *hinfo, const char *text, u8 psize,
> - u8 *output, int outlen)
> -{
> - struct seg6_hmac_algo *algo;
> - struct crypto_shash *tfm;
> - struct shash_desc *shash;
> - int ret, dgsize;
> -
> - algo = __hmac_get_algo(hinfo->alg_id);
> - if (!algo)
> - return -ENOENT;
> -
> - tfm = *this_cpu_ptr(algo->tfms);
> -
> - dgsize = crypto_shash_digestsize(tfm);
> - if (dgsize > outlen) {
> - pr_debug("sr-ipv6: __do_hmac: digest size too big (%d / %d)\n",
> - dgsize, outlen);
> - return -ENOMEM;
> - }
> -
> - ret = crypto_shash_setkey(tfm, hinfo->secret, hinfo->slen);
> - if (ret < 0) {
> - pr_debug("sr-ipv6: crypto_shash_setkey failed: err %d\n", ret);
> - goto failed;
> - }
> -
> - shash = *this_cpu_ptr(algo->shashs);
> - shash->tfm = tfm;
> -
> - ret = crypto_shash_digest(shash, text, psize, output);
> - if (ret < 0) {
> - pr_debug("sr-ipv6: crypto_shash_digest failed: err %d\n", ret);
> - goto failed;
> - }
> -
> - return dgsize;
> -
> -failed:
> - return ret;
> -}
> -
> int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
> struct in6_addr *saddr, u8 *output)
> {
> __be32 hmackeyid = cpu_to_be32(hinfo->hmackeyid);
> - u8 tmp_out[SEG6_HMAC_MAX_DIGESTSIZE];
> + struct crypto_pool_ahash hp;
> + struct seg6_hmac_algo *algo;
> int plen, i, dgsize, wrsize;
> + struct crypto_ahash *tfm;
> + struct scatterlist sg;
> char *ring, *off;
> + int err;
>
> /* a 160-byte buffer for digest output allows to store highest known
> * hash function (RadioGatun) with up to 1216 bits
> @@ -176,6 +145,10 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
> if (plen >= SEG6_HMAC_RING_SIZE)
> return -EMSGSIZE;
>
> + algo = __hmac_get_algo(hinfo->alg_id);
> + if (!algo)
> + return -ENOENT;
> +
> /* Let's build the HMAC text on the ring buffer. The text is composed
> * as follows, in order:
> *
> @@ -186,8 +159,36 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
> * 5. All segments in the segments list (n * 128 bits)
> */
>
> - local_bh_disable();
> + err = crypto_pool_get(algo->crypto_pool_id, (struct crypto_pool *)&hp);
> + if (err)
> + return err;
> +
> ring = this_cpu_ptr(hmac_ring);
> +
> + sg_init_one(&sg, ring, plen);
> +
> + tfm = crypto_ahash_reqtfm(hp.req);
> + dgsize = crypto_ahash_digestsize(tfm);
> + if (dgsize > SEG6_HMAC_MAX_DIGESTSIZE) {
> + pr_debug("digest size too big (%d / %d)\n",
> + dgsize, SEG6_HMAC_MAX_DIGESTSIZE);
> + err = -ENOMEM;
> + goto err_put_pool;
> + }
> +
> + err = crypto_ahash_setkey(tfm, hinfo->secret, hinfo->slen);
> + if (err) {
> + pr_debug("crypto_ahash_setkey failed: err %d\n", err);
> + goto err_put_pool;
> + }
> +
> + err = crypto_ahash_init(hp.req);
> + if (err)
> + goto err_put_pool;
> +
> + ahash_request_set_crypt(hp.req, &sg,
> + hp.base.scratch, SEG6_HMAC_MAX_DIGESTSIZE);
> +
> off = ring;
>
> /* source address */
> @@ -210,21 +211,25 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
> off += 16;
> }
>
> - dgsize = __do_hmac(hinfo, ring, plen, tmp_out,
> - SEG6_HMAC_MAX_DIGESTSIZE);
> - local_bh_enable();
> + err = crypto_ahash_update(hp.req);
> + if (err)
> + goto err_put_pool;
>
> - if (dgsize < 0)
> - return dgsize;
> + err = crypto_ahash_final(hp.req);
> + if (err)
> + goto err_put_pool;
>
> wrsize = SEG6_HMAC_FIELD_LEN;
> if (wrsize > dgsize)
> wrsize = dgsize;
>
> memset(output, 0, SEG6_HMAC_FIELD_LEN);
> - memcpy(output, tmp_out, wrsize);
> + memcpy(output, hp.base.scratch, wrsize);
>
> - return 0;
> +err_put_pool:
> + crypto_pool_put();
> +
> + return err;
> }
> EXPORT_SYMBOL(seg6_hmac_compute);
>
> @@ -291,12 +296,24 @@ EXPORT_SYMBOL(seg6_hmac_info_lookup);
> int seg6_hmac_info_add(struct net *net, u32 key, struct seg6_hmac_info *hinfo)
> {
> struct seg6_pernet_data *sdata = seg6_pernet(net);
> - int err;
> + struct seg6_hmac_algo *algo;
> + int ret;
>
> - err = rhashtable_lookup_insert_fast(&sdata->hmac_infos, &hinfo->node,
> + algo = __hmac_get_algo(hinfo->alg_id);
> + if (!algo)
> + return -ENOENT;
> +
> + ret = crypto_pool_alloc_ahash(algo->name);
> + if (ret < 0)
> + return ret;
> + algo->crypto_pool_id = ret;
> +
> + ret = rhashtable_lookup_insert_fast(&sdata->hmac_infos, &hinfo->node,
> rht_params);
> + if (ret)
> + crypto_pool_release(algo->crypto_pool_id);
>
> - return err;
> + return ret;
> }
> EXPORT_SYMBOL(seg6_hmac_info_add);
>
> @@ -304,6 +321,7 @@ int seg6_hmac_info_del(struct net *net, u32 key)
> {
> struct seg6_pernet_data *sdata = seg6_pernet(net);
> struct seg6_hmac_info *hinfo;
> + struct seg6_hmac_algo *algo;
> int err = -ENOENT;
>
> hinfo = rhashtable_lookup_fast(&sdata->hmac_infos, &key, rht_params);
> @@ -315,6 +333,12 @@ int seg6_hmac_info_del(struct net *net, u32 key)
> if (err)
> goto out;
>
> + algo = __hmac_get_algo(hinfo->alg_id);
> + if (algo)
> + crypto_pool_release(algo->crypto_pool_id);
> + else
> + WARN_ON_ONCE(1);
> +
> seg6_hinfo_release(hinfo);
>
> out:
> @@ -348,56 +372,9 @@ int seg6_push_hmac(struct net *net, struct in6_addr *saddr,
> }
> EXPORT_SYMBOL(seg6_push_hmac);
>
> -static int seg6_hmac_init_algo(void)
> -{
> - struct seg6_hmac_algo *algo;
> - struct crypto_shash *tfm;
> - struct shash_desc *shash;
> - int i, alg_count, cpu;
> -
> - alg_count = ARRAY_SIZE(hmac_algos);
> -
> - for (i = 0; i < alg_count; i++) {
> - struct crypto_shash **p_tfm;
> - int shsize;
> -
> - algo = &hmac_algos[i];
> - algo->tfms = alloc_percpu(struct crypto_shash *);
> - if (!algo->tfms)
> - return -ENOMEM;
> -
> - for_each_possible_cpu(cpu) {
> - tfm = crypto_alloc_shash(algo->name, 0, 0);
> - if (IS_ERR(tfm))
> - return PTR_ERR(tfm);
> - p_tfm = per_cpu_ptr(algo->tfms, cpu);
> - *p_tfm = tfm;
> - }
> -
> - p_tfm = raw_cpu_ptr(algo->tfms);
> - tfm = *p_tfm;
> -
> - shsize = sizeof(*shash) + crypto_shash_descsize(tfm);
> -
> - algo->shashs = alloc_percpu(struct shash_desc *);
> - if (!algo->shashs)
> - return -ENOMEM;
> -
> - for_each_possible_cpu(cpu) {
> - shash = kzalloc_node(shsize, GFP_KERNEL,
> - cpu_to_node(cpu));
> - if (!shash)
> - return -ENOMEM;
> - *per_cpu_ptr(algo->shashs, cpu) = shash;
> - }
> - }
> -
> - return 0;
> -}
> -
> int __init seg6_hmac_init(void)
> {
> - return seg6_hmac_init_algo();
> + return crypto_pool_reserve_scratch(SEG6_HMAC_MAX_DIGESTSIZE);
> }
>
> int __net_init seg6_hmac_net_init(struct net *net)
> @@ -407,29 +384,6 @@ int __net_init seg6_hmac_net_init(struct net *net)
> return rhashtable_init(&sdata->hmac_infos, &rht_params);
> }
>
> -void seg6_hmac_exit(void)
> -{
> - struct seg6_hmac_algo *algo = NULL;
> - int i, alg_count, cpu;
> -
> - alg_count = ARRAY_SIZE(hmac_algos);
> - for (i = 0; i < alg_count; i++) {
> - algo = &hmac_algos[i];
> - for_each_possible_cpu(cpu) {
> - struct crypto_shash *tfm;
> - struct shash_desc *shash;
> -
> - shash = *per_cpu_ptr(algo->shashs, cpu);
> - kfree(shash);
> - tfm = *per_cpu_ptr(algo->tfms, cpu);
> - crypto_free_shash(tfm);
> - }
> - free_percpu(algo->tfms);
> - free_percpu(algo->shashs);
> - }
> -}
> -EXPORT_SYMBOL(seg6_hmac_exit);
> -
> void __net_exit seg6_hmac_net_exit(struct net *net)
> {
> struct seg6_pernet_data *sdata = seg6_pernet(net);
>

\
 
 \ /
  Last update: 2022-08-08 05:40    [W:0.167 / U:1.980 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site