zoukankan      html  css  js  c++  java
  • TCP拥塞控制算法 — CUBIC的补丁(三)

    描述

    以下是提交者Stephen Hemminger对这个patch的描述:

    fix clock dependency

    The hystart code was written with assumption that HZ=1000.

    Replace the use of jiffies with bictcp_clock as a millisecond real time clock.

    代码

    --- a/net/ipv4/tcp_cubic.c
    +++ b/net/ipv4/tcp_cubic.c
    @@ -88,7 +88,7 @@ struct bictcp {
     	u32	last_time;	/* time when updated last_cwnd */
     	u32	bic_origin_point;/* origin point of bic function */
     	u32	bic_K;		/* time to origin point from the beginning of the current epoch */
    -	u32	delay_min;	/* min delay,以前的单位为jiffies*/
    +	u32	delay_min;	/* min delay (msec << 3),现在的单位为毫秒*/
     	u32	epoch_start;	/* beginning of an epoch */
     	u32	ack_cnt;	/* number of acks */
     	u32	tcp_cwnd;	/* estimated tcp cwnd */
    @@ -98,7 +98,7 @@ struct bictcp {
     	u8	found;		/* the exit point is found? */
     	u32	round_start;	/* beginning of each round */
     	u32	end_seq;	/* end_seq of the round */
    -	u32	last_jiffies;	/* last time when the ACK spacing is close,单位为jiffies */
    +	u32	last_ack;	/* last time when the ACK spacing is close,单位为毫秒 */
     	u32	curr_rtt;	/* the minimum rtt of current round */
     };
     
    @@ -119,12 +119,21 @@ static inline void bictcp_reset(struct bictcp *ca)
     	ca->found = 0;
     }
                 
    +static inline u32 bictcp_clock(void)
    +{
    +#if HZ < 1000 /* NZ小于1000,返回的是实际时间,单位为毫秒 */
    +	return ktime_to_ms(ktime_get_real());
    +#else
    +	return jiffies_to_msecs(jiffies); /* 返回的是jiffies时间,单位为毫秒*/
    +#endif
    +}
    +
     static inline void bictcp_hystart_reset(struct sock *sk)
     {
     	struct tcp_sock *tp = tcp_sk(sk);
     	struct bictcp *ca = inet_csk_ca(sk);
     
    -	ca->round_start = ca->last_jiffies = jiffies;
    +	ca->round_start = ca->last_ack = bictcp_clock();
     	ca->end_seq = tp->snd_nxt;
     	ca->curr_rtt = 0;
     	ca->sample_cnt = 0;
    @@ -239,8 +248,8 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
     	 */
     
     	/* change the unit from HZ to bictcp_HZ */
    -	t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start)
    -	     << BICTCP_HZ) / HZ;
    +	t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3)
    +	      - ca->epoch_start) << BICTCP_HZ) / HZ;
     
     	if (t < ca->bic_K)		/* t - K */
     		offs = ca->bic_K - t;
    @@ -342,14 +351,12 @@ static void hystart_update(struct sock *sk, u32 delay)
     	struct bictcp *ca = inet_csk_ca(sk);
     
     	if (!(ca->found & hystart_detect)) {
    -		u32 curr_jiffies = jiffies;
    +		u32 now = bictcp_clock();
     
     		/* first detection parameter - ack-train detection */
    -		if ((s32)(curr_jiffies - ca->last_jiffies) <=
    -		    msecs_to_jiffies(hystart_ack_delta)) {
    -			ca->last_jiffies = curr_jiffies;
    -			if ((s32) (curr_jiffies - ca->round_start) >
    -			    ca->delay_min >> 4)
    +		if ((s32)(now - ca->last_ack) <= hystart_ack_delta) {
    +			ca->last_ack = now;
    +			if ((s32)(now - ca->round_start) > ca->delay_min >> 4)
     				ca->found |= HYSTART_ACK_TRAIN;
     		}
     
    @@ -396,7 +403,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
     	if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ)
     		return;
     
    -	delay = usecs_to_jiffies(rtt_us) << 3;
    +	delay = (rtt_us << 3) / USEC_PER_MSEC;
     	if (delay == 0)
     		delay = 1;

    分析

    #ifndef _STRUCT_TIMESPEC
    #define _STRUCT_TIMESPEC
    struct timespec {
        __kernel_time_t tv_sec; /* seconds,long*/
        long tv_nsec; /* nanoseconds */
    };
    #endif
    
    union ktime {
        s64 tv64;
    
    #if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
        struct {
    #ifdef __BIG_ENDIAN
        s32 sec, nsec;
    #else
        s32 nsec, sec;
    #endif
        } tv;
    #endif
    };
    
    typedef union ktime ktime_t;
    
    /**
     * ktime_get_real - get the real (wall) time in ktime_t format
     * returns the time in ktime_t format
     */
    ktime_t ktime_get_real(void)
    {
        struct timespec now;
        getnstimeofday(&now);
        return timespec_to_ktime(now);
    }
    
    static inline s64 ktime_to_ms(const ktime_t kt)
    {
        struct timeval tv = ktime_to_timeval(kt);
        return (s64) tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC;
    }
    
    /**
     * ktime_to_timeval - convert a ktime_t variable to timeval format
     * @kt: the ktime_t variable to convert
     * Returns the timeval representation of the ktime value
     */
    static inline struct timeval ktime_to_timeval (const ktime_t kt)
    {
        return (struct timeval) {
            .tv_sec = (time_t) kt.tv.sec,
            .tv_usec = (suseconds_t) (kt.tv.nsec / NSEC_PER_USEC) };
    }

    评价

    原来的bictcp结构中的round_start、delay_min和last_jiffies的单位为jiffies,现在考虑到1jiffies不

    一定代表1ms(如果HZ不为1000),所以这三个变量就采用毫秒为单位来计算。原来的版本也没

    有错误,现在只是改了下度量单位。

    Author

    zhangskd @ csdn blog

  • 相关阅读:
    ArrayList removeRange方法分析
    LinkedHashMap源码分析(基于JDK1.6)
    LinkedList原码分析(基于JDK1.6)
    TreeMap源码分析——深入分析(基于JDK1.6)
    51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划
    51 NOD 1049 最大子段和 动态规划 模板 板子 DP
    51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
    8月20日 训练日记
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/aiwz/p/6333351.html
Copyright © 2011-2022 走看看