本文主要是介绍TCP连接建立之后的SACK选项解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这几天有点犯糊涂,搞不清楚连接建立之后,SACK选项的解析在什么地方处理。内核中唯一能解析SACK选项的函数就是tcp_parse_options,但是就找不到tcp_rcv_established函数在哪里调用它。这里犯了一个错误,一直以为tcp_validate_incoming函数仅是验证报文,其中的tcp_fast_parse_options只是快速解析timestamps选项。
static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,const struct tcphdr *th, int syn_inerr)
{struct tcp_sock *tp = tcp_sk(sk);bool rst_seq_match = false;/* RFC1323: H1. Apply PAWS check first. */if (tcp_fast_parse_options(sock_net(sk), skb, th, tp) &&tp->rx_opt.saw_tstamp &&tcp_paws_discard(sk, skb)) {if (!th->rst) {NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);if (!tcp_oow_rate_limited(sock_net(sk), skb,LINUX_MIB_TCPACKSKIPPEDPAWS,&tp->last_oow_ack_time))tcp_send_dupack(sk, skb);goto discard;}/* Reset is accepted even if it did not pass PAWS. */
然而,在tcp_fast_parse_options函数的处理中,如果报文存在SACK选项数据,timestamps选项的快速解析必然失败。快速解析是建立在TCP选项数据中仅有timestamps一个选项的基础上的。当有SACK选项时,必须执行后面的正常选项解析函数tcp_parse_options,其将解析所有的选项数据,包括SACK选项。
static bool tcp_fast_parse_options(const struct net *net,const struct sk_buff *skb, const struct tcphdr *th, struct tcp_sock *tp)
{/* In the spirit of fast parsing, compare doff directly to constant* values. Because equality is used, short doff can be ignored here.*/if (th->doff == (sizeof(*th) / 4)) {tp->rx_opt.saw_tstamp = 0;return false;} else if (tp->rx_opt.tstamp_ok &&th->doff == ((sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4)) {if (tcp_parse_aligned_timestamp(tp, th))return true;}tcp_parse_options(net, skb, &tp->rx_opt, 1, NULL);if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)tp->rx_opt.rcv_tsecr -= tp->tsoffset;return true;
内核版本 5.0
这篇关于TCP连接建立之后的SACK选项解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!