使用multi zone的nf conntrack来缓存路由和socket构建高性能处理

前些日子完成了一个extension for nf_conntrack底层基础设施,后来写了一个测试代码,将:
1.一个数据流两个方向的路由结果;
2.如果数据流目的地是本机,则和该流关联的socket;

缓存在了conntrack的extension中。这意味着什么?
        这意味着可以将几乎所有的查找操作都压缩在conntrack的查找中:
1.路由可以保存在conntrack中;
2.socket可以保存在conntrack中;
3.IPSec流量的SA指针可以保存在conntrack中;
4.数据流的描述信息可以保存在conntrack中;
...

这就真的现实,虽然不使用这个技术也能实现如上的诸多种种,但是本文毕竟不是讨论软件工程,也不奢谈所谓的模块化/重用性诸如此类,本文涉及的仅仅是一种选择,多了一种选择,可能善良的人们会因此过得更好或者更不好,但起码比不固定不变更加单调。
        压力似乎落在了conntrack查找的头上。毕竟,我不是在手持了高速ASIC板卡的前提下才说:我实现了Linux的高速cache转发机制。 conntrack毕竟是一个软件。但是,也正是由于它是软件,才更加好玩!在此,要提醒转发优化狂人们注意,Linux BOX或者任何中间的三层及3+层设备,一定是为了实现除转发之外的另一种或几种目的的,否则干脆用线缆直连岂不更好(当然,路由器要比硬连线更加灵活, 可是不是还有三层交换机的么...单论效率,低层设备永远比高层的更优)?如果你觉得自己通过缓存了路由项而使得数据包可以在PREROUTING或者还 没有进入netif_receive_skb的时候被forward,我只能说,不错,水平高,精通Linux协议栈...但是却不一定懂网 络...Netfilter的其它钩子难道都是摆样子的吗?审计怎么做?入侵检测怎么采样?流控怎么做?包分类怎么做?...我可以直接把机器关掉让数据 包bypass过去吗?
        在我度过了对协议栈本身的痴狂阶段后,我认为着手优化conntrack的查找是一条有点意思且还算正确的路,我并没有企图绕开它,因为很多check都 基于它。说了这么多其实就是想说我已经这么做了,并且效果还不错...我的做法就是将一张conntrack分成了好几张,比如每一个L4协议一张,或者 更加通用一点,在raw表中为skb分配conntrack表,为此,我修改了内核,在skb中增加了一个字段connmarkidx,然后内置16张 conntrack表,由skb的connmarkidx来索引具体的conntrack表。
        然而,和很多次一样,我发现自己做了无用功,因为Linux内核已经支持zone了,这并不需要修改Linux内核为skb增加字段,只需要增加一个 conntrack的extend就好了,我回顾了自己的思路,其实我想到了增加一个conntrack extend来保存一些东西,甚至在这样不满足我需求的时候,我想到了设计一个通用的extension of conntrack extend机制来保存任意数据,并且也做到了,但是我为何没有想到用extend机制来将conntrack表扩展成multi conntrack tables呢?我这是在内省自己,但恰恰是内省本身出了问题。真是太讽刺了,我已经知道了该做什么,但是却失败于怎么做,就是因为我对自己过度内省了, 却不信任conntrack本身的内省机制:多张conntrack表是conntrack机制内在的,不能用conntrack的extend机制来扩 展conntrack本身,它只适合保存一些和conntrack无关的东西...
        看,就是这样,太具讽刺意义。
        好了,现在使用multi zone conntrack机制,加上我的extension for nf_conntrack,我们就可以构建出一个快速转发机制了,该机制只是bypass了可以省去的查找操作而保留了协议栈的所有其它例行逻辑,比如校 验码检查,TTL递减,NAT,入侵检测等,办法如下:
1.使用iptables的CT target在raw表中为符合一定matches的skb绑定一个conntrack zone ID;
2.加载我在《在Linux的连接跟踪(nf_conntrack)中缓存私有数据省去每次查找》中的最后给出的实例编译而成的module(可能需要完善);
3.如果panic请debug

        nf conntrack机制自从诞生之日就被很多人诟病,因为它的效率太低,因为它在分给它的连接数份额用尽后会drop掉数据包等...这些都不是问题,首 先看它的效率问题,自第一代起,一直到最新的内核版本,conntrack的操作效率可以说一直在持续优化,比如单一spin lock改为了RCU lock,代码互斥区域的变化,lock粒度的变化,加上最为显著的硬件本身的变化。事实上,由于摩尔定律的存在,效率提升是一个无条件的结果,任何以效 率为由pass掉某种机制的做法都不是明智的,关键还是要看它能给你带来什么。至于说它有连接数份额的限制,其实你可以从另一个角度来思考这个问题,这难 道不是一种防DDos或者防SYN-Flood的方案吗?或者说一个副作用带来有益的效果。你不能单方面认为conntrack有个连接数份额就是对你的 系统做了什么限制,要知道,这个连接数的默认值是根据你系统的内存情况精心计算出来的(虽然称作“精心”还真的有点名不副实,但是我相信它会做到!),连 接数事实上是一个硬指标,不管你有没有限制它,总是存在的,就算你没有加载conntrack模块,难道你的系统就能处理无限的连接吗?当你的 conntrack连接份额默认被计算成比如65535的时候,其实它是想告诉你这个硬限制的存在,即便没有限制,或者说你将它改成了6553500,当 连接数大大超过65535的时候,强行进入协议栈的数据包也可能被其它逻辑由于处理不过来而丢弃。虽然这并不是说你试一下就会发生,但是记住,协议栈调优 是一个极其复杂的工程化过程,并不是调整某个参数就可以做到完美的。

你可能感兴趣的:(linux,软件工程,数据流)