ecn cwnd

1、收到ecn后调用tcp_fastretrans_alert--->tcp_try_to_open--->tcp_enter_cwr

 

复制代码
/* Enter CWR state. Disable cwnd undo since congestion is proven with ECN */
void tcp_enter_cwr(struct sock *sk)
{
    struct tcp_sock *tp = tcp_sk(sk);

    tp->prior_ssthresh = 0;
    if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) {
        tp->undo_marker = 0;
        tcp_init_cwnd_reduction(sk);
        tcp_set_ca_state(sk, TCP_CA_CWR);
    }
}

//对于cubic算法来说就是返回max((tp->snd_cwnd * beta) / BICTCP_BETA_SCALE, 2U);
//也就是 max((tp->snd_cwnd * 819) / 1024, 2U);
//如果snd_cwnd = 10; 也就是10*819/1024=7
复制代码

 

SO:snd_ssthresh = 7

 

后续调用tcp_cong_control--->tcp_in_cwnd_reduction---->tcp_cwnd_reduction

复制代码
void tcp_cwnd_reduction(struct sock *sk, int newly_acked_sacked, int flag)
{
    struct tcp_sock *tp = tcp_sk(sk);
    int sndcnt = 0;
    int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);

    if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd))
        return;

    tp->prr_delivered += newly_acked_sacked;
    if (delta < 0) {
        u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
                   tp->prior_cwnd - 1;
        sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
    } else if ((flag & (FLAG_RETRANS_DATA_ACKED | FLAG_LOST_RETRANS)) ==
           FLAG_RETRANS_DATA_ACKED) {
        sndcnt = min_t(int, delta,
                   max_t(int, tp->prr_delivered - tp->prr_out,
                     newly_acked_sacked) + 1);
    } else {
        sndcnt = min(delta, newly_acked_sacked);
    }
    /* Force a fast retransmit upon entering fast recovery */
    sndcnt = max(sndcnt, (tp->prr_out ? 0 : 1));
    tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
}
复制代码

 

 

复制代码
// Test that if we don't moderate cwnd when ECN sees congestion and reduces cwnd.

`../common/defaults.sh
sysctl -q net.ipv4.tcp_ecn=2    # server agrees to ECN if client proposes it
`

// Establish a connection.
    0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
   +0 bind(3, ..., ...) = 0
   +0 listen(3, 1) = 0

  +.1 < SEW 0:0(0) win 32792 <mss 1000,nop,nop,sackOK,nop,wscale 7>
   +0 > SE. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
  +.1 < [ect1] . 1:1(0) ack 1 win 320
   +0 accept(3, ..., ...) = 4

// Send 4 data segments.
   +0 write(4, ..., 4000) = 4000
   +0 > P. 1:4001(4000) ack 1
+.005 %{ assert tcpi_snd_cwnd == 10, tcpi_snd_cwnd }%

+.095 < [noecn] E. 1:1(0) ack 1001 win 320
+0 %{ print("ack 0:", "tcpi_snd_cwnd:", tcpi_snd_cwnd) }% 
+0 %{ print("ack 0:", "tcpi_snd_ssthresh:", tcpi_snd_ssthresh) }% 
+.005 %{
assert tcpi_ca_state == TCP_CA_CWR, tcpi_ca_state

# Since "tcp: use PRR to reduce cwin in CWR state" in Linux 3.7,
# we use PRR for CWR.
# Here, since we have 3 packets in flight and ssthresh is 7,
# we do PRR-CRB and sndcnt = min(3, 1) = 1,
# so cwnd = 3 + 1 = 4.
assert tcpi_snd_cwnd == 4, tcpi_snd_cwnd
}%
复制代码

ack 0: tcpi_snd_cwnd: 4
ack 0: tcpi_snd_ssthresh: 7

 如果内核是6.8的内核值为 :

 we do PRR-CRB and sndcnt = min(3, 2) = 2,
# so cwnd = 3 + 2 = 5.
assert tcpi_snd_cwnd == 5, tcpi_snd_cwnd

ack 0: tcpi_snd_cwnd: 5
ack 0: tcpi_snd_ssthresh: 7

 内核分析:参考以前文章

内核patch:https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/net?id=7e901ee7b6ab0b7c1a5e29b8513af23709285a29

 

posted @   codestacklinuxer  阅读(3)  评论(0)    收藏  举报
相关博文:
阅读排行:
· 推荐 3 种 .NET Windows 桌面应用程序自动更新解决方案
· 一周 Star 破万的开源项目「GitHub 热点速览」
· .NET 10 支持Linux/Unix 的Shebang(Hashbang)
· 上周热点回顾(6.9-6.15)
· 记一次 .NET 某SaaS版CRM系统 崩溃分析
历史上的今天:
2023-12-21 gorm阅读 5
2023-12-21 gorm 阅读4
点击右上角即可分享
微信分享提示