你的意思是BGP可以使用TCP,即使用TCP的封装头,用于封装BGP报文,为何要多此一举使用TCP的三次握手建立连接?
2012年有过类似的困惑。那时Cisco ASR 1000 产品开发一个新的Feature,一种新型的UDP隧道,为了检验其扩展性以及对各种报文的转发性能,需要从隧道的一端(入口)最大限度灌入IP、UDP、TCP流量。然后检查从隧道的另一端(出口)有多少流量流出来了?
IP、UDP流量都没有问题,目的IP、目的端口随便填,流量都可以生成并进入隧道。(默认路由)
TCP遇到了麻烦,需要提供对方的IP以及端口号。随便填了IP/端口,发现非但没有生成流量,测试仪还报错,提示连接失败。
突然才意识到TCP是基于连接的,只有本端的握手信号(第一次握手),被对方确认且收到对方握手信号(第二次握手),然后本端再确认收到对方握手信号(第三次握手)。
三次握手成功之后,本端才能生成TCP流量报文。可是脚本提供的对端IP、端口号都是不存在的,无法完成三次手,自然无法产生TCP数据流。
难道不能有一种特殊的API接口,只使用TCP的封装,不用建立TCP连接,这样就可以直接灌入TCP流量?
可是测试仪表并没有提供这个特殊的API。于是我就在网络上抓了一个TCP数据包,用脚本修改目的IP、端口号,于是就生成了TCP数据流量。
将生成的TCP流量灌入隧道入口,自然TCP流量从隧道出口流出。这些TCP流量最后到哪里去了?
丢了,它们的使命已经完成。
问题回来,BGP能否模仿我,自己生成TCP报文头,以避免TCP三次握手?
当然可以。
可是BGP自己生成的TCP封装 + BGP 报文,到达对端(Peer)的TCP/IP协议栈,谁来处理呢?
先是IP层来处理,因为二层ether type= 0x0800。
然后TCP来处理,因为IP头 Protocol = 6。
TCP将报文的源IP、目的IP、源端口、目的端口 提取出来,这四个参数输入hash()函数,得到一个hash ID,这个就是TCP连接库里的连接ID。
TCP在自己连接库没有查询到hash ID。TCP认为这是一个新建连接,可是发现报文里并没有SYN标志位,这是非法报文,丢弃并发Reset。
BGP既然选择了TCP做为自己的传输协议(运输供应商),那就把货物全权委托给自己的运输供应商。至于供应商TCP的内部运作方式,是无权干涉的,也是干涉不了的!
就凭TCP可以将字节流可靠按序送达目的地这句承诺,就可以让TCP这家供应商独领风骚多少年!不用TCP,还有更好的选择吗?