zoukankan      html  css  js  c++  java
  • tcp_tw_recycle检查tcp_timestamps的内核代码

    注意:本文档中的内核代码的版本号:linux-4.0.5
    /*************************************************
    * Author : Samson
    * Date : 07/14/2015
    * Test platform:
    * gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
    * GNU bash, 4.3.11(1)-release (x86_64-pc-linux-gnu)
    * Nginx version:
    * Nginx 1.6.2
    * Nginx 1.8.0
    * ***********************************************/

    两者的关系

    net.ipv4.tcp_tw_recycle是与net.ipv4.tcp_timestamps是密切相关的,而net.ipv4.tcp_timestamps默认是开启的。当tcp_tw_recycle和tcp_timestamps同一时候打开时会激活TCP的一种隐藏属性:缓存连接的时间戳。

    60秒内,同一源IP的兴许请求的时间戳小于缓存中的时间戳,内核就会丢弃该请求。

    那么在内核中相应的代码是如何处理的呢?

    在内核代码中net/ipv4/tcp_input.c中的tcp_conn_request函数的代码:

    if (tcp_death_row.sysctl_tw_recycle) {
                bool strict;
    
                dst = af_ops->route_req(sk, &fl, req, &strict);
    
                if (dst && strict &&
                    !tcp_peer_is_proven(req, dst, true,
                            tmp_opt.saw_tstamp)) {
                    NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
                    goto drop_and_release;
                }
            }

    //tcp_peer_is_proven函数的实现

    bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst,
                bool paws_check, bool timestamps)
    {   
        struct tcp_metrics_block *tm; 
        bool ret;      
        if (!dst)
            return false;   
        rcu_read_lock();
        tm = __tcp_get_metrics_req(req, dst);
        if (paws_check) {
            if (tm &&
                (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL &&
                ((s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW ||
                 !timestamps))
                ret = false;
            else
                ret = true;
        } else {
            if (tm && tcp_metric_get(tm, TCP_METRIC_RTT) && tm->tcpm_ts_stamp)
                ret = true;
            else
                ret = false;
        }
        rcu_read_unlock();
    
        return ret;
    }

    主要參数说明

    tmp_opt.saw_tstamp:该socket支持tcp_timestamp,
    tcp_death_row.sysctl_tw_recycle:本机系统开启tcp_tw_recycle选项
    TCP_PAWS_MSL:/* Per-host timestamps are invalidated
    * after this time. It should be equal
    * (or greater than) TCP_TIMEWAIT_LEN
    * to provide reliability equal to one
    * provided by timewait state.
    */
    60s。该条件推断表示该源ip的上次tcp通讯发生在60s内。

    TCP_PAWS_WINDOW:/* Replay window for per-host
    * timestamps. It must be less than
    * minimal timewait lifetime.
    */
    1,该条件推断表示该源ip的上次tcp通讯的timestamp 大于本次tcp;

    丢弃请求的关键代码

    (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL表示若当前请求的时间戳小于60S,则返回false,则跳转到goto drop_and_release;进行连接请求的丢弃及资源的回收。

    drop_and_release:
    dst_release(dst);
    drop_and_free:
    reqsk_free(req);
    drop:
    NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
    return 0;

  • 相关阅读:
    HBase MapReduce 一些 ClassNotFoundException 所缺少的jar包
    Eclipse 连接不上 hadoop 的解决办法
    Log4j 2 配置
    mysql 查询结果显示行号
    js刷新页面方法 -- (转)
    python 错误--UnboundLocalError: local variable '**' referenced before assignment
    Webview 中FaultyInfo代码说明
    HTML中设置超链接字体 & 字体颜色
    apache log 按日期记录 格式 <GOOD>-- (转)
    linux 下 /bin /sbin 的区别 -- (转)
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7028969.html
Copyright © 2011-2022 走看看