TCP最大报文段MSS源码分析

概述

本文主要对MSS相关的几个字段结合源码流程进行分析;

字段含义

user_mss(tcp_options_received)–用户配置的mss,优先级最高;

mss_clamp(tcp_options_received)–对端通告的mss,即为对端能接受的最大mss,对端通告的mss与user_mss中的较小值;

advmss(tcp_sock)–用于通告对端的mss值,本端能接受的最大mss;

mss_cache(tcp_sock)–缓存发送方当前有效的mss值,根据pmtu变化,不会超过mss_clamp;

rcv_mss(inet_connection_sock)–由最近接收到的段估算的对端mss,主要用来确定是否执行延迟确认;

user_mss配置

user_mss是用户配置的MSS,该MSS优先级最高,如果配置了该MSS,则MSS均不能超过该值;下面为调用setsockopt设置user_mss的代码,其操作字段为TCP_MAXSEG;配置范围不能小于最小MSS,不能大于最大窗口值;

 

交互流程代码分析

第一次握手
客户端发送syn

在进行connect操作的初始化中对mss的设置如下:

(1) 如果有用户配置的user_mss,则将mss_clamp(本端最大mss)设置为user_mss;

(2) 调用tcp_sync_mss来同步mss,其主要是根据设备mtu,最大窗口等计算出当前有效的mss,并将该mss记录到tp->mss_cache中;因该函数涉及篇幅较大,在本文最后进行分析;

(3) 设置用于通告给对端的advmss,去路由表中查MSS,这里会用到pmtu,然后将这个值与user_mss比较,取较小的值设置为向对端通告的值;

(4) 估算对端的mss,根据advmss,mss_cache,rcv_wnd,MSS_DEFAULT,MIN_MSS估算rcv_mss;

 

在发送syn流程中,会将advmss添加到tcp首部的选项中;调用关系为tcp_transmit_skb->tcp_syn_options->tcp_advertise_mss;可见这里不是直接使用前面的adv_mss,而是调用tcp_advertise_mss重新获取的;

 

tcp_advertise_mss重新取查路由表获取mss,并且与前面获取的mss取较小值;

 

服务器接收syn

服务器当前处于LISTEN状态,收到客户端发来的syn包,在处理过程中,需要解析tcp首部的选项,调用关系为tcp_conn_request->tcp_parse_options,其中解析选项的MSS部分如下,解析mss选项,与user_mss进行对比取较小值,然后将mss_clamp(最大mss)设置为该值;

 

在分配了请求控制块,对控制块进行初始化的时候,使用从选项中获取的最大mss初始化控制块的mss;

 

第二次握手
服务器发送syn+ack

在请求控制块添加到连接链表之后,需要向客户端发送syn+ack,在构造synack包时,需要在选项中指明本端的mss,调用关系如下:tcp_v4_send_synack–>tcp_make_synack–>tcp_synack_options;首先获取mss,方法与前客户端的方法一致,即从路由表中获取mss,与用户配置的user_mss进行比较,取其中较小值;然后调用选项设置将该mss加入到选项中;

 

 

客户端接收syn+ack

客户端当前处于SYN_SENT状态,此时收到服务器发来的syn+ack包,客户端进行以下工作:(1)解析该包tcp选项中的mss ,存入opt_rx->mss_clamp (2) 通过最新的pmtu计算mss (3) 估算对端mss (4) 如果需要进入快速模式,则需要通过rcv_mss计算快速模式额度;

 

已连接状态发送数据

tcp发送数据系统调用最终会调用tcp_sendmsg函数,该函数会在发送数据之前,获取发送mss,该mss用于限制后续发送数据段大小;

 

tcp_current_mss函数根据当前mtu和实际头部选项长度,来更新mss值;

 

函数tcp_sync_mss

这个函数上面的诸多流程都有用到,这里统一进行分析说明;

 

下面两个函数作用为根据mtu计算mss;

 

 

tcp_bound_to_half_wnd函数根据对端通告窗口的最大值来调整mss;如果最大窗口大于默认mss,则当前mss不能超过窗口的一半,当然也不能太小,最小68-headerlen;

 

本文链接:TCP最大报文段MSS源码分析

转载声明:转载请注明来源:Linux TCP/IP Stack,谢谢!


发表评论

电子邮件地址不会被公开。 必填项已用*标注