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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章