1、使用五元组创建session,即内网报文的源ip、源port、协议、目的ip、目的port作为key值创建hash表项,结构体如下,其中fib_index是客户所在vrf。
struct
{
ip4_address_t l_addr;
ip4_address_t r_addr;
u32 proto:8, fib_index:24;
u16 l_port;
u16 r_port;
};
2、cpe接收到报文先查找hash表,如果没有查找到表示没有session,通过上诉五元组创建hash,value值是session在pool中的位置。同时建立反向的hash表,反向hash表的五元组是公网ip,转换后的port,协议,目的ip,目的port。当接收到后续报文时,可直接查找hash表,提取出session做快转发。
3、如果只用内网五元组作为hash表key值,还有可能有冲突,复用的port可能已经被其他session使用,举例说明:
nat 公网ip:172.168.0.1,如果只选取内网报文的五元组,则有可能出现以下情况:
第一条流:tcp 1.1.1.1:100->8.8.8.8:50 修改成 172.168.0.1:300->8.8.8.8:50
第二条流:tcp 1.1.1.1:200->8.8.8.8:50 修改成 172.168.0.1:300->8.8.8.8:50
假如只用内网五元组区分可用port,上面的情况nat之后的信息完全一致,返程报文无法区分。所以在选取port的时候,还需建立一个记录flow的hash表项。报文选取port规则:随机在每线程可用的port中选取一个port,将nat 公网ip、选取的port、目的ip、目的port、协议做为新的五元组进行查找,如果hash表中没有,则这个port是可用的,如果hash表中存在,则表明这个port不可用,需要再次查找,查找每线程可用port一定次数后若找不到可用的session,则不做nat转换(防止没有可用的port而进入死循环)。
如果新的五元组总数超过65535的话,port也会占用完,极限情况如果所有流量访问同一个目的ip、目的port,最多只能有65535个会话。在老化和删除session的时候需要删除这个新的五元组来释放port。
通过上诉方法,可建立百万级别的并发,支撑客户高并发访问外网的场景。