ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[openssl] openssl async模块框架分析

2021-02-05 20:03:19  阅读:348  来源: 互联网

标签:qat int openssl SSL job 模块 ASYNC async


[classic_tong: https://www.cnblogs.com/hugetong/p/14379347.html]

这一部分内容的前面还有个第一部分,可以作为接下来内容的前提或者背景进行阅读:[openssl] intel qat场景下的openssl框架

 

引言

openssl1.1.1版本新增了async功能。是为了更好支持qat卡新增的功能。

详见:[openssl] intel qat场景下的openssl框架  有关性能部分的讨论。

 

API

回顾前文我们讨论了openssl的基本框架,包含:app,ssl,crypto,engines四部分。

async模块是crypto component中的一部分。它目前仅被ssl模块引用,被封装在SSL的api调用下面

sync模块的主要API:

/* 提供给应用程序的接口, */
int ASYNC_init_thread(size_t max_size, size_t init_size); void ASYNC_cleanup_thread(void); int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *ctx, int *ret, int (*func)(void *), void *args, size_t size);
/* 提供给应用程序用于epoll的接口。 */ ASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job); int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key, OSSL_ASYNC_FD *fd, void **custom_data); int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd, size_t *numfds); int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd, size_t *numaddfds, OSSL_ASYNC_FD *delfd, size_t *numdelfds); /* 对ENGINE的接口,在ENGINE中调用 */ ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void); void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx); int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, OSSL_ASYNC_FD fd, void *custom_data, void (*cleanup)(ASYNC_WAIT_CTX *, const void *, OSSL_ASYNC_FD, void *));
int ASYNC_pause_job(void);

 

SSL模块的主要API

/* SSL的基本IO接口 */
SSL *SSL_new(SSL_CTX *ctx); void SSL_free(SSL *ssl);
int SSL_accept(SSL *ssl);
int SSL_connect(SSL *ssl);
int SSL_read(SSL *ssl, void *buf, int num);
int SSL_peek(SSL *ssl, void *buf, int num);
int SSL_write(SSL *ssl, const void *buf, int num);

/* SSL 用于异步处理的 socket fd */
int SSL_get_fd(const SSL *s);

/* SSL 用于异步处理的加解密设备 fd */
int SSL_waiting_for_async(SSL *s);
int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds);
int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd,
size_t *numaddfds, OSSL_ASYNC_FD *delfd, size_t *numdelfds);

 

ENGINE注册进openssl的接口

ENGINE_set_id(e, engine_qat_id)
ENGINE_set_name(e, engine_qat_name)
ENGINE_set_RSA(e, qat_get_RSA_methods())
ENGINE_set_DSA(e, qat_get_DSA_methods())
ENGINE_set_DH(e, qat_get_DH_methods())
ENGINE_set_EC(e, qat_get_EC_methods())
ENGINE_set_pkey_meths(e, qat_pkey_methods)
ENGINE_set_RSA(e, multibuff_get_RSA_methods())
ENGINE_set_pkey_meths(e, multibuff_x25519_pkey_methods)
ENGINE_set_ciphers(e, qat_ciphers)

 

上下文切换

async为了达到并行的目的,在单线程中实现了协程。请读:[openssl] 协程

async模块中,将其抽象为job,job为一次运行即结束的。多个job同时运行,使用协程进行调度。

job有个pool,这个pool是堆内存,地址存储在每线程的全局变量里,使用api pthread_getspecfic()

核心的协程切换在这个函数里:https://github.com/openssl/openssl/blob/master/crypto/async/arch/async_posix.h::async_fibre_swapcontext()

 

封装

这一小节讲,上面的三部分接口是怎么结合起来的。主要包括ssl怎么与async结合,engine怎么对async支持。

ssl与async

ssl内部组织了一个状态机,将握手,读写等操作抽象为两个job,ssl_io_intern(读写), ssl_do_handshake_intern(握手), 统一通过api ASYNC_start_job()进行job调度。

JOB有 ASYNC_ERR, ASYNC_PAUSE, ASYNC_FINISH, ASYNC_NO_JOBS, 四个状态。状态表征了job的运行情况。

async的基本模型是,1 cpu进行用户应用的前期计算,2  cpu进行ssl框架内的前期计算, 3  write数据进qat卡,4 qat卡计算,5 read数据出qat卡,6  cpu进行ssl框架内的后期计算,7 cpu进行用户应用的后期计算。

async的目标就是让cpu在阶段3进行有效计算。

为了达到这个目标,async模块将流程2356划分为一个job,17作为主流程(主协程?主job)。4被卸载到了硬件卡上,不占用cpu。协程的本质是对cpu的分时复用,所以,我们讨论job的时候,就是在讨论cpu的时间片分配。

 

ssl调用了async_start_job之后,便进入了job 2356流程,当job执行完23之后,会调用api ASYNC_pause_job() 切换回主job,并将job状态设置为ASYNC_PAUSE, 这个时候CPU会交还给主job完全其他计算工作,qat并行的进行他自己的计算。

主job知道另一个job没有进入结束状态,所以它利用SSL_waiting_for_async()接口获得的一个eventfd,并将它epoll()起来。当qat卡计算完成(另一个问题,cpu怎么知道qat卡计算完成了?)会执行一个回调,这个回调会写入eventfd,从而

主job再次进入ssl之前的api,继续job的56流程。完成6之后,再调用ASYNC_pause_job()切换主job,并将job状态设置为ASYNC_FINISH. 主job完成流程7.  结束。

 

async与engine

接上面的问题, cpu怎么知道qat卡完成了计算?  

答案:文章[openssl] intel qat场景下的openssl框架中提到了四种模式,其中模式inline启动了一个线程,该线程在不停的调用qatdriver的polling api,轮训获取qat的计算状态,得到相应结果后,写入eventfd,唤醒job。

其他基于timer的模式,机制类似。

 

前文提到的流程2(一部分)356(一部分),都被封装在了以插件的形式注册的加解密函数中,如前文的api表格所示。

这部分处理除了负责读写硬件,还有另外两个职责,1, job的切回,也就是pause。2,eventfd的唤醒。

 

千言万语抵不过一张图,通过下图理解一下:

 

性能

最后回到上一篇提到的性能问题。

先回顾一下关于qat性能的讨论。 性能的提升有两个角度。

1.  用户调用openssl时使用异步IO,就是使用epoll,select等,完成多个SSL的操作,这个与常规典型的异步IO使用的方法一下,不在赘述。

2.  一个ssl流程里都包括,算随机数,做秘钥协商,非对称加密,对每个block的对称加密,对每个block的对称解密,这一个序列的每一个步都可以由qat卡完成计算。

    他们每一个被抽象成一个job,共同并行。这个并行包括了多个qat卡bank和cpu,他们多者之间的并行。

    也就是说,如上图所示的同一个SSL_accept(1st)的调用里,可以有多个ASYNC_start_job().

    而性能优化的角度1是:如上图的event_loop()的地方,可以有多个SSL_accept(1st)在等待完成。

 

--------

 

标签:qat,int,openssl,SSL,job,模块,ASYNC,async
来源: https://www.cnblogs.com/hugetong/p/14379347.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有