return(bucket);
}
转换后的 TCP/IP 报文源IP变为 WAN口IP,源端口变为session 索引值,这样做的优点是:外部返回的报文可以通过TCP/IP报文的目的端口号直接定位到 session 数组中,查找的速度最快。
3) 查找 session
通过 TCP/UDP 报文的源 IP 和源端口号计算出 hash 头,然后遍历该头所对应的链表,直到找到相匹配的hash 节点。
4) 删除 session
收到 TCP/UDP 连接关闭请求后,根据目的端口号找到 session 数组,释放该 session, 并将其从 Hash 表中 unlink 出来。
7.3.2 TCP/UDP 协议端口地址转换
setup_tcpudp_outgoing 为从内部网络出去的TCP/UDP连接建立一个session,记录下连接的源地址、端口,目标地址、端口,转换后的地址、端口,协议类型以及连接建立时间等信息。
translate_outgoing_tcpudp 核心函数,根据 session 的对应记录,转换数据包的IP地址、端口,同时重新调整IP校验和及TCP/UDP校验和,其中,校验和调整主要用到了adjust_chksum函数。算法如下:
void adjust_chksum(ulong *chkSum, ushort oldW, ushort newW)
{
*chkSum -= oldW & 0xffff;
if ((*lChkSum) <= 0)
{
(*chkSum) --;
(*chkSum) &= 0xffff;
}
(*chkSum) += newW & 0xffff;
if ((*chkSum) & 0x10000)
{
(*chkSum) ++;
(*chkSum) &= 0xffff;
}
}
8 设计总结
本系统的优点是,仅需采用一块 CPU 即可同时实现 ADSL接入和路由两项功能,硬件资源利用率高,而且,两种功能在同一套系统平台中可以有机结合,避免因中间插入多余转换接口导致包处理效率降低。
文中所述的仅实现了一个最简单的 ADSL 共享接入方式,并不能完全满足实际使用中的种种需求,还需要补充其它如协议报文处理、ICMP报文处理、应用层网关处理等功能。 此外,在实际测试中,感觉 NAT 地址转换Hash 表的算法还不够理想:在新建一个节点时需要重新遍历整个 nat_session 数组,这将导致在连接数较多的情况下再新建一条连接非常困难,系统效率急剧降低。
在这次开发设计前期,由于对操作系统的架构不够熟悉,在设备驱动编写方面没有经验,导致编写的驱动层次感很差,不利于维护和后期扩展。走了很多弯路之后,总结出经验:开发前期的调研工作非常必要,在着手写代码之前应该多花些时间了解开发平台、熟悉整个系统的架构、模块在系统之间的地位及模块间的接口关系。磨刀不误砍柴工,总体规划充分之后才能编写出效率高、易维护、易扩展的模块代码出来。
参考文档
ITU-T Recommendation I.363.5 AAL Specification: Type 5 AAL, March 1993
IETF RFC1483. Multiprotocol Encapsulation Over ATM Adaptation Layer5, July.1993
IETF RFC1577. Classical IP and ARP over ATM, January 1994
IETF RFC2364
IETF RFC2516
IETF RFC791 IP
IETF RFC768 UDP
IETF RFC793 TCP
IETF RFC792 ICMP
IETF RFC826 ARP
IETF RFC1631 NAT
Vxworks network services standard。