OpenVPN的Linux内核版,鬼魅的残缺 View

是时候给出一个总的图景了,是时候了。
我的意思是说,为什么非要将OpenVPN移植到内核,而不是在用户态,即在它本身优化它。为什么呢?事实上我已经在用户态优化了它,虽然有些难以定位的segment fault,但是并不是说我没有时间没有能力搞定这些,知难而退到内核(退到内核碰到panic岂不是更难搞),不是这样的。我的本意是,且一直都是,我要缩短处理路径的长度,我从来都不相信什么软件神话,事实上我憎恨这些神话。正如一位网友所说,干嘛非要区分什么内核态,用户态!关键点不在哪个态处理效率高,关键在处理路径的长度不同。就像有些人说的那样,数据平面一定要在用户态处理,那么事实上他的意思是说直接将数据包在驱动层面上抓到用户态,本质上还是缩短了处理路径的长度,所以我作图如下,虚线代表现有的路径:




在多核心时代,内核进行多处理真的是太简单不过了,只要把过程用softirq或者tasklet调度到不同的CPU核心即可,哪来的那么多诸如epoll的那么复杂的规范。但是这并不是说内核态写代码就一定好,前提得是你能驾驭它!不光是panic,oops...更重要的是即便你能处理了这些,你也不能把一个系统当成一个单片机来玩,因为你违背了软件设计的基本原则。我不喜欢嵌入式的原因就在于此。在内核中处理逻辑是极其不规范的做法,除非你知道自己在做什么。事实上,在内核态能做的事情在用户态都可以做,关键是你得知道怎么做,如果你不想copy buffer,你可以用map,如果你想缩短协议栈处理路径,干嘛不直接学学PF_RING的样子,在用户态平坦化处理...但问题是,你知道怎么折腾这些吗?
       本年初,我了解到一件事情,如果你想掌握类似PF_RING的技术,当然了并不是PF_RING,而是一个厂商的API,那么你要参加其昂贵的培训,花费一笔可观的费用,作为个人是很难承担的,作为公司而言,即便费用不成问题,也意味着要将之前的架构统一到新架构中来,要知道,这是完全不同的,除非单独开一条线,否则兼容性付出的代价将是无法弥补的。
       OpenVPN的代码都在处理什么?大多数的代码都在处理数据包buffer和包调度。这些是纯数据平面的,然而OpenVPN的控制平面代码和数据平面代码同处在一个大的while循环中。分开它们是一个相当常规的想法。OpenVPN的数据平面buffer管理粒度过粗,整个循环都使用同一个buffer,只是在一轮循环结束是更换buffer的内容,所以很难将循环过程中拆分成多处理的效果,因为这意味着在处理过程中需要对整个buffer加锁。于是乎,不得不复制整个大循环成多份,这样的效果是明显的,但是又涉及到了控制平面的同样的问题,一个while循环中的控制通道逻辑处理能影响另一个while循环吗?如果不能,就意味着必须在外部再封装一个管理层,这就是我的多队列tun驱动做的事情,这样导致了驱动和OpenVPN的耦合程度过大,如果可以,那么控制通道就会反过来影响别的while循环的数据通道的处理过程..这是一个两难的处境,不知道为何James Yonan将本来要加入的多线程又去掉了,难道他本人也意识到了这一点吗?难说,难说...
       怎么样?在《UNIX网络编程》这本书开创了一个时代且影响整整三代程序员后,所有人已经无法自拔,这是整个世界的壮举!全世界的网络编程者为socket而疯狂,设置了一个又一个的sockopt,cork了无数个的buffer,所有人争先恐后地poll,进而epoll,同时嘲笑着还在select的古人,而我,作为一个旧石器时代的人,还在使用while(1){recv;send;}这样的神器...这就是现状,且依然在继续...此时,如果能有什么方式绕开这一切,难道只是试一下不行吗?Just for myself,且不必用《UNP》砸我,那本书实在是厚,但这并不意味着我不会反击,且看我的案头:




郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。