配电自动化通信加密机性能优化
2022-01-05王众全臧家义
辛 阳,王众全,臧家义*
1.齐鲁工业大学(山东省科学院) 电气工程与自动化学院,济南 250353 2.山东安控信息科技有限公司,济南 250101
为了安全、经济、可靠的发供电,合理地分配电能,保证电力质量指标,及时地处理和防止系统事故,配电自动化系统应集中管理、统一调度,建立与之相适应的通信系统[1]。因此配电自动化系统的通信安全是目前主要研究方向,是实现电网上下级之间信息交互的重要手段,为电网正常运行、电网的维修等提供技术支撑。通过建立安全防护体系,使用防火墙、物理隔离、主机防护等安全防护技术和管理措施来保护电网系统的安全[2]。
电力加密机的使用可有效确保电力系统的通信安全[3]。加密技术是指将原始数据通过编码的方式转变为密文和把编码后的密文解码为原始数据的技术,其中,解码是编码的逆过程[4]。对称和非对称密钥算法是两种不同的加密类型。对称加密算法是使用最多的一个,因为它的实现简单,所以应用比较广泛,并且是目前大家较为认可的技术。对称加密过程可以概括为数据发送方将原始数据使用对称密钥并经过加密算法处理后得到密文的这样一个流程,而解密方只需使用加密算法的逆算法和使用对称密钥进行解密,就可以得到原始的报文[5]。
我国配电自动化正在逐步成长,由配电主站、子站和馈线终端构成的三层结构是最常见的并得到广泛赞同,光纤通信作为主干网的通信方式也得到认可[6]。由于电力系统信息安全的特殊重要性,国内外对电网通信保密性的高度重视,促进了加密机的发展,加密机在电网中的应用有效提高了安全性。目前,电力通信中接入的终端越来越多,信息的吞吐量也越来越多,对加密机的性能要求也随之增加。然而配电自动化通信加密机在国产化的兆芯平台上吞吐性能是120 Mb/s,这不足以满足性能需求,需要对加密机进行优化。在目前的配电自动化中配电主站需要接入大量的配电终端,为了满足配电自动化中的加/解密需求,要求加密机的吞吐性能要在250 Mb/s以上。
1 现有加密机的性能分析
影响设备性能的因素有很多。首先,从软件架构来看,软件架构是一个系统草图,它描述的是构成系统的抽象组件,各组件之间的连接明确和较为仔细地描述组件之间的通讯[7]。从具体实物来看,这些抽象组件会被细化为具体的实物,比如具体某个类或对象。从面向对象方面来看,各个组件的连接需要用接口来实现。构架是一个应用系统的基础,往往对性能有着决定性的影响,但是改动起来也是最困难的,不到万不得已一般不能随意变动架构。其次,从组件的具体实现上,比如算法代码的优化,空间换时间的运用,调整线程或者连接池的大小同样也可以提高性能指标。
加密机的软件架构如图1所示。
图1 加密机软件构架
图1中程序的执行路径是应用进程通过加密线程接到API接口,从连接池中取出一个已建立的可以使用的连接socket对象,将通信数据写入socket发送到服务端,服务端利用epoll侦听到数据,然后从加密线程池中取出一个可用的加密线程,将socket对象交给此线程,加密线程读出数据,使用加密卡同步接口进行加/解密,加密卡返回数据后,加密线程再将数据写入socket对象发送给客户端。
加密机为应用进程提供用于二次开发的API软件包,软件包内使用连接池技术,提前与服务器建立多个连接,让应用进程的多个业务线程共享这些连接,客户端和服务端使用TCP连接,加密服务使用epoll机制侦听客户端连接和数据收发,加密服务同时使用线程池技术和加密卡交互,数据共享这些加密线程。
多线程技术是充分利用和发挥CPU性能的一种现代计算机技术,采用并发执行的方式来实现。通过把程序分段,看成是许多个子任务,这些子任务并发执行。在单核CPU时,并发执行是把处理器分为多个时间片,每个时间片依次执行各个任务。因为每一个时间片的时间很短,所以可以看成每个程序都有处理器单独服务,从而达到多个程序同时运行的效果。也就是单核模拟多核,能同时提供多个服务,增强用户体验和程序的效率。在多核CPU时,能实现真正的多任务并发。连接池技术的使用可以减少时间从而提高性能,这些预先准备好的连接被任何需要它们的线程使用,这样可以实现连接的集中管理,不用每个业务线程都去创建一个连接,而只是在需要的时候利用其中一个连接,从而节省网络资源。连接池可以为动态实现的,连接数在设定的区间内根据实际业务需要动态增加或者减少。
2 可实现的优化方案
对设备进行分析,可以将性能分解到多个部分,通过测定分析各部件的性能情况,找到优化方法。
2.1 加密卡
需要保证加密卡的性能满足要求,如果瓶颈在加密卡,那么提高加密卡的运算速度或者更换性能更好,成本也就更高的加密卡,就可以显著提升加密机的性能。
2.2 代码优化
应用程序的性能优化,除了硬件升级,最主要的是代码本身的优化,一般来说满足二八原则,20%的代码消耗80%的性能,找到那20%的代码,就可以优化对应的80%的性能。常用的方法包括:
1)调整配置参数,比如线程池/连接池的大小,应用数据缓存的大小,IO数据缓存的大小,系统资源的限制等。通过检查分析这些参数,往往能找到制约性能的点。
2)算法优化,比如数据结构的设计,能否利用cpu_cache,循环语句或者条件语句的效率,并发锁的运用等等。通过一些性能分析工具,比如perf,能定量分析各个函数调用的时间占比,算法的cache利用率。
2.3 架构调整
构架调整影响比较大,但是效果经常比较显著,能突破既有架构的限制。比如修改单线程执行为多线程并发执行,更换通讯方式从TCP改成UDP通讯,从采用内核协议栈改为使用用户态协议栈,更换使用的数据库等。比如TCP使用了握手、确认、窗口、重传、拥塞控制等机制,这些机制采用的算法很难提升,而UDP是一个无状态的传输协议,不需要这些机制,所以它宽带需求低,而实时性非常高。
我们从这三个方面入手,并且借助一些性能测试工具得到定量数据,进行分析,找出瓶颈。
采用的性能测试方法和工具如下:
1)加密卡测试程序,检测加密卡的运算速度。
2)模拟客户端程序,调用加密机客户端API,检测加密机服务性能。
3)Perf工具,查看代码中具体的耗时函数,代码优化的基础。
4)Netstat工具,可观察TCP的连接情况,查看连接池的使用情况。
5)Sar工具,从多方面对系统的活动进行查看,包括:文件读写情况、系统调用使用情况、磁盘I/O、CPU的效率、内存的使用状况、进程活动及IPC有关活动等[8]。
3 加密机的优化
3.1 从加密卡出发
加密卡是一种用于PCI-E接口的硬件加密设备,它作为加密设备或应用服务器中加密算法加速和密钥保护的组件,用于完成数据加密、身份验证和数据防护。在加/解密算法的早期,大多数使用软件实现设备的安全。主要原因是以往的信息量不大,基本上不会要求高性能的技术指标,能够满足当时的需求。然而,伴随着配电自动化技术的发展,需要连接的配电终端快速增加,对于加密卡也提出了更高的要求。加/解密速度已经成为目前产品的一大指标,标志着加解密设备产品安全性能的瓶颈。因此需要从新的方面考虑,通过加密硬件的使用从而实现其吞吐量的增加。加密卡是通过使用SM1、SM2、SM3、SM4等加密硬件来实现的,加密过程中大部分的实现都与加密卡有关,即算法是硬件机制实现中最繁琐的。还可以使用加密卡的压缩功能,相应的就可以使数据处理速度得到提升。
通过对现有加密卡进行性能测试,结果如图2所示。
图2 加密卡性能测试结果
一次加密需要调动两次加密卡。观察结果可以发现,对256字节的小包加密性能可以达到677.79/2=338.89 Mb/s,足以满足要求。目前通过升级加密卡来提升性能的可操作性不强,提升的效果也不明显。考虑从其他方面进行提升。
3.2 从代码出发
使用perf工具测试程序运行,得到函数耗时情况如图3所示。
图3 perf查看耗时函数
可以发现malloc/free占用了比较大的时间,查看代码,发现在数据接收、处理、发送过程中有大量的堆分配调用,结合实际情况考虑两个方向:
1)使用线程局部变量替换堆分配,在收发过程中使用,减少堆分配的次数,完全省去了调用时间。
2)使用第三方jemalloc库malloc函数替换c运行时库的标准堆分配函数,获得性能的提升。
jemalloc提供的堆分配器,其最大的优势是多线程分配能力。在多核环境下,进程效率的最大瓶颈已经变成如何用好多线程和如何避免死锁。jemalloc实现了尽可能地避免死锁,从而加快多线程环境下的内存申请和释放。
对原有代码进行改进,改进如下,在这里挑出了三个部分进行展示。
1)头文件部分
#include "fm_def.h"
#include
#include
#include
……
2)使用线程本地存储分配读写缓冲区
_ _thread unsigned char
TransferDataIn[MAXIUM_TRANSFERBUF_LEN];
__thread unsigned char TransferDataOut[MAXIUM_TRANSFERBUF_LEN];
3)缓冲区的实际使用
void* doData(void* ptr)
{
int sockfd;
int len=0;
int rv=0;
int sock;
unsigned char *receiveBuff=NULL;
unsigned char *sendBuf=NULL;
struct epoll_event ev,pev;
ARG_ST* psinfo=(ARG_ST *)ptr;
struct epollData *ep;
int ord=0;
int totallen=0,sendBufLen=0;
int errflag=0;
void *pdev=g_hdev;
DEVICE_STATUS *pdevStatus=NULL;
OrderFunc pFunc=NULL;
recvhead recvh;
int TransferBufLen=0;
int TransferOffset=0;
pev.events=psinfo->ev.events;
ep=(struct epollData *)psinfo->ev.data.ptr;
sock=psinfo->sock;
free(psinfo);
if ((sockfd=ep->fd) < 0)
{
LOG_WriteLog(LOG,__FILE__,__LINE__,"dodata====>",errflag,NULL,0);
return 0;
}
memset(&ev,0x00,sizeof(struct epoll_event));
if(pev.events&EPOLLIN)
{
len=recv(sockfd,TransferDataIn,MAXIUM_TRANSFERBUF_LEN,0);
do{
if (len <=0)
{
……
break;
}
memcpy(&recvh,TransferDataIn,sizeof(int)*2);
ord=recvh.ord;
totallen=recvh.totallen;
TransferBufLen=totallen-len;
TransferOffset+=len;
if(totallen > len)
{
while(TransferBufLen > 0)
{
LOG_WriteLog(LOG,__FILE__,__LINE__,"Large message Transfer",totallen,NULL,0);
len=recv(sockfd,&TransferDataIn[TransferOffset],MAXIUM_TRANSFERBUF_LEN,0);
……
这个socket收发数据缓存区原来每次都用malloc从堆中分配,现在使用线程本地存储,不再需要分配,实际测试发现,减少堆分配和使用第三方堆分配函数将应用性能提升了30%。
从加密机的架构可以看到使用了多线程技术和连接池技术。通过使用“netstat-apn | grep 6666” 观察TCP连接情况,发现只有几十个连接,查看代码,这个连接池在配置代码中是固定的,是有限制的,所以在代码中加大连接池,将最大连接数从32调整为200,经过测试发现,性能提升了30%。
通过代码方面的优化,加密机的性能得到了提升,但是仍未到达设计要求。接下来考虑从架构出发,改变通信方式,从而达到目标。
3.3 从架构出发
从客户端发送信息到服务端,中间需要通过加密机的加密。首先,信息发送到加密机上,通过加密后,发送给服务端。其中涉及到TCP/IP传输,在是否基于连接方面,TCP是面向连接的协议,而UDP是无连接的协议。可以理解为使用TCP是需要建立连接,而使用UDP时是可以不用建立连接就能够进行数据的发送。并且使用UDP比使用TCP可以达到更好的实时性和更高的工作效率,主要应用在高速传输和高实时性的通信模式中。但是UDP没有滑动窗口实现拥塞机制,容易导致丢包。但在我们的应用场景中,加密是同步方式,只有数据返回后才会送下一个报文。因此天然的控制,不容易堵塞,所以,在这里把服务端和客户端的传输方式改为UDP传输。
通过使用UDP传输,更好的增加了加密机的性能。通过实际的测试可以发现,达到了设计要求。
4 验证与分析
4.1 加密机性能测试
首先我们把主机、交换机、加密机用网线连接好。其次配置好主机与加密机的IP地址,然后开始进行加密机的性能测试,如图4所示。具体的参数如表1所示。
图4 连接示意图
表1 设备参数
在基于现有加密机的基础上进行升级,可以得到一个性能更加优越的加密机。为了验证本文所提出的设计要求,使用性能工具进行测试,实际性能到达了280 Mb/s。实现了更高的运行速度,已经达到了设计要求。同时,我国信息加密仍具有许多问题,例如:核心技术设备受制于人,信息加密基础设施的安防能力较差,网络通讯体系不完善等[9]。
4.2 分析结果
加密机的性能得以提升,主要是通过代码优化以及架构调整两方面实现的。运用基于数字证书的认证技术及加密技术,实现配电主站和终端之间的双向身份鉴别和业务数据的加密,保障数据的完整性和机密性[10]。经过实际的测试,发现本文提出的方法可以达到目标,满足要求,具有一定的可操作行。优化后的加密机使电力系统通信有了更加及时、高效的通信能力,使加密机适应在高性能要求的环境中,可多机并行工作在各种类型的密码安全应用系统。向信息安全传输系统给出高性能的数据加、解密服务,确保配电自动化系统的通信安全。同时可以满足我国电力行业高速发展,满足电力系统通信的传输要求,保障电力通信的机密性,有效防止违法分子恶意破坏的攻击,防止由此引发电力系统事故。