TCP是一个复杂的协议。这种复杂性来自对消息传输的可靠性承诺。对于每一个TCP连接,除了有独立的状态机和定时器外,还有一些与拥塞控制相关的运行变量,如RTT、CWND、SSTHRESH等,这些运行参数也是每连接(Per-Connection)Per-Connection就是每个连接的这些参数互不影响,这是理所当然的!但是,想一想这样的场景:A和B之间已经建立了一个稳定的TCP连接,如果此时创建一??个新的连接,它的参数应该怎么设置呢?显然,与原始连接保持一致是实现稳定的快速方法。就像一个人要去一个陌生的地方,却不知道该选择哪种交通工具,也不知道该预估多少时间。对他来说,借鉴到过的人的经验永远是一条捷径。这就是Linux内核中TCPMetrics框架的作用,可以为后续的连接提供指导。当主机需要频繁建立和断开TCP连接时,它带来的好处更加明显。TCPMetrics显然不能是Per-Connection,而应该是Per-Destination。也就是说,TCPMetrics条目应该基于二元组。从一台主机的角度来看,到特定地址的另一台主机的网络链接状态应该由两台主机之间的所有连接共享。内核使用tcp_metrics_block来表示一个Metrics条目。这些条目按照<源IP,目的IP>组织在tcp_metrics_hash冲突列表中,记录的值存储在内部tcpm_vals数组structtcp_metrics_block{structtcp_metrics_block__rcu*tcpm_next;结构inetpeer_addrtcpm_saddr;inetpeer_addrtcpm_daddr;......u32tcpm_vals[TCP_METRIC_MAX_KERNEL+1];......};创建新的TCP连接时,内核使用如下接口,在TCPMetrics的指导下为TCPsocket设置参数voidRTT,内核将使用以下接口更新其相应的TCPMetrics条目。请记住,TCPMetrics条目是Per-Destination,因此,多个TCP连接的套接字可能会更新同一个条目。voidtcp_update_metrics(structsock*sk)内核还提供了ip-tcp_metrics命令来查看主机上的TCPMetrics条目。