测试命令:ab -k -c 8 -n 500 http://10.0.188.139/5m.html
机器部署:
S0:
eth0:192.168.188.194 mtu 1500 e1000e 1000baseT-FD flow-control
tun0:172.17.0.2 mtu 1500
route:10.0.188.139 dev tun0
S1:
eth0:192.168.188.193 mtu 1500 e1000e 1000baseT-FD flow-control
eth1:10.0.188.193 mtu 1500 e1000e 1000baseT-FD flow-control
tun0:172.16.0.1 mtu 1500
S2:
eth1:10.0.188.139 mtu 1500 e1000e 1000baseT-FD flow-control
route:172.17.0.0 gw 10.0.188.193
测试数据: OpenVPN配置:--cipher BF-CBC --auth SHA1
Transfer rate: 35480.31 [Kbytes/sec] received
cpu:接近100%
OpenVPN配置:--cipher none --auth SHA1
Transfer rate: 64513.28 [Kbytes/sec] received
cpu:接近100%
OpenVPN配置:--cipher none --auth none
Transfer rate: 94089.42 [Kbytes/sec] received
cpu:接近100%
从数据可以看出,加解密和摘要计算消耗了大量的cpu,由于OpenVPN的本身架构就是一个大的while(1)循环,即使cipher和auth都为none,cpu利用率并没有下来多少,cpu将消耗在传输上,这个信息可以从top中看出: cipher和auth为none时,绑定OpenVPN于cpu0时的top快照:
Cpu0 : 17.4%us, 57.1%sy, 0.0%ni, 1.0%id, 0.0%wa, 0.0%hi, 24.6%si, 0.0%st
cipher为DES-CBC,auth为SHA1时,绑定OpenVPN于cpu0时的top快照:
Cpu0 : 75.4%us, 14.3%sy, 0.0%ni, 6.9%id, 0.0%wa, 0.0%hi, 3.3%si, 0.0%st
可见,不使用加解密和摘要时,cpu大量消耗在内核空间和网卡软中断上,而使用加密以及摘要时,cpu大量消耗在OpenVPN的加解密/摘要计算上。既然加解密是一个很耗时的操作,我们也就有必要使用上篇《OpenVPN性能-OpenVPN的第一个瓶颈在tun驱动》修改后的tun驱动了,鉴于OpenVPN代码不是很简单,在修改OpenVPN从而使之支持修改后的tun驱动之前,首先在simpletun上模拟一下加解密的操作,再来看一下simpletun的执行框架:
while(1) {
int ret;
fd_set rd_set;
FD_ZERO(&rd_set);
FD_SET(tap_fd, &rd_set);
FD_SET(net_fd, &rd_set);
ret = select(100 + 1, &rd_set, NULL, NULL, NULL);
if (ret < 0 && errno == EINTR){
continue;
}
if (ret < 0) {
perror("select()");
exit(1);
}
if(FD_ISSET(tap_fd, &rd_set)) {
nread = cread(tap_fd, buffer, BUFSIZE);
//加入加密/mac操作encrypt(buffer)
plength = htons(nread);
nwrite = cwrite(net_fd, (char *)&plength, sizeof(plength));
nwrite = cwrite(net_fd, buffer, nread);
}
if(FD_ISSET(net_fd, &rd_set)) {
nread = read_n(net_fd, (char *)&plength, sizeof(plength));
if(nread == 0) {
break;
}
nread = read_n(net_fd, buffer, ntohs(plength));
//加入verify/解密操作decrypt(buffer)
nwrite = cwrite(tap_fd, buffer, nread);
}
}
在上述simpletun的执行框架中加入加解密和mac操作,以模拟OpenVPN的情况,因此我们需要给出encrypt和decrypt函数,由于我们只是想制造一点cpu型的延迟(cpu不断计算造成的延迟)而并不是真的想加解密数据,因此没有必要调用libcrypto的EVP系列函数,比如EVP_CipherInit/Update/Final之类的,于是我们给出下面的实现:
void encrypt(char *buf)
{
char buf2[8192] = {1}; //不要触动参数buf,只是制造一些计算
int i = 0;
for (i; i<4192; i++) {
buf2[i] += i;
}
}
void decrypt(char *buf)
{
encryp(NULL);
}
encrypt函数中的8192这个数字是随便猜测的,4192是微调出来的,不断地改变这个数字,然后编译,执行,直到执行ab -k -c 8 -n 500 http://10.0.188.139/5m.html
时得到和OpenVPN --config xxx --cipher BF-CBC --auth SHA1
测试得到的结果大致相同,也就是35M/s左右,这样就基本模拟了OpenVPN的加解密操作,在S0上,调到了4192正好得到35M/s的速率,因此encrypt和decrypt函数定型为上述。
接下来停掉simpletun的server和client,在S0(运行client的那台)和S1(运行server的那台)上执行rmmod tun,然后insmod上修改后的tun驱动,此时再次执行测试,ab -k -c 8 -n 500 http://10.0.188.139/5m.html
的结果是:
Transfer rate: 86526.22 [Kbytes/sec] received
是不是质的飞跃,这就是《OpenVPN性能-OpenVPN的第一个瓶颈在tun驱动》最后说的更猛的效果。
这样针对OpenVPN的修改就比较有意义了。